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