]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/renderer.cpp
fixed broken wxCtime() implementation (wrong buffer size count, wrong conversion)
[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:
bc13e772
VZ
85 // FIXME: shouldn't we destroy these windows somewhere?
86
e1befae3 87 // used by DrawHeaderButton and DrawComboBoxDropButton
bc13e772
VZ
88 static GtkWidget *GetButtonWidget();
89
90#ifdef __WXGTK20__
91 // used by DrawTreeItemButton()
92 static GtkWidget *GetTreeWidget();
93#endif // GTK+ 2.0
9c7f49f5
VZ
94};
95
96// ============================================================================
97// implementation
98// ============================================================================
99
100/* static */
f0244295 101wxRendererNative& wxRendererNative::GetDefault()
9c7f49f5
VZ
102{
103 static wxRendererGTK s_rendererGTK;
104
105 return s_rendererGTK;
106}
107
a4622f29 108// ----------------------------------------------------------------------------
bc13e772 109// helper functions
a4622f29
VZ
110// ----------------------------------------------------------------------------
111
bc13e772
VZ
112GtkWidget *
113wxRendererGTK::GetButtonWidget()
114{
115 static GtkWidget *s_button = NULL;
116 static GtkWidget *s_window = NULL;
a4622f29 117
bc13e772
VZ
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()
a4622f29 134{
bc13e772
VZ
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;
a4622f29
VZ
148}
149
bc13e772
VZ
150#endif // GTK+ 2.0
151
d16cf3cd
VZ
152// ----------------------------------------------------------------------------
153// list/tree controls drawing
154// ----------------------------------------------------------------------------
155
9c7f49f5
VZ
156void
157wxRendererGTK::DrawHeaderButton(wxWindow *win,
158 wxDC& dc,
159 const wxRect& rect,
160 int flags)
161{
9b311923 162
bc13e772 163 GtkWidget *button = GetButtonWidget();
9b311923 164
9c7f49f5
VZ
165 gtk_paint_box
166 (
bc13e772 167 button->style,
a4622f29
VZ
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?
9c7f49f5
VZ
170 GTK_PIZZA(win->m_wxwindow)->bin_window,
171 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
172 GTK_SHADOW_OUT,
38511687 173 NULL,
bc13e772 174 button,
9b311923
RR
175 "button",
176 dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
9c7f49f5
VZ
177 );
178}
179
180#ifdef __WXGTK20__
181
182// draw a ">" or "v" button
9c7f49f5 183void
f8b043e7 184wxRendererGTK::DrawTreeItemButton(wxWindow* win,
9a0b7e33 185 wxDC& dc, const wxRect& rect, int flags)
9c7f49f5 186{
bc13e772 187 GtkWidget *tree = GetTreeWidget();
f8b043e7 188
885dd597
RR
189 GtkStateType state;
190 if ( flags & wxCONTROL_CURRENT )
191 state = GTK_STATE_PRELIGHT;
192 else
193 state = GTK_STATE_NORMAL;
194
bc13e772
VZ
195 // VZ: I don't know how to get the size of the expander so as to centre it
196 // in the given rectangle, +2/3 below is just what looks good here...
197 gtk_paint_expander
198 (
199 tree->style,
200 GTK_PIZZA(win->m_wxwindow)->bin_window,
885dd597 201 state,
bc13e772
VZ
202 NULL,
203 tree,
204 "treeview",
205 dc.LogicalToDeviceX(rect.x) + 2,
206 dc.LogicalToDeviceY(rect.y) + 3,
207 flags & wxCONTROL_EXPANDED ? GTK_EXPANDER_EXPANDED
208 : GTK_EXPANDER_COLLAPSED
209 );
9c7f49f5
VZ
210}
211
bc13e772 212#endif // GTK+ 2.0
9c7f49f5 213
d16cf3cd
VZ
214// ----------------------------------------------------------------------------
215// splitter sash drawing
216// ----------------------------------------------------------------------------
217
38418827 218#ifndef __WXGTK20__
af99040c 219 // the full sash width (should be even)
35468934 220 static const wxCoord SASH_SIZE = 8;
af99040c
VZ
221
222 // margin around the sash
35468934 223 static const wxCoord SASH_MARGIN = 2;
af99040c 224#endif // GTK+ 2.x/1.x
d16cf3cd 225
38418827
RR
226static int GetGtkSplitterFullSize()
227{
228#ifdef __WXGTK20__
229 static GtkWidget *s_paned = NULL;
230 if (s_paned == NULL)
231 s_paned = gtk_vpaned_new();
232
233 gint handle_size;
234 gtk_widget_style_get (s_paned, "handle_size", &handle_size, NULL);
235
236 return handle_size;
237#else
238 return SASH_SIZE + SASH_MARGIN;
239#endif
240}
241
af99040c 242wxSplitterRenderParams
38418827 243wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
d16cf3cd 244{
af99040c
VZ
245 // we don't draw any border, hence 0 for the second field
246 return wxSplitterRenderParams
247 (
38418827 248 GetGtkSplitterFullSize(),
af99040c
VZ
249 0,
250#ifdef __WXGTK20__
251 true // hot sensitive
252#else // GTK+ 1.x
253 false // not
254#endif // GTK+ 2.x/1.x
255 );
d16cf3cd
VZ
256}
257
258void
259wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
260 wxDC& WXUNUSED(dc),
af99040c
VZ
261 const wxRect& WXUNUSED(rect),
262 int WXUNUSED(flags))
d16cf3cd
VZ
263{
264 // nothing to do
265}
95155e75 266
95155e75
VZ
267void
268wxRendererGTK::DrawSplitterSash(wxWindow *win,
269 wxDC& dc,
270 const wxSize& size,
d16cf3cd 271 wxCoord position,
af99040c
VZ
272 wxOrientation orient,
273 int WXUNUSED_IN_GTK1(flags))
95155e75
VZ
274{
275 if ( !win->m_wxwindow->window )
276 {
0100b858 277 // window not realized yet
95155e75
VZ
278 return;
279 }
38418827
RR
280
281 wxCoord full_size = GetGtkSplitterFullSize();
95155e75 282
d16cf3cd
VZ
283 // are we drawing vertical or horizontal splitter?
284 const bool isVert = orient == wxVERTICAL;
285
d16cf3cd 286 GdkRectangle rect;
35468934 287 GdkRectangle erase_rect;
d16cf3cd
VZ
288 if ( isVert )
289 {
0100b858 290 int h = win->GetClientSize().GetHeight();
e1befae3 291
d16cf3cd 292 rect.x = position;
0100b858 293 rect.y = 0;
38418827 294 rect.width = full_size;
0100b858 295 rect.height = h;
e1befae3 296
35468934
RR
297 erase_rect.x = position;
298 erase_rect.y = 0;
38418827 299 erase_rect.width = full_size;
35468934 300 erase_rect.height = h;
d16cf3cd
VZ
301 }
302 else // horz
303 {
0100b858 304 int w = win->GetClientSize().GetWidth();
e1befae3 305
0100b858 306 rect.x = 0;
d16cf3cd 307 rect.y = position;
38418827 308 rect.height = full_size;
0100b858 309 rect.width = w;
e1befae3 310
35468934
RR
311 erase_rect.y = position;
312 erase_rect.x = 0;
38418827 313 erase_rect.height = full_size;
35468934 314 erase_rect.width = w;
d16cf3cd
VZ
315 }
316
ab5ea030
RR
317#if 0
318 // RR: After a correction to the orientation of the sash
319 // this doesn't seem to be required anymore and it
320 // seems to confuse some themes
321
322 // we must erase everything first, otherwise the garbage
323 // from the old sash is left when dragging it
35468934
RR
324 gtk_paint_flat_box
325 (
326 win->m_wxwindow->style,
327 GTK_PIZZA(win->m_wxwindow)->bin_window,
328 GTK_STATE_NORMAL,
329 GTK_SHADOW_NONE,
330 NULL,
331 win->m_wxwindow,
ab5ea030 332 (char *)"viewportbin", // const_cast
35468934
RR
333 erase_rect.x,
334 erase_rect.y,
335 erase_rect.width,
336 erase_rect.height
337 );
ab5ea030 338#endif
35468934 339
af99040c
VZ
340#ifdef __WXGTK20__
341 gtk_paint_handle
342 (
343 win->m_wxwindow->style,
344 GTK_PIZZA(win->m_wxwindow)->bin_window,
345 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
346 GTK_SHADOW_NONE,
347 NULL /* no clipping */,
348 win->m_wxwindow,
349 "paned",
350 rect.x,
351 rect.y,
352 rect.width,
353 rect.height,
38418827 354 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
af99040c
VZ
355 );
356#else // GTK+ 1.x
d16cf3cd
VZ
357
358 // leave some margin before sash itself
359 position += SASH_MARGIN / 2;
360
361 // and finally draw it using GTK paint functions
362 typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
363 GtkStateType,
364 GdkRectangle *, GtkWidget *,
ef9bfb71 365 gchar *,
ef9bfb71 366 gint, gint, gint);
d16cf3cd
VZ
367
368 GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
369
370 (*func)
95155e75
VZ
371 (
372 win->m_wxwindow->style,
d16cf3cd 373 GTK_PIZZA(win->m_wxwindow)->bin_window,
95155e75 374 GTK_STATE_NORMAL,
d16cf3cd 375 NULL,
95155e75 376 win->m_wxwindow,
d16cf3cd
VZ
377 (char *)"paned", // const_cast
378 0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
95155e75
VZ
379 );
380
381 gtk_paint_box
382 (
383 win->m_wxwindow->style,
d16cf3cd 384 GTK_PIZZA(win->m_wxwindow)->bin_window,
95155e75
VZ
385 GTK_STATE_NORMAL,
386 GTK_SHADOW_OUT,
d16cf3cd 387 (GdkRectangle*) NULL,
95155e75
VZ
388 win->m_wxwindow,
389 (char *)"paned", // const_cast
d16cf3cd
VZ
390 isVert ? position : size.x - 2*SASH_SIZE,
391 isVert ? size.y - 2*SASH_SIZE : position,
392 SASH_SIZE, SASH_SIZE
95155e75 393 );
af99040c 394#endif // GTK+ 2.x/1.x
95155e75
VZ
395}
396
38511687
VZ
397void wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
398 wxDC& dc,
399 const wxRect& rect,
400 int flags)
401{
bc13e772 402 GtkWidget *button = GetButtonWidget();
38511687 403
a4622f29
VZ
404 // device context must inherit from wxWindowDC
405 // (so it must be wxClientDC, wxMemoryDC or wxPaintDC)
406 wxWindowDC& wdc = (wxWindowDC&)dc;
407
408 // only doing debug-time checking here (it should probably be enough)
409 wxASSERT ( wdc.IsKindOf(CLASSINFO(wxWindowDC)) );
410
e1befae3 411 GtkStateType state;
a4622f29 412
e1befae3 413 if ( flags & wxCONTROL_CURRENT )
a4622f29
VZ
414 state = GTK_STATE_PRELIGHT;
415 else if ( flags & wxCONTROL_DISABLED )
416 state = GTK_STATE_INSENSITIVE;
e1befae3
VZ
417 else
418 state = GTK_STATE_NORMAL;
a4622f29 419
a4622f29 420 // draw arrow on button
a4622f29
VZ
421 gtk_paint_arrow
422 (
bc13e772 423 button->style,
a4622f29
VZ
424 wdc.m_window,
425 state,
e1befae3 426 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
a4622f29 427 NULL,
bc13e772 428 button,
a4622f29
VZ
429 "arrow",
430 GTK_ARROW_DOWN,
a8ac548e 431 FALSE,
e1befae3 432 rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2
a4622f29 433 );
38511687
VZ
434}
435