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