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(wxWindow
):
56 def __init__(self
, parent
, ID
, label
,
57 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
58 style
= 0, validator
= wxDefaultValidator
,
60 wxWindow
.__init
__(self
, parent
, ID
, pos
, size
, style
, name
)
61 self
.SetValidator(validator
)
66 self
.useFocusInd
= true
70 font
= parent
.GetFont()
72 font
= wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT
)
74 self
.SetBestSize(size
)
77 EVT_LEFT_DOWN(self
, self
.OnLeftDown
)
78 EVT_LEFT_UP(self
, self
.OnLeftUp
)
79 EVT_MOTION(self
, self
.OnMotion
)
80 EVT_SET_FOCUS(self
, self
.OnGainFocus
)
81 EVT_KILL_FOCUS(self
, self
.OnLoseFocus
)
82 EVT_KEY_DOWN(self
, self
.OnKeyDown
)
83 EVT_KEY_UP(self
, self
.OnKeyUp
)
86 def SetBestSize(self
, size
=None):
88 Given the current font and bezel width settings, calculate
93 if type(size
) == type(()):
94 size
= wxSize(size
[0], size
[1])
96 # make a new size so we don't mess with the one passed in
97 size
= wxSize(size
.width
, size
.height
)
99 w
, h
, useMin
= self
._GetLabelSize
()
100 defSize
= wxButton_GetDefaultSize()
103 if useMin
and size
.width
< defSize
.width
:
104 size
.width
= defSize
.width
105 if size
.height
== -1:
107 if useMin
and size
.height
< defSize
.height
:
108 size
.height
= defSize
.height
110 size
.width
= size
.width
+ self
.bezelWidth
- 1
111 size
.height
= size
.height
+ self
.bezelWidth
- 1
116 def SetBezelWidth(self
, width
):
117 """Set the width of the 3D effect"""
118 self
.bezelWidth
= width
120 def GetBezelWidth(self
):
121 """Return the width of the 3D effect"""
122 return self
.bezelWidth
124 def SetUseFocusIndicator(self
, flag
):
125 """Specifiy if a focus indicator (dotted line) should be used"""
126 self
.useFocusInd
= flag
128 def GetUseFocusIndicator(self
):
129 """Return focus indicator flag"""
130 return self
.useFocusInd
133 def InitColours(self
):
134 faceClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE
)
135 textClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT
)
136 self
.faceDnClr
= faceClr
137 self
.SetBackgroundColour(faceClr
)
138 self
.SetForegroundColour(textClr
)
140 shadowClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNSHADOW
)
141 highlightClr
= wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNHIGHLIGHT
)
142 self
.shadowPen
= wxPen(shadowClr
, 1, wxSOLID
)
143 self
.highlightPen
= wxPen(highlightClr
, 1, wxSOLID
)
144 self
.focusIndPen
= wxPen(textClr
, 1, wxUSER_DASH
)
147 def SetBackgroundColour(self
, colour
):
148 wxWindow
.SetBackgroundColour(self
, colour
)
150 # Calculate a new set of highlight and shadow colours based on
151 # the new background colour. Works okay if the colour is dark...
152 r
, g
, b
= colour
.Get()
153 fr
, fg
, fb
= min(255,r
+32), min(255,g
+32), min(255,b
+32)
154 self
.faceDnClr
= wxColour(fr
, fg
, fb
)
155 sr
, sg
, sb
= max(0,r
-32), max(0,g
-32), max(0,b
-32)
156 self
.shadowPen
= wxPen(wxColour(sr
,sg
,sb
), 1, wxSOLID
)
157 hr
, hg
, hb
= min(255,r
+64), min(255,g
+64), min(255,b
+64)
158 self
.highlightPen
= wxPen(wxColour(hr
,hg
,hb
), 1, wxSOLID
)
161 def _GetLabelSize(self
):
162 """ used internally """
163 w
, h
= self
.GetTextExtent(self
.GetLabel())
168 evt
= wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED
, self
.GetId())
169 evt
.SetIsDown(not self
.up
)
170 evt
.SetButtonObj(self
)
171 self
.GetEventHandler().ProcessEvent(evt
)
174 def DrawBezel(self
, dc
, x1
, y1
, x2
, y2
):
175 # draw the upper left sides
177 dc
.SetPen(self
.highlightPen
)
179 dc
.SetPen(self
.shadowPen
)
180 for i
in range(self
.bezelWidth
):
181 dc
.DrawLine(x1
+i
, y1
, x1
+i
, y2
-i
)
182 dc
.DrawLine(x1
, y1
+i
, x2
-i
, y1
+i
)
184 # draw the lower right sides
186 dc
.SetPen(self
.shadowPen
)
188 dc
.SetPen(self
.highlightPen
)
189 for i
in range(self
.bezelWidth
):
190 dc
.DrawLine(x1
+i
, y2
-i
, x2
+1, y2
-i
)
191 dc
.DrawLine(x2
-i
, y1
+i
, x2
-i
, y2
)
194 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
195 dc
.SetFont(self
.GetFont())
197 dc
.SetTextForeground(self
.GetForegroundColour())
199 dc
.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT
))
200 label
= self
.GetLabel()
201 tw
, th
= dc
.GetTextExtent(label
)
204 dc
.DrawText(label
, (width
-tw
)/2+dw
, (height
-th
)/2+dy
)
207 def DrawFocusIndicator(self
, dc
, w
, h
):
209 dc
.SetLogicalFunction(wxINVERT
)
210 self
.focusIndPen
.SetColour(self
.GetForegroundColour())
211 self
.focusIndPen
.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
212 dc
.SetPen(self
.focusIndPen
)
213 dc
.SetBrush(wxTRANSPARENT_BRUSH
)
214 dc
.DrawRectangle(bw
+2,bw
+2, w
-bw
*2-4, h
-bw
*2-4)
217 def OnPaint(self
, event
):
218 (width
, height
) = self
.GetClientSizeTuple()
224 dc
.SetBackground(wxBrush(self
.GetBackgroundColour(), wxSOLID
))
226 dc
.SetBackground(wxBrush(self
.faceDnClr
, wxSOLID
))
228 self
.DrawBezel(dc
, x1
, y1
, x2
, y2
)
229 self
.DrawLabel(dc
, width
, height
)
230 if self
.hasFocus
and self
.useFocusInd
:
231 self
.DrawFocusIndicator(dc
, width
, height
)
233 def OnEraseBackground(self
, event
):
237 def OnLeftDown(self
, event
):
238 if not self
.IsEnabled():
246 def OnLeftUp(self
, event
):
247 if not self
.IsEnabled():
249 if not self
.up
: # if the button was down when the mouse was released...
256 def OnMotion(self
, event
):
257 if not self
.IsEnabled():
259 if event
.LeftIsDown():
260 x
,y
= event
.GetPositionTuple()
261 w
,h
= self
.GetClientSizeTuple()
262 if self
.up
and x
<w
and x
>=0 and y
<h
and y
>=0:
266 if not self
.up
and (x
<0 or y
<0 or x
>=w
or y
>=h
):
272 def OnGainFocus(self
, event
):
274 dc
= wxClientDC(self
)
275 w
, h
= self
.GetClientSizeTuple()
277 self
.DrawFocusIndicator(dc
, w
, h
)
280 def OnLoseFocus(self
, event
):
281 self
.hasFocus
= false
282 dc
= wxClientDC(self
)
283 w
, h
= self
.GetClientSizeTuple()
285 self
.DrawFocusIndicator(dc
, w
, h
)
288 def OnKeyDown(self
, event
):
289 if self
.hasFocus
and event
.KeyCode() == ord(" "):
294 def OnKeyUp(self
, event
):
295 if self
.hasFocus
and event
.KeyCode() == ord(" "):
302 #----------------------------------------------------------------------
304 class wxGenBitmapButton(wxGenButton
):
305 def __init__(self
, parent
, ID
, bitmap
,
306 pos
= wxDefaultPosition
, size
= wxDefaultSize
,
307 style
= 0, validator
= wxDefaultValidator
,
309 self
.bmpLabel
= bitmap
310 self
.bmpDisabled
= None
312 self
.bmpSelected
= None
313 wxGenButton
.__init
__(self
, parent
, ID
, "", pos
, size
, style
, validator
, name
)
316 def GetBitmapLabel(self
):
318 def GetBitmapDisabled(self
):
319 return self
.bmpDisabled
320 def GetBitmapFocus(self
):
322 def GetBitmapSelected(self
):
323 return self
.bmpSelected
326 def SetBitmapDisabled(self
, bitmap
):
327 """Set bitmap to display when the button is disabled"""
328 self
.bmpDisabled
= bitmap
330 def SetBitmapFocus(self
, bitmap
):
331 """Set bitmap to display when the button has the focus"""
332 self
.bmpFocus
= bitmap
333 self
.SetUseFocusIndicator(false
)
335 def SetBitmapSelected(self
, bitmap
):
336 """Set bitmap to display when the button is selected (pressed down)"""
337 self
.bmpSelected
= bitmap
339 def SetBitmapLabel(self
, bitmap
):
340 """Set the bitmap to display normally. This is the only one that is required."""
341 self
.bmpLabel
= bitmap
344 def _GetLabelSize(self
):
345 """ used internally """
346 if not self
.bmpLabel
:
348 return self
.bmpLabel
.GetWidth()+2, self
.bmpLabel
.GetHeight()+2, false
351 def DrawLabel(self
, dc
, width
, height
, dw
=0, dy
=0):
353 if self
.bmpDisabled
and not self
.IsEnabled():
354 bmp
= self
.bmpDisabled
355 if self
.bmpFocus
and self
.hasFocus
:
357 if self
.bmpSelected
and not self
.up
:
358 bmp
= self
.bmpSelected
359 bw
,bh
= bmp
.GetWidth(), bmp
.GetHeight()
362 dc
.DrawBitmap(bmp
, (width
-bw
)/2+dw
, (height
-bh
)/2+dy
, true
)
366 #----------------------------------------------------------------------
370 def SetToggle(self
, flag
):
376 def OnLeftDown(self
, event
):
377 if not self
.IsEnabled():
379 self
.up
= not self
.up
384 def OnLeftUp(self
, event
):
385 if not self
.IsEnabled():
391 def OnKeyDown(self
, event
):
394 def OnKeyUp(self
, event
):
395 if self
.hasFocus
and event
.KeyCode() == ord(" "):
396 self
.up
= not self
.up
404 class wxGenToggleButton(__ToggleMixin
, wxGenButton
):
407 class wxGenBitmapToggleButton(__ToggleMixin
, wxGenBitmapButton
):
410 #----------------------------------------------------------------------