]>
Commit | Line | Data |
---|---|---|
66dae888 RD |
1 | # --------------------------------------------------------------------------- # |
2 | # FANCYBUTTONPANEL Widget wxPython IMPLEMENTATION | |
3 | # | |
4 | # Original C++ Code From Eran. You Can Find It At: | |
5 | # | |
6 | # http://wxforum.shadonet.com/viewtopic.php?t=6619 | |
7 | # | |
8 | # License: wxWidgets license | |
9 | # | |
10 | # | |
11 | # Python Code By: | |
12 | # | |
13 | # Andrea Gavana, @ 02 Oct 2006 | |
14 | # Latest Revision: 02 Oct 2006, 17.00 GMT | |
15 | # | |
16 | # | |
17 | # For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please | |
18 | # Write To Me At: | |
19 | # | |
20 | # andrea.gavana@gmail.com | |
21 | # gavana@kpo.kz | |
22 | # | |
23 | # Or, Obviously, To The wxPython Mailing List!!! | |
24 | # | |
25 | # | |
26 | # End Of Comments | |
27 | # --------------------------------------------------------------------------- # | |
28 | ||
29 | """ | |
30 | With `ButtonPanel` class you have a panel with gradient coloring | |
31 | on it and with the possibility to place some buttons on it. Using a | |
32 | standard panel with normal wx.Buttons leads to an ugly result: the | |
33 | buttons are placed correctly on the panel - but with grey area around | |
34 | them. Gradient coloring is kept behind the images - this was achieved | |
35 | due to the PNG format and the transparency of the bitmaps. | |
36 | ||
37 | The image are functioning like a buttons and can be caught in your | |
38 | code using the usual self.Bind(wx.EVT_BUTTON, self.OnButton) method. | |
39 | ||
40 | The control is generic, and support theming (well, I tested it under | |
41 | Windows with the three defauls themes: grey, blue, silver and the | |
42 | classic look). | |
43 | ||
44 | ||
45 | Usage | |
46 | ----- | |
47 | ||
48 | The following example shows a simple implementation that uses ButtonPanel | |
49 | inside a very simple frame:: | |
50 | ||
51 | class MyFrame(wx.Frame): | |
52 | ||
53 | def __init__(self, parent, id=-1, title="ButtonPanel", pos=wx.DefaultPosition, | |
54 | size=(800, 600), style=wx.DEFAULT_FRAME_STYLE): | |
55 | ||
56 | wx.Frame.__init__(self, parent, id, title, pos, size, style) | |
57 | ||
58 | mainPanel = wx.Panel(self, -1) | |
59 | self.logtext = wx.TextCtrl(mainPanel, -1, "", style=wx.TE_MULTILINE) | |
60 | ||
61 | vSizer = wx.BoxSizer(wx.VERTICAL) | |
62 | mainPanel.SetSizer(vSizer) | |
63 | ||
64 | alignment = BP_ALIGN_RIGHT | |
65 | ||
66 | titleBar = ButtonPanel(mainPanel, -1, "A Simple Test & Demo") | |
67 | ||
68 | btn1 = ButtonInfo(wx.NewId(), wx.Bitmap("png4.png", wx.BITMAP_TYPE_PNG)) | |
69 | titleBar.AddButton(btn1) | |
70 | self.Bind(wx.EVT_BUTTON, self.OnButton, btn1) | |
71 | ||
72 | btn2 = ButtonInfo(wx.NewId(), wx.Bitmap("png3.png", wx.BITMAP_TYPE_PNG)) | |
73 | titleBar.AddButton(btn2) | |
74 | self.Bind(wx.EVT_BUTTON, self.OnButton, btn2) | |
75 | ||
76 | btn3 = ButtonInfo(wx.NewId(), wx.Bitmap("png2.png", wx.BITMAP_TYPE_PNG)) | |
77 | titleBar.AddButton(btn3) | |
78 | self.Bind(wx.EVT_BUTTON, self.OnButton, btn3) | |
79 | ||
80 | btn4 = ButtonInfo(wx.NewId(), wx.Bitmap("png1.png", wx.BITMAP_TYPE_PNG)) | |
81 | titleBar.AddButton(btn4) | |
82 | self.Bind(wx.EVT_BUTTON, self.OnButton, btn4) | |
83 | ||
84 | titleBar.SetColor(BP_TEXT_COLOR, wx.WHITE) | |
85 | titleBar.SetColor(BP_CAPTION_BORDER_COLOR, wx.WHITE) | |
86 | vSizer.Add(titleBar, 0, wx.EXPAND) | |
87 | vSizer.Add((20, 20)) | |
88 | vSizer.Add(self.logtext, 1, wx.EXPAND|wx.ALL, 5) | |
89 | ||
90 | vSizer.Layout() | |
91 | ||
92 | # our normal wxApp-derived class, as usual | |
93 | ||
94 | app = wx.PySimpleApp() | |
95 | ||
96 | frame = MyFrame(None) | |
97 | app.SetTopWindow(frame) | |
98 | frame.Show() | |
99 | ||
100 | app.MainLoop() | |
101 | ||
102 | ||
103 | License And Version: | |
104 | ||
105 | ButtonPanel Is Freeware And Distributed Under The wxPython License. | |
106 | ||
107 | Latest Revision: Andrea Gavana @ 02 Oct 2006, 17.00 GMT | |
108 | Version 0.1. | |
109 | ||
110 | """ | |
111 | ||
112 | ||
113 | import wx | |
114 | ||
115 | # Some constants | |
116 | BP_CAPTION_COLOR = 0, | |
117 | BP_CAPTION_GRADIENT_COLOR = 1 | |
118 | BP_CAPTION_BORDER_COLOR = 2 | |
119 | BP_TEXT_COLOR = 3 | |
120 | ||
121 | # Buttons states | |
122 | BP_BTN_NONE = 100 | |
123 | BP_BTN_PRESSED = 101 | |
124 | BP_BTN_HOVER = 102 | |
125 | ||
126 | # Flags for HitTest() method | |
127 | BP_HT_BUTTON = 200 | |
128 | BP_HT_NONE = 201 | |
129 | ||
130 | # Alignment of buttons in the panel | |
131 | BP_ALIGN_RIGHT = 1 | |
132 | BP_ALIGN_LEFT = 2 | |
133 | ||
134 | # ButtonPanel default style | |
135 | BP_DEFAULT_STYLE = 2 | |
136 | ||
137 | ||
138 | def BrightenColor(color, factor): | |
139 | """ Bright the input colour by a factor.""" | |
140 | ||
141 | val = color.Red()*factor | |
142 | if val > 255: | |
143 | red = 255 | |
144 | else: | |
145 | red = val | |
146 | ||
147 | val = color.Green()*factor | |
148 | if val > 255: | |
149 | green = 255 | |
150 | else: | |
151 | green = val | |
152 | ||
153 | val = color.Blue()*factor | |
154 | if val > 255: | |
155 | blue = 255 | |
156 | else: | |
157 | blue = val | |
158 | ||
159 | return wx.Color(red, green, blue) | |
160 | ||
161 | ||
162 | # -- ButtonInfo class implementation ---------------------------------------- | |
163 | # This class holds information about every button that is added to | |
164 | # ButtonPanel. It is an auxiliary class that you should use | |
165 | # every time you add a button. | |
166 | ||
167 | class ButtonInfo: | |
168 | ||
169 | def __init__(self, id=wx.ID_ANY, bmp=wx.NullBitmap, status=-1): | |
170 | """ | |
171 | Default class constructor. | |
172 | ||
173 | Parameters: | |
174 | - id: the button id; | |
175 | - bmp: the associated bitmap; | |
176 | - status: button status (pressed, hovered, None). | |
177 | """ | |
178 | if id == wx.ID_ANY: | |
179 | id = wx.NewId() | |
180 | self._id = id | |
181 | self._bmp = bmp | |
182 | self._status = status | |
183 | self._rect = wx.Rect() | |
184 | ||
185 | ||
186 | def GetBitmap(self): | |
187 | """ Returns the associated bitmap. """ | |
188 | ||
189 | return self._bmp | |
190 | ||
191 | ||
192 | def GetRect(self): | |
193 | """ Returns the button rect. """ | |
194 | ||
195 | return self._rect | |
196 | ||
197 | ||
198 | def GetStatus(self): | |
199 | """ Returns the button status. """ | |
200 | ||
201 | return self._status | |
202 | ||
203 | ||
204 | def GetId(self): | |
205 | """ Returns the button id. """ | |
206 | ||
207 | return self._id | |
208 | ||
209 | ||
210 | def SetRect(self, rect): | |
211 | """ Sets the button rect. """ | |
212 | ||
213 | self._rect = rect | |
214 | ||
215 | ||
216 | def SetBitmap(self, bmp): | |
217 | """ Sets the associated bitmap. """ | |
218 | ||
219 | self._bmp = bmp | |
220 | ||
221 | ||
222 | def SetStatus(self, status): | |
223 | """ Sets the button status. """ | |
224 | ||
225 | self._status = status | |
226 | ||
227 | ||
228 | def SetId(self, id): | |
229 | """ Sets the button id. """ | |
230 | ||
231 | self._id = id | |
232 | ||
233 | Bitmap = property(GetBitmap, SetBitmap) | |
234 | Id = property(GetId, SetId) | |
235 | Rect = property(GetRect, SetRect) | |
236 | Status = property(GetStatus, SetStatus) | |
237 | ||
238 | ||
239 | ||
240 | ||
241 | # -- ButtonPanel class implementation ---------------------------------- | |
242 | # This is the main class. | |
243 | ||
9d45af36 | 244 | class ButtonPanel(wx.PyPanel): |
66dae888 RD |
245 | |
246 | def __init__(self, parent, id=wx.ID_ANY, text="", style=BP_DEFAULT_STYLE, | |
247 | alignment=BP_ALIGN_RIGHT, name="buttonPanel"): | |
248 | """ | |
249 | Default class constructor. | |
250 | ||
251 | - parent: parent window | |
252 | - id: window ID | |
253 | - text: text to draw | |
254 | - style: window style | |
255 | - alignment: alignment of buttons (left or right) | |
256 | - name: window class name | |
257 | """ | |
258 | ||
9d45af36 | 259 | wx.PyPanel.__init__(self, parent, id, wx.DefaultPosition, wx.DefaultSize, |
66dae888 RD |
260 | wx.NO_BORDER, name=name) |
261 | self._vButtons = [] | |
262 | ||
263 | self._text = text | |
264 | self._nStyle = style | |
265 | self._alignment = alignment | |
266 | self._nPadding = 6 | |
267 | self._nBmpSize = 16 | |
268 | self._colorFrom = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION) | |
269 | self._colorTo = wx.WHITE | |
270 | self._colorBorder = wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DFACE) | |
271 | self._colorText = wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT) | |
272 | self._firsttime = True | |
273 | self._borderPenWidth = 3 | |
274 | ||
275 | self.Bind(wx.EVT_PAINT, self.OnPaint) | |
276 | self.Bind(wx.EVT_SIZE, self.OnSize) | |
277 | self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) | |
278 | self.Bind(wx.EVT_MOTION, self.OnMouseMove) | |
279 | self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) | |
280 | self.Bind(wx.EVT_LEFT_UP, self.OnLeftUp) | |
281 | self.Bind(wx.EVT_LEAVE_WINDOW, self.OnMouseLeave) | |
282 | self.Bind(wx.EVT_ENTER_WINDOW, self.OnMouseEnterWindow) | |
283 | ||
284 | ||
285 | def AddButton(self, btnInfo): | |
286 | """ | |
287 | Adds a button to ButtonPanel. Remember to pass a ButtonInfo instance to | |
288 | this method. See the demo for details. | |
289 | """ | |
290 | ||
291 | self._vButtons.append(btnInfo) | |
292 | self.Refresh() | |
293 | ||
294 | ||
295 | def RemoveAllButtons(self): | |
296 | """ Remove all the buttons from ButtonPanel. """ | |
297 | ||
298 | self._vButtons = [] | |
299 | self.Refresh() | |
300 | ||
301 | ||
302 | def GetAlignment(self): | |
303 | """ Returns the button alignment (left, right). """ | |
304 | ||
305 | return self._alignment | |
306 | ||
307 | ||
308 | def SetAlignment(self, alignment): | |
309 | """ Sets the button alignment (left, right). """ | |
310 | ||
311 | self._alignment = alignment | |
312 | ||
313 | ||
314 | def DoGetBestSize(self): | |
315 | w = h = 0 | |
316 | if self._text: | |
317 | dc = wx.ClientDC(self) | |
318 | boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) | |
319 | boldFont.SetWeight(wx.FONTWEIGHT_BOLD) | |
320 | dc.SetFont(boldFont) | |
321 | tw, th = dc.GetTextExtent(self._text) | |
322 | h = max(h, th) | |
323 | w += tw + self._nPadding | |
324 | ||
325 | if self._vButtons: | |
326 | bh = self._vButtons[0].GetBitmap().GetHeight() | |
327 | bw = self._vButtons[0].GetBitmap().GetWidth() | |
328 | ||
329 | bh += 2*self._nPadding + 2*self._borderPenWidth | |
330 | h = max(h, bh) | |
331 | ||
332 | bw = (len(self._vButtons)+1) * (bw + 2*self._nPadding) | |
333 | w += bw | |
334 | ||
335 | return (w, h) | |
336 | ||
337 | ||
338 | ||
339 | def OnPaint(self, event): | |
340 | """ Handles the wx.EVT_PAINT event for ButtonPanel. """ | |
341 | ||
342 | dc = wx.BufferedPaintDC(self) | |
343 | rect = self.GetClientRect() | |
344 | ||
345 | ##print rect, self.GetRect(), self.GetBestSize(), self.GetMinSize() | |
346 | ||
347 | # Draw gradient color in the background of the panel | |
348 | self.FillGradientColor(dc, rect) | |
349 | ||
350 | backBrush = wx.TRANSPARENT_BRUSH | |
351 | borderPen = wx.Pen(self._colorBorder) | |
352 | size = self.GetSize() | |
353 | borderPen.SetWidth(self._borderPenWidth) | |
354 | ||
355 | # Draw a rectangle around the panel | |
356 | dc.SetBrush(backBrush) | |
357 | dc.SetPen(borderPen) | |
358 | dc.DrawRectangleRect(rect) | |
359 | ||
360 | # Draw the text | |
361 | textWidth, textHeight = 0, 0 | |
362 | ||
363 | if self._text != "": | |
364 | ||
365 | dc.SetTextForeground(self._colorText) | |
366 | borderPen.SetWidth(2) | |
367 | boldFont = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) | |
368 | boldFont.SetWeight(wx.FONTWEIGHT_BOLD) | |
369 | dc.SetFont(boldFont) | |
370 | ||
371 | textWidth, textHeight = dc.GetTextExtent(self._text) | |
372 | ||
373 | if self._alignment == BP_ALIGN_RIGHT: | |
374 | textX = self._nPadding | |
375 | else: | |
376 | textX = rect.width - textWidth - self._nPadding | |
377 | ||
378 | textY = (rect.GetHeight() - textHeight)/2 | |
379 | dc.DrawText(self._text, textX, textY) | |
380 | ||
381 | if self._vButtons: | |
382 | ||
383 | height = self._vButtons[0].GetBitmap().GetHeight() | |
384 | self._nBmpSize = self._vButtons[0].GetBitmap().GetWidth() | |
385 | height += 2*self._nPadding + 2*self._borderPenWidth | |
386 | ||
387 | if self._firsttime: # this probably isn't needed anymore now that DoGetBestSize is implemented... | |
388 | self.GetContainingSizer().Layout() | |
389 | self._firsttime = False | |
390 | ||
391 | # Draw all buttons | |
392 | # [ Padding | Text | .. Buttons .. | Padding ] | |
393 | ||
394 | totalWidth = rect.width - self._nPadding*2 - textWidth | |
395 | ||
396 | # The button is drawn inside a circle with padding of self._nPadding around it | |
397 | # so the width of each image = imageWidth + 2 * self._nPadding | |
398 | nImageWidth = self._nBmpSize + 2*self._nPadding | |
399 | ||
400 | if self._alignment == BP_ALIGN_RIGHT: | |
401 | ||
402 | leftEndX = self._nPadding + textWidth | |
403 | posx = rect.width - nImageWidth - self._nPadding | |
404 | ||
405 | for ii in xrange(len(self._vButtons)): | |
406 | ||
407 | # Make sure we can keep drawing | |
408 | if posx < leftEndX: | |
409 | break | |
410 | ||
411 | # Draw a rectangle around the buttons | |
412 | if self._vButtons[ii].GetStatus() == BP_BTN_HOVER: | |
413 | ||
414 | dc.SetBrush(wx.Brush(wx.Color(225, 225, 255))) | |
415 | dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))) | |
416 | dc.DrawRectangle(posx, self._borderPenWidth, nImageWidth, nImageWidth) | |
417 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth, True) | |
418 | ||
419 | elif self._vButtons[ii].GetStatus() == BP_BTN_PRESSED: | |
420 | ||
421 | dc.SetBrush(wx.Brush(wx.Color(225, 225, 255))) | |
422 | dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))) | |
423 | dc.DrawRectangle(posx, self._borderPenWidth, nImageWidth, nImageWidth) | |
424 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth + 1, True) | |
425 | ||
426 | else: | |
427 | ||
428 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth, True) | |
429 | ||
430 | self._vButtons[ii].SetRect(wx.Rect(posx, self._borderPenWidth, nImageWidth, nImageWidth)) | |
431 | posx -= nImageWidth | |
432 | ||
433 | else: | |
434 | ||
435 | rightStartX = textX - self._nPadding - nImageWidth | |
436 | posx = self._nPadding | |
437 | ||
438 | for ii in xrange(len(self._vButtons)): | |
439 | ||
440 | # Make sure we can keep drawing | |
441 | if posx > rightStartX: | |
442 | break | |
443 | ||
444 | # Draw a rectangle around the buttons | |
445 | if self._vButtons[ii].GetStatus() == BP_BTN_HOVER: | |
446 | ||
447 | dc.SetBrush(wx.Brush(wx.Color(225, 225, 255))) | |
448 | dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))) | |
449 | dc.DrawRectangle(posx, self._borderPenWidth, nImageWidth, nImageWidth) | |
450 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth, True) | |
451 | ||
452 | elif self._vButtons[ii].GetStatus() == BP_BTN_PRESSED: | |
453 | ||
454 | dc.SetBrush(wx.Brush(wx.Color(225, 225, 255))) | |
455 | dc.SetPen(wx.Pen(wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION))) | |
456 | dc.DrawRectangle(posx, self._borderPenWidth, nImageWidth, nImageWidth) | |
457 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth + 1, True) | |
458 | ||
459 | else: | |
460 | ||
461 | dc.DrawBitmap(self._vButtons[ii].GetBitmap(), posx + self._nPadding, self._nPadding + self._borderPenWidth, True) | |
462 | ||
463 | self._vButtons[ii].SetRect(wx.Rect(posx, self._borderPenWidth, nImageWidth, nImageWidth)) | |
464 | posx += nImageWidth | |
465 | ||
466 | # Update all other buttons that they are not drawn (by setting the rect to 0) | |
467 | for cur in xrange(ii+1, len(self._vButtons)): | |
468 | self._vButtons[cur].SetRect(wx.Rect(0, 0, 0, 0)) | |
469 | ||
470 | ||
471 | def OnEraseBackground(self, event): | |
472 | """ Handles the wx.EVT_ERASE_BACKGROUND event for ButtonPanel (does nothing). """ | |
473 | ||
474 | pass | |
475 | ||
476 | ||
477 | def OnSize(self, event): | |
478 | """ Handles the wx.EVT_SIZE event for ButtonPanel. """ | |
479 | ||
480 | self.Refresh() | |
481 | event.Skip() | |
482 | ||
483 | ||
484 | def SetColor(self, switch, color): | |
485 | """ | |
486 | Sets the color depending on switch: | |
487 | - BP_CAPTION_COLOR: caption color; | |
488 | - BP_CAPTION_GRADIENT_COLOR: gradient color; | |
489 | - BP_CAPTION_BORDER_COLOR; border color; | |
490 | - BP_TEXT_COLOR: text color. | |
491 | """ | |
492 | ||
493 | if switch == BP_CAPTION_COLOR: | |
494 | self._colorFrom = color | |
495 | elif switch == BP_CAPTION_GRADIENT_COLOR: | |
496 | self._colorTo = color | |
497 | elif switch == BP_CAPTION_BORDER_COLOR: | |
498 | self._colorBorder = color | |
499 | elif switch == BP_TEXT_COLOR: | |
500 | self._colorText = color | |
501 | ||
502 | ||
503 | def FillGradientColor(self, dc, rect): | |
504 | """ Gradient fill from colour 1 to colour 2 with top to bottom. """ | |
505 | ||
506 | if rect.height < 1 or rect.width < 1: | |
507 | return | |
508 | ||
509 | size = rect.height | |
510 | ||
511 | # calculate gradient coefficients | |
512 | style = self.GetParent().GetWindowStyleFlag() | |
513 | col2 = self._colorFrom | |
514 | col1 = self._colorTo | |
515 | ||
516 | rf, gf, bf = 0, 0, 0 | |
517 | rstep = float((col2.Red() - col1.Red()))/float(size) | |
518 | gstep = float((col2.Green() - col1.Green()))/float(size) | |
519 | bstep = float((col2.Blue() - col1.Blue()))/float(size) | |
520 | ||
521 | for y in xrange(rect.y, rect.y + size): | |
522 | ||
523 | currCol = wx.Colour(col1.Red() + rf, col1.Green() + gf, col1.Blue() + bf) | |
524 | dc.SetBrush(wx.Brush(currCol, wx.SOLID)) | |
525 | dc.SetPen(wx.Pen(currCol)) | |
526 | dc.DrawLine(rect.x, y, rect.x + rect.width, y) | |
527 | rf += rstep | |
528 | gf += gstep | |
529 | bf += bstep | |
530 | ||
531 | ||
532 | def OnMouseMove(self, event): | |
533 | """ Handles the wx.EVT_MOTION event for ButtonPanel. """ | |
534 | ||
535 | # Check to see if we are hovering a button | |
536 | for ii in xrange(len(self._vButtons)): | |
537 | if self._vButtons[ii].GetRect().Inside(event.GetPosition()): | |
538 | self._vButtons[ii].SetStatus(BP_BTN_HOVER) | |
539 | else: | |
540 | self._vButtons[ii].SetStatus(BP_BTN_NONE) | |
541 | ||
542 | self.Refresh() | |
543 | event.Skip() | |
544 | ||
545 | ||
546 | def OnLeftDown(self, event): | |
547 | """ Handles the wx.EVT_LEFT_DOWN event for ButtonPanel. """ | |
548 | ||
549 | tabId, hit = self.HitTest(event.GetPosition()) | |
550 | ||
551 | if hit == BP_HT_BUTTON: | |
552 | ||
553 | self._vButtons[tabId].SetStatus(BP_BTN_PRESSED) | |
554 | self.Refresh() | |
555 | ||
556 | ||
557 | def OnLeftUp(self, event): | |
558 | """ Handles the wx.EVT_LEFT_UP event for ButtonPanel. """ | |
559 | ||
560 | tabId, hit = self.HitTest(event.GetPosition()) | |
561 | ||
562 | if hit == BP_HT_BUTTON: | |
563 | if self._vButtons[tabId].GetStatus() == BP_BTN_PRESSED: | |
564 | # Fire a button click event | |
565 | btnEvent = wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, self._vButtons[tabId].GetId()) | |
566 | self.GetEventHandler().ProcessEvent(btnEvent) | |
567 | ||
568 | # Update the button status to be hovered | |
569 | self._vButtons[tabId].SetStatus(BP_BTN_HOVER) | |
570 | self.Refresh() | |
571 | ||
572 | ||
573 | def OnMouseLeave(self, event): | |
574 | """ Handles the wx.EVT_LEAVE_WINDOW event for ButtonPanel. """ | |
575 | ||
576 | # Reset all buttons statuses | |
577 | for ii in xrange(len(self._vButtons)): | |
578 | self._vButtons[ii].SetStatus(BP_BTN_NONE) | |
579 | ||
580 | self.Refresh() | |
581 | event.Skip() | |
582 | ||
583 | ||
584 | def OnMouseEnterWindow(self, event): | |
585 | """ Handles the wx.EVT_ENTER_WINDOW event for ButtonPanel. """ | |
586 | ||
587 | event.Skip() | |
588 | ||
589 | ||
590 | def HitTest(self, pt): | |
591 | """ | |
592 | HitTest method for ButtonPanel. Returns the button (if any) and | |
593 | a flag (if any). | |
594 | """ | |
595 | ||
596 | btnIdx = -1 | |
597 | ||
598 | for ii in xrange(len(self._vButtons)): | |
599 | if self._vButtons[ii].GetRect().Inside(pt): | |
600 | return ii, BP_HT_BUTTON | |
601 | ||
602 | return -1, BP_HT_NONE | |
603 | ||
604 | ||
605 |