Allow panning with selectable key

Add optins to mouse dialog to allow modifier key-based mouse movement
panning

Fixes https://gitlab.com/kicad/code/kicad/-/issues/2492
This commit is contained in:
Seth Hillbrand 2025-08-11 13:18:18 -07:00
parent 833a5ee3ab
commit a7e6fa8198
11 changed files with 291 additions and 82 deletions

View File

@ -111,6 +111,14 @@ bool PANEL_MOUSE_SETTINGS::TransferDataFromWindow()
default: break;
}
switch( m_choicePanMoveKey->GetSelection() )
{
case 1: cfg->m_Input.motion_pan_modifier = WXK_ALT; break;
case 2: cfg->m_Input.motion_pan_modifier = WXK_CONTROL; break;
case 3: cfg->m_Input.motion_pan_modifier = WXK_SHIFT; break;
default: cfg->m_Input.motion_pan_modifier = 0; break;
}
cfg->m_Input.center_on_zoom = m_checkZoomCenter->GetValue();
cfg->m_Input.auto_pan = m_checkAutoPan->GetValue();
cfg->m_Input.auto_pan_acceleration = m_autoPanSpeed->GetValue();
@ -178,6 +186,14 @@ void PANEL_MOUSE_SETTINGS::applySettingsToPanel( const COMMON_SETTINGS& aSetting
default: break;
}
switch( aSettings.m_Input.motion_pan_modifier )
{
case WXK_ALT: m_choicePanMoveKey->SetSelection( 1 ); break;
case WXK_CONTROL: m_choicePanMoveKey->SetSelection( 2 ); break;
case WXK_SHIFT: m_choicePanMoveKey->SetSelection( 3 ); break;
default: m_choicePanMoveKey->SetSelection( 0 ); break;
}
m_currentScrollMod.zoom = aSettings.m_Input.scroll_modifier_zoom;
m_currentScrollMod.panh = aSettings.m_Input.scroll_modifier_pan_h;
m_currentScrollMod.panv = aSettings.m_Input.scroll_modifier_pan_v;

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -156,6 +156,19 @@ PANEL_MOUSE_SETTINGS_BASE::PANEL_MOUSE_SETTINGS_BASE( wxWindow* parent, wxWindow
fgSizer1->Add( m_choiceRightButtonDrag, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 );
m_panMoveKeyLabel = new wxStaticText( this, wxID_ANY, _("Pan on mouse movement with key:"), wxDefaultPosition, wxDefaultSize, 0 );
m_panMoveKeyLabel->Wrap( -1 );
fgSizer1->Add( m_panMoveKeyLabel, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT, 5 );
wxString m_choicePanMoveKeyChoices[] = { _("None"), _("Alt"), _("Ctrl"), _("Shift") };
int m_choicePanMoveKeyNChoices = sizeof( m_choicePanMoveKeyChoices ) / sizeof( wxString );
m_choicePanMoveKey = new wxChoice( this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_choicePanMoveKeyNChoices, m_choicePanMoveKeyChoices, 0 );
m_choicePanMoveKey->SetSelection( 0 );
fgSizer1->Add( m_choicePanMoveKey, 0, wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT, 5 );
fgSizer1->Add( 0, 0, 1, wxEXPAND, 5 );

View File

@ -934,11 +934,11 @@
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<object class="sizeritem" expanded="true">
<property name="border">5</property>
<property name="flag">wxEXPAND|wxALL</property>
<property name="proportion">1</property>
<object class="wxFlexGridSizer" expanded="false">
<object class="wxFlexGridSizer" expanded="true">
<property name="cols">3</property>
<property name="flexible_direction">wxHORIZONTAL</property>
<property name="growablecols">2</property>
@ -1361,6 +1361,143 @@
<property name="width">0</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxStaticText" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="label">Pan on mouse movement with key:</property>
<property name="markup">0</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_panMoveKeyLabel</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
<property name="wrap">-1</property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxALIGN_CENTER_VERTICAL|wxBOTTOM|wxEXPAND|wxLEFT|wxRIGHT</property>
<property name="proportion">0</property>
<object class="wxChoice" expanded="false">
<property name="BottomDockable">1</property>
<property name="LeftDockable">1</property>
<property name="RightDockable">1</property>
<property name="TopDockable">1</property>
<property name="aui_layer">0</property>
<property name="aui_name"></property>
<property name="aui_position">0</property>
<property name="aui_row">0</property>
<property name="best_size"></property>
<property name="bg"></property>
<property name="caption"></property>
<property name="caption_visible">1</property>
<property name="center_pane">0</property>
<property name="choices">&quot;None&quot; &quot;Alt&quot; &quot;Ctrl&quot; &quot;Shift&quot;</property>
<property name="close_button">1</property>
<property name="context_help"></property>
<property name="context_menu">1</property>
<property name="default_pane">0</property>
<property name="dock">Dock</property>
<property name="dock_fixed">0</property>
<property name="docking">Left</property>
<property name="drag_accept_files">0</property>
<property name="enabled">1</property>
<property name="fg"></property>
<property name="floatable">1</property>
<property name="font"></property>
<property name="gripper">0</property>
<property name="hidden">0</property>
<property name="id">wxID_ANY</property>
<property name="max_size"></property>
<property name="maximize_button">0</property>
<property name="maximum_size"></property>
<property name="min_size"></property>
<property name="minimize_button">0</property>
<property name="minimum_size"></property>
<property name="moveable">1</property>
<property name="name">m_choicePanMoveKey</property>
<property name="pane_border">1</property>
<property name="pane_position"></property>
<property name="pane_size"></property>
<property name="permission">protected</property>
<property name="pin_button">1</property>
<property name="pos"></property>
<property name="resize">Resizable</property>
<property name="selection">0</property>
<property name="show">1</property>
<property name="size"></property>
<property name="style"></property>
<property name="subclass">; ; forward_declare</property>
<property name="toolbar_pane">0</property>
<property name="tooltip"></property>
<property name="validator_data_type"></property>
<property name="validator_style">wxFILTER_NONE</property>
<property name="validator_type">wxDefaultValidator</property>
<property name="validator_variable"></property>
<property name="window_extra_style"></property>
<property name="window_name"></property>
<property name="window_style"></property>
</object>
</object>
<object class="sizeritem" expanded="false">
<property name="border">5</property>
<property name="flag">wxEXPAND</property>
<property name="proportion">1</property>
<object class="spacer" expanded="false">
<property name="height">0</property>
<property name="permission">protected</property>
<property name="width">0</property>
</object>
</object>
</object>
</object>
</object>

View File

@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6)
// C++ code generated with wxFormBuilder (version 4.2.1-0-g80c4cb6a-dirty)
// http://www.wxformbuilder.org/
//
// PLEASE DO *NOT* EDIT THIS FILE!
@ -61,6 +61,8 @@ class PANEL_MOUSE_SETTINGS_BASE : public RESETTABLE_PANEL
wxChoice* m_choiceMiddleButtonDrag;
wxStaticText* m_staticText31;
wxChoice* m_choiceRightButtonDrag;
wxStaticText* m_panMoveKeyLabel;
wxChoice* m_choicePanMoveKey;
wxStaticText* m_scrollLabel;
wxStaticLine* m_staticline2;
wxStaticText* m_staticText21;

View File

@ -716,6 +716,7 @@ KIGFX::VC_SETTINGS EDA_DRAW_PANEL_GAL::GetVcSettings()
vcSettings.m_scrollModifierZoom = cfg->m_Input.scroll_modifier_zoom;
vcSettings.m_scrollModifierPanH = cfg->m_Input.scroll_modifier_pan_h;
vcSettings.m_scrollModifierPanV = cfg->m_Input.scroll_modifier_pan_v;
vcSettings.m_motionPanModifier = cfg->m_Input.motion_pan_modifier;
vcSettings.m_dragLeft = cfg->m_Input.drag_left;
vcSettings.m_dragMiddle = cfg->m_Input.drag_middle;
vcSettings.m_dragRight = cfg->m_Input.drag_right;

View File

@ -269,6 +269,9 @@ COMMON_SETTINGS::COMMON_SETTINGS() :
m_params.emplace_back( new PARAM<int>( "input.scroll_modifier_pan_v",
&m_Input.scroll_modifier_pan_v, WXK_SHIFT ) );
m_params.emplace_back( new PARAM<int>( "input.motion_pan_modifier",
&m_Input.motion_pan_modifier, 0 ) );
m_params.emplace_back( new PARAM<bool>( "input.reverse_scroll_zoom",
&m_Input.reverse_scroll_zoom, false ) );

View File

@ -76,6 +76,7 @@ void VC_SETTINGS::Reset()
m_scrollModifierZoom = 0;
m_scrollModifierPanH = WXK_CONTROL;
m_scrollModifierPanV = WXK_SHIFT;
m_motionPanModifier = 0;
m_dragLeft = MOUSE_DRAG_ACTION::NONE;
m_dragMiddle = MOUSE_DRAG_ACTION::PAN;
m_dragRight = MOUSE_DRAG_ACTION::PAN;

View File

@ -35,7 +35,7 @@
#include <tool/tool_dispatcher.h>
#include <trace_helpers.h>
#include <settings/common_settings.h>
#include <math/util.h> // for KiROUND
#include <math/util.h> // for KiROUND
#include <geometry/geometry_utils.h>
#include <widgets/ui_common.h>
#include <class_draw_panel_gal.h>
@ -45,7 +45,7 @@
#include <wx/log.h>
#ifdef __WXMSW__
#define USE_MOUSE_CAPTURE
#define USE_MOUSE_CAPTURE
#endif
using namespace KIGFX;
@ -73,9 +73,16 @@ static std::unique_ptr<ZOOM_CONTROLLER> GetZoomControllerForPlatform( bool aAcce
WX_VIEW_CONTROLS::WX_VIEW_CONTROLS( VIEW* aView, EDA_DRAW_PANEL_GAL* aParentPanel ) :
VIEW_CONTROLS( aView ), m_state( IDLE ), m_parentPanel( aParentPanel ),
m_scrollScale( 1.0, 1.0 ), m_cursorPos( 0, 0 ), m_updateCursor( true ),
m_infinitePanWorks( false ), m_gestureLastZoomFactor( 1.0 )
VIEW_CONTROLS( aView ),
m_state( IDLE ),
m_parentPanel( aParentPanel ),
m_scrollScale( 1.0, 1.0 ),
m_cursorPos( 0, 0 ),
m_updateCursor( true ),
m_metaPanning( false ),
m_metaPanStart( 0, 0 ),
m_infinitePanWorks( false ),
m_gestureLastZoomFactor( 1.0 )
{
LoadSettings();
@ -178,6 +185,7 @@ void WX_VIEW_CONTROLS::LoadSettings()
m_settings.m_dragRight = cfg->m_Input.drag_right;
m_settings.m_scrollReverseZoom = cfg->m_Input.reverse_scroll_zoom;
m_settings.m_scrollReversePanH = cfg->m_Input.reverse_scroll_pan_h;
m_settings.m_motionPanModifier = cfg->m_Input.motion_pan_modifier;
m_zoomController.reset();
@ -238,6 +246,37 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
}
}
if( m_settings.m_motionPanModifier != WXK_NONE
&& wxGetKeyState( static_cast<wxKeyCode>( m_settings.m_motionPanModifier ) ) )
{
if( !m_metaPanning )
{
m_metaPanning = true;
m_metaPanStart = mousePos;
aEvent.StopPropagation();
}
else
{
VECTOR2D d = m_metaPanStart - mousePos;
m_metaPanStart = mousePos;
VECTOR2D delta = m_view->ToWorld( d, false );
m_view->SetCenter( m_view->GetCenter() + delta );
aEvent.StopPropagation();
}
if( m_updateCursor )
m_cursorPos = GetClampedCoords( m_view->ToWorld( mousePos ) );
else
m_updateCursor = true;
aEvent.Skip();
return;
}
else
{
m_metaPanning = false;
}
if( m_state != DRAG_PANNING && m_state != DRAG_ZOOMING )
handleCursorCapture( x, y );
@ -249,15 +288,15 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
if( m_state == DRAG_PANNING )
{
static bool justWarped = false;
int warpX = 0;
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
int warpX = 0;
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
if( x < 0 )
{
warpX = parentSize.x;
}
else if(x >= parentSize.x )
else if( x >= parentSize.x )
{
warpX = -parentSize.x;
}
@ -284,8 +323,7 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
{
if( !justWarped )
{
if( m_infinitePanWorks
&& KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
if( m_infinitePanWorks && KIPLATFORM::UI::WarpPointer( m_parentPanel, x + warpX, y + warpY ) )
{
m_dragStartPoint += VECTOR2D( warpX, warpY );
justWarped = true;
@ -304,8 +342,8 @@ void WX_VIEW_CONTROLS::onMotion( wxMouseEvent& aEvent )
else if( m_state == DRAG_ZOOMING )
{
static bool justWarped = false;
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
int warpY = 0;
wxSize parentSize = m_parentPanel->GetClientSize();
if( y < 0 )
{
@ -394,8 +432,7 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& aEvent )
// as vertical scroll events and confuse the user.
if( modifiers == m_settings.m_scrollModifierZoom && axis == wxMOUSE_WHEEL_VERTICAL )
{
const int rotation =
aEvent.GetWheelRotation() * ( m_settings.m_scrollReverseZoom ? -1 : 1 );
const int rotation = aEvent.GetWheelRotation() * ( m_settings.m_scrollReverseZoom ? -1 : 1 );
const double zoomScale = m_zoomController->GetScaleForRotation( rotation );
if( IsCursorWarpingEnabled() )
@ -477,8 +514,8 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
{
case IDLE:
case AUTO_PANNING:
if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::PAN ) ||
( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::PAN ) )
if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::PAN )
|| ( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::PAN ) )
{
m_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
setState( DRAG_PANNING );
@ -489,10 +526,10 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
m_parentPanel->CaptureMouse();
#endif
}
else if( ( aEvent.MiddleDown() && m_settings.m_dragMiddle == MOUSE_DRAG_ACTION::ZOOM ) ||
( aEvent.RightDown() && m_settings.m_dragRight == MOUSE_DRAG_ACTION::ZOOM ) )
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_dragStartPoint = VECTOR2D( aEvent.GetX(), aEvent.GetY() );
m_zoomStartPoint = m_dragStartPoint;
setState( DRAG_ZOOMING );
@ -503,7 +540,7 @@ void WX_VIEW_CONTROLS::onButton( wxMouseEvent& aEvent )
}
if( aEvent.LeftUp() )
setState( IDLE ); // Stop autopanning when user release left mouse button
setState( IDLE ); // Stop autopanning when user release left mouse button
break;
@ -619,7 +656,7 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
// For a small mouse cursor dist to area, just use the distance.
// But for a dist > borderSize / 2, use an accelerated pan value
if( dir.EuclideanNorm() >= borderSize ) // far from area limits
if( dir.EuclideanNorm() >= borderSize ) // far from area limits
dir = dir.Resize( borderSize * accel );
else if( dir.EuclideanNorm() > borderSize / 2 ) // Near from area limits
dir = dir.Resize( borderSize );
@ -633,10 +670,9 @@ void WX_VIEW_CONTROLS::onTimer( wxTimerEvent& aEvent )
}
break;
case IDLE: // Just remove unnecessary warnings
case IDLE: // Just remove unnecessary warnings
case DRAG_PANNING:
case DRAG_ZOOMING:
break;
case DRAG_ZOOMING: break;
}
}
@ -685,12 +721,11 @@ void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
if( type == wxEVT_SCROLLWIN_THUMBTRACK )
{
auto center = m_view->GetCenter();
auto center = m_view->GetCenter();
const auto& boundary = m_view->GetBoundary();
// Flip scroll direction in flipped view
const double xstart = ( m_view->IsMirroredX() ?
boundary.GetRight() : boundary.GetLeft() );
const double xstart = ( m_view->IsMirroredX() ? boundary.GetRight() : boundary.GetLeft() );
const double xdelta = ( m_view->IsMirroredX() ? -1 : 1 );
if( dir == wxHORIZONTAL )
@ -700,9 +735,7 @@ void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
m_view->SetCenter( center );
}
else if( type == wxEVT_SCROLLWIN_THUMBRELEASE ||
type == wxEVT_SCROLLWIN_TOP ||
type == wxEVT_SCROLLWIN_BOTTOM )
else if( type == wxEVT_SCROLLWIN_THUMBRELEASE || type == wxEVT_SCROLLWIN_TOP || type == wxEVT_SCROLLWIN_BOTTOM )
{
// Do nothing on thumb release, we don't care about it.
// We don't have a concept of top or bottom in our viewport, so ignore those events.
@ -737,7 +770,7 @@ void WX_VIEW_CONTROLS::onScroll( wxScrollWinEvent& aEvent )
double scrollX = 0.0;
double scrollY = 0.0;
if ( dir == wxHORIZONTAL )
if( dir == wxHORIZONTAL )
scrollX = -scroll.x;
else
scrollY = -scroll.y;
@ -769,8 +802,7 @@ void WX_VIEW_CONTROLS::CaptureCursor( bool aEnabled )
// Calling it without calling ReleaseMouse() is not accepted by wxWidgets (MSW specific)
m_parentPanel->m_MouseCapturedLost = false;
}
else if( !aEnabled && m_parentPanel->HasCapture()
&& m_state != DRAG_PANNING && m_state != DRAG_ZOOMING )
else if( !aEnabled && m_parentPanel->HasCapture() && m_state != DRAG_PANNING && m_state != DRAG_ZOOMING )
{
m_parentPanel->ReleaseMouse();
@ -793,12 +825,14 @@ void WX_VIEW_CONTROLS::CancelDrag()
m_parentPanel->ReleaseMouse();
#endif
}
m_metaPanning = false;
}
VECTOR2D WX_VIEW_CONTROLS::GetMousePosition( bool aWorldCoordinates ) const
{
wxPoint msp = getMouseScreenPosition();
wxPoint msp = getMouseScreenPosition();
VECTOR2D screenPos( msp.x, msp.y );
return aWorldCoordinates ? GetClampedCoords( m_view->ToWorld( screenPos ) ) : screenPos;
@ -833,8 +867,8 @@ VECTOR2D WX_VIEW_CONTROLS::GetCursorPosition( bool aEnableSnapping ) const
}
void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpView,
bool aTriggeredByArrows, long aArrowCommand )
void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpView, bool aTriggeredByArrows,
long aArrowCommand )
{
m_updateCursor = false;
@ -860,8 +894,7 @@ void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpV
}
void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition,
bool aWarpView = true )
void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition, bool aWarpView = true )
{
m_updateCursor = false;
@ -878,8 +911,7 @@ void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition,
}
void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates,
bool aWarpView )
void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates, bool aWarpView )
{
if( aWorldCoordinates )
{
@ -915,7 +947,7 @@ void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCo
void WX_VIEW_CONTROLS::CenterOnCursor()
{
const VECTOR2I& screenSize = m_view->GetGAL()->GetScreenPixelSize();
VECTOR2D screenCenter( screenSize / 2 );
VECTOR2D screenCenter( screenSize / 2 );
if( GetMousePosition( false ) != screenCenter )
{
@ -937,8 +969,7 @@ void WX_VIEW_CONTROLS::PinCursorInsideNonAutoscrollArea( bool aWarpMouseCursor )
border += 2;
VECTOR2D topLeft( border, border );
VECTOR2D botRight( m_view->GetScreenPixelSize().x - border,
m_view->GetScreenPixelSize().y - border );
VECTOR2D botRight( m_view->GetScreenPixelSize().x - border, m_view->GetScreenPixelSize().y - border );
topLeft = m_view->ToWorld( topLeft );
botRight = m_view->ToWorld( botRight );
@ -965,7 +996,7 @@ void WX_VIEW_CONTROLS::PinCursorInsideNonAutoscrollArea( bool aWarpMouseCursor )
bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
{
VECTOR2I p( aEvent.GetX(), aEvent.GetY() );
VECTOR2I pKey( m_view->ToScreen(m_settings.m_lastKeyboardCursorPosition ) );
VECTOR2I pKey( m_view->ToScreen( m_settings.m_lastKeyboardCursorPosition ) );
if( m_cursorWarped || ( m_settings.m_lastKeyboardCursorPositionValid && p == pKey ) )
{
@ -1028,8 +1059,7 @@ bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
return false;
case DRAG_PANNING:
case DRAG_ZOOMING:
return false;
case DRAG_ZOOMING: return false;
}
wxCHECK_MSG( false, false, wxT( "This line should never be reached" ) );
@ -1042,7 +1072,7 @@ void WX_VIEW_CONTROLS::handleCursorCapture( int x, int y )
{
if( m_settings.m_cursorCaptured )
{
bool warp = false;
bool warp = false;
wxSize parentSize = m_parentPanel->GetClientSize();
if( x < 0 )
@ -1077,7 +1107,7 @@ void WX_VIEW_CONTROLS::refreshMouse( bool aSetModifiers )
{
// Notify tools that the cursor position has changed in the world coordinates
wxMouseEvent moveEvent( EVT_REFRESH_MOUSE );
wxPoint msp = getMouseScreenPosition();
wxPoint msp = getMouseScreenPosition();
moveEvent.SetX( msp.x );
moveEvent.SetY( msp.y );
@ -1104,20 +1134,18 @@ wxPoint WX_VIEW_CONTROLS::getMouseScreenPosition() const
void WX_VIEW_CONTROLS::UpdateScrollbars()
{
const BOX2D viewport = m_view->GetViewport();
const BOX2D viewport = m_view->GetViewport();
const BOX2D& boundary = m_view->GetBoundary();
m_scrollScale.x = 2e3 / viewport.GetWidth(); // TODO it does not have to be updated so often
m_scrollScale.x = 2e3 / viewport.GetWidth(); // TODO it does not have to be updated so often
m_scrollScale.y = 2e3 / viewport.GetHeight();
VECTOR2I newScroll( ( viewport.Centre().x - boundary.GetLeft() ) * m_scrollScale.x,
( viewport.Centre().y - boundary.GetTop() ) * m_scrollScale.y );
// We add the width of the scroll bar thumb to the range because the scroll range is given by
// the full bar while the position is given by the left/top position of the thumb
VECTOR2I newRange( m_scrollScale.x * boundary.GetWidth() +
m_parentPanel->GetScrollThumb( wxSB_HORIZONTAL ),
m_scrollScale.y * boundary.GetHeight() +
m_parentPanel->GetScrollThumb( wxSB_VERTICAL ) );
VECTOR2I newRange( m_scrollScale.x * boundary.GetWidth() + m_parentPanel->GetScrollThumb( wxSB_HORIZONTAL ),
m_scrollScale.y * boundary.GetHeight() + m_parentPanel->GetScrollThumb( wxSB_VERTICAL ) );
// Flip scroll direction in flipped view
if( m_view->IsMirroredX() )
@ -1126,10 +1154,9 @@ void WX_VIEW_CONTROLS::UpdateScrollbars()
// Adjust scrollbars only if it is needed. Otherwise there are cases when canvas is continuously
// refreshed (Windows)
if( m_scrollPos != newScroll || newRange.x != m_parentPanel->GetScrollRange( wxSB_HORIZONTAL )
|| newRange.y != m_parentPanel->GetScrollRange( wxSB_VERTICAL ) )
|| newRange.y != m_parentPanel->GetScrollRange( wxSB_VERTICAL ) )
{
m_parentPanel->SetScrollbars( 1, 1, newRange.x, newRange.y, newScroll.x, newScroll.y,
true );
m_parentPanel->SetScrollbars( 1, 1, newRange.x, newRange.y, newScroll.x, newScroll.y, true );
m_scrollPos = newScroll;
#if !defined( __APPLE__ ) && !defined( WIN32 )

View File

@ -96,6 +96,8 @@ public:
int scroll_modifier_pan_h;
int scroll_modifier_pan_v;
int motion_pan_modifier;
MOUSE_DRAG_ACTION drag_left;
MOUSE_DRAG_ACTION drag_middle;
MOUSE_DRAG_ACTION drag_right;

View File

@ -109,6 +109,9 @@ struct GAL_API VC_SETTINGS
/// What modifier key to enable vertical with the (vertical) scroll wheel.
int m_scrollModifierPanV;
/// What modifier key pans the view when the mouse moves with it held.
int m_motionPanModifier;
MOUSE_DRAG_ACTION m_dragLeft;
MOUSE_DRAG_ACTION m_dragMiddle;
MOUSE_DRAG_ACTION m_dragRight;

View File

@ -89,15 +89,14 @@ public:
/// @copydoc VIEW_CONTROLS::GetRawCursorPosition()
VECTOR2D GetRawCursorPosition( bool aSnappingEnabled = true ) const override;
void SetCursorPosition( const VECTOR2D& aPosition, bool warpView,
bool aTriggeredByArrows, long aArrowCommand ) override;
void SetCursorPosition( const VECTOR2D& aPosition, bool warpView, bool aTriggeredByArrows,
long aArrowCommand ) override;
/// @copydoc VIEW_CONTROLS::SetCrossHairCursorPosition()
void SetCrossHairCursorPosition( const VECTOR2D& aPosition, bool aWarpView ) override;
/// @copydoc VIEW_CONTROLS::CursorWarp()
void WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates = false,
bool aWarpView = false ) override;
void WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates = false, bool aWarpView = false ) override;
/// @copydoc VIEW_CONTROLS::CenterOnCursor()
void CenterOnCursor() override;
@ -108,8 +107,7 @@ public:
/// End any mouse drag action still in progress.
void CancelDrag();
void ForceCursorPosition( bool aEnabled,
const VECTOR2D& aPosition = VECTOR2D( 0, 0 ) ) override;
void ForceCursorPosition( bool aEnabled, const VECTOR2D& aPosition = VECTOR2D( 0, 0 ) ) override;
/// Applies VIEW_CONTROLS settings from the program #COMMON_SETTINGS.
void LoadSettings() override;
@ -124,10 +122,10 @@ private:
/// Possible states for WX_VIEW_CONTROLS.
enum STATE
{
IDLE = 1, ///< Nothing is happening.
DRAG_PANNING, ///< Panning with mouse button pressed.
AUTO_PANNING, ///< Panning on approaching borders of the frame.
DRAG_ZOOMING, ///< Zooming with mouse button pressed.
IDLE = 1, ///< Nothing is happening.
DRAG_PANNING, ///< Panning with mouse button pressed.
AUTO_PANNING, ///< Panning on approaching borders of the frame.
DRAG_ZOOMING, ///< Zooming with mouse button pressed.
};
/**
@ -162,7 +160,7 @@ private:
* @param aSetModifiers If false, don't change the modifiers (they were set using the
* keyboard motion).
*/
void refreshMouse( bool aSetModifiers);
void refreshMouse( bool aSetModifiers );
/**
* Get the cursor position in the screen coordinates.
@ -170,34 +168,40 @@ private:
wxPoint getMouseScreenPosition() const;
/// Current state of VIEW_CONTROLS.
STATE m_state;
STATE m_state;
/// Panel that is affected by VIEW_CONTROLS.
EDA_DRAW_PANEL_GAL* m_parentPanel;
/// Store information about point where dragging has started.
VECTOR2D m_dragStartPoint;
VECTOR2D m_dragStartPoint;
/// Current direction of panning (only autopanning mode).
VECTOR2D m_panDirection;
VECTOR2D m_panDirection;
/// Timer responsible for handling autopanning.
wxTimer m_panTimer;
wxTimer m_panTimer;
/// Ratio used for scaling world coordinates to scrollbar position.
VECTOR2D m_scrollScale;
VECTOR2D m_scrollScale;
/// Current scrollbar position.
VECTOR2I m_scrollPos;
VECTOR2I m_scrollPos;
/// The mouse position when a drag zoom started.
VECTOR2D m_zoomStartPoint;
VECTOR2D m_zoomStartPoint;
/// Current cursor position (world coordinates).
VECTOR2D m_cursorPos;
VECTOR2D m_cursorPos;
/// Flag deciding whether the cursor position should be calculated using the mouse position.
bool m_updateCursor;
bool m_updateCursor;
/// True if we are panning via the meta key.
bool m_metaPanning;
/// Last mouse position when panning via the meta key.
VECTOR2D m_metaPanStart;
/// Flag to indicate if infinite panning works on this platform.
bool m_infinitePanWorks;