1 #---------------------------------------------------------------------- 
   2 # Name:        wxPython.lib.buttons 
   3 # Purpose:     Various kinds of generic buttons, (not native controls but 
  10 # Copyright:   (c) 1999 by Total Control Software 
  11 # Licence:     wxWindows license 
  12 #---------------------------------------------------------------------- 
  15 This module implements various forms of generic buttons, meaning that 
  16 they are not built on native controls but are self-drawn. 
  18 The wxGenButton is the base.  It acts like a normal button but you 
  19 are able to better control how it looks, bevel width, colours, etc. 
  21 wxGenBitmapButton is a button with one or more bitmaps that show 
  22 the various states the button can be in. 
  24 wxGenToggleButton stays depressed when clicked, until clicked again. 
  26 wxGenBitmapToggleButton the same but with bitmaps. 
  30 from wxPython
.wx 
import * 
  32 #---------------------------------------------------------------------- 
  34 class wxGenButtonEvent(wxPyCommandEvent
): 
  35     def __init__(self
, eventType
, ID
): 
  36         wxPyCommandEvent
.__init
__(self
, eventType
, ID
) 
  40     def SetIsDown(self
, isDown
): 
  46     def SetButtonObj(self
, btn
): 
  49     def GetButtonObj(self
): 
  53 #---------------------------------------------------------------------- 
  55 class wxGenButton(wxControl
): 
  58     def __init__(self
, parent
, ID
, label
, 
  59                  pos 
= wxDefaultPosition
, size 
= wxDefaultSize
, 
  60                  style 
= 0, validator 
= wxDefaultValidator
, 
  64         wxControl
.__init
__(self
, parent
, ID
, pos
, size
, style
, validator
, name
) 
  69         self
.useFocusInd 
= true
 
  73         font 
= parent
.GetFont() 
  75             font 
= wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT
) 
  77         self
.SetBestSize(size
) 
  80         EVT_LEFT_DOWN(self
,        self
.OnLeftDown
) 
  81         EVT_LEFT_UP(self
,          self
.OnLeftUp
) 
  82         EVT_MOTION(self
,           self
.OnMotion
) 
  83         EVT_SET_FOCUS(self
,        self
.OnGainFocus
) 
  84         EVT_KILL_FOCUS(self
,       self
.OnLoseFocus
) 
  85         EVT_KEY_DOWN(self
,         self
.OnKeyDown
) 
  86         EVT_KEY_UP(self
,           self
.OnKeyUp
) 
  87         EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
) 
  88         EVT_PAINT(self
,            self
.OnPaint
) 
  91     def SetBestSize(self
, size
=None): 
  93         Given the current font and bezel width settings, calculate 
  98         if type(size
) == type(()): 
  99             size 
= wxSize(size
[0], size
[1]) 
 101         # make a new size so we don't mess with the one passed in 
 102         size 
= wxSize(size
.width
, size
.height
) 
 104         w
, h
, useMin 
= self
._GetLabelSize
() 
 105         defSize 
= wxButton_GetDefaultSize() 
 108             if useMin 
and size
.width 
< defSize
.width
: 
 109                 size
.width 
= defSize
.width
 
 110         if size
.height 
== -1: 
 112             if useMin 
and size
.height 
< defSize
.height
: 
 113                 size
.height 
= defSize
.height
 
 115         size
.width 
= size
.width 
+ self
.bezelWidth 
- 1 
 116         size
.height 
= size
.height 
+ self
.bezelWidth 
- 1 
 121     def SetBezelWidth(self
, width
): 
 122         """Set the width of the 3D effect""" 
 123         self
.bezelWidth 
= width
 
 125     def GetBezelWidth(self
): 
 126         """Return the width of the 3D effect""" 
 127         return self
.bezelWidth
 
 129     def SetUseFocusIndicator(self
, flag
): 
 130         """Specifiy if a focus indicator (dotted line) should be used""" 
 131         self
.useFocusInd 
= flag
 
 133     def GetUseFocusIndicator(self
): 
 134         """Return focus indicator flag""" 
 135         return self
.useFocusInd
 
 138     def InitColours(self
): 
 139         faceClr      
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
) 
 140         textClr      
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT
) 
 141         self
.faceDnClr 
= faceClr
 
 142         self
.SetBackgroundColour(faceClr
) 
 143         self
.SetForegroundColour(textClr
) 
 145         shadowClr    
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW
) 
 146         highlightClr 
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT
) 
 147         self
.shadowPen    
= wxPen(shadowClr
, 1, wxSOLID
) 
 148         self
.highlightPen 
= wxPen(highlightClr
, 1, wxSOLID
) 
 149         ##self.focusIndPen  = wxPen(textClr, 1, wxUSER_DASH) 
 150         self
.focusIndPen 
= wxPen(textClr
, 1, wxDOT
) 
 153     def SetBackgroundColour(self
, colour
): 
 154         wxWindow
.SetBackgroundColour(self
, colour
) 
 156         # Calculate a new set of highlight and shadow colours based on 
 157         # the new background colour.  Works okay if the colour is dark... 
 158         r
, g
, b 
= colour
.Get() 
 159         fr
, fg
, fb 
= min(255,r
+32), min(255,g
+32), min(255,b
+32) 
 160         self
.faceDnClr 
= wxColour(fr
, fg
, fb
) 
 161         sr
, sg
, sb 
= max(0,r
-32), max(0,g
-32), max(0,b
-32) 
 162         self
.shadowPen 
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
) 
 163         hr
, hg
, hb 
= min(255,r
+64), min(255,g
+64), min(255,b
+64) 
 164         self
.highlightPen 
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
) 
 167     def _GetLabelSize(self
): 
 168         """ used internally """ 
 169         w
, h 
= self
.GetTextExtent(self
.GetLabel()) 
 174         evt 
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId()) 
 175         evt
.SetIsDown(not self
.up
) 
 176         evt
.SetButtonObj(self
) 
 177         self
.GetEventHandler().ProcessEvent(evt
) 
 180     def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
): 
 181         # draw the upper left sides 
 183             dc
.SetPen(self
.highlightPen
) 
 185             dc
.SetPen(self
.shadowPen
) 
 186         for i 
in range(self
.bezelWidth
): 
 187             dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
) 
 188             dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
) 
 190         # draw the lower right sides 
 192             dc
.SetPen(self
.shadowPen
) 
 194             dc
.SetPen(self
.highlightPen
) 
 195         for i 
in range(self
.bezelWidth
): 
 196             dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
) 
 197             dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
) 
 200     def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0): 
 201         dc
.SetFont(self
.GetFont()) 
 203             dc
.SetTextForeground(self
.GetForegroundColour()) 
 205             dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
)) 
 206         label 
= self
.GetLabel() 
 207         tw
, th 
= dc
.GetTextExtent(label
) 
 209             dw 
= dy 
= self
.labelDelta
 
 210         dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
) 
 213     def DrawFocusIndicator(self
, dc
, w
, h
): 
 215         dc
.SetLogicalFunction(wxINVERT
) 
 216         self
.focusIndPen
.SetColour(self
.GetForegroundColour()) 
 217         ##self.focusIndPen.SetDashes([1,2,1,2])  # This isn't quite working the way I expected... 
 218         dc
.SetPen(self
.focusIndPen
) 
 219         dc
.SetBrush(wxTRANSPARENT_BRUSH
) 
 220         dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4) 
 223     def OnPaint(self
, event
): 
 224         (width
, height
) = self
.GetClientSizeTuple() 
 230             dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
)) 
 232             dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
)) 
 234         self
.DrawBezel(dc
, x1
, y1
, x2
, y2
) 
 235         self
.DrawLabel(dc
, width
, height
) 
 236         if self
.hasFocus 
and self
.useFocusInd
: 
 237             self
.DrawFocusIndicator(dc
, width
, height
) 
 240     def OnEraseBackground(self
, event
): 
 244     def OnLeftDown(self
, event
): 
 245         if not self
.IsEnabled(): 
 254     def OnLeftUp(self
, event
): 
 255         if not self
.IsEnabled(): 
 257         if not self
.up
:    # if the button was down when the mouse was released... 
 264     def OnMotion(self
, event
): 
 265         if not self
.IsEnabled(): 
 267         if event
.LeftIsDown(): 
 268             x
,y 
= event
.GetPositionTuple() 
 269             w
,h 
= self
.GetClientSizeTuple() 
 270             if self
.up 
and x
<w 
and x
>=0 and y
<h 
and y
>=0: 
 274             if not self
.up 
and (x
<0 or y
<0 or x
>=w 
or y
>=h
): 
 281     def OnGainFocus(self
, event
): 
 283         dc 
= wxClientDC(self
) 
 284         w
, h 
= self
.GetClientSizeTuple() 
 286             self
.DrawFocusIndicator(dc
, w
, h
) 
 289     def OnLoseFocus(self
, event
): 
 290         self
.hasFocus 
= false
 
 291         dc 
= wxClientDC(self
) 
 292         w
, h 
= self
.GetClientSizeTuple() 
 294             self
.DrawFocusIndicator(dc
, w
, h
) 
 297     def OnKeyDown(self
, event
): 
 298         if self
.hasFocus 
and event
.KeyCode() == ord(" "): 
 304     def OnKeyUp(self
, event
): 
 305         if self
.hasFocus 
and event
.KeyCode() == ord(" "): 
 312 #---------------------------------------------------------------------- 
 314 class wxGenBitmapButton(wxGenButton
): 
 315     def __init__(self
, parent
, ID
, bitmap
, 
 316                  pos 
= wxDefaultPosition
, size 
= wxDefaultSize
, 
 317                  style 
= 0, validator 
= wxDefaultValidator
, 
 319         self
.bmpLabel 
= bitmap
 
 320         self
.bmpDisabled 
= None 
 322         self
.bmpSelected 
= None 
 323         wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
) 
 326     def GetBitmapLabel(self
): 
 328     def GetBitmapDisabled(self
): 
 329         return self
.bmpDisabled
 
 330     def GetBitmapFocus(self
): 
 332     def GetBitmapSelected(self
): 
 333         return self
.bmpSelected
 
 336     def SetBitmapDisabled(self
, bitmap
): 
 337         """Set bitmap to display when the button is disabled""" 
 338         self
.bmpDisabled 
= bitmap
 
 340     def SetBitmapFocus(self
, bitmap
): 
 341         """Set bitmap to display when the button has the focus""" 
 342         self
.bmpFocus 
= bitmap
 
 343         self
.SetUseFocusIndicator(false
) 
 345     def SetBitmapSelected(self
, bitmap
): 
 346         """Set bitmap to display when the button is selected (pressed down)""" 
 347         self
.bmpSelected 
= bitmap
 
 349     def SetBitmapLabel(self
, bitmap
): 
 350         """Set the bitmap to display normally.  This is the only one that is required.""" 
 351         self
.bmpLabel 
= bitmap
 
 354     def _GetLabelSize(self
): 
 355         """ used internally """ 
 356         if not self
.bmpLabel
: 
 358         return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
 
 361     def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0): 
 363         if self
.bmpDisabled 
and not self
.IsEnabled(): 
 364             bmp 
= self
.bmpDisabled
 
 365         if self
.bmpFocus 
and self
.hasFocus
: 
 367         if self
.bmpSelected 
and not self
.up
: 
 368             bmp 
= self
.bmpSelected
 
 369         bw
,bh 
= bmp
.GetWidth(), bmp
.GetHeight() 
 371             dw 
= dy 
= self
.labelDelta
 
 372         hasMask 
= bmp
.GetMask() != None 
 373         dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
) 
 377 #---------------------------------------------------------------------- 
 381     def SetToggle(self
, flag
): 
 387     def OnLeftDown(self
, event
): 
 388         if not self
.IsEnabled(): 
 390         self
.saveUp 
= self
.up
 
 391         self
.up 
= not self
.up
 
 396     def OnLeftUp(self
, event
): 
 397         if not self
.IsEnabled(): 
 399         if self
.up 
!= self
.saveUp
: 
 404     def OnKeyDown(self
, event
): 
 407     def OnKeyUp(self
, event
): 
 408         if self
.hasFocus 
and event
.KeyCode() == ord(" "): 
 409             self
.up 
= not self
.up
 
 417 class wxGenToggleButton(__ToggleMixin
, wxGenButton
): 
 420 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
): 
 423 #----------------------------------------------------------------------