1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/aui/dockart.cpp 
   3 // Purpose:     wxaui: wx advanced user interface - docking window manager 
   4 // Author:      Benjamin I. Williams 
   8 // Copyright:   (C) Copyright 2005-2006, Kirix Corporation, All Rights Reserved 
   9 // Licence:     wxWindows Library Licence, Version 3.1 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 #include "wx/wxprec.h" 
  28 #include "wx/aui/framemanager.h" 
  29 #include "wx/aui/dockart.h" 
  32     #include "wx/settings.h" 
  33     #include "wx/dcclient.h" 
  38 #include "wx/mac/private.h" 
  41 // -- wxDefaultDockArt class implementation -- 
  43 // wxDefaultDockArt is an art provider class which does all of the drawing for 
  44 // wxFrameManager.  This allows the library caller to customize the dock art 
  45 // (probably by deriving from this class), or to completely replace all drawing 
  46 // with custom dock art (probably by writing a new stand-alone class derived 
  47 // from the wxDockArt base class). The active dock art class can be set via 
  48 // wxFrameManager::SetDockArt() 
  51 // StepColour() it a utility function that simply darkens 
  52 // or lightens a color, based on the specified percentage 
  53 static wxColor 
StepColour(const wxColor
& c
, int percent
) 
  55     int r 
= c
.Red(), g 
= c
.Green(), b 
= c
.Blue(); 
  56     return wxColour((unsigned char)wxMin((r
*percent
)/100,255), 
  57                     (unsigned char)wxMin((g
*percent
)/100,255), 
  58                     (unsigned char)wxMin((b
*percent
)/100,255)); 
  61 static wxColor 
LightContrastColour(const wxColour
& c
) 
  65     // if the color is especially dark, then 
  66     // make the contrast even lighter 
  67     if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128) 
  70     return StepColour(c
, amount
); 
  73 // BitmapFromBits() is a utility function that creates a 
  74 // masked bitmap from raw bits (XBM format) 
  75 static wxBitmap 
BitmapFromBits(const unsigned char bits
[], int w
, int h
, 
  76                                const wxColour
& color
) 
  78     wxImage img 
= wxBitmap((const char*)bits
, w
, h
).ConvertToImage(); 
  79     img
.Replace(255,255,255,123,123,123); 
  80     img
.Replace(0,0,0,color
.Red(),color
.Green(),color
.Blue()); 
  81     img
.SetMaskColour(123,123,123); 
  86 static void DrawGradientRectangle(wxDC
& dc
, 
  88                                   const wxColour
& start_color
, 
  89                                   const wxColour
& end_color
, 
  92     int rd
, gd
, bd
, high 
= 0; 
  93     rd 
= end_color
.Red() - start_color
.Red(); 
  94     gd 
= end_color
.Green() - start_color
.Green(); 
  95     bd 
= end_color
.Blue() - start_color
.Blue(); 
  97     if (direction 
== wxAUI_GRADIENT_VERTICAL
) 
  98         high 
= rect
.GetHeight()-1; 
 100         high 
= rect
.GetWidth()-1; 
 102     for (int i 
= 0; i 
<= high
; ++i
) 
 104         int r 
= start_color
.Red() +  ((i
*rd
*100)/high
)/100; 
 105         int g 
= start_color
.Green() + ((i
*gd
*100)/high
)/100; 
 106         int b 
= start_color
.Blue() + ((i
*bd
*100)/high
)/100; 
 108         wxPen 
p(wxColor((unsigned char)r
, 
 113         if (direction 
== wxAUI_GRADIENT_VERTICAL
) 
 114             dc
.DrawLine(rect
.x
, rect
.y
+i
, rect
.x
+rect
.width
, rect
.y
+i
); 
 116             dc
.DrawLine(rect
.x
+i
, rect
.y
, rect
.x
+i
, rect
.y
+rect
.height
); 
 121 wxDefaultDockArt::wxDefaultDockArt() 
 124     wxBrush toolbarbrush
; 
 125     toolbarbrush
.MacSetTheme( kThemeBrushToolbarBackground 
); 
 126     wxColor base_color 
= toolbarbrush
.GetColour(); 
 128     wxColor base_color 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
); 
 131     wxColor darker1_color 
= StepColour(base_color
, 85); 
 132     wxColor darker2_color 
= StepColour(base_color
, 70); 
 133     wxColor darker3_color 
= StepColour(base_color
, 60); 
 134     wxColor darker4_color 
= StepColour(base_color
, 50); 
 135     wxColor darker5_color 
= StepColour(base_color
, 40); 
 137     m_active_caption_colour 
= LightContrastColour(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
)); 
 138     m_active_caption_gradient_colour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
); 
 139     m_active_caption_text_colour 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
 140     m_inactive_caption_colour 
= StepColour(darker1_color
, 80); 
 141     m_inactive_caption_gradient_colour 
= darker1_color
; 
 142     m_inactive_caption_text_colour 
= *wxBLACK
; 
 145     m_sash_brush 
= toolbarbrush
; 
 146     m_background_brush 
= toolbarbrush
; 
 147     m_gripper_brush 
= toolbarbrush
; 
 149     m_sash_brush 
= wxBrush(base_color
); 
 150     m_background_brush 
= wxBrush(base_color
); 
 151     m_gripper_brush 
= wxBrush(base_color
); 
 153     m_border_pen 
= wxPen(darker2_color
); 
 154     m_gripper_pen1 
= wxPen(darker5_color
); 
 155     m_gripper_pen2 
= wxPen(darker3_color
); 
 156     m_gripper_pen3 
= *wxWHITE_PEN
; 
 159     m_caption_font 
= *wxSMALL_FONT
; 
 161     m_caption_font 
= wxFont(8, wxDEFAULT
, wxNORMAL
, wxNORMAL
, FALSE
); 
 164     // some built in bitmaps 
 166      static unsigned char close_bits
[]={ 
 167          0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x03, 0xF8, 0x01, 0xF0, 0x19, 0xF3, 
 168          0xB8, 0xE3, 0xF0, 0xE1, 0xE0, 0xE0, 0xF0, 0xE1, 0xB8, 0xE3, 0x19, 0xF3, 
 169          0x01, 0xF0, 0x03, 0xF8, 0x0F, 0xFE, 0xFF, 0xFF }; 
 171     static unsigned char close_bits
[]={ 
 172         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xef,0xfb,0xcf,0xf9, 
 173         0x9f,0xfc,0x3f,0xfe,0x3f,0xfe,0x9f,0xfc,0xcf,0xf9,0xef,0xfb, 
 174         0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 
 177     static unsigned char pin_bits
[]={ 
 178         0xff,0xff,0xff,0xff,0xff,0xff,0x1f,0xfc,0xdf,0xfc,0xdf,0xfc, 
 179         0xdf,0xfc,0xdf,0xfc,0xdf,0xfc,0x0f,0xf8,0x7f,0xff,0x7f,0xff, 
 180         0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff}; 
 183     m_inactive_close_bitmap 
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE
); 
 185     m_inactive_close_bitmap 
= BitmapFromBits(close_bits
, 16, 16, m_inactive_caption_text_colour
); 
 187     m_inactive_pin_bitmap 
= BitmapFromBits(pin_bits
, 16, 16, m_inactive_caption_text_colour
); 
 189     m_active_close_bitmap 
= BitmapFromBits(close_bits
, 16, 16, *wxWHITE 
); 
 191     m_active_close_bitmap 
= BitmapFromBits(close_bits
, 16, 16, m_active_caption_text_colour
); 
 193     m_active_pin_bitmap 
= BitmapFromBits(pin_bits
, 16, 16, m_active_caption_text_colour
); 
 195     // default metric values 
 198     GetThemeMetric( kThemeMetricSmallPaneSplitterHeight 
, &height 
); 
 199     m_sash_size 
= height
; 
 207     m_gradient_type 
= wxAUI_GRADIENT_VERTICAL
; 
 210 int wxDefaultDockArt::GetMetric(int id
) 
 214         case wxAUI_ART_SASH_SIZE
:          return m_sash_size
; 
 215         case wxAUI_ART_CAPTION_SIZE
:       return m_caption_size
; 
 216         case wxAUI_ART_GRIPPER_SIZE
:       return m_gripper_size
; 
 217         case wxAUI_ART_PANE_BORDER_SIZE
:   return m_border_size
; 
 218         case wxAUI_ART_PANE_BUTTON_SIZE
:   return m_button_size
; 
 219         case wxAUI_ART_GRADIENT_TYPE
:      return m_gradient_type
; 
 220         default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break; 
 226 void wxDefaultDockArt::SetMetric(int id
, int new_val
) 
 230         case wxAUI_ART_SASH_SIZE
:          m_sash_size 
= new_val
; break; 
 231         case wxAUI_ART_CAPTION_SIZE
:       m_caption_size 
= new_val
; break; 
 232         case wxAUI_ART_GRIPPER_SIZE
:       m_gripper_size 
= new_val
; break; 
 233         case wxAUI_ART_PANE_BORDER_SIZE
:   m_border_size 
= new_val
; break; 
 234         case wxAUI_ART_PANE_BUTTON_SIZE
:   m_button_size 
= new_val
; break; 
 235         case wxAUI_ART_GRADIENT_TYPE
:      m_gradient_type 
= new_val
; break; 
 236         default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break; 
 240 wxColour 
wxDefaultDockArt::GetColour(int id
) 
 244         case wxAUI_ART_BACKGROUND_COLOUR
:                return m_background_brush
.GetColour(); 
 245         case wxAUI_ART_SASH_COLOUR
:                      return m_sash_brush
.GetColour(); 
 246         case wxAUI_ART_INACTIVE_CAPTION_COLOUR
:          return m_inactive_caption_colour
; 
 247         case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: return m_inactive_caption_gradient_colour
; 
 248         case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
:     return m_inactive_caption_text_colour
; 
 249         case wxAUI_ART_ACTIVE_CAPTION_COLOUR
:            return m_active_caption_colour
; 
 250         case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
:   return m_active_caption_gradient_colour
; 
 251         case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
:       return m_active_caption_text_colour
; 
 252         case wxAUI_ART_BORDER_COLOUR
:                    return m_border_pen
.GetColour(); 
 253         case wxAUI_ART_GRIPPER_COLOUR
:                   return m_gripper_brush
.GetColour(); 
 254         default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break; 
 260 void wxDefaultDockArt::SetColour(int id
, const wxColor
& colour
) 
 264         case wxAUI_ART_BACKGROUND_COLOUR
:                m_background_brush
.SetColour(colour
); break; 
 265         case wxAUI_ART_SASH_COLOUR
:                      m_sash_brush
.SetColour(colour
); break; 
 266         case wxAUI_ART_INACTIVE_CAPTION_COLOUR
:          m_inactive_caption_colour 
= colour
; break; 
 267         case wxAUI_ART_INACTIVE_CAPTION_GRADIENT_COLOUR
: m_inactive_caption_gradient_colour 
= colour
; break; 
 268         case wxAUI_ART_INACTIVE_CAPTION_TEXT_COLOUR
:     m_inactive_caption_text_colour 
= colour
; break; 
 269         case wxAUI_ART_ACTIVE_CAPTION_COLOUR
:            m_active_caption_colour 
= colour
; break; 
 270         case wxAUI_ART_ACTIVE_CAPTION_GRADIENT_COLOUR
:   m_active_caption_gradient_colour 
= colour
; break; 
 271         case wxAUI_ART_ACTIVE_CAPTION_TEXT_COLOUR
:       m_active_caption_text_colour 
= colour
; break; 
 272         case wxAUI_ART_BORDER_COLOUR
:                    m_border_pen
.SetColour(colour
); break; 
 273         case wxAUI_ART_GRIPPER_COLOUR
: 
 274             m_gripper_brush
.SetColour(colour
); 
 275             m_gripper_pen1
.SetColour(StepColour(colour
, 40)); 
 276             m_gripper_pen2
.SetColour(StepColour(colour
, 60)); 
 278         default: wxFAIL_MSG(wxT("Invalid Metric Ordinal")); break; 
 282 void wxDefaultDockArt::SetFont(int id
, const wxFont
& font
) 
 284     if (id 
== wxAUI_ART_CAPTION_FONT
) 
 285         m_caption_font 
= font
; 
 288 wxFont 
wxDefaultDockArt::GetFont(int id
) 
 290     if (id 
== wxAUI_ART_CAPTION_FONT
) 
 291         return m_caption_font
; 
 295 void wxDefaultDockArt::DrawSash(wxDC
& dc
, int, const wxRect
& rect
) 
 298     HIRect splitterRect 
= CGRectMake( rect
.x 
, rect
.y 
, rect
.width 
, rect
.height 
); 
 299     CGContextRef cgContext 
; 
 300 #if wxMAC_USE_CORE_GRAPHICS 
 301     cgContext 
= ((wxMacCGContext
*)(dc
.GetGraphicContext()))->GetNativeContext() ; 
 304     GetPortBounds( (CGrafPtr
) dc
.m_macPort 
, &bounds 
) ; 
 305     QDBeginCGContext( (CGrafPtr
) dc
.m_macPort 
, &cgContext 
) ; 
 306     CGContextTranslateCTM( cgContext 
, 0 , bounds
.bottom 
- bounds
.top 
) ; 
 307     CGContextScaleCTM( cgContext 
, 1 , -1 ) ; 
 310     HIThemeSplitterDrawInfo drawInfo 
; 
 311     drawInfo
.version 
= 0 ; 
 312     drawInfo
.state 
= kThemeStateActive 
; 
 313     drawInfo
.adornment 
= kHIThemeSplitterAdornmentNone 
; 
 314     HIThemeDrawPaneSplitter( &splitterRect 
, &drawInfo 
, cgContext 
, kHIThemeOrientationNormal 
) ; 
 316 #if wxMAC_USE_CORE_GRAPHICS 
 318     QDEndCGContext( (CGrafPtr
) dc
.m_macPort 
, &cgContext 
) ; 
 322     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 323     dc
.SetBrush(m_sash_brush
); 
 324     dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 329 void wxDefaultDockArt::DrawBackground(wxDC
& dc
, int, const wxRect
& rect
) 
 331     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 333     // we have to clear first, otherwise we are drawing a light striped pattern 
 334     // over an already darker striped background 
 335     dc
.SetBrush(*wxWHITE_BRUSH
) ; 
 336     dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 338     dc
.SetBrush(m_background_brush
); 
 339     dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 342 void wxDefaultDockArt::DrawBorder(wxDC
& dc
, const wxRect
& _rect
, 
 345     dc
.SetPen(m_border_pen
); 
 346     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
 349     int i
, border_width 
= GetMetric(wxAUI_ART_PANE_BORDER_SIZE
); 
 351     if (pane
.IsToolbar()) 
 353         for (i 
= 0; i 
< border_width
; ++i
) 
 355             dc
.SetPen(*wxWHITE_PEN
); 
 356             dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
+rect
.width
, rect
.y
); 
 357             dc
.DrawLine(rect
.x
, rect
.y
, rect
.x
, rect
.y
+rect
.height
); 
 358             dc
.SetPen(m_border_pen
); 
 359             dc
.DrawLine(rect
.x
, rect
.y
+rect
.height
-1, 
 360                         rect
.x
+rect
.width
, rect
.y
+rect
.height
-1); 
 361             dc
.DrawLine(rect
.x
+rect
.width
-1, rect
.y
, 
 362                         rect
.x
+rect
.width
-1, rect
.y
+rect
.height
); 
 368         for (i 
= 0; i 
< border_width
; ++i
) 
 370             dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 377 void wxDefaultDockArt::DrawCaptionBackground(wxDC
& dc
, const wxRect
& rect
, bool active
) 
 379     if (m_gradient_type 
== wxAUI_GRADIENT_NONE
) 
 382             dc
.SetBrush(wxBrush(m_active_caption_colour
)); 
 384             dc
.SetBrush(wxBrush(m_inactive_caption_colour
)); 
 386         dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
, rect
.height
); 
 392             // on mac the gradients are expected to become darker from the top 
 394             DrawGradientRectangle(dc
, rect
, 
 395                                  m_active_caption_gradient_colour
, 
 396                                  m_active_caption_colour
, 
 399             DrawGradientRectangle(dc
, rect
, 
 400                                  m_active_caption_colour
, 
 401                                  m_active_caption_gradient_colour
, 
 407             // on mac the gradients are expected to become darker from the top 
 409             DrawGradientRectangle(dc
, rect
, 
 410                                  m_inactive_caption_gradient_colour
, 
 411                                  m_inactive_caption_colour
, 
 414             DrawGradientRectangle(dc
, rect
, 
 415                                  m_inactive_caption_colour
, 
 416                                  m_inactive_caption_gradient_colour
, 
 424 void wxDefaultDockArt::DrawCaption(wxDC
& dc
, 
 425                                    const wxString
& text
, 
 429     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 430     dc
.SetFont(m_caption_font
); 
 432     DrawCaptionBackground(dc
, rect
, 
 433                           (pane
.state 
& wxPaneInfo::optionActive
)?true:false); 
 435     if (pane
.state 
& wxPaneInfo::optionActive
) 
 436         dc
.SetTextForeground(m_active_caption_text_colour
); 
 438         dc
.SetTextForeground(m_inactive_caption_text_colour
); 
 442     dc
.GetTextExtent(wxT("ABCDEFHXfgkj"), &w
, &h
); 
 444     dc
.SetClippingRegion(rect
); 
 445     dc
.DrawText(text
, rect
.x
+3, rect
.y
+(rect
.height
/2)-(h
/2)-1); 
 446     dc
.DestroyClippingRegion(); 
 449 void wxDefaultDockArt::DrawGripper(wxDC
& dc
, 
 453     dc
.SetPen(*wxTRANSPARENT_PEN
); 
 454     dc
.SetBrush(m_gripper_brush
); 
 456     dc
.DrawRectangle(rect
.x
, rect
.y
, rect
.width
,rect
.height
); 
 458     if (!pane
.HasGripperTop()) 
 463             dc
.SetPen(m_gripper_pen1
); 
 464             dc
.DrawPoint(rect
.x
+3, rect
.y
+y
); 
 465             dc
.SetPen(m_gripper_pen2
); 
 466             dc
.DrawPoint(rect
.x
+3, rect
.y
+y
+1); 
 467             dc
.DrawPoint(rect
.x
+4, rect
.y
+y
); 
 468             dc
.SetPen(m_gripper_pen3
); 
 469             dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+1); 
 470             dc
.DrawPoint(rect
.x
+5, rect
.y
+y
+2); 
 471             dc
.DrawPoint(rect
.x
+4, rect
.y
+y
+2); 
 474             if (y 
> rect
.GetHeight()-5) 
 483             dc
.SetPen(m_gripper_pen1
); 
 484             dc
.DrawPoint(rect
.x
+x
, rect
.y
+3); 
 485             dc
.SetPen(m_gripper_pen2
); 
 486             dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+3); 
 487             dc
.DrawPoint(rect
.x
+x
, rect
.y
+4); 
 488             dc
.SetPen(m_gripper_pen3
); 
 489             dc
.DrawPoint(rect
.x
+x
+1, rect
.y
+5); 
 490             dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+5); 
 491             dc
.DrawPoint(rect
.x
+x
+2, rect
.y
+4); 
 494             if (x 
> rect
.GetWidth()-5) 
 500 void wxDefaultDockArt::DrawPaneButton(wxDC
& dc
, 
 508     if (button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
 514     if (button_state 
== wxAUI_BUTTON_STATE_HOVER 
|| 
 515         button_state 
== wxAUI_BUTTON_STATE_PRESSED
) 
 517         if (pane
.state 
& wxPaneInfo::optionActive
) 
 519             dc
.SetBrush(wxBrush(StepColour(m_active_caption_colour
, 120))); 
 520             dc
.SetPen(wxPen(StepColour(m_active_caption_colour
, 70))); 
 524             dc
.SetBrush(wxBrush(StepColour(m_inactive_caption_colour
, 120))); 
 525             dc
.SetPen(wxPen(StepColour(m_inactive_caption_colour
, 70))); 
 528         // draw the background behind the button 
 529         dc
.DrawRectangle(rect
.x
, rect
.y
, 15, 15); 
 536         case wxPaneInfo::buttonClose
: 
 537             if (pane
.state 
& wxPaneInfo::optionActive
) 
 538                 bmp 
= m_active_close_bitmap
; 
 540                 bmp 
= m_inactive_close_bitmap
; 
 542         case wxPaneInfo::buttonPin
: 
 543             if (pane
.state 
& wxPaneInfo::optionActive
) 
 544                 bmp 
= m_active_pin_bitmap
; 
 546                 bmp 
= m_inactive_pin_bitmap
; 
 550     // draw the button itself 
 551     dc
.DrawBitmap(bmp
, rect
.x
, rect
.y
, true);