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