]> git.saurik.com Git - wxWidgets.git/blame - utils/wxPython/lib/buttons.py
new tests
[wxWidgets.git] / utils / wxPython / lib / buttons.py
CommitLineData
6999b0d8
RD
1#----------------------------------------------------------------------
2# Name: wxPython.lib.buttons
3# Purpose: Various kinds of generic buttons, (not native controls but
4# self-drawn.)
5#
6# Author: Robin Dunn
7#
8# Created: 9-Dec-1999
9# RCS-ID: $Id$
10# Copyright: (c) 1999 by Total Control Software
11# Licence: wxWindows license
12#----------------------------------------------------------------------
13
14"""
15This module implements various forms of generic buttons, meaning that
16they are not built on native controls but are self-drawn.
17
18The wxGenButton is the base. It acts like a normal button but you
19are able to better control how it looks, bevel width, colours, etc.
20
21wxGenBitmapButton is a button with one or more bitmaps that show
22the various states the button can be in.
23
24wxGenToggleButton stays depressed when clicked, until clicked again.
25
26wxGenBitmapToggleButton the same but with bitmaps.
27
28"""
29
30from wxPython.wx import *
31
32#----------------------------------------------------------------------
33
34class wxGenButtonEvent(wxPyCommandEvent):
35 def __init__(self, eventType, ID):
36 wxPyCommandEvent.__init__(self, eventType, ID)
37 self.isDown = false
78385733 38 self.theButton = None
6999b0d8
RD
39
40 def SetIsDown(self, isDown):
41 self.isDown = isDown
42
43 def GetIsDown(self):
44 return self.isDown
45
78385733
RD
46 def SetButtonObj(self, btn):
47 self.theButton = btn
48
49 def GetButtonObj(self):
50 return self.theButton
51
6999b0d8
RD
52
53#----------------------------------------------------------------------
54
9b3d3bc4 55class wxGenButton(wxControl):
6999b0d8
RD
56 def __init__(self, parent, ID, label,
57 pos = wxDefaultPosition, size = wxDefaultSize,
58 style = 0, validator = wxDefaultValidator,
59 name = "genbutton"):
9b3d3bc4
RD
60 if style == 0:
61 style = wxNO_BORDER
62 wxControl.__init__(self, parent, ID, pos, size, style, validator, name)
6999b0d8
RD
63
64 self.up = true
65 self.bezelWidth = 2
66 self.hasFocus = false
67 self.useFocusInd = true
68
69 self.SetLabel(label)
70 self.SetPosition(pos)
6999b0d8
RD
71 font = parent.GetFont()
72 if not font.Ok():
73 font = wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT)
74 self.SetFont(font)
78385733 75 self.SetBestSize(size)
6999b0d8
RD
76 self.InitColours()
77
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)
85
86
78385733
RD
87 def SetBestSize(self, size=None):
88 """
89 Given the current font and bezel width settings, calculate
90 and set a good size.
91 """
92 if size is None:
93 size = wxSize(-1,-1)
94 if type(size) == type(()):
95 size = wxSize(size[0], size[1])
96
97 # make a new size so we don't mess with the one passed in
98 size = wxSize(size.width, size.height)
99
100 w, h, useMin = self._GetLabelSize()
101 defSize = wxButton_GetDefaultSize()
102 if size.width == -1:
103 size.width = 12 + w
104 if useMin and size.width < defSize.width:
105 size.width = defSize.width
106 if size.height == -1:
107 size.height = 11 + h
108 if useMin and size.height < defSize.height:
109 size.height = defSize.height
110
111 size.width = size.width + self.bezelWidth - 1
112 size.height = size.height + self.bezelWidth - 1
113
114 self.SetSize(size)
6999b0d8
RD
115
116
117 def SetBezelWidth(self, width):
118 """Set the width of the 3D effect"""
119 self.bezelWidth = width
120
121 def GetBezelWidth(self):
122 """Return the width of the 3D effect"""
123 return self.bezelWidth
124
125 def SetUseFocusIndicator(self, flag):
126 """Specifiy if a focus indicator (dotted line) should be used"""
127 self.useFocusInd = flag
128
129 def GetUseFocusIndicator(self):
130 """Return focus indicator flag"""
131 return self.useFocusInd
132
133
134 def InitColours(self):
135 faceClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE)
136 textClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT)
78385733 137 self.faceDnClr = faceClr
6999b0d8
RD
138 self.SetBackgroundColour(faceClr)
139 self.SetForegroundColour(textClr)
140
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)
8e425133
RD
145 ##self.focusIndPen = wxPen(textClr, 1, wxUSER_DASH)
146 self.focusIndPen = wxPen(textClr, 1, wxDOT)
6999b0d8
RD
147
148
78385733
RD
149 def SetBackgroundColour(self, colour):
150 wxWindow.SetBackgroundColour(self, colour)
151
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)
161
162
163 def _GetLabelSize(self):
164 """ used internally """
165 w, h = self.GetTextExtent(self.GetLabel())
166 return w, h, true
167
168
6999b0d8
RD
169 def Notify(self):
170 evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
171 evt.SetIsDown(not self.up)
78385733 172 evt.SetButtonObj(self)
6999b0d8
RD
173 self.GetEventHandler().ProcessEvent(evt)
174
175
176 def DrawBezel(self, dc, x1, y1, x2, y2):
177 # draw the upper left sides
178 if self.up:
179 dc.SetPen(self.highlightPen)
180 else:
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)
185
186 # draw the lower right sides
187 if self.up:
188 dc.SetPen(self.shadowPen)
189 else:
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)
194
195
196 def DrawLabel(self, dc, width, height, dw=0, dy=0):
197 dc.SetFont(self.GetFont())
198 if self.IsEnabled():
199 dc.SetTextForeground(self.GetForegroundColour())
200 else:
201 dc.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT))
202 label = self.GetLabel()
203 tw, th = dc.GetTextExtent(label)
204 if not self.up:
205 dw = dy = 1
206 dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dy)
207
208
209 def DrawFocusIndicator(self, dc, w, h):
210 bw = self.bezelWidth
211 dc.SetLogicalFunction(wxINVERT)
212 self.focusIndPen.SetColour(self.GetForegroundColour())
8e425133 213 ##self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
6999b0d8
RD
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)
217
218
219 def OnPaint(self, event):
220 (width, height) = self.GetClientSizeTuple()
221 x1 = y1 = 0
222 x2 = width-1
223 y2 = height-1
224 dc = wxPaintDC(self)
78385733
RD
225 if self.up:
226 dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID))
227 else:
228 dc.SetBackground(wxBrush(self.faceDnClr, wxSOLID))
6999b0d8
RD
229 dc.Clear()
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)
234
235 def OnEraseBackground(self, event):
236 pass
237
238
239 def OnLeftDown(self, event):
240 if not self.IsEnabled():
241 return
242 self.up = false
243 self.CaptureMouse()
244 self.SetFocus()
245 self.Refresh()
246
247
248 def OnLeftUp(self, event):
249 if not self.IsEnabled():
250 return
251 if not self.up: # if the button was down when the mouse was released...
252 self.Notify()
253 self.up = true
254 self.ReleaseMouse()
255 self.Refresh()
256
257
258 def OnMotion(self, event):
259 if not self.IsEnabled():
260 return
261 if event.LeftIsDown():
262 x,y = event.GetPositionTuple()
263 w,h = self.GetClientSizeTuple()
264 if self.up and x<w and x>=0 and y<h and y>=0:
265 self.up = false
266 self.Refresh()
267 return
268 if not self.up and (x<0 or y<0 or x>=w or y>=h):
269 self.up = true
270 self.Refresh()
271 return
272
273
274 def OnGainFocus(self, event):
275 self.hasFocus = true
276 dc = wxClientDC(self)
277 w, h = self.GetClientSizeTuple()
278 if self.useFocusInd:
279 self.DrawFocusIndicator(dc, w, h)
280
281
282 def OnLoseFocus(self, event):
283 self.hasFocus = false
284 dc = wxClientDC(self)
285 w, h = self.GetClientSizeTuple()
286 if self.useFocusInd:
287 self.DrawFocusIndicator(dc, w, h)
288
289
290 def OnKeyDown(self, event):
291 if self.hasFocus and event.KeyCode() == ord(" "):
292 self.up = false
293 self.Refresh()
294 event.Skip()
295
296 def OnKeyUp(self, event):
297 if self.hasFocus and event.KeyCode() == ord(" "):
298 self.up = true
299 self.Notify()
300 self.Refresh()
301 event.Skip()
302
303
304#----------------------------------------------------------------------
305
306class wxGenBitmapButton(wxGenButton):
307 def __init__(self, parent, ID, bitmap,
308 pos = wxDefaultPosition, size = wxDefaultSize,
309 style = 0, validator = wxDefaultValidator,
310 name = "genbutton"):
6999b0d8
RD
311 self.bmpLabel = bitmap
312 self.bmpDisabled = None
313 self.bmpFocus = None
314 self.bmpSelected = None
78385733
RD
315 wxGenButton.__init__(self, parent, ID, "", pos, size, style, validator, name)
316
6999b0d8
RD
317
318 def GetBitmapLabel(self):
319 return self.bmpLabel
320 def GetBitmapDisabled(self):
321 return self.bmpDisabled
322 def GetBitmapFocus(self):
323 return self.bmpFocus
324 def GetBitmapSelected(self):
325 return self.bmpSelected
326
78385733 327
6999b0d8 328 def SetBitmapDisabled(self, bitmap):
78385733 329 """Set bitmap to display when the button is disabled"""
6999b0d8 330 self.bmpDisabled = bitmap
78385733 331
6999b0d8 332 def SetBitmapFocus(self, bitmap):
78385733 333 """Set bitmap to display when the button has the focus"""
6999b0d8
RD
334 self.bmpFocus = bitmap
335 self.SetUseFocusIndicator(false)
78385733 336
6999b0d8 337 def SetBitmapSelected(self, bitmap):
78385733 338 """Set bitmap to display when the button is selected (pressed down)"""
6999b0d8 339 self.bmpSelected = bitmap
78385733 340
6999b0d8 341 def SetBitmapLabel(self, bitmap):
78385733 342 """Set the bitmap to display normally. This is the only one that is required."""
6999b0d8
RD
343 self.bmpLabel = bitmap
344
345
78385733
RD
346 def _GetLabelSize(self):
347 """ used internally """
348 if not self.bmpLabel:
349 return -1, -1, false
350 return self.bmpLabel.GetWidth()+2, self.bmpLabel.GetHeight()+2, false
351
352
6999b0d8
RD
353 def DrawLabel(self, dc, width, height, dw=0, dy=0):
354 bmp = self.bmpLabel
355 if self.bmpDisabled and not self.IsEnabled():
356 bmp = self.bmpDisabled
357 if self.bmpFocus and self.hasFocus:
358 bmp = self.bmpFocus
359 if self.bmpSelected and not self.up:
360 bmp = self.bmpSelected
361 bw,bh = bmp.GetWidth(), bmp.GetHeight()
362 if not self.up:
363 dw = dy = 1
364 dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, true)
365
366
367
368#----------------------------------------------------------------------
369
370
371class __ToggleMixin:
fbff5d1b
RD
372 def SetToggle(self, flag):
373 self.up = not flag
374
375 def GetToggle(self):
376 return not self.up
377
6999b0d8
RD
378 def OnLeftDown(self, event):
379 if not self.IsEnabled():
380 return
381 self.up = not self.up
382 self.CaptureMouse()
383 self.SetFocus()
384 self.Refresh()
385
386 def OnLeftUp(self, event):
387 if not self.IsEnabled():
388 return
389 self.Notify()
390 self.ReleaseMouse()
391 self.Refresh()
392
393 def OnKeyDown(self, event):
394 event.Skip()
395
396 def OnKeyUp(self, event):
397 if self.hasFocus and event.KeyCode() == ord(" "):
398 self.up = not self.up
399 self.Notify()
400 self.Refresh()
401 event.Skip()
402
403
fbff5d1b
RD
404
405
6999b0d8
RD
406class wxGenToggleButton(__ToggleMixin, wxGenButton):
407 pass
408
409class wxGenBitmapToggleButton(__ToggleMixin, wxGenBitmapButton):
410 pass
411
412#----------------------------------------------------------------------
413
414