1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        gtk/renderer.cpp 
   3 // Purpose:     implementation of wxRendererNative for wxGTK 
   4 // Author:      Vadim Zeitlin 
   8 // Copyright:   (c) 2003 Vadim Zeitlin <vadim@wxwindows.org> 
   9 // License:     wxWindows licence 
  10 /////////////////////////////////////////////////////////////////////////////// 
  12 // ============================================================================ 
  14 // ============================================================================ 
  16 // ---------------------------------------------------------------------------- 
  18 // ---------------------------------------------------------------------------- 
  20 // for compilers that support precompilation, includes "wx.h". 
  21 #include "wx/wxprec.h" 
  27 #include "wx/renderer.h" 
  29 #include "wx/gtk/win_gtk.h" 
  31 #include "wx/window.h" 
  33 #include "wx/dcclient.h" 
  34 #include "wx/settings.h" 
  36 // RR: After a correction to the orientation of the sash 
  37 //     this doesn't seem to be required anymore and it 
  38 //     seems to confuse some themes so USE_ERASE_RECT=0 
  39 #define USE_ERASE_RECT 0 
  41 // ---------------------------------------------------------------------------- 
  42 // wxRendererGTK: our wxRendererNative implementation 
  43 // ---------------------------------------------------------------------------- 
  45 class WXDLLEXPORT wxRendererGTK 
: public wxDelegateRendererNative
 
  48     // draw the header control button (used by wxListCtrl) 
  49     virtual void DrawHeaderButton(wxWindow 
*win
, 
  54     // draw the expanded/collapsed icon for a tree control item 
  55     virtual void DrawTreeItemButton(wxWindow 
*win
, 
  60     virtual void DrawSplitterBorder(wxWindow 
*win
, 
  64     virtual void DrawSplitterSash(wxWindow 
*win
, 
  71     virtual void DrawComboBoxDropButton(wxWindow 
*win
, 
  76     virtual void DrawDropArrow(wxWindow 
*win
, 
  81     virtual wxSplitterRenderParams 
GetSplitterParams(const wxWindow 
*win
); 
  84     // FIXME: shouldn't we destroy these windows somewhere? 
  86     // used by DrawHeaderButton and DrawComboBoxDropButton 
  87     static GtkWidget 
*GetButtonWidget(); 
  89     // used by DrawTreeItemButton() 
  90     static GtkWidget 
*GetTreeWidget(); 
  93 // ============================================================================ 
  95 // ============================================================================ 
  98 wxRendererNative
& wxRendererNative::GetDefault() 
 100     static wxRendererGTK s_rendererGTK
; 
 102     return s_rendererGTK
; 
 105 // ---------------------------------------------------------------------------- 
 107 // ---------------------------------------------------------------------------- 
 110 wxRendererGTK::GetButtonWidget() 
 112     static GtkWidget 
*s_button 
= NULL
; 
 113     static GtkWidget 
*s_window 
= NULL
; 
 117         s_window 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 118         gtk_widget_realize( s_window 
); 
 119         s_button 
= gtk_button_new(); 
 120         gtk_container_add( GTK_CONTAINER(s_window
), s_button 
); 
 121         gtk_widget_realize( s_button 
); 
 128 wxRendererGTK::GetTreeWidget() 
 130     static GtkWidget 
*s_tree 
= NULL
; 
 131     static GtkWidget 
*s_window 
= NULL
; 
 135         s_tree 
= gtk_tree_view_new(); 
 136         s_window 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 137         gtk_widget_realize( s_window 
); 
 138         gtk_container_add( GTK_CONTAINER(s_window
), s_tree 
); 
 139         gtk_widget_realize( s_tree 
); 
 145 // ---------------------------------------------------------------------------- 
 146 // list/tree controls drawing 
 147 // ---------------------------------------------------------------------------- 
 150 wxRendererGTK::DrawHeaderButton(wxWindow 
*win
, 
 156     GtkWidget 
*button 
= GetButtonWidget(); 
 161         // FIXME: I suppose GTK_PIZZA(win->m_wxwindow)->bin_window doesn't work with wxMemoryDC. 
 162         //   Maybe use code similar as in DrawComboBoxDropButton below? 
 163         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 164         flags 
& wxCONTROL_DISABLED 
? GTK_STATE_INSENSITIVE 
: GTK_STATE_NORMAL
, 
 169         dc
.XLOG2DEV(rect
.x
) -1, rect
.y 
-1, rect
.width 
+2, rect
.height 
+2 
 173 // draw a ">" or "v" button 
 175 wxRendererGTK::DrawTreeItemButton(wxWindow
* win
, 
 176                                   wxDC
& dc
, const wxRect
& rect
, int flags
) 
 178     GtkWidget 
*tree 
= GetTreeWidget(); 
 181     if ( flags 
& wxCONTROL_CURRENT 
) 
 182         state 
= GTK_STATE_PRELIGHT
; 
 184         state 
= GTK_STATE_NORMAL
; 
 186     // VZ: I don't know how to get the size of the expander so as to centre it 
 187     //     in the given rectangle, +2/3 below is just what looks good here... 
 191         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 196         dc
.LogicalToDeviceX(rect
.x
) + 2, 
 197         dc
.LogicalToDeviceY(rect
.y
) + 3, 
 198         flags 
& wxCONTROL_EXPANDED 
? GTK_EXPANDER_EXPANDED
 
 199                                    : GTK_EXPANDER_COLLAPSED
 
 204 // ---------------------------------------------------------------------------- 
 205 // splitter sash drawing 
 206 // ---------------------------------------------------------------------------- 
 208 static int GetGtkSplitterFullSize() 
 210     static GtkWidget 
*s_paned 
= NULL
; 
 212         s_paned 
= gtk_vpaned_new(); 
 215     gtk_widget_style_get (s_paned
, "handle_size", &handle_size
, NULL
); 
 220 wxSplitterRenderParams
 
 221 wxRendererGTK::GetSplitterParams(const wxWindow 
*WXUNUSED(win
)) 
 223     // we don't draw any border, hence 0 for the second field 
 224     return wxSplitterRenderParams
 
 226                GetGtkSplitterFullSize(), 
 228                true     // hot sensitive 
 233 wxRendererGTK::DrawSplitterBorder(wxWindow 
* WXUNUSED(win
), 
 235                                   const wxRect
& WXUNUSED(rect
), 
 242 wxRendererGTK::DrawSplitterSash(wxWindow 
*win
, 
 246                                 wxOrientation orient
, 
 249     if ( !win
->m_wxwindow
->window 
) 
 251         // window not realized yet 
 255     wxCoord full_size 
= GetGtkSplitterFullSize(); 
 257     // are we drawing vertical or horizontal splitter? 
 258     const bool isVert 
= orient 
== wxVERTICAL
; 
 262     GdkRectangle erase_rect
; 
 267         int h 
= win
->GetClientSize().GetHeight(); 
 271         rect
.width 
= full_size
; 
 275         erase_rect
.x 
= position
; 
 277         erase_rect
.width 
= full_size
; 
 278         erase_rect
.height 
= h
; 
 283         int w 
= win
->GetClientSize().GetWidth(); 
 287         rect
.height 
= full_size
; 
 291         erase_rect
.y 
= position
; 
 293         erase_rect
.height 
= full_size
; 
 294         erase_rect
.width 
= w
; 
 299     // we must erase everything first, otherwise the garbage 
 300     // from the old sash is left when dragging it 
 303         win
->m_wxwindow
->style
, 
 304         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 309         (char *)"viewportbin", // const_cast 
 319         win
->m_wxwindow
->style
, 
 320         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 321         flags 
& wxCONTROL_CURRENT 
? GTK_STATE_PRELIGHT 
: GTK_STATE_NORMAL
, 
 323         NULL 
/* no clipping */, 
 330         isVert 
? GTK_ORIENTATION_VERTICAL 
: GTK_ORIENTATION_HORIZONTAL
 
 335 wxRendererGTK::DrawDropArrow(wxWindow 
*win
, 
 340     GtkWidget 
*button 
= GetButtonWidget(); 
 342     // If we give GTK_PIZZA(win->m_wxwindow)->bin_window as 
 343     // a window for gtk_paint_xxx function, then it won't 
 344     // work for wxMemoryDC. So that is why we assume wxDC 
 345     // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC 
 346     // are derived from it) and use its m_window. 
 347     wxWindowDC
& wdc 
= (wxWindowDC
&)dc
; 
 349     // only doing debug-time checking here (it should 
 350     // probably be enough) 
 351     wxASSERT ( wdc
.IsKindOf(CLASSINFO(wxWindowDC
)) ); 
 353     // draw arrow so that there is even space horizontally 
 355     int arrowX 
= rect
.width
/4 + 1; 
 356     int arrowWidth 
= rect
.width 
- (arrowX
*2); 
 358     // scale arrow's height accoording to the width 
 359     int arrowHeight 
= rect
.width
/3; 
 360     int arrowY 
= (rect
.height
-arrowHeight
)/2 + 
 361                  ((rect
.height
-arrowHeight
) & 1); 
 365     if ( flags 
& wxCONTROL_PRESSED 
) 
 366         state 
= GTK_STATE_ACTIVE
; 
 367     else if ( flags 
& wxCONTROL_DISABLED 
) 
 368         state 
= GTK_STATE_INSENSITIVE
; 
 369     else if ( flags 
& wxCONTROL_CURRENT 
) 
 370         state 
= GTK_STATE_PRELIGHT
; 
 372         state 
= GTK_STATE_NORMAL
; 
 374     // draw arrow on button 
 380         flags 
& wxCONTROL_PRESSED 
? GTK_SHADOW_IN 
: GTK_SHADOW_OUT
, 
 394 wxRendererGTK::DrawComboBoxDropButton(wxWindow 
*win
, 
 399     GtkWidget 
*button 
= GetButtonWidget(); 
 401     // for reason why we do this, see DrawDropArrow 
 402     wxWindowDC
& wdc 
= (wxWindowDC
&)dc
; 
 403     wxASSERT ( wdc
.IsKindOf(CLASSINFO(wxWindowDC
)) ); 
 408     if ( flags 
& wxCONTROL_PRESSED 
) 
 409         state 
= GTK_STATE_ACTIVE
; 
 410     else if ( flags 
& wxCONTROL_DISABLED 
) 
 411         state 
= GTK_STATE_INSENSITIVE
; 
 412     else if ( flags 
& wxCONTROL_CURRENT 
) 
 413         state 
= GTK_STATE_PRELIGHT
; 
 415         state 
= GTK_STATE_NORMAL
; 
 422         flags 
& wxCONTROL_PRESSED 
? GTK_SHADOW_IN 
: GTK_SHADOW_OUT
, 
 426         rect
.x
, rect
.y
, rect
.width
, rect
.height
 
 429     // draw arrow on button 
 430     DrawDropArrow(win
,dc
,rect
,flags
);