]> git.saurik.com Git - wxWidgets.git/blob - src/gtk1/renderer.cpp
Added wx.RendererNative.DrawCheckButton.
[wxWidgets.git] / src / gtk1 / renderer.cpp
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/gtk1/win_gtk.h"
30
31 #include "wx/window.h"
32 #include "wx/dc.h"
33 #include "wx/dcclient.h"
34
35 // RR: After a correction to the orientation of the sash
36 // this doesn't seem to be required anymore and it
37 // seems to confuse some themes so USE_ERASE_RECT=0
38 #define USE_ERASE_RECT 0
39
40 // ----------------------------------------------------------------------------
41 // wxRendererGTK: our wxRendererNative implementation
42 // ----------------------------------------------------------------------------
43
44 class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
45 {
46 public:
47 // draw the header control button (used by wxListCtrl)
48 virtual void DrawHeaderButton(wxWindow *win,
49 wxDC& dc,
50 const wxRect& rect,
51 int flags = 0);
52
53 virtual void DrawSplitterBorder(wxWindow *win,
54 wxDC& dc,
55 const wxRect& rect,
56 int flags = 0);
57 virtual void DrawSplitterSash(wxWindow *win,
58 wxDC& dc,
59 const wxSize& size,
60 wxCoord position,
61 wxOrientation orient,
62 int flags = 0);
63
64 virtual void DrawComboBoxDropButton(wxWindow *win,
65 wxDC& dc,
66 const wxRect& rect,
67 int flags = 0);
68
69 virtual void DrawDropArrow(wxWindow *win,
70 wxDC& dc,
71 const wxRect& rect,
72 int flags = 0);
73
74 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
75
76 private:
77 // FIXME: shouldn't we destroy these windows somewhere?
78
79 // used by DrawHeaderButton and DrawComboBoxDropButton
80 static GtkWidget *GetButtonWidget();
81 };
82
83 // ============================================================================
84 // implementation
85 // ============================================================================
86
87 /* static */
88 wxRendererNative& wxRendererNative::GetDefault()
89 {
90 static wxRendererGTK s_rendererGTK;
91
92 return s_rendererGTK;
93 }
94
95 // ----------------------------------------------------------------------------
96 // helper functions
97 // ----------------------------------------------------------------------------
98
99 GtkWidget *
100 wxRendererGTK::GetButtonWidget()
101 {
102 static GtkWidget *s_button = NULL;
103 static GtkWidget *s_window = NULL;
104
105 if ( !s_button )
106 {
107 s_window = gtk_window_new( GTK_WINDOW_POPUP );
108 gtk_widget_realize( s_window );
109 s_button = gtk_button_new();
110 gtk_container_add( GTK_CONTAINER(s_window), s_button );
111 gtk_widget_realize( s_button );
112 }
113
114 return s_button;
115 }
116
117 // ----------------------------------------------------------------------------
118 // list/tree controls drawing
119 // ----------------------------------------------------------------------------
120
121 void
122 wxRendererGTK::DrawHeaderButton(wxWindow *win,
123 wxDC& dc,
124 const wxRect& rect,
125 int flags)
126 {
127
128 GtkWidget *button = GetButtonWidget();
129
130 gtk_paint_box
131 (
132 button->style,
133 // FIXME: I suppose GTK_PIZZA(win->m_wxwindow)->bin_window doesn't work with wxMemoryDC.
134 // Maybe use code similar as in DrawComboBoxDropButton below?
135 GTK_PIZZA(win->m_wxwindow)->bin_window,
136 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
137 GTK_SHADOW_OUT,
138 NULL,
139 button,
140 "button",
141 dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
142 );
143 }
144
145 // ----------------------------------------------------------------------------
146 // splitter sash drawing
147 // ----------------------------------------------------------------------------
148
149 // the full sash width (should be even)
150 static const wxCoord SASH_SIZE = 8;
151
152 // margin around the sash
153 static const wxCoord SASH_MARGIN = 2;
154
155 static int GetGtkSplitterFullSize()
156 {
157 return SASH_SIZE + SASH_MARGIN;
158 }
159
160 wxSplitterRenderParams
161 wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
162 {
163 // we don't draw any border, hence 0 for the second field
164 return wxSplitterRenderParams
165 (
166 GetGtkSplitterFullSize(),
167 0,
168 false // not
169 );
170 }
171
172 void
173 wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
174 wxDC& WXUNUSED(dc),
175 const wxRect& WXUNUSED(rect),
176 int WXUNUSED(flags))
177 {
178 // nothing to do
179 }
180
181 void
182 wxRendererGTK::DrawSplitterSash(wxWindow *win,
183 wxDC& dc,
184 const wxSize& size,
185 wxCoord position,
186 wxOrientation orient,
187 int WXUNUSED(flags))
188 {
189 if ( !win->m_wxwindow->window )
190 {
191 // window not realized yet
192 return;
193 }
194
195 wxCoord full_size = GetGtkSplitterFullSize();
196
197 // are we drawing vertical or horizontal splitter?
198 const bool isVert = orient == wxVERTICAL;
199
200 GdkRectangle rect;
201 #if USE_ERASE_RECT
202 GdkRectangle erase_rect;
203 #endif
204
205 if ( isVert )
206 {
207 int h = win->GetClientSize().GetHeight();
208
209 rect.x = position;
210 rect.y = 0;
211 rect.width = full_size;
212 rect.height = h;
213
214 #if USE_ERASE_RECT
215 erase_rect.x = position;
216 erase_rect.y = 0;
217 erase_rect.width = full_size;
218 erase_rect.height = h;
219 #endif
220 }
221 else // horz
222 {
223 int w = win->GetClientSize().GetWidth();
224
225 rect.x = 0;
226 rect.y = position;
227 rect.height = full_size;
228 rect.width = w;
229
230 #if USE_ERASE_RECT
231 erase_rect.y = position;
232 erase_rect.x = 0;
233 erase_rect.height = full_size;
234 erase_rect.width = w;
235 #endif
236 }
237
238 #if USE_ERASE_RECT
239 // we must erase everything first, otherwise the garbage
240 // from the old sash is left when dragging it
241 gtk_paint_flat_box
242 (
243 win->m_wxwindow->style,
244 GTK_PIZZA(win->m_wxwindow)->bin_window,
245 GTK_STATE_NORMAL,
246 GTK_SHADOW_NONE,
247 NULL,
248 win->m_wxwindow,
249 (char *)"viewportbin", // const_cast
250 erase_rect.x,
251 erase_rect.y,
252 erase_rect.width,
253 erase_rect.height
254 );
255 #endif
256
257
258 // leave some margin before sash itself
259 position += SASH_MARGIN / 2;
260
261 // and finally draw it using GTK paint functions
262 typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
263 GtkStateType,
264 GdkRectangle *, GtkWidget *,
265 gchar *,
266 gint, gint, gint);
267
268 GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
269
270 (*func)
271 (
272 win->m_wxwindow->style,
273 GTK_PIZZA(win->m_wxwindow)->bin_window,
274 GTK_STATE_NORMAL,
275 NULL,
276 win->m_wxwindow,
277 (char *)"paned", // const_cast
278 0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
279 );
280
281 gtk_paint_box
282 (
283 win->m_wxwindow->style,
284 GTK_PIZZA(win->m_wxwindow)->bin_window,
285 GTK_STATE_NORMAL,
286 GTK_SHADOW_OUT,
287 (GdkRectangle*) NULL,
288 win->m_wxwindow,
289 (char *)"paned", // const_cast
290 isVert ? position : size.x - 2*SASH_SIZE,
291 isVert ? size.y - 2*SASH_SIZE : position,
292 SASH_SIZE, SASH_SIZE
293 );
294 }
295
296 void
297 wxRendererGTK::DrawDropArrow(wxWindow *win,
298 wxDC& dc,
299 const wxRect& rect,
300 int flags)
301 {
302 GtkWidget *button = GetButtonWidget();
303
304 // If we give GTK_PIZZA(win->m_wxwindow)->bin_window as
305 // a window for gtk_paint_xxx function, then it won't
306 // work for wxMemoryDC. So that is why we assume wxDC
307 // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC
308 // are derived from it) and use its m_window.
309 wxWindowDC& wdc = (wxWindowDC&)dc;
310
311 // only doing debug-time checking here (it should
312 // probably be enough)
313 wxASSERT ( wdc.IsKindOf(CLASSINFO(wxWindowDC)) );
314
315 // draw arrow so that there is even space horizontally
316 // on both sides
317 int arrowX = rect.width/4 + 1;
318 int arrowWidth = rect.width - (arrowX*2);
319
320 // scale arrow's height accoording to the width
321 int arrowHeight = rect.width/3;
322 int arrowY = (rect.height-arrowHeight)/2 +
323 ((rect.height-arrowHeight) & 1);
324
325 GtkStateType state;
326
327 if ( flags & wxCONTROL_PRESSED )
328 state = GTK_STATE_ACTIVE;
329 else if ( flags & wxCONTROL_DISABLED )
330 state = GTK_STATE_INSENSITIVE;
331 else if ( flags & wxCONTROL_CURRENT )
332 state = GTK_STATE_PRELIGHT;
333 else
334 state = GTK_STATE_NORMAL;
335
336 // draw arrow on button
337 gtk_paint_arrow
338 (
339 button->style,
340 wdc.m_window,
341 state,
342 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
343 NULL,
344 button,
345 "arrow",
346 GTK_ARROW_DOWN,
347 FALSE,
348 rect.x + arrowX,
349 rect.y + arrowY,
350 arrowWidth,
351 arrowHeight
352 );
353 }
354
355 void
356 wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
357 wxDC& dc,
358 const wxRect& rect,
359 int flags)
360 {
361 GtkWidget *button = GetButtonWidget();
362
363 // for reason why we do this, see DrawDropArrow
364 wxWindowDC& wdc = (wxWindowDC&)dc;
365 wxASSERT ( wdc.IsKindOf(CLASSINFO(wxWindowDC)) );
366
367 // draw button
368 GtkStateType state;
369
370 if ( flags & wxCONTROL_PRESSED )
371 state = GTK_STATE_ACTIVE;
372 else if ( flags & wxCONTROL_DISABLED )
373 state = GTK_STATE_INSENSITIVE;
374 else if ( flags & wxCONTROL_CURRENT )
375 state = GTK_STATE_PRELIGHT;
376 else
377 state = GTK_STATE_NORMAL;
378
379 gtk_paint_box
380 (
381 button->style,
382 wdc.m_window,
383 state,
384 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
385 NULL,
386 button,
387 "button",
388 rect.x, rect.y, rect.width, rect.height
389 );
390
391 // draw arrow on button
392 DrawDropArrow(win,dc,rect,flags);
393
394 }