]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/gtk1/renderer.cpp
Added assert (WinCE doesn't report checked status correctly)
[wxWidgets.git] / src / gtk1 / renderer.cpp
... / ...
CommitLineData
1///////////////////////////////////////////////////////////////////////////////
2// Name: gtk/renderer.cpp
3// Purpose: implementation of wxRendererNative for wxGTK
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 20.07.2003
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9// License: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20// for compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#include "wx/renderer.h"
28#include <gtk/gtk.h>
29#include "wx/gtk/win_gtk.h"
30
31#include "wx/window.h"
32#include "wx/dc.h"
33
34#ifdef __WXGTK20__
35 #include "wx/settings.h"
36#endif // GTK 2.0
37
38#ifdef __WXGTK20__
39 #define WXUNUSED_IN_GTK1(arg) arg
40#else
41 #define WXUNUSED_IN_GTK1(arg)
42#endif
43
44// ----------------------------------------------------------------------------
45// wxRendererGTK: our wxRendererNative implementation
46// ----------------------------------------------------------------------------
47
48class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
49{
50public:
51 // draw the header control button (used by wxListCtrl)
52 virtual void DrawHeaderButton(wxWindow *win,
53 wxDC& dc,
54 const wxRect& rect,
55 int flags = 0);
56
57#ifdef __WXGTK20__
58 // draw the expanded/collapsed icon for a tree control item
59 virtual void DrawTreeItemButton(wxWindow *win,
60 wxDC& dc,
61 const wxRect& rect,
62 int flags = 0);
63#endif // GTK 2.0
64
65 virtual void DrawSplitterBorder(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
69 virtual void DrawSplitterSash(wxWindow *win,
70 wxDC& dc,
71 const wxSize& size,
72 wxCoord position,
73 wxOrientation orient,
74 int flags = 0);
75
76 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
77};
78
79// ============================================================================
80// implementation
81// ============================================================================
82
83/* static */
84wxRendererNative& wxRendererNative::GetDefault()
85{
86 static wxRendererGTK s_rendererGTK;
87
88 return s_rendererGTK;
89}
90
91// ----------------------------------------------------------------------------
92// list/tree controls drawing
93// ----------------------------------------------------------------------------
94
95void
96wxRendererGTK::DrawHeaderButton(wxWindow *win,
97 wxDC& dc,
98 const wxRect& rect,
99 int flags)
100{
101
102 static GtkWidget *s_button = NULL;
103 static GtkWidget *s_window = NULL;
104 if (s_button == NULL)
105 {
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 );
111 }
112
113 gtk_paint_box
114 (
115 s_button->style,
116 GTK_PIZZA(win->m_wxwindow)->bin_window,
117 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
118 GTK_SHADOW_OUT,
119 NULL,
120 s_button,
121 "button",
122 dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
123 );
124}
125
126#ifdef __WXGTK20__
127
128// draw a ">" or "v" button
129//
130// TODO: replace the code below with gtk_paint_expander()
131void
132wxRendererGTK::DrawTreeItemButton(wxWindow* win,
133 wxDC& dc, const wxRect& rect, int flags)
134{
135#define PM_SIZE 8
136
137 GtkPizza *pizza = GTK_PIZZA( win->m_wxwindow );
138 GtkStyle *style = win->m_widget->style;
139 int x = rect.x;
140 int y = rect.y;
141 y = dc.LogicalToDeviceY( y );
142 x = dc.LogicalToDeviceX( x );
143
144 // This draws the GTK+ 2.2.4 triangle
145 x--;
146 GdkPoint points[3];
147
148 if ( flags & wxCONTROL_EXPANDED )
149 {
150 points[0].x = x;
151 points[0].y = y + (PM_SIZE + 2) / 6;
152 points[1].x = points[0].x + (PM_SIZE + 2);
153 points[1].y = points[0].y;
154 points[2].x = (points[0].x + (PM_SIZE + 2) / 2);
155 points[2].y = y + 2 * (PM_SIZE + 2) / 3;
156 }
157 else
158 {
159 points[0].x = x + ((PM_SIZE + 2) / 6 + 2);
160 points[0].y = y - 1;
161 points[1].x = points[0].x;
162 points[1].y = points[0].y + (PM_SIZE + 2);
163 points[2].x = (points[0].x +
164 (2 * (PM_SIZE + 2) / 3 - 1));
165 points[2].y = points[0].y + (PM_SIZE + 2) / 2;
166 }
167
168 if ( flags & wxCONTROL_CURRENT )
169 gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_PRELIGHT], TRUE, points, 3);
170 else
171 gdk_draw_polygon( pizza->bin_window, style->base_gc[GTK_STATE_NORMAL], TRUE, points, 3);
172 gdk_draw_polygon( pizza->bin_window, style->fg_gc[GTK_STATE_NORMAL], FALSE, points, 3 );
173}
174
175#endif // GTK 2.0
176
177// ----------------------------------------------------------------------------
178// splitter sash drawing
179// ----------------------------------------------------------------------------
180
181// all this should probably be read from the current theme settings somehow?
182#ifdef __WXGTK20__
183 // the full sash size
184 static const wxCoord SASH_FULL_SIZE = 5;
185#else // GTK+ 1.x
186 // the full sash width (should be even)
187 static const wxCoord SASH_SIZE = 8;
188
189 // margin around the sash
190 static const wxCoord SASH_MARGIN = 2;
191
192 // the full sash size
193 static const wxCoord SASH_FULL_SIZE = SASH_SIZE + SASH_MARGIN;
194#endif // GTK+ 2.x/1.x
195
196wxSplitterRenderParams
197wxRendererGTK::GetSplitterParams(const wxWindow * WXUNUSED(win))
198{
199 // we don't draw any border, hence 0 for the second field
200 return wxSplitterRenderParams
201 (
202 SASH_FULL_SIZE,
203 0,
204#ifdef __WXGTK20__
205 true // hot sensitive
206#else // GTK+ 1.x
207 false // not
208#endif // GTK+ 2.x/1.x
209 );
210}
211
212void
213wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
214 wxDC& WXUNUSED(dc),
215 const wxRect& WXUNUSED(rect),
216 int WXUNUSED(flags))
217{
218 // nothing to do
219}
220
221void
222wxRendererGTK::DrawSplitterSash(wxWindow *win,
223 wxDC& dc,
224 const wxSize& size,
225 wxCoord position,
226 wxOrientation orient,
227 int WXUNUSED_IN_GTK1(flags))
228{
229 if ( !win->m_wxwindow->window )
230 {
231 // window not realized yet
232 return;
233 }
234
235 // are we drawing vertical or horizontal splitter?
236 const bool isVert = orient == wxVERTICAL;
237
238 GdkRectangle rect;
239 GdkRectangle erase_rect;
240 if ( isVert )
241 {
242 int h = win->GetClientSize().GetHeight();
243
244 rect.x = position;
245 rect.y = 0;
246 rect.width = SASH_FULL_SIZE;
247 rect.height = h;
248
249 erase_rect.x = position;
250 erase_rect.y = 0;
251 erase_rect.width = SASH_FULL_SIZE;
252 erase_rect.height = h;
253 }
254 else // horz
255 {
256 int w = win->GetClientSize().GetWidth();
257
258 rect.x = 0;
259 rect.y = position;
260 rect.height = SASH_FULL_SIZE;
261 rect.width = w;
262
263 erase_rect.y = position;
264 erase_rect.x = 0;
265 erase_rect.height = SASH_FULL_SIZE;
266 erase_rect.width = w;
267 }
268
269 // we must erase everything first, otherwise the garbage from the old sash
270 // is left when dragging it
271 //
272 // TODO: is this the right way to draw themed background?
273 gtk_paint_flat_box
274 (
275 win->m_wxwindow->style,
276 GTK_PIZZA(win->m_wxwindow)->bin_window,
277 GTK_STATE_NORMAL,
278 GTK_SHADOW_NONE,
279 NULL,
280 win->m_wxwindow,
281 (char *)"base", // const_cast
282 erase_rect.x,
283 erase_rect.y,
284 erase_rect.width,
285 erase_rect.height
286 );
287
288#ifdef __WXGTK20__
289 gtk_paint_handle
290 (
291 win->m_wxwindow->style,
292 GTK_PIZZA(win->m_wxwindow)->bin_window,
293 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
294 GTK_SHADOW_NONE,
295 NULL /* no clipping */,
296 win->m_wxwindow,
297 "paned",
298 rect.x,
299 rect.y,
300 rect.width,
301 rect.height,
302 !isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
303 );
304#else // GTK+ 1.x
305
306 // leave some margin before sash itself
307 position += SASH_MARGIN / 2;
308
309 // and finally draw it using GTK paint functions
310 typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
311 GtkStateType,
312 GdkRectangle *, GtkWidget *,
313 gchar *,
314 gint, gint, gint);
315
316 GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
317
318 (*func)
319 (
320 win->m_wxwindow->style,
321 GTK_PIZZA(win->m_wxwindow)->bin_window,
322 GTK_STATE_NORMAL,
323 NULL,
324 win->m_wxwindow,
325 (char *)"paned", // const_cast
326 0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
327 );
328
329 gtk_paint_box
330 (
331 win->m_wxwindow->style,
332 GTK_PIZZA(win->m_wxwindow)->bin_window,
333 GTK_STATE_NORMAL,
334 GTK_SHADOW_OUT,
335 (GdkRectangle*) NULL,
336 win->m_wxwindow,
337 (char *)"paned", // const_cast
338 isVert ? position : size.x - 2*SASH_SIZE,
339 isVert ? size.y - 2*SASH_SIZE : position,
340 SASH_SIZE, SASH_SIZE
341 );
342#endif // GTK+ 2.x/1.x
343}
344