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"
29 #include "wx/aui/framemanager.h"
30 #include "wx/aui/dockart.h"
33 #include "wx/settings.h"
34 #include "wx/dcclient.h"
37 // -- wxDefaultDockArt class implementation --
39 // wxDefaultDockArt is an art provider class which does all of the drawing for
40 // wxFrameManager. This allows the library caller to customize the dock art
41 // (probably by deriving from this class), or to completely replace all drawing
42 // with custom dock art (probably by writing a new stand-alone class derived
43 // from the wxDockArt base class). The active dock art class can be set via
44 // wxFrameManager::SetDockArt()
47 // StepColour() it a utility function that simply darkens
48 // or lightens a color, based on the specified percentage
49 static wxColor
StepColour(const wxColor
& c
, int percent
)
51 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
52 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
53 (unsigned char)wxMin((g
*percent
)/100,255),
54 (unsigned char)wxMin((b
*percent
)/100,255));
57 static wxColor
LightContrastColour(const wxColour
& c
)
61 // if the color is especially dark, then
62 // make the contrast even lighter
63 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
66 return StepColour(c
, amount
);
69 // BitmapFromBits() is a utility function that creates a
70 // masked bitmap from raw bits (XBM format)
71 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
72 const wxColour
& color
)
74 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
75 img
.Replace(255,255,255,123,123,123);
76 img
.Replace(0,0,0,color
.Red(),color
.Green(),color
.Blue());
77 img
.SetMaskColour(123,123,123);
82 static void DrawGradientRectangle(wxDC
& dc
,
84 const wxColour
& start_color
,
85 const wxColour
& end_color
,
88 int rd
, gd
, bd
, high
= 0;
89 rd
= end_color
.Red() - start_color
.Red();
90 gd
= end_color
.Green() - start_color
.Green();
91 bd
= end_color
.Blue() - start_color
.Blue();
93 if (direction
== wxAUI_GRADIENT_VERTICAL
)
94 high
= rect
.GetHeight()-1;
96 high
= rect
.GetWidth()-1;
98 for (int i
= 0; i
<= high
; ++i
)
100 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
101 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
102 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
104 wxPen
p(wxColor((unsigned char)r
,
109 if (direction
== wxAUI_GRADIENT_VERTICAL
)
110 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
112 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
117 wxDefaultDockArt::wxDefaultDockArt()
120 wxBrush toolbarbrush
;
121 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
122 wxColor base_color
= toolbarbrush
.GetColour();
124 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
127 wxColor darker1_color
= StepColour(base_color
, 85);
128 wxColor darker2_color
= StepColour(base_color
, 70);
129 wxColor darker3_color
= StepColour(base_color
, 60);
130 wxColor darker4_color
= StepColour(base_color
, 50);
131 wxColor darker5_color
= StepColour(base_color
, 40);
133 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
134 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
135 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
136 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
137 m_inactive_caption_gradient_colour
= darker1_color
;
138 m_inactive_caption_text_colour
= *wxBLACK
;
141 m_sash_brush
= toolbarbrush
;
142 m_background_brush
= toolbarbrush
;
143 m_gripper_brush
= toolbarbrush
;
145 m_sash_brush
= wxBrush(base_color
);
146 m_background_brush
= wxBrush(base_color
);
147 m_gripper_brush
= wxBrush(base_color
);
149 m_border_pen
= wxPen(darker2_color
);
150 m_gripper_pen1
= wxPen(darker5_color
);
151 m_gripper_pen2
= wxPen(darker3_color
);
152 m_gripper_pen3
= *wxWHITE_PEN
;
155 m_caption_font
= *wxSMALL_FONT
;
157 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
160 // some built in bitmaps
162 static unsigned char close_bits
[]={
163 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
164 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
165 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
167 static unsigned char close_bits
[]={
168 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
169 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
170 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
173 static unsigned char pin_bits
[]={
174 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
175 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
176 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
179 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
181 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
183 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
185 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
187 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
189 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
191 // default metric values
194 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
195 m_sash_size
= height
;
203 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
206 int wxDefaultDockArt::GetMetric(int id
)
210 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
211 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
212 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
213 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
214 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
215 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
216 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
222 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
226 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
227 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
228 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
229 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
230 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
231 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
232 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
236 wxColour
wxDefaultDockArt::GetColour(int id
)
240 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour();
241 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour();
242 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
;
243 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
;
244 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
;
245 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
;
246 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
;
247 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
;
248 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour();
249 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour();
250 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
256 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
260 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
261 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
262 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
263 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
264 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
265 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
266 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
267 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
268 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
269 case wxAUI_ART_GRIPPER_COLOUR
:
270 m_gripper_brush
.SetColour(colour
);
271 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
272 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
274 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
278 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
280 if (id
== wxAUI_ART_CAPTION_FONT
)
281 m_caption_font
= font
;
284 wxFont
wxDefaultDockArt::GetFont(int id
)
286 if (id
== wxAUI_ART_CAPTION_FONT
)
287 return m_caption_font
;
291 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
)
294 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
295 CGContextRef cgContext
;
296 #if wxMAC_USE_CORE_GRAPHICS
297 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
300 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
301 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
302 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
303 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
306 HIThemeSplitterDrawInfo drawInfo
;
307 drawInfo
.version
= 0 ;
308 drawInfo
.state
= kThemeStateActive
;
309 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
310 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
312 #if wxMAC_USE_CORE_GRAPHICS
314 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
318 dc
.SetPen(*wxTRANSPARENT_PEN
);
319 dc
.SetBrush(m_sash_brush
);
320 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
325 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
)
327 dc
.SetPen(*wxTRANSPARENT_PEN
);
329 // we have to clear first, otherwise we are drawing a light striped pattern
330 // over an already darker striped background
331 dc
.SetBrush(*wxWHITE_BRUSH
) ;
332 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
334 dc
.SetBrush(m_background_brush
);
335 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
338 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
,
341 dc
.SetPen(m_border_pen
);
342 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
345 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
347 if (pane
.IsToolbar())
349 for (i
= 0; i
< border_width
; ++i
)
351 dc
.SetPen(*wxWHITE_PEN
);
352 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
353 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
354 dc
.SetPen(m_border_pen
);
355 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
356 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
357 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
358 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
364 for (i
= 0; i
< border_width
; ++i
)
366 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
373 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
375 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
378 dc
.SetBrush(wxBrush(m_active_caption_colour
));
380 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
382 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
388 // on mac the gradients are expected to become darker from the top
390 DrawGradientRectangle(dc
, rect
,
391 m_active_caption_gradient_colour
,
392 m_active_caption_colour
,
395 DrawGradientRectangle(dc
, rect
,
396 m_active_caption_colour
,
397 m_active_caption_gradient_colour
,
403 // on mac the gradients are expected to become darker from the top
405 DrawGradientRectangle(dc
, rect
,
406 m_inactive_caption_gradient_colour
,
407 m_inactive_caption_colour
,
410 DrawGradientRectangle(dc
, rect
,
411 m_inactive_caption_colour
,
412 m_inactive_caption_gradient_colour
,
420 void wxDefaultDockArt::DrawCaption(wxDC
& dc
,
421 const wxString
& text
,
425 dc
.SetPen(*wxTRANSPARENT_PEN
);
426 dc
.SetFont(m_caption_font
);
428 DrawCaptionBackground(dc
, rect
,
429 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
431 if (pane
.state
& wxPaneInfo::optionActive
)
432 dc
.SetTextForeground(m_active_caption_text_colour
);
434 dc
.SetTextForeground(m_inactive_caption_text_colour
);
438 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
440 dc
.SetClippingRegion(rect
);
441 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
442 dc
.DestroyClippingRegion();
445 void wxDefaultDockArt::DrawGripper(wxDC
& dc
,
449 dc
.SetPen(*wxTRANSPARENT_PEN
);
450 dc
.SetBrush(m_gripper_brush
);
452 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
454 if (!pane
.HasGripperTop())
459 dc
.SetPen(m_gripper_pen1
);
460 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
461 dc
.SetPen(m_gripper_pen2
);
462 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
463 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
464 dc
.SetPen(m_gripper_pen3
);
465 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
466 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
467 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
470 if (y
> rect
.GetHeight()-5)
479 dc
.SetPen(m_gripper_pen1
);
480 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
481 dc
.SetPen(m_gripper_pen2
);
482 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
483 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
484 dc
.SetPen(m_gripper_pen3
);
485 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
486 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
487 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
490 if (x
> rect
.GetWidth()-5)
496 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
,
504 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
510 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
511 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
513 if (pane
.state
& wxPaneInfo::optionActive
)
515 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
516 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
520 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
521 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
524 // draw the background behind the button
525 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
532 case wxPaneInfo::buttonClose
:
533 if (pane
.state
& wxPaneInfo::optionActive
)
534 bmp
= m_active_close_bitmap
;
536 bmp
= m_inactive_close_bitmap
;
538 case wxPaneInfo::buttonPin
:
539 if (pane
.state
& wxPaneInfo::optionActive
)
540 bmp
= m_active_pin_bitmap
;
542 bmp
= m_inactive_pin_bitmap
;
546 // draw the button itself
547 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);