1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/dockart.cpp
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"
28 #include "wx/aui/framemanager.h"
29 #include "wx/aui/dockart.h"
32 #include "wx/settings.h"
33 #include "wx/dcclient.h"
38 #include "wx/mac/private.h"
41 // -- wxDefaultDockArt class implementation --
43 // wxDefaultDockArt is an art provider class which does all of the drawing for
44 // wxFrameManager. This allows the library caller to customize the dock art
45 // (probably by deriving from this class), or to completely replace all drawing
46 // with custom dock art (probably by writing a new stand-alone class derived
47 // from the wxDockArt base class). The active dock art class can be set via
48 // wxFrameManager::SetDockArt()
51 // StepColour() it a utility function that simply darkens
52 // or lightens a color, based on the specified percentage
53 static wxColor
StepColour(const wxColor
& c
, int percent
)
55 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
56 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
57 (unsigned char)wxMin((g
*percent
)/100,255),
58 (unsigned char)wxMin((b
*percent
)/100,255));
61 static wxColor
LightContrastColour(const wxColour
& c
)
65 // if the color is especially dark, then
66 // make the contrast even lighter
67 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
70 return StepColour(c
, amount
);
73 // BitmapFromBits() is a utility function that creates a
74 // masked bitmap from raw bits (XBM format)
75 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
76 const wxColour
& color
)
78 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
79 img
.Replace(255,255,255,123,123,123);
80 img
.Replace(0,0,0,color
.Red(),color
.Green(),color
.Blue());
81 img
.SetMaskColour(123,123,123);
86 static void DrawGradientRectangle(wxDC
& dc
,
88 const wxColour
& start_color
,
89 const wxColour
& end_color
,
92 int rd
, gd
, bd
, high
= 0;
93 rd
= end_color
.Red() - start_color
.Red();
94 gd
= end_color
.Green() - start_color
.Green();
95 bd
= end_color
.Blue() - start_color
.Blue();
97 if (direction
== wxAUI_GRADIENT_VERTICAL
)
98 high
= rect
.GetHeight()-1;
100 high
= rect
.GetWidth()-1;
102 for (int i
= 0; i
<= high
; ++i
)
104 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
105 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
106 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
108 wxPen
p(wxColor((unsigned char)r
,
113 if (direction
== wxAUI_GRADIENT_VERTICAL
)
114 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
116 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
121 wxDefaultDockArt::wxDefaultDockArt()
124 wxBrush toolbarbrush
;
125 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
126 wxColor base_color
= toolbarbrush
.GetColour();
128 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
131 wxColor darker1_color
= StepColour(base_color
, 85);
132 wxColor darker2_color
= StepColour(base_color
, 70);
133 wxColor darker3_color
= StepColour(base_color
, 60);
134 wxColor darker4_color
= StepColour(base_color
, 50);
135 wxColor darker5_color
= StepColour(base_color
, 40);
137 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
138 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
139 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
140 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
141 m_inactive_caption_gradient_colour
= darker1_color
;
142 m_inactive_caption_text_colour
= *wxBLACK
;
145 m_sash_brush
= toolbarbrush
;
146 m_background_brush
= toolbarbrush
;
147 m_gripper_brush
= toolbarbrush
;
149 m_sash_brush
= wxBrush(base_color
);
150 m_background_brush
= wxBrush(base_color
);
151 m_gripper_brush
= wxBrush(base_color
);
153 m_border_pen
= wxPen(darker2_color
);
154 m_gripper_pen1
= wxPen(darker5_color
);
155 m_gripper_pen2
= wxPen(darker3_color
);
156 m_gripper_pen3
= *wxWHITE_PEN
;
159 m_caption_font
= *wxSMALL_FONT
;
161 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
164 // some built in bitmaps
166 static unsigned char close_bits
[]={
167 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
168 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
169 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
171 static unsigned char close_bits
[]={
172 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
173 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
174 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
177 static unsigned char pin_bits
[]={
178 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
179 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
180 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
183 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
185 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
187 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
189 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
191 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
193 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
195 // default metric values
198 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
199 m_sash_size
= height
;
207 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
210 int wxDefaultDockArt::GetMetric(int id
)
214 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
215 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
216 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
217 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
218 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
219 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
220 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
226 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
230 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
231 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
232 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
233 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
234 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
235 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
236 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
240 wxColour
wxDefaultDockArt::GetColour(int id
)
244 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour();
245 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour();
246 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
;
247 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
;
248 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
;
249 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
;
250 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
;
251 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
;
252 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour();
253 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour();
254 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
260 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
264 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
265 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
266 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
267 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
268 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
269 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
270 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
271 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
272 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
273 case wxAUI_ART_GRIPPER_COLOUR
:
274 m_gripper_brush
.SetColour(colour
);
275 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
276 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
278 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
282 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
284 if (id
== wxAUI_ART_CAPTION_FONT
)
285 m_caption_font
= font
;
288 wxFont
wxDefaultDockArt::GetFont(int id
)
290 if (id
== wxAUI_ART_CAPTION_FONT
)
291 return m_caption_font
;
295 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
)
298 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
299 CGContextRef cgContext
;
300 #if wxMAC_USE_CORE_GRAPHICS
301 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
304 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
305 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
306 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
307 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
310 HIThemeSplitterDrawInfo drawInfo
;
311 drawInfo
.version
= 0 ;
312 drawInfo
.state
= kThemeStateActive
;
313 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
314 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
316 #if wxMAC_USE_CORE_GRAPHICS
318 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
322 dc
.SetPen(*wxTRANSPARENT_PEN
);
323 dc
.SetBrush(m_sash_brush
);
324 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
329 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
)
331 dc
.SetPen(*wxTRANSPARENT_PEN
);
333 // we have to clear first, otherwise we are drawing a light striped pattern
334 // over an already darker striped background
335 dc
.SetBrush(*wxWHITE_BRUSH
) ;
336 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
338 dc
.SetBrush(m_background_brush
);
339 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
342 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
,
345 dc
.SetPen(m_border_pen
);
346 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
349 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
351 if (pane
.IsToolbar())
353 for (i
= 0; i
< border_width
; ++i
)
355 dc
.SetPen(*wxWHITE_PEN
);
356 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
357 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
358 dc
.SetPen(m_border_pen
);
359 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
360 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
361 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
362 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
368 for (i
= 0; i
< border_width
; ++i
)
370 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
377 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
379 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
382 dc
.SetBrush(wxBrush(m_active_caption_colour
));
384 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
386 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
392 // on mac the gradients are expected to become darker from the top
394 DrawGradientRectangle(dc
, rect
,
395 m_active_caption_gradient_colour
,
396 m_active_caption_colour
,
399 DrawGradientRectangle(dc
, rect
,
400 m_active_caption_colour
,
401 m_active_caption_gradient_colour
,
407 // on mac the gradients are expected to become darker from the top
409 DrawGradientRectangle(dc
, rect
,
410 m_inactive_caption_gradient_colour
,
411 m_inactive_caption_colour
,
414 DrawGradientRectangle(dc
, rect
,
415 m_inactive_caption_colour
,
416 m_inactive_caption_gradient_colour
,
424 void wxDefaultDockArt::DrawCaption(wxDC
& dc
,
425 const wxString
& text
,
429 dc
.SetPen(*wxTRANSPARENT_PEN
);
430 dc
.SetFont(m_caption_font
);
432 DrawCaptionBackground(dc
, rect
,
433 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
435 if (pane
.state
& wxPaneInfo::optionActive
)
436 dc
.SetTextForeground(m_active_caption_text_colour
);
438 dc
.SetTextForeground(m_inactive_caption_text_colour
);
442 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
444 dc
.SetClippingRegion(rect
);
445 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
446 dc
.DestroyClippingRegion();
449 void wxDefaultDockArt::DrawGripper(wxDC
& dc
,
453 dc
.SetPen(*wxTRANSPARENT_PEN
);
454 dc
.SetBrush(m_gripper_brush
);
456 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
458 if (!pane
.HasGripperTop())
463 dc
.SetPen(m_gripper_pen1
);
464 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
465 dc
.SetPen(m_gripper_pen2
);
466 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
467 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
468 dc
.SetPen(m_gripper_pen3
);
469 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
470 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
471 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
474 if (y
> rect
.GetHeight()-5)
483 dc
.SetPen(m_gripper_pen1
);
484 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
485 dc
.SetPen(m_gripper_pen2
);
486 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
487 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
488 dc
.SetPen(m_gripper_pen3
);
489 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
490 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
491 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
494 if (x
> rect
.GetWidth()-5)
500 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
,
508 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
514 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
515 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
517 if (pane
.state
& wxPaneInfo::optionActive
)
519 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
520 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
524 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
525 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
528 // draw the background behind the button
529 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
536 case wxPaneInfo::buttonClose
:
537 if (pane
.state
& wxPaneInfo::optionActive
)
538 bmp
= m_active_close_bitmap
;
540 bmp
= m_inactive_close_bitmap
;
542 case wxPaneInfo::buttonPin
:
543 if (pane
.state
& wxPaneInfo::optionActive
)
544 bmp
= m_active_pin_bitmap
;
546 bmp
= m_inactive_pin_bitmap
;
550 // draw the button itself
551 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);