1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk1/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" 
  30     #include "wx/window.h" 
  32     #include "wx/dcclient.h" 
  36 #include "wx/gtk1/win_gtk.h" 
  38 // RR: After a correction to the orientation of the sash 
  39 //     this doesn't seem to be required anymore and it 
  40 //     seems to confuse some themes so USE_ERASE_RECT=0 
  41 #define USE_ERASE_RECT 0 
  43 // ---------------------------------------------------------------------------- 
  44 // wxRendererGTK: our wxRendererNative implementation 
  45 // ---------------------------------------------------------------------------- 
  47 class WXDLLEXPORT wxRendererGTK 
: public wxDelegateRendererNative
 
  50     // draw the header control button (used by wxListCtrl) 
  51     virtual void DrawHeaderButton(wxWindow 
*win
, 
  56     virtual void DrawSplitterBorder(wxWindow 
*win
, 
  60     virtual void DrawSplitterSash(wxWindow 
*win
, 
  67     virtual void DrawComboBoxDropButton(wxWindow 
*win
, 
  72     virtual void DrawDropArrow(wxWindow 
*win
, 
  77     virtual wxSplitterRenderParams 
GetSplitterParams(const wxWindow 
*win
); 
  80     // FIXME: shouldn't we destroy these windows somewhere? 
  82     // used by DrawHeaderButton and DrawComboBoxDropButton 
  83     static GtkWidget 
*GetButtonWidget(); 
  86 // ============================================================================ 
  88 // ============================================================================ 
  91 wxRendererNative
& wxRendererNative::GetDefault() 
  93     static wxRendererGTK s_rendererGTK
; 
  98 // ---------------------------------------------------------------------------- 
 100 // ---------------------------------------------------------------------------- 
 103 wxRendererGTK::GetButtonWidget() 
 105     static GtkWidget 
*s_button 
= NULL
; 
 106     static GtkWidget 
*s_window 
= NULL
; 
 110         s_window 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 111         gtk_widget_realize( s_window 
); 
 112         s_button 
= gtk_button_new(); 
 113         gtk_container_add( GTK_CONTAINER(s_window
), s_button 
); 
 114         gtk_widget_realize( s_button 
); 
 120 // ---------------------------------------------------------------------------- 
 121 // list/tree controls drawing 
 122 // ---------------------------------------------------------------------------- 
 125 wxRendererGTK::DrawHeaderButton(wxWindow 
*win
, 
 131     GtkWidget 
*button 
= GetButtonWidget(); 
 136         // FIXME: I suppose GTK_PIZZA(win->m_wxwindow)->bin_window doesn't work with wxMemoryDC. 
 137         //   Maybe use code similar as in DrawComboBoxDropButton below? 
 138         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 139         flags 
& wxCONTROL_DISABLED 
? GTK_STATE_INSENSITIVE 
: GTK_STATE_NORMAL
, 
 144         dc
.XLOG2DEV(rect
.x
) -1, rect
.y 
-1, rect
.width 
+2, rect
.height 
+2 
 148 // ---------------------------------------------------------------------------- 
 149 // splitter sash drawing 
 150 // ---------------------------------------------------------------------------- 
 152 // the full sash width (should be even) 
 153 static const wxCoord SASH_SIZE 
= 8; 
 155 // margin around the sash 
 156 static const wxCoord SASH_MARGIN 
= 2; 
 158 static int GetGtkSplitterFullSize() 
 160     return SASH_SIZE 
+ SASH_MARGIN
; 
 163 wxSplitterRenderParams
 
 164 wxRendererGTK::GetSplitterParams(const wxWindow 
*WXUNUSED(win
)) 
 166     // we don't draw any border, hence 0 for the second field 
 167     return wxSplitterRenderParams
 
 169                GetGtkSplitterFullSize(), 
 176 wxRendererGTK::DrawSplitterBorder(wxWindow 
* WXUNUSED(win
), 
 178                                   const wxRect
& WXUNUSED(rect
), 
 185 wxRendererGTK::DrawSplitterSash(wxWindow 
*win
, 
 189                                 wxOrientation orient
, 
 192     if ( !win
->m_wxwindow
->window 
) 
 194         // window not realized yet 
 198     wxCoord full_size 
= GetGtkSplitterFullSize(); 
 200     // are we drawing vertical or horizontal splitter? 
 201     const bool isVert 
= orient 
== wxVERTICAL
; 
 205     GdkRectangle erase_rect
; 
 210         int h 
= win
->GetClientSize().GetHeight(); 
 214         rect
.width 
= full_size
; 
 218         erase_rect
.x 
= position
; 
 220         erase_rect
.width 
= full_size
; 
 221         erase_rect
.height 
= h
; 
 226         int w 
= win
->GetClientSize().GetWidth(); 
 230         rect
.height 
= full_size
; 
 234         erase_rect
.y 
= position
; 
 236         erase_rect
.height 
= full_size
; 
 237         erase_rect
.width 
= w
; 
 242     // we must erase everything first, otherwise the garbage 
 243     // from the old sash is left when dragging it 
 246         win
->m_wxwindow
->style
, 
 247         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 252         (char *)"viewportbin", // const_cast 
 261     // leave some margin before sash itself 
 262     position 
+= SASH_MARGIN 
/ 2; 
 264     // and finally draw it using GTK paint functions 
 265     typedef void (*GtkPaintLineFunc
)(GtkStyle 
*, GdkWindow 
*, 
 267                                                 GdkRectangle 
*, GtkWidget 
*, 
 271     GtkPaintLineFunc func 
= isVert 
? gtk_paint_vline 
: gtk_paint_hline
; 
 275         win
->m_wxwindow
->style
, 
 276         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 280         (char *)"paned", // const_cast 
 281         0, isVert 
? size
.y 
: size
.x
, position 
+ SASH_SIZE 
/ 2 - 1 
 286         win
->m_wxwindow
->style
, 
 287         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 290         (GdkRectangle
*) NULL
, 
 292         (char *)"paned", // const_cast 
 293         isVert 
? position 
: size
.x 
- 2*SASH_SIZE
, 
 294         isVert 
? size
.y 
- 2*SASH_SIZE 
: position
, 
 300 wxRendererGTK::DrawDropArrow(wxWindow 
*win
, 
 305     GtkWidget 
*button 
= GetButtonWidget(); 
 307     // If we give GTK_PIZZA(win->m_wxwindow)->bin_window as 
 308     // a window for gtk_paint_xxx function, then it won't 
 309     // work for wxMemoryDC. So that is why we assume wxDC 
 310     // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC 
 311     // are derived from it) and use its m_window. 
 312     wxWindowDC
& wdc 
= (wxWindowDC
&)dc
; 
 314     // only doing debug-time checking here (it should 
 315     // probably be enough) 
 316     wxASSERT ( wdc
.IsKindOf(CLASSINFO(wxWindowDC
)) ); 
 318     // draw arrow so that there is even space horizontally 
 320     int arrowX 
= rect
.width
/4 + 1; 
 321     int arrowWidth 
= rect
.width 
- (arrowX
*2); 
 323     // scale arrow's height accoording to the width 
 324     int arrowHeight 
= rect
.width
/3; 
 325     int arrowY 
= (rect
.height
-arrowHeight
)/2 + 
 326                  ((rect
.height
-arrowHeight
) & 1); 
 330     if ( flags 
& wxCONTROL_PRESSED 
) 
 331         state 
= GTK_STATE_ACTIVE
; 
 332     else if ( flags 
& wxCONTROL_DISABLED 
) 
 333         state 
= GTK_STATE_INSENSITIVE
; 
 334     else if ( flags 
& wxCONTROL_CURRENT 
) 
 335         state 
= GTK_STATE_PRELIGHT
; 
 337         state 
= GTK_STATE_NORMAL
; 
 339     // draw arrow on button 
 345         flags 
& wxCONTROL_PRESSED 
? GTK_SHADOW_IN 
: GTK_SHADOW_OUT
, 
 359 wxRendererGTK::DrawComboBoxDropButton(wxWindow 
*win
, 
 364     GtkWidget 
*button 
= GetButtonWidget(); 
 366     // for reason why we do this, see DrawDropArrow 
 367     wxWindowDC
& wdc 
= (wxWindowDC
&)dc
; 
 368     wxASSERT ( wdc
.IsKindOf(CLASSINFO(wxWindowDC
)) ); 
 373     if ( flags 
& wxCONTROL_PRESSED 
) 
 374         state 
= GTK_STATE_ACTIVE
; 
 375     else if ( flags 
& wxCONTROL_DISABLED 
) 
 376         state 
= GTK_STATE_INSENSITIVE
; 
 377     else if ( flags 
& wxCONTROL_CURRENT 
) 
 378         state 
= GTK_STATE_PRELIGHT
; 
 380         state 
= GTK_STATE_NORMAL
; 
 387         flags 
& wxCONTROL_PRESSED 
? GTK_SHADOW_IN 
: GTK_SHADOW_OUT
, 
 391         rect
.x
, rect
.y
, rect
.width
, rect
.height
 
 394     // draw arrow on button 
 395     DrawDropArrow(win
,dc
,rect
,flags
);