1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/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" 
  18 #include "wx/tglbtn.h" 
  21     #include "wx/button.h" 
  24 // FIXME: Use GtkImage instead of GtkPixmap. 
  25 #include <gtk/gtkversion.h> 
  26 #ifdef GTK_DISABLE_DEPRECATED 
  27 #undef GTK_DISABLE_DEPRECATED 
  30 #include "wx/gtk/private.h" 
  32 extern bool      g_blockEventsOnDrag
; 
  33 extern wxCursor   g_globalCursor
; 
  36 static void gtk_togglebutton_clicked_callback(GtkWidget 
*WXUNUSED(widget
), wxToggleButton 
*cb
) 
  39         wxapp_install_idle_handler(); 
  41     if (!cb
->m_hasVMT 
|| g_blockEventsOnDrag
) 
  44     if (cb
->m_blockEvent
) return; 
  46     // Generate a wx event. 
  47     wxCommandEvent 
event(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
, cb
->GetId()); 
  48     event
.SetInt(cb
->GetValue()); 
  49     event
.SetEventObject(cb
); 
  50     cb
->GetEventHandler()->ProcessEvent(event
); 
  54 DEFINE_EVENT_TYPE(wxEVT_COMMAND_TOGGLEBUTTON_CLICKED
) 
  56 // ------------------------------------------------------------------------ 
  57 // wxToggleBitmapButton 
  58 // ------------------------------------------------------------------------ 
  60 IMPLEMENT_DYNAMIC_CLASS(wxToggleBitmapButton
, wxControl
) 
  62 bool wxToggleBitmapButton::Create(wxWindow 
*parent
, wxWindowID id
, 
  63                             const wxBitmap 
&label
, const wxPoint 
&pos
, 
  64                             const wxSize 
&size
, long style
, 
  65                             const wxValidator
& validator
, 
  69     m_acceptsFocus 
= true; 
  73     if (!PreCreation(parent
, pos
, size
) || 
  74        !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) 
  76         wxFAIL_MSG(wxT("wxToggleBitmapButton creation failed")); 
  82     // Create the gtk widget. 
  83     m_widget 
= gtk_toggle_button_new(); 
  85     if (style 
& wxNO_BORDER
) 
  86        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
  93     g_signal_connect (m_widget
, "clicked", 
  94                       G_CALLBACK (gtk_togglebutton_clicked_callback
), 
  97     m_parent
->DoAddChild(this); 
 104 // void SetValue(bool state) 
 105 // Set the value of the toggle button. 
 106 void wxToggleBitmapButton::SetValue(bool state
) 
 108     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 110     if (state 
== GetValue()) 
 115     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 117     m_blockEvent 
= false; 
 120 // bool GetValue() const 
 121 // Get the value of the toggle button. 
 122 bool wxToggleBitmapButton::GetValue() const 
 124     wxCHECK_MSG(m_widget 
!= NULL
, false, wxT("invalid toggle button")); 
 126     return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 129 void wxToggleBitmapButton::SetLabel(const wxBitmap
& label
) 
 131     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 134     InvalidateBestSize(); 
 139 void wxToggleBitmapButton::OnSetBitmap() 
 141     if (!m_bitmap
.Ok()) return; 
 143     GdkBitmap 
*mask 
= (GdkBitmap 
*) NULL
; 
 144     if (m_bitmap
.GetMask()) mask 
= m_bitmap
.GetMask()->GetBitmap(); 
 146     GtkWidget 
*child 
= GTK_BIN(m_widget
)->child
; 
 150         GtkWidget 
*pixmap 
= gtk_pixmap_new(m_bitmap
.GetPixmap(), mask
); 
 151         gtk_widget_show(pixmap
); 
 152         gtk_container_add(GTK_CONTAINER(m_widget
), pixmap
); 
 155     {   // subsequent bitmaps 
 156         GtkPixmap 
*g_pixmap 
= GTK_PIXMAP(child
); 
 157         gtk_pixmap_set(g_pixmap
, m_bitmap
.GetPixmap(), mask
); 
 161 bool wxToggleBitmapButton::Enable(bool enable 
/*=true*/) 
 163     if (!wxControl::Enable(enable
)) 
 166     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 171 void wxToggleBitmapButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 173     gtk_widget_modify_style(m_widget
, style
); 
 174     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 177 bool wxToggleBitmapButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 179     return window 
== GTK_BUTTON(m_widget
)->event_window
; 
 182 void wxToggleBitmapButton::OnInternalIdle() 
 184     // Check if we have to show window now 
 185     if (GtkShowFromOnIdle()) return; 
 187     wxCursor cursor 
= m_cursor
; 
 189     if (g_globalCursor
.Ok()) 
 190         cursor 
= g_globalCursor
; 
 192     GdkWindow 
*win 
= GTK_BUTTON(m_widget
)->event_window
; 
 193     if ( win 
&& cursor
.Ok() ) 
 195       /* I now set the cursor the anew in every OnInternalIdle call 
 196          as setting the cursor in a parent window also effects the 
 197          windows above so that checking for the current cursor is 
 200         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 203     if (wxUpdateUIEvent::CanUpdate(this)) 
 204         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 208 // Get the "best" size for this control. 
 209 wxSize 
wxToggleBitmapButton::DoGetBestSize() const 
 215         int border 
= HasFlag(wxNO_BORDER
) ? 4 : 10; 
 216         best
.x 
= m_bitmap
.GetWidth()+border
; 
 217         best
.y 
= m_bitmap
.GetHeight()+border
; 
 226 wxToggleBitmapButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 228     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 232 // ------------------------------------------------------------------------ 
 234 // ------------------------------------------------------------------------ 
 236 IMPLEMENT_DYNAMIC_CLASS(wxToggleButton
, wxControl
) 
 238 bool wxToggleButton::Create(wxWindow 
*parent
, wxWindowID id
, 
 239                             const wxString 
&label
, const wxPoint 
&pos
, 
 240                             const wxSize 
&size
, long style
, 
 241                             const wxValidator
& validator
, 
 242                             const wxString 
&name
) 
 245     m_acceptsFocus 
= true; 
 247     m_blockEvent 
= false; 
 249     if (!PreCreation(parent
, pos
, size
) || 
 250         !CreateBase(parent
, id
, pos
, size
, style
, validator
, name 
)) { 
 251         wxFAIL_MSG(wxT("wxToggleButton creation failed")); 
 255     wxControl::SetLabel(label
); 
 257     // Create the gtk widget. 
 258     m_widget 
= gtk_toggle_button_new_with_label( wxGTK_CONV( m_label 
) ); 
 260     g_signal_connect (m_widget
, "clicked", 
 261                       G_CALLBACK (gtk_togglebutton_clicked_callback
), 
 264     m_parent
->DoAddChild(this); 
 271 // void SetValue(bool state) 
 272 // Set the value of the toggle button. 
 273 void wxToggleButton::SetValue(bool state
) 
 275     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 277     if (state 
== GetValue()) 
 282     gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_widget
), state
); 
 284     m_blockEvent 
= false; 
 287 // bool GetValue() const 
 288 // Get the value of the toggle button. 
 289 bool wxToggleButton::GetValue() const 
 291     wxCHECK_MSG(m_widget 
!= NULL
, false, wxT("invalid toggle button")); 
 293     return GTK_TOGGLE_BUTTON(m_widget
)->active
; 
 296 void wxToggleButton::SetLabel(const wxString
& label
) 
 298     wxCHECK_RET(m_widget 
!= NULL
, wxT("invalid toggle button")); 
 300     wxControl::SetLabel(label
); 
 302     gtk_label_set_text(GTK_LABEL(GTK_BIN(m_widget
)->child
), wxGTK_CONV(GetLabel())); 
 305 bool wxToggleButton::Enable(bool enable 
/*=true*/) 
 307     if (!wxControl::Enable(enable
)) 
 310     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 315 void wxToggleButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 317     gtk_widget_modify_style(m_widget
, style
); 
 318     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 321 bool wxToggleButton::IsOwnGtkWindow(GdkWindow 
*window
) 
 323     return window 
== GTK_BUTTON(m_widget
)->event_window
; 
 326 void wxToggleButton::OnInternalIdle() 
 328     wxCursor cursor 
= m_cursor
; 
 330     if (g_globalCursor
.Ok()) 
 331         cursor 
= g_globalCursor
; 
 333     GdkWindow 
*win 
= GTK_BUTTON(m_widget
)->event_window
; 
 334     if ( win 
&& cursor
.Ok() ) 
 336       /* I now set the cursor the anew in every OnInternalIdle call 
 337          as setting the cursor in a parent window also effects the 
 338          windows above so that checking for the current cursor is 
 341         gdk_window_set_cursor(win
, cursor
.GetCursor()); 
 344     if (wxUpdateUIEvent::CanUpdate(this)) 
 345         UpdateWindowUI(wxUPDATE_UI_FROMIDLE
); 
 349 // Get the "best" size for this control. 
 350 wxSize 
wxToggleButton::DoGetBestSize() const 
 352     wxSize 
ret(wxControl::DoGetBestSize()); 
 354     if (!HasFlag(wxBU_EXACTFIT
)) 
 356         if (ret
.x 
< 80) ret
.x 
= 80; 
 365 wxToggleButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 367     return GetDefaultAttributesFromGTKWidget(gtk_toggle_button_new
); 
 370 #endif // wxUSE_TOGGLEBTN