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)
146 self
.focusIndPen
= wxPen(textClr
, 1, wxDOT
)
149 def SetBackgroundColour(self
, colour
):
150 wxWindow
.SetBackgroundColour(self
, colour
)
152 # Calculate a new set of highlight and shadow colours based on
153 # the new background colour. Works okay if the colour is dark...
154 r
, g
, b
= colour
.Get()
155 fr
, fg
, fb
= min(255,r
+32), min(255,g
+32), min(255,b
+32)
156 self
.faceDnClr
= wxColour(fr
, fg
, fb
)
157 sr
, sg
, sb
= max(0,r
-32), max(0,g
-32), max(0,b
-32)
158 self
.shadowPen
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
)
159 hr
, hg
, hb
= min(255,r
+64), min(255,g
+64), min(255,b
+64)
160 self
.highlightPen
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
)
163 def _GetLabelSize(self
):
164 """ used internally """
165 w
, h
= self
.GetTextExtent(self
.GetLabel())
170 evt
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId())
171 evt
.SetIsDown(not self
.up
)
172 evt
.SetButtonObj(self
)
173 self
.GetEventHandler().ProcessEvent(evt
)
176 def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
):
177 # draw the upper left sides
179 dc
.SetPen(self
.highlightPen
)
181 dc
.SetPen(self
.shadowPen
)
182 for i
in range(self
.bezelWidth
):
183 dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
)
184 dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
)
186 # draw the lower right sides
188 dc
.SetPen(self
.shadowPen
)
190 dc
.SetPen(self
.highlightPen
)
191 for i
in range(self
.bezelWidth
):
192 dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
)
193 dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
)
196 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
197 dc
.SetFont(self
.GetFont())
199 dc
.SetTextForeground(self
.GetForegroundColour())
201 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
202 label
= self
.GetLabel()
203 tw
, th
= dc
.GetTextExtent(label
)
206 dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
)
209 def DrawFocusIndicator(self
, dc
, w
, h
):
211 dc
.SetLogicalFunction(wxINVERT
)
212 self
.focusIndPen
.SetColour(self
.GetForegroundColour())
213 ##self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
214 dc
.SetPen(self
.focusIndPen
)
215 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
216 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
219 def OnPaint(self
, event
):
220 (width
, height
) = self
.GetClientSizeTuple()
226 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
228 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
230 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
231 self
.DrawLabel(dc
, width
, height
)
232 if self
.hasFocus
and self
.useFocusInd
:
233 self
.DrawFocusIndicator(dc
, width
, height
)
236 def OnEraseBackground(self
, event
):
240 def OnLeftDown(self
, event
):
241 if not self
.IsEnabled():
249 def OnLeftUp(self
, event
):
250 if not self
.IsEnabled():
252 if not self
.up
: # if the button was down when the mouse was released...
259 def OnMotion(self
, event
):
260 if not self
.IsEnabled():
262 if event
.LeftIsDown():
263 x
,y
= event
.GetPositionTuple()
264 w
,h
= self
.GetClientSizeTuple()
265 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
269 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
275 def OnGainFocus(self
, event
):
277 dc
= wxClientDC(self
)
278 w
, h
= self
.GetClientSizeTuple()
280 self
.DrawFocusIndicator(dc
, w
, h
)
283 def OnLoseFocus(self
, event
):
284 self
.hasFocus
= false
285 dc
= wxClientDC(self
)
286 w
, h
= self
.GetClientSizeTuple()
288 self
.DrawFocusIndicator(dc
, w
, h
)
291 def OnKeyDown(self
, event
):
292 if self
.hasFocus
and event
.KeyCode() == ord(" "):
298 def OnKeyUp(self
, event
):
299 if self
.hasFocus
and event
.KeyCode() == ord(" "):
306 #----------------------------------------------------------------------
308 class wxGenBitmapButton(wxGenButton
):
309 def __init__(self
, parent
, ID
, bitmap
,
310 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
311 style
= 0, validator
= wxDefaultValidator
,
313 self
.bmpLabel
= bitmap
314 self
.bmpDisabled
= None
316 self
.bmpSelected
= None
317 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
320 def GetBitmapLabel(self
):
322 def GetBitmapDisabled(self
):
323 return self
.bmpDisabled
324 def GetBitmapFocus(self
):
326 def GetBitmapSelected(self
):
327 return self
.bmpSelected
330 def SetBitmapDisabled(self
, bitmap
):
331 """Set bitmap to display when the button is disabled"""
332 self
.bmpDisabled
= bitmap
334 def SetBitmapFocus(self
, bitmap
):
335 """Set bitmap to display when the button has the focus"""
336 self
.bmpFocus
= bitmap
337 self
.SetUseFocusIndicator(false
)
339 def SetBitmapSelected(self
, bitmap
):
340 """Set bitmap to display when the button is selected (pressed down)"""
341 self
.bmpSelected
= bitmap
343 def SetBitmapLabel(self
, bitmap
):
344 """Set the bitmap to display normally. This is the only one that is required."""
345 self
.bmpLabel
= bitmap
348 def _GetLabelSize(self
):
349 """ used internally """
350 if not self
.bmpLabel
:
352 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
355 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
357 if self
.bmpDisabled
and not self
.IsEnabled():
358 bmp
= self
.bmpDisabled
359 if self
.bmpFocus
and self
.hasFocus
:
361 if self
.bmpSelected
and not self
.up
:
362 bmp
= self
.bmpSelected
363 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
366 hasMask
= bmp
.GetMask() != None
367 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, hasMask
)
371 #----------------------------------------------------------------------
375 def SetToggle(self
, flag
):
381 def OnLeftDown(self
, event
):
382 if not self
.IsEnabled():
384 self
.saveUp
= self
.up
385 self
.up
= not self
.up
390 def OnLeftUp(self
, event
):
391 if not self
.IsEnabled():
393 if self
.up
!= self
.saveUp
:
398 def OnKeyDown(self
, event
):
401 def OnKeyUp(self
, event
):
402 if self
.hasFocus
and event
.KeyCode() == ord(" "):
403 self
.up
= not self
.up
411 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
414 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
417 #----------------------------------------------------------------------