1 ///////////////////////////////////////////////////////////////////////////// 
   7 // Copyright:   (c) Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  12 #pragma implementation "spinctrl.h" 
  15 #include "wx/spinctrl.h" 
  26 //----------------------------------------------------------------------------- 
  28 //----------------------------------------------------------------------------- 
  30 extern void wxapp_install_idle_handler(); 
  33 static const float sensitivity 
= 0.02; 
  35 //----------------------------------------------------------------------------- 
  37 //----------------------------------------------------------------------------- 
  39 extern bool   g_blockEventsOnDrag
; 
  41 //----------------------------------------------------------------------------- 
  43 //----------------------------------------------------------------------------- 
  45 static void gtk_spinctrl_callback( GtkWidget 
*WXUNUSED(widget
), wxSpinCtrl 
*win 
) 
  47     if (g_isIdle
) wxapp_install_idle_handler(); 
  49     if (!win
->m_hasVMT
) return; 
  50     if (g_blockEventsOnDrag
) return; 
  52     wxCommandEvent 
event( wxEVT_COMMAND_SPINCTRL_UPDATED
, win
->GetId()); 
  53     event
.SetEventObject( win 
); 
  54     event
.SetInt( win
->GetValue() ); 
  55     win
->GetEventHandler()->ProcessEvent( event 
); 
  58 //----------------------------------------------------------------------------- 
  60 //----------------------------------------------------------------------------- 
  62 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
,wxControl
) 
  64 BEGIN_EVENT_TABLE(wxSpinCtrl
, wxControl
) 
  65     EVT_CHAR(wxSpinCtrl::OnChar
) 
  68 bool wxSpinCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
  69                         const wxString
& value
, 
  70                         const wxPoint
& pos
,  const wxSize
& size
, 
  72                         int min
, int max
, int initial
, 
  76     m_acceptsFocus 
= TRUE
; 
  78     if (!PreCreation( parent
, pos
, size 
) || 
  79         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
  81         wxFAIL_MSG( wxT("wxSpinCtrl creation failed") ); 
  87     m_adjust 
= (GtkAdjustment
*) gtk_adjustment_new( initial
, min
, max
, 1.0, 5.0, 0.0); 
  89     m_widget 
= gtk_spin_button_new( m_adjust
, 1, 0 ); 
  91     gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget
), 
  92                               (int)(m_windowStyle 
& wxSP_WRAP
) ); 
  96     m_parent
->DoAddChild( this ); 
 102     SetFont( parent
->GetFont() ); 
 104     wxSize 
size_best( DoGetBestSize() ); 
 105     wxSize 
new_size( size 
); 
 106     if (new_size
.x 
== -1) 
 107         new_size
.x 
= size_best
.x
; 
 108     if (new_size
.y 
== -1) 
 109         new_size
.y 
= size_best
.y
; 
 110     if ((new_size
.x 
!= size
.x
) || (new_size
.y 
!= size
.y
)) 
 111         SetSize( new_size
.x
, new_size
.y 
); 
 113     SetBackgroundColour( parent
->GetBackgroundColour() ); 
 122 void wxSpinCtrl::GtkDisableEvents() 
 124     gtk_signal_disconnect_by_func( GTK_OBJECT(m_adjust
), 
 125                         GTK_SIGNAL_FUNC(gtk_spinctrl_callback
), 
 130 void wxSpinCtrl::GtkEnableEvents() 
 132     gtk_signal_connect( GTK_OBJECT (m_adjust
), 
 134                         GTK_SIGNAL_FUNC(gtk_spinctrl_callback
), 
 138 int wxSpinCtrl::GetMin() const 
 140     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 142     return (int)ceil(m_adjust
->lower
); 
 145 int wxSpinCtrl::GetMax() const 
 147     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 149     return (int)ceil(m_adjust
->upper
); 
 152 int wxSpinCtrl::GetValue() const 
 154     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 156     gtk_spin_button_update( GTK_SPIN_BUTTON(m_widget
) ); 
 158     return (int)ceil(m_adjust
->value
); 
 161 void wxSpinCtrl::SetValue( const wxString
& value 
) 
 163     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 166     if ( (wxSscanf(value
, wxT("%d"), &n
) == 1) ) 
 173         // invalid number - set text as is (wxMSW compatible) 
 175         gtk_entry_set_text( GTK_ENTRY(m_widget
), value
.mbc_str() ); 
 180 void wxSpinCtrl::SetValue( int value 
) 
 182     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 184     float fpos 
= (float)value
; 
 186     if (fabs(fpos
-m_adjust
->value
) < sensitivity
) return; 
 188     m_adjust
->value 
= fpos
; 
 191     gtk_signal_emit_by_name( GTK_OBJECT(m_adjust
), "value_changed" ); 
 195 void wxSpinCtrl::SetRange(int minVal
, int maxVal
) 
 197     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 199     float fmin 
= (float)minVal
; 
 200     float fmax 
= (float)maxVal
; 
 202     if ((fabs(fmin
-m_adjust
->lower
) < sensitivity
) && 
 203         (fabs(fmax
-m_adjust
->upper
) < sensitivity
)) 
 208     m_adjust
->lower 
= fmin
; 
 209     m_adjust
->upper 
= fmax
; 
 211     gtk_signal_emit_by_name( GTK_OBJECT(m_adjust
), "changed" ); 
 213     // these two calls are required due to some bug in GTK 
 218 void wxSpinCtrl::OnChar( wxKeyEvent 
&event 
) 
 220     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid spin ctrl") ); 
 222     if (event
.KeyCode() == WXK_RETURN
) 
 224         wxWindow 
*top_frame 
= m_parent
; 
 225         while (top_frame
->GetParent() && !(top_frame
->GetParent()->m_isFrame
)) 
 226             top_frame 
= top_frame
->GetParent(); 
 227         GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 229         if (window
->default_widget
) 
 231             gtk_widget_activate (window
->default_widget
); 
 239 bool wxSpinCtrl::IsOwnGtkWindow( GdkWindow 
*window 
) 
 241     return GTK_SPIN_BUTTON(m_widget
)->panel 
== window
; 
 244 void wxSpinCtrl::ApplyWidgetStyle() 
 247     gtk_widget_set_style( m_widget
, m_widgetStyle 
); 
 250 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 252     wxSize 
ret( wxControl::DoGetBestSize() ); 
 253     return wxSize(95, ret
.y
);