]>
git.saurik.com Git - wxWidgets.git/blob - wxPython/wx/lib/throbber.py
   2 A throbber displays an animated image that can be 
   3 started, stopped, reversed, etc.  Useful for showing 
   4 an ongoing process (like most web browsers use) or 
   5 simply for adding eye-candy to an application. 
   7 Throbbers utilize a wxTimer so that normal processing 
   8 can continue unencumbered. 
  12 # throbber.py - Cliff Wells <clifford.wells@comcast.net> 
  14 # Thanks to Harald Massa <harald.massa@suedvers.de> for 
  15 # suggestions and sample code. 
  19 # 12/12/2003 - Jeff Grimmett (grimmtooth@softhome.net) 
  21 # o 2.5 compatability update. 
  28 # ------------------------------------------------------------------------------ 
  30 THROBBER_EVENT 
= wx
.NewEventType() 
  31 EVT_UPDATE_THROBBER 
= wx
.PyEventBinder(THROBBER_EVENT
, 0) 
  33 class UpdateThrobberEvent(wx
.PyEvent
): 
  35         wx
.PyEvent
.__init
__(self
) 
  36         self
.SetEventType(THROBBER_EVENT
) 
  38 # ------------------------------------------------------------------------------ 
  40 class Throbber(wx
.Panel
): 
  42     The first argument is either the name of a file that will be split into frames 
  43     (a composite image) or a list of  strings of image names that will be treated 
  44     as individual frames.  If a single (composite) image is given, then additional 
  45     information must be provided: the number of frames in the image and the width 
  46     of each frame.  The first frame is treated as the "at rest" frame (it is not 
  47     shown during animation, but only when Throbber.Rest() is called. 
  48     A second, single image may be optionally specified to overlay on top of the 
  49     animation. A label may also be specified to show on top of the animation. 
  51     def __init__(self
, parent
, id, 
  52                  bitmap
,          # single (composite) bitmap or list of bitmaps 
  53                  pos 
= wx
.DefaultPosition
, 
  54                  size 
= wx
.DefaultSize
, 
  55                  frameDelay 
= 0.1,# time between frames 
  56                  frames 
= 0,      # number of frames (only necessary for composite image) 
  57                  frameWidth 
= 0,  # width of each frame (only necessary for composite image) 
  58                  label 
= None,    # optional text to be displayed 
  59                  overlay 
= None,  # optional image to overlay on animation 
  60                  reverse 
= 0,     # reverse direction at end of animation 
  61                  style 
= 0,       # window style 
  63         wx
.Panel
.__init
__(self
, parent
, id, pos
, size
, style
, name
) 
  66         self
.running 
= (1 != 1) 
  67         _seqTypes 
= (type([]), type(())) 
  69         # set size, guessing if necessary 
  72             if type(bitmap
) in _seqTypes
: 
  73                 width 
= bitmap
[0].GetWidth() 
  78             if type(bitmap
) in _seqTypes
: 
  79                 height 
= bitmap
[0].GetHeight() 
  81                 height 
= bitmap
.GetHeight() 
  82         self
.width
, self
.height 
= width
, height
 
  85         assert width 
!= -1 and height 
!= -1, "Unable to guess size" 
  88             extentX
, extentY 
= self
.GetTextExtent(label
) 
  89             self
.labelX 
= (width 
- extentX
)/2 
  90             self
.labelY 
= (height 
- extentY
)/2 
  91         self
.frameDelay 
= frameDelay
 
  94         self
.autoReverse 
= reverse
 
  95         self
.overlay 
= overlay
 
  96         if overlay 
is not None: 
  97             self
.overlay 
= overlay
 
  98             self
.overlayX 
= (width 
- self
.overlay
.GetWidth()) / 2 
  99             self
.overlayY 
= (height 
- self
.overlay
.GetHeight()) / 2 
 100         self
.showOverlay 
= overlay 
is not None 
 101         self
.showLabel 
= label 
is not None 
 103         # do we have a sequence of images? 
 104         if type(bitmap
) in _seqTypes
: 
 105             self
.submaps 
= bitmap
 
 106             self
.frames 
= len(self
.submaps
) 
 107         # or a composite image that needs to be split? 
 111             for chunk 
in range(frames
): 
 112                 rect 
= (chunk 
* frameWidth
, 0, width
, height
) 
 113                 self
.submaps
.append(bitmap
.GetSubBitmap(rect
)) 
 115         # self.sequence can be changed, but it's not recommended doing it 
 116         # while the throbber is running.  self.sequence[0] should always 
 117         # refer to whatever frame is to be shown when 'resting' and be sure 
 118         # that no item in self.sequence >= self.frames or < 0!!! 
 119         self
.sequence 
= range(self
.frames
) 
 121         self
.SetClientSize((width
, height
)) 
 124         self
.timer 
= wx
.Timer(self
, timerID
) 
 126         self
.Bind(EVT_UPDATE_THROBBER
, self
.Rotate
) 
 127         self
.Bind(wx
.EVT_PAINT
, self
.OnPaint
) 
 128         self
.Bind(wx
.EVT_TIMER
, self
.OnTimer
, self
.timer
) 
 129         self
.Bind(wx
.EVT_WINDOW_DESTROY
, self
.OnDestroyWindow
) 
 132     def OnTimer(self
, event
): 
 133         wx
.PostEvent(self
, UpdateThrobberEvent()) 
 136     def OnDestroyWindow(self
, event
): 
 142         dc
.DrawBitmap(self
.submaps
[self
.sequence
[self
.current
]], (0, 0), True) 
 143         if self
.overlay 
and self
.showOverlay
: 
 144             dc
.DrawBitmap(self
.overlay
, (self
.overlayX
, self
.overlayY
), True) 
 145         if self
.label 
and self
.showLabel
: 
 146             dc
.DrawText(self
.label
, (self
.labelX
, self
.labelY
)) 
 147             dc
.SetTextForeground(wx
.WHITE
) 
 148             dc
.DrawText(self
.label
, (self
.labelX
-1, self
.labelY
-1)) 
 151     def OnPaint(self
, event
): 
 152         self
.Draw(wx
.PaintDC(self
)) 
 156     def Rotate(self
, event
): 
 157         self
.current 
+= self
.direction
 
 158         if self
.current 
>= len(self
.sequence
): 
 161                 self
.current 
= len(self
.sequence
) - 1 
 169                 self
.current 
= len(self
.sequence
) - 1 
 170         self
.Draw(wx
.ClientDC(self
)) 
 173     # --------- public methods --------- 
 174     def SetFont(self
, font
): 
 175         """Set the font for the label""" 
 176         wx
.Panel
.SetFont(self
, font
) 
 177         self
.SetLabel(self
.label
) 
 178         self
.Draw(wx
.ClientDC(self
)) 
 182         """Stop the animation and return to frame 0""" 
 185         self
.Draw(wx
.ClientDC(self
)) 
 189         """Change the direction of the animation""" 
 190         self
.direction 
= -self
.direction
 
 194         """Returns True if the animation is running""" 
 199         """Start the animation""" 
 201             self
.running 
= not self
.running
 
 202             self
.timer
.Start(int(self
.frameDelay 
* 1000)) 
 206         """Stop the animation""" 
 209             self
.running 
= not self
.running
 
 212     def SetFrameDelay(self
, frameDelay 
= 0.05): 
 213         """Delay between each frame""" 
 214         self
.frameDelay 
= frameDelay
 
 220     def ToggleOverlay(self
, state 
= None): 
 221         """Toggle the overlay image""" 
 223             self
.showOverlay 
= not self
.showOverlay
 
 225             self
.showOverlay 
= state
 
 226         self
.Draw(wx
.ClientDC(self
)) 
 229     def ToggleLabel(self
, state 
= None): 
 230         """Toggle the label""" 
 232             self
.showLabel 
= not self
.showLabel
 
 234             self
.showLabel 
= state
 
 235         self
.Draw(wx
.ClientDC(self
)) 
 238     def SetLabel(self
, label
): 
 239         """Change the text of the label""" 
 242             extentX
, extentY 
= self
.GetTextExtent(label
) 
 243             self
.labelX 
= (self
.width 
- extentX
)/2 
 244             self
.labelY 
= (self
.height 
- extentY
)/2 
 245         self
.Draw(wx
.ClientDC(self
)) 
 249 # ------------------------------------------------------------------------------