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