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)

Last updated 14th of October, 2005

© 2006 MeccaMedialight. Site Powered by Wrangler 8.