1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/gtk/anybutton.cpp
4 // Author: Robert Roebling
5 // Created: 1998-05-20 (extracted from button.cpp)
7 // Copyright: (c) 1998 Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
14 #ifdef wxHAS_ANY_BUTTON
17 #include "wx/anybutton.h"
20 #include "wx/stockitem.h"
23 #include "wx/gtk/private/gtk2-compat.h"
25 // ----------------------------------------------------------------------------
27 // ----------------------------------------------------------------------------
33 wxgtk_button_enter_callback(GtkWidget
*WXUNUSED(widget
), wxAnyButton
*button
)
35 if ( button
->GTKShouldIgnoreEvent() )
38 button
->GTKMouseEnters();
42 wxgtk_button_leave_callback(GtkWidget
*WXUNUSED(widget
), wxAnyButton
*button
)
44 if ( button
->GTKShouldIgnoreEvent() )
47 button
->GTKMouseLeaves();
51 wxgtk_button_press_callback(GtkWidget
*WXUNUSED(widget
), wxAnyButton
*button
)
53 if ( button
->GTKShouldIgnoreEvent() )
60 wxgtk_button_released_callback(GtkWidget
*WXUNUSED(widget
), wxAnyButton
*button
)
62 if ( button
->GTKShouldIgnoreEvent() )
65 button
->GTKReleased();
70 //-----------------------------------------------------------------------------
72 //-----------------------------------------------------------------------------
74 bool wxAnyButton::Enable( bool enable
)
76 if (!base_type::Enable(enable
))
79 gtk_widget_set_sensitive(gtk_bin_get_child(GTK_BIN(m_widget
)), enable
);
89 GdkWindow
*wxAnyButton::GTKGetWindow(wxArrayGdkWindows
& WXUNUSED(windows
)) const
91 return gtk_button_get_event_window(GTK_BUTTON(m_widget
));
96 wxAnyButton::GetClassDefaultAttributes(wxWindowVariant
WXUNUSED(variant
))
98 return GetDefaultAttributesFromGTKWidget(gtk_button_new
);
101 // ----------------------------------------------------------------------------
103 // ----------------------------------------------------------------------------
105 void wxAnyButton::GTKMouseEnters()
112 void wxAnyButton::GTKMouseLeaves()
119 void wxAnyButton::GTKPressed()
126 void wxAnyButton::GTKReleased()
133 void wxAnyButton::GTKOnFocus(wxFocusEvent
& event
)
140 wxAnyButton::State
wxAnyButton::GTKGetCurrentState() const
142 if ( !IsThisEnabled() )
143 return m_bitmaps
[State_Disabled
].IsOk() ? State_Disabled
: State_Normal
;
145 if ( m_isPressed
&& m_bitmaps
[State_Pressed
].IsOk() )
146 return State_Pressed
;
148 if ( m_isCurrent
&& m_bitmaps
[State_Current
].IsOk() )
149 return State_Current
;
151 if ( HasFocus() && m_bitmaps
[State_Focused
].IsOk() )
152 return State_Focused
;
157 void wxAnyButton::GTKUpdateBitmap()
159 // if we don't show bitmaps at all, there is nothing to update
160 if ( m_bitmaps
[State_Normal
].IsOk() )
162 // if we do show them, this will return a state for which we do have a
164 State state
= GTKGetCurrentState();
166 GTKDoShowBitmap(m_bitmaps
[state
]);
170 void wxAnyButton::GTKDoShowBitmap(const wxBitmap
& bitmap
)
172 wxASSERT_MSG( bitmap
.IsOk(), "invalid bitmap" );
175 if ( DontShowLabel() )
177 image
= gtk_bin_get_child(GTK_BIN(m_widget
));
179 else // have both label and bitmap
181 image
= gtk_button_get_image(GTK_BUTTON(m_widget
));
184 wxCHECK_RET( image
&& GTK_IS_IMAGE(image
), "must have image widget" );
186 gtk_image_set_from_pixbuf(GTK_IMAGE(image
), bitmap
.GetPixbuf());
189 wxBitmap
wxAnyButton::DoGetBitmap(State which
) const
191 return m_bitmaps
[which
];
194 void wxAnyButton::DoSetBitmap(const wxBitmap
& bitmap
, State which
)
199 if ( DontShowLabel() )
201 // we only have the bitmap in this button, never remove it but
202 // do invalidate the best size when the bitmap (and presumably
204 InvalidateBestSize();
206 // normal image is special: setting it enables images for the button and
207 // resetting it to nothing disables all of them
210 GtkWidget
*image
= gtk_button_get_image(GTK_BUTTON(m_widget
));
211 if ( image
&& !bitmap
.IsOk() )
213 gtk_container_remove(GTK_CONTAINER(m_widget
), image
);
215 else if ( !image
&& bitmap
.IsOk() )
217 image
= gtk_image_new();
218 gtk_button_set_image(GTK_BUTTON(m_widget
), image
);
220 else // image presence or absence didn't change
222 // don't invalidate best size below
226 InvalidateBestSize();
233 if ( !m_bitmaps
[which
].IsOk() )
235 // we need to install the callbacks to be notified about
236 // the button pressed state change
241 G_CALLBACK(wxgtk_button_press_callback
),
249 G_CALLBACK(wxgtk_button_released_callback
),
254 else // no valid bitmap
256 if ( m_bitmaps
[which
].IsOk() )
258 // we don't need to be notified about the button pressed
259 // state changes any more
260 g_signal_handlers_disconnect_by_func
263 (gpointer
)wxgtk_button_press_callback
,
267 g_signal_handlers_disconnect_by_func
270 (gpointer
)wxgtk_button_released_callback
,
274 // also make sure we don't remain stuck in pressed state
285 // the logic here is the same as above for State_Pressed: we need
286 // to connect the handlers if we must be notified about the changes
287 // in the button current state and we disconnect them when/if we
288 // don't need them any more
291 if ( !m_bitmaps
[which
].IsOk() )
297 G_CALLBACK(wxgtk_button_enter_callback
),
305 G_CALLBACK(wxgtk_button_leave_callback
),
310 else // no valid bitmap
312 if ( m_bitmaps
[which
].IsOk() )
314 g_signal_handlers_disconnect_by_func
317 (gpointer
)wxgtk_button_enter_callback
,
321 g_signal_handlers_disconnect_by_func
324 (gpointer
)wxgtk_button_leave_callback
,
340 Connect(wxEVT_SET_FOCUS
,
341 wxFocusEventHandler(wxAnyButton::GTKOnFocus
));
342 Connect(wxEVT_KILL_FOCUS
,
343 wxFocusEventHandler(wxAnyButton::GTKOnFocus
));
345 else // no valid focused bitmap
347 Disconnect(wxEVT_SET_FOCUS
,
348 wxFocusEventHandler(wxAnyButton::GTKOnFocus
));
349 Disconnect(wxEVT_KILL_FOCUS
,
350 wxFocusEventHandler(wxAnyButton::GTKOnFocus
));
355 // no callbacks to connect/disconnect
359 m_bitmaps
[which
] = bitmap
;
361 // update the bitmap immediately if necessary, otherwise it will be done
362 // when the bitmap for the corresponding state is needed the next time by
364 if ( bitmap
.IsOk() && which
== GTKGetCurrentState() )
366 GTKDoShowBitmap(bitmap
);
370 void wxAnyButton::DoSetBitmapPosition(wxDirection dir
)
373 if ( !gtk_check_version(2,10,0) )
375 GtkPositionType gtkpos
;
379 wxFAIL_MSG( "invalid position" );
383 gtkpos
= GTK_POS_LEFT
;
387 gtkpos
= GTK_POS_RIGHT
;
391 gtkpos
= GTK_POS_TOP
;
395 gtkpos
= GTK_POS_BOTTOM
;
399 gtk_button_set_image_position(GTK_BUTTON(m_widget
), gtkpos
);
400 InvalidateBestSize();
405 #endif // wxHAS_ANY_BUTTON