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 
  23 #include "wx/gtk/private.h" 
  25 //----------------------------------------------------------------------------- 
  27 //----------------------------------------------------------------------------- 
  29 extern bool   g_blockEventsOnDrag
; 
  31 //----------------------------------------------------------------------------- 
  33 //----------------------------------------------------------------------------- 
  37 gtk_value_changed(GtkSpinButton
* spinbutton
, wxSpinCtrl
* win
) 
  39     if (g_isIdle
) wxapp_install_idle_handler(); 
  41     win
->m_pos 
= int(gtk_spin_button_get_value(spinbutton
)); 
  42     if (!win
->m_hasVMT 
|| g_blockEventsOnDrag 
|| win
->m_blockScrollEvent
) 
  45     wxCommandEvent 
event( wxEVT_COMMAND_SPINCTRL_UPDATED
, win
->GetId()); 
  46     event
.SetEventObject( win 
); 
  48     // note that we don't use wxSpinCtrl::GetValue() here because it would 
  49     // adjust the value to fit into the control range and this means that we 
  50     // would never be able to enter an "invalid" value in the control, even 
  51     // temporarily - and trying to enter 10 into the control which accepts the 
  52     // values in range 5..50 is then, ummm, quite challenging (hint: you can't 
  54     event
.SetInt(win
->m_pos
); 
  55     win
->GetEventHandler()->ProcessEvent( event 
); 
  59 //----------------------------------------------------------------------------- 
  61 //----------------------------------------------------------------------------- 
  65 gtk_changed(GtkSpinButton
* spinbutton
, wxSpinCtrl
* win
) 
  68         wxapp_install_idle_handler(); 
  70     if (!win
->m_hasVMT 
|| win
->m_blockScrollEvent
) 
  73     wxCommandEvent 
event( wxEVT_COMMAND_TEXT_UPDATED
, win
->GetId() ); 
  74     event
.SetEventObject( win 
); 
  77     event
.SetInt(win
->m_pos
); 
  78     win
->GetEventHandler()->ProcessEvent( event 
); 
  82 //----------------------------------------------------------------------------- 
  84 //----------------------------------------------------------------------------- 
  86 IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl
,wxControl
) 
  88 BEGIN_EVENT_TABLE(wxSpinCtrl
, wxControl
) 
  89     EVT_CHAR(wxSpinCtrl::OnChar
) 
  92 wxSpinCtrl::wxSpinCtrl() 
  97 bool wxSpinCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
  98                         const wxString
& value
, 
  99                         const wxPoint
& pos
,  const wxSize
& size
, 
 101                         int min
, int max
, int initial
, 
 102                         const wxString
& name
) 
 105     m_acceptsFocus 
= true; 
 107     if (!PreCreation( parent
, pos
, size 
) || 
 108         !CreateBase( parent
, id
, pos
, size
, style
, wxDefaultValidator
, name 
)) 
 110         wxFAIL_MSG( wxT("wxSpinCtrl creation failed") ); 
 114     m_widget 
= gtk_spin_button_new_with_range(min
, max
, 1); 
 115     gtk_spin_button_set_value((GtkSpinButton
*)m_widget
, initial
); 
 116     m_pos 
= int(gtk_spin_button_get_value((GtkSpinButton
*)m_widget
)); 
 118     gtk_spin_button_set_wrap( GTK_SPIN_BUTTON(m_widget
), 
 119                               (int)(m_windowStyle 
& wxSP_WRAP
) ); 
 121     g_signal_connect(m_widget
, "value_changed", G_CALLBACK(gtk_value_changed
), this); 
 122     g_signal_connect(m_widget
, "changed", G_CALLBACK(gtk_changed
), this); 
 124     m_parent
->DoAddChild( this ); 
 136 int wxSpinCtrl::GetMin() const 
 138     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 141     gtk_spin_button_get_range((GtkSpinButton
*)m_widget
, &min
, NULL
); 
 145 int wxSpinCtrl::GetMax() const 
 147     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 150     gtk_spin_button_get_range((GtkSpinButton
*)m_widget
, NULL
, &max
); 
 154 int wxSpinCtrl::GetValue() const 
 156     wxCHECK_MSG( (m_widget 
!= NULL
), 0, wxT("invalid spin button") ); 
 158     wx_const_cast(wxSpinCtrl
*, this)->BlockScrollEvent(); 
 159     gtk_spin_button_update( GTK_SPIN_BUTTON(m_widget
) ); 
 160     wx_const_cast(wxSpinCtrl
*, this)->UnblockScrollEvent(); 
 165 void wxSpinCtrl::SetValue( const wxString
& value 
) 
 167     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 170     if ( (wxSscanf(value
, wxT("%d"), &n
) == 1) ) 
 177         // invalid number - set text as is (wxMSW compatible) 
 179         gtk_entry_set_text( GTK_ENTRY(m_widget
), wxGTK_CONV( value 
) ); 
 180         UnblockScrollEvent(); 
 184 void wxSpinCtrl::SetValue( int value 
) 
 186     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 189     gtk_spin_button_set_value((GtkSpinButton
*)m_widget
, value
); 
 190     UnblockScrollEvent(); 
 193 void wxSpinCtrl::SetSelection(long from
, long to
) 
 195     // translate from wxWidgets conventions to GTK+ ones: (-1, -1) means the 
 197     if ( from 
== -1 && to 
== -1 ) 
 203     gtk_editable_select_region( GTK_EDITABLE(m_widget
), (gint
)from
, (gint
)to 
); 
 206 void wxSpinCtrl::SetRange(int minVal
, int maxVal
) 
 208     wxCHECK_RET( (m_widget 
!= NULL
), wxT("invalid spin button") ); 
 211     gtk_spin_button_set_range((GtkSpinButton
*)m_widget
, minVal
, maxVal
); 
 212     UnblockScrollEvent(); 
 215 void wxSpinCtrl::OnChar( wxKeyEvent 
&event 
) 
 217     wxCHECK_RET( m_widget 
!= NULL
, wxT("invalid spin ctrl") ); 
 219     if (event
.GetKeyCode() == WXK_RETURN
) 
 221         wxWindow 
*top_frame 
= wxGetTopLevelParent(m_parent
); 
 223         if ( GTK_IS_WINDOW(top_frame
->m_widget
) ) 
 225             GtkWindow 
*window 
= GTK_WINDOW(top_frame
->m_widget
); 
 228                 GtkWidget 
*widgetDef 
= window
->default_widget
; 
 232                     gtk_widget_activate(widgetDef
); 
 239     if ((event
.GetKeyCode() == WXK_RETURN
) && (m_windowStyle 
& wxTE_PROCESS_ENTER
)) 
 241         wxCommandEvent 
evt( wxEVT_COMMAND_TEXT_ENTER
, m_windowId 
); 
 242         evt
.SetEventObject(this); 
 243         GtkSpinButton 
*gsb 
= GTK_SPIN_BUTTON(m_widget
); 
 244         wxString val 
= wxGTK_CONV_BACK( gtk_entry_get_text( &gsb
->entry 
) ); 
 245         evt
.SetString( val 
); 
 246         if (GetEventHandler()->ProcessEvent(evt
)) return; 
 252 bool wxSpinCtrl::IsOwnGtkWindow( GdkWindow 
*window 
) 
 254     GtkSpinButton
* spinbutton 
= GTK_SPIN_BUTTON(m_widget
); 
 255     return window 
== spinbutton
->entry
.text_area 
|| window 
== spinbutton
->panel
; 
 258 wxSize 
wxSpinCtrl::DoGetBestSize() const 
 260     wxSize 
ret( wxControl::DoGetBestSize() ); 
 261     wxSize 
best(95, ret
.y
); 
 268 wxSpinCtrl::GetClassDefaultAttributes(wxWindowVariant 
WXUNUSED(variant
)) 
 270     // TODO: overload to accept functions like gtk_spin_button_new? 
 271     // Until then use a similar type 
 272     return GetDefaultAttributesFromGTKWidget(gtk_entry_new
, true);