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
):
56 def __init__(self
, parent
, ID
, label
,
57 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
58 style
= 0, validator
= wxDefaultValidator
,
62 wxControl
.__init
__(self
, parent
, ID
, pos
, size
, style
, validator
, name
)
67 self
.useFocusInd
= true
71 font
= parent
.GetFont()
73 font
= wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)
75 self
.SetBestSize(size
)
78 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
79 EVT_LEFT_UP(self
, self
.OnLeftUp
)
80 EVT_MOTION(self
, self
.OnMotion
)
81 EVT_SET_FOCUS(self
, self
.OnGainFocus
)
82 EVT_KILL_FOCUS(self
, self
.OnLoseFocus
)
83 EVT_KEY_DOWN(self
, self
.OnKeyDown
)
84 EVT_KEY_UP(self
, self
.OnKeyUp
)
87 def SetBestSize(self
, size
=None):
89 Given the current font and bezel width settings, calculate
94 if type(size
) == type(()):
95 size
= wxSize(size
[0], size
[1])
97 # make a new size so we don't mess with the one passed in
98 size
= wxSize(size
.width
, size
.height
)
100 w
, h
, useMin
= self
._GetLabelSize
()
101 defSize
= wxButton_GetDefaultSize()
104 if useMin
and size
.width
< defSize
.width
:
105 size
.width
= defSize
.width
106 if size
.height
== -1:
108 if useMin
and size
.height
< defSize
.height
:
109 size
.height
= defSize
.height
111 size
.width
= size
.width
+ self
.bezelWidth
- 1
112 size
.height
= size
.height
+ self
.bezelWidth
- 1
117 def SetBezelWidth(self
, width
):
118 """Set the width of the 3D effect"""
119 self
.bezelWidth
= width
121 def GetBezelWidth(self
):
122 """Return the width of the 3D effect"""
123 return self
.bezelWidth
125 def SetUseFocusIndicator(self
, flag
):
126 """Specifiy if a focus indicator (dotted line) should be used"""
127 self
.useFocusInd
= flag
129 def GetUseFocusIndicator(self
):
130 """Return focus indicator flag"""
131 return self
.useFocusInd
134 def InitColours(self
):
135 faceClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)
136 textClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT
)
137 self
.faceDnClr
= faceClr
138 self
.SetBackgroundColour(faceClr
)
139 self
.SetForegroundColour(textClr
)
141 shadowClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW
)
142 highlightClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT
)
143 self
.shadowPen
= wxPen(shadowClr
, 1, wxSOLID
)
144 self
.highlightPen
= wxPen(highlightClr
, 1, wxSOLID
)
145 self
.focusIndPen
= wxPen(textClr
, 1, wxUSER_DASH
)
148 def SetBackgroundColour(self
, colour
):
149 wxWindow
.SetBackgroundColour(self
, colour
)
151 # Calculate a new set of highlight and shadow colours based on
152 # the new background colour. Works okay if the colour is dark...
153 r
, g
, b
= colour
.Get()
154 fr
, fg
, fb
= min(255,r
+32), min(255,g
+32), min(255,b
+32)
155 self
.faceDnClr
= wxColour(fr
, fg
, fb
)
156 sr
, sg
, sb
= max(0,r
-32), max(0,g
-32), max(0,b
-32)
157 self
.shadowPen
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
)
158 hr
, hg
, hb
= min(255,r
+64), min(255,g
+64), min(255,b
+64)
159 self
.highlightPen
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
)
162 def _GetLabelSize(self
):
163 """ used internally """
164 w
, h
= self
.GetTextExtent(self
.GetLabel())
169 evt
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId())
170 evt
.SetIsDown(not self
.up
)
171 evt
.SetButtonObj(self
)
172 self
.GetEventHandler().ProcessEvent(evt
)
175 def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
):
176 # draw the upper left sides
178 dc
.SetPen(self
.highlightPen
)
180 dc
.SetPen(self
.shadowPen
)
181 for i
in range(self
.bezelWidth
):
182 dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
)
183 dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
)
185 # draw the lower right sides
187 dc
.SetPen(self
.shadowPen
)
189 dc
.SetPen(self
.highlightPen
)
190 for i
in range(self
.bezelWidth
):
191 dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
)
192 dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
)
195 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
196 dc
.SetFont(self
.GetFont())
198 dc
.SetTextForeground(self
.GetForegroundColour())
200 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
201 label
= self
.GetLabel()
202 tw
, th
= dc
.GetTextExtent(label
)
205 dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
)
208 def DrawFocusIndicator(self
, dc
, w
, h
):
210 dc
.SetLogicalFunction(wxINVERT
)
211 self
.focusIndPen
.SetColour(self
.GetForegroundColour())
212 self
.focusIndPen
.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
213 dc
.SetPen(self
.focusIndPen
)
214 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
215 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
218 def OnPaint(self
, event
):
219 (width
, height
) = self
.GetClientSizeTuple()
225 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
227 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
229 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
230 self
.DrawLabel(dc
, width
, height
)
231 if self
.hasFocus
and self
.useFocusInd
:
232 self
.DrawFocusIndicator(dc
, width
, height
)
234 def OnEraseBackground(self
, event
):
238 def OnLeftDown(self
, event
):
239 if not self
.IsEnabled():
247 def OnLeftUp(self
, event
):
248 if not self
.IsEnabled():
250 if not self
.up
: # if the button was down when the mouse was released...
257 def OnMotion(self
, event
):
258 if not self
.IsEnabled():
260 if event
.LeftIsDown():
261 x
,y
= event
.GetPositionTuple()
262 w
,h
= self
.GetClientSizeTuple()
263 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
267 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
273 def OnGainFocus(self
, event
):
275 dc
= wxClientDC(self
)
276 w
, h
= self
.GetClientSizeTuple()
278 self
.DrawFocusIndicator(dc
, w
, h
)
281 def OnLoseFocus(self
, event
):
282 self
.hasFocus
= false
283 dc
= wxClientDC(self
)
284 w
, h
= self
.GetClientSizeTuple()
286 self
.DrawFocusIndicator(dc
, w
, h
)
289 def OnKeyDown(self
, event
):
290 if self
.hasFocus
and event
.KeyCode() == ord(" "):
295 def OnKeyUp(self
, event
):
296 if self
.hasFocus
and event
.KeyCode() == ord(" "):
303 #----------------------------------------------------------------------
305 class wxGenBitmapButton(wxGenButton
):
306 def __init__(self
, parent
, ID
, bitmap
,
307 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
308 style
= 0, validator
= wxDefaultValidator
,
310 self
.bmpLabel
= bitmap
311 self
.bmpDisabled
= None
313 self
.bmpSelected
= None
314 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
317 def GetBitmapLabel(self
):
319 def GetBitmapDisabled(self
):
320 return self
.bmpDisabled
321 def GetBitmapFocus(self
):
323 def GetBitmapSelected(self
):
324 return self
.bmpSelected
327 def SetBitmapDisabled(self
, bitmap
):
328 """Set bitmap to display when the button is disabled"""
329 self
.bmpDisabled
= bitmap
331 def SetBitmapFocus(self
, bitmap
):
332 """Set bitmap to display when the button has the focus"""
333 self
.bmpFocus
= bitmap
334 self
.SetUseFocusIndicator(false
)
336 def SetBitmapSelected(self
, bitmap
):
337 """Set bitmap to display when the button is selected (pressed down)"""
338 self
.bmpSelected
= bitmap
340 def SetBitmapLabel(self
, bitmap
):
341 """Set the bitmap to display normally. This is the only one that is required."""
342 self
.bmpLabel
= bitmap
345 def _GetLabelSize(self
):
346 """ used internally """
347 if not self
.bmpLabel
:
349 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
352 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
354 if self
.bmpDisabled
and not self
.IsEnabled():
355 bmp
= self
.bmpDisabled
356 if self
.bmpFocus
and self
.hasFocus
:
358 if self
.bmpSelected
and not self
.up
:
359 bmp
= self
.bmpSelected
360 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
363 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, true
)
367 #----------------------------------------------------------------------
371 def SetToggle(self
, flag
):
377 def OnLeftDown(self
, event
):
378 if not self
.IsEnabled():
380 self
.up
= not self
.up
385 def OnLeftUp(self
, event
):
386 if not self
.IsEnabled():
392 def OnKeyDown(self
, event
):
395 def OnKeyUp(self
, event
):
396 if self
.hasFocus
and event
.KeyCode() == ord(" "):
397 self
.up
= not self
.up
405 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
408 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
411 #----------------------------------------------------------------------