]> git.saurik.com Git - wxWidgets.git/blame - wxPython/wxPython/lib/buttons.py
reformat
[wxWidgets.git] / wxPython / 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):
f6bcfd97
BP
56 labelDelta = 1
57
6999b0d8
RD
58 def __init__(self, parent, ID, label,
59 pos = wxDefaultPosition, size = wxDefaultSize,
60 style = 0, validator = wxDefaultValidator,
61 name = "genbutton"):
9b3d3bc4
RD
62 if style == 0:
63 style = wxNO_BORDER
64 wxControl.__init__(self, parent, ID, pos, size, style, validator, name)
6999b0d8
RD
65
66 self.up = true
67 self.bezelWidth = 2
68 self.hasFocus = false
69 self.useFocusInd = true
1b62f00d 70 self.evtToSend = []
6999b0d8
RD
71
72 self.SetLabel(label)
73 self.SetPosition(pos)
6999b0d8
RD
74 font = parent.GetFont()
75 if not font.Ok():
76 font = wxSystemSettings_GetSystemFont(wxSYS_DEFAULT_GUI_FONT)
77 self.SetFont(font)
78385733 78 self.SetBestSize(size)
6999b0d8
RD
79 self.InitColours()
80
f6bcfd97
BP
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)
1b62f00d 90 EVT_IDLE(self, self.OnIdle)
6999b0d8
RD
91
92
78385733
RD
93 def SetBestSize(self, size=None):
94 """
95 Given the current font and bezel width settings, calculate
96 and set a good size.
97 """
98 if size is None:
99 size = wxSize(-1,-1)
100 if type(size) == type(()):
101 size = wxSize(size[0], size[1])
102
103 # make a new size so we don't mess with the one passed in
104 size = wxSize(size.width, size.height)
105
106 w, h, useMin = self._GetLabelSize()
107 defSize = wxButton_GetDefaultSize()
108 if size.width == -1:
109 size.width = 12 + w
110 if useMin and size.width < defSize.width:
111 size.width = defSize.width
112 if size.height == -1:
113 size.height = 11 + h
114 if useMin and size.height < defSize.height:
115 size.height = defSize.height
116
117 size.width = size.width + self.bezelWidth - 1
118 size.height = size.height + self.bezelWidth - 1
119
120 self.SetSize(size)
6999b0d8
RD
121
122
123 def SetBezelWidth(self, width):
124 """Set the width of the 3D effect"""
125 self.bezelWidth = width
126
127 def GetBezelWidth(self):
128 """Return the width of the 3D effect"""
129 return self.bezelWidth
130
131 def SetUseFocusIndicator(self, flag):
132 """Specifiy if a focus indicator (dotted line) should be used"""
133 self.useFocusInd = flag
134
135 def GetUseFocusIndicator(self):
136 """Return focus indicator flag"""
137 return self.useFocusInd
138
139
140 def InitColours(self):
141 faceClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNFACE)
142 textClr = wxSystemSettings_GetSystemColour(wxSYS_COLOUR_BTNTEXT)
78385733 143 self.faceDnClr = faceClr
6999b0d8
RD
144 self.SetBackgroundColour(faceClr)
145 self.SetForegroundColour(textClr)
146
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)
8e425133
RD
151 ##self.focusIndPen = wxPen(textClr, 1, wxUSER_DASH)
152 self.focusIndPen = wxPen(textClr, 1, wxDOT)
6999b0d8
RD
153
154
78385733
RD
155 def SetBackgroundColour(self, colour):
156 wxWindow.SetBackgroundColour(self, colour)
157
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)
167
168
169 def _GetLabelSize(self):
170 """ used internally """
171 w, h = self.GetTextExtent(self.GetLabel())
172 return w, h, true
173
174
6999b0d8
RD
175 def Notify(self):
176 evt = wxGenButtonEvent(wxEVT_COMMAND_BUTTON_CLICKED, self.GetId())
177 evt.SetIsDown(not self.up)
78385733 178 evt.SetButtonObj(self)
1b62f00d
RD
179 self.evtToSend.append(evt)
180
181
182 def OnIdle(self, evt):
183 while self.evtToSend:
184 evt = self.evtToSend[0]
185 del self.evtToSend[0]
186 self.GetEventHandler().ProcessEvent(evt)
6999b0d8
RD
187
188
189 def DrawBezel(self, dc, x1, y1, x2, y2):
190 # draw the upper left sides
191 if self.up:
192 dc.SetPen(self.highlightPen)
193 else:
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)
198
199 # draw the lower right sides
200 if self.up:
201 dc.SetPen(self.shadowPen)
202 else:
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)
207
208
209 def DrawLabel(self, dc, width, height, dw=0, dy=0):
210 dc.SetFont(self.GetFont())
211 if self.IsEnabled():
212 dc.SetTextForeground(self.GetForegroundColour())
213 else:
214 dc.SetTextForeground(wxSystemSettings_GetSystemColour(wxSYS_COLOUR_GRAYTEXT))
215 label = self.GetLabel()
216 tw, th = dc.GetTextExtent(label)
217 if not self.up:
f6bcfd97 218 dw = dy = self.labelDelta
6999b0d8
RD
219 dc.DrawText(label, (width-tw)/2+dw, (height-th)/2+dy)
220
221
222 def DrawFocusIndicator(self, dc, w, h):
223 bw = self.bezelWidth
224 dc.SetLogicalFunction(wxINVERT)
225 self.focusIndPen.SetColour(self.GetForegroundColour())
8e425133 226 ##self.focusIndPen.SetDashes([1,2,1,2]) # This isn't quite working the way I expected...
6999b0d8
RD
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)
230
231
232 def OnPaint(self, event):
233 (width, height) = self.GetClientSizeTuple()
234 x1 = y1 = 0
235 x2 = width-1
236 y2 = height-1
237 dc = wxPaintDC(self)
78385733
RD
238 if self.up:
239 dc.SetBackground(wxBrush(self.GetBackgroundColour(), wxSOLID))
240 else:
241 dc.SetBackground(wxBrush(self.faceDnClr, wxSOLID))
6999b0d8
RD
242 dc.Clear()
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)
247
eec92d76 248
6999b0d8
RD
249 def OnEraseBackground(self, event):
250 pass
251
252
253 def OnLeftDown(self, event):
254 if not self.IsEnabled():
255 return
256 self.up = false
257 self.CaptureMouse()
258 self.SetFocus()
259 self.Refresh()
185d7c3e 260 event.Skip()
6999b0d8
RD
261
262
263 def OnLeftUp(self, event):
264 if not self.IsEnabled():
265 return
266 if not self.up: # if the button was down when the mouse was released...
267 self.Notify()
268 self.up = true
269 self.ReleaseMouse()
270 self.Refresh()
185d7c3e 271 event.Skip()
6999b0d8
RD
272
273 def OnMotion(self, event):
274 if not self.IsEnabled():
275 return
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:
280 self.up = false
281 self.Refresh()
282 return
283 if not self.up and (x<0 or y<0 or x>=w or y>=h):
284 self.up = true
285 self.Refresh()
286 return
185d7c3e 287 event.Skip()
6999b0d8
RD
288
289
290 def OnGainFocus(self, event):
291 self.hasFocus = true
292 dc = wxClientDC(self)
293 w, h = self.GetClientSizeTuple()
294 if self.useFocusInd:
295 self.DrawFocusIndicator(dc, w, h)
296
297
298 def OnLoseFocus(self, event):
299 self.hasFocus = false
300 dc = wxClientDC(self)
301 w, h = self.GetClientSizeTuple()
302 if self.useFocusInd:
303 self.DrawFocusIndicator(dc, w, h)
304
305
306 def OnKeyDown(self, event):
307 if self.hasFocus and event.KeyCode() == ord(" "):
308 self.up = false
309 self.Refresh()
310 event.Skip()
311
eec92d76 312
6999b0d8
RD
313 def OnKeyUp(self, event):
314 if self.hasFocus and event.KeyCode() == ord(" "):
315 self.up = true
316 self.Notify()
317 self.Refresh()
318 event.Skip()
319
320
321#----------------------------------------------------------------------
322
323class wxGenBitmapButton(wxGenButton):
324 def __init__(self, parent, ID, bitmap,
325 pos = wxDefaultPosition, size = wxDefaultSize,
326 style = 0, validator = wxDefaultValidator,
327 name = "genbutton"):
6999b0d8
RD
328 self.bmpLabel = bitmap
329 self.bmpDisabled = None
330 self.bmpFocus = None
331 self.bmpSelected = None
78385733
RD
332 wxGenButton.__init__(self, parent, ID, "", pos, size, style, validator, name)
333
6999b0d8
RD
334
335 def GetBitmapLabel(self):
336 return self.bmpLabel
337 def GetBitmapDisabled(self):
338 return self.bmpDisabled
339 def GetBitmapFocus(self):
340 return self.bmpFocus
341 def GetBitmapSelected(self):
342 return self.bmpSelected
343
78385733 344
6999b0d8 345 def SetBitmapDisabled(self, bitmap):
78385733 346 """Set bitmap to display when the button is disabled"""
6999b0d8 347 self.bmpDisabled = bitmap
78385733 348
6999b0d8 349 def SetBitmapFocus(self, bitmap):
78385733 350 """Set bitmap to display when the button has the focus"""
6999b0d8
RD
351 self.bmpFocus = bitmap
352 self.SetUseFocusIndicator(false)
78385733 353
6999b0d8 354 def SetBitmapSelected(self, bitmap):
78385733 355 """Set bitmap to display when the button is selected (pressed down)"""
6999b0d8 356 self.bmpSelected = bitmap
78385733 357
6999b0d8 358 def SetBitmapLabel(self, bitmap):
78385733 359 """Set the bitmap to display normally. This is the only one that is required."""
6999b0d8
RD
360 self.bmpLabel = bitmap
361
362
78385733
RD
363 def _GetLabelSize(self):
364 """ used internally """
365 if not self.bmpLabel:
366 return -1, -1, false
367 return self.bmpLabel.GetWidth()+2, self.bmpLabel.GetHeight()+2, false
368
369
6999b0d8
RD
370 def DrawLabel(self, dc, width, height, dw=0, dy=0):
371 bmp = self.bmpLabel
372 if self.bmpDisabled and not self.IsEnabled():
373 bmp = self.bmpDisabled
374 if self.bmpFocus and self.hasFocus:
375 bmp = self.bmpFocus
376 if self.bmpSelected and not self.up:
377 bmp = self.bmpSelected
378 bw,bh = bmp.GetWidth(), bmp.GetHeight()
379 if not self.up:
f6bcfd97 380 dw = dy = self.labelDelta
eec92d76
RD
381 hasMask = bmp.GetMask() != None
382 dc.DrawBitmap(bmp, (width-bw)/2+dw, (height-bh)/2+dy, hasMask)
6999b0d8
RD
383
384
385
386#----------------------------------------------------------------------
387
388
389class __ToggleMixin:
fbff5d1b
RD
390 def SetToggle(self, flag):
391 self.up = not flag
392
393 def GetToggle(self):
394 return not self.up
395
6999b0d8
RD
396 def OnLeftDown(self, event):
397 if not self.IsEnabled():
398 return
c4c829ae 399 self.saveUp = self.up
6999b0d8
RD
400 self.up = not self.up
401 self.CaptureMouse()
402 self.SetFocus()
403 self.Refresh()
404
405 def OnLeftUp(self, event):
406 if not self.IsEnabled():
407 return
c4c829ae
RD
408 if self.up != self.saveUp:
409 self.Notify()
6999b0d8
RD
410 self.ReleaseMouse()
411 self.Refresh()
412
413 def OnKeyDown(self, event):
414 event.Skip()
415
416 def OnKeyUp(self, event):
417 if self.hasFocus and event.KeyCode() == ord(" "):
418 self.up = not self.up
419 self.Notify()
420 self.Refresh()
421 event.Skip()
422
423
fbff5d1b
RD
424
425
6999b0d8
RD
426class wxGenToggleButton(__ToggleMixin, wxGenButton):
427 pass
428
429class wxGenBitmapToggleButton(__ToggleMixin, wxGenBitmapButton):
430 pass
431
432#----------------------------------------------------------------------
433
434