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: renderer.cpp 54792 2008-07-28 05:49:04Z PC $ 8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org> 9// License: 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#endif 34 35#include <gtk/gtk.h> 36#include "wx/gtk/win_gtk.h" 37 38// ---------------------------------------------------------------------------- 39// wxRendererGTK: our wxRendererNative implementation 40// ---------------------------------------------------------------------------- 41 42class WXDLLEXPORT wxRendererGTK : public wxDelegateRendererNative 43{ 44public: 45 // draw the header control button (used by wxListCtrl) 46 virtual int DrawHeaderButton(wxWindow *win, 47 wxDC& dc, 48 const wxRect& rect, 49 int flags = 0, 50 wxHeaderSortIconType sortArrow = wxHDR_SORT_ICON_NONE, 51 wxHeaderButtonParams* params = NULL); 52 53 // draw the expanded/collapsed icon for a tree control item 54 virtual void DrawTreeItemButton(wxWindow *win, 55 wxDC& dc, 56 const wxRect& rect, 57 int flags = 0); 58 59 virtual void DrawSplitterBorder(wxWindow *win, 60 wxDC& dc, 61 const wxRect& rect, 62 int flags = 0); 63 virtual void DrawSplitterSash(wxWindow *win, 64 wxDC& dc, 65 const wxSize& size, 66 wxCoord position, 67 wxOrientation orient, 68 int flags = 0); 69 70 virtual void DrawComboBoxDropButton(wxWindow *win, 71 wxDC& dc, 72 const wxRect& rect, 73 int flags = 0); 74 75 virtual void DrawDropArrow(wxWindow *win, 76 wxDC& dc, 77 const wxRect& rect, 78 int flags = 0); 79 80 virtual void DrawCheckBox(wxWindow *win, 81 wxDC& dc, 82 const wxRect& rect, 83 int flags = 0); 84 85 virtual void DrawPushButton(wxWindow *win, 86 wxDC& dc, 87 const wxRect& rect, 88 int flags = 0); 89 90 virtual void DrawItemSelectionRect(wxWindow *win, 91 wxDC& dc, 92 const wxRect& rect, 93 int flags = 0); 94 95 virtual wxSplitterRenderParams GetSplitterParams(const wxWindow *win); 96 97// private: 98 // FIXME: shouldn't we destroy these windows somewhere? 99 100 // used by DrawPushButton and DrawDropArrow 101 static GtkWidget *GetButtonWidget(); 102 103 // used by DrawTreeItemButton() 104 static GtkWidget *GetTreeWidget(); 105 106 // used by DrawCheckBox() 107 static GtkWidget *GetCheckButtonWidget(); 108 109 // used by DrawRadioButton() 110 static GtkWidget *GetRadioButtonWidget(); 111 112 // Used by DrawHeaderButton 113 static GtkWidget *GetHeaderButtonWidget(); 114 115 // Used by DrawTextCtrl 116 static GtkWidget *GetTextEntryWidget(); 117 118 // Used by DrawComboBox 119 static GtkWidget *GetComboBoxWidget(); 120}; 121 122GdkWindow* wxGetGdkWindowForDC(wxWindow* win, wxDC& dc) 123{ 124 // The way to get a GdkWindow* from a wxWindow is to use 125 // GTK_PIZZA(win->m_wxwindow)->bin_window, but this approach 126 // won't work when drawing to a wxMemoryDC as it has its own 127 // GdkWindow* for its bitmap. wxWindowDC's GetGDKWindow() was 128 // designed to create a solution for all DCs, but we can't 129 // implement it with wxGCDC since it doesn't retain its wxWindow. 130 // So, to work around this, we use GetGDKWindow whenever possible 131 // and use bin_window for wxGCDC. 132 GdkWindow* gdk_window = NULL; 133#if wxUSE_GRAPHICS_CONTEXT 134 if ( dc.IsKindOf( CLASSINFO(wxGCDC) ) ) 135 gdk_window = GTK_PIZZA(win->m_wxwindow)->bin_window; 136 else 137#endif 138 gdk_window = dc.GetGDKWindow(); 139 wxASSERT_MSG( gdk_window, 140 wxT("cannot use wxRendererNative on wxDC of this type") ); 141 142 return gdk_window; 143} 144 145// ============================================================================ 146// implementation 147// ============================================================================ 148 149/* static */ 150wxRendererNative& wxRendererNative::GetDefault() 151{ 152 static wxRendererGTK s_rendererGTK; 153 154 return s_rendererGTK; 155} 156 157// ---------------------------------------------------------------------------- 158// helper functions 159// ---------------------------------------------------------------------------- 160 161GtkWidget * 162wxRendererGTK::GetButtonWidget() 163{ 164 static GtkWidget *s_button = NULL; 165 static GtkWidget *s_window = NULL; 166 167 if ( !s_button ) 168 { 169 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 170 gtk_widget_realize( s_window ); 171 s_button = gtk_button_new(); 172 gtk_container_add( GTK_CONTAINER(s_window), s_button ); 173 gtk_widget_realize( s_button ); 174 } 175 176 return s_button; 177} 178 179GtkWidget * 180wxRendererGTK::GetTextEntryWidget() 181{ 182 static GtkWidget *s_button = NULL; 183 static GtkWidget *s_window = NULL; 184 185 if ( !s_button ) 186 { 187 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 188 gtk_widget_realize( s_window ); 189 s_button = gtk_entry_new(); 190 gtk_container_add( GTK_CONTAINER(s_window), s_button ); 191 gtk_widget_realize( s_button ); 192 } 193 194 return s_button; 195} 196 197GtkWidget * 198wxRendererGTK::GetComboBoxWidget() 199{ 200 static GtkWidget *s_button = NULL; 201 static GtkWidget *s_window = NULL; 202 203#ifdef __WXGTK24__ 204 if (!gtk_check_version(2,4,0)) 205 { 206 if ( !s_button ) 207 { 208 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 209 gtk_widget_realize( s_window ); 210 s_button = gtk_combo_box_new(); 211 gtk_container_add( GTK_CONTAINER(s_window), s_button ); 212 gtk_widget_realize( s_button ); 213 } 214 } 215#endif 216 return s_button; 217} 218 219GtkWidget * 220wxRendererGTK::GetCheckButtonWidget() 221{ 222 static GtkWidget *s_button = NULL; 223 static GtkWidget *s_window = NULL; 224 225 if ( !s_button ) 226 { 227 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 228 gtk_widget_realize( s_window ); 229 s_button = gtk_check_button_new(); 230 gtk_container_add( GTK_CONTAINER(s_window), s_button ); 231 gtk_widget_realize( s_button ); 232 } 233 234 return s_button; 235} 236 237GtkWidget * 238wxRendererGTK::GetRadioButtonWidget() 239{ 240 static GtkWidget *s_button = NULL; 241 static GtkWidget *s_window = NULL; 242 243 if ( !s_button ) 244 { 245 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 246 gtk_widget_realize( s_window ); 247 s_button = gtk_radio_button_new(NULL); 248 gtk_container_add( GTK_CONTAINER(s_window), s_button ); 249 gtk_widget_realize( s_button ); 250 } 251 252 return s_button; 253} 254 255GtkWidget * 256wxRendererGTK::GetTreeWidget() 257{ 258 static GtkWidget *s_tree = NULL; 259 static GtkWidget *s_window = NULL; 260 261 if ( !s_tree ) 262 { 263 s_tree = gtk_tree_view_new(); 264 s_window = gtk_window_new( GTK_WINDOW_POPUP ); 265 gtk_widget_realize( s_window ); 266 gtk_container_add( GTK_CONTAINER(s_window), s_tree ); 267 gtk_widget_realize( s_tree ); 268 } 269 270 return s_tree; 271} 272 273 274// This one just gets the button used by the column header. Although it's 275// still a gtk_button the themes will typically differentiate and draw them 276// differently if the button is in a treeview. 277GtkWidget * 278wxRendererGTK::GetHeaderButtonWidget() 279{ 280 static GtkWidget *s_button = NULL; 281 282 if ( !s_button ) 283 { 284 // Get the dummy tree widget, give it a column, and then use the 285 // widget in the column header for the rendering code. 286 GtkWidget* treewidget = GetTreeWidget(); 287 GtkTreeViewColumn* column = gtk_tree_view_column_new(); 288 gtk_tree_view_append_column(GTK_TREE_VIEW(treewidget), column); 289 s_button = column->button; 290 } 291 292 return s_button; 293} 294 295// ---------------------------------------------------------------------------- 296// list/tree controls drawing 297// ---------------------------------------------------------------------------- 298 299int 300wxRendererGTK::DrawHeaderButton(wxWindow *win, 301 wxDC& dc, 302 const wxRect& rect, 303 int flags, 304 wxHeaderSortIconType sortArrow, 305 wxHeaderButtonParams* params) 306{ 307 308 GtkWidget *button = GetHeaderButtonWidget(); 309 310 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 311 312 int x_diff = 0; 313 if (win->GetLayoutDirection() == wxLayout_RightToLeft) 314 x_diff = rect.width; 315 316 gtk_paint_box 317 ( 318 button->style, 319 gdk_window, 320 flags & wxCONTROL_DISABLED ? GTK_STATE_INSENSITIVE : GTK_STATE_NORMAL, 321 GTK_SHADOW_OUT, 322 NULL, 323 button, 324 "button", 325 dc.LogicalToDeviceX(rect.x) - x_diff, rect.y, rect.width, rect.height 326 ); 327 328 return DrawHeaderButtonContents(win, dc, rect, flags, sortArrow, params); 329} 330 331// draw a ">" or "v" button 332void 333wxRendererGTK::DrawTreeItemButton(wxWindow* win, 334 wxDC& dc, const wxRect& rect, int flags) 335{ 336 GtkWidget *tree = GetTreeWidget(); 337 338 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 339 340 GtkStateType state; 341 if ( flags & wxCONTROL_CURRENT ) 342 state = GTK_STATE_PRELIGHT; 343 else 344 state = GTK_STATE_NORMAL; 345 346 int x_diff = 0; 347 if (win->GetLayoutDirection() == wxLayout_RightToLeft) 348 x_diff = rect.width; 349 350 // VZ: I don't know how to get the size of the expander so as to centre it 351 // in the given rectangle, +2/3 below is just what looks good here... 352 gtk_paint_expander 353 ( 354 tree->style, 355 gdk_window, 356 state, 357 NULL, 358 tree, 359 "treeview", 360 dc.LogicalToDeviceX(rect.x) + 6 - x_diff, 361 dc.LogicalToDeviceY(rect.y) + 3, 362 flags & wxCONTROL_EXPANDED ? GTK_EXPANDER_EXPANDED 363 : GTK_EXPANDER_COLLAPSED 364 ); 365} 366 367 368// ---------------------------------------------------------------------------- 369// splitter sash drawing 370// ---------------------------------------------------------------------------- 371 372static int GetGtkSplitterFullSize() 373{ 374 static GtkWidget *s_paned = NULL; 375 if (s_paned == NULL) 376 s_paned = gtk_vpaned_new(); 377 378 gint handle_size; 379 gtk_widget_style_get (s_paned, "handle_size", &handle_size, NULL); 380 381 return handle_size; 382} 383 384wxSplitterRenderParams 385wxRendererGTK::GetSplitterParams(const wxWindow *WXUNUSED(win)) 386{ 387 // we don't draw any border, hence 0 for the second field 388 return wxSplitterRenderParams 389 ( 390 GetGtkSplitterFullSize(), 391 0, 392 true // hot sensitive 393 ); 394} 395 396void 397wxRendererGTK::DrawSplitterBorder(wxWindow * WXUNUSED(win), 398 wxDC& WXUNUSED(dc), 399 const wxRect& WXUNUSED(rect), 400 int WXUNUSED(flags)) 401{ 402 // nothing to do 403} 404 405void 406wxRendererGTK::DrawSplitterSash(wxWindow *win, 407 wxDC& dc, 408 const wxSize& size, 409 wxCoord position, 410 wxOrientation orient, 411 int flags) 412{ 413 if ( !win->m_wxwindow->window ) 414 { 415 // window not realized yet 416 return; 417 } 418 419 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 420 421 wxCoord full_size = GetGtkSplitterFullSize(); 422 423 // are we drawing vertical or horizontal splitter? 424 const bool isVert = orient == wxVERTICAL; 425 426 GdkRectangle rect; 427 428 if ( isVert ) 429 { 430 int h = win->GetClientSize().GetHeight(); 431 432 rect.x = position; 433 rect.y = 0; 434 rect.width = full_size; 435 rect.height = h; 436 } 437 else // horz 438 { 439 int w = win->GetClientSize().GetWidth(); 440 441 rect.x = 0; 442 rect.y = position; 443 rect.height = full_size; 444 rect.width = w; 445 } 446 447 int x_diff = 0; 448 if (win->GetLayoutDirection() == wxLayout_RightToLeft) 449 x_diff = rect.width; 450 451 gtk_paint_handle 452 ( 453 win->m_wxwindow->style, 454 gdk_window, 455 flags & wxCONTROL_CURRENT ? GTK_STATE_PRELIGHT : GTK_STATE_NORMAL, 456 GTK_SHADOW_NONE, 457 NULL /* no clipping */, 458 win->m_wxwindow, 459 "paned", 460 dc.LogicalToDeviceX(rect.x) - x_diff, 461 dc.LogicalToDeviceY(rect.y), 462 rect.width, 463 rect.height, 464 isVert ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL 465 ); 466} 467 468void 469wxRendererGTK::DrawDropArrow(wxWindow *win, 470 wxDC& dc, 471 const wxRect& rect, 472 int flags) 473{ 474 GtkWidget *button = GetButtonWidget(); 475 476 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 477 478 // draw arrow so that there is even space horizontally 479 // on both sides 480 int arrowX = rect.width/4 + 1; 481 int arrowWidth = rect.width - (arrowX*2); 482 483 // scale arrow's height accoording to the width 484 int arrowHeight = rect.width/3; 485 int arrowY = (rect.height-arrowHeight)/2 + 486 ((rect.height-arrowHeight) & 1); 487 488 GtkStateType state; 489 490 if ( flags & wxCONTROL_PRESSED ) 491 state = GTK_STATE_ACTIVE; 492 else if ( flags & wxCONTROL_DISABLED ) 493 state = GTK_STATE_INSENSITIVE; 494 else if ( flags & wxCONTROL_CURRENT ) 495 state = GTK_STATE_PRELIGHT; 496 else 497 state = GTK_STATE_NORMAL; 498 499 // draw arrow on button 500 gtk_paint_arrow 501 ( 502 button->style, 503 gdk_window, 504 state, 505 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT, 506 NULL, 507 button, 508 "arrow", 509 GTK_ARROW_DOWN, 510 FALSE, 511 rect.x + arrowX, 512 rect.y + arrowY, 513 arrowWidth, 514 arrowHeight 515 ); 516} 517 518void 519wxRendererGTK::DrawComboBoxDropButton(wxWindow *win, 520 wxDC& dc, 521 const wxRect& rect, 522 int flags) 523{ 524 DrawPushButton(win,dc,rect,flags); 525 DrawDropArrow(win,dc,rect); 526} 527 528void 529wxRendererGTK::DrawCheckBox(wxWindow *win, 530 wxDC& dc, 531 const wxRect& rect, 532 int flags ) 533{ 534 GtkWidget *button = GetCheckButtonWidget(); 535 536 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 537 538 GtkStateType state; 539 540 if ( flags & wxCONTROL_PRESSED ) 541 state = GTK_STATE_ACTIVE; 542 else if ( flags & wxCONTROL_DISABLED ) 543 state = GTK_STATE_INSENSITIVE; 544 else if ( flags & wxCONTROL_CURRENT ) 545 state = GTK_STATE_PRELIGHT; 546 else 547 state = GTK_STATE_NORMAL; 548 549 gtk_paint_check 550 ( 551 button->style, 552 gdk_window, 553 state, 554 flags & wxCONTROL_CHECKED ? GTK_SHADOW_IN : GTK_SHADOW_OUT, 555 NULL, 556 button, 557 "cellcheck", 558 dc.LogicalToDeviceX(rect.x)+2, 559 dc.LogicalToDeviceY(rect.y)+3, 560 13, 13 561 ); 562} 563 564void 565wxRendererGTK::DrawPushButton(wxWindow* win, 566 wxDC& dc, 567 const wxRect& rect, 568 int flags) 569{ 570 GtkWidget *button = GetButtonWidget(); 571 572 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 573 574 // draw button 575 GtkStateType state; 576 577 if ( flags & wxCONTROL_PRESSED ) 578 state = GTK_STATE_ACTIVE; 579 else if ( flags & wxCONTROL_DISABLED ) 580 state = GTK_STATE_INSENSITIVE; 581 else if ( flags & wxCONTROL_CURRENT ) 582 state = GTK_STATE_PRELIGHT; 583 else 584 state = GTK_STATE_NORMAL; 585 586 gtk_paint_box 587 ( 588 button->style, 589 gdk_window, 590 state, 591 flags & wxCONTROL_PRESSED ? GTK_SHADOW_IN : GTK_SHADOW_OUT, 592 NULL, 593 button, 594 "button", 595 dc.LogicalToDeviceX(rect.x), 596 dc.LogicalToDeviceY(rect.y), 597 rect.width, 598 rect.height 599 ); 600} 601 602void 603wxRendererGTK::DrawItemSelectionRect(wxWindow *win, 604 wxDC& dc, 605 const wxRect& rect, 606 int flags ) 607{ 608 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 609 610 int x_diff = 0; 611 if (win->GetLayoutDirection() == wxLayout_RightToLeft) 612 x_diff = rect.width; 613 614 GtkStateType state; 615 if (flags & wxCONTROL_SELECTED) 616 { 617 // the wxCONTROL_FOCUSED state is deduced 618 // directly from the m_wxwindow by GTK+ 619 state = GTK_STATE_SELECTED; 620 621 gtk_paint_flat_box( win->m_widget->style, 622 gdk_window, 623 state, 624 GTK_SHADOW_NONE, 625 NULL, 626 win->m_wxwindow, 627 "cell_even", 628 dc.LogicalToDeviceX(rect.x) - x_diff, 629 dc.LogicalToDeviceY(rect.y), 630 rect.width, 631 rect.height ); 632 } 633 634 if (flags & wxCONTROL_CURRENT) 635 { 636 gtk_paint_focus( win->m_widget->style, 637 gdk_window, 638 GTK_STATE_SELECTED, 639 NULL, 640 win->m_wxwindow, 641 // Detail "treeview" causes warning with GTK+ 2.12 Clearlooks theme: 642 // "... no property named `row-ending-details'" 643 // Using "treeview-middle" would fix the warning, but the right 644 // edge of the focus rect is not getting erased properly either. 645 // Better to not specify this detail unless the drawing is fixed. 646 NULL, 647 dc.LogicalToDeviceX(rect.x), 648 dc.LogicalToDeviceY(rect.y), 649 rect.width, 650 rect.height ); 651 } 652} 653 654 655// ---------------------------------------------------------------------------- 656// Other renderer functions to be merged in to wxRenderer class in 2.9, but 657// they are standalone functions here to protect the ABI. 658// ---------------------------------------------------------------------------- 659 660// Uses the theme to draw the border and fill for something like a wxTextCtrl 661void wxRenderer_DrawTextCtrl(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) 662{ 663 GtkWidget *entry = wxRendererGTK::GetTextEntryWidget(); 664 665 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 666 667 GtkStateType state = GTK_STATE_NORMAL; 668 if ( flags & wxCONTROL_DISABLED ) 669 state = GTK_STATE_INSENSITIVE; 670 671 if (flags & wxCONTROL_CURRENT ) 672 GTK_WIDGET_SET_FLAGS( entry, GTK_HAS_FOCUS ); 673 else 674 GTK_WIDGET_UNSET_FLAGS( entry, GTK_HAS_FOCUS ); 675 676 gtk_paint_shadow 677 ( 678 entry->style, 679 gdk_window, 680 state, 681 GTK_SHADOW_OUT, 682 NULL, 683 entry, 684 "entry", 685 dc.LogicalToDeviceX(rect.x), 686 dc.LogicalToDeviceY(rect.y), 687 rect.width, 688 rect.height 689 ); 690} 691 692// Draw the equivallent of a wxComboBox 693void wxRenderer_DrawComboBox(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) 694{ 695 if (gtk_check_version(2,4,0)) 696 return; 697 698 GtkWidget *combo = wxRendererGTK::GetComboBoxWidget(); 699 700 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 701 702 GtkStateType state = GTK_STATE_NORMAL; 703 if ( flags & wxCONTROL_DISABLED ) 704 state = GTK_STATE_INSENSITIVE; 705 706 if (flags & wxCONTROL_CURRENT ) 707 GTK_WIDGET_SET_FLAGS( combo, GTK_HAS_FOCUS ); 708 else 709 GTK_WIDGET_UNSET_FLAGS( combo, GTK_HAS_FOCUS ); 710 711 gtk_paint_shadow 712 ( 713 combo->style, 714 gdk_window, 715 state, 716 GTK_SHADOW_OUT, 717 NULL, 718 combo, 719 "combobox", 720 dc.LogicalToDeviceX(rect.x), 721 dc.LogicalToDeviceY(rect.y), 722 rect.width, 723 rect.height 724 ); 725 726 wxRect r = rect; 727 int extent = rect.height / 2; 728 r.x += rect.width - extent - extent/2; 729 r.y += extent/2; 730 r.width = extent; 731 r.height = extent; 732 733 gtk_paint_arrow 734 ( 735 combo->style, 736 gdk_window, 737 state, 738 GTK_SHADOW_OUT, 739 NULL, 740 combo, 741 "arrow", 742 GTK_ARROW_DOWN, 743 TRUE, 744 dc.LogicalToDeviceX(r.x), 745 dc.LogicalToDeviceY(r.y), 746 r.width, 747 r.height 748 ); 749 750 r = rect; 751 r.x += rect.width - 2*extent; 752 r.width = 2; 753 754 gtk_paint_box 755 ( 756 combo->style, 757 gdk_window, 758 state, 759 GTK_SHADOW_ETCHED_OUT, 760 NULL, 761 combo, 762 "vseparator", 763 dc.LogicalToDeviceX(r.x), 764 dc.LogicalToDeviceY(r.y+1), 765 r.width, 766 r.height-2 767 ); 768} 769 770 771void wxRenderer_DrawChoice(wxWindow* win, wxDC& dc, 772 const wxRect& rect, int flags) 773{ 774 wxRenderer_DrawComboBox( win, dc, rect, flags ); 775} 776 777 778// Draw a themed radio button 779void wxRenderer_DrawRadioButton(wxWindow* win, wxDC& dc, const wxRect& rect, int flags) 780{ 781 GtkWidget *button = wxRendererGTK::GetRadioButtonWidget(); 782 783 GdkWindow* gdk_window = wxGetGdkWindowForDC(win, dc); 784 785 GtkShadowType shadow_type = GTK_SHADOW_OUT; 786 if ( flags & wxCONTROL_CHECKED ) 787 shadow_type = GTK_SHADOW_IN; 788 else if ( flags & wxCONTROL_UNDETERMINED ) 789 shadow_type = GTK_SHADOW_ETCHED_IN; 790 791 GtkStateType state = GTK_STATE_NORMAL; 792 if ( flags & wxCONTROL_DISABLED ) 793 state = GTK_STATE_INSENSITIVE; 794 if ( flags & wxCONTROL_PRESSED ) 795 state = GTK_STATE_ACTIVE; 796/* 797 Don't know when to set this 798 state_type = GTK_STATE_PRELIGHT; 799*/ 800 801 gtk_paint_option 802 ( 803 button->style, 804 gdk_window, 805 state, 806 shadow_type, 807 NULL, 808 button, 809 "radiobutton", 810 dc.LogicalToDeviceX(rect.x), 811 dc.LogicalToDeviceY(rect.y), 812 rect.width, rect.height 813 ); 814} 815