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
74 font
= parent
.GetFont()
76 font
= wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)
78 self
.SetBestSize(size
)
81 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
82 EVT_LEFT_UP(self
, self
.OnLeftUp
)
83 EVT_MOTION(self
, self
.OnMotion
)
84 EVT_SET_FOCUS(self
, self
.OnGainFocus
)
85 EVT_KILL_FOCUS(self
, self
.OnLoseFocus
)
86 EVT_KEY_DOWN(self
, self
.OnKeyDown
)
87 EVT_KEY_UP(self
, self
.OnKeyUp
)
88 EVT_ERASE_BACKGROUND(self
, self
.OnEraseBackground
)
89 EVT_PAINT(self
, self
.OnPaint
)
90 EVT_IDLE(self
, self
.OnIdle
)
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])
103 # make a new size so we don't mess with the one passed in
104 size
= wxSize(size
.width
, size
.height
)
106 w
, h
, useMin
= self
._GetLabelSize
()
107 defSize
= wxButton_GetDefaultSize()
110 if useMin
and size
.width
< defSize
.width
:
111 size
.width
= defSize
.width
112 if size
.height
== -1:
114 if useMin
and size
.height
< defSize
.height
:
115 size
.height
= defSize
.height
117 size
.width
= size
.width
+ self
.bezelWidth
- 1
118 size
.height
= size
.height
+ self
.bezelWidth
- 1
123 def SetBezelWidth(self
, width
):
124 """Set the width of the 3D effect"""
125 self
.bezelWidth
= width
127 def GetBezelWidth(self
):
128 """Return the width of the 3D effect"""
129 return self
.bezelWidth
131 def SetUseFocusIndicator(self
, flag
):
132 """Specifiy if a focus indicator (dotted line) should be used"""
133 self
.useFocusInd
= flag
135 def GetUseFocusIndicator(self
):
136 """Return focus indicator flag"""
137 return self
.useFocusInd
140 def InitColours(self
):
141 faceClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)
142 textClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT
)
143 self
.faceDnClr
= faceClr
144 self
.SetBackgroundColour(faceClr
)
145 self
.SetForegroundColour(textClr
)
147 shadowClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW
)
148 highlightClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT
)
149 self
.shadowPen
= wxPen(shadowClr
, 1, wxSOLID
)
150 self
.highlightPen
= wxPen(highlightClr
, 1, wxSOLID
)
151 ##self.focusIndPen = wxPen(textClr, 1, wxUSER_DASH)
152 self
.focusIndPen
= wxPen(textClr
, 1, wxDOT
)
155 def SetBackgroundColour(self
, colour
):
156 wxWindow
.SetBackgroundColour(self
, colour
)
158 # Calculate a new set of highlight and shadow colours based on
159 # the new background colour. Works okay if the colour is dark...
160 r
, g
, b
= colour
.Get()
161 fr
, fg
, fb
= min(255,r
+32), min(255,g
+32), min(255,b
+32)
162 self
.faceDnClr
= wxColour(fr
, fg
, fb
)
163 sr
, sg
, sb
= max(0,r
-32), max(0,g
-32), max(0,b
-32)
164 self
.shadowPen
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
)
165 hr
, hg
, hb
= min(255,r
+64), min(255,g
+64), min(255,b
+64)
166 self
.highlightPen
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
)
169 def _GetLabelSize(self
):
170 """ used internally """
171 w
, h
= self
.GetTextExtent(self
.GetLabel())
176 evt
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId())
177 evt
.SetIsDown(not self
.up
)
178 evt
.SetButtonObj(self
)
179 self
.evtToSend
.append(evt
)
182 def OnIdle(self
, evt
):
183 while self
.evtToSend
:
184 evt
= self
.evtToSend
[0]
185 del self
.evtToSend
[0]
186 self
.GetEventHandler().ProcessEvent(evt
)
189 def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
):
190 # draw the upper left sides
192 dc
.SetPen(self
.highlightPen
)
194 dc
.SetPen(self
.shadowPen
)
195 for i
in range(self
.bezelWidth
):
196 dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
)
197 dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
)
199 # draw the lower right sides
201 dc
.SetPen(self
.shadowPen
)
203 dc
.SetPen(self
.highlightPen
)
204 for i
in range(self
.bezelWidth
):
205 dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
)
206 dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
)
209 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
210 dc
.SetFont(self
.GetFont())
212 dc
.SetTextForeground(self
.GetForegroundColour())
214 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
215 label
= self
.GetLabel()
216 tw
, th
= dc
.GetTextExtent(label
)
218 dw
= dy
= self
.labelDelta
219 dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
)
222 def DrawFocusIndicator(self
, dc
, w
, h
):
224 dc
.SetLogicalFunction(wxINVERT
)
225 self
.focusIndPen
.SetColour(self
.GetForegroundColour())
226 ##self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
227 dc
.SetPen(self
.focusIndPen
)
228 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
229 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
232 def OnPaint(self
, event
):
233 (width
, height
) = self
.GetClientSizeTuple()
239 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
241 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
243 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
244 self
.DrawLabel(dc
, width
, height
)
245 if self
.hasFocus
and self
.useFocusInd
:
246 self
.DrawFocusIndicator(dc
, width
, height
)
249 def OnEraseBackground(self
, event
):
253 def OnLeftDown(self
, event
):
254 if not self
.IsEnabled():
263 def OnLeftUp(self
, event
):
264 if not self
.IsEnabled():
266 if not self
.up
: # if the button was down when the mouse was released...
273 def OnMotion(self
, event
):
274 if not self
.IsEnabled():
276 if event
.LeftIsDown():
277 x
,y
= event
.GetPositionTuple()
278 w
,h
= self
.GetClientSizeTuple()
279 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
283 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
290 def OnGainFocus(self
, event
):
292 dc
= wxClientDC(self
)
293 w
, h
= self
.GetClientSizeTuple()
295 self
.DrawFocusIndicator(dc
, w
, h
)
298 def OnLoseFocus(self
, event
):
299 self
.hasFocus
= false
300 dc
= wxClientDC(self
)
301 w
, h
= self
.GetClientSizeTuple()
303 self
.DrawFocusIndicator(dc
, w
, h
)
306 def OnKeyDown(self
, event
):
307 if self
.hasFocus
and event
.KeyCode() == ord(" "):
313 def OnKeyUp(self
, event
):
314 if self
.hasFocus
and event
.KeyCode() == ord(" "):
321 #----------------------------------------------------------------------
323 class wxGenBitmapButton(wxGenButton
):
324 def __init__(self
, parent
, ID
, bitmap
,
325 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
326 style
= 0, validator
= wxDefaultValidator
,
328 self
.bmpLabel
= bitmap
329 self
.bmpDisabled
= None
331 self
.bmpSelected
= None
332 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
335 def GetBitmapLabel(self
):
337 def GetBitmapDisabled(self
):
338 return self
.bmpDisabled
339 def GetBitmapFocus(self
):
341 def GetBitmapSelected(self
):
342 return self
.bmpSelected
345 def SetBitmapDisabled(self
, bitmap
):
346 """Set bitmap to display when the button is disabled"""
347 self
.bmpDisabled
= bitmap
349 def SetBitmapFocus(self
, bitmap
):
350 """Set bitmap to display when the button has the focus"""
351 self
.bmpFocus
= bitmap
352 self
.SetUseFocusIndicator(false
)
354 def SetBitmapSelected(self
, bitmap
):
355 """Set bitmap to display when the button is selected (pressed down)"""
356 self
.bmpSelected
= bitmap
358 def SetBitmapLabel(self
, bitmap
):
359 """Set the bitmap to display normally. This is the only one that is required."""
360 self
.bmpLabel
= bitmap
363 def _GetLabelSize(self
):
364 """ used internally """
365 if not self
.bmpLabel
:
367 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
370 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
372 if self
.bmpDisabled
and not self
.IsEnabled():
373 bmp
= self
.bmpDisabled
374 if self
.bmpFocus
and self
.hasFocus
:
376 if self
.bmpSelected
and not self
.up
:
377 bmp
= self
.bmpSelected
378 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
380 dw
= dy
= self
.labelDelta
381 hasMask
= bmp
.GetMask() != None
382 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
)
386 #----------------------------------------------------------------------
390 def SetToggle(self
, flag
):
396 def OnLeftDown(self
, event
):
397 if not self
.IsEnabled():
399 self
.saveUp
= self
.up
400 self
.up
= not self
.up
405 def OnLeftUp(self
, event
):
406 if not self
.IsEnabled():
408 if self
.up
!= self
.saveUp
:
413 def OnKeyDown(self
, event
):
416 def OnKeyUp(self
, event
):
417 if self
.hasFocus
and event
.KeyCode() == ord(" "):
418 self
.up
= not self
.up
426 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
429 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
432 #----------------------------------------------------------------------