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 // FIXME: Use GtkImage instead of GtkPixmap. 
  22 #include <gtk/gtkversion.h> 
  23 #ifdef GTK_DISABLE_DEPRECATED 
  24 #undef GTK_DISABLE_DEPRECATED 
  27 #include "wx/gtk/private.h" 
  29 extern bool      g_blockEventsOnDrag
; 
  30 extern wxCursor   g_globalCursor
; 
  33 static void gtk_togglebutton_clicked_callback(GtkWidget 
*WXUNUSED(widget
), wxToggleButton 
*cb
) 
  36         wxapp_install_idle_handler(); 
  38     if (!cb
->m_hasVMT 
|| g_blockEventsOnDrag
) 
  41     if (cb
->m_blockEvent
) return; 
  43     // Generate a wx event. 
  44     wxCommandEvent 
event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
, cb
->GetId()); 
  45     event
.SetInt(cb
->GetValue()); 
  46     event
.SetEventObject(cb
); 
  47     cb
->GetEventHandler()->ProcessEvent(event
); 
  51 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
) 
  53 // ------------------------------------------------------------------------ 
  54 // wxToggleBitmapButton 
  55 // ------------------------------------------------------------------------ 
  57 IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton
, wxControl
) 
  59 bool wxToggleBitmapButton::Create(wxWindow 
*parent
, wxWindowID id
, 
  60                             const wxBitmap 
&label
, const wxPoint 
&pos
, 
  61                             const wxSize 
&size
, long style
, 
  62                             const wxValidator
& validator
, 
  66     m_acceptsFocus 
= true; 
  70     if (!PreCreation(parent
, pos
, size
) || 
  71        !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) 
  73         wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed")); 
  79     // Create the gtk widget. 
  80     m_widget 
= gtk_toggle_button_new(); 
  82     if (style 
& wxNO_BORDER
) 
  83        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
  90     g_signal_connect (m_widget
, "clicked", 
  91                       G_CALLBACK (gtk_togglebutton_clicked_callback
), 
  94     m_parent
->DoAddChild(this); 
 101 // void SetValue(bool state) 
 102 // Set the value of the toggle button. 
 103 void wxToggleBitmapButton::SetValue(bool state
) 
 105     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 107     if (state 
== GetValue()) 
 112     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 114     m_blockEvent 
= false; 
 117 // bool GetValue() const 
 118 // Get the value of the toggle button. 
 119 bool wxToggleBitmapButton::GetValue() const 
 121     wxCHECK_MSG(m_widget 
!= NULL
, false, wxT("invalid toggle button")); 
 123     return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 126 void wxToggleBitmapButton::SetLabel(const wxBitmap
& label
) 
 128     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 131     InvalidateBestSize(); 
 136 void wxToggleBitmapButton::OnSetBitmap() 
 138     if (!m_bitmap
.Ok()) return; 
 140     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 141     if (m_bitmap
.GetMask()) mask 
= m_bitmap
.GetMask()->GetBitmap(); 
 143     GtkWidget 
*child 
= GTK_BIN(m_widget
)->child
; 
 147         GtkWidget 
*pixmap 
= gtk_pixmap_new(m_bitmap
.GetPixmap(), mask
); 
 148         gtk_widget_show(pixmap
); 
 149         gtk_container_add(GTK_CONTAINER(m_widget
), pixmap
); 
 152     {   // subsequent bitmaps 
 153         GtkPixmap 
*g_pixmap 
= GTK_PIXMAP(child
); 
 154         gtk_pixmap_set(g_pixmap
, m_bitmap
.GetPixmap(), mask
); 
 158 bool wxToggleBitmapButton::Enable(bool enable 
/*=true*/) 
 160     if (!wxControl::Enable(enable
)) 
 163     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 168 void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 170     gtk_widget_modify_style(m_widget
, style
); 
 171     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 174 bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 176     return window 
== GTK_BUTTON(m_widget
)->event_window
; 
 179 void wxToggleBitmapButton::OnInternalIdle() 
 181     wxCursor cursor 
= m_cursor
; 
 183     if (g_globalCursor
.Ok()) 
 184         cursor 
= g_globalCursor
; 
 186     GdkWindow 
*win 
= GTK_BUTTON(m_widget
)->event_window
; 
 187     if ( win 
&& cursor
.Ok() ) 
 189       /* I now set the cursor the anew in every OnInternalIdle call 
 190          as setting the cursor in a parent window also effects the 
 191          windows above so that checking for the current cursor is 
 194         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 197     if (wxUpdateUIEvent::CanUpdate(this)) 
 198         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 202 // Get the "best" size for this control. 
 203 wxSize 
wxToggleBitmapButton::DoGetBestSize() const 
 209         int border 
= HasFlag(wxNO_BORDER
) ? 4 : 10; 
 210         best
.x 
= m_bitmap
.GetWidth()+border
; 
 211         best
.y 
= m_bitmap
.GetHeight()+border
; 
 220 wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 222     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 226 // ------------------------------------------------------------------------ 
 228 // ------------------------------------------------------------------------ 
 230 IMPLEMENT_DYNAMIC_CLASS(wxToggleButton
, wxControl
) 
 232 bool wxToggleButton::Create(wxWindow 
*parent
, wxWindowID id
, 
 233                             const wxString 
&label
, const wxPoint 
&pos
, 
 234                             const wxSize 
&size
, long style
, 
 235                             const wxValidator
& validator
, 
 236                             const wxString 
&name
) 
 239     m_acceptsFocus 
= true; 
 241     m_blockEvent 
= false; 
 243     if (!PreCreation(parent
, pos
, size
) || 
 244         !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) { 
 245         wxFAIL_MSG(wxT("wxToggleButton creation failed")); 
 249     wxControl::SetLabel(label
); 
 251     // Create the gtk widget. 
 252     m_widget 
= gtk_toggle_button_new_with_label( wxGTK_CONV( m_label 
) ); 
 254     g_signal_connect (m_widget
, "clicked", 
 255                       G_CALLBACK (gtk_togglebutton_clicked_callback
), 
 258     m_parent
->DoAddChild(this); 
 265 // void SetValue(bool state) 
 266 // Set the value of the toggle button. 
 267 void wxToggleButton::SetValue(bool state
) 
 269     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 271     if (state 
== GetValue()) 
 276     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 278     m_blockEvent 
= false; 
 281 // bool GetValue() const 
 282 // Get the value of the toggle button. 
 283 bool wxToggleButton::GetValue() const 
 285     wxCHECK_MSG(m_widget 
!= NULL
, false, wxT("invalid toggle button")); 
 287     return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 290 void wxToggleButton::SetLabel(const wxString
& label
) 
 292     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 294     wxControl::SetLabel(label
); 
 296     gtk_label_set_text(GTK_LABEL(GTK_BIN(m_widget
)->child
), wxGTK_CONV(GetLabel())); 
 299 bool wxToggleButton::Enable(bool enable 
/*=true*/) 
 301     if (!wxControl::Enable(enable
)) 
 304     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 309 void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 311     gtk_widget_modify_style(m_widget
, style
); 
 312     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 315 bool wxToggleButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 317     return window 
== GTK_BUTTON(m_widget
)->event_window
; 
 320 void wxToggleButton::OnInternalIdle() 
 322     wxCursor cursor 
= m_cursor
; 
 324     if (g_globalCursor
.Ok()) 
 325         cursor 
= g_globalCursor
; 
 327     GdkWindow 
*win 
= GTK_BUTTON(m_widget
)->event_window
; 
 328     if ( win 
&& cursor
.Ok() ) 
 330       /* I now set the cursor the anew in every OnInternalIdle call 
 331          as setting the cursor in a parent window also effects the 
 332          windows above so that checking for the current cursor is 
 335         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 338     if (wxUpdateUIEvent::CanUpdate(this)) 
 339         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 343 // Get the "best" size for this control. 
 344 wxSize 
wxToggleButton::DoGetBestSize() const 
 346     wxSize 
ret(wxControl::DoGetBestSize()); 
 348     if (!HasFlag(wxBU_EXACTFIT
)) 
 350         if (ret
.x 
< 80) ret
.x 
= 80; 
 359 wxToggleButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 361     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 364 #endif // wxUSE_TOGGLEBTN