1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/spinbutt.cpp 
   7 // Copyright:   (c) Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // For compilers that support precompilation, includes "wx.h". 
  12 #include "wx/wxprec.h" 
  16 #include "wx/spinctrl.h" 
  19     #include "wx/textctrl.h"    // for wxEVT_COMMAND_TEXT_UPDATED 
  21     #include "wx/wxcrtvararg.h" 
  24 #include "wx/gtk/private.h" 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  30 extern bool   g_blockEventsOnDrag
; 
  32 //----------------------------------------------------------------------------- 
  34 //----------------------------------------------------------------------------- 
  38 gtk_value_changed(GtkSpinButton
* spinbutton
, wxSpinCtrl
* win
) 
  40     win
->m_pos 
= int(gtk_spin_button_get_value(spinbutton
)); 
  41     if (!win
->m_hasVMT 
|| g_blockEventsOnDrag 
|| win
->m_blockScrollEvent
) 
  44     wxCommandEvent 
event( wxEVT_COMMAND_SPINCTRL_UPDATED
, win
->GetId()); 
  45     event
.SetEventObject( win 
); 
  47     // note that we don't use wxSpinCtrl::GetValue() here because it would 
  48     // adjust the value to fit into the control range and this means that we 
  49     // would never be able to enter an "invalid" value in the control, even 
  50     // temporarily - and trying to enter 10 into the control which accepts the 
  51     // values in range 5..50 is then, ummm, quite challenging (hint: you can't 
  53     event
.SetInt(win
->m_pos
); 
  54     win
->GetEventHandler()->ProcessEvent( event 
); 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  64 gtk_changed(GtkSpinButton
* spinbutton
, wxSpinCtrl
* win
) 
  66     if (!win
->m_hasVMT 
|| win
->m_blockScrollEvent
) 
  69     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, win
->GetId() ); 
  70     event
.SetEventObject( win 
); 
  71     event
.SetString( GTK_ENTRY(spinbutton
)->text 
); 
  74     event
.SetInt(win
->m_pos
); 
  75     win
->GetEventHandler()->ProcessEvent( event 
); 
  79 //----------------------------------------------------------------------------- 
  81 //----------------------------------------------------------------------------- 
  83 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
,wxControl
) 
  85 BEGIN_EVENT_TABLE(wxSpinCtrl
, wxControl
) 
  86     EVT_CHAR(wxSpinCtrl::OnChar
) 
  89 wxSpinCtrl::wxSpinCtrl() 
  94 bool wxSpinCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
  95                         const wxString
& value
, 
  96                         const wxPoint
& pos
,  const wxSize
& size
, 
  98                         int min
, int max
, int initial
, 
 101     if (!PreCreation( parent
, pos
, size 
) || 
 102         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 104         wxFAIL_MSG( wxT("wxSpinCtrl creation failed") ); 
 108     m_widget 
= gtk_spin_button_new_with_range(min
, max
, 1); 
 109     gtk_spin_button_set_value((GtkSpinButton
*)m_widget
, initial
); 
 110     m_pos 
= int(gtk_spin_button_get_value((GtkSpinButton
*)m_widget
)); 
 112     gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget
), 
 113                               (int)(m_windowStyle 
& wxSP_WRAP
) ); 
 115     g_signal_connect_after(m_widget
, "value_changed", G_CALLBACK(gtk_value_changed
), this); 
 116     g_signal_connect_after(m_widget
, "changed", G_CALLBACK(gtk_changed
), this); 
 118     m_parent
->DoAddChild( this ); 
 130 int wxSpinCtrl::GetMin() const 
 132     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 135     gtk_spin_button_get_range((GtkSpinButton
*)m_widget
, &min
, NULL
); 
 139 int wxSpinCtrl::GetMax() const 
 141     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 144     gtk_spin_button_get_range((GtkSpinButton
*)m_widget
, NULL
, &max
); 
 148 int wxSpinCtrl::GetValue() const 
 150     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 153     gtk_spin_button_update( GTK_SPIN_BUTTON(m_widget
) ); 
 159 void wxSpinCtrl::SetValue( const wxString
& value 
) 
 161     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 164     if ( (wxSscanf(value
, wxT("%d"), &n
) == 1) ) 
 171         // invalid number - set text as is (wxMSW compatible) 
 173         gtk_entry_set_text( GTK_ENTRY(m_widget
), wxGTK_CONV( value 
) ); 
 178 void wxSpinCtrl::SetValue( int value 
) 
 180     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 183     gtk_spin_button_set_value((GtkSpinButton
*)m_widget
, value
); 
 187 void wxSpinCtrl::SetSelection(long from
, long to
) 
 189     // translate from wxWidgets conventions to GTK+ ones: (-1, -1) means the 
 191     if ( from 
== -1 && to 
== -1 ) 
 197     gtk_editable_select_region( GTK_EDITABLE(m_widget
), (gint
)from
, (gint
)to 
); 
 200 void wxSpinCtrl::SetRange(int minVal
, int maxVal
) 
 202     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 205     gtk_spin_button_set_range((GtkSpinButton
*)m_widget
, minVal
, maxVal
); 
 210 void wxSpinCtrl::GtkDisableEvents() const 
 212     g_signal_handlers_block_by_func( m_widget
, 
 213         (gpointer
)gtk_value_changed
, (void*) this); 
 215     g_signal_handlers_block_by_func(m_widget
, 
 216         (gpointer
)gtk_changed
, (void*) this); 
 219 void wxSpinCtrl::GtkEnableEvents() const 
 221     g_signal_handlers_unblock_by_func(m_widget
, 
 222         (gpointer
)gtk_value_changed
, (void*) this); 
 224     g_signal_handlers_unblock_by_func(m_widget
, 
 225         (gpointer
)gtk_changed
, (void*) this); 
 228 void wxSpinCtrl::OnChar( wxKeyEvent 
&event 
) 
 230     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid spin ctrl") ); 
 232     if (event
.GetKeyCode() == WXK_RETURN
) 
 234         wxWindow 
*top_frame 
= wxGetTopLevelParent(m_parent
); 
 236         if ( GTK_IS_WINDOW(top_frame
->m_widget
) ) 
 238             GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 241                 GtkWidget 
*widgetDef 
= window
->default_widget
; 
 245                     gtk_widget_activate(widgetDef
); 
 252     if ((event
.GetKeyCode() == WXK_RETURN
) && (m_windowStyle 
& wxTE_PROCESS_ENTER
)) 
 254         wxCommandEvent 
evt( wxEVT_COMMAND_TEXT_ENTER
, m_windowId 
); 
 255         evt
.SetEventObject(this); 
 256         GtkSpinButton 
*gsb 
= GTK_SPIN_BUTTON(m_widget
); 
 257         wxString val 
= wxGTK_CONV_BACK( gtk_entry_get_text( &gsb
->entry 
) ); 
 258         evt
.SetString( val 
); 
 259         if (GetEventHandler()->ProcessEvent(evt
)) return; 
 265 GdkWindow 
*wxSpinCtrl::GTKGetWindow(wxArrayGdkWindows
& windows
) const 
 267     GtkSpinButton
* spinbutton 
= GTK_SPIN_BUTTON(m_widget
); 
 269     windows
.push_back(spinbutton
->entry
.text_area
); 
 270     windows
.push_back(spinbutton
->panel
); 
 275 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 277     wxSize 
ret( wxControl::DoGetBestSize() ); 
 278     wxSize 
best(95, ret
.y
); // FIXME: 95? 
 285 wxSpinCtrl::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 287     // TODO: overload to accept functions like gtk_spin_button_new? 
 288     // Until then use a similar type 
 289     return GetDefaultAttributesFromGTKWidget(gtk_entry_new
, true);