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
23class wxBitmapButton;
24
25//-----------------------------------------------------------------------------
26// data
27//-----------------------------------------------------------------------------
28
29extern bool   g_blockEventsOnDrag;
30
31//-----------------------------------------------------------------------------
32// "clicked"
33//-----------------------------------------------------------------------------
34
35extern "C" {
36static 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
54extern "C" {
55static 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
68extern "C" {
69static 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
82extern "C" {
83static 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
96extern "C" {
97static 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
110IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton,wxButton)
111
112void wxBitmapButton::Init()
113{
114    m_hasFocus =
115    m_isSelected = false;
116}
117
118bool 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
176void 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
184void wxBitmapButton::SetLabel( const wxString &label )
185{
186    wxCHECK_RET( m_widget != NULL, wxT("invalid button") );
187
188    wxControl::SetLabel( label );
189}
190
191void wxBitmapButton::DoApplyWidgetStyle(GtkRcStyle *style)
192{
193    if (!GTK_BIN(m_widget)->child)
194        return;
195
196    wxButton::DoApplyWidgetStyle(style);
197}
198
199void 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
241wxSize wxBitmapButton::DoGetBestSize() const
242{
243    return wxControl::DoGetBestSize();
244}
245
246bool wxBitmapButton::Enable( bool enable )
247{
248    if ( !wxWindow::Enable(enable) )
249        return false;
250
251    OnSetBitmap();
252
253    return true;
254}
255
256void wxBitmapButton::HasFocus()
257{
258    m_hasFocus = true;
259    OnSetBitmap();
260}
261
262void wxBitmapButton::NotFocus()
263{
264    m_hasFocus = false;
265    OnSetBitmap();
266}
267
268void wxBitmapButton::StartSelect()
269{
270    m_isSelected = true;
271    OnSetBitmap();
272}
273
274void wxBitmapButton::EndSelect()
275{
276    m_isSelected = false;
277    OnSetBitmap();
278}
279
280void wxBitmapButton::OnFocusChange(wxFocusEvent& event)
281{
282    event.Skip();
283    OnSetBitmap();
284}
285
286#endif // wxUSE_BMPBUTTON
287