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"
39 #include "wx/graphics.h"
44 #include "wx/gtk/win_gtk.h"
45 #include "wx/renderer.h"
49 // -- wxDefaultDockArt class implementation --
51 // wxDefaultDockArt is an art provider class which does all of the drawing for
52 // wxFrameManager. This allows the library caller to customize the dock art
53 // (probably by deriving from this class), or to completely replace all drawing
54 // with custom dock art (probably by writing a new stand-alone class derived
55 // from the wxDockArt base class). The active dock art class can be set via
56 // wxFrameManager::SetDockArt()
59 // StepColour() it a utility function that simply darkens
60 // or lightens a color, based on the specified percentage
61 static wxColor
StepColour(const wxColor
& c
, int percent
)
63 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
64 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
65 (unsigned char)wxMin((g
*percent
)/100,255),
66 (unsigned char)wxMin((b
*percent
)/100,255));
69 static wxColor
LightContrastColour(const wxColour
& c
)
73 // if the color is especially dark, then
74 // make the contrast even lighter
75 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
78 return StepColour(c
, amount
);
81 // BitmapFromBits() is a utility function that creates a
82 // masked bitmap from raw bits (XBM format)
83 static wxBitmap
BitmapFromBits(const unsigned char bits
[], int w
, int h
,
84 const wxColour
& color
)
86 wxImage img
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage();
87 img
.Replace(0,0,0,123,123,123);
88 img
.Replace(255,255,255,color
.Red(),color
.Green(),color
.Blue());
89 img
.SetMaskColour(123,123,123);
94 static void DrawGradientRectangle(wxDC
& dc
,
96 const wxColour
& start_color
,
97 const wxColour
& end_color
,
100 int rd
, gd
, bd
, high
= 0;
101 rd
= end_color
.Red() - start_color
.Red();
102 gd
= end_color
.Green() - start_color
.Green();
103 bd
= end_color
.Blue() - start_color
.Blue();
105 if (direction
== wxAUI_GRADIENT_VERTICAL
)
106 high
= rect
.GetHeight()-1;
108 high
= rect
.GetWidth()-1;
110 for (int i
= 0; i
<= high
; ++i
)
112 int r
= start_color
.Red() + ((i
*rd
*100)/high
)/100;
113 int g
= start_color
.Green() + ((i
*gd
*100)/high
)/100;
114 int b
= start_color
.Blue() + ((i
*bd
*100)/high
)/100;
116 wxPen
p(wxColor((unsigned char)r
,
121 if (direction
== wxAUI_GRADIENT_VERTICAL
)
122 dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
);
124 dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
);
129 wxDefaultDockArt::wxDefaultDockArt()
132 wxBrush toolbarbrush
;
133 toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground
);
134 wxColor base_color
= toolbarbrush
.GetColour();
136 wxColor base_color
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
139 wxColor darker1_color
= StepColour(base_color
, 85);
140 wxColor darker2_color
= StepColour(base_color
, 70);
141 wxColor darker3_color
= StepColour(base_color
, 60);
142 wxColor darker4_color
= StepColour(base_color
, 50);
143 wxColor darker5_color
= StepColour(base_color
, 40);
145 m_active_caption_colour
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
));
146 m_active_caption_gradient_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
);
147 m_active_caption_text_colour
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
);
148 m_inactive_caption_colour
= StepColour(darker1_color
, 80);
149 m_inactive_caption_gradient_colour
= darker1_color
;
150 m_inactive_caption_text_colour
= *wxBLACK
;
153 m_sash_brush
= toolbarbrush
;
154 m_background_brush
= toolbarbrush
;
155 m_gripper_brush
= toolbarbrush
;
157 m_sash_brush
= wxBrush(base_color
);
158 m_background_brush
= wxBrush(base_color
);
159 m_gripper_brush
= wxBrush(base_color
);
161 m_border_pen
= wxPen(darker2_color
);
162 m_gripper_pen1
= wxPen(darker5_color
);
163 m_gripper_pen2
= wxPen(darker3_color
);
164 m_gripper_pen3
= *wxWHITE_PEN
;
167 m_caption_font
= *wxSMALL_FONT
;
169 m_caption_font
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
);
172 // some built in bitmaps
173 #if defined( __WXMAC__ )
174 static unsigned char close_bits
[]={
175 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
176 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
177 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
178 #elif defined( __WXGTK__)
179 static unsigned char close_bits
[]={
180 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
181 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
182 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
184 static unsigned char close_bits
[]={
185 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
186 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
187 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
190 static unsigned char pin_bits
[]={
191 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
192 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
193 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
196 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
198 m_inactive_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
);
200 m_inactive_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
);
202 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
);
204 m_active_close_bitmap
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
);
206 m_active_pin_bitmap
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
);
208 // default metric values
209 #if defined(__WXMAC__)
211 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight
, &height
);
212 m_sash_size
= height
;
213 #elif defined(__WXGTK__)
214 m_sash_size
= wxRendererNative::Get().GetSplitterParams(NULL
).widthSash
;
222 m_gradient_type
= wxAUI_GRADIENT_VERTICAL
;
225 int wxDefaultDockArt::GetMetric(int id
)
229 case wxAUI_ART_SASH_SIZE
: return m_sash_size
;
230 case wxAUI_ART_CAPTION_SIZE
: return m_caption_size
;
231 case wxAUI_ART_GRIPPER_SIZE
: return m_gripper_size
;
232 case wxAUI_ART_PANE_BORDER_SIZE
: return m_border_size
;
233 case wxAUI_ART_PANE_BUTTON_SIZE
: return m_button_size
;
234 case wxAUI_ART_GRADIENT_TYPE
: return m_gradient_type
;
235 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
241 void wxDefaultDockArt::SetMetric(int id
, int new_val
)
245 case wxAUI_ART_SASH_SIZE
: m_sash_size
= new_val
; break;
246 case wxAUI_ART_CAPTION_SIZE
: m_caption_size
= new_val
; break;
247 case wxAUI_ART_GRIPPER_SIZE
: m_gripper_size
= new_val
; break;
248 case wxAUI_ART_PANE_BORDER_SIZE
: m_border_size
= new_val
; break;
249 case wxAUI_ART_PANE_BUTTON_SIZE
: m_button_size
= new_val
; break;
250 case wxAUI_ART_GRADIENT_TYPE
: m_gradient_type
= new_val
; break;
251 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
255 wxColour
wxDefaultDockArt::GetColour(int id
)
259 case wxAUI_ART_BACKGROUND_COLOUR
: return m_background_brush
.GetColour();
260 case wxAUI_ART_SASH_COLOUR
: return m_sash_brush
.GetColour();
261 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: return m_inactive_caption_colour
;
262 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
;
263 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: return m_inactive_caption_text_colour
;
264 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: return m_active_caption_colour
;
265 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: return m_active_caption_gradient_colour
;
266 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: return m_active_caption_text_colour
;
267 case wxAUI_ART_BORDER_COLOUR
: return m_border_pen
.GetColour();
268 case wxAUI_ART_GRIPPER_COLOUR
: return m_gripper_brush
.GetColour();
269 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
275 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
)
279 case wxAUI_ART_BACKGROUND_COLOUR
: m_background_brush
.SetColour(colour
); break;
280 case wxAUI_ART_SASH_COLOUR
: m_sash_brush
.SetColour(colour
); break;
281 case wxAUI_ART_INACTIVE_CAPTION_COLOUR
: m_inactive_caption_colour
= colour
; break;
282 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour
= colour
; break;
283 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
: m_inactive_caption_text_colour
= colour
; break;
284 case wxAUI_ART_ACTIVE_CAPTION_COLOUR
: m_active_caption_colour
= colour
; break;
285 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
: m_active_caption_gradient_colour
= colour
; break;
286 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
: m_active_caption_text_colour
= colour
; break;
287 case wxAUI_ART_BORDER_COLOUR
: m_border_pen
.SetColour(colour
); break;
288 case wxAUI_ART_GRIPPER_COLOUR
:
289 m_gripper_brush
.SetColour(colour
);
290 m_gripper_pen1
.SetColour(StepColour(colour
, 40));
291 m_gripper_pen2
.SetColour(StepColour(colour
, 60));
293 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
297 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
)
299 if (id
== wxAUI_ART_CAPTION_FONT
)
300 m_caption_font
= font
;
303 wxFont
wxDefaultDockArt::GetFont(int id
)
305 if (id
== wxAUI_ART_CAPTION_FONT
)
306 return m_caption_font
;
310 void wxDefaultDockArt::DrawSash(wxDC
& dc
, wxWindow
*window
, int orientation
, const wxRect
& rect
)
312 #if defined(__WXMAC__)
313 HIRect splitterRect
= CGRectMake( rect
.x
, rect
.y
, rect
.width
, rect
.height
);
314 CGContextRef cgContext
;
315 #if wxMAC_USE_CORE_GRAPHICS
316 cgContext
= (CGContextRef
) dc
.GetGraphicsContext()->GetNativeContext() ;
319 GetPortBounds( (CGrafPtr
) dc
.m_macPort
, &bounds
) ;
320 QDBeginCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
321 CGContextTranslateCTM( cgContext
, 0 , bounds
.bottom
- bounds
.top
) ;
322 CGContextScaleCTM( cgContext
, 1 , -1 ) ;
325 HIThemeSplitterDrawInfo drawInfo
;
326 drawInfo
.version
= 0 ;
327 drawInfo
.state
= kThemeStateActive
;
328 drawInfo
.adornment
= kHIThemeSplitterAdornmentNone
;
329 HIThemeDrawPaneSplitter( &splitterRect
, &drawInfo
, cgContext
, kHIThemeOrientationNormal
) ;
331 #if wxMAC_USE_CORE_GRAPHICS
333 QDEndCGContext( (CGrafPtr
) dc
.m_macPort
, &cgContext
) ;
336 #elif defined(__WXGTK__)
338 GdkRectangle gdk_rect
;
339 if (orientation
== wxVERTICAL
)
343 gdk_rect
.width
= m_sash_size
;
344 gdk_rect
.height
= rect
.height
;
350 gdk_rect
.width
= rect
.width
;
351 gdk_rect
.height
= m_sash_size
;
355 if (!window
->m_wxwindow
) return;
356 if (!GTK_PIZZA(window
->m_wxwindow
)->bin_window
) return;
360 window
->m_wxwindow
->style
,
361 GTK_PIZZA(window
->m_wxwindow
)->bin_window
,
362 // flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
365 NULL
/* no clipping */,
372 (orientation
== wxVERTICAL
) ? GTK_ORIENTATION_VERTICAL
: GTK_ORIENTATION_HORIZONTAL
377 wxUnusedVar(orientation
);
378 dc
.SetPen(*wxTRANSPARENT_PEN
);
379 dc
.SetBrush(m_sash_brush
);
380 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
385 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, wxWindow
*WXUNUSED(window
), int, const wxRect
& rect
)
387 dc
.SetPen(*wxTRANSPARENT_PEN
);
389 // we have to clear first, otherwise we are drawing a light striped pattern
390 // over an already darker striped background
391 dc
.SetBrush(*wxWHITE_BRUSH
) ;
392 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
394 dc
.SetBrush(m_background_brush
);
395 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
398 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, wxWindow
*WXUNUSED(window
), const wxRect
& _rect
,
401 dc
.SetPen(m_border_pen
);
402 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
405 int i
, border_width
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
);
407 if (pane
.IsToolbar())
409 for (i
= 0; i
< border_width
; ++i
)
411 dc
.SetPen(*wxWHITE_PEN
);
412 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
);
413 dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
);
414 dc
.SetPen(m_border_pen
);
415 dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1,
416 rect
.x
+rect
.width
, rect
.y
+rect
.height
-1);
417 dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
,
418 rect
.x
+rect
.width
-1, rect
.y
+rect
.height
);
424 for (i
= 0; i
< border_width
; ++i
)
426 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
433 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
)
435 if (m_gradient_type
== wxAUI_GRADIENT_NONE
)
438 dc
.SetBrush(wxBrush(m_active_caption_colour
));
440 dc
.SetBrush(wxBrush(m_inactive_caption_colour
));
442 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
448 // on mac the gradients are expected to become darker from the top
450 DrawGradientRectangle(dc
, rect
,
451 m_active_caption_gradient_colour
,
452 m_active_caption_colour
,
455 DrawGradientRectangle(dc
, rect
,
456 m_active_caption_colour
,
457 m_active_caption_gradient_colour
,
463 // on mac the gradients are expected to become darker from the top
465 DrawGradientRectangle(dc
, rect
,
466 m_inactive_caption_gradient_colour
,
467 m_inactive_caption_colour
,
470 DrawGradientRectangle(dc
, rect
,
471 m_inactive_caption_colour
,
472 m_inactive_caption_gradient_colour
,
480 void wxDefaultDockArt::DrawCaption(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
481 const wxString
& text
,
485 dc
.SetPen(*wxTRANSPARENT_PEN
);
486 dc
.SetFont(m_caption_font
);
488 DrawCaptionBackground(dc
, rect
,
489 (pane
.state
& wxPaneInfo::optionActive
)?true:false);
491 if (pane
.state
& wxPaneInfo::optionActive
)
492 dc
.SetTextForeground(m_active_caption_text_colour
);
494 dc
.SetTextForeground(m_inactive_caption_text_colour
);
498 dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
);
500 dc
.SetClippingRegion(rect
);
501 dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1);
502 dc
.DestroyClippingRegion();
505 void wxDefaultDockArt::DrawGripper(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
509 dc
.SetPen(*wxTRANSPARENT_PEN
);
510 dc
.SetBrush(m_gripper_brush
);
512 dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
);
514 if (!pane
.HasGripperTop())
519 dc
.SetPen(m_gripper_pen1
);
520 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
);
521 dc
.SetPen(m_gripper_pen2
);
522 dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1);
523 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
);
524 dc
.SetPen(m_gripper_pen3
);
525 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1);
526 dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2);
527 dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2);
530 if (y
> rect
.GetHeight()-5)
539 dc
.SetPen(m_gripper_pen1
);
540 dc
.DrawPoint(rect
.x
+x
, rect
.y
+3);
541 dc
.SetPen(m_gripper_pen2
);
542 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3);
543 dc
.DrawPoint(rect
.x
+x
, rect
.y
+4);
544 dc
.SetPen(m_gripper_pen3
);
545 dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5);
546 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5);
547 dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4);
550 if (x
> rect
.GetWidth()-5)
556 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
, wxWindow
*WXUNUSED(window
),
564 if (button_state
== wxAUI_BUTTON_STATE_PRESSED
)
570 if (button_state
== wxAUI_BUTTON_STATE_HOVER
||
571 button_state
== wxAUI_BUTTON_STATE_PRESSED
)
573 if (pane
.state
& wxPaneInfo::optionActive
)
575 dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120)));
576 dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70)));
580 dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120)));
581 dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70)));
584 // draw the background behind the button
585 dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15);
592 case wxPaneInfo::buttonClose
:
593 if (pane
.state
& wxPaneInfo::optionActive
)
594 bmp
= m_active_close_bitmap
;
596 bmp
= m_inactive_close_bitmap
;
598 case wxPaneInfo::buttonPin
:
599 if (pane
.state
& wxPaneInfo::optionActive
)
600 bmp
= m_active_pin_bitmap
;
602 bmp
= m_inactive_pin_bitmap
;
606 // draw the button itself
607 dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);