]>
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
.PyPanel
): 
  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
.PyPanel
.__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 DoGetBestSize(self
): 
 133         return (self
.width
, self
.height
) 
 136     def OnTimer(self
, event
): 
 137         wx
.PostEvent(self
, UpdateThrobberEvent()) 
 140     def OnDestroyWindow(self
, event
): 
 146         dc
.DrawBitmap(self
.submaps
[self
.sequence
[self
.current
]], 0, 0, True) 
 147         if self
.overlay 
and self
.showOverlay
: 
 148             dc
.DrawBitmap(self
.overlay
, self
.overlayX
, self
.overlayY
, True) 
 149         if self
.label 
and self
.showLabel
: 
 150             dc
.DrawText(self
.label
, self
.labelX
, self
.labelY
) 
 151             dc
.SetTextForeground(wx
.WHITE
) 
 152             dc
.DrawText(self
.label
, self
.labelX
-1, self
.labelY
-1) 
 155     def OnPaint(self
, event
): 
 156         self
.Draw(wx
.PaintDC(self
)) 
 160     def Rotate(self
, event
): 
 161         self
.current 
+= self
.direction
 
 162         if self
.current 
>= len(self
.sequence
): 
 165                 self
.current 
= len(self
.sequence
) - 1 
 173                 self
.current 
= len(self
.sequence
) - 1 
 174         self
.Draw(wx
.ClientDC(self
)) 
 177     # --------- public methods --------- 
 178     def SetFont(self
, font
): 
 179         """Set the font for the label""" 
 180         wx
.Panel
.SetFont(self
, font
) 
 181         self
.SetLabel(self
.label
) 
 182         self
.Draw(wx
.ClientDC(self
)) 
 186         """Stop the animation and return to frame 0""" 
 189         self
.Draw(wx
.ClientDC(self
)) 
 193         """Change the direction of the animation""" 
 194         self
.direction 
= -self
.direction
 
 198         """Returns True if the animation is running""" 
 203         """Start the animation""" 
 205             self
.running 
= not self
.running
 
 206             self
.timer
.Start(int(self
.frameDelay 
* 1000)) 
 210         """Stop the animation""" 
 213             self
.running 
= not self
.running
 
 216     def SetFrameDelay(self
, frameDelay 
= 0.05): 
 217         """Delay between each frame""" 
 218         self
.frameDelay 
= frameDelay
 
 224     def ToggleOverlay(self
, state 
= None): 
 225         """Toggle the overlay image""" 
 227             self
.showOverlay 
= not self
.showOverlay
 
 229             self
.showOverlay 
= state
 
 230         self
.Draw(wx
.ClientDC(self
)) 
 233     def ToggleLabel(self
, state 
= None): 
 234         """Toggle the label""" 
 236             self
.showLabel 
= not self
.showLabel
 
 238             self
.showLabel 
= state
 
 239         self
.Draw(wx
.ClientDC(self
)) 
 242     def SetLabel(self
, label
): 
 243         """Change the text of the label""" 
 246             extentX
, extentY 
= self
.GetTextExtent(label
) 
 247             self
.labelX 
= (self
.width 
- extentX
)/2 
 248             self
.labelY 
= (self
.height 
- extentY
)/2 
 249         self
.Draw(wx
.ClientDC(self
)) 
 253 # ------------------------------------------------------------------------------