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 wxControl
.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
):
216 self
.focusIndPen
.SetColour(self
.GetForegroundColour())
218 self
.focusIndPen
.SetColour(self
.GetBackgroundColour())
219 ##self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
220 dc
.SetPen(self
.focusIndPen
)
221 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
222 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
225 def OnPaint(self
, event
):
226 (width
, height
) = self
.GetClientSizeTuple()
230 dc
= wxBufferedPaintDC(self
)
232 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
234 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
236 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
237 self
.DrawLabel(dc
, width
, height
)
238 if self
.hasFocus
and self
.useFocusInd
:
239 self
.DrawFocusIndicator(dc
, width
, height
)
242 def OnEraseBackground(self
, event
):
246 def OnLeftDown(self
, event
):
247 if not self
.IsEnabled():
256 def OnLeftUp(self
, event
):
257 if not self
.IsEnabled():
260 if not self
.up
: # if the button was down when the mouse was released...
266 def OnMotion(self
, event
):
267 if not self
.IsEnabled():
269 if event
.LeftIsDown():
270 x
,y
= event
.GetPositionTuple()
271 w
,h
= self
.GetClientSizeTuple()
272 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
276 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
283 def OnGainFocus(self
, event
):
285 dc
= wxClientDC(self
)
286 w
, h
= self
.GetClientSizeTuple()
288 self
.DrawFocusIndicator(dc
, w
, h
)
291 def OnLoseFocus(self
, event
):
292 self
.hasFocus
= false
293 dc
= wxClientDC(self
)
294 w
, h
= self
.GetClientSizeTuple()
296 self
.DrawFocusIndicator(dc
, w
, h
)
299 def OnKeyDown(self
, event
):
300 if self
.hasFocus
and event
.KeyCode() == ord(" "):
306 def OnKeyUp(self
, event
):
307 if self
.hasFocus
and event
.KeyCode() == ord(" "):
314 #----------------------------------------------------------------------
316 class wxGenBitmapButton(wxGenButton
):
317 def __init__(self
, parent
, ID
, bitmap
,
318 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
319 style
= 0, validator
= wxDefaultValidator
,
321 self
.bmpLabel
= bitmap
322 self
.bmpDisabled
= None
324 self
.bmpSelected
= None
325 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
328 def GetBitmapLabel(self
):
330 def GetBitmapDisabled(self
):
331 return self
.bmpDisabled
332 def GetBitmapFocus(self
):
334 def GetBitmapSelected(self
):
335 return self
.bmpSelected
338 def SetBitmapDisabled(self
, bitmap
):
339 """Set bitmap to display when the button is disabled"""
340 self
.bmpDisabled
= bitmap
342 def SetBitmapFocus(self
, bitmap
):
343 """Set bitmap to display when the button has the focus"""
344 self
.bmpFocus
= bitmap
345 self
.SetUseFocusIndicator(false
)
347 def SetBitmapSelected(self
, bitmap
):
348 """Set bitmap to display when the button is selected (pressed down)"""
349 self
.bmpSelected
= bitmap
351 def SetBitmapLabel(self
, bitmap
):
352 """Set the bitmap to display normally. This is the only one that is required."""
353 self
.bmpLabel
= bitmap
356 def _GetLabelSize(self
):
357 """ used internally """
358 if not self
.bmpLabel
:
360 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
362 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
364 if self
.bmpDisabled
and not self
.IsEnabled():
365 bmp
= self
.bmpDisabled
366 if self
.bmpFocus
and self
.hasFocus
:
368 if self
.bmpSelected
and not self
.up
:
369 bmp
= self
.bmpSelected
370 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
372 dw
= dy
= self
.labelDelta
373 hasMask
= bmp
.GetMask() != None
374 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
)
377 #----------------------------------------------------------------------
380 class wxGenBitmapTextButton(wxGenBitmapButton
): # generic bitmapped button with Text Label
381 def __init__(self
, parent
, ID
, bitmap
, label
,
382 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
383 style
= 0, validator
= wxDefaultValidator
,
385 wxGenBitmapButton
.__init
__(self
, parent
, ID
, bitmap
, pos
, size
, style
, validator
, name
)
389 def _GetLabelSize(self
):
390 """ used internally """
391 w
, h
= self
.GetTextExtent(self
.GetLabel())
392 if not self
.bmpLabel
:
393 return w
, h
, true
# if there isn't a bitmap use the size of the text
395 w_bmp
= self
.bmpLabel
.GetWidth()+2
396 h_bmp
= self
.bmpLabel
.GetHeight()+2
402 return width
, height
, true
405 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
407 if bmp
!= None: # if the bitmap is used
408 if self
.bmpDisabled
and not self
.IsEnabled():
409 bmp
= self
.bmpDisabled
410 if self
.bmpFocus
and self
.hasFocus
:
412 if self
.bmpSelected
and not self
.up
:
413 bmp
= self
.bmpSelected
414 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
416 dw
= dy
= self
.labelDelta
417 hasMask
= bmp
.GetMask() != None
419 bw
= bh
= 0 # no bitmap -> size is zero
421 dc
.SetFont(self
.GetFont())
423 dc
.SetTextForeground(self
.GetForegroundColour())
425 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
427 label
= self
.GetLabel()
428 tw
, th
= dc
.GetTextExtent(label
) # size of text
430 dw
= dy
= self
.labelDelta
432 pos_x
= (width
-bw
-tw
)/2+dw
# adjust for bitmap and text to centre
434 dc
.DrawBitmap(bmp
, pos_x
, (height
-bh
)/2+dy
, hasMask
) # draw bitmap if available
435 pos_x
= pos_x
+ 2 # extra spacing from bitmap
437 dc
.DrawText(label
, pos_x
+ dw
+bw
, (height
-th
)/2+dy
) # draw the text
440 #----------------------------------------------------------------------
444 def SetToggle(self
, flag
):
450 def OnLeftDown(self
, event
):
451 if not self
.IsEnabled():
453 self
.saveUp
= self
.up
454 self
.up
= not self
.up
459 def OnLeftUp(self
, event
):
460 if not self
.IsEnabled():
462 if self
.up
!= self
.saveUp
:
467 def OnKeyDown(self
, event
):
470 def OnKeyUp(self
, event
):
471 if self
.hasFocus
and event
.KeyCode() == ord(" "):
472 self
.up
= not self
.up
480 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
483 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
486 class wxGenBitmapTextToggleButton(__ToggleMixin
, wxGenBitmapTextButton
):
489 #----------------------------------------------------------------------