X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/eeea41abbcda4a2078014dc12f9d48242a21df89..0a4090e635a3765e62181ecf039914c2c27df63c:/src/msw/spinctrl.cpp?ds=inline diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index da8bb856f6..1b9910d66f 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/spinctrl.cpp +// Name: src/msw/spinctrl.cpp // Purpose: wxSpinCtrl class implementation for Win32 // Author: Vadim Zeitlin // Modified by: @@ -24,15 +24,18 @@ #pragma hdrstop #endif -#ifndef WX_PRECOMP - #include "wx/wx.h" -#endif - #if wxUSE_SPINCTRL #include "wx/spinctrl.h" + +#ifndef WX_PRECOMP + #include "wx/msw/wrapcctl.h" // include "properly" + #include "wx/event.h" + #include "wx/textctrl.h" + #include "wx/wxcrtvararg.h" +#endif + #include "wx/msw/private.h" -#include "wx/msw/wrapcctl.h" #if wxUSE_TOOLTIPS #include "wx/tooltip.h" @@ -85,7 +88,7 @@ wxEND_FLAGS( wxSpinCtrlStyle ) 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 ) @@ -109,7 +112,6 @@ wxCONSTRUCTOR_6( wxSpinCtrl , wxWindow* , Parent , wxWindowID , Id , wxString , IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl) #endif -//pmg EVT_KILL_FOCUS BEGIN_EVENT_TABLE(wxSpinCtrl, wxSpinButton) EVT_CHAR(wxSpinCtrl::OnChar) @@ -198,28 +200,14 @@ wxSpinCtrl *wxSpinCtrl::GetSpinForTextCtrl(WXHWND hwndBuddy) // process a WM_COMMAND generated by the buddy text control bool wxSpinCtrl::ProcessTextCommand(WXWORD cmd, WXWORD WXUNUSED(id)) { - switch (cmd) + if ( cmd == EN_CHANGE ) { - case EN_CHANGE: - { - wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId()); - event.SetEventObject(this); - wxString val = wxGetWindowText(m_hwndBuddy); - event.SetString(val); - event.SetInt(GetValue()); - return GetEventHandler()->ProcessEvent(event); - } - case EN_SETFOCUS: - case EN_KILLFOCUS: - { - wxFocusEvent event(cmd == EN_KILLFOCUS ? wxEVT_KILL_FOCUS - : wxEVT_SET_FOCUS, - m_windowId); - event.SetEventObject( this ); - return GetEventHandler()->ProcessEvent(event); - } - default: - break; + wxCommandEvent event(wxEVT_COMMAND_TEXT_UPDATED, GetId()); + event.SetEventObject(this); + wxString val = wxGetWindowText(m_hwndBuddy); + event.SetString(val); + event.SetInt(GetValue()); + return GetEventHandler()->ProcessEvent(event); } // not processed @@ -265,8 +253,8 @@ void wxSpinCtrl::OnChar(wxKeyEvent& event) void wxSpinCtrl::OnKillFocus(wxFocusEvent& event) { - // ensure that the value is shown correctly - SetValue(GetValue()) ; + // ensure that a correct value is shown by the control + NormalizeValue(); event.Skip(); } @@ -279,6 +267,22 @@ void wxSpinCtrl::OnSetFocus(wxFocusEvent& event) 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 // ---------------------------------------------------------------------------- @@ -292,6 +296,11 @@ bool wxSpinCtrl::Create(wxWindow *parent, 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) @@ -309,7 +318,12 @@ bool wxSpinCtrl::Create(wxWindow *parent, WXDWORD exStyle = 0; WXDWORD msStyle = MSWGetStyle(GetWindowStyle(), & exStyle) ; - // calculate the sizes: the size given is the toal size for both controls + // this control is used for numeric entry so normally using these flags by + // default shouldn't be a problem, if it is we can always add a style such + // as wxSP_NON_NUMERIC later + msStyle |= ES_RIGHT | ES_NUMBER; + + // calculate the sizes: the size given is the total size for both controls // and we need to fit them both in the given width (height is the same) wxSize sizeText(size), sizeBtn(size); sizeBtn.x = wxSpinButton::DoGetBestSize().x; @@ -364,8 +378,7 @@ bool wxSpinCtrl::Create(wxWindow *parent, 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); @@ -387,16 +400,27 @@ bool wxSpinCtrl::Create(wxWindow *parent, 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 @@ -443,8 +467,11 @@ void wxSpinCtrl::SetValue(int val) // 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("%ld"), val)); + ::SetWindowText(GetBuddyHwnd(), + wxString::Format(_T("%d"), val).wx_str()); } + + m_oldValue = GetValue(); } int wxSpinCtrl::GetValue() const @@ -535,20 +562,26 @@ void wxSpinCtrl::DoSetToolTip(wxToolTip *tip) #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); } } @@ -622,4 +655,3 @@ void wxSpinCtrl::DoGetPosition(int *x, int *y) const } #endif // wxUSE_SPINCTRL -