## 6.4 Example: An Animated Time Waster

In this section we want to program a procedure that signals to the user that a particular computation is still running and entertains the user by some animation.

Figure 6.4 shows a subclass of `Tk.canvasTag` that creates a bitmap item showing a magnifying glass and starts a thread to move that bitmap randomly. The random movement can be stopped by binding the variable `D` given as value for the feature `done`. If the animation has stopped indeed, the variable `S` gets bound, as you can see in method `move`.

  `local
  fun {RandCoord} {OS.rand} mod 20 + 15 end
  in
  class RandMag from Tk.canvasTag
  meth init(parent:P done:D stopped:S)
  {self tkInit(parent:P)}
  {P tk(create bitmap 0 0
  bitmap:'@'#{Property.get 'oz.home'}#
  '/doc/wp/magnifier.xbm'
  tags:self foreground:blue)}
  thread {self move(D S)} end
  end
  meth move(D S)
  {WaitOr {Alarm 400} D}
  if {IsDet D} then S=unit else
  {self tk(coords {RandCoord} {RandCoord})}
  {self move(D S)}
  end
  end
  end
  end`

Figure 6.4: An animated time waster class.

The procedure `WaitDone` shown in Figure 6.5 takes a variable `Done` which is used for signalling when the computation we are waiting for is finished. It creates a randomly moving magnifier item and as soon as the magnifier signals that it has been stopped (by `Stopped`) the toplevel windows is closed.

  `proc {WaitDone Done}
  W={New Tk.toplevel tkInit(withdraw:true)}
  L={New Tk.label tkInit(parent:W text:'Computing...')}
  C={New Tk.canvas tkInit(parent:W width:50 height:50)}
  Stopped
  in
  {Tk.batch [wm(overrideredirect W true)
  pack(L C side:left pady:2#m padx:2#m)
  wm(deiconify W)]}
  _={New RandMag init(parent:C done:Done stopped:Stopped)}
  thread {Wait Stopped} {W tkClose} end
  end`

Figure 6.5: A procedure for creating wait dialogs.

For example,

  `declare Done
  {WaitDone Done}`

creates a waiting dialog which disappears by binding `Done`

  `Done=unit`