X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a842a96e24cff3d4448fbdb6c2e94dd9f4ad54da..ac2153a686f20f68038395ab4734161e31eb01c5:/src/mac/carbon/spinctrl.cpp?ds=sidebyside diff --git a/src/mac/carbon/spinctrl.cpp b/src/mac/carbon/spinctrl.cpp index 54384ccb1c..22553d47f1 100644 --- a/src/mac/carbon/spinctrl.cpp +++ b/src/mac/carbon/spinctrl.cpp @@ -14,28 +14,320 @@ #include "wx/defs.h" +#ifndef WX_PRECOMP + #include "wx/textctrl.h" +#endif //WX_PRECOMP + #if wxUSE_SPINCTRL +#include "wx/spinbutt.h" #include "wx/spinctrl.h" -//----------------------------------------------------------------------------- -// wxSpinCtrl -//----------------------------------------------------------------------------- +#include "wx/spinctrl.h" + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- -#if wxUSE_SPINBTN +// the margin between the text control and the spin +static const wxCoord MARGIN = 2; -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl,wxControl) -#endif +// ---------------------------------------------------------------------------- +// wxSpinCtrlText: text control used by spin control +// ---------------------------------------------------------------------------- + +class wxSpinCtrlText : public wxTextCtrl +{ +public: + wxSpinCtrlText(wxSpinCtrl *spin, const wxString& value) + : wxTextCtrl(spin , -1, value) + { + m_spin = spin; + } + +protected: + void OnTextChange(wxCommandEvent& event) + { + int val; + if ( m_spin->GetTextValue(&val) ) + { + m_spin->GetSpinButton()->SetValue(val); + } + + event.Skip(); + } + + bool ProcessEvent(wxEvent &event) + { + // Hand button down events to wxSpinCtrl. Doesn't work. + if (event.GetEventType() == wxEVT_LEFT_DOWN && m_spin->ProcessEvent( event )) + return TRUE; + + return wxTextCtrl::ProcessEvent( event ); + } + +private: + wxSpinCtrl *m_spin; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxSpinCtrlText, wxTextCtrl) + EVT_TEXT(-1, wxSpinCtrlText::OnTextChange) +END_EVENT_TABLE() + +// ---------------------------------------------------------------------------- +// wxSpinCtrlButton: spin button used by spin control +// ---------------------------------------------------------------------------- + +class wxSpinCtrlButton : public wxSpinButton +{ +public: + wxSpinCtrlButton(wxSpinCtrl *spin, int style) + : wxSpinButton(spin ) + { + m_spin = spin; + + SetWindowStyle(style | wxSP_VERTICAL); + } -#else // !wxUSE_SPINBTN +protected: + void OnSpinButton(wxSpinEvent& eventSpin) + { +#if defined(__WXMAC__) || defined(__WXMOTIF__) + m_spin->SetTextValue(eventSpin.GetPosition()); -#if !USE_SHARED_LIBRARY - IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl,wxTextCtrl) + wxCommandEvent event(wxEVT_COMMAND_SPINCTRL_UPDATED, m_spin->GetId()); + event.SetEventObject(m_spin); + event.SetInt(eventSpin.GetPosition()); + + m_spin->GetEventHandler()->ProcessEvent(event); +#else + m_spin->SetTextValue(eventSpin.GetPosition()); + eventSpin.Skip(); #endif + } + +private: + wxSpinCtrl *m_spin; + + DECLARE_EVENT_TABLE() +}; + +BEGIN_EVENT_TABLE(wxSpinCtrlButton, wxSpinButton) + EVT_SPIN(-1, wxSpinCtrlButton::OnSpinButton) +END_EVENT_TABLE() + +IMPLEMENT_DYNAMIC_CLASS(wxSpinCtrl, wxControl) + +// ============================================================================ +// implementation +// ============================================================================ + +// ---------------------------------------------------------------------------- +// wxSpinCtrl creation +// ---------------------------------------------------------------------------- + +void wxSpinCtrl::Init() +{ + m_text = NULL; + m_btn = NULL; +} + +bool wxSpinCtrl::Create(wxWindow *parent, + wxWindowID id, + const wxString& value, + const wxPoint& pos, + const wxSize& size, + long style, + int min, + int max, + int initial, + const wxString& name) +{ + if ( !wxControl::Create(parent, id, wxDefaultPosition, wxDefaultSize, style, + wxDefaultValidator, name) ) + { + return FALSE; + } + + // the string value overrides the numeric one (for backwards compatibility + // reasons and also because it is simpler to satisfy the string value which + // comes much sooner in the list of arguments and leave the initial + // parameter unspecified) + if ( !value.empty() ) + { + long l; + if ( value.ToLong(&l) ) + initial = l; + } + + wxSize csize = size ; + m_text = new wxSpinCtrlText(this, value); + m_btn = new wxSpinCtrlButton(this, style); + + m_btn->SetRange(min, max); + m_btn->SetValue(initial); + + if ( size.y == -1 ) { + csize.y = m_text->GetSize().y ; + } + DoSetSize(pos.x , pos.y , csize.x, csize.y); + + return TRUE; +} + +wxSpinCtrl::~wxSpinCtrl() +{ + // delete the controls now, don't leave them alive even though they would + // still be eventually deleted by our parent - but it will be too late, the + // user code expects them to be gone now + delete m_text; + m_text = NULL ; + delete m_btn; + m_btn = NULL ; +} + +// ---------------------------------------------------------------------------- +// geometry +// ---------------------------------------------------------------------------- + +wxSize wxSpinCtrl::DoGetBestSize() const +{ + wxSize sizeBtn = m_btn->GetBestSize(), + sizeText = m_text->GetBestSize(); + + return wxSize(sizeBtn.x + sizeText.x + MARGIN, sizeText.y); +} + +void wxSpinCtrl::DoMoveWindow(int x, int y, int width, int height) +{ + wxControl::DoMoveWindow(x, y, width, height); + + // position the subcontrols inside the client area + wxSize sizeBtn = m_btn->GetSize(); + + wxCoord wText = width - sizeBtn.x; + m_text->SetSize(0, 0, wText, height); + m_btn->SetSize(0 + wText + MARGIN, 0, -1, -1); +} + +// ---------------------------------------------------------------------------- +// operations forwarded to the subcontrols +// ---------------------------------------------------------------------------- + +bool wxSpinCtrl::Enable(bool enable) +{ + if ( !wxControl::Enable(enable) ) + return FALSE; + return TRUE; +} + +bool wxSpinCtrl::Show(bool show) +{ + if ( !wxControl::Show(show) ) + return FALSE; + return TRUE; +} + +// ---------------------------------------------------------------------------- +// value and range access +// ---------------------------------------------------------------------------- + +bool wxSpinCtrl::GetTextValue(int *val) const +{ + long l; + if ( !m_text->GetValue().ToLong(&l) ) + { + // not a number at all + return FALSE; + } + + if ( l < GetMin() || l > GetMax() ) + { + // out of range + return FALSE; + } + + *val = l; + + return TRUE; +} + +int wxSpinCtrl::GetValue() const +{ + return m_btn ? m_btn->GetValue() : 0; +} + +int wxSpinCtrl::GetMin() const +{ + return m_btn ? m_btn->GetMin() : 0; +} + +int wxSpinCtrl::GetMax() const +{ + return m_btn ? m_btn->GetMax() : 0; +} + +// ---------------------------------------------------------------------------- +// changing value and range +// ---------------------------------------------------------------------------- + +void wxSpinCtrl::SetTextValue(int val) +{ + wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetTextValue") ); + + m_text->SetValue(wxString::Format(_T("%d"), val)); + + // select all text + m_text->SetSelection(0, -1); + + // and give focus to the control! + // m_text->SetFocus(); Why???? TODO. +} + +void wxSpinCtrl::SetValue(int val) +{ + wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetValue") ); + + SetTextValue(val); + + m_btn->SetValue(val); +} + +void wxSpinCtrl::SetValue(const wxString& text) +{ + wxCHECK_RET( m_text, _T("invalid call to wxSpinCtrl::SetValue") ); + + long val; + if ( text.ToLong(&val) && ((val > INT_MIN) && (val < INT_MAX)) ) + { + SetValue((int)val); + } + else // not a number at all or out of range + { + m_text->SetValue(text); + m_text->SetSelection(0, -1); + } +} + +void wxSpinCtrl::SetRange(int min, int max) +{ + wxCHECK_RET( m_btn, _T("invalid call to wxSpinCtrl::SetRange") ); -#endif // wxUSE_SPINBTN/!wxUSE_SPINBTN + m_btn->SetRange(min, max); +} -#endif // wxUSE_SPINCTRL +void wxSpinCtrl::SetSelection(long from, long to) +{ + // if from and to are both -1, it means (in wxWindows) that all text should + // be selected + if ( (from == -1) && (to == -1) ) + { + from = 0; + } + m_text->SetSelection(from, to); +} +#endif // wxUSE_SPINCTRL