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