]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/renderer.cpp
Don't assume that msw.remap was 1, instead change it back to what it
[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 28#include <gtk/gtk.h>
3cbab641 29#include "wx/gtk1/win_gtk.h"
9c7f49f5 30
38c4cb6a
VZ
31#include "wx/window.h"
32#include "wx/dc.h"
31059a74 33#include "wx/dcclient.h"
9c7f49f5 34
91af0895
WS
35// RR: After a correction to the orientation of the sash
36// this doesn't seem to be required anymore and it
37// seems to confuse some themes so USE_ERASE_RECT=0
38#define USE_ERASE_RECT 0
39
9c7f49f5 40// ----------------------------------------------------------------------------
38c4cb6a 41// wxRendererGTK: our wxRendererNative implementation
9c7f49f5
VZ
42// ----------------------------------------------------------------------------
43
38c4cb6a 44class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
9c7f49f5
VZ
45{
46public:
47 // draw the header control button (used by wxListCtrl)
48 virtual void DrawHeaderButton(wxWindow *win,
49 wxDC& dc,
50 const wxRect& rect,
51 int flags = 0);
52
d16cf3cd
VZ
53 virtual void DrawSplitterBorder(wxWindow *win,
54 wxDC& dc,
af99040c
VZ
55 const wxRect& rect,
56 int flags = 0);
95155e75
VZ
57 virtual void DrawSplitterSash(wxWindow *win,
58 wxDC& dc,
59 const wxSize& size,
d16cf3cd 60 wxCoord position,
af99040c
VZ
61 wxOrientation orient,
62 int flags = 0);
d16cf3cd 63
38511687
VZ
64 virtual void DrawComboBoxDropButton(wxWindow *win,
65 wxDC& dc,
66 const wxRect& rect,
67 int flags = 0);
68
4c85ab75
VZ
69 virtual void DrawDropArrow(wxWindow *win,
70 wxDC& dc,
71 const wxRect& rect,
72 int flags = 0);
73
af99040c 74 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
e1befae3
VZ
75
76private:
bc13e772
VZ
77 // FIXME: shouldn't we destroy these windows somewhere?
78
e1befae3 79 // used by DrawHeaderButton and DrawComboBoxDropButton
bc13e772 80 static GtkWidget *GetButtonWidget();
9c7f49f5
VZ
81};
82
83// ============================================================================
84// implementation
85// ============================================================================
86
87/* static */
f0244295 88wxRendererNative& wxRendererNative::GetDefault()
9c7f49f5
VZ
89{
90 static wxRendererGTK s_rendererGTK;
91
92 return s_rendererGTK;
93}
94
a4622f29 95// ----------------------------------------------------------------------------
bc13e772 96// helper functions
a4622f29
VZ
97// ----------------------------------------------------------------------------
98
bc13e772
VZ
99GtkWidget *
100wxRendererGTK::GetButtonWidget()
101{
102 static GtkWidget *s_button = NULL;
103 static GtkWidget *s_window = NULL;
a4622f29 104
bc13e772
VZ
105 if ( !s_button )
106 {
107 s_window = gtk_window_new( GTK_WINDOW_POPUP );
108 gtk_widget_realize( s_window );
109 s_button = gtk_button_new();
110 gtk_container_add( GTK_CONTAINER(s_window), s_button );
111 gtk_widget_realize( s_button );
112 }
113
114 return s_button;
115}
116
d16cf3cd
VZ
117// ----------------------------------------------------------------------------
118// list/tree controls drawing
119// ----------------------------------------------------------------------------
120
9c7f49f5
VZ
121void
122wxRendererGTK::DrawHeaderButton(wxWindow *win,
123 wxDC& dc,
124 const wxRect& rect,
125 int flags)
126{
9b311923 127
bc13e772 128 GtkWidget *button = GetButtonWidget();
9b311923 129
9c7f49f5
VZ
130 gtk_paint_box
131 (
bc13e772 132 button->style,
a4622f29
VZ
133 // FIXME: I suppose GTK_PIZZA(win->m_wxwindow)->bin_window doesn't work with wxMemoryDC.
134 // Maybe use code similar as in DrawComboBoxDropButton below?
9c7f49f5
VZ
135 GTK_PIZZA(win->m_wxwindow)->bin_window,
136 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL,
137 GTK_SHADOW_OUT,
38511687 138 NULL,
bc13e772 139 button,
9b311923
RR
140 "button",
141 dc.XLOG2DEV(rect.x) -1, rect.y -1, rect.width +2, rect.height +2
9c7f49f5
VZ
142 );
143}
144
d16cf3cd
VZ
145// ----------------------------------------------------------------------------
146// splitter sash drawing
147// ----------------------------------------------------------------------------
148
3cbab641
MR
149// the full sash width (should be even)
150static const wxCoord SASH_SIZE = 8;
af99040c 151
3cbab641
MR
152// margin around the sash
153static const wxCoord SASH_MARGIN = 2;
d16cf3cd 154
38418827
RR
155static int GetGtkSplitterFullSize()
156{
38418827 157 return SASH_SIZE + SASH_MARGIN;
38418827
RR
158}
159
af99040c 160wxSplitterRenderParams
38418827 161wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
d16cf3cd 162{
af99040c
VZ
163 // we don't draw any border, hence 0 for the second field
164 return wxSplitterRenderParams
165 (
38418827 166 GetGtkSplitterFullSize(),
af99040c 167 0,
af99040c 168 false // not
af99040c 169 );
d16cf3cd
VZ
170}
171
172void
173wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
174 wxDC& WXUNUSED(dc),
af99040c
VZ
175 const wxRect& WXUNUSED(rect),
176 int WXUNUSED(flags))
d16cf3cd
VZ
177{
178 // nothing to do
179}
95155e75 180
95155e75
VZ
181void
182wxRendererGTK::DrawSplitterSash(wxWindow *win,
183 wxDC& dc,
184 const wxSize& size,
d16cf3cd 185 wxCoord position,
af99040c 186 wxOrientation orient,
3cbab641 187 int WXUNUSED(flags))
95155e75
VZ
188{
189 if ( !win->m_wxwindow->window )
190 {
0100b858 191 // window not realized yet
95155e75
VZ
192 return;
193 }
91af0895 194
38418827 195 wxCoord full_size = GetGtkSplitterFullSize();
95155e75 196
d16cf3cd
VZ
197 // are we drawing vertical or horizontal splitter?
198 const bool isVert = orient == wxVERTICAL;
199
d16cf3cd 200 GdkRectangle rect;
91af0895 201#if USE_ERASE_RECT
35468934 202 GdkRectangle erase_rect;
91af0895
WS
203#endif
204
d16cf3cd
VZ
205 if ( isVert )
206 {
0100b858 207 int h = win->GetClientSize().GetHeight();
e1befae3 208
d16cf3cd 209 rect.x = position;
0100b858 210 rect.y = 0;
38418827 211 rect.width = full_size;
0100b858 212 rect.height = h;
e1befae3 213
91af0895 214#if USE_ERASE_RECT
35468934
RR
215 erase_rect.x = position;
216 erase_rect.y = 0;
38418827 217 erase_rect.width = full_size;
35468934 218 erase_rect.height = h;
91af0895 219#endif
d16cf3cd
VZ
220 }
221 else // horz
222 {
0100b858 223 int w = win->GetClientSize().GetWidth();
e1befae3 224
0100b858 225 rect.x = 0;
d16cf3cd 226 rect.y = position;
38418827 227 rect.height = full_size;
0100b858 228 rect.width = w;
e1befae3 229
91af0895 230#if USE_ERASE_RECT
35468934
RR
231 erase_rect.y = position;
232 erase_rect.x = 0;
38418827 233 erase_rect.height = full_size;
35468934 234 erase_rect.width = w;
91af0895 235#endif
d16cf3cd
VZ
236 }
237
91af0895 238#if USE_ERASE_RECT
ab5ea030
RR
239 // we must erase everything first, otherwise the garbage
240 // from the old sash is left when dragging it
35468934
RR
241 gtk_paint_flat_box
242 (
243 win->m_wxwindow->style,
244 GTK_PIZZA(win->m_wxwindow)->bin_window,
245 GTK_STATE_NORMAL,
246 GTK_SHADOW_NONE,
247 NULL,
248 win->m_wxwindow,
ab5ea030 249 (char *)"viewportbin", // const_cast
35468934
RR
250 erase_rect.x,
251 erase_rect.y,
252 erase_rect.width,
253 erase_rect.height
254 );
ab5ea030 255#endif
35468934 256
d16cf3cd
VZ
257
258 // leave some margin before sash itself
259 position += SASH_MARGIN / 2;
260
261 // and finally draw it using GTK paint functions
262 typedef void (*GtkPaintLineFunc)(GtkStyle *, GdkWindow *,
263 GtkStateType,
264 GdkRectangle *, GtkWidget *,
ef9bfb71 265 gchar *,
ef9bfb71 266 gint, gint, gint);
d16cf3cd
VZ
267
268 GtkPaintLineFunc func = isVert ? gtk_paint_vline : gtk_paint_hline;
269
270 (*func)
95155e75
VZ
271 (
272 win->m_wxwindow->style,
d16cf3cd 273 GTK_PIZZA(win->m_wxwindow)->bin_window,
95155e75 274 GTK_STATE_NORMAL,
d16cf3cd 275 NULL,
95155e75 276 win->m_wxwindow,
d16cf3cd
VZ
277 (char *)"paned", // const_cast
278 0, isVert ? size.y : size.x, position + SASH_SIZE / 2 - 1
95155e75
VZ
279 );
280
281 gtk_paint_box
282 (
283 win->m_wxwindow->style,
d16cf3cd 284 GTK_PIZZA(win->m_wxwindow)->bin_window,
95155e75
VZ
285 GTK_STATE_NORMAL,
286 GTK_SHADOW_OUT,
d16cf3cd 287 (GdkRectangle*) NULL,
95155e75
VZ
288 win->m_wxwindow,
289 (char *)"paned", // const_cast
d16cf3cd
VZ
290 isVert ? position : size.x - 2*SASH_SIZE,
291 isVert ? size.y - 2*SASH_SIZE : position,
292 SASH_SIZE, SASH_SIZE
95155e75
VZ
293 );
294}
295
4c85ab75
VZ
296void
297wxRendererGTK::DrawDropArrow(wxWindow *win,
298 wxDC& dc,
299 const wxRect& rect,
300 int flags)
38511687 301{
bc13e772 302 GtkWidget *button = GetButtonWidget();
38511687 303
4c85ab75
VZ
304 // If we give GTK_PIZZA(win->m_wxwindow)->bin_window as
305 // a window for gtk_paint_xxx function, then it won't
306 // work for wxMemoryDC. So that is why we assume wxDC
307 // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC
308 // are derived from it) and use its m_window.
a4622f29
VZ
309 wxWindowDC& wdc = (wxWindowDC&)dc;
310
4c85ab75
VZ
311 // only doing debug-time checking here (it should
312 // probably be enough)
a4622f29
VZ
313 wxASSERT ( wdc.IsKindOf(CLASSINFO(wxWindowDC)) );
314
4c85ab75
VZ
315 // draw arrow so that there is even space horizontally
316 // on both sides
317 int arrowX = rect.width/4 + 1;
318 int arrowWidth = rect.width - (arrowX*2);
319
320 // scale arrow's height accoording to the width
321 int arrowHeight = rect.width/3;
322 int arrowY = (rect.height-arrowHeight)/2 +
323 ((rect.height-arrowHeight) & 1);
324
e1befae3 325 GtkStateType state;
a4622f29 326
3203621a
JS
327 if ( flags & wxCONTROL_PRESSED )
328 state = GTK_STATE_ACTIVE;
a4622f29
VZ
329 else if ( flags & wxCONTROL_DISABLED )
330 state = GTK_STATE_INSENSITIVE;
3203621a
JS
331 else if ( flags & wxCONTROL_CURRENT )
332 state = GTK_STATE_PRELIGHT;
e1befae3
VZ
333 else
334 state = GTK_STATE_NORMAL;
a4622f29 335
a4622f29 336 // draw arrow on button
a4622f29
VZ
337 gtk_paint_arrow
338 (
bc13e772 339 button->style,
a4622f29
VZ
340 wdc.m_window,
341 state,
e1befae3 342 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
a4622f29 343 NULL,
bc13e772 344 button,
a4622f29
VZ
345 "arrow",
346 GTK_ARROW_DOWN,
a8ac548e 347 FALSE,
4c85ab75
VZ
348 rect.x + arrowX,
349 rect.y + arrowY,
350 arrowWidth,
351 arrowHeight
a4622f29 352 );
38511687
VZ
353}
354
4c85ab75
VZ
355void
356wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
357 wxDC& dc,
358 const wxRect& rect,
359 int flags)
360{
361 GtkWidget *button = GetButtonWidget();
362
363 // for reason why we do this, see DrawDropArrow
364 wxWindowDC& wdc = (wxWindowDC&)dc;
365 wxASSERT ( wdc.IsKindOf(CLASSINFO(wxWindowDC)) );
366
367 // draw button
368 GtkStateType state;
369
3203621a
JS
370 if ( flags & wxCONTROL_PRESSED )
371 state = GTK_STATE_ACTIVE;
4c85ab75
VZ
372 else if ( flags & wxCONTROL_DISABLED )
373 state = GTK_STATE_INSENSITIVE;
3203621a
JS
374 else if ( flags & wxCONTROL_CURRENT )
375 state = GTK_STATE_PRELIGHT;
4c85ab75
VZ
376 else
377 state = GTK_STATE_NORMAL;
378
379 gtk_paint_box
380 (
381 button->style,
382 wdc.m_window,
383 state,
384 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
385 NULL,
386 button,
387 "button",
388 rect.x, rect.y, rect.width, rect.height
389 );
390
391 // draw arrow on button
392 DrawDropArrow(win,dc,rect,flags);
393
394}