1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/gtk/bmpbuttn.cpp
3 // Purpose:
4 // Author:      Robert Roebling
5 // Id:          $Id: bmpbuttn.cpp 52007 2008-02-22 19:57:54Z VS $
6 // Copyright:   (c) 1998 Robert Roebling
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 // For compilers that support precompilation, includes "wx.h".
11 #include "wx/wxprec.h"
12 
13 #if wxUSE_BMPBUTTON
14 
15 #include "wx/bmpbuttn.h"
16 
17 #include "wx/gtk/private.h"
18 
19 //-----------------------------------------------------------------------------
20 // classes
21 //-----------------------------------------------------------------------------
22 
23 class wxBitmapButton;
24 
25 //-----------------------------------------------------------------------------
26 // data
27 //-----------------------------------------------------------------------------
28 
29 extern bool   g_blockEventsOnDrag;
30 
31 //-----------------------------------------------------------------------------
32 // "clicked"
33 //-----------------------------------------------------------------------------
34 
35 extern "C" {
gtk_bmpbutton_clicked_callback(GtkWidget * WXUNUSED (widget),wxBitmapButton * button)36 static void gtk_bmpbutton_clicked_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button )
37 {
38     if (g_isIdle)
39         wxapp_install_idle_handler();
40 
41     if (!button->m_hasVMT) return;
42     if (g_blockEventsOnDrag) return;
43 
44     wxCommandEvent event(wxEVT_COMMAND_BUTTON_CLICKED, button->GetId());
45     event.SetEventObject(button);
46     button->GetEventHandler()->ProcessEvent(event);
47 }
48 }
49 
50 //-----------------------------------------------------------------------------
51 // "enter"
52 //-----------------------------------------------------------------------------
53 
54 extern "C" {
gtk_bmpbutton_enter_callback(GtkWidget * WXUNUSED (widget),wxBitmapButton * button)55 static void gtk_bmpbutton_enter_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button )
56 {
57     if (!button->m_hasVMT) return;
58     if (g_blockEventsOnDrag) return;
59 
60     button->HasFocus();
61 }
62 }
63 
64 //-----------------------------------------------------------------------------
65 // "leave"
66 //-----------------------------------------------------------------------------
67 
68 extern "C" {
gtk_bmpbutton_leave_callback(GtkWidget * WXUNUSED (widget),wxBitmapButton * button)69 static void gtk_bmpbutton_leave_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button )
70 {
71     if (!button->m_hasVMT) return;
72     if (g_blockEventsOnDrag) return;
73 
74     button->NotFocus();
75 }
76 }
77 
78 //-----------------------------------------------------------------------------
79 // "pressed"
80 //-----------------------------------------------------------------------------
81 
82 extern "C" {
gtk_bmpbutton_press_callback(GtkWidget * WXUNUSED (widget),wxBitmapButton * button)83 static void gtk_bmpbutton_press_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button )
84 {
85     if (!button->m_hasVMT) return;
86     if (g_blockEventsOnDrag) return;
87 
88     button->StartSelect();
89 }
90 }
91 
92 //-----------------------------------------------------------------------------
93 // "released"
94 //-----------------------------------------------------------------------------
95 
96 extern "C" {
gtk_bmpbutton_release_callback(GtkWidget * WXUNUSED (widget),wxBitmapButton * button)97 static void gtk_bmpbutton_release_callback( GtkWidget *WXUNUSED(widget), wxBitmapButton *button )
98 {
99     if (!button->m_hasVMT) return;
100     if (g_blockEventsOnDrag) return;
101 
102     button->EndSelect();
103 }
104 }
105 
106 //-----------------------------------------------------------------------------
107 // wxBitmapButton
108 //-----------------------------------------------------------------------------
109 
IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton,wxButton)110 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton,wxButton)
111 
112 void wxBitmapButton::Init()
113 {
114     m_hasFocus =
115     m_isSelected = false;
116 }
117 
Create(wxWindow * parent,wxWindowID id,const wxBitmap & bitmap,const wxPoint & pos,const wxSize & size,long style,const wxValidator & validator,const wxString & name)118 bool wxBitmapButton::Create( wxWindow *parent,
119                              wxWindowID id,
120                              const wxBitmap& bitmap,
121                              const wxPoint& pos,
122                              const wxSize& size,
123                              long style,
124                              const wxValidator& validator,
125                              const wxString &name )
126 {
127     m_needParent = true;
128     m_acceptsFocus = true;
129 
130     if (!PreCreation( parent, pos, size ) ||
131         !CreateBase( parent, id, pos, size, style, validator, name ))
132     {
133         wxFAIL_MSG( wxT("wxBitmapButton creation failed") );
134         return false;
135     }
136 
137     m_bmpNormal = bitmap;
138 
139     m_widget = gtk_button_new();
140 
141     if (style & wxNO_BORDER)
142        gtk_button_set_relief( GTK_BUTTON(m_widget), GTK_RELIEF_NONE );
143 
144     if (m_bmpNormal.Ok())
145     {
146         OnSetBitmap();
147     }
148 
149     g_signal_connect_after (m_widget, "clicked",
150                             G_CALLBACK (gtk_bmpbutton_clicked_callback),
151                             this);
152 
153     g_signal_connect (m_widget, "enter",
154                       G_CALLBACK (gtk_bmpbutton_enter_callback), this);
155     g_signal_connect (m_widget, "leave",
156                       G_CALLBACK (gtk_bmpbutton_leave_callback), this);
157     g_signal_connect (m_widget, "pressed",
158                       G_CALLBACK (gtk_bmpbutton_press_callback), this);
159     g_signal_connect (m_widget, "released",
160                       G_CALLBACK (gtk_bmpbutton_release_callback), this);
161 
162     m_parent->DoAddChild( this );
163 
164     PostCreation(size);
165 
166     Connect(wxEVT_SET_FOCUS,
167             wxFocusEventHandler(wxBitmapButton::OnFocusChange),
168             NULL, this);
169     Connect(wxEVT_KILL_FOCUS,
170             wxFocusEventHandler(wxBitmapButton::OnFocusChange),
171             NULL, this);
172 
173     return true;
174 }
175 
SetDefault()176 void wxBitmapButton::SetDefault()
177 {
178     GTK_WIDGET_SET_FLAGS( m_widget, GTK_CAN_DEFAULT );
179     gtk_widget_grab_default( m_widget );
180 
181     SetSize( m_x, m_y, m_width, m_height );
182 }
183 
SetLabel(const wxString & label)184 void wxBitmapButton::SetLabel( const wxString &label )
185 {
186     wxCHECK_RET( m_widget != NULL, wxT("invalid button") );
187 
188     wxControl::SetLabel( label );
189 }
190 
DoApplyWidgetStyle(GtkRcStyle * style)191 void wxBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
192 {
193     if (!GTK_BIN(m_widget)->child)
194         return;
195 
196     wxButton::DoApplyWidgetStyle(style);
197 }
198 
OnSetBitmap()199 void wxBitmapButton::OnSetBitmap()
200 {
201     wxCHECK_RET( m_widget != NULL, wxT("invalid bitmap button") );
202 
203     InvalidateBestSize();
204 
205     wxBitmap the_one;
206     if (!m_isEnabled)
207         the_one = m_bmpDisabled;
208     else if (m_isSelected)
209         the_one = m_bmpSelected;
210     else if (m_hasFocus)
211     {
212         // NB: this is misnomer, m_hasFocus doesn't mean "has focus", but
213         //     "mouse is over the window"
214         the_one = m_bmpHover;
215     }
216     else if (FindFocus() == this)
217         the_one = m_bmpFocus;
218     else
219         the_one = m_bmpNormal;
220 
221     if (!the_one.Ok()) the_one = m_bmpNormal;
222     if (!the_one.Ok()) return;
223 
224     GtkWidget *child = GTK_BIN(m_widget)->child;
225     if (child == NULL)
226     {
227         // initial bitmap
228         GtkWidget *pixmap =
229             gtk_image_new_from_pixbuf(the_one.GetPixbuf());
230 
231         gtk_widget_show(pixmap);
232         gtk_container_add(GTK_CONTAINER(m_widget), pixmap);
233     }
234     else
235     {   // subsequent bitmaps
236         GtkImage *pixmap = GTK_IMAGE(child);
237         gtk_image_set_from_pixbuf(pixmap, the_one.GetPixbuf());
238     }
239 }
240 
DoGetBestSize() const241 wxSize wxBitmapButton::DoGetBestSize() const
242 {
243     return wxControl::DoGetBestSize();
244 }
245 
Enable(bool enable)246 bool wxBitmapButton::Enable( bool enable )
247 {
248     if ( !wxWindow::Enable(enable) )
249         return false;
250 
251     OnSetBitmap();
252 
253     return true;
254 }
255 
HasFocus()256 void wxBitmapButton::HasFocus()
257 {
258     m_hasFocus = true;
259     OnSetBitmap();
260 }
261 
NotFocus()262 void wxBitmapButton::NotFocus()
263 {
264     m_hasFocus = false;
265     OnSetBitmap();
266 }
267 
StartSelect()268 void wxBitmapButton::StartSelect()
269 {
270     m_isSelected = true;
271     OnSetBitmap();
272 }
273 
EndSelect()274 void wxBitmapButton::EndSelect()
275 {
276     m_isSelected = false;
277     OnSetBitmap();
278 }
279 
OnFocusChange(wxFocusEvent & event)280 void wxBitmapButton::OnFocusChange(wxFocusEvent& event)
281 {
282     event.Skip();
283     OnSetBitmap();
284 }
285 
286 #endif // wxUSE_BMPBUTTON
287