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"
43 #include "wx/gtk/win_gtk.h"
44 #include "wx/renderer.h"
48 // -- wxDefaultDockArt class implementation --
50 // wxDefaultDockArt is an art provider class which does all of the drawing for
51 // wxFrameManager. This allows the library caller to customize the dock art
52 // (probably by deriving from this class), or to completely replace all drawing
53 // with custom dock art (probably by writing a new stand-alone class derived
54 // from the wxDockArt base class). The active dock art class can be set via
55 // wxFrameManager::SetDockArt()
58 // StepColour() it a utility function that simply darkens
59 // or lightens a color, based on the specified percentage
60 static wxColor
StepColour(const wxColor
& c
, int percent
)
62 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
63 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
64 (unsigned char)wxMin((g
*percent
)/100,255),
65 (unsigned char)wxMin((b
*percent
)/100,255));
68 static wxColor
LightContrastColour(const wxColour
& c
)
72 // if the color is especially dark, then
73 // make the contrast even lighter
74 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
77 return StepColour(c
, amount
);
80 // BitmapFromBits() is a utility function that creates a
81 // masked bitmap from raw bits (XBM format)
82 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
83 const wxColour
& color
)
85 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
86 img
.Replace(0,0,0,123,123,123);
87 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
88 img
.SetMaskColour(123,123,123);
93 static void DrawGradientRectangle(wxDC
& dc
,
95 const wxColour
& start_color
,
96 const wxColour
& end_color
,
99 int rd
, gd
, bd
, high
= 0;
100 rd
= end_color
.Red() - start_color
.Red();
101 gd
= end_color
.Green() - start_color
.Green();
102 bd
= end_color
.Blue() - start_color
.Blue();
104 if (direction
== wxAUI_GRADIENT_VERTICAL
)
105 high
= rect
.GetHeight()-1;
107 high
= rect
.GetWidth()-1;
109 for (int i
= 0; i
<= high
; ++i
)
111 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
112 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
113 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
115 wxPen
p(wxColor((unsigned char)r
,
120 if (direction
== wxAUI_GRADIENT_VERTICAL
)
121 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
123 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
128 wxDefaultDockArt::wxDefaultDockArt()
131 wxBrush toolbarbrush
;
132 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
133 wxColor base_color
= toolbarbrush
.GetColour();
135 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
138 wxColor darker1_color
= StepColour(base_color
, 85);
139 wxColor darker2_color
= StepColour(base_color
, 70);
140 wxColor darker3_color
= StepColour(base_color
, 60);
141 wxColor darker4_color
= StepColour(base_color
, 50);
142 wxColor darker5_color
= StepColour(base_color
, 40);
144 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
145 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
146 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
147 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
148 m_inactive_caption_gradient_colour
= darker1_color
;
149 m_inactive_caption_text_colour
= *wxBLACK
;
152 m_sash_brush
= toolbarbrush
;
153 m_background_brush
= toolbarbrush
;
154 m_gripper_brush
= toolbarbrush
;
156 m_sash_brush
= wxBrush(base_color
);
157 m_background_brush
= wxBrush(base_color
);
158 m_gripper_brush
= wxBrush(base_color
);
160 m_border_pen
= wxPen(darker2_color
);
161 m_gripper_pen1
= wxPen(darker5_color
);
162 m_gripper_pen2
= wxPen(darker3_color
);
163 m_gripper_pen3
= *wxWHITE_PEN
;
166 m_caption_font
= *wxSMALL_FONT
;
168 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
171 // some built in bitmaps
172 #if defined( __WXMAC__ )
173 static unsigned char close_bits
[]={
174 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
175 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
176 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
177 #elif defined( __WXGTK__)
178 static unsigned char close_bits
[]={
179 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
180 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
181 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
183 static unsigned char close_bits
[]={
184 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
185 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
186 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
189 static unsigned char pin_bits
[]={
190 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
191 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
192 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
195 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
197 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
199 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
201 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
203 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
205 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
207 // default metric values
208 #if defined(__WXMAC__)
210 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
211 m_sash_size
= height
;
212 #elif defined(__WXGTK__)
213 m_sash_size
= wxRendererNative::Get().GetSplitterParams(NULL
).widthSash
;
221 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
224 int wxDefaultDockArt::GetMetric(int id
)
228 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
229 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
230 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
231 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
232 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
233 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
234 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
240 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
244 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
245 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
246 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
247 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
248 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
249 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
250 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
254 wxColour
wxDefaultDockArt::GetColour(int id
)
258 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour();
259 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour();
260 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
;
261 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
;
262 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
;
263 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
;
264 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
;
265 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
;
266 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour();
267 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour();
268 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
274 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
278 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
279 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
280 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
281 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
282 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
283 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
284 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
285 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
286 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
287 case wxAUI_ART_GRIPPER_COLOUR
:
288 m_gripper_brush
.SetColour(colour
);
289 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
290 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
292 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
296 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
298 if (id
== wxAUI_ART_CAPTION_FONT
)
299 m_caption_font
= font
;
302 wxFont
wxDefaultDockArt::GetFont(int id
)
304 if (id
== wxAUI_ART_CAPTION_FONT
)
305 return m_caption_font
;
309 void wxDefaultDockArt::DrawSash(wxDC
& dc
, wxWindow
*window
, int orientation
, const wxRect
& rect
)
311 #if defined(__WXMAC__)
312 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
313 CGContextRef cgContext
;
314 #if wxMAC_USE_CORE_GRAPHICS
315 cgContext
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ;
318 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
319 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
320 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
321 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
324 HIThemeSplitterDrawInfo drawInfo
;
325 drawInfo
.version
= 0 ;
326 drawInfo
.state
= kThemeStateActive
;
327 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
328 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
330 #if wxMAC_USE_CORE_GRAPHICS
332 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
335 #elif defined(__WXGTK__)
337 GdkRectangle gdk_rect
;
338 if (orientation
== wxVERTICAL
)
342 gdk_rect
.width
= m_sash_size
;
343 gdk_rect
.height
= rect
.height
;
349 gdk_rect
.width
= rect
.width
;
350 gdk_rect
.height
= m_sash_size
;
354 if (!window
->m_wxwindow
) return;
355 if (!GTK_PIZZA(window
->m_wxwindow
)->bin_window
) return;
359 window
->m_wxwindow
->style
,
360 GTK_PIZZA(window
->m_wxwindow
)->bin_window
,
361 // flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
364 NULL
/* no clipping */,
371 (orientation
== wxVERTICAL
) ? GTK_ORIENTATION_VERTICAL
: GTK_ORIENTATION_HORIZONTAL
375 dc
.SetPen(*wxTRANSPARENT_PEN
);
376 dc
.SetBrush(m_sash_brush
);
377 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
382 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, wxWindow
*window
, int, const wxRect
& rect
)
384 dc
.SetPen(*wxTRANSPARENT_PEN
);
386 // we have to clear first, otherwise we are drawing a light striped pattern
387 // over an already darker striped background
388 dc
.SetBrush(*wxWHITE_BRUSH
) ;
389 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
391 dc
.SetBrush(m_background_brush
);
392 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
395 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, wxWindow
*window
, const wxRect
& _rect
,
398 dc
.SetPen(m_border_pen
);
399 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
402 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
404 if (pane
.IsToolbar())
406 for (i
= 0; i
< border_width
; ++i
)
408 dc
.SetPen(*wxWHITE_PEN
);
409 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
410 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
411 dc
.SetPen(m_border_pen
);
412 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
413 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
414 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
415 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
421 for (i
= 0; i
< border_width
; ++i
)
423 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
430 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
432 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
435 dc
.SetBrush(wxBrush(m_active_caption_colour
));
437 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
439 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
445 // on mac the gradients are expected to become darker from the top
447 DrawGradientRectangle(dc
, rect
,
448 m_active_caption_gradient_colour
,
449 m_active_caption_colour
,
452 DrawGradientRectangle(dc
, rect
,
453 m_active_caption_colour
,
454 m_active_caption_gradient_colour
,
460 // on mac the gradients are expected to become darker from the top
462 DrawGradientRectangle(dc
, rect
,
463 m_inactive_caption_gradient_colour
,
464 m_inactive_caption_colour
,
467 DrawGradientRectangle(dc
, rect
,
468 m_inactive_caption_colour
,
469 m_inactive_caption_gradient_colour
,
477 void wxDefaultDockArt::DrawCaption(wxDC
& dc
, wxWindow
*window
,
478 const wxString
& text
,
482 dc
.SetPen(*wxTRANSPARENT_PEN
);
483 dc
.SetFont(m_caption_font
);
485 DrawCaptionBackground(dc
, rect
,
486 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
488 if (pane
.state
& wxPaneInfo::optionActive
)
489 dc
.SetTextForeground(m_active_caption_text_colour
);
491 dc
.SetTextForeground(m_inactive_caption_text_colour
);
495 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
497 dc
.SetClippingRegion(rect
);
498 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
499 dc
.DestroyClippingRegion();
502 void wxDefaultDockArt::DrawGripper(wxDC
& dc
, wxWindow
*window
,
506 dc
.SetPen(*wxTRANSPARENT_PEN
);
507 dc
.SetBrush(m_gripper_brush
);
509 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
511 if (!pane
.HasGripperTop())
516 dc
.SetPen(m_gripper_pen1
);
517 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
518 dc
.SetPen(m_gripper_pen2
);
519 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
520 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
521 dc
.SetPen(m_gripper_pen3
);
522 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
523 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
524 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
527 if (y
> rect
.GetHeight()-5)
536 dc
.SetPen(m_gripper_pen1
);
537 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
538 dc
.SetPen(m_gripper_pen2
);
539 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
540 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
541 dc
.SetPen(m_gripper_pen3
);
542 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
543 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
544 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
547 if (x
> rect
.GetWidth()-5)
553 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
, wxWindow
*window
,
561 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
567 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
568 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
570 if (pane
.state
& wxPaneInfo::optionActive
)
572 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
573 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
577 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
578 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
581 // draw the background behind the button
582 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
589 case wxPaneInfo::buttonClose
:
590 if (pane
.state
& wxPaneInfo::optionActive
)
591 bmp
= m_active_close_bitmap
;
593 bmp
= m_inactive_close_bitmap
;
595 case wxPaneInfo::buttonPin
:
596 if (pane
.state
& wxPaneInfo::optionActive
)
597 bmp
= m_active_pin_bitmap
;
599 bmp
= m_inactive_pin_bitmap
;
603 // draw the button itself
604 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);