1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  17 #include "wx/button.h" 
  18 #include "wx/stockitem.h" 
  20 #include "wx/gtk/private.h" 
  21 #include "wx/gtk/win_gtk.h" 
  23 //----------------------------------------------------------------------------- 
  25 //----------------------------------------------------------------------------- 
  29 //----------------------------------------------------------------------------- 
  31 //----------------------------------------------------------------------------- 
  33 extern bool   g_blockEventsOnDrag
; 
  35 //----------------------------------------------------------------------------- 
  37 //----------------------------------------------------------------------------- 
  40 static void gtk_button_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxButton 
*button 
) 
  43        wxapp_install_idle_handler(); 
  45     if (!button
->m_hasVMT
) return; 
  46     if (g_blockEventsOnDrag
) return; 
  48     wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, button
->GetId()); 
  49     event
.SetEventObject(button
); 
  50     button
->GetEventHandler()->ProcessEvent(event
); 
  54 //----------------------------------------------------------------------------- 
  55 // "style_set" from m_widget 
  56 //----------------------------------------------------------------------------- 
  59 gtk_button_style_set_callback( GtkWidget 
*m_widget
, GtkStyle 
*WXUNUSED(style
), wxButton 
*win 
) 
  62         wxapp_install_idle_handler(); 
  67     int bottom_border 
= 0; 
  69     /* the default button has a border around it */ 
  70     if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
  72         GtkBorder 
*default_border 
= NULL
; 
  73         gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
  76             left_border 
+= default_border
->left
; 
  77             right_border 
+= default_border
->right
; 
  78             top_border 
+= default_border
->top
; 
  79             bottom_border 
+= default_border
->bottom
; 
  80             g_free( default_border 
); 
  83             win
->m_x 
- top_border
, 
  84             win
->m_y 
- left_border
, 
  85             win
->m_width 
+ left_border 
+ right_border
, 
  86             win
->m_height 
+ top_border 
+ bottom_border
); 
  92 //----------------------------------------------------------------------------- 
  94 //----------------------------------------------------------------------------- 
  96 IMPLEMENT_DYNAMIC_CLASS(wxButton
,wxControl
) 
 102 wxButton::~wxButton() 
 106 bool wxButton::Create(  wxWindow 
*parent
, wxWindowID id
, const wxString 
&label
, 
 107       const wxPoint 
&pos
, const wxSize 
&size
, 
 108       long style
, const wxValidator
& validator
, const wxString 
&name 
) 
 111     m_acceptsFocus 
= TRUE
; 
 113     if (!PreCreation( parent
, pos
, size 
) || 
 114         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 116         wxFAIL_MSG( wxT("wxButton creation failed") ); 
 120     m_widget 
= gtk_button_new_with_mnemonic(""); 
 122     float x_alignment 
= 0.5; 
 123     if (HasFlag(wxBU_LEFT
)) 
 125     else if (HasFlag(wxBU_RIGHT
)) 
 128     float y_alignment 
= 0.5; 
 129     if (HasFlag(wxBU_TOP
)) 
 131     else if (HasFlag(wxBU_BOTTOM
)) 
 135     if (!gtk_check_version(2,4,0)) 
 137         gtk_button_set_alignment(GTK_BUTTON(m_widget
), x_alignment
, y_alignment
); 
 142         if (GTK_IS_MISC(GTK_BIN(m_widget
)->child
)) 
 143             gtk_misc_set_alignment(GTK_MISC(GTK_BIN(m_widget
)->child
), 
 144                                 x_alignment
, y_alignment
); 
 149     if (style 
& wxNO_BORDER
) 
 150        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
 152     g_signal_connect_after (m_widget
, "clicked", 
 153                             G_CALLBACK (gtk_button_clicked_callback
), 
 156     g_signal_connect_after (m_widget
, "style_set", 
 157                             G_CALLBACK (gtk_button_style_set_callback
), 
 160     m_parent
->DoAddChild( this ); 
 168 void wxButton::SetDefault() 
 170     wxWindow 
*parent 
= GetParent(); 
 171     wxCHECK_RET( parent
, _T("button without parent?") ); 
 173     parent
->SetDefaultItem(this); 
 175     GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 176     gtk_widget_grab_default( m_widget 
); 
 178     // resize for default border 
 179     gtk_button_style_set_callback( m_widget
, NULL
, this ); 
 183 wxSize 
wxButtonBase::GetDefaultSize() 
 185     static wxSize size 
= wxDefaultSize
; 
 186     if (size 
== wxDefaultSize
) 
 188         // NB: Default size of buttons should be same as size of stock 
 189         //     buttons as used in most GTK+ apps. Unfortunately it's a little 
 190         //     tricky to obtain this size: stock button's size may be smaller 
 191         //     than size of button in GtkButtonBox and vice versa, 
 192         //     GtkButtonBox's minimal button size may be smaller than stock 
 193         //     button's size. We have to retrieve both values and combine them. 
 195         GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 196         GtkWidget 
*box 
= gtk_hbutton_box_new(); 
 197         GtkWidget 
*btn 
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
); 
 198         gtk_container_add(GTK_CONTAINER(box
), btn
); 
 199         gtk_container_add(GTK_CONTAINER(wnd
), box
); 
 201         gtk_widget_size_request(btn
, &req
); 
 203         gint minwidth
, minheight
; 
 204         gtk_widget_style_get(box
, 
 205                              "child-min-width", &minwidth
, 
 206                              "child-min-height", &minheight
, 
 209         size
.x 
= wxMax(minwidth
, req
.width
); 
 210         size
.y 
= wxMax(minheight
, req
.height
); 
 212         gtk_widget_destroy(wnd
); 
 217 void wxButton::SetLabel( const wxString 
&lbl 
) 
 219     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid button") ); 
 223     if (label
.empty() && wxIsStockID(m_windowId
)) 
 224         label 
= wxGetStockLabel(m_windowId
); 
 226     wxControl::SetLabel(label
); 
 228     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 230     if (wxIsStockID(m_windowId
) && wxIsStockLabel(m_windowId
, label
)) 
 232         const char *stock 
= wxGetStockGtkID(m_windowId
); 
 235             gtk_button_set_label(GTK_BUTTON(m_widget
), stock
); 
 236             gtk_button_set_use_stock(GTK_BUTTON(m_widget
), TRUE
); 
 241     gtk_button_set_label(GTK_BUTTON(m_widget
), wxGTK_CONV(labelGTK
)); 
 242     gtk_button_set_use_stock(GTK_BUTTON(m_widget
), FALSE
); 
 244     ApplyWidgetStyle( false ); 
 247 bool wxButton::Enable( bool enable 
) 
 249     if ( !wxControl::Enable( enable 
) ) 
 252     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 257 bool wxButton::IsOwnGtkWindow( GdkWindow 
*window 
) 
 259     return GTK_BUTTON(m_widget
)->event_window
; 
 262 void wxButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 264     gtk_widget_modify_style(m_widget
, style
); 
 265     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 268 wxSize 
wxButton::DoGetBestSize() const 
 270     // the default button in wxGTK is bigger than the other ones because of an 
 271     // extra border around it, but we don't want to take it into account in 
 272     // our size calculations (otherwsie the result is visually ugly), so 
 273     // always return the size of non default button from here 
 274     const bool isDefault 
= GTK_WIDGET_HAS_DEFAULT(m_widget
); 
 277         // temporarily unset default flag 
 278         GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 281     wxSize 
ret( wxControl::DoGetBestSize() ); 
 286         GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 289     if (!HasFlag(wxBU_EXACTFIT
)) 
 291         wxSize defaultSize 
= GetDefaultSize(); 
 292         if (ret
.x 
< defaultSize
.x
) ret
.x 
= defaultSize
.x
; 
 293         if (ret
.y 
< defaultSize
.y
) ret
.y 
= defaultSize
.y
; 
 302 wxButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 304     return GetDefaultAttributesFromGTKWidget(gtk_button_new
); 
 307 #endif // wxUSE_BUTTON