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