1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  11 #pragma implementation "button.h" 
  14 // For compilers that support precompilation, includes "wx.h". 
  15 #include "wx/wxprec.h" 
  21 #include "wx/button.h" 
  22 #include "wx/stockitem.h" 
  24 #include "wx/gtk/private.h" 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  34 //----------------------------------------------------------------------------- 
  36 extern void wxapp_install_idle_handler(); 
  39 //----------------------------------------------------------------------------- 
  41 //----------------------------------------------------------------------------- 
  43 extern bool   g_blockEventsOnDrag
; 
  45 //----------------------------------------------------------------------------- 
  47 //----------------------------------------------------------------------------- 
  49 static void gtk_button_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxButton 
*button 
) 
  52        wxapp_install_idle_handler(); 
  54     if (!button
->m_hasVMT
) return; 
  55     if (g_blockEventsOnDrag
) return; 
  57     wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, button
->GetId()); 
  58     event
.SetEventObject(button
); 
  59     button
->GetEventHandler()->ProcessEvent(event
); 
  62 //----------------------------------------------------------------------------- 
  63 // "style_set" from m_widget 
  64 //----------------------------------------------------------------------------- 
  67 gtk_button_style_set_callback( GtkWidget 
*m_widget
, GtkStyle 
*WXUNUSED(style
), wxButton 
*win 
) 
  70         wxapp_install_idle_handler(); 
  72     if (GTK_WIDGET_REALIZED(m_widget
)) 
  73         win
->SetSize( win
->m_x
, win
->m_y
, win
->m_width
, win
->m_height 
); 
  78 //----------------------------------------------------------------------------- 
  80 //----------------------------------------------------------------------------- 
  82 IMPLEMENT_DYNAMIC_CLASS(wxButton
,wxControl
) 
  92 bool wxButton::Create(  wxWindow 
*parent
, wxWindowID id
, const wxString 
&label
, 
  93       const wxPoint 
&pos
, const wxSize 
&size
, 
  94       long style
, const wxValidator
& validator
, const wxString 
&name 
) 
  97     m_acceptsFocus 
= TRUE
; 
  99     if (!PreCreation( parent
, pos
, size 
) || 
 100         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 102         wxFAIL_MSG( wxT("wxButton creation failed") ); 
 107     wxString label2( label ); 
 108     for (size_t i = 0; i < label2.Len(); i++) 
 110         if (label2.GetChar(i) == wxT('&')) 
 111         label2.SetChar(i,wxT('_')); 
 114     GtkWidget *accel_label = gtk_accel_label_new( label2.mb_str() ); 
 115     gtk_widget_show( accel_label ); 
 117     m_widget = gtk_button_new(); 
 118     gtk_container_add( GTK_CONTAINER(m_widget), accel_label ); 
 120     gtk_accel_label_set_accel_widget( GTK_ACCEL_LABEL(accel_label), m_widget ); 
 122     guint accel_key = gtk_label_parse_uline (GTK_LABEL(accel_label), label2.mb_str() ); 
 123     gtk_accel_label_refetch( GTK_ACCEL_LABEL(accel_label) ); 
 125     wxControl::SetLabel( label ); 
 129     m_widget 
= gtk_button_new_with_mnemonic(""); 
 131     m_widget 
= gtk_button_new_with_label(""); 
 134     float x_alignment 
= 0.5; 
 135     if (HasFlag(wxBU_LEFT
)) 
 137     else if (HasFlag(wxBU_RIGHT
)) 
 140     float y_alignment 
= 0.5; 
 141     if (HasFlag(wxBU_TOP
)) 
 143     else if (HasFlag(wxBU_BOTTOM
)) 
 147     if (!gtk_check_version(2,4,0)) 
 149         gtk_button_set_alignment(GTK_BUTTON(m_widget
), x_alignment
, y_alignment
); 
 154         if (GTK_IS_MISC(BUTTON_CHILD(m_widget
))) 
 155             gtk_misc_set_alignment (GTK_MISC (BUTTON_CHILD (m_widget
)), 
 156                                 x_alignment
, y_alignment
); 
 161     if (style 
& wxNO_BORDER
) 
 162        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
 164     gtk_signal_connect_after( GTK_OBJECT(m_widget
), "clicked", 
 165       GTK_SIGNAL_FUNC(gtk_button_clicked_callback
), (gpointer
*)this ); 
 167     gtk_signal_connect_after( GTK_OBJECT(m_widget
), "style_set", 
 168       GTK_SIGNAL_FUNC(gtk_button_style_set_callback
), (gpointer
*) this ); 
 170     m_parent
->DoAddChild( this ); 
 178 void wxButton::SetDefault() 
 180     wxWindow 
*parent 
= GetParent(); 
 181     wxCHECK_RET( parent
, _T("button without parent?") ); 
 183     parent
->SetDefaultItem(this); 
 185     GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 186     gtk_widget_grab_default( m_widget 
); 
 188     SetSize( m_x
, m_y
, m_width
, m_height 
); 
 192 wxSize 
wxButtonBase::GetDefaultSize() 
 195     static wxSize size 
= wxDefaultSize
; 
 196     if (size 
== wxDefaultSize
) 
 198         // NB: Default size of buttons should be same as size of stock 
 199         //     buttons as used in most GTK+ apps. Unfortunately it's a little 
 200         //     tricky to obtain this size: stock button's size may be smaller 
 201         //     than size of button in GtkButtonBox and vice versa, 
 202         //     GtkButtonBox's minimal button size may be smaller than stock 
 203         //     button's size. We have to retrieve both values and combine them. 
 205         GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 206         GtkWidget 
*box 
= gtk_hbutton_box_new(); 
 207         GtkWidget 
*btn 
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
); 
 208         gtk_container_add(GTK_CONTAINER(box
), btn
); 
 209         gtk_container_add(GTK_CONTAINER(wnd
), box
); 
 211         gtk_widget_size_request(btn
, &req
); 
 213         gint minwidth
, minheight
; 
 214         gtk_widget_style_get(box
, 
 215                              "child-min-width", &minwidth
, 
 216                              "child-min-height", &minheight
, 
 219         size
.x 
= wxMax(minwidth
, req
.width
); 
 220         size
.y 
= wxMax(minheight
, req
.height
); 
 222         gtk_widget_destroy(wnd
); 
 226     return wxSize(80,26); 
 230 void wxButton::SetLabel( const wxString 
&lbl 
) 
 232     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid button") ); 
 236     if (label
.empty() && wxIsStockID(m_windowId
)) 
 237         label 
= wxGetStockLabel(m_windowId
); 
 239     wxControl::SetLabel(label
); 
 242     if (wxIsStockID(m_windowId
) && wxIsStockLabel(m_windowId
, label
)) 
 244         const char *stock 
= wxGetStockGtkID(m_windowId
); 
 247             gtk_button_set_label(GTK_BUTTON(m_widget
), stock
); 
 248             gtk_button_set_use_stock(GTK_BUTTON(m_widget
), TRUE
); 
 253     wxString label2 
= PrepareLabelMnemonics(label
); 
 254     gtk_button_set_label(GTK_BUTTON(m_widget
), wxGTK_CONV(label2
)); 
 255     gtk_button_set_use_stock(GTK_BUTTON(m_widget
), FALSE
); 
 257     ApplyWidgetStyle( false ); 
 260     gtk_label_set(GTK_LABEL(BUTTON_CHILD(m_widget
)), wxGTK_CONV(GetLabel())); 
 264 bool wxButton::Enable( bool enable 
) 
 266     if ( !wxControl::Enable( enable 
) ) 
 269     gtk_widget_set_sensitive( BUTTON_CHILD(m_widget
), enable 
); 
 274 bool wxButton::IsOwnGtkWindow( GdkWindow 
*window 
) 
 277     return GTK_BUTTON(m_widget
)->event_window
; 
 279     return (window 
== m_widget
->window
); 
 283 void wxButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 285     gtk_widget_modify_style(m_widget
, style
); 
 286     gtk_widget_modify_style(BUTTON_CHILD(m_widget
), style
); 
 289 wxSize 
wxButton::DoGetBestSize() const 
 291     // the default button in wxGTK is bigger than the other ones because of an 
 292     // extra border around it, but we don't want to take it into account in 
 293     // our size calculations (otherwsie the result is visually ugly), so 
 294     // always return the size of non default button from here 
 295     const bool isDefault 
= GTK_WIDGET_HAS_DEFAULT(m_widget
); 
 298         // temporarily unset default flag 
 299         GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 302     wxSize 
ret( wxControl::DoGetBestSize() ); 
 307         GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 311     ret
.x 
+= 10;  // add a few pixels for sloppy (but common) themes 
 314     if (!HasFlag(wxBU_EXACTFIT
)) 
 316         wxSize defaultSize 
= GetDefaultSize(); 
 317         if (ret
.x 
< defaultSize
.x
) ret
.x 
= defaultSize
.x
; 
 318         if (ret
.y 
< defaultSize
.y
) ret
.y 
= defaultSize
.y
; 
 327 wxButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 329     return GetDefaultAttributesFromGTKWidget(gtk_button_new
); 
 332 #endif // wxUSE_BUTTON