A Progress Bar Widget

In the previous section, we created a 'Preloader' script to (1) preload a URL; (2) send a message when the preload is complete; and (3) send 'status' messages while the preload is happening. In this section, we are going to create a progress bar that shows the current status (such as the percentage of the preload that has been completed).

Example Movie can be downloaded here. It contains the scripts discussed in this tutorial.

(Updated 25th June 05)

There are many ways to create progress bars. We can use Flash sprites, simple shapes that are stretched and resized, simple text sprites, widgets provided by Xtras such as OS Controls, and so on. In this example, we are going to use imaging lingo. No matter which way we do it, the script needs to have the ability to respond to two messages that we are going to send to it: (a) a #mShowWorking message, which we will send while we are waiting to connect to a server, and a #ShowProgress(amount) message which we will send when we know how far we have progressed through the preload.

The script below will create an object that will draw a simple 'barberpole' type animation to an image when we send it the #ShowWorking message. When we send the #ShowProgress message, it will replace this barberpole with a simple progress bar.

--  [PARENT SCRIPT] "ProgressBar" (v.1).  



-- Author defined properties

property myColour, myColour2

-- Internally defined properties

property myCanvas, myRectOnCanvas, myBuffer, myBufferRect, myAlpha

property myStep, mySegmentSize



on Initialise (me, aCanvas, aRectOnCanvas, settings)

  

  -- stash a reference to the output canvas and rect

  myCanvas = aCanvas

  myRectOnCanvas = aRectOnCanvas

  

  -- some basic settings

  myColour =  rgb(68,68,68) -- bar colour

  myColour2 = rgb(255,255,255) -- stripe colour

  

  -- create an image buffer

  myBuffer = image(myRectOnCanvas.width, myRectOnCanvas.height, 16)

  myBuffer.copyPixels(myCanvas, myBuffer.Rect, myRectOnCanvas)



  -- store this rect for use later

  myBufferRect = myBuffer.rect

  -- set up parameters for working animation

  myStep = 0

  mySegmentSize = myBuffer.height -4

  

  return me

end



on Destroy (me)

  -- store the canvas to its previous state

  myCanvas.copyPixels(myBuffer, myRectOnCanvas, myBufferRect)

end





on ShowProgress (me, amt)

  -- make sure the amt is between 0 and 1.0

  amt = min(1.0, max(0, amt))

  -- create a duplicate of the buffer

  buffer = myBuffer.duplicate()

  -- draw a border

  buffer.draw(myBufferRect, [#ShapeType: #rect, #Color: myColour])

  -- calculate a fill rect based on the amount to show

  progressBarRect = rect(2,2, (myBufferRect.width-2)*amt, myBufferRect.height-2)

  -- fill the progress bar rect

  buffer.fill(progressBarRect, myColour2)

  -- copy the result to the stage

  myCanvas.copyPixels(buffer, myRectOnCanvas, myBufferRect)

end



on ShowWorking (me)

  -- create a duplicate of the buffer

  buffer = myBuffer.duplicate()

  -- draw a border

  buffer.draw(myBufferRect, [#ShapeType: #rect, #Color: myColour])

  -- add 1 to the myStep property. This is used to move the 'stripes' along

  myStep = myStep + 1

  -- if the step is bigger than the striped segment, then reset it

  if myStep > 0 then myStep = -mySegmentSize

  -- create the temporary inner image for the barber pole 

  innerRect = buffer.rect.inflate(-2,-2) 

  innerImage = image(innerRect.width, innerRect.height, 24)

  innerImage.fill(innerImage.rect, myColour)

  -- now draw the stripes

  L = myStep

  repeat while true

    dRect = rect(L, 0, L + mySegmentSize, mySegmentSize+2)

    innerImage.draw(point(L,0), point( L + mySegmentSize, mySegmentSize),\

 [#ShapeType: #Line, #lineSize: 1, #Color: myColour2, #ink: 2])

    L = L + mySegmentSize

    if L > buffer.width then exit repeat

  end repeat

  -- add the striped pole to the buffer

  buffer.copyPixels(innerImage, innerRect, innerImage.rect)

  -- copy the result to the stage

  myCanvas.copyPixels(buffer, myRectOnCanvas, myBufferRect)

  

end



This script is designed to do nothing except in response to either #ShowWorking or #ShowProgress messages. To see how it works, have a look at this "PreloaderInterface" frame script that both creates a Progressbar and a Preloader object discussed in the previous section, and then sends messages to the Progressbar:

 [FRAME SCRIPT / BEHAVIOUR]



property myURL, myProgressBarObj



on beginSprite  (me)

  if the runMode = "Author" then clearcache()

  PreloaderDaemon = script("NetOp.Preloader").new(myURL)

  PreloaderDaemon.AddListener(me)

  

  myProgressBarObj = script("ProgressBar")

  canvas = (the stage).image

  rectOnCanvas = rect(10,10,110,22)

  myProgressBarObj.Initialise(canvas, rectOnCanvas)

end



on endSprite(me)

  myProgressBarObj.Destroy()

end



on exitframe (me)

  go to the frame

end







-- Messages Sent by the preloader



on PreloadStatusUpdate (me, newOp, statusList)

  --  member("StatusDisplay").text = statusList.state 

  put statusList.state 

  if statusList.state = "InProgress" then

    myProgressBarObj.ShowProgress(statusList.fractionDone)

  else myProgressBarObj.ShowWorking()

end



on PreloadFinished (me, newOp, errorNum)

  if errorNum <> 0 then 

    -- get a description of the error 

    description = newOp.GetErrorDescription(errorNum)

    alert "Network Error!" & return & description

  else alert "All Done"

end



-- Author Settings

on getPropertyDescriptionList (me)

  pdList = [:]

  pdList[#myURL] = [#Comment: "URL", #format: #String, \

#Default: "http://www.lingoworkshop.com/Tutorials/Preloader/Main.dcr"]

  return pdList

end

So whats happening here?

1. When this "PreloaderInterface" behaviour is instantiated and receives the #beginSprite event, it creates a new Preloader object and a ProgressBar object. It keeps a reference to the ProgressBar object so that it can send messages to the ProgressBar.

2. As the preload proceeds, the Preloader Object starts sending #PreloadStatusUpdate messages to the "PreloaderInterface" object. The "PreloaderInterface" object then sends #ShowWorking and #ShowProgress messages to the ProgressBar object (depending on whether the preload has actually started or not).

Downloads

Example Movie can be downloaded here. It contains the scripts discussed in the tutorial.

(Updated 25th June 05)

First published 23/05/2005