From 8a337f95d82671e8f94809a49687d2c18d316e39 Mon Sep 17 00:00:00 2001 From: Jaakko Salli Date: Tue, 2 Dec 2008 18:39:40 +0000 Subject: [PATCH] Implement ability to rapidly change spin value of SpinCtrl property editor by moving mouse while one of the spin buttons is depressed git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@57076 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- samples/propgrid/propgrid.cpp | 2 +- src/propgrid/advprops.cpp | 126 +++++++++++++++++++++++++++++++++- 2 files changed, 126 insertions(+), 2 deletions(-) diff --git a/samples/propgrid/propgrid.cpp b/samples/propgrid/propgrid.cpp index e8e320529f..46baf1c55c 100644 --- a/samples/propgrid/propgrid.cpp +++ b/samples/propgrid/propgrid.cpp @@ -1369,7 +1369,7 @@ void FormMain::PopulateWithExamples () pg->SetPropertyEditor( wxT("SpinCtrl"), wxPGEditor_SpinCtrl ); pg->SetPropertyAttribute( wxT("SpinCtrl"), wxPG_ATTR_MIN, (long)-10 ); // Use constants instead of string - pg->SetPropertyAttribute( wxT("SpinCtrl"), wxPG_ATTR_MAX, (long)10 ); // for reduced binary size. + pg->SetPropertyAttribute( wxT("SpinCtrl"), wxPG_ATTR_MAX, (long)16384 ); // for reduced binary size. pg->SetPropertyAttribute( wxT("SpinCtrl"), wxT("Step"), (long)2 ); //pg->SetPropertyAttribute( wxT("SpinCtrl"), wxT("Wrap"), true ); diff --git a/src/propgrid/advprops.cpp b/src/propgrid/advprops.cpp index dac42ea320..32eff3b0a7 100644 --- a/src/propgrid/advprops.cpp +++ b/src/propgrid/advprops.cpp @@ -108,6 +108,116 @@ bool operator == (const wxArrayInt& array1, const wxArrayInt& array2) #if wxUSE_SPINBTN +// +// This class implements ability to rapidly change "spin" value +// by moving mouse when one of the spin buttons is depressed. +class wxPGSpinButton : public wxSpinButton +{ +public: + wxPGSpinButton() : wxSpinButton() + { + m_bLeftDown = false; + m_hasCapture = false; + m_spins = 1; + + Connect( wxEVT_LEFT_DOWN, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_LEFT_UP, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_MOTION, + wxMouseEventHandler(wxPGSpinButton::OnMouseEvent) ); + Connect( wxEVT_MOUSE_CAPTURE_LOST, + wxMouseCaptureLostEventHandler(wxPGSpinButton::OnMouseCaptureLost) ); + } + + int GetSpins() const + { + return m_spins; + } + +private: + wxPoint m_ptPosition; + + // Having a separate spins variable allows us to handle validation etc. for + // multiple spin events at once (with quick mouse movements there could be + // hundreds of 'spins' being done at once). Technically things like this + // should be stored in event (wxSpinEvent in this case), but there probably + // isn't anything there that can be reliably reused. + int m_spins; + + bool m_bLeftDown; + + // SpinButton seems to be a special for mouse capture, so we may need track + // privately whether mouse is actually captured. + bool m_hasCapture; + + void Capture() + { + if ( !m_hasCapture ) + { + CaptureMouse(); + m_hasCapture = true; + } + + SetCursor(wxCURSOR_SIZENS); + } + void Release() + { + m_bLeftDown = false; + + if ( m_hasCapture ) + { + ReleaseMouse(); + m_hasCapture = false; + } + + wxWindow *parent = GetParent(); + if ( parent ) + SetCursor(parent->GetCursor()); + else + SetCursor(wxNullCursor); + } + + void OnMouseEvent(wxMouseEvent& event) + { + if ( event.GetEventType() == wxEVT_LEFT_DOWN ) + { + m_bLeftDown = true; + m_ptPosition = event.GetPosition(); + } + else if ( event.GetEventType() == wxEVT_LEFT_UP ) + { + Release(); + m_bLeftDown = false; + } + else if ( event.GetEventType() == wxEVT_MOTION ) + { + if ( m_bLeftDown ) + { + Capture(); + int dy = m_ptPosition.y - event.GetPosition().y; + m_ptPosition = event.GetPosition(); + + wxSpinEvent evtscroll( (dy >= 0) ? wxEVT_SCROLL_LINEUP : + wxEVT_SCROLL_LINEDOWN, + GetId() ); + evtscroll.SetEventObject(this); + + m_spins = abs(dy); + GetEventHandler()->ProcessEvent(evtscroll); + m_spins = 1; + } + } + + event.Skip(); + } + void OnMouseCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) + { + Release(); + } +}; + + WX_PG_IMPLEMENT_INTERNAL_EDITOR_CLASS(SpinCtrl, wxPGSpinCtrlEditor, wxPGEditor) @@ -128,7 +238,10 @@ wxPGWindowList wxPGSpinCtrlEditor::CreateControls( wxPropertyGrid* propgrid, wxP wxSize tcSz(sz.x - butSz.x - margin, sz.y); wxPoint butPos(pos.x + tcSz.x + margin, pos.y); - wxSpinButton* wnd2 = new wxSpinButton(); + wxSpinButton* wnd2; + + wnd2 = new wxPGSpinButton(); + #ifdef __WXMSW__ wnd2->Hide(); #endif @@ -152,6 +265,7 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper { int evtType = event.GetEventType(); int keycode = -1; + int spins = 1; bool bigStep = false; if ( evtType == wxEVT_KEY_DOWN ) @@ -177,6 +291,12 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( evtType == wxEVT_SCROLL_LINEUP || evtType == wxEVT_SCROLL_LINEDOWN ) { + wxPGSpinButton* spinButton = + (wxPGSpinButton*) propgrid->GetEditorControlSecondary(); + + if ( spinButton ) + spins = spinButton->GetSpins(); + wxString s; // Can't use wnd since it might be clipper window wxTextCtrl* tc = wxDynamicCast(propgrid->GetEditorControl(), wxTextCtrl); @@ -202,6 +322,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10.0; + step *= (double) spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_d += step; else v_d -= step; @@ -226,6 +348,8 @@ bool wxPGSpinCtrlEditor::OnEvent( wxPropertyGrid* propgrid, wxPGProperty* proper if ( bigStep ) step *= 10; + step *= spins; + if ( evtType == wxEVT_SCROLL_LINEUP ) v_ll += step; else v_ll -= step;