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(0,0,0,123,123,123);
80 img
.Replace(255,255,255,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
165 #if defined( __WXMAC__ )
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 };
170 #elif defined( __WXGTK__)
171 static unsigned char close_bits
[]={
172 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
173 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
174 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
176 static unsigned char close_bits
[]={
177 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
178 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
179 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
182 static unsigned char pin_bits
[]={
183 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
184 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
185 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
188 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
190 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
192 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
194 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
196 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
198 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
200 // default metric values
203 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
204 m_sash_size
= height
;
212 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
215 int wxDefaultDockArt::GetMetric(int id
)
219 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
220 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
221 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
222 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
223 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
224 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
225 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
231 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
235 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
236 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
237 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
238 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
239 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
240 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
241 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
245 wxColour
wxDefaultDockArt::GetColour(int id
)
249 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour();
250 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour();
251 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
;
252 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
;
253 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
;
254 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
;
255 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
;
256 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
;
257 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour();
258 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour();
259 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
265 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
269 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
270 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
271 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
272 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
273 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
274 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
275 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
276 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
277 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
278 case wxAUI_ART_GRIPPER_COLOUR
:
279 m_gripper_brush
.SetColour(colour
);
280 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
281 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
283 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
287 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
289 if (id
== wxAUI_ART_CAPTION_FONT
)
290 m_caption_font
= font
;
293 wxFont
wxDefaultDockArt::GetFont(int id
)
295 if (id
== wxAUI_ART_CAPTION_FONT
)
296 return m_caption_font
;
300 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
)
303 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
304 CGContextRef cgContext
;
305 #if wxMAC_USE_CORE_GRAPHICS
306 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
309 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
310 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
311 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
312 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
315 HIThemeSplitterDrawInfo drawInfo
;
316 drawInfo
.version
= 0 ;
317 drawInfo
.state
= kThemeStateActive
;
318 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
319 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
321 #if wxMAC_USE_CORE_GRAPHICS
323 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
327 dc
.SetPen(*wxTRANSPARENT_PEN
);
328 dc
.SetBrush(m_sash_brush
);
329 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
334 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
)
336 dc
.SetPen(*wxTRANSPARENT_PEN
);
338 // we have to clear first, otherwise we are drawing a light striped pattern
339 // over an already darker striped background
340 dc
.SetBrush(*wxWHITE_BRUSH
) ;
341 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
343 dc
.SetBrush(m_background_brush
);
344 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
347 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
,
350 dc
.SetPen(m_border_pen
);
351 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
354 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
356 if (pane
.IsToolbar())
358 for (i
= 0; i
< border_width
; ++i
)
360 dc
.SetPen(*wxWHITE_PEN
);
361 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
362 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
363 dc
.SetPen(m_border_pen
);
364 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
365 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
366 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
367 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
373 for (i
= 0; i
< border_width
; ++i
)
375 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
382 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
384 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
387 dc
.SetBrush(wxBrush(m_active_caption_colour
));
389 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
391 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
397 // on mac the gradients are expected to become darker from the top
399 DrawGradientRectangle(dc
, rect
,
400 m_active_caption_gradient_colour
,
401 m_active_caption_colour
,
404 DrawGradientRectangle(dc
, rect
,
405 m_active_caption_colour
,
406 m_active_caption_gradient_colour
,
412 // on mac the gradients are expected to become darker from the top
414 DrawGradientRectangle(dc
, rect
,
415 m_inactive_caption_gradient_colour
,
416 m_inactive_caption_colour
,
419 DrawGradientRectangle(dc
, rect
,
420 m_inactive_caption_colour
,
421 m_inactive_caption_gradient_colour
,
429 void wxDefaultDockArt::DrawCaption(wxDC
& dc
,
430 const wxString
& text
,
434 dc
.SetPen(*wxTRANSPARENT_PEN
);
435 dc
.SetFont(m_caption_font
);
437 DrawCaptionBackground(dc
, rect
,
438 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
440 if (pane
.state
& wxPaneInfo::optionActive
)
441 dc
.SetTextForeground(m_active_caption_text_colour
);
443 dc
.SetTextForeground(m_inactive_caption_text_colour
);
447 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
449 dc
.SetClippingRegion(rect
);
450 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
451 dc
.DestroyClippingRegion();
454 void wxDefaultDockArt::DrawGripper(wxDC
& dc
,
458 dc
.SetPen(*wxTRANSPARENT_PEN
);
459 dc
.SetBrush(m_gripper_brush
);
461 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
463 if (!pane
.HasGripperTop())
468 dc
.SetPen(m_gripper_pen1
);
469 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
470 dc
.SetPen(m_gripper_pen2
);
471 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
472 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
473 dc
.SetPen(m_gripper_pen3
);
474 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
475 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
476 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
479 if (y
> rect
.GetHeight()-5)
488 dc
.SetPen(m_gripper_pen1
);
489 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
490 dc
.SetPen(m_gripper_pen2
);
491 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
492 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
493 dc
.SetPen(m_gripper_pen3
);
494 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
495 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
496 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
499 if (x
> rect
.GetWidth()-5)
505 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
,
513 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
519 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
520 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
522 if (pane
.state
& wxPaneInfo::optionActive
)
524 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
525 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
529 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
530 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
533 // draw the background behind the button
534 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
541 case wxPaneInfo::buttonClose
:
542 if (pane
.state
& wxPaneInfo::optionActive
)
543 bmp
= m_active_close_bitmap
;
545 bmp
= m_inactive_close_bitmap
;
547 case wxPaneInfo::buttonPin
:
548 if (pane
.state
& wxPaneInfo::optionActive
)
549 bmp
= m_active_pin_bitmap
;
551 bmp
= m_inactive_pin_bitmap
;
555 // draw the button itself
556 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);