1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/button.cpp 
   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" 
  15 #include "wx/button.h" 
  18     #include "wx/toplevel.h" 
  21 #include "wx/stockitem.h" 
  23 #include "wx/gtk/private.h" 
  24 #include "wx/gtk/win_gtk.h" 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  32 //----------------------------------------------------------------------------- 
  34 //----------------------------------------------------------------------------- 
  36 extern bool   g_blockEventsOnDrag
; 
  38 //----------------------------------------------------------------------------- 
  40 //----------------------------------------------------------------------------- 
  43 static void gtk_button_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxButton 
*button 
) 
  46        wxapp_install_idle_handler(); 
  48     if (!button
->m_hasVMT
) return; 
  49     if (g_blockEventsOnDrag
) return; 
  51     wxCommandEvent 
event(wxEVT_COMMAND_BUTTON_CLICKED
, button
->GetId()); 
  52     event
.SetEventObject(button
); 
  53     button
->GetEventHandler()->ProcessEvent(event
); 
  57 //----------------------------------------------------------------------------- 
  58 // "style_set" from m_widget 
  59 //----------------------------------------------------------------------------- 
  62 gtk_button_style_set_callback( GtkWidget 
*m_widget
, GtkStyle 
*WXUNUSED(style
), wxButton 
*win 
) 
  65         wxapp_install_idle_handler(); 
  70     int bottom_border 
= 0; 
  72     /* the default button has a border around it */ 
  73     if (GTK_WIDGET_CAN_DEFAULT(m_widget
)) 
  75         GtkBorder 
*default_border 
= NULL
; 
  76         gtk_widget_style_get( m_widget
, "default_border", &default_border
, NULL 
); 
  79             left_border 
+= default_border
->left
; 
  80             right_border 
+= default_border
->right
; 
  81             top_border 
+= default_border
->top
; 
  82             bottom_border 
+= default_border
->bottom
; 
  83             g_free( default_border 
); 
  86             win
->m_x 
- top_border
, 
  87             win
->m_y 
- left_border
, 
  88             win
->m_width 
+ left_border 
+ right_border
, 
  89             win
->m_height 
+ top_border 
+ bottom_border
); 
  95 //----------------------------------------------------------------------------- 
  97 //----------------------------------------------------------------------------- 
  99 IMPLEMENT_DYNAMIC_CLASS(wxButton
,wxControl
) 
 105 wxButton::~wxButton() 
 109 bool wxButton::Create(  wxWindow 
*parent
, wxWindowID id
, const wxString 
&label
, 
 110       const wxPoint 
&pos
, const wxSize 
&size
, 
 111       long style
, const wxValidator
& validator
, const wxString 
&name 
) 
 114     m_acceptsFocus 
= true; 
 116     if (!PreCreation( parent
, pos
, size 
) || 
 117         !CreateBase( parent
, id
, pos
, size
, style
, validator
, name 
)) 
 119         wxFAIL_MSG( wxT("wxButton creation failed") ); 
 123     m_widget 
= gtk_button_new_with_mnemonic(""); 
 125     float x_alignment 
= 0.5; 
 126     if (HasFlag(wxBU_LEFT
)) 
 128     else if (HasFlag(wxBU_RIGHT
)) 
 131     float y_alignment 
= 0.5; 
 132     if (HasFlag(wxBU_TOP
)) 
 134     else if (HasFlag(wxBU_BOTTOM
)) 
 138     if (!gtk_check_version(2,4,0)) 
 140         gtk_button_set_alignment(GTK_BUTTON(m_widget
), x_alignment
, y_alignment
); 
 145         if (GTK_IS_MISC(GTK_BIN(m_widget
)->child
)) 
 146             gtk_misc_set_alignment(GTK_MISC(GTK_BIN(m_widget
)->child
), 
 147                                 x_alignment
, y_alignment
); 
 152     if (style 
& wxNO_BORDER
) 
 153        gtk_button_set_relief( GTK_BUTTON(m_widget
), GTK_RELIEF_NONE 
); 
 155     g_signal_connect_after (m_widget
, "clicked", 
 156                             G_CALLBACK (gtk_button_clicked_callback
), 
 159     g_signal_connect_after (m_widget
, "style_set", 
 160                             G_CALLBACK (gtk_button_style_set_callback
), 
 163     m_parent
->DoAddChild( this ); 
 171 void wxButton::SetDefault() 
 173     wxTopLevelWindow 
*tlw 
= wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow
); 
 174     wxCHECK_RET( tlw
, _T("button without top level window?") ); 
 176     tlw
->SetDefaultItem(this); 
 178     GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 179     gtk_widget_grab_default( m_widget 
); 
 181     // resize for default border 
 182     gtk_button_style_set_callback( m_widget
, NULL
, this ); 
 186 wxSize 
wxButtonBase::GetDefaultSize() 
 188     static wxSize size 
= wxDefaultSize
; 
 189     if (size 
== wxDefaultSize
) 
 191         // NB: Default size of buttons should be same as size of stock 
 192         //     buttons as used in most GTK+ apps. Unfortunately it's a little 
 193         //     tricky to obtain this size: stock button's size may be smaller 
 194         //     than size of button in GtkButtonBox and vice versa, 
 195         //     GtkButtonBox's minimal button size may be smaller than stock 
 196         //     button's size. We have to retrieve both values and combine them. 
 198         GtkWidget 
*wnd 
= gtk_window_new(GTK_WINDOW_TOPLEVEL
); 
 199         GtkWidget 
*box 
= gtk_hbutton_box_new(); 
 200         GtkWidget 
*btn 
= gtk_button_new_from_stock(GTK_STOCK_CANCEL
); 
 201         gtk_container_add(GTK_CONTAINER(box
), btn
); 
 202         gtk_container_add(GTK_CONTAINER(wnd
), box
); 
 204         gtk_widget_size_request(btn
, &req
); 
 206         gint minwidth
, minheight
; 
 207         gtk_widget_style_get(box
, 
 208                              "child-min-width", &minwidth
, 
 209                              "child-min-height", &minheight
, 
 212         size
.x 
= wxMax(minwidth
, req
.width
); 
 213         size
.y 
= wxMax(minheight
, req
.height
); 
 215         gtk_widget_destroy(wnd
); 
 220 void wxButton::SetLabel( const wxString 
&lbl 
) 
 222     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid button") ); 
 226     if (label
.empty() && wxIsStockID(m_windowId
)) 
 227         label 
= wxGetStockLabel(m_windowId
); 
 229     wxControl::SetLabel(label
); 
 231     const wxString labelGTK 
= GTKConvertMnemonics(label
); 
 233     if (wxIsStockID(m_windowId
) && wxIsStockLabel(m_windowId
, label
)) 
 235         const char *stock 
= wxGetStockGtkID(m_windowId
); 
 238             gtk_button_set_label(GTK_BUTTON(m_widget
), stock
); 
 239             gtk_button_set_use_stock(GTK_BUTTON(m_widget
), TRUE
); 
 244     gtk_button_set_label(GTK_BUTTON(m_widget
), wxGTK_CONV(labelGTK
)); 
 245     gtk_button_set_use_stock(GTK_BUTTON(m_widget
), FALSE
); 
 247     ApplyWidgetStyle( false ); 
 250 bool wxButton::Enable( bool enable 
) 
 252     if ( !wxControl::Enable( enable 
) ) 
 255     gtk_widget_set_sensitive(GTK_BIN(m_widget
)->child
, enable
); 
 260 bool wxButton::IsOwnGtkWindow( GdkWindow 
*window 
) 
 262     return GTK_BUTTON(m_widget
)->event_window
; 
 265 void wxButton::DoApplyWidgetStyle(GtkRcStyle 
*style
) 
 267     gtk_widget_modify_style(m_widget
, style
); 
 268     gtk_widget_modify_style(GTK_BIN(m_widget
)->child
, style
); 
 271 wxSize 
wxButton::DoGetBestSize() const 
 273     // the default button in wxGTK is bigger than the other ones because of an 
 274     // extra border around it, but we don't want to take it into account in 
 275     // our size calculations (otherwsie the result is visually ugly), so 
 276     // always return the size of non default button from here 
 277     const bool isDefault 
= GTK_WIDGET_HAS_DEFAULT(m_widget
); 
 280         // temporarily unset default flag 
 281         GTK_WIDGET_UNSET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 284     wxSize 
ret( wxControl::DoGetBestSize() ); 
 289         GTK_WIDGET_SET_FLAGS( m_widget
, GTK_CAN_DEFAULT 
); 
 292     if (!HasFlag(wxBU_EXACTFIT
)) 
 294         wxSize defaultSize 
= GetDefaultSize(); 
 295         if (ret
.x 
< defaultSize
.x
) ret
.x 
= defaultSize
.x
; 
 296         if (ret
.y 
< defaultSize
.y
) ret
.y 
= defaultSize
.y
; 
 305 wxButton::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 307     return GetDefaultAttributesFromGTKWidget(gtk_button_new
); 
 310 #endif // wxUSE_BUTTON