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