]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/renderer.cpp
Fix for scroll position being changed when partial layout is done
[wxWidgets.git] / src / gtk / renderer.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/renderer.cpp
3 // Purpose: implementation of wxRendererNative for wxGTK
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>
9 // Licence: wxWindows licence
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
27 #include "wx/renderer.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/window.h"
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #include "wx/module.h"
34 #endif
35
36 #include "wx/dcgraph.h"
37 #ifndef __WXGTK3__
38 #include "wx/gtk/dc.h"
39 #endif
40
41 #include <gtk/gtk.h>
42 #include "wx/gtk/private.h"
43 #include "wx/gtk/private/gtk2-compat.h"
44
45 // ----------------------------------------------------------------------------
46 // wxRendererGTK: our wxRendererNative implementation
47 // ----------------------------------------------------------------------------
48
49 class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
50 {
51 public:
52 // draw the header control button (used by wxListCtrl)
53 virtual int DrawHeaderButton(wxWindow *win,
54 wxDC& dc,
55 const wxRect& rect,
56 int flags = 0,
57 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
58 wxHeaderButtonParams* params = NULL);
59
60 virtual int GetHeaderButtonHeight(wxWindow *win);
61
62 virtual int GetHeaderButtonMargin(wxWindow *win);
63
64
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);
70
71 virtual void DrawSplitterBorder(wxWindow *win,
72 wxDC& dc,
73 const wxRect& rect,
74 int flags = 0);
75 virtual void DrawSplitterSash(wxWindow *win,
76 wxDC& dc,
77 const wxSize& size,
78 wxCoord position,
79 wxOrientation orient,
80 int flags = 0);
81
82 virtual void DrawComboBoxDropButton(wxWindow *win,
83 wxDC& dc,
84 const wxRect& rect,
85 int flags = 0);
86
87 virtual void DrawDropArrow(wxWindow *win,
88 wxDC& dc,
89 const wxRect& rect,
90 int flags = 0);
91
92 virtual void DrawCheckBox(wxWindow *win,
93 wxDC& dc,
94 const wxRect& rect,
95 int flags = 0);
96
97 virtual void DrawPushButton(wxWindow *win,
98 wxDC& dc,
99 const wxRect& rect,
100 int flags = 0);
101
102 virtual void DrawItemSelectionRect(wxWindow *win,
103 wxDC& dc,
104 const wxRect& rect,
105 int flags = 0);
106
107 virtual void DrawChoice(wxWindow* win,
108 wxDC& dc,
109 const wxRect& rect,
110 int flags=0);
111
112 virtual void DrawComboBox(wxWindow* win,
113 wxDC& dc,
114 const wxRect& rect,
115 int flags=0);
116
117 virtual void DrawTextCtrl(wxWindow* win,
118 wxDC& dc,
119 const wxRect& rect,
120 int flags=0);
121
122 virtual void DrawRadioBitmap(wxWindow* win,
123 wxDC& dc,
124 const wxRect& rect,
125 int flags=0);
126
127 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
128
129 virtual wxSize GetCheckBoxSize(wxWindow *win);
130
131 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
132 };
133
134 // ============================================================================
135 // implementation
136 // ============================================================================
137
138 /* static */
139 wxRendererNative& wxRendererNative::GetDefault()
140 {
141 static wxRendererGTK s_rendererGTK;
142
143 return s_rendererGTK;
144 }
145
146 #ifdef __WXGTK3__
147 #define NULL_RECT
148 typedef cairo_t wxGTKDrawable;
149
150 static 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
157 static 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,
165 typedef GdkWindow wxGTKDrawable;
166
167 static GdkWindow* wxGetGTKDrawable(wxWindow* win, wxDC& dc)
168 {
169 GdkWindow* gdk_window = NULL;
170
171 #if wxUSE_GRAPHICS_CONTEXT
172 if ( wxDynamicCast(&dc, wxGCDC) )
173 gdk_window = win->GTKGetDrawingWindow();
174 else
175 #endif
176 {
177 wxDCImpl *impl = dc.GetImpl();
178 wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl );
179 if (gtk_impl)
180 gdk_window = gtk_impl->GetGDKWindow();
181 else
182 wxFAIL_MSG("cannot use wxRendererNative on wxDC of this type");
183 }
184
185 #if !wxUSE_GRAPHICS_CONTEXT
186 wxUnusedVar(win);
187 #endif
188
189 return gdk_window;
190 }
191 #endif
192
193 // ----------------------------------------------------------------------------
194 // list/tree controls drawing
195 // ----------------------------------------------------------------------------
196
197 int
198 wxRendererGTK::DrawHeaderButton(wxWindow *win,
199 wxDC& dc,
200 const wxRect& rect,
201 int flags,
202 wxHeaderSortIconType sortArrow,
203 wxHeaderButtonParams* params)
204 {
205 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
206 if (flags & wxCONTROL_SPECIAL)
207 button = wxGTKPrivate::GetHeaderButtonWidgetFirst();
208 if (flags & wxCONTROL_DIRTY)
209 button = wxGTKPrivate::GetHeaderButtonWidgetLast();
210
211 int x_diff = 0;
212 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
213 x_diff = rect.width;
214
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
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);
237 gtk_paint_box
238 (
239 gtk_widget_get_style(button),
240 gdk_window,
241 state,
242 GTK_SHADOW_OUT,
243 NULL,
244 button,
245 "button",
246 dc.LogicalToDeviceX(rect.x) - x_diff, rect.y, rect.width, rect.height
247 );
248 #endif
249
250 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
251 }
252
253 int wxRendererGTK::GetHeaderButtonHeight(wxWindow *WXUNUSED(win))
254 {
255 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
256
257 GtkRequisition req;
258 #ifdef __WXGTK3__
259 gtk_widget_get_preferred_height(button, NULL, &req.height);
260 #else
261 GTK_WIDGET_GET_CLASS(button)->size_request(button, &req);
262 #endif
263
264 return req.height;
265 }
266
267 int wxRendererGTK::GetHeaderButtonMargin(wxWindow *WXUNUSED(win))
268 {
269 wxFAIL_MSG( "GetHeaderButtonMargin() not implemented" );
270 return -1;
271 }
272
273
274 // draw a ">" or "v" button
275 void
276 wxRendererGTK::DrawTreeItemButton(wxWindow* win,
277 wxDC& dc, const wxRect& rect, int flags)
278 {
279 GtkWidget *tree = wxGTKPrivate::GetTreeWidget();
280
281 GtkStateType state;
282 if ( flags & wxCONTROL_CURRENT )
283 state = GTK_STATE_PRELIGHT;
284 else
285 state = GTK_STATE_NORMAL;
286
287 int x_diff = 0;
288 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
289 x_diff = rect.width;
290
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
300 // x and y parameters specify the center of the expander
301 GdkWindow* gdk_window = wxGetGTKDrawable(win, dc);
302 if (gdk_window == NULL)
303 return;
304 gtk_paint_expander
305 (
306 gtk_widget_get_style(tree),
307 gdk_window,
308 state,
309 NULL,
310 tree,
311 "treeview",
312 dc.LogicalToDeviceX(rect.x) + rect.width / 2 - x_diff,
313 dc.LogicalToDeviceY(rect.y) + rect.height / 2,
314 flags & wxCONTROL_EXPANDED ? GTK_EXPANDER_EXPANDED
315 : GTK_EXPANDER_COLLAPSED
316 );
317 #endif
318 }
319
320
321 // ----------------------------------------------------------------------------
322 // splitter sash drawing
323 // ----------------------------------------------------------------------------
324
325 static int GetGtkSplitterFullSize(GtkWidget* widget)
326 {
327 gint handle_size;
328 gtk_widget_style_get(widget, "handle_size", &handle_size, NULL);
329
330 return handle_size;
331 }
332
333 wxSplitterRenderParams
334 wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
335 {
336 // we don't draw any border, hence 0 for the second field
337 return wxSplitterRenderParams
338 (
339 GetGtkSplitterFullSize(wxGTKPrivate::GetSplitterWidget()),
340 0,
341 true // hot sensitive
342 );
343 }
344
345 void
346 wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
347 wxDC& WXUNUSED(dc),
348 const wxRect& WXUNUSED(rect),
349 int WXUNUSED(flags))
350 {
351 // nothing to do
352 }
353
354 void
355 wxRendererGTK::DrawSplitterSash(wxWindow* win,
356 wxDC& dc,
357 const wxSize& size,
358 wxCoord position,
359 wxOrientation orient,
360 int flags)
361 {
362 if (gtk_widget_get_window(win->m_wxwindow) == NULL)
363 {
364 // window not realized yet
365 return;
366 }
367
368 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
369 if (drawable == NULL)
370 return;
371
372 // are we drawing vertical or horizontal splitter?
373 const bool isVert = orient == wxVERTICAL;
374
375 GtkWidget* widget = wxGTKPrivate::GetSplitterWidget(orient);
376 const int full_size = GetGtkSplitterFullSize(widget);
377
378 GdkRectangle rect;
379
380 if ( isVert )
381 {
382 rect.x = position;
383 rect.y = 0;
384 rect.width = full_size;
385 rect.height = size.y;
386 }
387 else // horz
388 {
389 rect.x = 0;
390 rect.y = position;
391 rect.height = full_size;
392 rect.width = size.x;
393 }
394
395 int x_diff = 0;
396 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
397 x_diff = rect.width;
398
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;
411 gtk_paint_handle
412 (
413 gtk_widget_get_style(win->m_wxwindow),
414 gdk_window,
415 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
416 GTK_SHADOW_NONE,
417 NULL /* no clipping */,
418 win->m_wxwindow,
419 "paned",
420 dc.LogicalToDeviceX(rect.x) - x_diff,
421 dc.LogicalToDeviceY(rect.y),
422 rect.width,
423 rect.height,
424 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
425 );
426 #endif
427 }
428
429 void
430 wxRendererGTK::DrawDropArrow(wxWindow* win,
431 wxDC& dc,
432 const wxRect& rect,
433 int flags)
434 {
435 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
436
437 // If we give WX_PIZZA(win->m_wxwindow)->bin_window as
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.
442
443 // draw arrow so that there is even space horizontally
444 // on both sides
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;
448
449 GtkStateType state;
450
451 if ( flags & wxCONTROL_PRESSED )
452 state = GTK_STATE_ACTIVE;
453 else if ( flags & wxCONTROL_DISABLED )
454 state = GTK_STATE_INSENSITIVE;
455 else if ( flags & wxCONTROL_CURRENT )
456 state = GTK_STATE_PRELIGHT;
457 else
458 state = GTK_STATE_NORMAL;
459
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;
472 // draw arrow on button
473 gtk_paint_arrow
474 (
475 gtk_widget_get_style(button),
476 gdk_window,
477 state,
478 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
479 NULL,
480 button,
481 "arrow",
482 GTK_ARROW_DOWN,
483 FALSE,
484 x, y,
485 size, size
486 );
487 #endif
488 }
489
490 void
491 wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
492 wxDC& dc,
493 const wxRect& rect,
494 int flags)
495 {
496 DrawPushButton(win,dc,rect,flags);
497 DrawDropArrow(win,dc,rect);
498 }
499
500 wxSize
501 wxRendererGTK::GetCheckBoxSize(wxWindow *WXUNUSED(win))
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
513 void
514 wxRendererGTK::DrawCheckBox(wxWindow* win,
515 wxDC& dc,
516 const wxRect& rect,
517 int flags )
518 {
519 GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget();
520
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
527 #ifndef __WXGTK3__
528 GtkStateType state;
529
530 if ( flags & wxCONTROL_PRESSED )
531 state = GTK_STATE_ACTIVE;
532 else if ( flags & wxCONTROL_DISABLED )
533 state = GTK_STATE_INSENSITIVE;
534 else if ( flags & wxCONTROL_CURRENT )
535 state = GTK_STATE_PRELIGHT;
536 else
537 state = GTK_STATE_NORMAL;
538
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;
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;
576
577 gtk_paint_check
578 (
579 gtk_widget_get_style(button),
580 gdk_window,
581 state,
582 shadow_type,
583 NULL,
584 button,
585 "cellcheck",
586 dc.LogicalToDeviceX(rect.x) + indicator_spacing,
587 dc.LogicalToDeviceY(rect.y) + indicator_spacing,
588 indicator_size, indicator_size
589 );
590 #endif
591 }
592
593 void
594 wxRendererGTK::DrawPushButton(wxWindow* win,
595 wxDC& dc,
596 const wxRect& rect,
597 int flags)
598 {
599 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
600
601 // draw button
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;
612
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
629 gtk_paint_box
630 (
631 gtk_widget_get_style(button),
632 gdk_window,
633 state,
634 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
635 NULL,
636 button,
637 "button",
638 dc.LogicalToDeviceX(rect.x),
639 dc.LogicalToDeviceY(rect.y),
640 rect.width,
641 rect.height
642 );
643 #endif
644 }
645
646 void
647 wxRendererGTK::DrawItemSelectionRect(wxWindow* win,
648 wxDC& dc,
649 const wxRect& rect,
650 int flags )
651 {
652 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
653
654 if (drawable && (flags & wxCONTROL_SELECTED))
655 {
656 int x_diff = 0;
657 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
658 x_diff = rect.width;
659
660 // the wxCONTROL_FOCUSED state is deduced
661 // directly from the m_wxwindow by GTK+
662 gtk_paint_flat_box(gtk_widget_get_style(wxGTKPrivate::GetTreeWidget()),
663 drawable,
664 GTK_STATE_SELECTED,
665 GTK_SHADOW_NONE,
666 NULL_RECT
667 win->m_wxwindow,
668 "cell_even",
669 dc.LogicalToDeviceX(rect.x) - x_diff,
670 dc.LogicalToDeviceY(rect.y),
671 rect.width,
672 rect.height );
673 }
674
675 if ((flags & wxCONTROL_CURRENT) && (flags & wxCONTROL_FOCUSED))
676 DrawFocusRect(win, dc, rect, flags);
677 }
678
679 void wxRendererGTK::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
680 {
681 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
682 if (drawable == NULL)
683 return;
684
685 GtkStateType state;
686 if (flags & wxCONTROL_SELECTED)
687 state = GTK_STATE_SELECTED;
688 else
689 state = GTK_STATE_NORMAL;
690
691 #ifdef __WXGTK3__
692 GtkStyleContext* sc = gtk_widget_get_style_context(win->m_widget);
693 gtk_style_context_save(sc);
694 gtk_style_context_set_state(sc, stateTypeToFlags[state]);
695 gtk_render_focus(sc, drawable, rect.x, rect.y, rect.width, rect.height);
696 gtk_style_context_restore(sc);
697 #else
698 gtk_paint_focus( gtk_widget_get_style(win->m_widget),
699 drawable,
700 state,
701 NULL_RECT
702 win->m_wxwindow,
703 NULL,
704 dc.LogicalToDeviceX(rect.x),
705 dc.LogicalToDeviceY(rect.y),
706 rect.width,
707 rect.height );
708 #endif
709 }
710
711 //TODO: GTK3 implementations for the remaining functions below
712
713 // Uses the theme to draw the border and fill for something like a wxTextCtrl
714 void wxRendererGTK::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
715 {
716 GtkWidget *entry = wxGTKPrivate::GetTextEntryWidget();
717
718 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
719 if (drawable == NULL)
720 return;
721
722 GtkStateType state = GTK_STATE_NORMAL;
723 if ( flags & wxCONTROL_DISABLED )
724 state = GTK_STATE_INSENSITIVE;
725
726 gtk_widget_set_can_focus(entry, (flags & wxCONTROL_CURRENT) != 0);
727
728 gtk_paint_shadow
729 (
730 gtk_widget_get_style(entry),
731 drawable,
732 state,
733 GTK_SHADOW_OUT,
734 NULL_RECT
735 entry,
736 "entry",
737 dc.LogicalToDeviceX(rect.x),
738 dc.LogicalToDeviceY(rect.y),
739 rect.width,
740 rect.height
741 );
742 }
743
744 // Draw the equivalent of a wxComboBox
745 void wxRendererGTK::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
746 {
747 GtkWidget *combo = wxGTKPrivate::GetComboBoxWidget();
748
749 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
750
751 GtkStateType state = GTK_STATE_NORMAL;
752 if ( flags & wxCONTROL_DISABLED )
753 state = GTK_STATE_INSENSITIVE;
754
755 gtk_widget_set_can_focus(combo, (flags & wxCONTROL_CURRENT) != 0);
756
757 if (drawable == NULL)
758 return;
759
760 gtk_paint_shadow
761 (
762 gtk_widget_get_style(combo),
763 drawable,
764 state,
765 GTK_SHADOW_OUT,
766 NULL_RECT
767 combo,
768 "combobox",
769 dc.LogicalToDeviceX(rect.x),
770 dc.LogicalToDeviceY(rect.y),
771 rect.width,
772 rect.height
773 );
774
775 wxRect r = rect;
776 int extent = rect.height / 2;
777 r.x += rect.width - extent - extent/2;
778 r.y += extent/2;
779 r.width = extent;
780 r.height = extent;
781
782 gtk_paint_arrow
783 (
784 gtk_widget_get_style(combo),
785 drawable,
786 state,
787 GTK_SHADOW_OUT,
788 NULL_RECT
789 combo,
790 "arrow",
791 GTK_ARROW_DOWN,
792 TRUE,
793 dc.LogicalToDeviceX(r.x),
794 dc.LogicalToDeviceY(r.y),
795 r.width,
796 r.height
797 );
798
799 r = rect;
800 r.x += rect.width - 2*extent;
801 r.width = 2;
802
803 gtk_paint_box
804 (
805 gtk_widget_get_style(combo),
806 drawable,
807 state,
808 GTK_SHADOW_ETCHED_OUT,
809 NULL_RECT
810 combo,
811 "vseparator",
812 dc.LogicalToDeviceX(r.x),
813 dc.LogicalToDeviceY(r.y+1),
814 r.width,
815 r.height-2
816 );
817 }
818
819
820 void wxRendererGTK::DrawChoice(wxWindow* win, wxDC& dc,
821 const wxRect& rect, int flags)
822 {
823 DrawComboBox( win, dc, rect, flags );
824 }
825
826
827 // Draw a themed radio button
828 void wxRendererGTK::DrawRadioBitmap(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
829 {
830 GtkWidget *button = wxGTKPrivate::GetRadioButtonWidget();
831
832 wxGTKDrawable* drawable = wxGetGTKDrawable(win, dc);
833 if (drawable == NULL)
834 return;
835
836 GtkShadowType shadow_type = GTK_SHADOW_OUT;
837 if ( flags & wxCONTROL_CHECKED )
838 shadow_type = GTK_SHADOW_IN;
839 else if ( flags & wxCONTROL_UNDETERMINED )
840 shadow_type = GTK_SHADOW_ETCHED_IN;
841
842 GtkStateType state = GTK_STATE_NORMAL;
843 if ( flags & wxCONTROL_DISABLED )
844 state = GTK_STATE_INSENSITIVE;
845 if ( flags & wxCONTROL_PRESSED )
846 state = GTK_STATE_ACTIVE;
847 /*
848 Don't know when to set this
849 state_type = GTK_STATE_PRELIGHT;
850 */
851
852 gtk_paint_option
853 (
854 gtk_widget_get_style(button),
855 drawable,
856 state,
857 shadow_type,
858 NULL_RECT
859 button,
860 "radiobutton",
861 dc.LogicalToDeviceX(rect.x),
862 dc.LogicalToDeviceY(rect.y),
863 rect.width, rect.height
864 );
865 }