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" 
  36     #include "wx/settings.h" 
  40     #define WXUNUSED_IN_GTK1(arg) arg 
  42     #define WXUNUSED_IN_GTK1(arg) 
  45 // ---------------------------------------------------------------------------- 
  46 // wxRendererGTK: our wxRendererNative implementation 
  47 // ---------------------------------------------------------------------------- 
  49 class WXDLLEXPORT wxRendererGTK 
: public wxDelegateRendererNative
 
  52     // draw the header control button (used by wxListCtrl) 
  53     virtual void DrawHeaderButton(wxWindow 
*win
, 
  59     // draw the expanded/collapsed icon for a tree control item 
  60     virtual void DrawTreeItemButton(wxWindow 
*win
, 
  66     virtual void DrawSplitterBorder(wxWindow 
*win
, 
  70     virtual void DrawSplitterSash(wxWindow 
*win
, 
  77     virtual void DrawComboBoxDropButton(wxWindow 
*win
, 
  82     virtual wxSplitterRenderParams 
GetSplitterParams(const wxWindow 
*win
); 
  85     // used by DrawHeaderButton and DrawComboBoxDropButton 
  86     void PrepareButtonDraw(); 
  89 // ============================================================================ 
  91 // ============================================================================ 
  94 wxRendererNative
& wxRendererNative::GetDefault() 
  96     static wxRendererGTK s_rendererGTK
; 
 101 // ---------------------------------------------------------------------------- 
 103 // ---------------------------------------------------------------------------- 
 105 static GtkWidget 
*gs_button 
= NULL
; 
 106 static GtkWidget 
*gs_window 
= NULL
; 
 109 wxRendererGTK::PrepareButtonDraw() 
 111     // prepares gs_button and gs_window which are used when 
 112     // drawing button based elements. 
 113     wxASSERT ( !gs_button 
); 
 115     gs_window 
= gtk_window_new( GTK_WINDOW_POPUP 
); 
 116     gtk_widget_realize( gs_window 
); 
 117     gs_button 
= gtk_button_new(); 
 118     gtk_container_add( GTK_CONTAINER(gs_window
), gs_button 
); 
 119     gtk_widget_realize( gs_button 
); 
 122 // ---------------------------------------------------------------------------- 
 123 // list/tree controls drawing 
 124 // ---------------------------------------------------------------------------- 
 127 wxRendererGTK::DrawHeaderButton(wxWindow 
*win
, 
 133     if (gs_button 
== NULL
) 
 139         // FIXME: I suppose GTK_PIZZA(win->m_wxwindow)->bin_window doesn't work with wxMemoryDC. 
 140         //   Maybe use code similar as in DrawComboBoxDropButton below? 
 141         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 142         flags 
& wxCONTROL_DISABLED 
? GTK_STATE_INSENSITIVE 
: GTK_STATE_NORMAL
, 
 147         dc
.XLOG2DEV(rect
.x
) -1, rect
.y 
-1, rect
.width 
+2, rect
.height 
+2 
 153 // draw a ">" or "v" button 
 155 // TODO: replace the code below with gtk_paint_expander() 
 157 wxRendererGTK::DrawTreeItemButton(wxWindow
* win
, 
 158                                   wxDC
& dc
, const wxRect
& rect
, int flags
) 
 162     GtkPizza 
*pizza 
= GTK_PIZZA( win
->m_wxwindow 
); 
 163     GtkStyle 
*style 
= win
->m_widget
->style
; 
 166     y 
= dc
.LogicalToDeviceY( y 
); 
 167     x 
= dc
.LogicalToDeviceX( x 
); 
 169     // This draws the GTK+ 2.2.4 triangle 
 173     if ( flags 
& wxCONTROL_EXPANDED 
) 
 176         points
[0].y 
= y 
+ (PM_SIZE 
+ 2) / 6; 
 177         points
[1].x 
= points
[0].x 
+ (PM_SIZE 
+ 2); 
 178         points
[1].y 
= points
[0].y
; 
 179         points
[2].x 
= (points
[0].x 
+ (PM_SIZE 
+ 2) / 2); 
 180         points
[2].y 
= y 
+ 2 * (PM_SIZE 
+ 2) / 3; 
 184         points
[0].x 
= x 
+ ((PM_SIZE 
+ 2) / 6 + 2); 
 186         points
[1].x 
= points
[0].x
; 
 187         points
[1].y 
= points
[0].y 
+ (PM_SIZE 
+ 2); 
 188         points
[2].x 
= (points
[0].x 
+ 
 189              (2 * (PM_SIZE 
+ 2) / 3 - 1)); 
 190         points
[2].y 
= points
[0].y 
+ (PM_SIZE 
+ 2) / 2; 
 193     if ( flags 
& wxCONTROL_CURRENT 
) 
 194         gdk_draw_polygon( pizza
->bin_window
, style
->fg_gc
[GTK_STATE_PRELIGHT
], TRUE
, points
, 3); 
 196         gdk_draw_polygon( pizza
->bin_window
, style
->base_gc
[GTK_STATE_NORMAL
], TRUE
, points
, 3); 
 197     gdk_draw_polygon( pizza
->bin_window
, style
->fg_gc
[GTK_STATE_NORMAL
], FALSE
, points
, 3 ); 
 200 #endif // __WXGTK20__ 
 202 // ---------------------------------------------------------------------------- 
 203 // splitter sash drawing 
 204 // ---------------------------------------------------------------------------- 
 206 // all this should probably be read from the current theme settings somehow? 
 208     // the full sash size 
 209     static const wxCoord SASH_FULL_SIZE 
= 5; 
 211     // the full sash width (should be even) 
 212     static const wxCoord SASH_SIZE 
= 8; 
 214     // margin around the sash 
 215     static const wxCoord SASH_MARGIN 
= 2; 
 217     // the full sash size 
 218     static const wxCoord SASH_FULL_SIZE 
= SASH_SIZE 
+ SASH_MARGIN
; 
 219 #endif // GTK+ 2.x/1.x 
 221 wxSplitterRenderParams
 
 222 wxRendererGTK::GetSplitterParams(const wxWindow 
* WXUNUSED(win
)) 
 224     // we don't draw any border, hence 0 for the second field 
 225     return wxSplitterRenderParams
 
 230                true     // hot sensitive 
 233 #endif // GTK+ 2.x/1.x 
 238 wxRendererGTK::DrawSplitterBorder(wxWindow 
* WXUNUSED(win
), 
 240                                   const wxRect
& WXUNUSED(rect
), 
 247 wxRendererGTK::DrawSplitterSash(wxWindow 
*win
, 
 251                                 wxOrientation orient
, 
 252                                 int WXUNUSED_IN_GTK1(flags
)) 
 254     if ( !win
->m_wxwindow
->window 
) 
 256         // window not realized yet 
 260     // are we drawing vertical or horizontal splitter? 
 261     const bool isVert 
= orient 
== wxVERTICAL
; 
 264     GdkRectangle erase_rect
; 
 267         int h 
= win
->GetClientSize().GetHeight(); 
 271         rect
.width 
= SASH_FULL_SIZE
; 
 274         erase_rect
.x 
= position
; 
 276         erase_rect
.width 
= SASH_FULL_SIZE
; 
 277         erase_rect
.height 
= h
; 
 281         int w 
= win
->GetClientSize().GetWidth(); 
 285         rect
.height 
= SASH_FULL_SIZE
; 
 288         erase_rect
.y 
= position
; 
 290         erase_rect
.height 
= SASH_FULL_SIZE
; 
 291         erase_rect
.width 
= w
; 
 294     // we must erase everything first, otherwise the garbage from the old sash 
 295     // is left when dragging it 
 297     // TODO: is this the right way to draw themed background? 
 300         win
->m_wxwindow
->style
, 
 301         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 306         (char *)"base", // const_cast 
 316         win
->m_wxwindow
->style
, 
 317         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 318         flags 
& wxCONTROL_CURRENT 
? GTK_STATE_PRELIGHT 
: GTK_STATE_NORMAL
, 
 320         NULL 
/* no clipping */, 
 327         !isVert 
? GTK_ORIENTATION_VERTICAL 
: GTK_ORIENTATION_HORIZONTAL
 
 331     // leave some margin before sash itself 
 332     position 
+= SASH_MARGIN 
/ 2; 
 334     // and finally draw it using GTK paint functions 
 335     typedef void (*GtkPaintLineFunc
)(GtkStyle 
*, GdkWindow 
*, 
 337                                                 GdkRectangle 
*, GtkWidget 
*, 
 341     GtkPaintLineFunc func 
= isVert 
? gtk_paint_vline 
: gtk_paint_hline
; 
 345         win
->m_wxwindow
->style
, 
 346         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 350         (char *)"paned", // const_cast 
 351         0, isVert 
? size
.y 
: size
.x
, position 
+ SASH_SIZE 
/ 2 - 1 
 356         win
->m_wxwindow
->style
, 
 357         GTK_PIZZA(win
->m_wxwindow
)->bin_window
, 
 360         (GdkRectangle
*) NULL
, 
 362         (char *)"paned", // const_cast 
 363         isVert 
? position 
: size
.x 
- 2*SASH_SIZE
, 
 364         isVert 
? size
.y 
- 2*SASH_SIZE 
: position
, 
 367 #endif // GTK+ 2.x/1.x 
 370 void wxRendererGTK::DrawComboBoxDropButton(wxWindow 
*win
, 
 375     if (gs_button 
== NULL
) 
 378     // device context must inherit from wxWindowDC 
 379     // (so it must be wxClientDC, wxMemoryDC or wxPaintDC) 
 380     wxWindowDC
& wdc 
= (wxWindowDC
&)dc
; 
 382     // only doing debug-time checking here (it should probably be enough) 
 383     wxASSERT ( wdc
.IsKindOf(CLASSINFO(wxWindowDC
)) ); 
 387     if ( flags 
& wxCONTROL_CURRENT 
) 
 388         state 
= GTK_STATE_PRELIGHT
; 
 389     else if ( flags 
& wxCONTROL_DISABLED 
) 
 390         state 
= GTK_STATE_INSENSITIVE
; 
 392         state 
= GTK_STATE_NORMAL
; 
 394     // erase background first 
 404         rect
.x
, rect
.y
, rect
.width
, rect
.height
 
 407     // draw arrow on button 
 413         flags 
& wxCONTROL_PRESSED 
? GTK_SHADOW_IN 
: GTK_SHADOW_OUT
, 
 419         rect
.x 
+ 1, rect
.y 
+ 1, rect
.width 
- 2, rect
.height 
- 2