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