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