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
53 // used by DrawHeaderButton and DrawComboBoxDropButton
54 void PrepareButtonDraw();
56 // draw the header control button (used by wxListCtrl)
57 virtual void DrawHeaderButton(wxWindow
*win
,
63 // draw the expanded/collapsed icon for a tree control item
64 virtual void DrawTreeItemButton(wxWindow
*win
,
70 virtual void DrawSplitterBorder(wxWindow
*win
,
74 virtual void DrawSplitterSash(wxWindow
*win
,
81 virtual void DrawComboBoxDropButton(wxWindow
*win
,
86 virtual wxSplitterRenderParams
GetSplitterParams(const wxWindow
*win
);
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 );
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
)) );
385 GtkStateType state
= GTK_STATE_NORMAL
;
386 GtkShadowType shadow
= GTK_SHADOW_OUT
;
388 if ( flags
& wxCONTROL_PRESSED
)
389 shadow
= GTK_SHADOW_IN
;
390 else if ( flags
& wxCONTROL_CURRENT
)
391 state
= GTK_STATE_PRELIGHT
;
392 else if ( flags
& wxCONTROL_DISABLED
)
393 state
= GTK_STATE_INSENSITIVE
;
398 //GTK_PIZZA(wdc->m_window)->bin_window,
405 dc
.XLOG2DEV(rect
.x
), rect
.y
, rect
.width
, rect
.height
408 // draw arrow on button
410 int arr_wid
= rect
.width
/2;
411 int arr_hei
= rect
.height
/2;
412 arr_wid
+= arr_wid
& 1;
413 arr_hei
+= arr_hei
& 1;
418 //GTK_PIZZA(wdc->m_window)->bin_window,
427 dc
.XLOG2DEV(rect
.x
) + (rect
.width
/2-arr_wid
/2) + 1,
428 rect
.y
+ (rect
.height
/2-arr_hei
/2) + 1,