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