Allow endless panning

Warp the cursor if it leaves the window while panning, to allow endless motion.
This commit is contained in:
mitxela 2021-01-18 22:07:59 +00:00 committed by Jon Evans
parent b8dfcb34c4
commit 744d745ee5
2 changed files with 158 additions and 41 deletions

View File

@ -176,7 +176,41 @@ void WX_VIEW_CONTROLS::LoadSettings()
void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
bool isAutoPanning = false;
VECTOR2D mousePos( aEvent.GetX(), aEvent.GetY() );
int x = aEvent.GetX();
int y = aEvent.GetY();
VECTOR2D mousePos( x, y );
if( !aEvent.Dragging() &&
( m_settings.m_cursorCaptured || m_settings.m_grabMouse || m_settings.m_autoPanEnabled ) )
{
bool warp = false;
wxSize parentSize = m_parentPanel->GetClientSize();
if( x < 0 )
{
x = 0;
warp = true;
}
else if( x >= parentSize.x )
{
x = parentSize.x - 1;
warp = true;
}
if( y < 0 )
{
y = 0;
warp = true;
}
else if( y >= parentSize.y )
{
y = parentSize.y - 1;
warp = true;
}
if( warp )
m_parentPanel->WarpPointer( x, y );
}
if( m_settings.m_autoPanEnabled && m_settings.m_autoPanSettingEnabled )
isAutoPanning = handleAutoPanning( aEvent );
@ -184,24 +218,92 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
if( !isAutoPanning && aEvent.Dragging() )
{
if( m_state == DRAG_PANNING )
{
static bool justWarped = false;
int warpX = 0;
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
if( x < 0 )
{
warpX = parentSize.x;
}
else if(x >= parentSize.x )
{
warpX = -parentSize.x;
}
if( y < 0 )
{
warpY = parentSize.y;
}
else if( y >= parentSize.y )
{
warpY = -parentSize.y;
}
if( !justWarped )
{
VECTOR2D d = m_dragStartPoint - mousePos;
VECTOR2D delta = m_view->ToWorld( d, false );
m_view->SetCenter( m_lookStartPoint + delta );
aEvent.StopPropagation();
}
if( warpX || warpY )
{
if( !justWarped )
{
m_parentPanel->WarpPointer( x + warpX, y + warpY );
m_dragStartPoint += VECTOR2D( warpX, warpY );
justWarped = true;
}
else
justWarped = false;
}
else
justWarped = false;
}
else if( m_state == DRAG_ZOOMING )
{
VECTOR2D d = m_dragStartPoint - mousePos;
static bool justWarped = false;
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
double scale = 1 + ( d.y * m_settings.m_zoomSpeed * 0.001 );
if( y < 0 )
{
warpY = parentSize.y;
}
else if( y >= parentSize.y )
{
warpY = -parentSize.y;
}
if( !justWarped )
{
VECTOR2D d = m_dragStartPoint - mousePos;
double scale = exp( d.y * m_settings.m_zoomSpeed * 0.001 );
wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) );
m_view->SetScale( m_initialZoomScale * scale, m_view->ToWorld( m_dragStartPoint ) );
m_view->SetScale( m_initialZoomScale * scale, m_view->ToWorld( m_zoomStartPoint ) );
aEvent.StopPropagation();
}
if( warpY )
{
if( !justWarped )
{
m_parentPanel->WarpPointer( x, y + warpY );
m_dragStartPoint += VECTOR2D( 0, warpY );
justWarped = true;
}
else
justWarped = false;
}
else
justWarped = false;
}
}
if( m_updateCursor ) // do not update the cursor position if it was explicitly set
@ -309,13 +411,16 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
m_lookStartPoint = m_view->GetCenter();
m_state = DRAG_PANNING;
m_parentPanel->CaptureMouse();
}
else if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::ZOOM ) ||
( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::ZOOM ) )
{
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
m_zoomStartPoint = m_dragStartPoint;
m_initialZoomScale = m_view->GetScale();
m_state = DRAG_ZOOMING;
m_parentPanel->CaptureMouse();
}
if( aEvent.LeftUp() )
@ -326,7 +431,10 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
case DRAG_ZOOMING:
case DRAG_PANNING:
if( aEvent.MiddleUp() || aEvent.LeftUp() || aEvent.RightUp() )
{
m_state = IDLE;
m_parentPanel->ReleaseMouse();
}
break;
}
@ -364,38 +472,7 @@ void WX_VIEW_CONTROLS::onEnter( wxMouseEvent& aEvent )
void WX_VIEW_CONTROLS::onLeave( wxMouseEvent& aEvent )
{
if( m_settings.m_cursorCaptured )
{
bool warp = false;
int x = aEvent.GetX();
int y = aEvent.GetY();
wxSize parentSize = m_parentPanel->GetClientSize();
if( x < 0 )
{
x = 0;
warp = true;
}
else if( x >= parentSize.x )
{
x = parentSize.x - 1;
warp = true;
}
if( y < 0 )
{
y = 0;
warp = true;
}
else if( y >= parentSize.y )
{
y = parentSize.y - 1;
warp = true;
}
if( warp )
m_parentPanel->WarpPointer( x, y );
}
}
@ -514,6 +591,28 @@ void WX_VIEW_CONTROLS::SetGrabMouse( bool aEnabled )
}
void WX_VIEW_CONTROLS::CaptureCursor( bool aEnabled )
{
if( aEnabled && !m_settings.m_cursorCaptured )
m_parentPanel->CaptureMouse();
else if( !aEnabled && m_settings.m_cursorCaptured )
m_parentPanel->ReleaseMouse();
VIEW_CONTROLS::CaptureCursor( aEnabled );
}
void WX_VIEW_CONTROLS::SetAutoPan( bool aEnabled )
{
if( aEnabled && !m_settings.m_autoPanEnabled )
m_parentPanel->CaptureMouse();
else if( !aEnabled && m_settings.m_autoPanEnabled )
m_parentPanel->ReleaseMouse();
VIEW_CONTROLS::SetAutoPan( aEnabled );
}
VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
{
wxPoint msp = getMouseScreenPosition();

View File

@ -72,6 +72,21 @@ public:
*/
void SetGrabMouse( bool aEnabled ) override;
/**
* Force the cursor to stay within the drawing panel area.
*
* @param aEnabled determines if the cursor should be captured.
*/
void CaptureCursor( bool aEnabled ) override;
/**
* Turn on/off auto panning (this feature is used when there is a tool active (eg. drawing a
* track) and user moves mouse to the VIEW edge - then the view can be translated or not).
*
* @param aEnabled tells if the autopanning should be active.
*/
void SetAutoPan( bool aEnabled ) override;
///< @copydoc VIEW_CONTROLS::GetMousePosition()
VECTOR2D GetMousePosition( bool aWorldCoordinates = true ) const override;
@ -169,6 +184,9 @@ private:
///< The zoom scale when a drag zoom started.
double m_initialZoomScale;
///< The mouse position when a drag zoom started.
VECTOR2D m_zoomStartPoint;
#ifdef __WXGTK3__
///< Last event timestamp used to de-bounce mouse wheel.
long int m_lastTimestamp;