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():
258 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
360 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
362 if self
.bmpDisabled
and not self
.IsEnabled():
363 bmp
= self
.bmpDisabled
364 if self
.bmpFocus
and self
.hasFocus
:
366 if self
.bmpSelected
and not self
.up
:
367 bmp
= self
.bmpSelected
368 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
370 dw
= dy
= self
.labelDelta
371 hasMask
= bmp
.GetMask() != None
372 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
)
375 #----------------------------------------------------------------------
378 class wxGenBitmapTextButton(wxGenBitmapButton
): # generic bitmapped button with Text Label
379 def __init__(self
, parent
, ID
, bitmap
, label
,
380 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
381 style
= 0, validator
= wxDefaultValidator
,
383 wxGenBitmapButton
.__init
__(self
, parent
, ID
, bitmap
, pos
, size
, style
, validator
, name
)
387 def _GetLabelSize(self
):
388 """ used internally """
389 w
, h
= self
.GetTextExtent(self
.GetLabel())
390 if not self
.bmpLabel
:
391 return w
, h
, true
# if there isn't a bitmap use the size of the text
393 w_bmp
= self
.bmpLabel
.GetWidth()+2
394 h_bmp
= self
.bmpLabel
.GetHeight()+2
400 return width
, height
, true
403 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
405 if bmp
!= None: # if the bitmap is used
406 if self
.bmpDisabled
and not self
.IsEnabled():
407 bmp
= self
.bmpDisabled
408 if self
.bmpFocus
and self
.hasFocus
:
410 if self
.bmpSelected
and not self
.up
:
411 bmp
= self
.bmpSelected
412 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
414 dw
= dy
= self
.labelDelta
415 hasMask
= bmp
.GetMask() != None
417 bw
= bh
= 0 # no bitmap -> size is zero
419 dc
.SetFont(self
.GetFont())
421 dc
.SetTextForeground(self
.GetForegroundColour())
423 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
425 label
= self
.GetLabel()
426 tw
, th
= dc
.GetTextExtent(label
) # size of text
428 dw
= dy
= self
.labelDelta
430 pos_x
= (width
-bw
-tw
)/2+dw
# adjust for bitmap and text to centre
432 dc
.DrawBitmap(bmp
, pos_x
, (height
-bh
)/2+dy
, hasMask
) # draw bitmap if available
433 pos_x
= pos_x
+ 2 # extra spacing from bitmap
435 dc
.DrawText(label
, pos_x
+ dw
+bw
, (height
-th
)/2+dy
) # draw the text
438 #----------------------------------------------------------------------
442 def SetToggle(self
, flag
):
448 def OnLeftDown(self
, event
):
449 if not self
.IsEnabled():
451 self
.saveUp
= self
.up
452 self
.up
= not self
.up
457 def OnLeftUp(self
, event
):
458 if not self
.IsEnabled():
460 if self
.up
!= self
.saveUp
:
465 def OnKeyDown(self
, event
):
468 def OnKeyUp(self
, event
):
469 if self
.hasFocus
and event
.KeyCode() == ord(" "):
470 self
.up
= not self
.up
478 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
481 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
484 class wxGenBitmapTextToggleButton(__ToggleMixin
, wxGenBitmapTextButton
):
487 #----------------------------------------------------------------------