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/mac/private.h"
39 // #include "wx/log.h"
42 // -- wxDefaultDockArt class implementation --
44 // wxDefaultDockArt is an art provider class which does all of the drawing for
45 // wxFrameManager. This allows the library caller to customize the dock art
46 // (probably by deriving from this class), or to completely replace all drawing
47 // with custom dock art (probably by writing a new stand-alone class derived
48 // from the wxDockArt base class). The active dock art class can be set via
49 // wxFrameManager::SetDockArt()
52 // StepColour() it a utility function that simply darkens
53 // or lightens a color, based on the specified percentage
54 static wxColor
StepColour(const wxColor
& c
, int percent
)
56 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
57 return wxColour(wxMin((r
*percent
)/100,255),
58 wxMin((g
*percent
)/100,255),
59 wxMin((b
*percent
)/100,255));
62 static wxColor
LightContrastColour(const wxColour
& c
)
66 // if the color is especially dark, then
67 // make the contrast even lighter
68 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
71 return StepColour(c
, amount
);
74 // BitmapFromBits() is a utility function that creates a
75 // masked bitmap from raw bits (XBM format)
76 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
77 const wxColour
& color
)
79 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
80 img
.Replace(255,255,255,123,123,123);
81 img
.Replace(0,0,0,color
.Red(),color
.Green(),color
.Blue());
82 img
.SetMaskColour(123,123,123);
87 static void DrawGradientRectangle(wxDC
& dc
,
89 const wxColour
& start_color
,
90 const wxColour
& end_color
,
93 int rd
, gd
, bd
, high
= 0;
94 rd
= end_color
.Red() - start_color
.Red();
95 gd
= end_color
.Green() - start_color
.Green();
96 bd
= end_color
.Blue() - start_color
.Blue();
98 if (direction
== wxAUI_GRADIENT_VERTICAL
)
99 high
= rect
.GetHeight()-1;
101 high
= rect
.GetWidth()-1;
103 for (int i
= 0; i
<= high
; ++i
)
105 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
106 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
107 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
109 wxPen
p(wxColor(r
,g
,b
));
112 if (direction
== wxAUI_GRADIENT_VERTICAL
)
113 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
115 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
120 wxDefaultDockArt::wxDefaultDockArt()
123 wxBrush toolbarbrush
;
124 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
125 wxColor base_color
= toolbarbrush
.GetColour();
127 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
130 wxColor darker1_color
= StepColour(base_color
, 85);
131 wxColor darker2_color
= StepColour(base_color
, 70);
132 wxColor darker3_color
= StepColour(base_color
, 60);
133 wxColor darker4_color
= StepColour(base_color
, 50);
134 wxColor darker5_color
= StepColour(base_color
, 40);
136 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
137 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
138 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
139 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
140 m_inactive_caption_gradient_colour
= darker1_color
;
141 m_inactive_caption_text_colour
= *wxBLACK
;
144 m_sash_brush
= toolbarbrush
;
145 m_background_brush
= toolbarbrush
;
146 m_gripper_brush
= toolbarbrush
;
148 m_sash_brush
= wxBrush(base_color
);
149 m_background_brush
= wxBrush(base_color
);
150 m_gripper_brush
= wxBrush(base_color
);
152 m_border_pen
= wxPen(darker2_color
);
153 m_gripper_pen1
= wxPen(darker5_color
);
154 m_gripper_pen2
= wxPen(darker3_color
);
155 m_gripper_pen3
= *wxWHITE_PEN
;
158 m_caption_font
= *wxSMALL_FONT
;
160 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
163 // some built in bitmaps
165 static unsigned char close_bits
[]={
166 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
167 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
168 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
170 static unsigned char close_bits
[]={
171 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
172 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
173 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
176 static unsigned char pin_bits
[]={
177 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
178 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
179 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
182 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
184 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
186 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
188 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
190 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
192 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
194 // default metric values
197 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
198 m_sash_size
= height
;
206 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
209 int wxDefaultDockArt::GetMetric(int id
)
213 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
214 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
215 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
216 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
217 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
218 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
219 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
225 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
229 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
230 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
231 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
232 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
233 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
234 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
235 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
239 wxColour
wxDefaultDockArt::GetColour(int id
)
243 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour(); break;
244 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour(); break;
245 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
; break;
246 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
; break;
247 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
; break;
248 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
; break;
249 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
; break;
250 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
; break;
251 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour(); break;
252 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour(); break;
253 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
259 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
263 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
264 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
265 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
266 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
267 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
268 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
269 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
270 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
271 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
272 case wxAUI_ART_GRIPPER_COLOUR
:
273 m_gripper_brush
.SetColour(colour
);
274 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
275 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
277 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
281 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
283 if (id
== wxAUI_ART_CAPTION_FONT
)
284 m_caption_font
= font
;
287 wxFont
wxDefaultDockArt::GetFont(int id
)
289 if (id
== wxAUI_ART_CAPTION_FONT
)
290 return m_caption_font
;
294 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
)
297 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
298 CGContextRef cgContext
;
299 #if wxMAC_USE_CORE_GRAPHICS
300 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
303 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
304 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
305 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
306 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
309 HIThemeSplitterDrawInfo drawInfo
;
310 drawInfo
.version
= 0 ;
311 drawInfo
.state
= kThemeStateActive
;
312 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
313 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
315 #if wxMAC_USE_CORE_GRAPHICS
317 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
321 dc
.SetPen(*wxTRANSPARENT_PEN
);
322 dc
.SetBrush(m_sash_brush
);
323 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
328 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
)
330 dc
.SetPen(*wxTRANSPARENT_PEN
);
332 // we have to clear first, otherwise we are drawing a light striped pattern
333 // over an already darker striped background
334 dc
.SetBrush(*wxWHITE_BRUSH
) ;
335 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
337 dc
.SetBrush(m_background_brush
);
338 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
341 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
,
344 dc
.SetPen(m_border_pen
);
345 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
348 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
350 if (pane
.IsToolbar())
352 for (i
= 0; i
< border_width
; ++i
)
354 dc
.SetPen(*wxWHITE_PEN
);
355 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
356 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
357 dc
.SetPen(m_border_pen
);
358 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
359 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
360 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
361 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
367 for (i
= 0; i
< border_width
; ++i
)
369 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
376 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
378 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
381 dc
.SetBrush(wxBrush(m_active_caption_colour
));
383 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
385 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
391 // on mac the gradients are expected to become darker from the top
393 DrawGradientRectangle(dc
, rect
,
394 m_active_caption_gradient_colour
,
395 m_active_caption_colour
,
398 DrawGradientRectangle(dc
, rect
,
399 m_active_caption_colour
,
400 m_active_caption_gradient_colour
,
406 // on mac the gradients are expected to become darker from the top
408 DrawGradientRectangle(dc
, rect
,
409 m_inactive_caption_gradient_colour
,
410 m_inactive_caption_colour
,
413 DrawGradientRectangle(dc
, rect
,
414 m_inactive_caption_colour
,
415 m_inactive_caption_gradient_colour
,
423 void wxDefaultDockArt::DrawCaption(wxDC
& dc
,
424 const wxString
& text
,
428 dc
.SetPen(*wxTRANSPARENT_PEN
);
429 dc
.SetFont(m_caption_font
);
431 DrawCaptionBackground(dc
, rect
,
432 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
434 if (pane
.state
& wxPaneInfo::optionActive
)
435 dc
.SetTextForeground(m_active_caption_text_colour
);
437 dc
.SetTextForeground(m_inactive_caption_text_colour
);
441 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
443 dc
.SetClippingRegion(rect
);
444 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
445 dc
.DestroyClippingRegion();
448 void wxDefaultDockArt::DrawGripper(wxDC
& dc
,
452 dc
.SetPen(*wxTRANSPARENT_PEN
);
453 dc
.SetBrush(m_gripper_brush
);
455 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
457 if (!pane
.HasGripperTop())
462 dc
.SetPen(m_gripper_pen1
);
463 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
464 dc
.SetPen(m_gripper_pen2
);
465 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
466 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
467 dc
.SetPen(m_gripper_pen3
);
468 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
469 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
470 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
473 if (y
> rect
.GetHeight()-5)
482 dc
.SetPen(m_gripper_pen1
);
483 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
484 dc
.SetPen(m_gripper_pen2
);
485 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
486 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
487 dc
.SetPen(m_gripper_pen3
);
488 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
489 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
490 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
493 if (x
> rect
.GetWidth()-5)
499 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
,
507 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
513 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
514 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
516 if (pane
.state
& wxPaneInfo::optionActive
)
518 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
519 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
523 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
524 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
527 // draw the background behind the button
528 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
535 case wxPaneInfo::buttonClose
:
536 if (pane
.state
& wxPaneInfo::optionActive
)
537 bmp
= m_active_close_bitmap
;
539 bmp
= m_inactive_close_bitmap
;
541 case wxPaneInfo::buttonPin
:
542 if (pane
.state
& wxPaneInfo::optionActive
)
543 bmp
= m_active_pin_bitmap
;
545 bmp
= m_inactive_pin_bitmap
;
549 // draw the button itself
550 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);