#include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly"
#include "wx/event.h"
#include "wx/textctrl.h"
+ #include "wx/wxcrtvararg.h"
#endif
#include "wx/msw/private.h"
IMPLEMENT_DYNAMIC_CLASS_XTI(wxSpinCtrl, wxControl,"wx/spinbut.h")
wxBEGIN_PROPERTIES_TABLE(wxSpinCtrl)
- wxEVENT_RANGE_PROPERTY( Spin , wxEVT_SCROLL_TOP , wxEVT_SCROLL_ENDSCROLL , wxSpinEvent )
+ wxEVENT_RANGE_PROPERTY( Spin , wxEVT_SCROLL_TOP , wxEVT_SCROLL_CHANGED , wxSpinEvent )
wxEVENT_PROPERTY( Updated , wxEVT_COMMAND_SPINCTRL_UPDATED , wxCommandEvent )
wxEVENT_PROPERTY( TextUpdated , wxEVT_COMMAND_TEXT_UPDATED , wxCommandEvent )
wxEVENT_PROPERTY( TextEnter , wxEVT_COMMAND_TEXT_ENTER , wxCommandEvent )
IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl)
#endif
-//pmg EVT_KILL_FOCUS
BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton)
EVT_CHAR(wxSpinCtrl::OnChar)
event.Skip();
}
+void wxSpinCtrl::NormalizeValue()
+{
+ const int value = GetValue();
+ const bool changed = value != m_oldValue;
+
+ // notice that we have to call SetValue() even if the value didn't change
+ // because otherwise we could be left with empty buddy control when value
+ // is 0, see comment in SetValue()
+ SetValue(value);
+
+ if ( changed )
+ {
+ SendSpinUpdate(value);
+ }
+}
+
// ----------------------------------------------------------------------------
// construction
// ----------------------------------------------------------------------------
int min, int max, int initial,
const wxString& name)
{
+ // this should be in ctor/init function but I don't want to add one to 2.8
+ // to avoid problems with default ctor which can be inlined in the user
+ // code and so might not get this fix without recompilation
+ m_oldValue = INT_MIN;
+
// before using DoGetBestSize(), have to set style to let the base class
// know whether this is a horizontal or vertical control (we're always
// vertical)
return false;
}
- SetRange(min, max);
- SetValue(initial);
+ wxSpinButtonBase::SetRange(min, max);
// subclass the text ctrl to be able to intercept some events
wxSetWindowUserData(GetBuddyHwnd(), this);
sizeText.y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(cy);
}
- SetBestSize(size);
+ SetInitialSize(size);
(void)::ShowWindow(GetBuddyHwnd(), SW_SHOW);
// associate the text window with the spin button
(void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0);
+ SetValue(initial);
+
+ // Set the range in the native control
+ SetRange(min, max);
+
if ( !value.empty() )
{
SetValue(value);
+ m_oldValue = (int) wxAtol(value);
+ }
+ else
+ {
+ SetValue(wxString::Format(wxT("%d"), initial));
+ m_oldValue = initial;
}
// do it after finishing with m_hwndBuddy creation to avoid generating
// text control is currently empty, the spin button seems to be happy
// to leave it like this, while we really want to always show the
// current value in the control, so do it manually
- ::SetWindowText(GetBuddyHwnd(), wxString::Format(_T("%d"), val));
+ ::SetWindowText(GetBuddyHwnd(),
+ wxString::Format(_T("%d"), val).wx_str());
}
+
+ m_oldValue = GetValue();
}
int wxSpinCtrl::GetValue() const
#endif // wxUSE_TOOLTIPS
// ----------------------------------------------------------------------------
-// event processing
+// events processing and generation
// ----------------------------------------------------------------------------
-void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
+void wxSpinCtrl::SendSpinUpdate(int value)
{
wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, GetId());
event.SetEventObject(this);
- event.SetInt(eventSpin.GetPosition());
+ event.SetInt(value);
(void)GetEventHandler()->ProcessEvent(event);
- if ( eventSpin.GetSkipped() )
+ m_oldValue = value;
+}
+
+void wxSpinCtrl::OnSpinChange(wxSpinEvent& eventSpin)
+{
+ const int value = eventSpin.GetPosition();
+ if ( value != m_oldValue )
{
- event.Skip();
+ SendSpinUpdate(value);
}
}