1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        wx/gtk/tglbtn.cpp 
   3 // Purpose:     Definition of the wxToggleButton class, which implements a 
   4 //              toggle button under wxGTK. 
   5 // Author:      John Norris, minor changes by Axel Schlueter 
   9 // Copyright:   (c) 2000 Johnny C. Norris II 
  10 // License:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 // For compilers that support precompilation, includes "wx.h". 
  14 #include "wx/wxprec.h" 
  16 #include "wx/tglbtn.h" 
  17 #include "wx/button.h" 
  21 #include "wx/gtk/private.h" 
  23 extern void wxapp_install_idle_handler(); 
  25 extern bool      g_blockEventsOnDrag
; 
  26 extern wxCursor   g_globalCursor
; 
  27 extern wxWindowGTK 
*g_delayedFocus
; 
  29 static void gtk_togglebutton_clicked_callback(GtkWidget 
*WXUNUSED(widget
), wxToggleButton 
*cb
) 
  32       wxapp_install_idle_handler(); 
  34    if (!cb
->m_hasVMT 
|| g_blockEventsOnDrag
) 
  37    if (cb
->m_blockEvent
) return; 
  39    // Generate a wx event. 
  40    wxCommandEvent 
event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
, cb
->GetId()); 
  41    event
.SetInt(cb
->GetValue()); 
  42    event
.SetEventObject(cb
); 
  43    cb
->GetEventHandler()->ProcessEvent(event
); 
  46 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
) 
  48 // ------------------------------------------------------------------------ 
  49 // wxToggleBitmapButton 
  50 // ------------------------------------------------------------------------ 
  52 IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton
, wxControl
) 
  54 bool wxToggleBitmapButton::Create(wxWindow 
*parent
, wxWindowID id
, 
  55                             const wxBitmap 
&label
, const wxPoint 
&pos
, 
  56                             const wxSize 
&size
, long style
, 
  57                             const wxValidator
& validator
, 
  61     m_acceptsFocus 
= TRUE
; 
  65     if (!PreCreation(parent
, pos
, size
) || 
  66        !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) 
  68         wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed")); 
  74     // Create the gtk widget. 
  75     m_widget 
= gtk_toggle_button_new(); 
  77     if (style 
& wxNO_BORDER
) 
  78        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
  85     gtk_signal_connect(GTK_OBJECT(m_widget
), "clicked", 
  86                       GTK_SIGNAL_FUNC(gtk_togglebutton_clicked_callback
), 
  89     m_parent
->DoAddChild(this); 
  96 // void SetValue(bool state) 
  97 // Set the value of the toggle button. 
  98 void wxToggleBitmapButton::SetValue(bool state
) 
 100    wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 102    if (state 
== GetValue()) 
 107    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 109    m_blockEvent 
= FALSE
; 
 112 // bool GetValue() const 
 113 // Get the value of the toggle button. 
 114 bool wxToggleBitmapButton::GetValue() const 
 116    wxCHECK_MSG(m_widget 
!= NULL
, FALSE
, wxT("invalid toggle button")); 
 118    return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 121 void wxToggleBitmapButton::SetLabel(const wxBitmap
& label
) 
 123     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 126     InvalidateBestSize(); 
 131 void wxToggleBitmapButton::OnSetBitmap() 
 133     if (!m_bitmap
.Ok()) return; 
 135     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 136     if (m_bitmap
.GetMask()) mask 
= m_bitmap
.GetMask()->GetBitmap(); 
 138     GtkWidget 
*child 
= BUTTON_CHILD(m_widget
); 
 142         GtkWidget 
*pixmap 
= gtk_pixmap_new(m_bitmap
.GetPixmap(), mask
); 
 143         gtk_widget_show(pixmap
); 
 144         gtk_container_add(GTK_CONTAINER(m_widget
), pixmap
); 
 147     {   // subsequent bitmaps 
 148         GtkPixmap 
*g_pixmap 
= GTK_PIXMAP(child
); 
 149         gtk_pixmap_set(g_pixmap
, m_bitmap
.GetPixmap(), mask
); 
 153 bool wxToggleBitmapButton::Enable(bool enable 
/*=TRUE*/) 
 155     if (!wxControl::Enable(enable
)) 
 158     gtk_widget_set_sensitive(BUTTON_CHILD(m_widget
), enable
); 
 163 void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 165     gtk_widget_modify_style(m_widget
, style
); 
 166     gtk_widget_modify_style(BUTTON_CHILD(m_widget
), style
); 
 169 bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 171     return window 
== TOGGLE_BUTTON_EVENT_WIN(m_widget
); 
 174 void wxToggleBitmapButton::OnInternalIdle() 
 176     wxCursor cursor 
= m_cursor
; 
 178     if (g_globalCursor
.Ok()) 
 179         cursor 
= g_globalCursor
; 
 181     GdkWindow 
*win 
= TOGGLE_BUTTON_EVENT_WIN(m_widget
); 
 182     if ( win 
&& cursor
.Ok() ) 
 184       /* I now set the cursor the anew in every OnInternalIdle call 
 185          as setting the cursor in a parent window also effects the 
 186          windows above so that checking for the current cursor is 
 189         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 192     if (wxUpdateUIEvent::CanUpdate(this)) 
 193         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 197 // Get the "best" size for this control. 
 198 wxSize 
wxToggleBitmapButton::DoGetBestSize() const 
 204         int border 
= HasFlag(wxNO_BORDER
) ? 4 : 10; 
 205         best
.x 
= m_bitmap
.GetWidth()+border
; 
 206         best
.y 
= m_bitmap
.GetHeight()+border
; 
 215 wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 217     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 221 // ------------------------------------------------------------------------ 
 223 // ------------------------------------------------------------------------ 
 225 IMPLEMENT_DYNAMIC_CLASS(wxToggleButton
, wxControl
) 
 227 bool wxToggleButton::Create(wxWindow 
*parent
, wxWindowID id
, 
 228                             const wxString 
&label
, const wxPoint 
&pos
, 
 229                             const wxSize 
&size
, long style
, 
 230                             const wxValidator
& validator
, 
 231                             const wxString 
&name
) 
 234    m_acceptsFocus 
= TRUE
; 
 236    m_blockEvent 
= FALSE
; 
 238    if (!PreCreation(parent
, pos
, size
) || 
 239        !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) { 
 240       wxFAIL_MSG(wxT("wxToggleButton creation failed")); 
 244    wxControl::SetLabel(label
); 
 246    // Create the gtk widget. 
 247    m_widget 
= gtk_toggle_button_new_with_label( wxGTK_CONV( m_label 
) ); 
 249    gtk_signal_connect(GTK_OBJECT(m_widget
), "clicked", 
 250                       GTK_SIGNAL_FUNC(gtk_togglebutton_clicked_callback
), 
 253    m_parent
->DoAddChild(this); 
 260 // void SetValue(bool state) 
 261 // Set the value of the toggle button. 
 262 void wxToggleButton::SetValue(bool state
) 
 264    wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 266    if (state 
== GetValue()) 
 271    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 273    m_blockEvent 
= FALSE
; 
 276 // bool GetValue() const 
 277 // Get the value of the toggle button. 
 278 bool wxToggleButton::GetValue() const 
 280    wxCHECK_MSG(m_widget 
!= NULL
, FALSE
, wxT("invalid toggle button")); 
 282    return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 285 void wxToggleButton::SetLabel(const wxString
& label
) 
 287     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 289     wxControl::SetLabel(label
); 
 291     gtk_label_set(GTK_LABEL(BUTTON_CHILD(m_widget
)), wxGTK_CONV( GetLabel() ) ); 
 294 bool wxToggleButton::Enable(bool enable 
/*=TRUE*/) 
 296     if (!wxControl::Enable(enable
)) 
 299     gtk_widget_set_sensitive(BUTTON_CHILD(m_widget
), enable
); 
 304 void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 306     gtk_widget_modify_style(m_widget
, style
); 
 307     gtk_widget_modify_style(BUTTON_CHILD(m_widget
), style
); 
 310 bool wxToggleButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 312     return window 
== TOGGLE_BUTTON_EVENT_WIN(m_widget
); 
 315 void wxToggleButton::OnInternalIdle() 
 317     wxCursor cursor 
= m_cursor
; 
 319     if (g_globalCursor
.Ok()) 
 320         cursor 
= g_globalCursor
; 
 322     GdkWindow 
*win 
= TOGGLE_BUTTON_EVENT_WIN(m_widget
); 
 323     if ( win 
&& cursor
.Ok() ) 
 325       /* I now set the cursor the anew in every OnInternalIdle call 
 326          as setting the cursor in a parent window also effects the 
 327          windows above so that checking for the current cursor is 
 330         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 333     if (wxUpdateUIEvent::CanUpdate(this)) 
 334         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 338 // Get the "best" size for this control. 
 339 wxSize 
wxToggleButton::DoGetBestSize() const 
 341     wxSize 
ret(wxControl::DoGetBestSize()); 
 343     if (!HasFlag(wxBU_EXACTFIT
)) 
 345         if (ret
.x 
< 80) ret
.x 
= 80; 
 354 wxToggleButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 356     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 359 #endif // wxUSE_TOGGLEBTN