diff --git a/common/view/wx_view_controls.cpp b/common/view/wx_view_controls.cpp index 7427cef764..385841d8af 100644 --- a/common/view/wx_view_controls.cpp +++ b/common/view/wx_view_controls.cpp @@ -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 ); @@ -185,22 +219,90 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent ) { if( m_state == DRAG_PANNING ) { - VECTOR2D d = m_dragStartPoint - mousePos; - VECTOR2D delta = m_view->ToWorld( d, false ); + static bool justWarped = false; + int warpX = 0; + int warpY = 0; + wxSize parentSize = m_parentPanel->GetClientSize(); - m_view->SetCenter( m_lookStartPoint + delta ); - aEvent.StopPropagation(); + 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; + } - wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) ); + if( !justWarped ) + { + VECTOR2D d = m_dragStartPoint - mousePos; + double scale = exp( d.y * m_settings.m_zoomSpeed * 0.001 ); - m_view->SetScale( m_initialZoomScale * scale, m_view->ToWorld( m_dragStartPoint ) ); - aEvent.StopPropagation(); + wxLogTrace( traceZoomScroll, wxString::Format( "dy: %f scale: %f", d.y, scale ) ); + + 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; } } @@ -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(); diff --git a/include/view/wx_view_controls.h b/include/view/wx_view_controls.h index 58711c4e12..6b98844ca6 100644 --- a/include/view/wx_view_controls.h +++ b/include/view/wx_view_controls.h @@ -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;