X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/f7dd07f64d344e5b84c8dbe278ce4ad9da2a3c67..404b319a85dadd7decf7a5a5331020520031a41c:/src/msw/spinctrl.cpp?ds=sidebyside diff --git a/src/msw/spinctrl.cpp b/src/msw/spinctrl.cpp index 71c1221f49..a034cda2ee 100644 --- a/src/msw/spinctrl.cpp +++ b/src/msw/spinctrl.cpp @@ -298,6 +298,10 @@ bool wxSpinCtrl::Create(wxWindow *parent, WXDWORD exStyle = 0; WXDWORD msStyle = MSWGetStyle(GetWindowStyle(), & exStyle) ; + // Scroll text automatically if there is not enough space to show all of + // it, this is better than not allowing to enter more digits at all. + msStyle |= ES_AUTOHSCROLL; + // propagate text alignment style to text ctrl if ( style & wxALIGN_RIGHT ) msStyle |= ES_RIGHT; @@ -389,22 +393,24 @@ bool wxSpinCtrl::Create(wxWindow *parent, // associate the text window with the spin button (void)::SendMessage(GetHwnd(), UDM_SETBUDDY, (WPARAM)m_hwndBuddy, 0); - SetValue(initial); + // If the initial text value is actually a number, it overrides the + // "initial" argument specified later. + long initialFromText; + if ( value.ToLong(&initialFromText) ) + initial = initialFromText; - // Set the range in the native control + // Set the range in the native control: notice that we must do it before + // calling SetValue() to use the correct validity checks for the initial + // value. SetRange(min, max); + SetValue(initial); - // If necessary, set the textual value. Don't do it if it's the same as the - // numeric value though. - if ( value != wxString::Format("%d", initial) ) - { + // Also set the text part of the control if it was specified independently + // but don't generate an event for this, it would be unexpected. + m_blockEvent = true; + if ( !value.empty() ) SetValue(value); - m_oldValue = (int) wxAtol(value); - } - else - { - m_oldValue = initial; - } + m_blockEvent = false; return true; } @@ -418,6 +424,27 @@ wxSpinCtrl::~wxSpinCtrl() gs_spinForTextCtrl.erase(GetBuddyHwnd()); } +// ---------------------------------------------------------------------------- +// wxSpinCtrl-specific methods +// ---------------------------------------------------------------------------- + +int wxSpinCtrl::GetBase() const +{ + return ::SendMessage(GetHwnd(), UDM_GETBASE, 0, 0); +} + +bool wxSpinCtrl::SetBase(int base) +{ + if ( !::SendMessage(GetHwnd(), UDM_SETBASE, base, 0) ) + return false; + + // Whether we need to be able enter "x" or not influences whether we should + // use ES_NUMBER for the buddy control. + UpdateBuddyStyle(); + + return true; +} + // ---------------------------------------------------------------------------- // wxTextCtrl-like methods // ---------------------------------------------------------------------------- @@ -436,16 +463,28 @@ void wxSpinCtrl::SetValue(int val) wxSpinButton::SetValue(val); - // normally setting the value of the spin button is enough as it updates - // its buddy control automatically ... - if ( wxGetWindowText(m_hwndBuddy).empty() ) + // Normally setting the value of the spin button is enough as it updates + // its buddy control automatically but in a couple of situations it doesn't + // do it, for whatever reason, do it explicitly then: + const wxString text = wxGetWindowText(m_hwndBuddy); + + // First case is when the text control is empty and the value is 0: the + // spin button just leaves it empty in this case, while we want to show 0 + // in it. + if ( text.empty() && !val ) + { + ::SetWindowText(GetBuddyHwnd(), wxT("0")); + } + + // Another one is when we're using hexadecimal base but the user input + // doesn't start with "0x" -- we prefer to show it to avoid ambiguity + // between decimal and hexadecimal. + if ( GetBase() == 16 && + (text.length() < 3 || text[0] != '0' || + (text[1] != 'x' && text[1] != 'X')) ) { - // ... but sometimes it doesn't, notably when the value is 0 and the - // 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(wxT("%d"), val).wx_str()); + wxPrivate::wxSpinCtrlFormatAsHex(val, m_max).t_str()); } m_oldValue = GetValue(); @@ -455,10 +494,10 @@ void wxSpinCtrl::SetValue(int val) int wxSpinCtrl::GetValue() const { - wxString val = wxGetWindowText(m_hwndBuddy); + const wxString val = wxGetWindowText(m_hwndBuddy); long n; - if ( (wxSscanf(val, wxT("%ld"), &n) != 1) ) + if ( !val.ToLong(&n, GetBase()) ) n = INT_MIN; if ( n < m_min ) @@ -487,14 +526,29 @@ void wxSpinCtrl::SetSelection(long from, long to) void wxSpinCtrl::SetRange(int minVal, int maxVal) { + // Manually adjust the old value to avoid an event being sent from + // NormalizeValue() called from inside the base class SetRange() as we're + // not supposed to generate any events from here. + if ( m_oldValue < minVal ) + m_oldValue = minVal; + else if ( m_oldValue > maxVal ) + m_oldValue = maxVal; + wxSpinButton::SetRange(minVal, maxVal); + UpdateBuddyStyle(); +} + +void wxSpinCtrl::UpdateBuddyStyle() +{ // this control is used for numeric entry so restrict the input to numeric // keys only -- but only if we don't need to be able to enter "-" in it as - // otherwise this would become impossible + // otherwise this would become impossible and also if we don't use + // hexadecimal as entering "x" of the "0x" prefix wouldn't be allowed + // neither then const DWORD styleOld = ::GetWindowLong(GetBuddyHwnd(), GWL_STYLE); DWORD styleNew; - if ( minVal < 0 ) + if ( m_min < 0 || GetBase() != 10 ) styleNew = styleOld & ~ES_NUMBER; else styleNew = styleOld | ES_NUMBER; @@ -625,7 +679,7 @@ void wxSpinCtrl::SendSpinUpdate(int value) } bool wxSpinCtrl::MSWOnScroll(int WXUNUSED(orientation), WXWORD wParam, - WXWORD pos, WXHWND control) + WXWORD WXUNUSED(pos), WXHWND control) { wxCHECK_MSG( control, false, wxT("scrolling what?") ); @@ -635,11 +689,13 @@ bool wxSpinCtrl::MSWOnScroll(int WXUNUSED(orientation), WXWORD wParam, return false; } - int new_value = (short) pos; + // Notice that we can't use "pos" from WM_VSCROLL as it is 16 bit and we + // might be using 32 bit range. + int new_value = GetValue(); if (m_oldValue != new_value) SendSpinUpdate( new_value ); - return TRUE; + return true; } bool wxSpinCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *result) @@ -660,26 +716,29 @@ bool wxSpinCtrl::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM *re // ---------------------------------------------------------------------------- wxSize wxSpinCtrl::DoGetBestSize() const +{ + return DoGetSizeFromTextSize(DEFAULT_ITEM_WIDTH); +} + +wxSize wxSpinCtrl::DoGetSizeFromTextSize(int xlen, int ylen) const { wxSize sizeBtn = wxSpinButton::DoGetBestSize(); - sizeBtn.x += DEFAULT_ITEM_WIDTH + MARGIN_BETWEEN; int y; wxGetCharSize(GetHWND(), NULL, &y, GetFont()); - y = EDIT_HEIGHT_FROM_CHAR_HEIGHT(y); - // JACS: we should always use the height calculated // from above, because otherwise we'll get a spin control // that's too big. So never use the height calculated // from wxSpinButton::DoGetBestSize(). - // if ( sizeBtn.y < y ) - { - // make the text tall enough - sizeBtn.y = y; - } + wxSize tsize(xlen + sizeBtn.x + MARGIN_BETWEEN + 0.3 * y + 10, + EDIT_HEIGHT_FROM_CHAR_HEIGHT(y)); + + // Check if the user requested a non-standard height. + if ( ylen > 0 ) + tsize.IncBy(0, ylen - y); - return sizeBtn; + return tsize; } void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height)