]> git.saurik.com Git - wxWidgets.git/blob - src/aui/dockart.cpp
68c5bb373b2b2a3c3fe12f670ad6af7b76a12477
[wxWidgets.git] / src / aui / dockart.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: dockart.cpp
3 // Purpose: wxaui: wx advanced user interface - docking window manager
4 // Author: Benjamin I. Williams
5 // Modified by:
6 // Created: 2005-05-17
7 // RCS-ID:
8 // Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
9 // Licence: wxWindows Library Licence, Version 3.1
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #if wxUSE_AUI
27
28 #include "wx/image.h"
29 #include "wx/dcclient.h"
30 #include "wx/settings.h"
31 #include "wx/aui/framemanager.h"
32 #include "wx/aui/dockart.h"
33
34 #ifndef WX_PRECOMP
35 // #include "wx/log.h"
36 #endif
37
38 // -- wxDefaultDockArt class implementation --
39
40 // wxDefaultDockArt is an art provider class which does all of the drawing for
41 // wxFrameManager. This allows the library caller to customize the dock art
42 // (probably by deriving from this class), or to completely replace all drawing
43 // with custom dock art (probably by writing a new stand-alone class derived
44 // from the wxDockArt base class). The active dock art class can be set via
45 // wxFrameManager::SetDockArt()
46
47
48 // StepColour() it a utility function that simply darkens
49 // or lightens a color, based on the specified percentage
50 static wxColor StepColour(const wxColor& c, int percent)
51 {
52 int r = c.Red(), g = c.Green(), b = c.Blue();
53 return wxColour(wxMin((r*percent)/100,255),
54 wxMin((g*percent)/100,255),
55 wxMin((b*percent)/100,255));
56 }
57
58 static wxColor LightContrastColour(const wxColour& c)
59 {
60 int amount = 120;
61
62 // if the color is especially dark, then
63 // make the contrast even lighter
64 if (c.Red() < 128 && c.Green() < 128 && c.Blue() < 128)
65 amount = 160;
66
67 return StepColour(c, amount);
68 }
69
70 // BitmapFromBits() is a utility function that creates a
71 // masked bitmap from raw bits (XBM format)
72 static wxBitmap BitmapFromBits(const unsigned char bits[], int w, int h,
73 const wxColour& color)
74 {
75 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
76 img.Replace(255,255,255,123,123,123);
77 img.Replace(0,0,0,color.Red(),color.Green(),color.Blue());
78 img.SetMaskColour(123,123,123);
79 return wxBitmap(img);
80 }
81
82
83 static void DrawGradientRectangle(wxDC& dc,
84 const wxRect& rect,
85 const wxColour& start_color,
86 const wxColour& end_color,
87 int direction)
88 {
89 int rd, gd, bd, high = 0;
90 rd = end_color.Red() - start_color.Red();
91 gd = end_color.Green() - start_color.Green();
92 bd = end_color.Blue() - start_color.Blue();
93
94 if (direction == wxAUI_GRADIENT_VERTICAL)
95 high = rect.GetHeight()-1;
96 else
97 high = rect.GetWidth()-1;
98
99 for (int i = 0; i <= high; ++i)
100 {
101 int r = start_color.Red() + ((i*rd*100)/high)/100;
102 int g = start_color.Green() + ((i*gd*100)/high)/100;
103 int b = start_color.Blue() + ((i*bd*100)/high)/100;
104
105 wxPen p(wxColor(r,g,b));
106 dc.SetPen(p);
107
108 if (direction == wxAUI_GRADIENT_VERTICAL)
109 dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i);
110 else
111 dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height);
112 }
113
114 }
115
116 wxDefaultDockArt::wxDefaultDockArt()
117 {
118 #ifdef __WXMAC__
119 wxBrush toolbarbrush;
120 toolbarbrush.MacSetTheme( kThemeBrushToolbarBackground );
121 wxColor base_color = toolbarbrush.GetColour();
122 #else
123 wxColor base_color = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
124 #endif
125
126 wxColor darker1_color = StepColour(base_color, 85);
127 wxColor darker2_color = StepColour(base_color, 70);
128 wxColor darker3_color = StepColour(base_color, 60);
129 wxColor darker4_color = StepColour(base_color, 50);
130 wxColor darker5_color = StepColour(base_color, 40);
131
132 m_active_caption_colour = LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
133 m_active_caption_gradient_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
134 m_active_caption_text_colour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
135 m_inactive_caption_colour = StepColour(darker1_color, 80);
136 m_inactive_caption_gradient_colour = darker1_color;
137 m_inactive_caption_text_colour = *wxBLACK;
138
139 #ifdef __WXMAC__
140 m_sash_brush = toolbarbrush;
141 m_background_brush = toolbarbrush;
142 m_gripper_brush = toolbarbrush;
143 #else
144 m_sash_brush = wxBrush(base_color);
145 m_background_brush = wxBrush(base_color);
146 m_gripper_brush = wxBrush(base_color);
147 #endif
148 m_border_pen = wxPen(darker2_color);
149 m_gripper_pen1 = wxPen(darker5_color);
150 m_gripper_pen2 = wxPen(darker3_color);
151 m_gripper_pen3 = *wxWHITE_PEN;
152
153 #ifdef __WXMAC__
154 m_caption_font = *wxSMALL_FONT;
155 #else
156 m_caption_font = wxFont(8, wxDEFAULT, wxNORMAL, wxNORMAL, FALSE);
157 #endif
158
159 // some built in bitmaps
160 #ifdef __WXMAC__
161 static unsigned char close_bits[]={
162 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
163 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
164 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
165 #else
166 static unsigned char close_bits[]={
167 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9,
168 0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb,
169 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
170 #endif
171
172 static unsigned char pin_bits[]={
173 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
174 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
175 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
176
177 #ifdef __WXMAC__
178 m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE);
179 #else
180 m_inactive_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_inactive_caption_text_colour);
181 #endif
182 m_inactive_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_inactive_caption_text_colour);
183 #ifdef __WXMAC__
184 m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, *wxWHITE );
185 #else
186 m_active_close_bitmap = BitmapFromBits(close_bits, 16, 16, m_active_caption_text_colour);
187 #endif
188 m_active_pin_bitmap = BitmapFromBits(pin_bits, 16, 16, m_active_caption_text_colour);
189
190 // default metric values
191 #ifdef __WXMAC__
192 SInt32 height;
193 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
194 m_sash_size = height;
195 #else
196 m_sash_size = 4;
197 #endif
198 m_caption_size = 17;
199 m_border_size = 1;
200 m_button_size = 14;
201 m_gripper_size = 9;
202 m_gradient_type = wxAUI_GRADIENT_VERTICAL;
203 }
204
205 int wxDefaultDockArt::GetMetric(int id)
206 {
207 switch (id)
208 {
209 case wxAUI_ART_SASH_SIZE: return m_sash_size;
210 case wxAUI_ART_CAPTION_SIZE: return m_caption_size;
211 case wxAUI_ART_GRIPPER_SIZE: return m_gripper_size;
212 case wxAUI_ART_PANE_BORDER_SIZE: return m_border_size;
213 case wxAUI_ART_PANE_BUTTON_SIZE: return m_button_size;
214 case wxAUI_ART_GRADIENT_TYPE: return m_gradient_type;
215 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
216 }
217
218 return 0;
219 }
220
221 void wxDefaultDockArt::SetMetric(int id, int new_val)
222 {
223 switch (id)
224 {
225 case wxAUI_ART_SASH_SIZE: m_sash_size = new_val; break;
226 case wxAUI_ART_CAPTION_SIZE: m_caption_size = new_val; break;
227 case wxAUI_ART_GRIPPER_SIZE: m_gripper_size = new_val; break;
228 case wxAUI_ART_PANE_BORDER_SIZE: m_border_size = new_val; break;
229 case wxAUI_ART_PANE_BUTTON_SIZE: m_button_size = new_val; break;
230 case wxAUI_ART_GRADIENT_TYPE: m_gradient_type = new_val; break;
231 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
232 }
233 }
234
235 wxColour wxDefaultDockArt::GetColour(int id)
236 {
237 switch (id)
238 {
239 case wxAUI_ART_BACKGROUND_COLOUR: return m_background_brush.GetColour(); break;
240 case wxAUI_ART_SASH_COLOUR: return m_sash_brush.GetColour(); break;
241 case wxAUI_ART_INACTIVE_CAPTION_COLOUR: return m_inactive_caption_colour; break;
242 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: return m_inactive_caption_gradient_colour; break;
243 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: return m_inactive_caption_text_colour; break;
244 case wxAUI_ART_ACTIVE_CAPTION_COLOUR: return m_active_caption_colour; break;
245 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: return m_active_caption_gradient_colour; break;
246 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: return m_active_caption_text_colour; break;
247 case wxAUI_ART_BORDER_COLOUR: return m_border_pen.GetColour(); break;
248 case wxAUI_ART_GRIPPER_COLOUR: return m_gripper_brush.GetColour(); break;
249 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
250 }
251
252 return wxColour();
253 }
254
255 void wxDefaultDockArt::SetColour(int id, const wxColor& colour)
256 {
257 switch (id)
258 {
259 case wxAUI_ART_BACKGROUND_COLOUR: m_background_brush.SetColour(colour); break;
260 case wxAUI_ART_SASH_COLOUR: m_sash_brush.SetColour(colour); break;
261 case wxAUI_ART_INACTIVE_CAPTION_COLOUR: m_inactive_caption_colour = colour; break;
262 case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR: m_inactive_caption_gradient_colour = colour; break;
263 case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR: m_inactive_caption_text_colour = colour; break;
264 case wxAUI_ART_ACTIVE_CAPTION_COLOUR: m_active_caption_colour = colour; break;
265 case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR: m_active_caption_gradient_colour = colour; break;
266 case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR: m_active_caption_text_colour = colour; break;
267 case wxAUI_ART_BORDER_COLOUR: m_border_pen.SetColour(colour); break;
268 case wxAUI_ART_GRIPPER_COLOUR:
269 m_gripper_brush.SetColour(colour);
270 m_gripper_pen1.SetColour(StepColour(colour, 40));
271 m_gripper_pen2.SetColour(StepColour(colour, 60));
272 break;
273 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
274 }
275 }
276
277 void wxDefaultDockArt::SetFont(int id, const wxFont& font)
278 {
279 if (id == wxAUI_ART_CAPTION_FONT)
280 m_caption_font = font;
281 }
282
283 wxFont wxDefaultDockArt::GetFont(int id)
284 {
285 if (id == wxAUI_ART_CAPTION_FONT)
286 return m_caption_font;
287 return wxNullFont;
288 }
289
290 void wxDefaultDockArt::DrawSash(wxDC& dc, int, const wxRect& rect)
291 {
292 #ifdef __WXMAC__
293 HIRect splitterRect = CGRectMake( rect.x , rect.y , rect.width , rect.height );
294 CGContextRef cgContext ;
295 #if wxMAC_USE_CORE_GRAPHICS
296 cgContext = ((wxMacCGContext*)(dc.GetGraphicContext()))->GetNativeContext() ;
297 #else
298 Rect bounds ;
299 GetPortBounds( (CGrafPtr) dc.m_macPort , &bounds ) ;
300 QDBeginCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
301 CGContextTranslateCTM( cgContext , 0 , bounds.bottom - bounds.top ) ;
302 CGContextScaleCTM( cgContext , 1 , -1 ) ;
303 #endif
304
305 HIThemeSplitterDrawInfo drawInfo ;
306 drawInfo.version = 0 ;
307 drawInfo.state = kThemeStateActive ;
308 drawInfo.adornment = kHIThemeSplitterAdornmentNone ;
309 HIThemeDrawPaneSplitter( &splitterRect , &drawInfo , cgContext , kHIThemeOrientationNormal ) ;
310
311 #if wxMAC_USE_CORE_GRAPHICS
312 #else
313 QDEndCGContext( (CGrafPtr) dc.m_macPort , &cgContext ) ;
314 #endif
315
316 #else
317 dc.SetPen(*wxTRANSPARENT_PEN);
318 dc.SetBrush(m_sash_brush);
319 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
320 #endif
321 }
322
323
324 void wxDefaultDockArt::DrawBackground(wxDC& dc, int, const wxRect& rect)
325 {
326 dc.SetPen(*wxTRANSPARENT_PEN);
327 #ifdef __WXMAC__
328 // we have to clear first, otherwise we are drawing a light striped pattern
329 // over an already darker striped background
330 dc.SetBrush(*wxWHITE_BRUSH) ;
331 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
332 #endif
333 dc.SetBrush(m_background_brush);
334 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
335 }
336
337 void wxDefaultDockArt::DrawBorder(wxDC& dc, const wxRect& _rect,
338 wxPaneInfo& pane)
339 {
340 dc.SetPen(m_border_pen);
341 dc.SetBrush(*wxTRANSPARENT_BRUSH);
342
343 wxRect rect = _rect;
344 int i, border_width = GetMetric(wxAUI_ART_PANE_BORDER_SIZE);
345
346 if (pane.IsToolbar())
347 {
348 for (i = 0; i < border_width; ++i)
349 {
350 dc.SetPen(*wxWHITE_PEN);
351 dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
352 dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height);
353 dc.SetPen(m_border_pen);
354 dc.DrawLine(rect.x, rect.y+rect.height-1,
355 rect.x+rect.width, rect.y+rect.height-1);
356 dc.DrawLine(rect.x+rect.width-1, rect.y,
357 rect.x+rect.width-1, rect.y+rect.height);
358 rect.Deflate(1);
359 }
360 }
361 else
362 {
363 for (i = 0; i < border_width; ++i)
364 {
365 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
366 rect.Deflate(1);
367 }
368 }
369 }
370
371
372 void wxDefaultDockArt::DrawCaptionBackground(wxDC& dc, const wxRect& rect, bool active)
373 {
374 if (m_gradient_type == wxAUI_GRADIENT_NONE)
375 {
376 if (active)
377 dc.SetBrush(wxBrush(m_active_caption_colour));
378 else
379 dc.SetBrush(wxBrush(m_inactive_caption_colour));
380
381 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
382 }
383 else
384 {
385 if (active)
386 {
387 // on mac the gradients are expected to become darker from the top
388 #ifdef __WXMAC__
389 DrawGradientRectangle(dc, rect,
390 m_active_caption_gradient_colour,
391 m_active_caption_colour,
392 m_gradient_type);
393 #else
394 DrawGradientRectangle(dc, rect,
395 m_active_caption_colour,
396 m_active_caption_gradient_colour,
397 m_gradient_type);
398 #endif
399 }
400 else
401 {
402 // on mac the gradients are expected to become darker from the top
403 #ifdef __WXMAC__
404 DrawGradientRectangle(dc, rect,
405 m_inactive_caption_gradient_colour,
406 m_inactive_caption_colour,
407 m_gradient_type);
408 #else
409 DrawGradientRectangle(dc, rect,
410 m_inactive_caption_colour,
411 m_inactive_caption_gradient_colour,
412 m_gradient_type);
413 #endif
414 }
415 }
416 }
417
418
419 void wxDefaultDockArt::DrawCaption(wxDC& dc,
420 const wxString& text,
421 const wxRect& rect,
422 wxPaneInfo& pane)
423 {
424 dc.SetPen(*wxTRANSPARENT_PEN);
425 dc.SetFont(m_caption_font);
426
427 DrawCaptionBackground(dc, rect,
428 (pane.state & wxPaneInfo::optionActive)?true:false);
429
430 if (pane.state & wxPaneInfo::optionActive)
431 dc.SetTextForeground(m_active_caption_text_colour);
432 else
433 dc.SetTextForeground(m_inactive_caption_text_colour);
434
435
436 wxCoord w,h;
437 dc.GetTextExtent(wxT("ABCDEFHXfgkj"), &w, &h);
438
439 dc.SetClippingRegion(rect);
440 dc.DrawText(text, rect.x+3, rect.y+(rect.height/2)-(h/2)-1);
441 dc.DestroyClippingRegion();
442 }
443
444 void wxDefaultDockArt::DrawGripper(wxDC& dc,
445 const wxRect& rect,
446 wxPaneInfo& pane)
447 {
448 dc.SetPen(*wxTRANSPARENT_PEN);
449 dc.SetBrush(m_gripper_brush);
450
451 dc.DrawRectangle(rect.x, rect.y, rect.width,rect.height);
452
453 if (!pane.HasGripperTop())
454 {
455 int y = 5;
456 while (1)
457 {
458 dc.SetPen(m_gripper_pen1);
459 dc.DrawPoint(rect.x+3, rect.y+y);
460 dc.SetPen(m_gripper_pen2);
461 dc.DrawPoint(rect.x+3, rect.y+y+1);
462 dc.DrawPoint(rect.x+4, rect.y+y);
463 dc.SetPen(m_gripper_pen3);
464 dc.DrawPoint(rect.x+5, rect.y+y+1);
465 dc.DrawPoint(rect.x+5, rect.y+y+2);
466 dc.DrawPoint(rect.x+4, rect.y+y+2);
467
468 y += 4;
469 if (y > rect.GetHeight()-5)
470 break;
471 }
472 }
473 else
474 {
475 int x = 5;
476 while (1)
477 {
478 dc.SetPen(m_gripper_pen1);
479 dc.DrawPoint(rect.x+x, rect.y+3);
480 dc.SetPen(m_gripper_pen2);
481 dc.DrawPoint(rect.x+x+1, rect.y+3);
482 dc.DrawPoint(rect.x+x, rect.y+4);
483 dc.SetPen(m_gripper_pen3);
484 dc.DrawPoint(rect.x+x+1, rect.y+5);
485 dc.DrawPoint(rect.x+x+2, rect.y+5);
486 dc.DrawPoint(rect.x+x+2, rect.y+4);
487
488 x += 4;
489 if (x > rect.GetWidth()-5)
490 break;
491 }
492 }
493 }
494
495 void wxDefaultDockArt::DrawPaneButton(wxDC& dc,
496 int button,
497 int button_state,
498 const wxRect& _rect,
499 wxPaneInfo& pane)
500 {
501 wxRect rect = _rect;
502
503 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
504 {
505 rect.x++;
506 rect.y++;
507 }
508
509 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
510 button_state == wxAUI_BUTTON_STATE_PRESSED)
511 {
512 if (pane.state & wxPaneInfo::optionActive)
513 {
514 dc.SetBrush(wxBrush(StepColour(m_active_caption_colour, 120)));
515 dc.SetPen(wxPen(StepColour(m_active_caption_colour, 70)));
516 }
517 else
518 {
519 dc.SetBrush(wxBrush(StepColour(m_inactive_caption_colour, 120)));
520 dc.SetPen(wxPen(StepColour(m_inactive_caption_colour, 70)));
521 }
522
523 // draw the background behind the button
524 dc.DrawRectangle(rect.x, rect.y, 15, 15);
525 }
526
527 wxBitmap bmp;
528 switch (button)
529 {
530 default:
531 case wxPaneInfo::buttonClose:
532 if (pane.state & wxPaneInfo::optionActive)
533 bmp = m_active_close_bitmap;
534 else
535 bmp = m_inactive_close_bitmap;
536 break;
537 case wxPaneInfo::buttonPin:
538 if (pane.state & wxPaneInfo::optionActive)
539 bmp = m_active_pin_bitmap;
540 else
541 bmp = m_inactive_pin_bitmap;
542 break;
543 }
544
545 // draw the button itself
546 dc.DrawBitmap(bmp, rect.x, rect.y, true);
547 }
548
549
550 #endif // wxUSE_AUI