]> git.saurik.com Git - wxWidgets.git/blame - src/gtk/renderer.cpp
Not calling _size_allocate() breaks a.o. the native wxDataViewCtrl
[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>
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"
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"
888dde65 37#include "wx/gtk/dc.h"
e8759560 38#include "wx/gtk/private.h"
888dde65 39
9c7f49f5 40#include <gtk/gtk.h>
9c7f49f5 41
9c7f49f5 42// ----------------------------------------------------------------------------
38c4cb6a 43// wxRendererGTK: our wxRendererNative implementation
9c7f49f5
VZ
44// ----------------------------------------------------------------------------
45
38c4cb6a 46class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative
9c7f49f5
VZ
47{
48public:
49 // draw the header control button (used by wxListCtrl)
c97c9952 50 virtual int DrawHeaderButton(wxWindow *win,
9c7f49f5
VZ
51 wxDC& dc,
52 const wxRect& rect,
4b94ddc4 53 int flags = 0,
80752b57 54 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE,
4b94ddc4 55 wxHeaderButtonParams* params = NULL);
9c7f49f5 56
6f91f3a3
RR
57 virtual int GetHeaderButtonHeight(wxWindow *win);
58
59
9c7f49f5
VZ
60 // draw the expanded/collapsed icon for a tree control item
61 virtual void DrawTreeItemButton(wxWindow *win,
62 wxDC& dc,
63 const wxRect& rect,
64 int flags = 0);
9c7f49f5 65
d16cf3cd
VZ
66 virtual void DrawSplitterBorder(wxWindow *win,
67 wxDC& dc,
af99040c
VZ
68 const wxRect& rect,
69 int flags = 0);
95155e75
VZ
70 virtual void DrawSplitterSash(wxWindow *win,
71 wxDC& dc,
72 const wxSize& size,
d16cf3cd 73 wxCoord position,
af99040c
VZ
74 wxOrientation orient,
75 int flags = 0);
d16cf3cd 76
38511687
VZ
77 virtual void DrawComboBoxDropButton(wxWindow *win,
78 wxDC& dc,
79 const wxRect& rect,
80 int flags = 0);
81
4c85ab75
VZ
82 virtual void DrawDropArrow(wxWindow *win,
83 wxDC& dc,
84 const wxRect& rect,
85 int flags = 0);
86
90b903c2
WS
87 virtual void DrawCheckBox(wxWindow *win,
88 wxDC& dc,
89 const wxRect& rect,
90 int flags = 0);
2209baae
RR
91
92 virtual void DrawPushButton(wxWindow *win,
93 wxDC& dc,
94 const wxRect& rect,
95 int flags = 0);
96
daebb44c
RR
97 virtual void DrawItemSelectionRect(wxWindow *win,
98 wxDC& dc,
99 const wxRect& rect,
100 int flags = 0);
90b903c2 101
e4131985
KO
102 virtual void DrawChoice(wxWindow* win,
103 wxDC& dc,
104 const wxRect& rect,
105 int flags=0);
106
107 virtual void DrawComboBox(wxWindow* win,
108 wxDC& dc,
109 const wxRect& rect,
110 int flags=0);
111
112 virtual void DrawTextCtrl(wxWindow* win,
113 wxDC& dc,
114 const wxRect& rect,
115 int flags=0);
116
117 virtual void DrawRadioButton(wxWindow* win,
118 wxDC& dc,
119 const wxRect& rect,
120 int flags=0);
121
6d789987
JS
122 virtual void DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags = 0);
123
e8759560 124 virtual wxSize GetCheckBoxSize(wxWindow *win);
f1c09bed 125
e8759560 126 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win);
9c7f49f5
VZ
127};
128
129// ============================================================================
130// implementation
131// ============================================================================
132
133/* static */
f0244295 134wxRendererNative& wxRendererNative::GetDefault()
9c7f49f5
VZ
135{
136 static wxRendererGTK s_rendererGTK;
137
138 return s_rendererGTK;
139}
140
02f07b19 141static GdkWindow* wxGetGdkWindowForDC(wxWindow* win, wxDC& dc)
e4131985
KO
142{
143 GdkWindow* gdk_window = NULL;
02f07b19
KO
144
145#if wxUSE_GRAPHICS_CONTEXT
146 if ( dc.IsKindOf( CLASSINFO(wxGCDC) ) )
d81b2f54 147 gdk_window = win->GTKGetDrawingWindow();
02f07b19
KO
148 else
149#endif
150 {
e4131985 151#if wxUSE_NEW_DC
02f07b19
KO
152 wxDCImpl *impl = dc.GetImpl();
153 wxGTKDCImpl *gtk_impl = wxDynamicCast( impl, wxGTKDCImpl );
154 if (gtk_impl)
155 gdk_window = gtk_impl->GetGDKWindow();
e4131985 156#else
02f07b19 157 gdk_window = dc.GetGDKWindow();
e4131985 158#endif
02f07b19 159 }
e4131985
KO
160 return gdk_window;
161}
162
d16cf3cd
VZ
163// ----------------------------------------------------------------------------
164// list/tree controls drawing
165// ----------------------------------------------------------------------------
166
c97c9952 167int
9c7f49f5
VZ
168wxRendererGTK::DrawHeaderButton(wxWindow *win,
169 wxDC& dc,
170 const wxRect& rect,
4b94ddc4 171 int flags,
80752b57 172 wxHeaderSortIconType sortArrow,
4b94ddc4 173 wxHeaderButtonParams* params)
9c7f49f5 174{
9b311923 175
e8759560 176 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
09e72468
RR
177 if (flags & wxCONTROL_SPECIAL)
178 button = wxGTKPrivate::GetHeaderButtonWidgetFirst();
6f91f3a3 179 if (flags & wxCONTROL_DIRTY)
b047e876 180 button = wxGTKPrivate::GetHeaderButtonWidgetLast();
f1c09bed 181
02f07b19 182 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
183 wxASSERT_MSG( gdk_window,
184 wxT("cannot use wxRendererNative on wxDC of this type") );
185
5eefe029
RR
186 int x_diff = 0;
187 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
188 x_diff = rect.width;
f4322df6 189
1cfc4971
RR
190 GtkStateType state = GTK_STATE_NORMAL;
191 if (flags & wxCONTROL_DISABLED)
192 state = GTK_STATE_INSENSITIVE;
193 else
194 {
195 if (flags & wxCONTROL_CURRENT)
196 state = GTK_STATE_PRELIGHT;
197 }
198
9c7f49f5
VZ
199 gtk_paint_box
200 (
bc13e772 201 button->style,
2e992e06 202 gdk_window,
1cfc4971 203 state,
9c7f49f5 204 GTK_SHADOW_OUT,
38511687 205 NULL,
bc13e772 206 button,
9b311923 207 "button",
5eefe029 208 dc.LogicalToDeviceX(rect.x) - x_diff, rect.y, rect.width, rect.height
9c7f49f5 209 );
6f91f3a3 210
c97c9952 211 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params);
9c7f49f5
VZ
212}
213
6f91f3a3
RR
214int wxRendererGTK::GetHeaderButtonHeight(wxWindow *WXUNUSED(win))
215{
216 GtkWidget *button = wxGTKPrivate::GetHeaderButtonWidget();
217
218 GtkRequisition req;
219 GTK_WIDGET_GET_CLASS(button)->size_request(button, &req);
220
221 return req.height;
222}
223
224
9c7f49f5 225// draw a ">" or "v" button
9c7f49f5 226void
f8b043e7 227wxRendererGTK::DrawTreeItemButton(wxWindow* win,
9a0b7e33 228 wxDC& dc, const wxRect& rect, int flags)
9c7f49f5 229{
e8759560 230 GtkWidget *tree = wxGTKPrivate::GetTreeWidget();
f8b043e7 231
02f07b19 232 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
233 wxASSERT_MSG( gdk_window,
234 wxT("cannot use wxRendererNative on wxDC of this type") );
235
885dd597
RR
236 GtkStateType state;
237 if ( flags & wxCONTROL_CURRENT )
238 state = GTK_STATE_PRELIGHT;
239 else
240 state = GTK_STATE_NORMAL;
91af0895 241
428f4657
RR
242 int x_diff = 0;
243 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
244 x_diff = rect.width;
2e992e06 245
bc13e772
VZ
246 // VZ: I don't know how to get the size of the expander so as to centre it
247 // in the given rectangle, +2/3 below is just what looks good here...
248 gtk_paint_expander
249 (
250 tree->style,
2e992e06 251 gdk_window,
885dd597 252 state,
bc13e772
VZ
253 NULL,
254 tree,
255 "treeview",
11012f47 256 dc.LogicalToDeviceX(rect.x) + 6 - x_diff,
bc13e772
VZ
257 dc.LogicalToDeviceY(rect.y) + 3,
258 flags & wxCONTROL_EXPANDED ? GTK_EXPANDER_EXPANDED
259 : GTK_EXPANDER_COLLAPSED
260 );
9c7f49f5
VZ
261}
262
9c7f49f5 263
d16cf3cd
VZ
264// ----------------------------------------------------------------------------
265// splitter sash drawing
266// ----------------------------------------------------------------------------
267
f1c09bed 268static int GetGtkSplitterFullSize(GtkWidget* widget)
38418827 269{
38418827 270 gint handle_size;
f1c09bed 271 gtk_widget_style_get(widget, "handle_size", &handle_size, NULL);
91af0895 272
38418827 273 return handle_size;
38418827
RR
274}
275
af99040c 276wxSplitterRenderParams
38418827 277wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win))
d16cf3cd 278{
af99040c
VZ
279 // we don't draw any border, hence 0 for the second field
280 return wxSplitterRenderParams
281 (
e8759560 282 GetGtkSplitterFullSize(wxGTKPrivate::GetSplitterWidget()),
af99040c 283 0,
af99040c 284 true // hot sensitive
af99040c 285 );
d16cf3cd
VZ
286}
287
288void
289wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win),
290 wxDC& WXUNUSED(dc),
af99040c
VZ
291 const wxRect& WXUNUSED(rect),
292 int WXUNUSED(flags))
d16cf3cd
VZ
293{
294 // nothing to do
295}
95155e75 296
95155e75 297void
02f07b19 298wxRendererGTK::DrawSplitterSash(wxWindow* win,
95155e75
VZ
299 wxDC& dc,
300 const wxSize& size,
d16cf3cd 301 wxCoord position,
af99040c 302 wxOrientation orient,
68567a96 303 int flags)
95155e75
VZ
304{
305 if ( !win->m_wxwindow->window )
306 {
0100b858 307 // window not realized yet
95155e75
VZ
308 return;
309 }
91af0895 310
02f07b19 311 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
312 wxASSERT_MSG( gdk_window,
313 wxT("cannot use wxRendererNative on wxDC of this type") );
314
e8759560 315 wxCoord full_size = GetGtkSplitterFullSize(wxGTKPrivate::GetSplitterWidget());
95155e75 316
d16cf3cd
VZ
317 // are we drawing vertical or horizontal splitter?
318 const bool isVert = orient == wxVERTICAL;
319
d16cf3cd 320 GdkRectangle rect;
91af0895 321
d16cf3cd
VZ
322 if ( isVert )
323 {
324 rect.x = position;
0100b858 325 rect.y = 0;
38418827 326 rect.width = full_size;
e4161a2a 327 rect.height = size.y;
d16cf3cd
VZ
328 }
329 else // horz
330 {
0100b858 331 rect.x = 0;
d16cf3cd 332 rect.y = position;
38418827 333 rect.height = full_size;
e4161a2a 334 rect.width = size.x;
d16cf3cd 335 }
f4322df6 336
847dfdb4
RR
337 int x_diff = 0;
338 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
339 x_diff = rect.width;
35468934 340
af99040c
VZ
341 gtk_paint_handle
342 (
343 win->m_wxwindow->style,
2e992e06 344 gdk_window,
af99040c
VZ
345 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL,
346 GTK_SHADOW_NONE,
347 NULL /* no clipping */,
348 win->m_wxwindow,
349 "paned",
847dfdb4
RR
350 dc.LogicalToDeviceX(rect.x) - x_diff,
351 dc.LogicalToDeviceY(rect.y),
af99040c
VZ
352 rect.width,
353 rect.height,
38418827 354 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL
af99040c 355 );
95155e75
VZ
356}
357
4c85ab75 358void
02f07b19 359wxRendererGTK::DrawDropArrow(wxWindow* win,
4c85ab75
VZ
360 wxDC& dc,
361 const wxRect& rect,
362 int flags)
38511687 363{
e8759560 364 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
38511687 365
02f07b19 366 // If we give WX_PIZZA(win->m_wxwindow)->bin_window as
4c85ab75
VZ
367 // a window for gtk_paint_xxx function, then it won't
368 // work for wxMemoryDC. So that is why we assume wxDC
369 // is wxWindowDC (wxClientDC, wxMemoryDC and wxPaintDC
370 // are derived from it) and use its m_window.
02f07b19 371 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
372 wxASSERT_MSG( gdk_window,
373 wxT("cannot use wxRendererNative on wxDC of this type") );
a4622f29 374
4c85ab75
VZ
375 // draw arrow so that there is even space horizontally
376 // on both sides
377 int arrowX = rect.width/4 + 1;
378 int arrowWidth = rect.width - (arrowX*2);
379
380 // scale arrow's height accoording to the width
381 int arrowHeight = rect.width/3;
382 int arrowY = (rect.height-arrowHeight)/2 +
383 ((rect.height-arrowHeight) & 1);
384
e1befae3 385 GtkStateType state;
a4622f29 386
3203621a
JS
387 if ( flags & wxCONTROL_PRESSED )
388 state = GTK_STATE_ACTIVE;
a4622f29
VZ
389 else if ( flags & wxCONTROL_DISABLED )
390 state = GTK_STATE_INSENSITIVE;
3203621a
JS
391 else if ( flags & wxCONTROL_CURRENT )
392 state = GTK_STATE_PRELIGHT;
e1befae3
VZ
393 else
394 state = GTK_STATE_NORMAL;
a4622f29 395
a4622f29 396 // draw arrow on button
a4622f29
VZ
397 gtk_paint_arrow
398 (
bc13e772 399 button->style,
2e992e06 400 gdk_window,
a4622f29 401 state,
e1befae3 402 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
a4622f29 403 NULL,
bc13e772 404 button,
a4622f29
VZ
405 "arrow",
406 GTK_ARROW_DOWN,
a8ac548e 407 FALSE,
4c85ab75
VZ
408 rect.x + arrowX,
409 rect.y + arrowY,
410 arrowWidth,
411 arrowHeight
a4622f29 412 );
38511687
VZ
413}
414
4c85ab75
VZ
415void
416wxRendererGTK::DrawComboBoxDropButton(wxWindow *win,
417 wxDC& dc,
418 const wxRect& rect,
419 int flags)
420{
2209baae
RR
421 DrawPushButton(win,dc,rect,flags);
422 DrawDropArrow(win,dc,rect);
423}
424
e8759560
VZ
425wxSize
426wxRendererGTK::GetCheckBoxSize(wxWindow *WXUNUSED(win))
427{
428 gint indicator_size, indicator_spacing;
429 gtk_widget_style_get(wxGTKPrivate::GetCheckButtonWidget(),
430 "indicator_size", &indicator_size,
431 "indicator_spacing", &indicator_spacing,
432 NULL);
433
434 int size = indicator_size + indicator_spacing * 2;
435 return wxSize(size, size);
436}
437
cdccdfab 438void
02f07b19 439wxRendererGTK::DrawCheckBox(wxWindow* win,
90b903c2
WS
440 wxDC& dc,
441 const wxRect& rect,
442 int flags )
2209baae 443{
e8759560 444 GtkWidget *button = wxGTKPrivate::GetCheckButtonWidget();
f1c09bed 445
02f07b19 446 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
447 wxASSERT_MSG( gdk_window,
448 wxT("cannot use wxRendererNative on wxDC of this type") );
90b903c2 449
e8759560
VZ
450 gint indicator_size, indicator_spacing;
451 gtk_widget_style_get(button,
452 "indicator_size", &indicator_size,
453 "indicator_spacing", &indicator_spacing,
454 NULL);
455
4c85ab75
VZ
456 GtkStateType state;
457
3203621a
JS
458 if ( flags & wxCONTROL_PRESSED )
459 state = GTK_STATE_ACTIVE;
4c85ab75
VZ
460 else if ( flags & wxCONTROL_DISABLED )
461 state = GTK_STATE_INSENSITIVE;
3203621a
JS
462 else if ( flags & wxCONTROL_CURRENT )
463 state = GTK_STATE_PRELIGHT;
4c85ab75
VZ
464 else
465 state = GTK_STATE_NORMAL;
90b903c2 466
2209baae 467 gtk_paint_check
4c85ab75
VZ
468 (
469 button->style,
2e992e06 470 gdk_window,
4c85ab75 471 state,
2209baae 472 flags & wxCONTROL_CHECKED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
4c85ab75
VZ
473 NULL,
474 button,
2209baae 475 "cellcheck",
e8759560
VZ
476 dc.LogicalToDeviceX(rect.x) + indicator_spacing,
477 dc.LogicalToDeviceY(rect.y) + indicator_spacing,
478 indicator_size, indicator_size
4c85ab75 479 );
4c85ab75
VZ
480}
481
2209baae 482void
02f07b19 483wxRendererGTK::DrawPushButton(wxWindow* win,
2209baae
RR
484 wxDC& dc,
485 const wxRect& rect,
486 int flags)
862d8041 487{
e8759560 488 GtkWidget *button = wxGTKPrivate::GetButtonWidget();
862d8041 489
02f07b19 490 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
491 wxASSERT_MSG( gdk_window,
492 wxT("cannot use wxRendererNative on wxDC of this type") );
2209baae
RR
493
494 // draw button
862d8041
RR
495 GtkStateType state;
496
497 if ( flags & wxCONTROL_PRESSED )
498 state = GTK_STATE_ACTIVE;
499 else if ( flags & wxCONTROL_DISABLED )
500 state = GTK_STATE_INSENSITIVE;
501 else if ( flags & wxCONTROL_CURRENT )
502 state = GTK_STATE_PRELIGHT;
503 else
504 state = GTK_STATE_NORMAL;
2209baae
RR
505
506 gtk_paint_box
862d8041
RR
507 (
508 button->style,
2e992e06 509 gdk_window,
862d8041 510 state,
2209baae 511 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT,
862d8041
RR
512 NULL,
513 button,
2209baae 514 "button",
e4131985
KO
515 dc.LogicalToDeviceX(rect.x),
516 dc.LogicalToDeviceY(rect.y),
517 rect.width,
518 rect.height
862d8041
RR
519 );
520}
daebb44c 521
cdccdfab 522void
02f07b19 523wxRendererGTK::DrawItemSelectionRect(wxWindow* win,
cdccdfab
WS
524 wxDC& dc,
525 const wxRect& rect,
526 int flags )
daebb44c 527{
981a8049
RR
528 GtkWidget *tree = wxGTKPrivate::GetTreeWidget();
529
02f07b19 530 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
2e992e06
VZ
531 wxASSERT_MSG( gdk_window,
532 wxT("cannot use wxRendererNative on wxDC of this type") );
533
08f57d21
RR
534 int x_diff = 0;
535 if (win->GetLayoutDirection() == wxLayout_RightToLeft)
536 x_diff = rect.width;
537
981a8049
RR
538 GtkStateType state = GTK_STATE_NORMAL;
539
90b903c2 540 if (flags & wxCONTROL_SELECTED)
daebb44c 541 {
05d97538
RR
542 // the wxCONTROL_FOCUSED state is deduced
543 // directly from the m_wxwindow by GTK+
544 state = GTK_STATE_SELECTED;
daebb44c 545
981a8049 546 gtk_paint_flat_box( tree->style, // win->m_widget->style,
2e992e06 547 gdk_window,
daebb44c
RR
548 state,
549 GTK_SHADOW_NONE,
cdccdfab 550 NULL,
daebb44c 551 win->m_wxwindow,
05d97538 552 "cell_even",
08f57d21 553 dc.LogicalToDeviceX(rect.x) - x_diff,
daebb44c
RR
554 dc.LogicalToDeviceY(rect.y),
555 rect.width,
556 rect.height );
557 }
72be9a3a
VZ
558 else // !wxCONTROL_SELECTED
559 {
560 state = GTK_STATE_NORMAL;
561 }
90b903c2 562
ce0cf2b8 563 if ((flags & wxCONTROL_CURRENT) && (flags & wxCONTROL_FOCUSED))
daebb44c 564 {
981a8049
RR
565 if (flags & wxCONTROL_SELECTED)
566 state = GTK_STATE_SELECTED;
567
568 gtk_paint_focus( tree->style,
05d97538 569 gdk_window,
72be9a3a 570 state,
05d97538
RR
571 NULL,
572 win->m_wxwindow,
5a34b9b9
PC
573 // Detail "treeview" causes warning with GTK+ 2.12 Clearlooks theme:
574 // "... no property named `row-ending-details'"
575 // Using "treeview-middle" would fix the warning, but the right
576 // edge of the focus rect is not getting erased properly either.
577 // Better to not specify this detail unless the drawing is fixed.
981a8049
RR
578 // RR: I added that to the Pizza widget class.
579 "treeview",
05d97538
RR
580 dc.LogicalToDeviceX(rect.x),
581 dc.LogicalToDeviceY(rect.y),
582 rect.width,
583 rect.height );
daebb44c
RR
584 }
585}
6d789987
JS
586
587void wxRendererGTK::DrawFocusRect(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
588{
02f07b19 589 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
6d789987
JS
590 wxASSERT_MSG( gdk_window,
591 wxT("cannot use wxRendererNative on wxDC of this type") );
592
593 GtkStateType state;
594 if (flags & wxCONTROL_SELECTED)
595 state = GTK_STATE_SELECTED;
596 else
597 state = GTK_STATE_NORMAL;
598
599 gtk_paint_focus( win->m_widget->style,
600 gdk_window,
601 state,
602 NULL,
603 win->m_wxwindow,
604 NULL,
605 dc.LogicalToDeviceX(rect.x),
606 dc.LogicalToDeviceY(rect.y),
607 rect.width,
608 rect.height );
609}
e4131985
KO
610
611// Uses the theme to draw the border and fill for something like a wxTextCtrl
02f07b19 612void wxRendererGTK::DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985
KO
613{
614 GtkWidget *entry = wxGTKPrivate::GetTextEntryWidget();
615
02f07b19 616 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
e4131985
KO
617
618 GtkStateType state = GTK_STATE_NORMAL;
619 if ( flags & wxCONTROL_DISABLED )
620 state = GTK_STATE_INSENSITIVE;
621
622 if (flags & wxCONTROL_CURRENT )
623 GTK_WIDGET_SET_FLAGS( entry, GTK_HAS_FOCUS );
624 else
625 GTK_WIDGET_UNSET_FLAGS( entry, GTK_HAS_FOCUS );
626
627 gtk_paint_shadow
628 (
629 entry->style,
630 gdk_window,
631 state,
632 GTK_SHADOW_OUT,
633 NULL,
634 entry,
635 "entry",
636 dc.LogicalToDeviceX(rect.x),
637 dc.LogicalToDeviceY(rect.y),
638 rect.width,
639 rect.height
640 );
641}
642
643// Draw the equivallent of a wxComboBox
02f07b19 644void wxRendererGTK::DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985
KO
645{
646 GtkWidget *combo = wxGTKPrivate::GetComboBoxWidget();
647
02f07b19 648 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
e4131985
KO
649
650 GtkStateType state = GTK_STATE_NORMAL;
651 if ( flags & wxCONTROL_DISABLED )
652 state = GTK_STATE_INSENSITIVE;
653
654 if (flags & wxCONTROL_CURRENT )
655 GTK_WIDGET_SET_FLAGS( combo, GTK_HAS_FOCUS );
656 else
657 GTK_WIDGET_UNSET_FLAGS( combo, GTK_HAS_FOCUS );
658
659 gtk_paint_shadow
660 (
661 combo->style,
662 gdk_window,
663 state,
664 GTK_SHADOW_OUT,
665 NULL,
666 combo,
667 "combobox",
668 dc.LogicalToDeviceX(rect.x),
669 dc.LogicalToDeviceY(rect.y),
670 rect.width,
671 rect.height
672 );
673
674 wxRect r = rect;
675 int extent = rect.height / 2;
676 r.x += rect.width - extent - extent/2;
677 r.y += extent/2;
678 r.width = extent;
679 r.height = extent;
680
681 gtk_paint_arrow
682 (
683 combo->style,
684 gdk_window,
685 state,
686 GTK_SHADOW_OUT,
687 NULL,
688 combo,
689 "arrow",
690 GTK_ARROW_DOWN,
691 TRUE,
692 dc.LogicalToDeviceX(r.x),
693 dc.LogicalToDeviceY(r.y),
694 r.width,
695 r.height
696 );
697
698 r = rect;
699 r.x += rect.width - 2*extent;
700 r.width = 2;
701
702 gtk_paint_box
703 (
704 combo->style,
705 gdk_window,
706 state,
707 GTK_SHADOW_ETCHED_OUT,
708 NULL,
709 combo,
710 "vseparator",
711 dc.LogicalToDeviceX(r.x),
712 dc.LogicalToDeviceY(r.y+1),
713 r.width,
714 r.height-2
715 );
716}
717
718
719void wxRendererGTK::DrawChoice(wxWindow* win, wxDC& dc,
720 const wxRect& rect, int flags)
721{
722 DrawComboBox( win, dc, rect, flags );
723}
724
725
726// Draw a themed radio button
02f07b19 727void wxRendererGTK::DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags)
e4131985
KO
728{
729 GtkWidget *button = wxGTKPrivate::GetRadioButtonWidget();
730
02f07b19 731 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc);
e4131985
KO
732
733 GtkShadowType shadow_type = GTK_SHADOW_OUT;
734 if ( flags & wxCONTROL_CHECKED )
735 shadow_type = GTK_SHADOW_IN;
736 else if ( flags & wxCONTROL_UNDETERMINED )
737 shadow_type = GTK_SHADOW_ETCHED_IN;
738
739 GtkStateType state = GTK_STATE_NORMAL;
740 if ( flags & wxCONTROL_DISABLED )
7e717730 741 state = GTK_STATE_INSENSITIVE;
e4131985 742 if ( flags & wxCONTROL_PRESSED )
7e717730 743 state = GTK_STATE_ACTIVE;
e4131985
KO
744/*
745 Don't know when to set this
746 state_type = GTK_STATE_PRELIGHT;
747*/
748
749 gtk_paint_option
750 (
751 button->style,
752 gdk_window,
753 state,
754 shadow_type,
755 NULL,
756 button,
757 "radiobutton",
758 dc.LogicalToDeviceX(rect.x),
759 dc.LogicalToDeviceY(rect.y),
760 rect.width, rect.height
761 );
762}