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"
35 #include "wx/settings.h"
39 #define WXUNUSED_IN_GTK1(arg) arg
41 #define WXUNUSED_IN_GTK1(arg)
44 // ----------------------------------------------------------------------------
45 // wxRendererGTK: our wxRendererNative implementation
46 // ----------------------------------------------------------------------------
48 class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
51 // draw the header control button (used by wxListCtrl)
52 virtual void DrawHeaderButton(wxWindow *win,
58 // draw the expanded/collapsed icon for a tree control item
59 virtual void DrawTreeItemButton(wxWindow *win,
65 virtual void DrawSplitterBorder(wxWindow *win,
69 virtual void DrawSplitterSash(wxWindow *win,
76 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
79 // ============================================================================
81 // ============================================================================
84 wxRendererNative& wxRendererNative::GetDefault()
86 static wxRendererGTK s_rendererGTK;
91 // ----------------------------------------------------------------------------
92 // list/tree controls drawing
93 // ----------------------------------------------------------------------------
96 wxRendererGTK::DrawHeaderButton(wxWindow *win,
102 static GtkWidget *s_button = NULL;
103 static GtkWidget *s_window = NULL;
104 if (s_button == NULL)
106 s_window = gtk_window_new( GTK_WINDOW_POPUP );
107 gtk_widget_realize( s_window );
108 s_button = gtk_button_new();
109 gtk_container_add( GTK_CONTAINER(s_window), s_button );
110 gtk_widget_realize( s_button );
116 GTK_PIZZA(win->m_wxwindow)->bin_window,
117 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
122 dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
128 // draw a ">" or "v" button
130 // TODO: isn't there a GTK function to draw it?
132 wxRendererGTK::DrawTreeItemButton(wxWindow* win,
133 wxDC& dc, const wxRect& rect, int flags)
139 GtkPizza *pizza = GTK_PIZZA( win->m_wxwindow );
140 GtkStyle *style = win->m_widget->style;
143 y = dc.LogicalToDeviceY( y );
144 x = dc.LogicalToDeviceX( x );
147 // This draws the GTK+ 2.2.4 triangle
151 if ( flags & wxCONTROL_EXPANDED )
154 points[0].y = y + (PM_SIZE + 2) / 6;
155 points[1].x = points[0].x + (PM_SIZE + 2);
156 points[1].y = points[0].y;
157 points[2].x = (points[0].x + (PM_SIZE + 2) / 2);
158 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
162 points[0].x = x + ((PM_SIZE + 2) / 6 + 2);
164 points[1].x = points[0].x;
165 points[1].y = points[0].y + (PM_SIZE + 2);
166 points[2].x = (points[0].x +
167 (2 * (PM_SIZE + 2) / 3 - 1));
168 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
171 if ( flags & wxCONTROL_CURRENT )
172 gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_PRELIGHT], TRUE, points, 3);
174 gdk_draw_polygon( pizza->bin_window, style->base_gc[GTK_STATE_NORMAL], TRUE, points, 3);
175 gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL], FALSE, points, 3 );
177 // this draws the GTK+ 2.2.3 tree item square
178 gdk_draw_rectangle( pizza->bin_window,
179 style->base_gc[GTK_STATE_NORMAL], TRUE,
180 x, y, PM_SIZE, PM_SIZE);
181 gdk_draw_rectangle( pizza->bin_window,
182 style->fg_gc[GTK_STATE_NORMAL], FALSE,
183 x, y, PM_SIZE, PM_SIZE);
185 gdk_draw_line( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL],
186 x + 2, y + PM_SIZE / 2, x + PM_SIZE - 2, y + PM_SIZE / 2);
188 if ( flags & wxCONTROL_EXPANDED )
190 gdk_draw_line( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL],
191 x + PM_SIZE / 2, y + 2,
192 x + PM_SIZE / 2, y + PM_SIZE - 2);
198 dc.SetBrush(wxBrush(wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT),
200 dc.SetPen(*wxBLACK_PEN);
203 const wxCoord xMiddle = rect.x + rect.width/2;
204 const wxCoord yMiddle = rect.y + rect.height/2;
206 if ( flags & wxCONTROL_EXPANDED )
208 button[0].x = rect.GetLeft();
209 button[0].y = yMiddle - 2;
210 button[1].x = rect.GetRight();
211 button[1].y = yMiddle - 2;
212 button[2].x = xMiddle;
213 button[2].y = yMiddle + 3;
217 button[0].y = rect.GetBottom();
218 button[0].x = xMiddle - 2;
219 button[1].y = rect.GetTop();
220 button[1].x = xMiddle - 2;
221 button[2].y = yMiddle;
222 button[2].x = xMiddle + 3;
225 dc.DrawPolygon(3, button);
231 // ----------------------------------------------------------------------------
232 // splitter sash drawing
233 // ----------------------------------------------------------------------------
235 // all this should probably be read from the current theme settings somehow?
237 // the full sash size
238 static const wxCoord SASH_FULL_SIZE = 5;
240 // the full sash width (should be even)
241 static const wxCoord SASH_SIZE = 8;
243 // margin around the sash
244 static const wxCoord SASH_MARGIN = 2;
246 // the full sash size
247 static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN;
248 #endif // GTK+ 2.x/1.x
250 wxSplitterRenderParams
251 wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win))
253 // we don't draw any border, hence 0 for the second field
254 return wxSplitterRenderParams
259 true // hot sensitive
262 #endif // GTK+ 2.x/1.x
267 wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
269 const wxRect& WXUNUSED(rect),
276 wxRendererGTK::DrawSplitterSash(wxWindow *win,
280 wxOrientation orient,
281 int WXUNUSED_IN_GTK1(flags))
283 if ( !win->m_wxwindow->window )
285 // window not realized yet
289 // are we drawing vertical or horizontal splitter?
290 const bool isVert = orient == wxVERTICAL;
293 GdkRectangle erase_rect;
296 int h = win->GetClientSize().GetHeight();
300 rect.width = SASH_FULL_SIZE;
303 erase_rect.x = position;
305 erase_rect.width = SASH_FULL_SIZE;
306 erase_rect.height = h;
310 int w = win->GetClientSize().GetWidth();
314 rect.height = SASH_FULL_SIZE;
317 erase_rect.y = position;
319 erase_rect.height = SASH_FULL_SIZE;
320 erase_rect.width = w;
323 // we must erase everything first, otherwise the garbage from the old sash
324 // is left when dragging it
326 // TODO: is this the right way to draw themed background?
329 win->m_wxwindow->style,
330 GTK_PIZZA(win->m_wxwindow)->bin_window,
335 (char *)"base", // const_cast
345 win->m_wxwindow->style,
346 GTK_PIZZA(win->m_wxwindow)->bin_window,
347 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
349 NULL /* no clipping */,
356 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
360 // leave some margin before sash itself
361 position += SASH_MARGIN / 2;
363 // and finally draw it using GTK paint functions
364 typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
366 GdkRectangle *, GtkWidget *,
370 GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
374 win->m_wxwindow->style,
375 GTK_PIZZA(win->m_wxwindow)->bin_window,
379 (char *)"paned", // const_cast
380 0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
385 win->m_wxwindow->style,
386 GTK_PIZZA(win->m_wxwindow)->bin_window,
389 (GdkRectangle*) NULL,
391 (char *)"paned", // const_cast
392 isVert ? position : size.x - 2*SASH_SIZE,
393 isVert ? size.y - 2*SASH_SIZE : position,
396 #endif // GTK+ 2.x/1.x