2 Dock art provider code - a dock provider provides all drawing functionality to
3 the AUI dock manager. This allows the dock manager to have a plugable look-and-feel.
5 By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt}
6 which provides bitmap art and a colour scheme that is adapted to the major platforms'
7 look. You can either derive from that class to alter its behaviour or write a
8 completely new dock art class. Call L{AuiManager.SetArtProvider} to make use this
12 __author__ = "Andrea Gavana <andrea.gavana@gmail.com>"
13 __date__ = "31 March 2009"
19 from aui_utilities import BitmapFromBits, StepColour, ChopText, GetBaseColour
20 from aui_utilities import DrawGradientRectangle, DrawMACCloseButton
21 from aui_utilities import DarkenBitmap, LightContrastColour
22 from aui_constants import *
28 # Try to import winxptheme for ModernDockArt
29 if wx.Platform == "__WXMSW__":
37 # -- AuiDefaultDockArt class implementation --
39 class AuiDefaultDockArt(object):
41 Dock art provider code - a dock provider provides all drawing functionality
42 to the AUI dock manager. This allows the dock manager to have a plugable
45 By default, a L{AuiManager} uses an instance of this class called L{AuiDefaultDockArt}
46 which provides bitmap art and a colour scheme that is adapted to the major
47 platforms' look. You can either derive from that class to alter its behaviour or
48 write a completely new dock art class.
50 Call L{AuiManager.SetArtProvider} to make use this new dock art.
55 These are the possible pane dock art settings for L{AuiManager}:
57 ================================================ ======================================
58 Metric Ordinal Constant Description
59 ================================================ ======================================
60 ``AUI_DOCKART_SASH_SIZE`` Customizes the sash size
61 ``AUI_DOCKART_CAPTION_SIZE`` Customizes the caption size
62 ``AUI_DOCKART_GRIPPER_SIZE`` Customizes the gripper size
63 ``AUI_DOCKART_PANE_BORDER_SIZE`` Customizes the pane border size
64 ``AUI_DOCKART_PANE_BUTTON_SIZE`` Customizes the pane button size
65 ``AUI_DOCKART_BACKGROUND_COLOUR`` Customizes the background colour
66 ``AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR`` Customizes the background gradient colour
67 ``AUI_DOCKART_SASH_COLOUR`` Customizes the sash colour
68 ``AUI_DOCKART_ACTIVE_CAPTION_COLOUR`` Customizes the active caption colour
69 ``AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the active caption gradient colour
70 ``AUI_DOCKART_INACTIVE_CAPTION_COLOUR`` Customizes the inactive caption colour
71 ``AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR`` Customizes the inactive gradient caption colour
72 ``AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR`` Customizes the active caption text colour
73 ``AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR`` Customizes the inactive caption text colour
74 ``AUI_DOCKART_BORDER_COLOUR`` Customizes the border colour
75 ``AUI_DOCKART_GRIPPER_COLOUR`` Customizes the gripper colour
76 ``AUI_DOCKART_CAPTION_FONT`` Customizes the caption font
77 ``AUI_DOCKART_GRADIENT_TYPE`` Customizes the gradient type (no gradient, vertical or horizontal)
78 ``AUI_DOCKART_DRAW_SASH_GRIP`` Draw a sash grip on the sash
79 ================================================ ======================================
84 These are the possible gradient dock art settings for L{AuiManager}:
86 ============================================ ======================================
87 Gradient Constant Description
88 ============================================ ======================================
89 ``AUI_GRADIENT_NONE`` No gradient on the captions
90 ``AUI_GRADIENT_VERTICAL`` Vertical gradient on the captions
91 ``AUI_GRADIENT_HORIZONTAL`` Horizontal gradient on the captions
92 ============================================ ======================================
97 These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button states:
99 ============================================ ======================================
100 Button State Constant Description
101 ============================================ ======================================
102 ``AUI_BUTTON_STATE_NORMAL`` Normal button state
103 ``AUI_BUTTON_STATE_HOVER`` Hovered button state
104 ``AUI_BUTTON_STATE_PRESSED`` Pressed button state
105 ``AUI_BUTTON_STATE_DISABLED`` Disabled button state
106 ``AUI_BUTTON_STATE_HIDDEN`` Hidden button state
107 ``AUI_BUTTON_STATE_CHECKED`` Checked button state
108 ============================================ ======================================
111 **Button Identifiers**
113 These are the possible pane button / L{AuiNotebook} button / L{AuiToolBar} button identifiers:
115 ============================================ ======================================
116 Button Identifier Description
117 ============================================ ======================================
118 ``AUI_BUTTON_CLOSE`` Shows a close button on the pane
119 ``AUI_BUTTON_MAXIMIZE_RESTORE`` Shows a maximize/restore button on the pane
120 ``AUI_BUTTON_MINIMIZE`` Shows a minimize button on the pane
121 ``AUI_BUTTON_PIN`` Shows a pin button on the pane
122 ``AUI_BUTTON_OPTIONS`` Shows an option button on the pane (not implemented)
123 ``AUI_BUTTON_WINDOWLIST`` Shows a window list button on the pane (for L{AuiNotebook})
124 ``AUI_BUTTON_LEFT`` Shows a left button on the pane (for L{AuiNotebook})
125 ``AUI_BUTTON_RIGHT`` Shows a right button on the pane (for L{AuiNotebook})
126 ``AUI_BUTTON_UP`` Shows an up button on the pane (not implemented)
127 ``AUI_BUTTON_DOWN`` Shows a down button on the pane (not implemented)
128 ``AUI_BUTTON_CUSTOM1`` Shows a custom button on the pane (not implemented)
129 ``AUI_BUTTON_CUSTOM2`` Shows a custom button on the pane (not implemented)
130 ``AUI_BUTTON_CUSTOM3`` Shows a custom button on the pane (not implemented)
131 ============================================ ======================================
136 """ Default class constructor. """
140 isMac = wx.Platform == "__WXMAC__"
143 self._caption_font = wx.SMALL_FONT
145 self._caption_font = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False)
147 self.SetDefaultPaneBitmaps(isMac)
148 self._restore_bitmap = wx.BitmapFromXPMData(restore_xpm)
150 # default metric values
154 # This really should be implemented in wx.SystemSettings
155 # There is no way to do this that I am aware outside of using
156 # the cocoa python bindings. 8 pixels looks correct on my system
157 # so hard coding it for now.
159 # How do I translate this?!? Not sure of the below implementation...
161 # GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
162 # self._sash_size = height;
164 self._sash_size = 8 # Carbon.Appearance.kThemeMetricPaneSplitterHeight
166 elif wx.Platform == "__WXGTK__":
167 self._sash_size = wx.RendererNative.Get().GetSplitterParams(wx.GetTopLevelWindows()[0]).widthSash
172 self._caption_size = 19
173 self._border_size = 1
174 self._button_size = 14
175 self._gripper_size = 9
176 self._gradient_type = AUI_GRADIENT_VERTICAL
177 self._draw_sash = False
181 """ Initializes the dock art. """
183 base_colour = GetBaseColour()
184 darker1_colour = StepColour(base_colour, 85)
185 darker2_colour = StepColour(base_colour, 75)
186 darker3_colour = StepColour(base_colour, 60)
187 darker4_colour = StepColour(base_colour, 40)
189 self._background_colour = base_colour
190 self._background_gradient_colour = StepColour(base_colour, 180)
192 isMac = wx.Platform == "__WXMAC__"
195 self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT)
197 self._active_caption_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_ACTIVECAPTION)
199 self._active_caption_gradient_colour = LightContrastColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHT))
200 self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_HIGHLIGHTTEXT)
201 self._inactive_caption_colour = darker1_colour
202 self._inactive_caption_gradient_colour = StepColour(base_colour, 97)
203 self._inactive_caption_text_colour = wx.BLACK
205 self._sash_brush = wx.Brush(base_colour)
206 self._background_brush = wx.Brush(base_colour)
207 self._border_pen = wx.Pen(darker2_colour)
208 self._gripper_brush = wx.Brush(base_colour)
209 self._gripper_pen1 = wx.Pen(darker4_colour)
210 self._gripper_pen2 = wx.Pen(darker3_colour)
211 self._gripper_pen3 = wx.WHITE_PEN
214 def GetMetric(self, id):
216 Gets the value of a certain setting.
218 :param `id`: can be one of the size values in `Metric Ordinals`.
222 if id == AUI_DOCKART_SASH_SIZE:
223 return self._sash_size
224 elif id == AUI_DOCKART_CAPTION_SIZE:
225 return self._caption_size
226 elif id == AUI_DOCKART_GRIPPER_SIZE:
227 return self._gripper_size
228 elif id == AUI_DOCKART_PANE_BORDER_SIZE:
229 return self._border_size
230 elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
231 return self._button_size
232 elif id == AUI_DOCKART_GRADIENT_TYPE:
233 return self._gradient_type
234 elif id == AUI_DOCKART_DRAW_SASH_GRIP:
235 return self._draw_sash
237 raise Exception("Invalid Metric Ordinal.")
240 def SetMetric(self, id, new_val):
242 Sets the value of a certain setting using `new_val`
244 :param `id`: can be one of the size values in `Metric Ordinals`;
245 :param `new_val`: the new value of the setting.
248 if id == AUI_DOCKART_SASH_SIZE:
249 self._sash_size = new_val
250 elif id == AUI_DOCKART_CAPTION_SIZE:
251 self._caption_size = new_val
252 elif id == AUI_DOCKART_GRIPPER_SIZE:
253 self._gripper_size = new_val
254 elif id == AUI_DOCKART_PANE_BORDER_SIZE:
255 self._border_size = new_val
256 elif id == AUI_DOCKART_PANE_BUTTON_SIZE:
257 self._button_size = new_val
258 elif id == AUI_DOCKART_GRADIENT_TYPE:
259 self._gradient_type = new_val
260 elif id == AUI_DOCKART_DRAW_SASH_GRIP:
261 self._draw_sash = new_val
263 raise Exception("Invalid Metric Ordinal.")
266 def GetColor(self, id):
268 Gets the colour of a certain setting.
270 :param `id`: can be one of the colour values in `Metric Ordinals`.
273 if id == AUI_DOCKART_BACKGROUND_COLOUR:
274 return self._background_brush.GetColour()
275 elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
276 return self._background_gradient_colour
277 elif id == AUI_DOCKART_SASH_COLOUR:
278 return self._sash_brush.GetColour()
279 elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
280 return self._inactive_caption_colour
281 elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
282 return self._inactive_caption_gradient_colour
283 elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
284 return self._inactive_caption_text_colour
285 elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
286 return self._active_caption_colour
287 elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
288 return self._active_caption_gradient_colour
289 elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
290 return self._active_caption_text_colour
291 elif id == AUI_DOCKART_BORDER_COLOUR:
292 return self._border_pen.GetColour()
293 elif id == AUI_DOCKART_GRIPPER_COLOUR:
294 return self._gripper_brush.GetColour()
296 raise Exception("Invalid Colour Ordinal.")
299 def SetColor(self, id, colour):
301 Sets the colour of a certain setting.
303 :param `id`: can be one of the colour values in `Metric Ordinals`;
304 :param `colour`: the new value of the setting.
307 if isinstance(colour, basestring):
308 colour = wx.NamedColour(colour)
309 elif isinstance(colour, types.TupleType):
310 colour = wx.Colour(*colour)
311 elif isinstance(colour, types.IntType):
312 colour = wx.ColourRGB(colour)
314 if id == AUI_DOCKART_BACKGROUND_COLOUR:
315 self._background_brush.SetColour(colour)
316 elif id == AUI_DOCKART_BACKGROUND_GRADIENT_COLOUR:
317 self._background_gradient_colour = colour
318 elif id == AUI_DOCKART_SASH_COLOUR:
319 self._sash_brush.SetColour(colour)
320 elif id == AUI_DOCKART_INACTIVE_CAPTION_COLOUR:
321 self._inactive_caption_colour = colour
322 if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
323 # No custom bitmaps for the pane close button
324 # Change the MAC close bitmap colour
325 self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)
327 elif id == AUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR:
328 self._inactive_caption_gradient_colour = colour
329 elif id == AUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR:
330 self._inactive_caption_text_colour = colour
331 elif id == AUI_DOCKART_ACTIVE_CAPTION_COLOUR:
332 self._active_caption_colour = colour
333 if not self._custom_pane_bitmaps and wx.Platform == "__WXMAC__":
334 # No custom bitmaps for the pane close button
335 # Change the MAC close bitmap colour
336 self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, colour)
338 elif id == AUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR:
339 self._active_caption_gradient_colour = colour
340 elif id == AUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR:
341 self._active_caption_text_colour = colour
342 elif id == AUI_DOCKART_BORDER_COLOUR:
343 self._border_pen.SetColour(colour)
344 elif id == AUI_DOCKART_GRIPPER_COLOUR:
345 self._gripper_brush.SetColour(colour)
346 self._gripper_pen1.SetColour(StepColour(colour, 40))
347 self._gripper_pen2.SetColour(StepColour(colour, 60))
349 raise Exception("Invalid Colour Ordinal.")
355 def SetFont(self, id, font):
359 :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``;
360 :param `font`: an instance of `wx.Font`.
363 if id == AUI_DOCKART_CAPTION_FONT:
364 self._caption_font = font
367 def GetFont(self, id):
371 :param `id`: must be ``AUI_DOCKART_CAPTION_FONT``, otherwise `wx.NullFont` is returned.
374 if id == AUI_DOCKART_CAPTION_FONT:
375 return self._caption_font
380 def DrawSash(self, dc, window, orient, rect):
382 Draws a sash between two windows.
384 :param `dc`: a `wx.DC` device context;
385 :param `window`: an instance of `wx.Window`;
386 :param `orient`: the sash orientation;
387 :param `rect`: the sash rectangle.
390 # AG: How do we make this work?!?
391 # RendererNative does not use the sash_brush chosen by the user
392 # and the rect.GetSize() is ignored as the sash is always drawn
394 # wx.RendererNative.Get().DrawSplitterSash(window, dc, rect.GetSize(), pos, orient)
396 dc.SetPen(wx.TRANSPARENT_PEN)
397 dc.SetBrush(self._sash_brush)
398 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
400 draw_sash = self.GetMetric(AUI_DOCKART_DRAW_SASH_GRIP)
402 self.DrawSashGripper(dc, orient, rect)
405 def DrawBackground(self, dc, window, orient, rect):
409 :param `dc`: a `wx.DC` device context;
410 :param `window`: an instance of `wx.Window`;
411 :param `orient`: the gradient (if any) orientation;
412 :param `rect`: the background rectangle.
415 dc.SetPen(wx.TRANSPARENT_PEN)
416 if wx.Platform == "__WXMAC__":
417 # we have to clear first, otherwise we are drawing a light striped pattern
418 # over an already darker striped background
419 dc.SetBrush(wx.WHITE_BRUSH)
420 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
422 DrawGradientRectangle(dc, rect, self._background_brush.GetColour(),
423 self._background_gradient_colour,
424 AUI_GRADIENT_HORIZONTAL, rect.x, 700)
427 def DrawBorder(self, dc, window, rect, pane):
429 Draws the pane border.
431 :param `dc`: a `wx.DC` device context;
432 :param `window`: an instance of `wx.Window`;
433 :param `rect`: the border rectangle;
434 :param `pane`: the pane for which the border is drawn.
437 drect = wx.Rect(*rect)
439 dc.SetPen(self._border_pen)
440 dc.SetBrush(wx.TRANSPARENT_BRUSH)
442 border_width = self.GetMetric(AUI_DOCKART_PANE_BORDER_SIZE)
446 for ii in xrange(0, border_width):
448 dc.SetPen(wx.WHITE_PEN)
449 dc.DrawLine(drect.x, drect.y, drect.x+drect.width, drect.y)
450 dc.DrawLine(drect.x, drect.y, drect.x, drect.y+drect.height)
451 dc.SetPen(self._border_pen)
452 dc.DrawLine(drect.x, drect.y+drect.height-1,
453 drect.x+drect.width, drect.y+drect.height-1)
454 dc.DrawLine(drect.x+drect.width-1, drect.y,
455 drect.x+drect.width-1, drect.y+drect.height)
460 for ii in xrange(0, border_width):
462 dc.DrawRectangle(drect.x, drect.y, drect.width, drect.height)
466 def DrawCaptionBackground(self, dc, rect, pane):
468 Draws the text caption background in the pane.
470 :param `dc`: a `wx.DC` device context;
471 :param `rect`: the text caption rectangle;
472 :param `pane`: the pane for which the text background is drawn.
475 active = pane.state & optionActive
477 if self._gradient_type == AUI_GRADIENT_NONE:
479 dc.SetBrush(wx.Brush(self._active_caption_colour))
481 dc.SetBrush(wx.Brush(self._inactive_caption_colour))
483 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
487 switch_gradient = pane.HasCaptionLeft()
488 gradient_type = self._gradient_type
490 gradient_type = (self._gradient_type == AUI_GRADIENT_HORIZONTAL and [AUI_GRADIENT_VERTICAL] or \
491 [AUI_GRADIENT_HORIZONTAL])[0]
494 if wx.Platform == "__WXMAC__":
495 DrawGradientRectangle(dc, rect, self._active_caption_colour,
496 self._active_caption_gradient_colour,
499 DrawGradientRectangle(dc, rect, self._active_caption_gradient_colour,
500 self._active_caption_colour,
503 if wx.Platform == "__WXMAC__":
504 DrawGradientRectangle(dc, rect, self._inactive_caption_gradient_colour,
505 self._inactive_caption_colour,
508 DrawGradientRectangle(dc, rect, self._inactive_caption_colour,
509 self._inactive_caption_gradient_colour,
513 def DrawIcon(self, dc, rect, pane):
515 Draws the icon in the pane caption area.
517 :param `dc`: a `wx.DC` device context;
518 :param `rect`: the pane caption rectangle;
519 :param `pane`: the pane for which the icon is drawn.
522 # Draw the icon centered vertically
524 if pane.HasCaptionLeft():
525 bmp = wx.ImageFromBitmap(pane.icon).Rotate90(clockwise=False)
526 dc.DrawBitmap(bmp.ConvertToBitmap(), rect.x+(rect.width-pane.icon.GetWidth())/2, rect.y+rect.height-2-pane.icon.GetHeight(), True)
528 dc.DrawBitmap(pane.icon, rect.x+2, rect.y+(rect.height-pane.icon.GetHeight())/2, True)
531 def DrawCaption(self, dc, window, text, rect, pane):
533 Draws the text in the pane caption.
535 :param `dc`: a `wx.DC` device context;
536 :param `window`: an instance of `wx.Window`;
537 :param `text`: the text to be displayed;
538 :param `rect`: the pane caption rectangle;
539 :param `pane`: the pane for which the text is drawn.
542 dc.SetPen(wx.TRANSPARENT_PEN)
543 dc.SetFont(self._caption_font)
545 self.DrawCaptionBackground(dc, rect, pane)
547 if pane.state & optionActive:
548 dc.SetTextForeground(self._active_caption_text_colour)
550 dc.SetTextForeground(self._inactive_caption_text_colour)
552 w, h = dc.GetTextExtent("ABCDEFHXfgkj")
554 clip_rect = wx.Rect(*rect)
555 btns = pane.CountButtons()
557 captionLeft = pane.HasCaptionLeft()
558 variable = (captionLeft and [rect.height] or [rect.width])[0]
560 variable -= 3 # text offset
561 variable -= 2 # button padding
566 caption_offset += pane.icon.GetHeight() + 3
568 caption_offset += pane.icon.GetWidth() + 3
570 self.DrawIcon(dc, rect, pane)
572 variable -= caption_offset
573 variable -= btns*(self._button_size + self._border_size)
574 draw_text = ChopText(dc, text, variable)
577 dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-1, rect.y+rect.height-3-caption_offset, 90)
579 dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-1)
582 def RequestUserAttention(self, dc, window, text, rect, pane):
584 Requests the user attention by intermittently highlighting the pane caption.
586 :param `dc`: a `wx.DC` device context;
587 :param `window`: an instance of `wx.Window`;
588 :param `text`: the text to be displayed;
589 :param `rect`: the pane caption rectangle;
590 :param `pane`: the pane for which the text is drawn.
594 pane.state &= ~optionActive
596 for indx in xrange(6):
597 active = (indx%2 == 0 and [True] or [False])[0]
599 pane.state |= optionActive
601 pane.state &= ~optionActive
603 self.DrawCaptionBackground(dc, rect, pane)
604 self.DrawCaption(dc, window, text, rect, pane)
611 def DrawGripper(self, dc, window, rect, pane):
613 Draws a gripper on the pane.
615 :param `dc`: a `wx.DC` device context;
616 :param `window`: an instance of `wx.Window`;
617 :param `rect`: the pane caption rectangle;
618 :param `pane`: the pane for which the gripper is drawn.
621 dc.SetPen(wx.TRANSPARENT_PEN)
622 dc.SetBrush(self._gripper_brush)
624 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
626 if not pane.HasGripperTop():
629 dc.SetPen(self._gripper_pen1)
630 dc.DrawPoint(rect.x+3, rect.y+y)
631 dc.SetPen(self._gripper_pen2)
632 dc.DrawPoint(rect.x+3, rect.y+y+1)
633 dc.DrawPoint(rect.x+4, rect.y+y)
634 dc.SetPen(self._gripper_pen3)
635 dc.DrawPoint(rect.x+5, rect.y+y+1)
636 dc.DrawPoint(rect.x+5, rect.y+y+2)
637 dc.DrawPoint(rect.x+4, rect.y+y+2)
639 if y > rect.GetHeight() - 4:
644 dc.SetPen(self._gripper_pen1)
645 dc.DrawPoint(rect.x+x, rect.y+3)
646 dc.SetPen(self._gripper_pen2)
647 dc.DrawPoint(rect.x+x+1, rect.y+3)
648 dc.DrawPoint(rect.x+x, rect.y+4)
649 dc.SetPen(self._gripper_pen3)
650 dc.DrawPoint(rect.x+x+1, rect.y+5)
651 dc.DrawPoint(rect.x+x+2, rect.y+5)
652 dc.DrawPoint(rect.x+x+2, rect.y+4)
654 if x > rect.GetWidth() - 4:
658 def DrawPaneButton(self, dc, window, button, button_state, _rect, pane):
660 Draws a pane button in the pane caption area.
662 :param `dc`: a `wx.DC` device context;
663 :param `window`: an instance of `wx.Window`;
664 :param `button`: the button to be drawn;
665 :param `button_state`: the pane button state;
666 :param `_rect`: the pane caption rectangle;
667 :param `pane`: the pane for which the button is drawn.
673 if button == AUI_BUTTON_CLOSE:
674 if pane.state & optionActive:
675 bmp = self._active_close_bitmap
677 bmp = self._inactive_close_bitmap
679 elif button == AUI_BUTTON_PIN:
680 if pane.state & optionActive:
681 bmp = self._active_pin_bitmap
683 bmp = self._inactive_pin_bitmap
685 elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
686 if pane.IsMaximized():
687 if pane.state & optionActive:
688 bmp = self._active_restore_bitmap
690 bmp = self._inactive_restore_bitmap
692 if pane.state & optionActive:
693 bmp = self._active_maximize_bitmap
695 bmp = self._inactive_maximize_bitmap
697 elif button == AUI_BUTTON_MINIMIZE:
698 if pane.state & optionActive:
699 bmp = self._active_minimize_bitmap
701 bmp = self._inactive_minimize_bitmap
703 isVertical = pane.HasCaptionLeft()
705 rect = wx.Rect(*_rect)
709 rect.x = rect.x + (rect.width/2) - (bmp.GetWidth()/2)
710 rect.width = old_x + rect.width - rect.x - 1
713 rect.y = rect.y + (rect.height/2) - (bmp.GetHeight()/2)
714 rect.height = old_y + rect.height - rect.y - 1
716 if button_state == AUI_BUTTON_STATE_PRESSED:
720 if button_state in [AUI_BUTTON_STATE_HOVER, AUI_BUTTON_STATE_PRESSED]:
722 if pane.state & optionActive:
724 dc.SetBrush(wx.Brush(StepColour(self._active_caption_colour, 120)))
725 dc.SetPen(wx.Pen(StepColour(self._active_caption_colour, 70)))
729 dc.SetBrush(wx.Brush(StepColour(self._inactive_caption_colour, 120)))
730 dc.SetPen(wx.Pen(StepColour(self._inactive_caption_colour, 70)))
732 if wx.Platform != "__WXMAC__":
733 # draw the background behind the button
734 dc.DrawRectangle(rect.x, rect.y, 15, 15)
736 # Darker the bitmap a bit
737 bmp = DarkenBitmap(bmp, self._active_caption_colour, StepColour(self._active_caption_colour, 110))
740 bmp = wx.ImageFromBitmap(bmp).Rotate90(clockwise=False).ConvertToBitmap()
742 # draw the button itself
743 dc.DrawBitmap(bmp, rect.x, rect.y, True)
746 def DrawSashGripper(self, dc, orient, rect):
748 Draws a sash gripper on a sash between two windows.
750 :param `dc`: a `wx.DC` device context;
751 :param `orient`: the sash orientation;
752 :param `rect`: the sash rectangle.
755 dc.SetBrush(self._gripper_brush)
757 if orient == wx.HORIZONTAL: # horizontal sash
759 x = rect.x + int((1.0/4.0)*rect.width)
760 xend = rect.x + int((3.0/4.0)*rect.width)
761 y = rect.y + (rect.height/2) - 1
764 dc.SetPen(self._gripper_pen3)
765 dc.DrawRectangle(x, y, 2, 2)
766 dc.SetPen(self._gripper_pen2)
767 dc.DrawPoint(x+1, y+1)
775 y = rect.y + int((1.0/4.0)*rect.height)
776 yend = rect.y + int((3.0/4.0)*rect.height)
777 x = rect.x + (rect.width/2) - 1
780 dc.SetPen(self._gripper_pen3)
781 dc.DrawRectangle(x, y, 2, 2)
782 dc.SetPen(self._gripper_pen2)
783 dc.DrawPoint(x+1, y+1)
790 def SetDefaultPaneBitmaps(self, isMac):
792 Assigns the default pane bitmaps.
794 :param `isMac`: whether we are on wxMAC or not.
798 self._inactive_close_bitmap = DrawMACCloseButton(wx.WHITE, self._inactive_caption_colour)
799 self._active_close_bitmap = DrawMACCloseButton(wx.WHITE, self._active_caption_colour)
801 self._inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._inactive_caption_text_colour)
802 self._active_close_bitmap = BitmapFromBits(close_bits, 16, 16, self._active_caption_text_colour)
805 self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
806 self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, wx.WHITE)
808 self._inactive_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._inactive_caption_text_colour)
809 self._active_maximize_bitmap = BitmapFromBits(max_bits, 16, 16, self._active_caption_text_colour)
812 self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
813 self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, wx.WHITE)
815 self._inactive_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._inactive_caption_text_colour)
816 self._active_restore_bitmap = BitmapFromBits(restore_bits, 16, 16, self._active_caption_text_colour)
819 self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
820 self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, wx.WHITE)
822 self._inactive_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._inactive_caption_text_colour)
823 self._active_minimize_bitmap = BitmapFromBits(minimize_bits, 16, 16, self._active_caption_text_colour)
825 self._inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._inactive_caption_text_colour)
826 self._active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, self._active_caption_text_colour)
828 self._custom_pane_bitmaps = False
831 def SetCustomPaneBitmap(self, bmp, button, active, maximize=False):
833 Sets a custom button bitmap for the pane button.
835 :param `bmp`: the actual bitmap to set;
836 :param `button`: the button identifier;
837 :param `active`: whether it is the bitmap for the active button or not;
838 :param `maximize`: used to distinguish between the maximize and restore bitmaps.
841 if bmp.GetWidth() > 16 or bmp.GetHeight() > 16:
842 raise Exception("The input bitmap is too big")
844 if button == AUI_BUTTON_CLOSE:
846 self._active_close_bitmap = bmp
848 self._inactive_close_bitmap = bmp
850 if wx.Platform == "__WXMAC__":
851 self._custom_pane_bitmaps = True
853 elif button == AUI_BUTTON_PIN:
855 self._active_pin_bitmap = bmp
857 self._inactive_pin_bitmap = bmp
859 elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
862 self._active_maximize_bitmap = bmp
864 self._inactive_maximize_bitmap = bmp
867 self._active_restore_bitmap = bmp
869 self._inactive_restore_bitmap = bmp
871 elif button == AUI_BUTTON_MINIMIZE:
873 self._active_minimize_bitmap = bmp
875 self._inactive_minimize_bitmap = bmp
879 class RECT(ctypes.Structure):
880 """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """
881 _fields_ = [('left', ctypes.c_ulong),('top', ctypes.c_ulong),('right', ctypes.c_ulong),('bottom', ctypes.c_ulong)]
884 """ Dumps `self` as a `wx.Rect`. """
885 return map(int, (self.left, self.top, self.right, self.bottom))
888 class SIZE(ctypes.Structure):
889 """ Used to handle L{ModernDockArt} on Windows XP/Vista/7. """
890 _fields_ = [('x', ctypes.c_long),('y', ctypes.c_long)]
893 class ModernDockArt(AuiDefaultDockArt):
895 ModernDockArt is a custom `AuiDockArt` class, that implements a look similar to
896 Firefox and other recents applications.
898 Is uses the `winxptheme` module and XP themes whenever possible, so it should
899 look good even if the user has a custom theme.
901 :note: This dock art is Windows only and will only work if you have installed
902 Mark Hammond's `pywin32` module (http://sourceforge.net/projects/pywin32/).
905 def __init__(self, win):
907 Default class constructor.
909 :param `win`: the window managed by L{AuiManager}.
912 AuiDefaultDockArt.__init__(self)
916 # Get the size of a small close button (themed)
917 hwnd = self.win.GetHandle()
919 self.hTheme1 = winxptheme.OpenThemeData(hwnd, "Window")
921 self.usingTheme = True
924 self.usingTheme = False
926 self._button_size = 13
928 self._button_border_size = 3
929 self._caption_text_indent = 6
930 self._caption_size = 22
932 # We only highlight the active pane with the caption text being in bold.
933 # So we do not want a special colour for active elements.
934 self._active_close_bitmap = self._inactive_close_bitmap
940 """ Initializes the dock art. """
942 AuiDefaultDockArt.Init(self)
944 self._active_caption_colour = self._inactive_caption_colour
945 self._active_caption_text_colour = wx.SystemSettings.GetColour(wx.SYS_COLOUR_CAPTIONTEXT)
946 self._inactive_caption_text_colour = self._active_caption_text_colour
949 def DrawCaption(self, dc, window, text, rect, pane):
951 Draws the text in the pane caption.
953 :param `dc`: a `wx.DC` device context;
954 :param `window`: an instance of `wx.Window`;
955 :param `text`: the text to be displayed;
956 :param `rect`: the pane caption rectangle;
957 :param `pane`: the pane for which the text is drawn.
960 dc.SetPen(wx.TRANSPARENT_PEN)
961 self.DrawCaptionBackground(dc, rect, pane)
963 active = ((pane.state & optionActive) and [True] or [False])[0]
965 self._caption_font.SetWeight(wx.FONTWEIGHT_BOLD)
966 dc.SetFont(self._caption_font)
969 dc.SetTextForeground(self._active_caption_text_colour)
971 dc.SetTextForeground(self._inactive_caption_text_colour)
973 w, h = dc.GetTextExtent("ABCDEFHXfgkj")
975 clip_rect = wx.Rect(*rect)
976 btns = pane.CountButtons()
978 captionLeft = pane.HasCaptionLeft()
979 variable = (captionLeft and [rect.height] or [rect.width])[0]
981 variable -= 3 # text offset
982 variable -= 2 # button padding
987 caption_offset += pane.icon.GetHeight() + 3
989 caption_offset += pane.icon.GetWidth() + 3
991 self.DrawIcon(dc, rect, pane)
997 variable -= caption_offset
998 variable -= btns*(self._button_size + self._button_border_size)
999 draw_text = ChopText(dc, text, variable)
1002 dc.DrawRotatedText(draw_text, rect.x+(rect.width/2)-(h/2)-diff, rect.y+rect.height-3-caption_offset, 90)
1004 dc.DrawText(draw_text, rect.x+3+caption_offset, rect.y+(rect.height/2)-(h/2)-diff)
1007 def DrawCaptionBackground(self, dc, rect, pane):
1009 Draws the text caption background in the pane.
1011 :param `dc`: a `wx.DC` device context;
1012 :param `rect`: the text caption rectangle;
1013 :param `pane`: the pane for which we are drawing the caption background.
1016 dc.SetBrush(self._background_brush)
1017 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height)
1019 active = ((pane.state & optionActive) and [True] or [False])[0]
1023 rectangle = wx.Rect()
1025 rc = RECT(rectangle.x, rectangle.y, rectangle.width, rectangle.height)
1027 # If rect x/y values are negative rc.right/bottom values will overflow and winxptheme.DrawThemeBackground
1028 # will raise a TypeError. Ensure they are never negative.
1029 rect.x = max(0, rect.x)
1030 rect.y = max(0, rect.y)
1034 rc.right = rect.x + rect.width
1035 rc.bottom = rect.y + rect.height
1038 winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 1, (rc.top, rc.left, rc.right, rc.bottom), None)
1040 winxptheme.DrawThemeBackground(self.hTheme1, dc.GetHDC(), 5, 2, (rc.top, rc.left, rc.right, rc.bottom), None)
1044 AuiDefaultDockArt.DrawCaptionBackground(self, dc, rect, pane)
1047 def RequestUserAttention(self, dc, window, text, rect, pane):
1049 Requests the user attention by intermittently highlighting the pane caption.
1051 :param `dc`: a `wx.DC` device context;
1052 :param `window`: an instance of `wx.Window`;
1053 :param `text`: the text to be displayed;
1054 :param `rect`: the pane caption rectangle;
1055 :param `pane`: the pane for which the text is drawn.
1059 pane.state &= ~optionActive
1061 for indx in xrange(6):
1062 active = (indx%2 == 0 and [True] or [False])[0]
1064 pane.state |= optionActive
1066 pane.state &= ~optionActive
1068 self.DrawCaptionBackground(dc, rect, pane)
1069 self.DrawCaption(dc, window, text, rect, pane)
1076 def DrawPaneButton(self, dc, window, button, button_state, rect, pane):
1078 Draws a pane button in the pane caption area.
1080 :param `dc`: a `wx.DC` device context;
1081 :param `window`: an instance of `wx.Window`;
1082 :param `button`: the button to be drawn;
1083 :param `button_state`: the pane button state;
1084 :param `rect`: the pane caption rectangle;
1085 :param `pane`: the pane for which the button is drawn.
1090 hTheme = self.hTheme1
1092 # Get the real button position (compensating for borders)
1093 drect = wx.Rect(rect.x, rect.y, self._button_size, self._button_size)
1095 # Draw the themed close button
1096 rc = RECT(0, 0, 0, 0)
1097 if pane.HasCaptionLeft():
1098 rc.top = rect.x + self._button_border_size
1099 rc.left = int(rect.y + 1.5*self._button_border_size)
1100 rc.right = rect.x + self._button_size + self._button_border_size
1101 rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)
1103 rc.top = rect.x - self._button_border_size
1104 rc.left = int(rect.y + 1.5*self._button_border_size)
1105 rc.right = rect.x + self._button_size- self._button_border_size
1106 rc.bottom = int(rect.y + self._button_size + 1.5*self._button_border_size)
1108 if button == AUI_BUTTON_CLOSE:
1111 elif button == AUI_BUTTON_PIN:
1114 elif button == AUI_BUTTON_MAXIMIZE_RESTORE:
1115 if not pane.IsMaximized():
1122 state = 4 # CBS_DISABLED
1124 if pane.state & optionActive:
1126 if button_state == AUI_BUTTON_STATE_NORMAL:
1127 state = 1 # CBS_NORMAL
1129 elif button_state == AUI_BUTTON_STATE_HOVER:
1132 elif button_state == AUI_BUTTON_STATE_PRESSED:
1133 state = 3 # CBS_PUSHED
1136 raise Exception("ERROR: Unknown State.")
1138 else: # inactive pane
1140 if button_state == AUI_BUTTON_STATE_NORMAL:
1141 state = 5 # CBS_NORMAL
1143 elif button_state == AUI_BUTTON_STATE_HOVER:
1146 elif button_state == AUI_BUTTON_STATE_PRESSED:
1147 state = 7 # CBS_PUSHED
1150 raise Exception("ERROR: Unknown State.")
1153 winxptheme.DrawThemeBackground(hTheme, dc.GetHDC(), btntype, state, (rc.top, rc.left, rc.right, rc.bottom), None)
1159 # Fallback to default closebutton if themes are not enabled
1160 rect2 = wx.Rect(rect.x-4, rect.y+2, rect.width, rect.height)
1161 AuiDefaultDockArt.DrawPaneButton(self, dc, window, button, button_state, rect2, pane)