1 ///////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxaui: wx advanced user interface - docking window manager
4 // Author: Benjamin I. Williams
8 // Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
9 // Licence: wxWindows Library Licence, Version 3.1
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #include "wx/wxprec.h"
29 #include "wx/dcclient.h"
30 #include "wx/settings.h"
31 #include "wx/aui/framemanager.h"
32 #include "wx/aui/dockart.h"
35 // #include "wx/log.h"
38 // -- wxDefaultDockArt class implementation --
40 // wxDefaultDockArt is an art provider class which does all of the drawing for
41 // wxFrameManager. This allows the library caller to customize the dock art
42 // (probably by deriving from this class), or to completely replace all drawing
43 // with custom dock art (probably by writing a new stand-alone class derived
44 // from the wxDockArt base class). The active dock art class can be set via
45 // wxFrameManager::SetDockArt()
48 // StepColour() it a utility function that simply darkens
49 // or lightens a color, based on the specified percentage
50 static wxColor
StepColour(const wxColor
& c
, int percent
)
52 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
53 return wxColour(wxMin((r
*percent
)/100,255),
54 wxMin((g
*percent
)/100,255),
55 wxMin((b
*percent
)/100,255));
58 static wxColor
LightContrastColour(const wxColour
& c
)
62 // if the color is especially dark, then
63 // make the contrast even lighter
64 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
67 return StepColour(c
, amount
);
70 // BitmapFromBits() is a utility function that creates a
71 // masked bitmap from raw bits (XBM format)
72 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
73 const wxColour
& color
)
75 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
76 img
.Replace(255,255,255,123,123,123);
77 img
.Replace(0,0,0,color
.Red(),color
.Green(),color
.Blue());
78 img
.SetMaskColour(123,123,123);
83 static void DrawGradientRectangle(wxDC
& dc
,
85 const wxColour
& start_color
,
86 const wxColour
& end_color
,
89 int rd
, gd
, bd
, high
= 0;
90 rd
= end_color
.Red() - start_color
.Red();
91 gd
= end_color
.Green() - start_color
.Green();
92 bd
= end_color
.Blue() - start_color
.Blue();
94 if (direction
== wxAUI_GRADIENT_VERTICAL
)
95 high
= rect
.GetHeight()-1;
97 high
= rect
.GetWidth()-1;
99 for (int i
= 0; i
<= high
; ++i
)
101 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
102 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
103 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
105 wxPen
p(wxColor(r
,g
,b
));
108 if (direction
== wxAUI_GRADIENT_VERTICAL
)
109 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
111 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
116 wxDefaultDockArt::wxDefaultDockArt()
119 wxBrush toolbarbrush
;
120 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
121 wxColor base_color
= toolbarbrush
.GetColour();
123 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
126 wxColor darker1_color
= StepColour(base_color
, 85);
127 wxColor darker2_color
= StepColour(base_color
, 70);
128 wxColor darker3_color
= StepColour(base_color
, 60);
129 wxColor darker4_color
= StepColour(base_color
, 50);
130 wxColor darker5_color
= StepColour(base_color
, 40);
132 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
133 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
134 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
135 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
136 m_inactive_caption_gradient_colour
= darker1_color
;
137 m_inactive_caption_text_colour
= *wxBLACK
;
140 m_sash_brush
= toolbarbrush
;
141 m_background_brush
= toolbarbrush
;
142 m_gripper_brush
= toolbarbrush
;
144 m_sash_brush
= wxBrush(base_color
);
145 m_background_brush
= wxBrush(base_color
);
146 m_gripper_brush
= wxBrush(base_color
);
148 m_border_pen
= wxPen(darker2_color
);
149 m_gripper_pen1
= wxPen(darker5_color
);
150 m_gripper_pen2
= wxPen(darker3_color
);
151 m_gripper_pen3
= *wxWHITE_PEN
;
154 m_caption_font
= *wxSMALL_FONT
;
156 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
159 // some built in bitmaps
161 static unsigned char close_bits
[]={
162 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
163 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
164 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
166 static unsigned char close_bits
[]={
167 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
168 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
169 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
172 static unsigned char pin_bits
[]={
173 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
174 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
175 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
178 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
180 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
182 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
184 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
186 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
188 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
190 // default metric values
193 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
194 m_sash_size
= height
;
202 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
205 int wxDefaultDockArt::GetMetric(int id
)
209 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
210 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
211 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
212 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
213 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
214 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
215 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
221 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
225 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
226 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
227 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
228 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
229 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
230 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
231 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
235 wxColour
wxDefaultDockArt::GetColour(int id
)
239 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour(); break;
240 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour(); break;
241 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
; break;
242 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
; break;
243 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
; break;
244 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
; break;
245 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
; break;
246 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
; break;
247 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour(); break;
248 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour(); break;
249 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
255 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
259 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
260 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
261 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
262 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
263 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
264 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
265 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
266 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
267 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
268 case wxAUI_ART_GRIPPER_COLOUR
:
269 m_gripper_brush
.SetColour(colour
);
270 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
271 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
273 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
277 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
279 if (id
== wxAUI_ART_CAPTION_FONT
)
280 m_caption_font
= font
;
283 wxFont
wxDefaultDockArt::GetFont(int id
)
285 if (id
== wxAUI_ART_CAPTION_FONT
)
286 return m_caption_font
;
290 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
)
293 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
294 CGContextRef cgContext
;
295 #if wxMAC_USE_CORE_GRAPHICS
296 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
299 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
300 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
301 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
302 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
305 HIThemeSplitterDrawInfo drawInfo
;
306 drawInfo
.version
= 0 ;
307 drawInfo
.state
= kThemeStateActive
;
308 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
309 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
311 #if wxMAC_USE_CORE_GRAPHICS
313 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
317 dc
.SetPen(*wxTRANSPARENT_PEN
);
318 dc
.SetBrush(m_sash_brush
);
319 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
324 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
)
326 dc
.SetPen(*wxTRANSPARENT_PEN
);
328 // we have to clear first, otherwise we are drawing a light striped pattern
329 // over an already darker striped background
330 dc
.SetBrush(*wxWHITE_BRUSH
) ;
331 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
333 dc
.SetBrush(m_background_brush
);
334 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
337 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
,
340 dc
.SetPen(m_border_pen
);
341 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
344 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
346 if (pane
.IsToolbar())
348 for (i
= 0; i
< border_width
; ++i
)
350 dc
.SetPen(*wxWHITE_PEN
);
351 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
352 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
353 dc
.SetPen(m_border_pen
);
354 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
355 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
356 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
357 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
363 for (i
= 0; i
< border_width
; ++i
)
365 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
372 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
374 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
377 dc
.SetBrush(wxBrush(m_active_caption_colour
));
379 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
381 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
387 // on mac the gradients are expected to become darker from the top
389 DrawGradientRectangle(dc
, rect
,
390 m_active_caption_gradient_colour
,
391 m_active_caption_colour
,
394 DrawGradientRectangle(dc
, rect
,
395 m_active_caption_colour
,
396 m_active_caption_gradient_colour
,
402 // on mac the gradients are expected to become darker from the top
404 DrawGradientRectangle(dc
, rect
,
405 m_inactive_caption_gradient_colour
,
406 m_inactive_caption_colour
,
409 DrawGradientRectangle(dc
, rect
,
410 m_inactive_caption_colour
,
411 m_inactive_caption_gradient_colour
,
419 void wxDefaultDockArt::DrawCaption(wxDC
& dc
,
420 const wxString
& text
,
424 dc
.SetPen(*wxTRANSPARENT_PEN
);
425 dc
.SetFont(m_caption_font
);
427 DrawCaptionBackground(dc
, rect
,
428 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
430 if (pane
.state
& wxPaneInfo::optionActive
)
431 dc
.SetTextForeground(m_active_caption_text_colour
);
433 dc
.SetTextForeground(m_inactive_caption_text_colour
);
437 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
439 dc
.SetClippingRegion(rect
);
440 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
441 dc
.DestroyClippingRegion();
444 void wxDefaultDockArt::DrawGripper(wxDC
& dc
,
448 dc
.SetPen(*wxTRANSPARENT_PEN
);
449 dc
.SetBrush(m_gripper_brush
);
451 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
453 if (!pane
.HasGripperTop())
458 dc
.SetPen(m_gripper_pen1
);
459 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
460 dc
.SetPen(m_gripper_pen2
);
461 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
462 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
463 dc
.SetPen(m_gripper_pen3
);
464 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
465 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
466 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
469 if (y
> rect
.GetHeight()-5)
478 dc
.SetPen(m_gripper_pen1
);
479 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
480 dc
.SetPen(m_gripper_pen2
);
481 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
482 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
483 dc
.SetPen(m_gripper_pen3
);
484 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
485 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
486 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
489 if (x
> rect
.GetWidth()-5)
495 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
,
503 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
509 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
510 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
512 if (pane
.state
& wxPaneInfo::optionActive
)
514 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
515 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
519 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
520 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
523 // draw the background behind the button
524 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
531 case wxPaneInfo::buttonClose
:
532 if (pane
.state
& wxPaneInfo::optionActive
)
533 bmp
= m_active_close_bitmap
;
535 bmp
= m_inactive_close_bitmap
;
537 case wxPaneInfo::buttonPin
:
538 if (pane
.state
& wxPaneInfo::optionActive
)
539 bmp
= m_active_pin_bitmap
;
541 bmp
= m_inactive_pin_bitmap
;
545 // draw the button itself
546 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);