]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/renderer.cpp
revert nested event loop support for wxGTK1 because it causes applications hangs
[wxWidgets.git] / src / gtk / renderer.cpp
CommitLineData
9c7f49f5 1///////////////////////////////////////////////////////////////////////////////
90b903c2 2// Name: src/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
9c7f49f5 7// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
526954c5 8// Licence: wxWindows licence
9c7f49f5
VZ
9///////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
e1bf3ad3 26#include "wx/renderer.h"
cdccdfab
WS
27
28#ifndef WX_PRECOMP
29 #include "wx/window.h"
ed4b0fdc 30 #include "wx/dcclient.h"
9eddec69 31 #include "wx/settings.h"
f1c09bed 32 #include "wx/module.h"
cdccdfab
WS
33#endif
34
02f07b19 35#include "wx/dcgraph.h"
9dc44eff 36#ifndef __WXGTK3__
888dde65 37#include "wx/gtk/dc.h"
9dc44eff 38#endif
888dde65 39
9c7f49f5 40#include <gtk/gtk.h>
9dc44eff
PC
41#include "wx/gtk/private.h"
42#include "wx/gtk/private/gtk2-compat.h"
9c7f49f5 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)
c97c9952 52 virtual int DrawHeaderButton(wxWindow *win,
9c7f49f5
VZ
53 wxDC& dc,
54 const wxRect& rect,
4b94ddc4 55 int flags = 0,
80752b57 56 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4 57 wxHeaderButtonParams* params = NULL);
9c7f49f5 58
6f91f3a3
RR
59 virtual int GetHeaderButtonHeight(wxWindow *win);
60
9aebcb5e
VS
61 virtual int GetHeaderButtonMargin(wxWindow *win);
62
6f91f3a3 63
9c7f49f5
VZ
64 // draw the expanded/collapsed icon for a tree control item
65 virtual void DrawTreeItemButton(wxWindow *win,
66 wxDC& dc,
67 const wxRect& rect,
68 int flags = 0);
9c7f49f5 69
d16cf3cd
VZ
70 virtual void DrawSplitterBorder(wxWindow *win,
71 wxDC& dc,
af99040c
VZ
72 const wxRect& rect,
73 int flags = 0);
95155e75
VZ
74 virtual void DrawSplitterSash(wxWindow *win,
75 wxDC& dc,
76 const wxSize& size,
d16cf3cd 77 wxCoord position,
af99040c
VZ
78 wxOrientation orient,
79 int flags = 0);
d16cf3cd 80
38511687
VZ
81 virtual void DrawComboBoxDropButton(wxWindow *win,
82 wxDC& dc,
83 const wxRect& rect,
84 int flags = 0);
85
4c85ab75
VZ
86 virtual void DrawDropArrow(wxWindow *win,
87 wxDC& dc,
88 const wxRect& rect,
89 int flags = 0);
90
90b903c2
WS
91 virtual void DrawCheckBox(wxWindow *win,
92 wxDC& dc,
93 const wxRect& rect,
94 int flags = 0);
2209baae
RR
95
96 virtual void DrawPushButton(wxWindow *win,
97 wxDC& dc,
98 const wxRect& rect,
99 int flags = 0);
100
daebb44c
RR
101 virtual void DrawItemSelectionRect(wxWindow *win,
102 wxDC& dc,
103 const wxRect& rect,
104 int flags = 0);
90b903c2 105
99c4be68
VZ
106 virtual void DrawChoice(wxWindow* win,
107 wxDC& dc,
108 const wxRect& rect,
e4131985
KO
109 int flags=0);
110
99c4be68
VZ
111 virtual void DrawComboBox(wxWindow* win,
112 wxDC& dc,
113 const wxRect& rect,
e4131985
KO
114 int flags=0);
115
99c4be68
VZ
116 virtual void DrawTextCtrl(wxWindow* win,
117 wxDC& dc,
118 const wxRect& rect,
e4131985
KO
119 int flags=0);
120
6e6b532c 121 virtual void DrawRadioBitmap(wxWindow* win,
99c4be68
VZ
122 wxDC& dc,
123 const wxRect& rect,
e4131985
KO
124 int flags=0);
125
6d789987
JS
126 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
127
191e43fd 128 virtual wxSize GetCheckBoxSize(wxWindow *win);
f1c09bed 129
e8759560 130 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
9c7f49f5
VZ
131};
132
133// ============================================================================
134// implementation
135// ============================================================================
136
137/* static */
f0244295 138wxRendererNative& wxRendererNative::GetDefault()
9c7f49f5
VZ
139{
140 static wxRendererGTK s_rendererGTK;
141
142 return s_rendererGTK;
143}
144
9dc44eff
PC
145#ifdef __WXGTK3__
146#define NULL_RECT
147typedef cairo_t wxGTKDrawable;
148
149static cairo_t* wxGetGTKDrawable(wxWindow*, const wxDC& dc)
150{
151 wxGraphicsContext* gc = dc.GetGraphicsContext();
152 wxCHECK_MSG(gc, NULL, "cannot use wxRendererNative on wxDC of this type");
153 return static_cast<cairo_t*>(gc->GetNativeContext());
154}
155
156static const GtkStateFlags stateTypeToFlags[] = {
157 GTK_STATE_FLAG_NORMAL, GTK_STATE_FLAG_ACTIVE, GTK_STATE_FLAG_PRELIGHT,
158 GTK_STATE_FLAG_SELECTED, GTK_STATE_FLAG_INSENSITIVE, GTK_STATE_FLAG_INCONSISTENT,
159 GTK_STATE_FLAG_FOCUSED
160};
161
162#else
163#define NULL_RECT NULL,
164typedef GdkWindow wxGTKDrawable;
165
166static GdkWindow* wxGetGTKDrawable(wxWindow* win, wxDC& dc)
e4131985
KO
167{
168 GdkWindow* gdk_window = NULL;
99c4be68 169
02f07b19 170#if wxUSE_GRAPHICS_CONTEXT
345c78ca 171 if ( wxDynamicCast(&dc, wxGCDC) )
d81b2f54 172 gdk_window = win->GTKGetDrawingWindow();
02f07b19
KO
173 else
174#endif
175 {
02f07b19
KO
176 wxDCImpl *impl = dc.GetImpl();
177 wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl );
178 if (gtk_impl)
179 gdk_window = gtk_impl->GetGDKWindow();
9dc44eff
PC
180 else
181 wxFAIL_MSG("cannot use wxRendererNative on wxDC of this type");
02f07b19 182 }
b162ccca
FM
183
184#if !wxUSE_GRAPHICS_CONTEXT
185 wxUnusedVar(win);
186#endif
187
e4131985
KO
188 return gdk_window;
189}
9dc44eff 190#endif
e4131985 191
d16cf3cd
VZ
192// ----------------------------------------------------------------------------
193// list/tree controls drawing
194// ----------------------------------------------------------------------------
195
c97c9952 196int
9c7f49f5
VZ
197wxRendererGTK::DrawHeaderButton(wxWindow *win,
198 wxDC& dc,
199 const wxRect& rect,
4b94ddc4 200 int flags,
80752b57 201 wxHeaderSortIconType sortArrow,
4b94ddc4 202 wxHeaderButtonParams* params)
9c7f49f5 203{
e8759560 204 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
09e72468
RR
205 if (flags & wxCONTROL_SPECIAL)
206 button = wxGTKPrivate::GetHeaderButtonWidgetFirst();
6f91f3a3 207 if (flags & wxCONTROL_DIRTY)
b047e876 208 button = wxGTKPrivate::GetHeaderButtonWidgetLast();
f1c09bed 209
5eefe029
RR
210 int x_diff = 0;
211 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
212 x_diff = rect.width;
f4322df6 213
1cfc4971
RR
214 GtkStateType state = GTK_STATE_NORMAL;
215 if (flags & wxCONTROL_DISABLED)
216 state = GTK_STATE_INSENSITIVE;
217 else
218 {
219 if (flags & wxCONTROL_CURRENT)
220 state = GTK_STATE_PRELIGHT;
221 }
222
9dc44eff
PC
223#ifdef __WXGTK3__
224 cairo_t* cr = wxGetGTKDrawable(win, dc);
225 if (cr)
226 {
227 GtkStyleContext* sc = gtk_widget_get_style_context(button);
228 gtk_style_context_save(sc);
229 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
230 gtk_render_background(sc, cr, rect.x - x_diff+4, rect.y+4, rect.width-8, rect.height-8);
231 gtk_render_frame(sc, cr, rect.x - x_diff+4, rect.y+4, rect.width-8, rect.height-8);
232 gtk_style_context_restore(sc);
233 }
234#else
235 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
9c7f49f5
VZ
236 gtk_paint_box
237 (
385e8575 238 gtk_widget_get_style(button),
2e992e06 239 gdk_window,
1cfc4971 240 state,
9c7f49f5 241 GTK_SHADOW_OUT,
38511687 242 NULL,
bc13e772 243 button,
9b311923 244 "button",
5eefe029 245 dc.LogicalToDeviceX(rect.x) - x_diff, rect.y, rect.width, rect.height
9c7f49f5 246 );
9dc44eff 247#endif
99c4be68 248
c97c9952 249 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
9c7f49f5
VZ
250}
251
6f91f3a3
RR
252int wxRendererGTK::GetHeaderButtonHeight(wxWindow *WXUNUSED(win))
253{
254 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
99c4be68 255
6f91f3a3 256 GtkRequisition req;
9dc44eff
PC
257#ifdef __WXGTK3__
258 gtk_widget_get_preferred_height(button, NULL, &req.height);
259#else
6f91f3a3 260 GTK_WIDGET_GET_CLASS(button)->size_request(button, &req);
9dc44eff 261#endif
99c4be68 262
6f91f3a3
RR
263 return req.height;
264}
265
9aebcb5e
VS
266int wxRendererGTK::GetHeaderButtonMargin(wxWindow *WXUNUSED(win))
267{
268 wxFAIL_MSG( "GetHeaderButtonMargin() not implemented" );
269 return -1;
270}
271
6f91f3a3 272
9c7f49f5 273// draw a ">" or "v" button
9c7f49f5 274void
f8b043e7 275wxRendererGTK::DrawTreeItemButton(wxWindow* win,
9a0b7e33 276 wxDC& dc, const wxRect& rect, int flags)
9c7f49f5 277{
e8759560 278 GtkWidget *tree = wxGTKPrivate::GetTreeWidget();
f8b043e7 279
885dd597
RR
280 GtkStateType state;
281 if ( flags & wxCONTROL_CURRENT )
282 state = GTK_STATE_PRELIGHT;
283 else
284 state = GTK_STATE_NORMAL;
91af0895 285
428f4657
RR
286 int x_diff = 0;
287 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
288 x_diff = rect.width;
2e992e06 289
9dc44eff
PC
290#ifdef __WXGTK3__
291 cairo_t* cr = wxGetGTKDrawable(win, dc);
292 if (cr)
293 {
294 gtk_widget_set_state_flags(tree, stateTypeToFlags[state], true);
295 GtkStyleContext* sc = gtk_widget_get_style_context(tree);
296 gtk_render_expander(sc, cr, rect.x - x_diff, rect.y, rect.width, rect.height);
297 }
298#else
5ede3d24 299 // x and y parameters specify the center of the expander
9dc44eff
PC
300 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
301 if (gdk_window == NULL)
302 return;
bc13e772
VZ
303 gtk_paint_expander
304 (
385e8575 305 gtk_widget_get_style(tree),
2e992e06 306 gdk_window,
885dd597 307 state,
bc13e772
VZ
308 NULL,
309 tree,
310 "treeview",
5ede3d24
PC
311 dc.LogicalToDeviceX(rect.x) + rect.width / 2 - x_diff,
312 dc.LogicalToDeviceY(rect.y) + rect.height / 2,
bc13e772
VZ
313 flags & wxCONTROL_EXPANDED ? GTK_EXPANDER_EXPANDED
314 : GTK_EXPANDER_COLLAPSED
315 );
9dc44eff 316#endif
9c7f49f5
VZ
317}
318
9c7f49f5 319
d16cf3cd
VZ
320// ----------------------------------------------------------------------------
321// splitter sash drawing
322// ----------------------------------------------------------------------------
323
f1c09bed 324static int GetGtkSplitterFullSize(GtkWidget* widget)
38418827 325{
38418827 326 gint handle_size;
f1c09bed 327 gtk_widget_style_get(widget, "handle_size", &handle_size, NULL);
91af0895 328
38418827 329 return handle_size;
38418827
RR
330}
331
af99040c 332wxSplitterRenderParams
38418827 333wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
d16cf3cd 334{
af99040c
VZ
335 // we don't draw any border, hence 0 for the second field
336 return wxSplitterRenderParams
337 (
e8759560 338 GetGtkSplitterFullSize(wxGTKPrivate::GetSplitterWidget()),
af99040c 339 0,
af99040c 340 true // hot sensitive
af99040c 341 );
d16cf3cd
VZ
342}
343
344void
345wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
346 wxDC& WXUNUSED(dc),
af99040c
VZ
347 const wxRect& WXUNUSED(rect),
348 int WXUNUSED(flags))
d16cf3cd
VZ
349{
350 // nothing to do
351}
95155e75 352
95155e75 353void
02f07b19 354wxRendererGTK::DrawSplitterSash(wxWindow* win,
95155e75
VZ
355 wxDC& dc,
356 const wxSize& size,
d16cf3cd 357 wxCoord position,
af99040c 358 wxOrientation orient,
68567a96 359 int flags)
95155e75 360{
385e8575 361 if (gtk_widget_get_window(win->m_wxwindow) == NULL)
95155e75 362 {
0100b858 363 // window not realized yet
95155e75
VZ
364 return;
365 }
91af0895 366
9dc44eff
PC
367 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
368 if (drawable == NULL)
369 return;
95155e75 370
d16cf3cd
VZ
371 // are we drawing vertical or horizontal splitter?
372 const bool isVert = orient == wxVERTICAL;
373
9dc44eff
PC
374 GtkWidget* widget = wxGTKPrivate::GetSplitterWidget(orient);
375 const int full_size = GetGtkSplitterFullSize(widget);
376
d16cf3cd 377 GdkRectangle rect;
91af0895 378
d16cf3cd
VZ
379 if ( isVert )
380 {
381 rect.x = position;
0100b858 382 rect.y = 0;
38418827 383 rect.width = full_size;
e4161a2a 384 rect.height = size.y;
d16cf3cd
VZ
385 }
386 else // horz
387 {
0100b858 388 rect.x = 0;
d16cf3cd 389 rect.y = position;
38418827 390 rect.height = full_size;
e4161a2a 391 rect.width = size.x;
d16cf3cd 392 }
f4322df6 393
847dfdb4
RR
394 int x_diff = 0;
395 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
396 x_diff = rect.width;
35468934 397
9dc44eff
PC
398#ifdef __WXGTK3__
399 cairo_t* cr = wxGetGTKDrawable(win, dc);
400 if (cr)
401 {
402 gtk_widget_set_state_flags(widget, stateTypeToFlags[flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL], true);
403 GtkStyleContext* sc = gtk_widget_get_style_context(widget);
404 gtk_render_handle(sc, cr, rect.x - x_diff, rect.y, rect.width, rect.height);
405 }
406#else
407 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
408 if (gdk_window == NULL)
409 return;
af99040c
VZ
410 gtk_paint_handle
411 (
385e8575 412 gtk_widget_get_style(win->m_wxwindow),
2e992e06 413 gdk_window,
af99040c
VZ
414 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
415 GTK_SHADOW_NONE,
416 NULL /* no clipping */,
417 win->m_wxwindow,
418 "paned",
847dfdb4
RR
419 dc.LogicalToDeviceX(rect.x) - x_diff,
420 dc.LogicalToDeviceY(rect.y),
af99040c
VZ
421 rect.width,
422 rect.height,
38418827 423 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
af99040c 424 );
9dc44eff 425#endif
95155e75
VZ
426}
427
4c85ab75 428void
02f07b19 429wxRendererGTK::DrawDropArrow(wxWindow* win,
4c85ab75
VZ
430 wxDC& dc,
431 const wxRect& rect,
432 int flags)
38511687 433{
e8759560 434 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
38511687 435
02f07b19 436 // If we give WX_PIZZA(win->m_wxwindow)->bin_window as
4c85ab75
VZ
437 // a window for gtk_paint_xxx function, then it won't
438 // work for wxMemoryDC. So that is why we assume wxDC
439 // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC
440 // are derived from it) and use its m_window.
a4622f29 441
4c85ab75
VZ
442 // draw arrow so that there is even space horizontally
443 // on both sides
9dc44eff
PC
444 const int size = rect.width / 2;
445 const int x = rect.x + (size + 1) / 2;
446 const int y = rect.y + (rect.height - size + 1) / 2;
4c85ab75 447
e1befae3 448 GtkStateType state;
a4622f29 449
3203621a
JS
450 if ( flags & wxCONTROL_PRESSED )
451 state = GTK_STATE_ACTIVE;
a4622f29
VZ
452 else if ( flags & wxCONTROL_DISABLED )
453 state = GTK_STATE_INSENSITIVE;
3203621a
JS
454 else if ( flags & wxCONTROL_CURRENT )
455 state = GTK_STATE_PRELIGHT;
e1befae3
VZ
456 else
457 state = GTK_STATE_NORMAL;
a4622f29 458
9dc44eff
PC
459#ifdef __WXGTK3__
460 cairo_t* cr = wxGetGTKDrawable(win, dc);
461 if (cr)
462 {
463 gtk_widget_set_state_flags(button, stateTypeToFlags[state], true);
464 GtkStyleContext* sc = gtk_widget_get_style_context(button);
465 gtk_render_arrow(sc, cr, G_PI, x, y, size);
466 }
467#else
468 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
469 if (gdk_window == NULL)
470 return;
a4622f29 471 // draw arrow on button
a4622f29
VZ
472 gtk_paint_arrow
473 (
385e8575 474 gtk_widget_get_style(button),
2e992e06 475 gdk_window,
a4622f29 476 state,
e1befae3 477 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
a4622f29 478 NULL,
bc13e772 479 button,
a4622f29
VZ
480 "arrow",
481 GTK_ARROW_DOWN,
a8ac548e 482 FALSE,
9dc44eff
PC
483 x, y,
484 size, size
a4622f29 485 );
9dc44eff 486#endif
38511687
VZ
487}
488
4c85ab75
VZ
489void
490wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
491 wxDC& dc,
492 const wxRect& rect,
493 int flags)
494{
2209baae
RR
495 DrawPushButton(win,dc,rect,flags);
496 DrawDropArrow(win,dc,rect);
497}
498
e8759560 499wxSize
191e43fd 500wxRendererGTK::GetCheckBoxSize(wxWindow *WXUNUSED(win))
e8759560
VZ
501{
502 gint indicator_size, indicator_spacing;
503 gtk_widget_style_get(wxGTKPrivate::GetCheckButtonWidget(),
504 "indicator_size", &indicator_size,
505 "indicator_spacing", &indicator_spacing,
506 NULL);
507
508 int size = indicator_size + indicator_spacing * 2;
509 return wxSize(size, size);
510}
511
cdccdfab 512void
02f07b19 513wxRendererGTK::DrawCheckBox(wxWindow* win,
90b903c2
WS
514 wxDC& dc,
515 const wxRect& rect,
516 int flags )
2209baae 517{
e8759560 518 GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget();
f1c09bed 519
e8759560
VZ
520 gint indicator_size, indicator_spacing;
521 gtk_widget_style_get(button,
522 "indicator_size", &indicator_size,
523 "indicator_spacing", &indicator_spacing,
524 NULL);
525
9dc44eff 526#ifndef __WXGTK3__
4c85ab75
VZ
527 GtkStateType state;
528
3203621a
JS
529 if ( flags & wxCONTROL_PRESSED )
530 state = GTK_STATE_ACTIVE;
4c85ab75
VZ
531 else if ( flags & wxCONTROL_DISABLED )
532 state = GTK_STATE_INSENSITIVE;
3203621a
JS
533 else if ( flags & wxCONTROL_CURRENT )
534 state = GTK_STATE_PRELIGHT;
4c85ab75
VZ
535 else
536 state = GTK_STATE_NORMAL;
90b903c2 537
e78778c8
RR
538 GtkShadowType shadow_type;
539
540 if ( flags & wxCONTROL_UNDETERMINED )
541 shadow_type = GTK_SHADOW_ETCHED_IN;
542 else if ( flags & wxCONTROL_CHECKED )
543 shadow_type = GTK_SHADOW_IN;
544 else
545 shadow_type = GTK_SHADOW_OUT;
9dc44eff
PC
546#endif
547
548#ifdef __WXGTK3__
549 cairo_t* cr = wxGetGTKDrawable(win, dc);
550 if (cr)
551 {
552 int stateFlags = GTK_STATE_FLAG_NORMAL;
553 if (flags & wxCONTROL_CHECKED)
554 stateFlags = GTK_STATE_FLAG_ACTIVE;
555 if (flags & wxCONTROL_DISABLED)
556 stateFlags |= GTK_STATE_FLAG_INSENSITIVE;
557 if (flags & wxCONTROL_UNDETERMINED)
558 stateFlags |= GTK_STATE_FLAG_INCONSISTENT;
559 if (flags & wxCONTROL_CURRENT)
560 stateFlags |= GTK_STATE_FLAG_PRELIGHT;
561 GtkStyleContext* sc = gtk_widget_get_style_context(button);
562 gtk_style_context_save(sc);
563 gtk_style_context_set_state(sc, GtkStateFlags(stateFlags));
564 gtk_style_context_add_class(sc, GTK_STYLE_CLASS_CHECK);
565 gtk_render_check(sc, cr,
566 rect.x + (rect.width - indicator_size) / 2,
567 rect.y + (rect.height - indicator_size) / 2,
568 indicator_size, indicator_size);
569 gtk_style_context_restore(sc);
570 }
571#else
572 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
573 if (gdk_window == NULL)
574 return;
e78778c8 575
2209baae 576 gtk_paint_check
4c85ab75 577 (
385e8575 578 gtk_widget_get_style(button),
2e992e06 579 gdk_window,
4c85ab75 580 state,
e78778c8 581 shadow_type,
4c85ab75
VZ
582 NULL,
583 button,
2209baae 584 "cellcheck",
e8759560
VZ
585 dc.LogicalToDeviceX(rect.x) + indicator_spacing,
586 dc.LogicalToDeviceY(rect.y) + indicator_spacing,
587 indicator_size, indicator_size
4c85ab75 588 );
9dc44eff 589#endif
4c85ab75
VZ
590}
591
2209baae 592void
02f07b19 593wxRendererGTK::DrawPushButton(wxWindow* win,
2209baae
RR
594 wxDC& dc,
595 const wxRect& rect,
596 int flags)
862d8041 597{
e8759560 598 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
862d8041 599
2209baae 600 // draw button
862d8041
RR
601 GtkStateType state;
602
603 if ( flags & wxCONTROL_PRESSED )
604 state = GTK_STATE_ACTIVE;
605 else if ( flags & wxCONTROL_DISABLED )
606 state = GTK_STATE_INSENSITIVE;
607 else if ( flags & wxCONTROL_CURRENT )
608 state = GTK_STATE_PRELIGHT;
609 else
610 state = GTK_STATE_NORMAL;
2209baae 611
9dc44eff
PC
612#ifdef __WXGTK3__
613 cairo_t* cr = wxGetGTKDrawable(win, dc);
614 if (cr)
615 {
616 GtkStyleContext* sc = gtk_widget_get_style_context(button);
617 gtk_style_context_save(sc);
618 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
619 gtk_render_background(sc, cr, rect.x, rect.y, rect.width, rect.height);
620 gtk_render_frame(sc, cr, rect.x, rect.y, rect.width, rect.height);
621 gtk_style_context_restore(sc);
622 }
623#else
624 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
625 if (gdk_window == NULL)
626 return;
627
2209baae 628 gtk_paint_box
862d8041 629 (
385e8575 630 gtk_widget_get_style(button),
2e992e06 631 gdk_window,
862d8041 632 state,
2209baae 633 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
862d8041
RR
634 NULL,
635 button,
2209baae 636 "button",
99c4be68
VZ
637 dc.LogicalToDeviceX(rect.x),
638 dc.LogicalToDeviceY(rect.y),
639 rect.width,
e4131985 640 rect.height
862d8041 641 );
9dc44eff 642#endif
862d8041 643}
daebb44c 644
cdccdfab 645void
02f07b19 646wxRendererGTK::DrawItemSelectionRect(wxWindow* win,
cdccdfab
WS
647 wxDC& dc,
648 const wxRect& rect,
649 int flags )
daebb44c 650{
9dc44eff 651 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
3cc638ed
PC
652 if (drawable == NULL)
653 return;
2e992e06 654
3cc638ed 655 if (flags & wxCONTROL_SELECTED)
daebb44c 656 {
c70ad287
VZ
657 int x_diff = 0;
658 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
659 x_diff = rect.width;
660
3cc638ed
PC
661 GtkWidget* treeWidget = wxGTKPrivate::GetTreeWidget();
662
663#ifdef __WXGTK3__
664 GtkStyleContext* sc = gtk_widget_get_style_context(treeWidget);
665 gtk_style_context_save(sc);
666 gtk_style_context_set_state(sc, GTK_STATE_FLAG_SELECTED);
667 gtk_style_context_add_class(sc, GTK_STYLE_CLASS_CELL);
668 gtk_render_background(sc, drawable, rect.x - x_diff, rect.y, rect.width, rect.height);
669 gtk_style_context_restore(sc);
670#else
05d97538
RR
671 // the wxCONTROL_FOCUSED state is deduced
672 // directly from the m_wxwindow by GTK+
3cc638ed 673 gtk_paint_flat_box(gtk_widget_get_style(treeWidget),
9dc44eff 674 drawable,
c70ad287 675 GTK_STATE_SELECTED,
daebb44c 676 GTK_SHADOW_NONE,
9dc44eff 677 NULL_RECT
daebb44c 678 win->m_wxwindow,
05d97538 679 "cell_even",
08f57d21 680 dc.LogicalToDeviceX(rect.x) - x_diff,
daebb44c
RR
681 dc.LogicalToDeviceY(rect.y),
682 rect.width,
683 rect.height );
3cc638ed 684#endif
daebb44c 685 }
90b903c2 686
ce0cf2b8 687 if ((flags & wxCONTROL_CURRENT) && (flags & wxCONTROL_FOCUSED))
c70ad287 688 DrawFocusRect(win, dc, rect, flags);
daebb44c 689}
6d789987
JS
690
691void wxRendererGTK::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
692{
9dc44eff
PC
693 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
694 if (drawable == NULL)
695 return;
6d789987
JS
696
697 GtkStateType state;
698 if (flags & wxCONTROL_SELECTED)
699 state = GTK_STATE_SELECTED;
700 else
701 state = GTK_STATE_NORMAL;
702
9dc44eff
PC
703#ifdef __WXGTK3__
704 GtkStyleContext* sc = gtk_widget_get_style_context(win->m_widget);
705 gtk_style_context_save(sc);
706 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
707 gtk_render_focus(sc, drawable, rect.x, rect.y, rect.width, rect.height);
708 gtk_style_context_restore(sc);
709#else
385e8575 710 gtk_paint_focus( gtk_widget_get_style(win->m_widget),
9dc44eff 711 drawable,
6d789987 712 state,
9dc44eff 713 NULL_RECT
6d789987
JS
714 win->m_wxwindow,
715 NULL,
716 dc.LogicalToDeviceX(rect.x),
717 dc.LogicalToDeviceY(rect.y),
718 rect.width,
719 rect.height );
9dc44eff 720#endif
6d789987 721}
e4131985
KO
722
723// Uses the theme to draw the border and fill for something like a wxTextCtrl
02f07b19 724void wxRendererGTK::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985 725{
9dc44eff
PC
726 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
727 if (drawable == NULL)
728 return;
e4131985 729
295683b2
PC
730 GtkWidget* entry = wxGTKPrivate::GetTextEntryWidget();
731
e4131985
KO
732 GtkStateType state = GTK_STATE_NORMAL;
733 if ( flags & wxCONTROL_DISABLED )
734 state = GTK_STATE_INSENSITIVE;
99c4be68 735
385e8575 736 gtk_widget_set_can_focus(entry, (flags & wxCONTROL_CURRENT) != 0);
e4131985 737
295683b2
PC
738#ifdef __WXGTK3__
739 GtkStyleContext* sc = gtk_widget_get_style_context(entry);
740 gtk_style_context_save(sc);
741 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
742 gtk_render_background(sc, drawable, rect.x, rect.y, rect.width, rect.height);
743 gtk_render_frame(sc, drawable, rect.x, rect.y, rect.width, rect.height);
744 gtk_style_context_restore(sc);
745#else
e4131985
KO
746 gtk_paint_shadow
747 (
385e8575 748 gtk_widget_get_style(entry),
9dc44eff 749 drawable,
e4131985
KO
750 state,
751 GTK_SHADOW_OUT,
9dc44eff 752 NULL_RECT
e4131985
KO
753 entry,
754 "entry",
755 dc.LogicalToDeviceX(rect.x),
756 dc.LogicalToDeviceY(rect.y),
757 rect.width,
99c4be68 758 rect.height
e4131985 759 );
295683b2 760#endif
e4131985
KO
761}
762
4c51a665 763// Draw the equivalent of a wxComboBox
02f07b19 764void wxRendererGTK::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985 765{
9dc44eff 766 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
295683b2
PC
767 if (drawable == NULL)
768 return;
769
770 GtkWidget* combo = wxGTKPrivate::GetComboBoxWidget();
e4131985
KO
771
772 GtkStateType state = GTK_STATE_NORMAL;
773 if ( flags & wxCONTROL_DISABLED )
774 state = GTK_STATE_INSENSITIVE;
99c4be68 775
385e8575 776 gtk_widget_set_can_focus(combo, (flags & wxCONTROL_CURRENT) != 0);
e4131985 777
295683b2
PC
778#ifdef __WXGTK3__
779 GtkStyleContext* sc = gtk_widget_get_style_context(combo);
780 gtk_style_context_save(sc);
781 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
782 gtk_render_background(sc, drawable, rect.x, rect.y, rect.width, rect.height);
783 gtk_render_frame(sc, drawable, rect.x, rect.y, rect.width, rect.height);
784 gtk_style_context_restore(sc);
785 wxRect r = rect;
786 r.x += r.width - r.height;
787 r.width = r.height;
788 DrawComboBoxDropButton(win, dc, r, flags);
789#else
e4131985
KO
790 gtk_paint_shadow
791 (
385e8575 792 gtk_widget_get_style(combo),
9dc44eff 793 drawable,
e4131985
KO
794 state,
795 GTK_SHADOW_OUT,
9dc44eff 796 NULL_RECT
e4131985
KO
797 combo,
798 "combobox",
799 dc.LogicalToDeviceX(rect.x),
800 dc.LogicalToDeviceY(rect.y),
801 rect.width,
99c4be68 802 rect.height
e4131985
KO
803 );
804
805 wxRect r = rect;
806 int extent = rect.height / 2;
807 r.x += rect.width - extent - extent/2;
808 r.y += extent/2;
809 r.width = extent;
810 r.height = extent;
811
812 gtk_paint_arrow
813 (
385e8575 814 gtk_widget_get_style(combo),
9dc44eff 815 drawable,
e4131985
KO
816 state,
817 GTK_SHADOW_OUT,
9dc44eff 818 NULL_RECT
e4131985
KO
819 combo,
820 "arrow",
821 GTK_ARROW_DOWN,
822 TRUE,
823 dc.LogicalToDeviceX(r.x),
824 dc.LogicalToDeviceY(r.y),
825 r.width,
826 r.height
827 );
828
829 r = rect;
830 r.x += rect.width - 2*extent;
831 r.width = 2;
832
833 gtk_paint_box
834 (
385e8575 835 gtk_widget_get_style(combo),
9dc44eff 836 drawable,
e4131985
KO
837 state,
838 GTK_SHADOW_ETCHED_OUT,
9dc44eff 839 NULL_RECT
e4131985
KO
840 combo,
841 "vseparator",
842 dc.LogicalToDeviceX(r.x),
843 dc.LogicalToDeviceY(r.y+1),
844 r.width,
845 r.height-2
846 );
295683b2 847#endif
e4131985
KO
848}
849
e4131985
KO
850void wxRendererGTK::DrawChoice(wxWindow* win, wxDC& dc,
851 const wxRect& rect, int flags)
852{
853 DrawComboBox( win, dc, rect, flags );
854}
855
99c4be68 856
e4131985 857// Draw a themed radio button
6e6b532c 858void wxRendererGTK::DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985 859{
9dc44eff
PC
860 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
861 if (drawable == NULL)
862 return;
99c4be68 863
295683b2
PC
864 GtkWidget* button = wxGTKPrivate::GetRadioButtonWidget();
865
866#ifdef __WXGTK3__
867 int state = GTK_STATE_FLAG_NORMAL;
868 if (flags & wxCONTROL_CHECKED)
869 state = GTK_STATE_FLAG_ACTIVE;
870 else if (flags & wxCONTROL_UNDETERMINED)
871 state = GTK_STATE_FLAG_INCONSISTENT;
872 if (flags & wxCONTROL_DISABLED)
873 state |= GTK_STATE_FLAG_INSENSITIVE;
874
875 GtkStyleContext* sc = gtk_widget_get_style_context(button);
876 gtk_style_context_save(sc);
877 gtk_style_context_add_class(sc, GTK_STYLE_CLASS_RADIO);
878 gtk_style_context_set_state(sc, GtkStateFlags(state));
879 gtk_render_option(sc, drawable, rect.x, rect.y, rect.width, rect.height);
880 gtk_style_context_restore(sc);
881#else
e4131985
KO
882 GtkShadowType shadow_type = GTK_SHADOW_OUT;
883 if ( flags & wxCONTROL_CHECKED )
884 shadow_type = GTK_SHADOW_IN;
885 else if ( flags & wxCONTROL_UNDETERMINED )
886 shadow_type = GTK_SHADOW_ETCHED_IN;
99c4be68 887
e4131985
KO
888 GtkStateType state = GTK_STATE_NORMAL;
889 if ( flags & wxCONTROL_DISABLED )
7e717730 890 state = GTK_STATE_INSENSITIVE;
e4131985 891 if ( flags & wxCONTROL_PRESSED )
7e717730 892 state = GTK_STATE_ACTIVE;
e4131985
KO
893/*
894 Don't know when to set this
895 state_type = GTK_STATE_PRELIGHT;
896*/
897
898 gtk_paint_option
899 (
385e8575 900 gtk_widget_get_style(button),
9dc44eff 901 drawable,
e4131985
KO
902 state,
903 shadow_type,
9dc44eff 904 NULL_RECT
e4131985
KO
905 button,
906 "radiobutton",
99c4be68
VZ
907 dc.LogicalToDeviceX(rect.x),
908 dc.LogicalToDeviceY(rect.y),
e4131985
KO
909 rect.width, rect.height
910 );
295683b2 911#endif
e4131985 912}