]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/spinbutt.cpp
Test the commit announcement bot some more by fixing more gtk signal callback handler...
[wxWidgets.git] / src / gtk / spinbutt.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: spinbutt.cpp
3 // Purpose: wxSpinButton
4 // Author: Robert
5 // Modified by:
6 // RCS-ID: $Id$
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13
14 #include "wx/spinbutt.h"
15
16 #if wxUSE_SPINBTN
17
18 #include "wx/utils.h"
19 #include "wx/math.h"
20 #include "wx/gtk/private.h"
21
22 //-----------------------------------------------------------------------------
23 // idle system
24 //-----------------------------------------------------------------------------
25
26 extern void wxapp_install_idle_handler();
27 extern bool g_isIdle;
28
29 //-----------------------------------------------------------------------------
30 // data
31 //-----------------------------------------------------------------------------
32
33 extern bool g_blockEventsOnDrag;
34
35 static const float sensitivity = 0.02;
36
37 //-----------------------------------------------------------------------------
38 // "value_changed"
39 //-----------------------------------------------------------------------------
40
41 extern "C" {
42 static void gtk_spinbutt_callback( GtkWidget *WXUNUSED(widget), wxSpinButton *win )
43 {
44 if (g_isIdle) wxapp_install_idle_handler();
45
46 if (!win->m_hasVMT) return;
47 if (g_blockEventsOnDrag) return;
48
49 float diff = win->m_adjust->value - win->m_oldPos;
50 if (fabs(diff) < sensitivity) return;
51
52 wxEventType command = wxEVT_NULL;
53
54 float line_step = win->m_adjust->step_increment;
55
56 if (fabs(diff-line_step) < sensitivity) command = wxEVT_SCROLL_LINEUP;
57 else if (fabs(diff+line_step) < sensitivity) command = wxEVT_SCROLL_LINEDOWN;
58 else command = wxEVT_SCROLL_THUMBTRACK;
59
60 int value = (int)ceil(win->m_adjust->value);
61
62 wxSpinEvent event( command, win->GetId());
63 event.SetPosition( value );
64 event.SetEventObject( win );
65
66 if ((win->GetEventHandler()->ProcessEvent( event )) &&
67 !event.IsAllowed() )
68 {
69 /* program has vetoed */
70 win->m_adjust->value = win->m_oldPos;
71
72 g_signal_handlers_disconnect_by_func (win->m_adjust,
73 (gpointer) gtk_spinbutt_callback,
74 win);
75
76 g_signal_emit_by_name (win->m_adjust, "value_changed");
77
78 g_signal_connect (win->m_adjust, "value_changed",
79 G_CALLBACK (gtk_spinbutt_callback), win);
80 return;
81 }
82
83 win->m_oldPos = win->m_adjust->value;
84
85 /* always send a thumbtrack event */
86 if (command != wxEVT_SCROLL_THUMBTRACK)
87 {
88 command = wxEVT_SCROLL_THUMBTRACK;
89 wxSpinEvent event2( command, win->GetId());
90 event2.SetPosition( value );
91 event2.SetEventObject( win );
92 win->GetEventHandler()->ProcessEvent( event2 );
93 }
94 }
95 }
96
97 //-----------------------------------------------------------------------------
98 // wxSpinButton
99 //-----------------------------------------------------------------------------
100
101 IMPLEMENT_DYNAMIC_CLASS(wxSpinButton,wxControl)
102 IMPLEMENT_DYNAMIC_CLASS(wxSpinEvent, wxNotifyEvent)
103
104 BEGIN_EVENT_TABLE(wxSpinButton, wxControl)
105 EVT_SIZE(wxSpinButton::OnSize)
106 END_EVENT_TABLE()
107
108 bool wxSpinButton::Create(wxWindow *parent,
109 wxWindowID id,
110 const wxPoint& pos,
111 const wxSize& size,
112 long style,
113 const wxString& name)
114 {
115 m_needParent = TRUE;
116
117 wxSize new_size = size,
118 sizeBest = DoGetBestSize();
119 new_size.x = sizeBest.x; // override width always
120 if (new_size.y == -1)
121 new_size.y = sizeBest.y;
122
123 if (!PreCreation( parent, pos, new_size ) ||
124 !CreateBase( parent, id, pos, new_size, style, wxDefaultValidator, name ))
125 {
126 wxFAIL_MSG( wxT("wxXX creation failed") );
127 return FALSE;
128 }
129
130 m_oldPos = 0.0;
131
132 m_adjust = (GtkAdjustment*) gtk_adjustment_new( 0.0, 0.0, 100.0, 1.0, 5.0, 0.0);
133
134 m_widget = gtk_spin_button_new( m_adjust, 0, 0 );
135
136 gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget),
137 (int)(m_windowStyle & wxSP_WRAP) );
138
139 g_signal_connect (m_adjust, "value_changed",
140 G_CALLBACK (gtk_spinbutt_callback), this);
141
142 m_parent->DoAddChild( this );
143
144 PostCreation(new_size);
145
146 return TRUE;
147 }
148
149 int wxSpinButton::GetMin() const
150 {
151 wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
152
153 return (int)ceil(m_adjust->lower);
154 }
155
156 int wxSpinButton::GetMax() const
157 {
158 wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
159
160 return (int)ceil(m_adjust->upper);
161 }
162
163 int wxSpinButton::GetValue() const
164 {
165 wxCHECK_MSG( (m_widget != NULL), 0, wxT("invalid spin button") );
166
167 return (int)ceil(m_adjust->value);
168 }
169
170 void wxSpinButton::SetValue( int value )
171 {
172 wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
173
174 float fpos = (float)value;
175 m_oldPos = fpos;
176 if (fabs(fpos-m_adjust->value) < sensitivity) return;
177
178 m_adjust->value = fpos;
179
180 g_signal_emit_by_name (m_adjust, "value_changed");
181 }
182
183 void wxSpinButton::SetRange(int minVal, int maxVal)
184 {
185 wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
186
187 float fmin = (float)minVal;
188 float fmax = (float)maxVal;
189
190 if ((fabs(fmin-m_adjust->lower) < sensitivity) &&
191 (fabs(fmax-m_adjust->upper) < sensitivity))
192 {
193 return;
194 }
195
196 m_adjust->lower = fmin;
197 m_adjust->upper = fmax;
198
199 g_signal_emit_by_name (m_adjust, "changed");
200
201 // these two calls are required due to some bug in GTK
202 Refresh();
203 SetFocus();
204 }
205
206 void wxSpinButton::OnSize( wxSizeEvent &WXUNUSED(event) )
207 {
208 wxCHECK_RET( (m_widget != NULL), wxT("invalid spin button") );
209
210 m_width = DoGetBestSize().x;
211 gtk_widget_set_size_request( m_widget, m_width, m_height );
212 }
213
214 bool wxSpinButton::IsOwnGtkWindow( GdkWindow *window )
215 {
216 return GTK_SPIN_BUTTON(m_widget)->panel == window;
217 }
218
219 wxSize wxSpinButton::DoGetBestSize() const
220 {
221 wxSize best(15, 26); // FIXME
222 CacheBestSize(best);
223 return best;
224 }
225
226 // static
227 wxVisualAttributes
228 wxSpinButton::GetClassDefaultAttributes(wxWindowVariant WXUNUSED(variant))
229 {
230 // TODO: overload to accept functions like gtk_spin_button_new?
231 // Until then use a similar type
232 return GetDefaultAttributesFromGTKWidget(gtk_button_new);
233 }
234
235 #endif