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