1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/aui/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 // Copyright: (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved
8 // Licence: wxWindows Library Licence, Version 3.1
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 #include "wx/wxprec.h"
20
21
22 #if wxUSE_AUI
23
24 #include "wx/aui/framemanager.h"
25 #include "wx/aui/dockart.h"
26 #include "wx/aui/auibook.h"
27 #include "wx/aui/tabart.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/settings.h"
31 #include "wx/dcclient.h"
32 #include "wx/image.h"
33 #endif
34
35 #ifdef __WXMAC__
36 #include "wx/osx/private.h"
37 #include "wx/graphics.h"
38 #include "wx/dcgraph.h"
39 #endif
40
41 #ifdef __WXGTK__
42 #include "wx/renderer.h"
43 #ifdef __WXGTK20__
44 #include "wx/gtk/private/wrapgtk.h"
45 #else
46 #include <gtk/gtk.h>
47 #define gtk_widget_is_drawable GTK_WIDGET_DRAWABLE
48 #endif
49 #ifdef __WXGTK3__
50 #include "wx/graphics.h"
51 #include "wx/gtk/private.h"
52 #endif
53 #endif
54
55 #include <math.h>
56
wxAuiLightContrastColour(const wxColour & c)57 wxColor wxAuiLightContrastColour(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 c.ChangeLightness(amount);
67 }
68
wxAuiGetSRGB(float r)69 inline float wxAuiGetSRGB(float r) {
70 return r <= 0.03928f ? r / 12.92f : std::pow((r + 0.055f) / 1.055f, 2.4f);
71 }
72
wxAuiGetRelativeLuminance(const wxColour & c)73 float wxAuiGetRelativeLuminance(const wxColour& c)
74 {
75 // based on https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
76 return
77 0.2126f * wxAuiGetSRGB(c.Red() / 255.0f) +
78 0.7152f * wxAuiGetSRGB(c.Green() / 255.0f) +
79 0.0722f * wxAuiGetSRGB(c.Blue() / 255.0f);
80 }
81
wxAuiGetColourContrast(const wxColour & c1,const wxColour & c2)82 float wxAuiGetColourContrast(const wxColour& c1, const wxColour& c2)
83 {
84 // based on https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html
85 float L1 = wxAuiGetRelativeLuminance(c1);
86 float L2 = wxAuiGetRelativeLuminance(c2);
87 return L1 > L2 ? (L1 + 0.05f) / (L2 + 0.05f) : (L2 + 0.05f) / (L1 + 0.05f);
88 }
89
90 // wxAuiBitmapFromBits() is a utility function that creates a
91 // masked bitmap from raw bits (XBM format)
wxAuiBitmapFromBits(const unsigned char bits[],int w,int h,const wxColour & color)92 wxBitmap wxAuiBitmapFromBits(const unsigned char bits[], int w, int h,
93 const wxColour& color)
94 {
95 wxImage img = wxBitmap((const char*)bits, w, h).ConvertToImage();
96 if (color.Alpha() == wxALPHA_OPAQUE)
97 {
98 img.Replace(0,0,0,123,123,123);
99 img.Replace(255,255,255,color.Red(),color.Green(),color.Blue());
100 img.SetMaskColour(123,123,123);
101 }
102 else
103 {
104 img.InitAlpha();
105 const int newr = color.Red();
106 const int newg = color.Green();
107 const int newb = color.Blue();
108 const int newa = color.Alpha();
109 for (int x = 0; x < w; x++)
110 {
111 for (int y = 0; y < h; y++)
112 {
113 int r = img.GetRed(x, y);
114 int g = img.GetGreen(x, y);
115 int b = img.GetBlue(x, y);
116 if (r == 0 && g == 0 && b == 0)
117 {
118 img.SetAlpha(x, y, wxALPHA_TRANSPARENT);
119 }
120 else
121 {
122 img.SetRGB(x, y, newr, newg, newb);
123 img.SetAlpha(x, y, newa);
124 }
125 }
126 }
127 }
128 return wxBitmap(img);
129 }
130
131 // A utility function to scales a bitmap in place for use at the given scale
132 // factor.
wxAuiScaleBitmap(wxBitmap & bmp,double scale)133 void wxAuiScaleBitmap(wxBitmap& bmp, double scale)
134 {
135 #if wxUSE_IMAGE && !defined(__WXGTK3__) && !defined(__WXMAC__)
136 // scale to a close round number to improve quality
137 scale = floor(scale + 0.25);
138 if (scale > 1.0 && !(bmp.GetScaleFactor() > 1.0))
139 {
140 wxImage img = bmp.ConvertToImage();
141 img.Rescale(bmp.GetWidth()*scale, bmp.GetHeight()*scale,
142 wxIMAGE_QUALITY_BOX_AVERAGE);
143 bmp = wxBitmap(img);
144 }
145 #else
146 wxUnusedVar(bmp);
147 wxUnusedVar(scale);
148 #endif // wxUSE_IMAGE
149 }
150
DrawGradientRectangle(wxDC & dc,const wxRect & rect,const wxColour & start_color,const wxColour & end_color,int direction)151 static void DrawGradientRectangle(wxDC& dc,
152 const wxRect& rect,
153 const wxColour& start_color,
154 const wxColour& end_color,
155 int direction)
156 {
157 int rd, gd, bd, high = 0;
158 rd = end_color.Red() - start_color.Red();
159 gd = end_color.Green() - start_color.Green();
160 bd = end_color.Blue() - start_color.Blue();
161
162 if (direction == wxAUI_GRADIENT_VERTICAL)
163 high = rect.GetHeight()-1;
164 else
165 high = rect.GetWidth()-1;
166
167 for (int i = 0; i <= high; ++i)
168 {
169 int r,g,b;
170
171
172 r = start_color.Red() + (high <= 0 ? 0 : (((i*rd*100)/high)/100));
173 g = start_color.Green() + (high <= 0 ? 0 : (((i*gd*100)/high)/100));
174 b = start_color.Blue() + (high <= 0 ? 0 : (((i*bd*100)/high)/100));
175
176 wxPen p(wxColor((unsigned char)r,
177 (unsigned char)g,
178 (unsigned char)b));
179 dc.SetPen(p);
180
181 if (direction == wxAUI_GRADIENT_VERTICAL)
182 dc.DrawLine(rect.x, rect.y+i, rect.x+rect.width, rect.y+i);
183 else
184 dc.DrawLine(rect.x+i, rect.y, rect.x+i, rect.y+rect.height);
185 }
186 }
187
wxAuiChopText(wxDC & dc,const wxString & text,int max_size)188 wxString wxAuiChopText(wxDC& dc, const wxString& text, int max_size)
189 {
190 wxCoord x,y;
191
192 // first check if the text fits with no problems
193 dc.GetTextExtent(text, &x, &y);
194 if (x <= max_size)
195 return text;
196
197 size_t i, len = text.Length();
198 size_t last_good_length = 0;
199 for (i = 0; i < len; ++i)
200 {
201 wxString s = text.Left(i);
202 s += wxT("...");
203
204 dc.GetTextExtent(s, &x, &y);
205 if (x > max_size)
206 break;
207
208 last_good_length = i;
209 }
210
211 wxString ret = text.Left(last_good_length);
212 ret += wxT("...");
213 return ret;
214 }
215
216 // -- wxAuiDefaultDockArt class implementation --
217
218 // wxAuiDefaultDockArt is an art provider class which does all of the drawing for
219 // wxAuiManager. This allows the library caller to customize the dock art
220 // (probably by deriving from this class), or to completely replace all drawing
221 // with custom dock art (probably by writing a new stand-alone class derived
222 // from the wxAuiDockArt base class). The active dock art class can be set via
223 // wxAuiManager::SetDockArt()
wxAuiDefaultDockArt()224 wxAuiDefaultDockArt::wxAuiDefaultDockArt()
225 {
226 UpdateColoursFromSystem();
227
228 #ifdef __WXMAC__
229 m_captionFont = *wxSMALL_FONT;
230 #else
231 m_captionFont = wxFont(8, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
232 #endif
233
234 // default metric values
235 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
236 SInt32 height;
237 GetThemeMetric( kThemeMetricSmallPaneSplitterHeight , &height );
238 m_sashSize = height;
239 #elif defined(__WXGTK__)
240 m_sashSize = wxRendererNative::Get().GetSplitterParams(NULL).widthSash;
241 #else
242 m_sashSize = wxWindow::FromDIP( 4, NULL);
243 #endif
244 m_captionSize = wxWindow::FromDIP(17, NULL);
245 m_borderSize = 1;
246 m_buttonSize = wxWindow::FromDIP(14, NULL);
247 m_gripperSize = wxWindow::FromDIP( 9, NULL);
248 m_gradientType = wxAUI_GRADIENT_VERTICAL;
249
250 InitBitmaps();
251 }
252
Clone()253 wxAuiDockArt* wxAuiDefaultDockArt::Clone()
254 {
255 return new wxAuiDefaultDockArt(*this);
256 }
257
258 void
InitBitmaps()259 wxAuiDefaultDockArt::InitBitmaps ()
260 {
261 // some built in bitmaps
262 // TODO: Provide x1.5 and x2.0 versions or migrate to SVG.
263 #if defined( __WXMAC__ )
264 static const unsigned char close_bits[]={
265 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3,
266 0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3,
267 0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF };
268 #elif defined(__WXGTK__)
269 static const unsigned char close_bits[]={
270 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
271 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
272 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
273 #else
274 static const unsigned char close_bits[]={
275 // reduced height, symmetric
276 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xf3, 0x9f, 0xf9,
277 0x3f, 0xfc, 0x7f, 0xfe, 0x3f, 0xfc, 0x9f, 0xf9, 0xcf, 0xf3, 0xff, 0xff,
278 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
279 /*
280 // same height as maximize/restore
281 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xe7, 0xcf, 0xf3, 0x9f, 0xf9,
282 0x3f, 0xfc, 0x7f, 0xfe, 0x3f, 0xfc, 0x9f, 0xf9, 0xcf, 0xf3, 0xe7, 0xe7,
283 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
284 */
285 #endif
286
287 static const unsigned char maximize_bits[] = {
288 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xf7, 0xf7, 0x07, 0xf0,
289 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0x07, 0xf0,
290 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
291
292 static const unsigned char restore_bits[]={
293 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xf0, 0x1f, 0xf0, 0xdf, 0xf7,
294 0x07, 0xf4, 0x07, 0xf4, 0xf7, 0xf5, 0xf7, 0xf1, 0xf7, 0xfd, 0xf7, 0xfd,
295 0x07, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
296
297 static const unsigned char pin_bits[]={
298 0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc,
299 0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff,
300 0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
301
302 #ifdef __WXMAC__
303 const wxColour inactive = wxSystemSettings::GetColour(wxSYS_COLOUR_INACTIVECAPTION);
304 const wxColour active = wxSystemSettings::GetColour(wxSYS_COLOUR_CAPTIONTEXT);
305 #else
306 const wxColor inactive = m_inactiveCaptionTextColour;
307 const wxColor active = m_activeCaptionTextColour;
308 #endif
309
310 m_inactiveCloseBitmap = wxAuiBitmapFromBits(close_bits, 16, 16, inactive);
311 m_activeCloseBitmap = wxAuiBitmapFromBits(close_bits, 16, 16, active);
312
313 m_inactiveMaximizeBitmap = wxAuiBitmapFromBits(maximize_bits, 16, 16, inactive);
314 m_activeMaximizeBitmap = wxAuiBitmapFromBits(maximize_bits, 16, 16, active);
315
316 m_inactiveRestoreBitmap = wxAuiBitmapFromBits(restore_bits, 16, 16, inactive);
317 m_activeRestoreBitmap = wxAuiBitmapFromBits(restore_bits, 16, 16, active);
318
319 m_inactivePinBitmap = wxAuiBitmapFromBits(pin_bits, 16, 16, inactive);
320 m_activePinBitmap = wxAuiBitmapFromBits(pin_bits, 16, 16, active);
321 }
322
UpdateColoursFromSystem()323 void wxAuiDefaultDockArt::UpdateColoursFromSystem()
324 {
325 wxColor baseColour = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
326
327 // the baseColour is too pale to use as our base colour,
328 // so darken it a bit --
329 if ((255-baseColour.Red()) +
330 (255-baseColour.Green()) +
331 (255-baseColour.Blue()) < 60)
332 {
333 baseColour = baseColour.ChangeLightness(92);
334 }
335
336 m_baseColour = baseColour;
337 wxColor darker1Colour = baseColour.ChangeLightness(85);
338 wxColor darker2Colour = baseColour.ChangeLightness(75);
339 wxColor darker3Colour = baseColour.ChangeLightness(60);
340 //wxColor darker4Colour = baseColour.ChangeLightness(50);
341 wxColor darker5Colour = baseColour.ChangeLightness(40);
342
343 m_activeCaptionColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT);
344 m_activeCaptionGradientColour = wxAuiLightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT));
345 m_activeCaptionTextColour = wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT);
346 m_inactiveCaptionColour = darker1Colour;
347 m_inactiveCaptionGradientColour = baseColour.ChangeLightness(97);
348 m_inactiveCaptionTextColour = wxSystemSettings::GetColour(wxSYS_COLOUR_INACTIVECAPTIONTEXT);
349
350 m_sashBrush = wxBrush(baseColour);
351 m_backgroundBrush = wxBrush(baseColour);
352 m_gripperBrush = wxBrush(baseColour);
353
354 m_borderPen = wxPen(darker2Colour);
355 int pen_width = wxWindow::FromDIP(1, NULL);
356 m_gripperPen1 = wxPen(darker5Colour, pen_width);
357 m_gripperPen2 = wxPen(darker3Colour, pen_width);
358 m_gripperPen3 = wxPen(*wxStockGDI::GetColour(wxStockGDI::COLOUR_WHITE), pen_width);
359 InitBitmaps();
360 }
361
GetMetric(int id)362 int wxAuiDefaultDockArt::GetMetric(int id)
363 {
364 switch (id)
365 {
366 case wxAUI_DOCKART_SASH_SIZE: return m_sashSize;
367 case wxAUI_DOCKART_CAPTION_SIZE: return m_captionSize;
368 case wxAUI_DOCKART_GRIPPER_SIZE: return m_gripperSize;
369 case wxAUI_DOCKART_PANE_BORDER_SIZE: return m_borderSize;
370 case wxAUI_DOCKART_PANE_BUTTON_SIZE: return m_buttonSize;
371 case wxAUI_DOCKART_GRADIENT_TYPE: return m_gradientType;
372 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
373 }
374
375 return 0;
376 }
377
SetMetric(int id,int new_val)378 void wxAuiDefaultDockArt::SetMetric(int id, int new_val)
379 {
380 switch (id)
381 {
382 case wxAUI_DOCKART_SASH_SIZE: m_sashSize = new_val; break;
383 case wxAUI_DOCKART_CAPTION_SIZE: m_captionSize = new_val; break;
384 case wxAUI_DOCKART_GRIPPER_SIZE: m_gripperSize = new_val; break;
385 case wxAUI_DOCKART_PANE_BORDER_SIZE: m_borderSize = new_val; break;
386 case wxAUI_DOCKART_PANE_BUTTON_SIZE: m_buttonSize = new_val; break;
387 case wxAUI_DOCKART_GRADIENT_TYPE: m_gradientType = new_val; break;
388 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
389 }
390 }
391
GetColour(int id)392 wxColour wxAuiDefaultDockArt::GetColour(int id)
393 {
394 switch (id)
395 {
396 case wxAUI_DOCKART_BACKGROUND_COLOUR: return m_backgroundBrush.GetColour();
397 case wxAUI_DOCKART_SASH_COLOUR: return m_sashBrush.GetColour();
398 case wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR: return m_inactiveCaptionColour;
399 case wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR: return m_inactiveCaptionGradientColour;
400 case wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR: return m_inactiveCaptionTextColour;
401 case wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR: return m_activeCaptionColour;
402 case wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR: return m_activeCaptionGradientColour;
403 case wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR: return m_activeCaptionTextColour;
404 case wxAUI_DOCKART_BORDER_COLOUR: return m_borderPen.GetColour();
405 case wxAUI_DOCKART_GRIPPER_COLOUR: return m_gripperBrush.GetColour();
406 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
407 }
408
409 return wxColour();
410 }
411
SetColour(int id,const wxColor & colour)412 void wxAuiDefaultDockArt::SetColour(int id, const wxColor& colour)
413 {
414 switch (id)
415 {
416 case wxAUI_DOCKART_BACKGROUND_COLOUR: m_backgroundBrush.SetColour(colour); break;
417 case wxAUI_DOCKART_SASH_COLOUR: m_sashBrush.SetColour(colour); break;
418 case wxAUI_DOCKART_INACTIVE_CAPTION_COLOUR: m_inactiveCaptionColour = colour; break;
419 case wxAUI_DOCKART_INACTIVE_CAPTION_GRADIENT_COLOUR: m_inactiveCaptionGradientColour = colour; break;
420 case wxAUI_DOCKART_INACTIVE_CAPTION_TEXT_COLOUR: m_inactiveCaptionTextColour = colour; break;
421 case wxAUI_DOCKART_ACTIVE_CAPTION_COLOUR: m_activeCaptionColour = colour; break;
422 case wxAUI_DOCKART_ACTIVE_CAPTION_GRADIENT_COLOUR: m_activeCaptionGradientColour = colour; break;
423 case wxAUI_DOCKART_ACTIVE_CAPTION_TEXT_COLOUR: m_activeCaptionTextColour = colour; break;
424 case wxAUI_DOCKART_BORDER_COLOUR: m_borderPen.SetColour(colour); break;
425 case wxAUI_DOCKART_GRIPPER_COLOUR:
426 m_gripperBrush.SetColour(colour);
427 m_gripperPen1.SetColour(colour.ChangeLightness(40));
428 m_gripperPen2.SetColour(colour.ChangeLightness(60));
429 break;
430 default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break;
431 }
432
433 InitBitmaps();
434 }
435
SetFont(int id,const wxFont & font)436 void wxAuiDefaultDockArt::SetFont(int id, const wxFont& font)
437 {
438 if (id == wxAUI_DOCKART_CAPTION_FONT)
439 m_captionFont = font;
440 }
441
GetFont(int id)442 wxFont wxAuiDefaultDockArt::GetFont(int id)
443 {
444 if (id == wxAUI_DOCKART_CAPTION_FONT)
445 return m_captionFont;
446 return wxNullFont;
447 }
448
DrawSash(wxDC & dc,wxWindow * window,int orientation,const wxRect & rect)449 void wxAuiDefaultDockArt::DrawSash(wxDC& dc, wxWindow *window, int orientation, const wxRect& rect)
450 {
451 #if defined( __WXMAC__ ) && wxOSX_USE_COCOA_OR_CARBON
452 wxUnusedVar(window);
453 wxUnusedVar(orientation);
454
455 if ( wxPlatformInfo::Get().CheckOSVersion(10, 14) && wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).Red() < 128 )
456 {
457 dc.SetPen(*wxTRANSPARENT_PEN);
458 dc.SetBrush(m_sashBrush);
459 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
460 }
461 else
462 {
463 HIRect splitterRect = CGRectMake( rect.x , rect.y , rect.width , rect.height );
464 CGContextRef cgContext ;
465 wxGCDCImpl *impl = (wxGCDCImpl*) dc.GetImpl();
466 cgContext = (CGContextRef) impl->GetGraphicsContext()->GetNativeContext() ;
467
468 HIThemeSplitterDrawInfo drawInfo ;
469 drawInfo.version = 0 ;
470 drawInfo.state = kThemeStateActive ;
471 drawInfo.adornment = kHIThemeSplitterAdornmentNone ;
472 HIThemeDrawPaneSplitter( &splitterRect , &drawInfo , cgContext , kHIThemeOrientationNormal ) ;
473 }
474
475 #elif defined(__WXGTK__)
476 // clear out the rectangle first
477 dc.SetPen(*wxTRANSPARENT_PEN);
478 dc.SetBrush(m_sashBrush);
479 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
480
481 #if 0
482 GdkRectangle gdk_rect;
483 if (orientation == wxVERTICAL )
484 {
485 gdk_rect.x = rect.x;
486 gdk_rect.y = rect.y;
487 gdk_rect.width = m_sashSize;
488 gdk_rect.height = rect.height;
489 }
490 else
491 {
492 gdk_rect.x = rect.x;
493 gdk_rect.y = rect.y;
494 gdk_rect.width = rect.width;
495 gdk_rect.height = m_sashSize;
496 }
497 #endif
498
499 if (!window) return;
500 if (!window->m_wxwindow) return;
501 if (!gtk_widget_is_drawable(window->m_wxwindow)) return;
502
503 #ifdef __WXGTK3__
504 cairo_t* cr = static_cast<cairo_t*>(dc.GetGraphicsContext()->GetNativeContext());
505 // invert orientation for widget (horizontal GtkPaned has a vertical splitter)
506 wxOrientation orient = orientation == wxVERTICAL ? wxHORIZONTAL : wxVERTICAL;
507 GtkWidget* widget = wxGTKPrivate::GetSplitterWidget(orient);
508 GtkStyleContext* sc = gtk_widget_get_style_context(widget);
509 gtk_style_context_save(sc);
510
511 gtk_style_context_add_class(sc, GTK_STYLE_CLASS_PANE_SEPARATOR);
512 gtk_render_handle(sc, cr, rect.x, rect.y, rect.width, rect.height);
513
514 gtk_style_context_restore(sc);
515 #else
516 gtk_paint_handle
517 (
518 gtk_widget_get_style(window->m_wxwindow),
519 window->GTKGetDrawingWindow(),
520 // flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
521 GTK_STATE_NORMAL,
522 GTK_SHADOW_NONE,
523 NULL /* no clipping */,
524 window->m_wxwindow,
525 "paned",
526 rect.x,
527 rect.y,
528 rect.width,
529 rect.height,
530 (orientation == wxVERTICAL) ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
531 );
532 #endif // !__WXGTK3__
533
534 #else
535 wxUnusedVar(window);
536 wxUnusedVar(orientation);
537 dc.SetPen(*wxTRANSPARENT_PEN);
538 dc.SetBrush(m_sashBrush);
539 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
540 #endif
541 }
542
543
DrawBackground(wxDC & dc,wxWindow * WXUNUSED (window),int,const wxRect & rect)544 void wxAuiDefaultDockArt::DrawBackground(wxDC& dc, wxWindow *WXUNUSED(window), int, const wxRect& rect)
545 {
546 dc.SetPen(*wxTRANSPARENT_PEN);
547 #ifdef __WXMAC__
548 // we have to clear first, otherwise we are drawing a light striped pattern
549 // over an already darker striped background
550 dc.SetBrush(*wxWHITE_BRUSH) ;
551 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
552 #endif
553 dc.SetBrush(m_backgroundBrush);
554 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
555 }
556
DrawBorder(wxDC & dc,wxWindow * window,const wxRect & _rect,wxAuiPaneInfo & pane)557 void wxAuiDefaultDockArt::DrawBorder(wxDC& dc, wxWindow* window, const wxRect& _rect,
558 wxAuiPaneInfo& pane)
559 {
560 dc.SetPen(m_borderPen);
561 dc.SetBrush(*wxTRANSPARENT_BRUSH);
562
563 wxRect rect = _rect;
564 int i, border_width = GetMetric(wxAUI_DOCKART_PANE_BORDER_SIZE);
565
566 if (pane.IsToolbar())
567 {
568 for (i = 0; i < border_width; ++i)
569 {
570 dc.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
571 dc.DrawLine(rect.x, rect.y, rect.x+rect.width, rect.y);
572 dc.DrawLine(rect.x, rect.y, rect.x, rect.y+rect.height);
573 dc.SetPen(m_borderPen);
574 dc.DrawLine(rect.x, rect.y+rect.height-1,
575 rect.x+rect.width, rect.y+rect.height-1);
576 dc.DrawLine(rect.x+rect.width-1, rect.y,
577 rect.x+rect.width-1, rect.y+rect.height);
578 rect.Deflate(1);
579 }
580 }
581 else
582 {
583 // notebooks draw the border themselves, so they can use native rendering (e.g. tabartgtk)
584 wxAuiTabArt* art = 0;
585 wxAuiNotebook* nb = wxDynamicCast(window, wxAuiNotebook);
586 if (nb)
587 art = nb->GetArtProvider();
588
589 if (art)
590 art->DrawBorder(dc, window, rect);
591 else
592 {
593 for (i = 0; i < border_width; ++i)
594 {
595 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
596 rect.Deflate(1);
597 }
598 }
599 }
600 }
601
602
DrawCaptionBackground(wxDC & dc,const wxRect & rect,bool active)603 void wxAuiDefaultDockArt::DrawCaptionBackground(wxDC& dc, const wxRect& rect, bool active)
604 {
605 if (m_gradientType == wxAUI_GRADIENT_NONE)
606 {
607 if (active)
608 dc.SetBrush(wxBrush(m_activeCaptionColour));
609 else
610 dc.SetBrush(wxBrush(m_inactiveCaptionColour));
611
612 dc.DrawRectangle(rect.x, rect.y, rect.width, rect.height);
613 }
614 else
615 {
616 if (active)
617 {
618 // on mac the gradients are expected to become darker from the top
619 #ifdef __WXMAC__
620 DrawGradientRectangle(dc, rect,
621 m_activeCaptionColour,
622 m_activeCaptionGradientColour,
623 m_gradientType);
624 #else
625 // on other platforms, active gradients become lighter at the top
626 DrawGradientRectangle(dc, rect,
627 m_activeCaptionGradientColour,
628 m_activeCaptionColour,
629 m_gradientType);
630 #endif
631 }
632 else
633 {
634 #ifdef __WXMAC__
635 // on mac the gradients are expected to become darker from the top
636 DrawGradientRectangle(dc, rect,
637 m_inactiveCaptionGradientColour,
638 m_inactiveCaptionColour,
639 m_gradientType);
640 #else
641 // on other platforms, inactive gradients become lighter at the bottom
642 DrawGradientRectangle(dc, rect,
643 m_inactiveCaptionColour,
644 m_inactiveCaptionGradientColour,
645 m_gradientType);
646 #endif
647 }
648 }
649 }
650
651
DrawCaption(wxDC & dc,wxWindow * window,const wxString & text,const wxRect & rect,wxAuiPaneInfo & pane)652 void wxAuiDefaultDockArt::DrawCaption(wxDC& dc,
653 wxWindow* window,
654 const wxString& text,
655 const wxRect& rect,
656 wxAuiPaneInfo& pane)
657 {
658 dc.SetPen(*wxTRANSPARENT_PEN);
659 dc.SetFont(m_captionFont);
660
661 DrawCaptionBackground(dc, rect,
662 (pane.state & wxAuiPaneInfo::optionActive)?true:false);
663
664 int caption_offset = 0;
665 if ( pane.icon.IsOk() )
666 {
667 DrawIcon(dc, window, rect, pane);
668
669 caption_offset += pane.icon.GetScaledWidth() + window->FromDIP(3);
670 }
671
672 if (pane.state & wxAuiPaneInfo::optionActive)
673 dc.SetTextForeground(m_activeCaptionTextColour);
674 else
675 dc.SetTextForeground(m_inactiveCaptionTextColour);
676
677
678 wxCoord w,h;
679 dc.GetTextExtent(wxT("ABCDEFHXfgkj"), &w, &h);
680
681 wxRect clip_rect = rect;
682 clip_rect.width -= window->FromDIP(3); // text offset
683 clip_rect.width -= window->FromDIP(2); // button padding
684 if (pane.HasCloseButton())
685 clip_rect.width -= m_buttonSize;
686 if (pane.HasPinButton())
687 clip_rect.width -= m_buttonSize;
688 if (pane.HasMaximizeButton())
689 clip_rect.width -= m_buttonSize;
690
691 wxString draw_text = wxAuiChopText(dc, text, clip_rect.width);
692
693 dc.SetClippingRegion(clip_rect);
694 dc.DrawText(draw_text, rect.x+window->FromDIP(3) + caption_offset, rect.y+(rect.height/2)-(h/2)-1);
695 dc.DestroyClippingRegion();
696 }
697
698 #if WXWIN_COMPATIBILITY_3_0
DrawIcon(wxDC & dc,const wxRect & rect,wxAuiPaneInfo & pane)699 void wxAuiDefaultDockArt::DrawIcon(wxDC& dc, const wxRect& rect, wxAuiPaneInfo& pane)
700 {
701 DrawIcon(dc, NULL, rect, pane);
702 }
703 #endif
704
705 void
DrawIcon(wxDC & dc,wxWindow * window,const wxRect & rect,wxAuiPaneInfo & pane)706 wxAuiDefaultDockArt::DrawIcon(wxDC& dc, wxWindow *window, const wxRect& rect, wxAuiPaneInfo& pane)
707 {
708 // Draw the icon centered vertically
709 int xOffset = window ? window->FromDIP(2) : 2;
710 dc.DrawBitmap(pane.icon,
711 rect.x+xOffset, rect.y+(rect.height-pane.icon.GetScaledHeight())/2,
712 true);
713 }
714
DrawGripper(wxDC & dc,wxWindow * window,const wxRect & rect,wxAuiPaneInfo & pane)715 void wxAuiDefaultDockArt::DrawGripper(wxDC& dc,
716 wxWindow* window,
717 const wxRect& rect,
718 wxAuiPaneInfo& pane)
719 {
720 dc.SetPen(*wxTRANSPARENT_PEN);
721 dc.SetBrush(m_gripperBrush);
722
723 dc.DrawRectangle(rect.x, rect.y, rect.width,rect.height);
724
725 if (!pane.HasGripperTop())
726 {
727 int y = window->FromDIP(5);
728 while (1)
729 {
730 dc.SetPen(m_gripperPen1);
731 dc.DrawPoint(rect.x+window->FromDIP(3), rect.y+y);
732 dc.SetPen(m_gripperPen2);
733 dc.DrawPoint(rect.x+window->FromDIP(3), rect.y+y+window->FromDIP(1));
734 dc.DrawPoint(rect.x+window->FromDIP(4), rect.y+y );
735 dc.SetPen(m_gripperPen3);
736 dc.DrawPoint(rect.x+window->FromDIP(5), rect.y+y+window->FromDIP(1));
737 dc.DrawPoint(rect.x+window->FromDIP(5), rect.y+y+window->FromDIP(2));
738 dc.DrawPoint(rect.x+window->FromDIP(4), rect.y+y+window->FromDIP(2));
739
740 y += window->FromDIP(4);
741 if (y > rect.GetHeight()-window->FromDIP(5))
742 break;
743 }
744 }
745 else
746 {
747 int x = window->FromDIP(5);
748 while (1)
749 {
750 dc.SetPen(m_gripperPen1);
751 dc.DrawPoint(rect.x+x, rect.y+window->FromDIP(3));
752 dc.SetPen(m_gripperPen2);
753 dc.DrawPoint(rect.x+x+window->FromDIP(1), rect.y+window->FromDIP(3));
754 dc.DrawPoint(rect.x+x , rect.y+window->FromDIP(4));
755 dc.SetPen(m_gripperPen3);
756 dc.DrawPoint(rect.x+x+window->FromDIP(1), rect.y+window->FromDIP(5));
757 dc.DrawPoint(rect.x+x+window->FromDIP(2), rect.y+window->FromDIP(5));
758 dc.DrawPoint(rect.x+x+window->FromDIP(2), rect.y+window->FromDIP(4));
759
760 x += window->FromDIP(4);
761 if (x > rect.GetWidth()-window->FromDIP(5))
762 break;
763 }
764 }
765 }
766
DrawPaneButton(wxDC & dc,wxWindow * window,int button,int button_state,const wxRect & _rect,wxAuiPaneInfo & pane)767 void wxAuiDefaultDockArt::DrawPaneButton(wxDC& dc,
768 wxWindow* window,
769 int button,
770 int button_state,
771 const wxRect& _rect,
772 wxAuiPaneInfo& pane)
773 {
774 wxBitmap bmp;
775 switch (button)
776 {
777 default:
778 case wxAUI_BUTTON_CLOSE:
779 if (pane.state & wxAuiPaneInfo::optionActive)
780 bmp = m_activeCloseBitmap;
781 else
782 bmp = m_inactiveCloseBitmap;
783 break;
784 case wxAUI_BUTTON_PIN:
785 if (pane.state & wxAuiPaneInfo::optionActive)
786 bmp = m_activePinBitmap;
787 else
788 bmp = m_inactivePinBitmap;
789 break;
790 case wxAUI_BUTTON_MAXIMIZE_RESTORE:
791 if (pane.IsMaximized())
792 {
793 if (pane.state & wxAuiPaneInfo::optionActive)
794 bmp = m_activeRestoreBitmap;
795 else
796 bmp = m_inactiveRestoreBitmap;
797 }
798 else
799 {
800 if (pane.state & wxAuiPaneInfo::optionActive)
801 bmp = m_activeMaximizeBitmap;
802 else
803 bmp = m_inactiveMaximizeBitmap;
804 }
805 break;
806 }
807
808 wxAuiScaleBitmap(bmp, window->GetDPIScaleFactor());
809
810 wxRect rect = _rect;
811
812 rect.y = rect.y + (rect.height/2) - (bmp.GetScaledHeight()/2);
813
814 if (button_state == wxAUI_BUTTON_STATE_PRESSED)
815 {
816 rect.x += window->FromDIP(1);
817 rect.y += window->FromDIP(1);
818 }
819
820 if (button_state == wxAUI_BUTTON_STATE_HOVER ||
821 button_state == wxAUI_BUTTON_STATE_PRESSED)
822 {
823 if (pane.state & wxAuiPaneInfo::optionActive)
824 {
825 dc.SetBrush(wxBrush(m_activeCaptionColour.ChangeLightness(120)));
826 dc.SetPen(wxPen(m_activeCaptionColour.ChangeLightness(70)));
827 }
828 else
829 {
830 dc.SetBrush(wxBrush(m_inactiveCaptionColour.ChangeLightness(120)));
831 dc.SetPen(wxPen(m_inactiveCaptionColour.ChangeLightness(70)));
832 }
833
834 // draw the background behind the button
835 dc.DrawRectangle(rect.x, rect.y,
836 bmp.GetScaledWidth() - window->FromDIP(1),
837 bmp.GetScaledHeight() - window->FromDIP(1));
838 }
839
840 // draw the button itself
841 dc.DrawBitmap(bmp, rect.x, rect.y, true);
842 }
843
844
845 #endif // wxUSE_AUI
846