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
376 wxUnusedVar(orientation
);
377 dc
.SetPen(*wxTRANSPARENT_PEN
);
378 dc
.SetBrush(m_sash_brush
);
379 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
384 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, wxWindow
*WXUNUSED(window
), int, const wxRect
& rect
)
386 dc
.SetPen(*wxTRANSPARENT_PEN
);
388 // we have to clear first, otherwise we are drawing a light striped pattern
389 // over an already darker striped background
390 dc
.SetBrush(*wxWHITE_BRUSH
) ;
391 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
393 dc
.SetBrush(m_background_brush
);
394 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
397 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, wxWindow
*WXUNUSED(window
), const wxRect
& _rect
,
400 dc
.SetPen(m_border_pen
);
401 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
404 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
406 if (pane
.IsToolbar())
408 for (i
= 0; i
< border_width
; ++i
)
410 dc
.SetPen(*wxWHITE_PEN
);
411 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
412 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
413 dc
.SetPen(m_border_pen
);
414 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
415 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
416 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
417 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
423 for (i
= 0; i
< border_width
; ++i
)
425 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
432 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
434 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
437 dc
.SetBrush(wxBrush(m_active_caption_colour
));
439 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
441 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
447 // on mac the gradients are expected to become darker from the top
449 DrawGradientRectangle(dc
, rect
,
450 m_active_caption_gradient_colour
,
451 m_active_caption_colour
,
454 DrawGradientRectangle(dc
, rect
,
455 m_active_caption_colour
,
456 m_active_caption_gradient_colour
,
462 // on mac the gradients are expected to become darker from the top
464 DrawGradientRectangle(dc
, rect
,
465 m_inactive_caption_gradient_colour
,
466 m_inactive_caption_colour
,
469 DrawGradientRectangle(dc
, rect
,
470 m_inactive_caption_colour
,
471 m_inactive_caption_gradient_colour
,
479 void wxDefaultDockArt::DrawCaption(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
480 const wxString
& text
,
484 dc
.SetPen(*wxTRANSPARENT_PEN
);
485 dc
.SetFont(m_caption_font
);
487 DrawCaptionBackground(dc
, rect
,
488 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
490 if (pane
.state
& wxPaneInfo::optionActive
)
491 dc
.SetTextForeground(m_active_caption_text_colour
);
493 dc
.SetTextForeground(m_inactive_caption_text_colour
);
497 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
499 dc
.SetClippingRegion(rect
);
500 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
501 dc
.DestroyClippingRegion();
504 void wxDefaultDockArt::DrawGripper(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
508 dc
.SetPen(*wxTRANSPARENT_PEN
);
509 dc
.SetBrush(m_gripper_brush
);
511 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
513 if (!pane
.HasGripperTop())
518 dc
.SetPen(m_gripper_pen1
);
519 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
520 dc
.SetPen(m_gripper_pen2
);
521 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
522 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
523 dc
.SetPen(m_gripper_pen3
);
524 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
525 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
526 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
529 if (y
> rect
.GetHeight()-5)
538 dc
.SetPen(m_gripper_pen1
);
539 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
540 dc
.SetPen(m_gripper_pen2
);
541 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
542 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
543 dc
.SetPen(m_gripper_pen3
);
544 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
545 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
546 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
549 if (x
> rect
.GetWidth()-5)
555 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
563 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
569 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
570 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
572 if (pane
.state
& wxPaneInfo::optionActive
)
574 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
575 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
579 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
580 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
583 // draw the background behind the button
584 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
591 case wxPaneInfo::buttonClose
:
592 if (pane
.state
& wxPaneInfo::optionActive
)
593 bmp
= m_active_close_bitmap
;
595 bmp
= m_inactive_close_bitmap
;
597 case wxPaneInfo::buttonPin
:
598 if (pane
.state
& wxPaneInfo::optionActive
)
599 bmp
= m_active_pin_bitmap
;
601 bmp
= m_inactive_pin_bitmap
;
605 // draw the button itself
606 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);