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(wxPyControl
):
58 def __init__(self
, parent
, ID
, label
,
59 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
60 style
= 0, validator
= wxDefaultValidator
,
64 wxPyControl
.__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 if wxPlatform
== '__WXMSW__':
83 EVT_LEFT_DCLICK(self
, self
.OnLeftDown
)
84 EVT_MOTION(self
, self
.OnMotion
)
85 EVT_SET_FOCUS(self
, self
.OnGainFocus
)
86 EVT_KILL_FOCUS(self
, self
.OnLoseFocus
)
87 EVT_KEY_DOWN(self
, self
.OnKeyDown
)
88 EVT_KEY_UP(self
, self
.OnKeyUp
)
89 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
90 EVT_PAINT(self
, self
.OnPaint
)
93 def SetBestSize(self
, size
=None):
95 Given the current font and bezel width settings, calculate
100 if type(size
) == type(()):
101 size
= wxSize(size
[0], size
[1])
102 size
= wxSize(size
.width
, size
.height
) # make a copy
104 best
= self
.GetBestSize()
106 size
.width
= best
.width
107 if size
.height
== -1:
108 size
.height
= best
.height
113 def DoGetBestSize(self
):
114 """Overridden base class virtual. Determines the best size of the
115 button based on the label and bezel size."""
116 w
, h
, useMin
= self
._GetLabelSize
()
117 defSize
= wxButton_GetDefaultSize()
119 if useMin
and width
< defSize
.width
:
120 width
= defSize
.width
122 if useMin
and height
< defSize
.height
:
123 height
= defSize
.height
124 width
= width
+ self
.bezelWidth
- 1
125 height
= height
+ self
.bezelWidth
- 1
126 return (width
, height
)
129 def AcceptsFocus(self
):
130 """Overridden base class virtual."""
131 return self
.IsShown() and self
.IsEnabled()
134 def SetBezelWidth(self
, width
):
135 """Set the width of the 3D effect"""
136 self
.bezelWidth
= width
138 def GetBezelWidth(self
):
139 """Return the width of the 3D effect"""
140 return self
.bezelWidth
142 def SetUseFocusIndicator(self
, flag
):
143 """Specifiy if a focus indicator (dotted line) should be used"""
144 self
.useFocusInd
= flag
146 def GetUseFocusIndicator(self
):
147 """Return focus indicator flag"""
148 return self
.useFocusInd
151 def InitColours(self
):
152 faceClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)
153 textClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT
)
154 self
.faceDnClr
= faceClr
155 self
.SetBackgroundColour(faceClr
)
156 self
.SetForegroundColour(textClr
)
158 shadowClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW
)
159 highlightClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT
)
160 self
.shadowPen
= wxPen(shadowClr
, 1, wxSOLID
)
161 self
.highlightPen
= wxPen(highlightClr
, 1, wxSOLID
)
162 if wxPlatform
== "__WXMAC__":
163 self
.focusIndPen
= wxPen(textClr
, 1, wxSOLID
)
165 self
.focusIndPen
= wxPen(textClr
, 1, wxUSER_DASH
)
166 self
.focusIndPen
.SetDashes([1,1])
167 self
.focusIndPen
.SetCap(wxCAP_BUTT
)
168 self
.focusClr
= highlightClr
171 def SetBackgroundColour(self
, colour
):
172 wxPyControl
.SetBackgroundColour(self
, colour
)
173 colour
= self
.GetBackgroundColour()
175 # Calculate a new set of highlight and shadow colours based on
176 # the new background colour. Works okay if the colour is dark...
177 r
, g
, b
= colour
.Get()
178 fr
, fg
, fb
= min(255,r
+32), min(255,g
+32), min(255,b
+32)
179 self
.faceDnClr
= wxColour(fr
, fg
, fb
)
180 sr
, sg
, sb
= max(0,r
-32), max(0,g
-32), max(0,b
-32)
181 self
.shadowPen
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
)
182 hr
, hg
, hb
= min(255,r
+64), min(255,g
+64), min(255,b
+64)
183 self
.highlightPen
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
)
184 self
.focusClr
= wxColour(hr
, hg
, hb
)
187 def _GetLabelSize(self
):
188 """ used internally """
189 w
, h
= self
.GetTextExtent(self
.GetLabel())
194 evt
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId())
195 evt
.SetIsDown(not self
.up
)
196 evt
.SetButtonObj(self
)
197 evt
.SetEventObject(self
)
198 self
.GetEventHandler().ProcessEvent(evt
)
201 def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
):
202 # draw the upper left sides
204 dc
.SetPen(self
.highlightPen
)
206 dc
.SetPen(self
.shadowPen
)
207 for i
in range(self
.bezelWidth
):
208 dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
)
209 dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
)
211 # draw the lower right sides
213 dc
.SetPen(self
.shadowPen
)
215 dc
.SetPen(self
.highlightPen
)
216 for i
in range(self
.bezelWidth
):
217 dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
)
218 dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
)
221 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
222 dc
.SetFont(self
.GetFont())
224 dc
.SetTextForeground(self
.GetForegroundColour())
226 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
227 label
= self
.GetLabel()
228 tw
, th
= dc
.GetTextExtent(label
)
230 dw
= dy
= self
.labelDelta
231 dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
)
234 def DrawFocusIndicator(self
, dc
, w
, h
):
237 ## self.focusIndPen.SetColour(self.GetForegroundColour())
239 ## #self.focusIndPen.SetColour(self.GetBackgroundColour())
240 ## self.focusIndPen.SetColour(self.GetForegroundColour())
241 self
.focusIndPen
.SetColour(self
.focusClr
)
242 dc
.SetLogicalFunction(wxINVERT
)
243 dc
.SetPen(self
.focusIndPen
)
244 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
245 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
246 dc
.SetLogicalFunction(wxCOPY
)
249 def OnPaint(self
, event
):
250 (width
, height
) = self
.GetClientSizeTuple()
254 dc
= wxBufferedPaintDC(self
)
256 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
258 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
260 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
261 self
.DrawLabel(dc
, width
, height
)
262 if self
.hasFocus
and self
.useFocusInd
:
263 self
.DrawFocusIndicator(dc
, width
, height
)
266 def OnEraseBackground(self
, event
):
270 def OnLeftDown(self
, event
):
271 if not self
.IsEnabled():
280 def OnLeftUp(self
, event
):
281 if not self
.IsEnabled():
284 if not self
.up
: # if the button was down when the mouse was released...
291 def OnMotion(self
, event
):
292 if not self
.IsEnabled():
294 if event
.LeftIsDown():
295 x
,y
= event
.GetPositionTuple()
296 w
,h
= self
.GetClientSizeTuple()
297 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
301 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
308 def OnGainFocus(self
, event
):
310 dc
= wxClientDC(self
)
311 w
, h
= self
.GetClientSizeTuple()
313 self
.DrawFocusIndicator(dc
, w
, h
)
316 def OnLoseFocus(self
, event
):
317 self
.hasFocus
= false
318 dc
= wxClientDC(self
)
319 w
, h
= self
.GetClientSizeTuple()
321 self
.DrawFocusIndicator(dc
, w
, h
)
324 def OnKeyDown(self
, event
):
325 if self
.hasFocus
and event
.KeyCode() == ord(" "):
331 def OnKeyUp(self
, event
):
332 if self
.hasFocus
and event
.KeyCode() == ord(" "):
339 #----------------------------------------------------------------------
341 class wxGenBitmapButton(wxGenButton
):
342 def __init__(self
, parent
, ID
, bitmap
,
343 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
344 style
= 0, validator
= wxDefaultValidator
,
346 self
.bmpLabel
= bitmap
347 self
.bmpDisabled
= None
349 self
.bmpSelected
= None
350 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
353 def GetBitmapLabel(self
):
355 def GetBitmapDisabled(self
):
356 return self
.bmpDisabled
357 def GetBitmapFocus(self
):
359 def GetBitmapSelected(self
):
360 return self
.bmpSelected
363 def SetBitmapDisabled(self
, bitmap
):
364 """Set bitmap to display when the button is disabled"""
365 self
.bmpDisabled
= bitmap
367 def SetBitmapFocus(self
, bitmap
):
368 """Set bitmap to display when the button has the focus"""
369 self
.bmpFocus
= bitmap
370 self
.SetUseFocusIndicator(false
)
372 def SetBitmapSelected(self
, bitmap
):
373 """Set bitmap to display when the button is selected (pressed down)"""
374 self
.bmpSelected
= bitmap
376 def SetBitmapLabel(self
, bitmap
):
377 """Set the bitmap to display normally. This is the only one that is required."""
378 self
.bmpLabel
= bitmap
381 def _GetLabelSize(self
):
382 """ used internally """
383 if not self
.bmpLabel
:
385 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
387 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
389 if self
.bmpDisabled
and not self
.IsEnabled():
390 bmp
= self
.bmpDisabled
391 if self
.bmpFocus
and self
.hasFocus
:
393 if self
.bmpSelected
and not self
.up
:
394 bmp
= self
.bmpSelected
395 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
397 dw
= dy
= self
.labelDelta
398 hasMask
= bmp
.GetMask() != None
399 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
)
402 #----------------------------------------------------------------------
405 class wxGenBitmapTextButton(wxGenBitmapButton
): # generic bitmapped button with Text Label
406 def __init__(self
, parent
, ID
, bitmap
, label
,
407 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
408 style
= 0, validator
= wxDefaultValidator
,
410 wxGenBitmapButton
.__init
__(self
, parent
, ID
, bitmap
, pos
, size
, style
, validator
, name
)
414 def _GetLabelSize(self
):
415 """ used internally """
416 w
, h
= self
.GetTextExtent(self
.GetLabel())
417 if not self
.bmpLabel
:
418 return w
, h
, true
# if there isn't a bitmap use the size of the text
420 w_bmp
= self
.bmpLabel
.GetWidth()+2
421 h_bmp
= self
.bmpLabel
.GetHeight()+2
427 return width
, height
, true
430 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
432 if bmp
!= None: # if the bitmap is used
433 if self
.bmpDisabled
and not self
.IsEnabled():
434 bmp
= self
.bmpDisabled
435 if self
.bmpFocus
and self
.hasFocus
:
437 if self
.bmpSelected
and not self
.up
:
438 bmp
= self
.bmpSelected
439 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
441 dw
= dy
= self
.labelDelta
442 hasMask
= bmp
.GetMask() != None
444 bw
= bh
= 0 # no bitmap -> size is zero
446 dc
.SetFont(self
.GetFont())
448 dc
.SetTextForeground(self
.GetForegroundColour())
450 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
452 label
= self
.GetLabel()
453 tw
, th
= dc
.GetTextExtent(label
) # size of text
455 dw
= dy
= self
.labelDelta
457 pos_x
= (width
-bw
-tw
)/2+dw
# adjust for bitmap and text to centre
459 dc
.DrawBitmap(bmp
, pos_x
, (height
-bh
)/2+dy
, hasMask
) # draw bitmap if available
460 pos_x
= pos_x
+ 2 # extra spacing from bitmap
462 dc
.DrawText(label
, pos_x
+ dw
+bw
, (height
-th
)/2+dy
) # draw the text
465 #----------------------------------------------------------------------
469 def SetToggle(self
, flag
):
475 def OnLeftDown(self
, event
):
476 if not self
.IsEnabled():
478 self
.saveUp
= self
.up
479 self
.up
= not self
.up
484 def OnLeftUp(self
, event
):
485 if not self
.IsEnabled():
487 if self
.up
!= self
.saveUp
:
492 def OnKeyDown(self
, event
):
495 def OnKeyUp(self
, event
):
496 if self
.hasFocus
and event
.KeyCode() == ord(" "):
497 self
.up
= not self
.up
505 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
508 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
511 class wxGenBitmapTextToggleButton(__ToggleMixin
, wxGenBitmapTextButton
):
514 #----------------------------------------------------------------------