Uniformly use a single facility for location-less prime events.
Also implements a uniform mechanism for avoiding auto-scroll after a prime event or dialog which results in a mouse position at the edge of the canvas. Fixes https://gitlab.com/kicad/code/kicad/issues/11057
This commit is contained in:
parent
b00bf2bc6b
commit
23fb4c7433
|
@ -703,7 +703,7 @@ void WX_VIEW_CONTROLS::SetCursorPosition( const VECTOR2D& aPosition, bool aWarpV
|
|||
m_cursorWarped = true;
|
||||
}
|
||||
|
||||
WarpCursor( clampedPosition, true, aWarpView );
|
||||
WarpMouseCursor( clampedPosition, true, aWarpView );
|
||||
m_cursorPos = clampedPosition;
|
||||
}
|
||||
|
||||
|
@ -726,8 +726,8 @@ void WX_VIEW_CONTROLS::SetCrossHairCursorPosition( const VECTOR2D& aPosition,
|
|||
}
|
||||
|
||||
|
||||
void WX_VIEW_CONTROLS::WarpCursor( const VECTOR2D& aPosition, bool aWorldCoordinates,
|
||||
bool aWarpView )
|
||||
void WX_VIEW_CONTROLS::WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates,
|
||||
bool aWarpView )
|
||||
{
|
||||
if( aWorldCoordinates )
|
||||
{
|
||||
|
@ -771,6 +771,38 @@ void WX_VIEW_CONTROLS::CenterOnCursor() const
|
|||
}
|
||||
|
||||
|
||||
void WX_VIEW_CONTROLS::PinCursorInsideNonAutoscrollArea( bool aWarpMouseCursor )
|
||||
{
|
||||
int border = std::min( m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().x,
|
||||
m_settings.m_autoPanMargin * m_view->GetScreenPixelSize().y );
|
||||
border += 2;
|
||||
|
||||
VECTOR2D topLeft( border, border );
|
||||
VECTOR2D botRight( m_view->GetScreenPixelSize().x - border,
|
||||
m_view->GetScreenPixelSize().y - border );
|
||||
|
||||
topLeft = m_view->ToWorld( topLeft );
|
||||
botRight = m_view->ToWorld( botRight );
|
||||
|
||||
VECTOR2D pos = GetMousePosition( true );
|
||||
|
||||
if( pos.x < topLeft.x )
|
||||
pos.x = topLeft.x;
|
||||
else if( pos.x > botRight.x )
|
||||
pos.x = botRight.x;
|
||||
|
||||
if( pos.y < topLeft.y )
|
||||
pos.y = topLeft.y;
|
||||
else if( pos.y > botRight.y )
|
||||
pos.y = botRight.y;
|
||||
|
||||
SetCursorPosition( pos, false, false, 0 );
|
||||
|
||||
if( aWarpMouseCursor )
|
||||
WarpMouseCursor( pos, true );
|
||||
}
|
||||
|
||||
|
||||
bool WX_VIEW_CONTROLS::handleAutoPanning( const wxMouseEvent& aEvent )
|
||||
{
|
||||
VECTOR2I p( aEvent.GetX(), aEvent.GetY() );
|
||||
|
|
|
@ -260,7 +260,7 @@ void SCH_BASE_FRAME::CenterScreen( const VECTOR2I& aCenterPoint, bool aWarpPoint
|
|||
GetCanvas()->GetView()->SetCenter( aCenterPoint );
|
||||
|
||||
if( aWarpPointer )
|
||||
GetCanvas()->GetViewControls()->WarpCursor( aCenterPoint, true );
|
||||
GetCanvas()->GetViewControls()->WarpMouseCursor( aCenterPoint, true );
|
||||
|
||||
GetCanvas()->Refresh();
|
||||
}
|
||||
|
|
|
@ -95,29 +95,14 @@ bool SCH_DRAWING_TOOLS::Init()
|
|||
}
|
||||
|
||||
|
||||
EDA_RECT SCH_DRAWING_TOOLS::GetCanvasFreeAreaPixels()
|
||||
{
|
||||
// calculate the area of the canvas in pixels that create no autopan when
|
||||
// is inside this area the mouse cursor
|
||||
wxSize canvas_size = m_frame->GetCanvas()->GetSize();
|
||||
EDA_RECT canvas_area( wxPoint( 0, 0 ), canvas_size );
|
||||
const KIGFX::VC_SETTINGS& v_settings = getViewControls()->GetSettings();
|
||||
|
||||
if( v_settings.m_autoPanEnabled )
|
||||
canvas_area.Inflate( - v_settings.m_autoPanMargin );
|
||||
|
||||
// Gives a margin of 2 pixels
|
||||
canvas_area.Inflate( -2 );
|
||||
|
||||
return canvas_area;
|
||||
}
|
||||
|
||||
|
||||
int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCH_SYMBOL* symbol = aEvent.Parameter<SCH_SYMBOL*>();
|
||||
SYMBOL_LIBRARY_FILTER filter;
|
||||
std::vector<PICKED_SYMBOL>* historyList = nullptr;
|
||||
bool ignorePrimePosition = false;
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
|
||||
if( m_inPlaceSymbol )
|
||||
return 0;
|
||||
|
@ -183,17 +168,25 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
|||
if( symbol )
|
||||
{
|
||||
addSymbol( symbol );
|
||||
getViewControls()->WarpCursor( getViewControls()->GetMousePosition( false ) );
|
||||
getViewControls()->WarpMouseCursor( getViewControls()->GetMousePosition( false ));
|
||||
}
|
||||
else if( !aEvent.IsReactivate() )
|
||||
else if( aEvent.HasPosition() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
}
|
||||
else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( { 0, 0 } );
|
||||
ignorePrimePosition = true;
|
||||
}
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
setCursor();
|
||||
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
|
||||
|
||||
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
|
@ -243,39 +236,32 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
// Store the mouse position: if it is outside the canvas,
|
||||
// (happens when clicking on a toolbar tool) one cannot
|
||||
// use the last stored cursor position to place the new symbol
|
||||
// (Current mouse pos after closing the dialog will be used)
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
VECTOR2D initialMousePos = controls->GetMousePosition(false);
|
||||
// Build the rectangle area acceptable to move the cursor without
|
||||
// having an auto-pan
|
||||
EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
|
||||
|
||||
// Pick the footprint to be placed
|
||||
bool footprintPreviews = m_frame->eeconfig()->m_Appearance.footprint_preview;
|
||||
PICKED_SYMBOL sel = m_frame->PickSymbolFromLibTree( &filter, *historyList, true,
|
||||
1, 1, footprintPreviews );
|
||||
// Restore cursor position after closing the dialog,
|
||||
// but only if it has meaning (i.e inside the canvas)
|
||||
VECTOR2D newMousePos = controls->GetMousePosition(false);
|
||||
|
||||
if( canvas_area.Contains( VECTOR2I( initialMousePos ) ) )
|
||||
controls->WarpCursor( controls->GetCursorPosition(), true );
|
||||
else if( !canvas_area.Contains( VECTOR2I( newMousePos ) ) )
|
||||
// The mouse is outside the canvas area, after closing the dialog,
|
||||
// thus can creating autopan issues. Warp the mouse to the canvas center
|
||||
controls->WarpCursor( canvas_area.Centre(), false );
|
||||
|
||||
LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ?
|
||||
m_frame->GetLibSymbol( sel.LibId ) : nullptr;
|
||||
LIB_SYMBOL* libSymbol = sel.LibId.IsValid() ? m_frame->GetLibSymbol( sel.LibId )
|
||||
: nullptr;
|
||||
|
||||
if( !libSymbol )
|
||||
continue;
|
||||
|
||||
VECTOR2I pos( cursorPos );
|
||||
symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, pos );
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = grid.Align( evt->Position() );
|
||||
getViewControls()->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
getViewControls()->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = getViewControls()->GetMousePosition();
|
||||
}
|
||||
|
||||
symbol = new SCH_SYMBOL( *libSymbol, &m_frame->GetCurrentSheet(), sel, cursorPos );
|
||||
addSymbol( symbol );
|
||||
|
||||
// Update cursor now that we have a symbol
|
||||
|
@ -380,9 +366,11 @@ int SCH_DRAWING_TOOLS::PlaceSymbol( const TOOL_EVENT& aEvent )
|
|||
|
||||
int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
||||
{
|
||||
SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
|
||||
bool immediateMode = image;
|
||||
VECTOR2I cursorPos = getViewControls()->GetCursorPosition();
|
||||
SCH_BITMAP* image = aEvent.Parameter<SCH_BITMAP*>();
|
||||
bool immediateMode = image != nullptr;
|
||||
EE_GRID_HELPER grid( m_toolMgr );
|
||||
bool ignorePrimePosition = false;
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
|
||||
if( m_inPlaceImage )
|
||||
return 0;
|
||||
|
@ -394,7 +382,7 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
|||
// Add all the drawable symbols to preview
|
||||
if( image )
|
||||
{
|
||||
image->SetPosition( cursorPos );
|
||||
image->SetPosition( getViewControls()->GetCursorPosition() );
|
||||
m_view->ClearPreview();
|
||||
m_view->AddToPreview( image->Clone() );
|
||||
}
|
||||
|
@ -428,15 +416,24 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
|||
|
||||
// Prime the pump
|
||||
if( image )
|
||||
{
|
||||
m_toolMgr->RunAction( ACTIONS::refreshPreview );
|
||||
else if( !aEvent.IsReactivate() )
|
||||
}
|
||||
else if( aEvent.HasPosition() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
}
|
||||
else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( { 0, 0 } );
|
||||
ignorePrimePosition = true;
|
||||
}
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
setCursor();
|
||||
cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
VECTOR2I cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
|
@ -491,17 +488,6 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
// Store the mouse position: if it is outside the canvas,
|
||||
// (happens when clicking on a toolbar tool) one cannot
|
||||
// use the last stored cursor position to place the new symbol
|
||||
// (Current mouse pos after closing the dialog will be used)
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
VECTOR2D initialMousePos = controls->GetMousePosition(false);
|
||||
|
||||
// Build the rectangle area acceptable to move the cursor without
|
||||
// having an auto-pan
|
||||
EDA_RECT canvas_area = GetCanvasFreeAreaPixels();
|
||||
|
||||
wxFileDialog dlg( m_frame, _( "Choose Image" ), m_mruPath, wxEmptyString,
|
||||
_( "Image Files" ) + wxS( " " ) + wxImage::GetImageExtWildcard(),
|
||||
wxFD_OPEN );
|
||||
|
@ -509,18 +495,19 @@ int SCH_DRAWING_TOOLS::PlaceImage( const TOOL_EVENT& aEvent )
|
|||
if( dlg.ShowModal() != wxID_OK )
|
||||
continue;
|
||||
|
||||
// Restore cursor position after closing the dialog,
|
||||
// but only if it has meaning (i.e inside the canvas)
|
||||
VECTOR2D newMousePos = controls->GetMousePosition( false );
|
||||
|
||||
if( canvas_area.Contains( VECTOR2I( initialMousePos ) ) )
|
||||
controls->WarpCursor( controls->GetCursorPosition(), true );
|
||||
else if( !canvas_area.Contains( VECTOR2I( newMousePos ) ) )
|
||||
// The mouse is outside the canvas area, after closing the dialog,
|
||||
// thus can creating autopan issues. Warp the mouse to the canvas center
|
||||
controls->WarpCursor( canvas_area.Centre(), false );
|
||||
|
||||
cursorPos = controls->GetMousePosition( true );
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = grid.Align( evt->Position() );
|
||||
getViewControls()->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
getViewControls()->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = getViewControls()->GetMousePosition();
|
||||
}
|
||||
|
||||
wxString fullFilename = dlg.GetPath();
|
||||
m_mruPath = wxPathOnly( fullFilename );
|
||||
|
@ -626,7 +613,7 @@ int SCH_DRAWING_TOOLS::SingleClickPlace( const TOOL_EVENT& aEvent )
|
|||
SEG seg( wire->GetStartPoint(), wire->GetEndPoint() );
|
||||
VECTOR2I nearest = seg.NearestPoint( getViewControls()->GetCursorPosition() );
|
||||
getViewControls()->SetCrossHairCursorPosition( nearest, false );
|
||||
getViewControls()->WarpCursor( getViewControls()->GetCursorPosition(), true );
|
||||
getViewControls()->WarpMouseCursor( getViewControls()->GetCursorPosition(), true );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1124,7 +1111,7 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
grid.SetSnap( !evt->Modifier( MD_SHIFT ) );
|
||||
grid.SetUseGrid( getView()->GetGAL()->GetGridSnapping() && !evt->DisableGridSnapping() );
|
||||
|
||||
VECTOR2I cursorPos = evt->IsPrime() ? evt->Position() : controls->GetMousePosition();
|
||||
VECTOR2I cursorPos = controls->GetMousePosition();
|
||||
cursorPos = grid.BestSnapAnchor( cursorPos, snapLayer, item );
|
||||
controls->ForceCursorPosition( true, cursorPos );
|
||||
|
||||
|
@ -1288,12 +1275,19 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
}
|
||||
|
||||
// If we started with a click on a tool button or menu then continue with the
|
||||
// current mouse position. Otherwise warp back to the original click position.
|
||||
if( evt->IsPrime() && ignorePrimePosition )
|
||||
cursorPos = grid.Align( controls->GetMousePosition() );
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = grid.Align( evt->Position() );
|
||||
getViewControls()->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
controls->WarpCursor( cursorPos, true );
|
||||
{
|
||||
getViewControls()->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = getViewControls()->GetMousePosition();
|
||||
}
|
||||
|
||||
if( item )
|
||||
{
|
||||
|
@ -1305,6 +1299,8 @@ int SCH_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
|
||||
m_selectionTool->AddItemToSel( item );
|
||||
|
||||
m_toolMgr->RunAction( ACTIONS::refreshPreview );
|
||||
|
||||
// update the cursor so it looks correct before another event
|
||||
setCursor();
|
||||
}
|
||||
|
|
|
@ -79,6 +79,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
bool ignorePrimePosition = false;
|
||||
LIB_ITEM* item = nullptr;
|
||||
bool isText = aEvent.IsAction( &EE_ACTIONS::placeSymbolText );
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
|
||||
m_toolMgr->RunAction( EE_ACTIONS::clearSelection, true );
|
||||
|
||||
|
@ -115,7 +116,7 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
{
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
}
|
||||
else if( !aEvent.IsReactivate() )
|
||||
else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( { 0, 0 } );
|
||||
ignorePrimePosition = true;
|
||||
|
@ -217,12 +218,19 @@ int SYMBOL_EDITOR_DRAWING_TOOLS::TwoClickPlace( const TOOL_EVENT& aEvent )
|
|||
wxFAIL_MSG( "TwoClickPlace(): unknown type" );
|
||||
}
|
||||
|
||||
// If we started with a click on a tool button or menu then continue with the
|
||||
// current mouse position. Otherwise warp back to the original click position.
|
||||
if( evt->IsPrime() && ignorePrimePosition )
|
||||
cursorPos = grid.Align( controls->GetMousePosition() );
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = grid.Align( evt->Position() );
|
||||
getViewControls()->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
controls->WarpCursor( cursorPos, true );
|
||||
{
|
||||
getViewControls()->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = getViewControls()->GetMousePosition();
|
||||
}
|
||||
|
||||
if( item )
|
||||
{
|
||||
|
|
|
@ -209,7 +209,7 @@ int SYMBOL_EDITOR_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
|
|||
VECTOR2I itemPos = selection.GetTopLeftItem()->GetPosition();
|
||||
m_anchorPos = VECTOR2I( itemPos.x, -itemPos.y );
|
||||
|
||||
getViewControls()->WarpCursor( m_anchorPos, true, true );
|
||||
getViewControls()->WarpMouseCursor( m_anchorPos, true, true );
|
||||
m_cursor = m_anchorPos;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -198,6 +198,8 @@ public:
|
|||
m_settings.m_autoPanMargin = aMargin;
|
||||
}
|
||||
|
||||
virtual void PinCursorInsideNonAutoscrollArea( bool aWarpMouseCursor ) = 0;
|
||||
|
||||
/**
|
||||
* Return the current mouse pointer position.
|
||||
*
|
||||
|
@ -324,8 +326,8 @@ public:
|
|||
* specified in the world coordinates and its not visible in the current
|
||||
* viewport).
|
||||
*/
|
||||
virtual void WarpCursor( const VECTOR2D& aPosition, bool aWorldCoordinates = false,
|
||||
bool aWarpView = false ) = 0;
|
||||
virtual void WarpMouseCursor( const VECTOR2D& aPosition, bool aWorldCoordinates = false,
|
||||
bool aWarpView = false ) = 0;
|
||||
|
||||
/**
|
||||
* Enable or disable warping the cursor.
|
||||
|
|
|
@ -76,6 +76,8 @@ public:
|
|||
void CaptureCursor( bool aEnabled ) override;
|
||||
|
||||
|
||||
void PinCursorInsideNonAutoscrollArea( bool aWarpMouseCursor ) override;
|
||||
|
||||
///< @copydoc VIEW_CONTROLS::GetMousePosition()
|
||||
VECTOR2D GetMousePosition( bool aWorldCoordinates = true ) const override;
|
||||
|
||||
|
@ -94,8 +96,8 @@ public:
|
|||
void SetCrossHairCursorPosition( const VECTOR2D& aPosition, bool aWarpView ) override;
|
||||
|
||||
///< @copydoc VIEW_CONTROLS::CursorWarp()
|
||||
void WarpCursor( 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() const override;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* This program source code file is part of KiCad, a free EDA CAD application.
|
||||
*
|
||||
* Copyright (C) 2019 CERN
|
||||
* Copyright (C) 2019 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
* Copyright (C) 2019-2022 KiCad Developers, see AUTHORS.txt for contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
|
@ -24,21 +24,17 @@
|
|||
|
||||
#include <class_draw_panel_gal.h>
|
||||
#include <confirm.h>
|
||||
#include <view/view_group.h>
|
||||
#include <view/view_controls.h>
|
||||
#include <view/view.h>
|
||||
#include <tool/tool_manager.h>
|
||||
#include <bitmaps.h>
|
||||
#include <drawing_sheet/ds_draw_item.h>
|
||||
#include <drawing_sheet/ds_data_item.h>
|
||||
|
||||
#include "invoke_pl_editor_dialog.h"
|
||||
#include "pl_editor_frame.h"
|
||||
#include "pl_editor_id.h"
|
||||
#include "pl_point_editor.h"
|
||||
#include "tools/pl_actions.h"
|
||||
#include "tools/pl_selection_tool.h"
|
||||
#include "tools/pl_drawing_tools.h"
|
||||
#include "pgm_base.h"
|
||||
|
||||
PL_DRAWING_TOOLS::PL_DRAWING_TOOLS() :
|
||||
TOOL_INTERACTIVE( "plEditor.InteractiveDrawing" ),
|
||||
|
@ -94,6 +90,16 @@ int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
|
|||
m_frame->GetCanvas()->SetCurrentCursor( isText ? KICURSOR::TEXT : KICURSOR::PENCIL );
|
||||
};
|
||||
|
||||
auto cleanup =
|
||||
[&] ()
|
||||
{
|
||||
m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
|
||||
item = nullptr;
|
||||
|
||||
// There's nothing to roll-back, but we still need to pop the undo stack
|
||||
// This also deletes the item being placed.
|
||||
m_frame->RollbackFromUndo();
|
||||
};
|
||||
|
||||
Activate();
|
||||
// Must be done after Activate() so that it gets set into the correct context
|
||||
|
@ -101,27 +107,15 @@ int PL_DRAWING_TOOLS::PlaceItem( const TOOL_EVENT& aEvent )
|
|||
// Set initial cursor
|
||||
setCursor();
|
||||
|
||||
if( aEvent.HasPosition() || ( !aEvent.IsReactivate() && isText ) )
|
||||
if( aEvent.HasPosition() )
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
{
|
||||
setCursor();
|
||||
|
||||
cursorPos = getViewControls()->GetCursorPosition( !evt->DisableGridSnapping() );
|
||||
|
||||
auto cleanup =
|
||||
[&] ()
|
||||
{
|
||||
m_toolMgr->RunAction( PL_ACTIONS::clearSelection, true );
|
||||
item = nullptr;
|
||||
|
||||
// There's nothing to roll-back, but we still need to pop the undo stack
|
||||
// This also deletes the item being placed.
|
||||
m_frame->RollbackFromUndo();
|
||||
};
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
if( item )
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
#include <pgm_base.h>
|
||||
#include <advanced_config.h>
|
||||
#include "board_editor_control.h"
|
||||
#include <bitmaps.h>
|
||||
|
@ -996,9 +997,11 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
REENTRANCY_GUARD guard( &m_inPlaceFootprint );
|
||||
|
||||
FOOTPRINT* fp = aEvent.Parameter<FOOTPRINT*>();
|
||||
bool fromOtherCommand = fp != nullptr;
|
||||
KIGFX::VIEW_CONTROLS* controls = getViewControls();
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
BOARD* board = getModel<BOARD>();
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
|
||||
|
@ -1011,6 +1014,28 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
m_frame->GetCanvas()->SetCurrentCursor( KICURSOR::PENCIL );
|
||||
};
|
||||
|
||||
auto cleanup =
|
||||
[&] ()
|
||||
{
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
commit.Revert();
|
||||
|
||||
if( fromOtherCommand )
|
||||
{
|
||||
PICKED_ITEMS_LIST* undo = m_frame->PopCommandFromUndoList();
|
||||
|
||||
if( undo )
|
||||
{
|
||||
m_frame->PutDataInPreviousState( undo );
|
||||
undo->ClearListAndDeleteItems();
|
||||
delete undo;
|
||||
}
|
||||
}
|
||||
|
||||
fp = nullptr;
|
||||
m_placingFootprint = false;
|
||||
};
|
||||
|
||||
Activate();
|
||||
// Must be done after Activate() so that it gets set into the correct context
|
||||
controls->ShowCursor( true );
|
||||
|
@ -1018,22 +1043,26 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
setCursor();
|
||||
|
||||
VECTOR2I cursorPos = controls->GetCursorPosition();
|
||||
bool ignorePrimePosition = false;
|
||||
bool reselect = false;
|
||||
bool fromOtherCommand = fp != nullptr;
|
||||
bool resetCursor = aEvent.HasPosition(); // Detect if activated from a hotkey.
|
||||
|
||||
// Prime the pump
|
||||
if( fp )
|
||||
{
|
||||
m_placingFootprint = true;
|
||||
fp->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||
fp->SetPosition( cursorPos );
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, fp );
|
||||
m_toolMgr->RunAction( ACTIONS::refreshPreview );
|
||||
}
|
||||
else if( !aEvent.IsReactivate() )
|
||||
else if( aEvent.HasPosition() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
}
|
||||
else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( { 0, 0 } );
|
||||
ignorePrimePosition = true;
|
||||
}
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
|
@ -1044,28 +1073,6 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
if( reselect && fp )
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, fp );
|
||||
|
||||
auto cleanup =
|
||||
[&] ()
|
||||
{
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
|
||||
commit.Revert();
|
||||
|
||||
if( fromOtherCommand )
|
||||
{
|
||||
PICKED_ITEMS_LIST* undo = m_frame->PopCommandFromUndoList();
|
||||
|
||||
if( undo )
|
||||
{
|
||||
m_frame->PutDataInPreviousState( undo );
|
||||
undo->ClearListAndDeleteItems();
|
||||
delete undo;
|
||||
}
|
||||
}
|
||||
|
||||
fp = nullptr;
|
||||
m_placingFootprint = false;
|
||||
};
|
||||
|
||||
if( evt->IsCancelInteractive() )
|
||||
{
|
||||
if( fp )
|
||||
|
@ -1104,6 +1111,20 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
if( fp == nullptr )
|
||||
continue;
|
||||
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = evt->Position();
|
||||
getViewControls()->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
getViewControls()->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = getViewControls()->GetMousePosition();
|
||||
}
|
||||
|
||||
m_placingFootprint = true;
|
||||
|
||||
fp->SetLink( niluuid );
|
||||
|
@ -1127,18 +1148,11 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
fp->Flip( fp->GetPosition(), m_frame->Settings().m_FlipLeftRight );
|
||||
|
||||
fp->SetOrientation( ANGLE_0 );
|
||||
fp->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||
fp->SetPosition( cursorPos );
|
||||
|
||||
commit.Add( fp );
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::selectItem, true, fp );
|
||||
|
||||
// Reset cursor to the position before the dialog opened if activated from hotkey
|
||||
if( resetCursor )
|
||||
controls->SetCursorPosition( cursorPos, false );
|
||||
|
||||
// Other events must be from hotkeys or mouse clicks, so always reset cursor
|
||||
resetCursor = true;
|
||||
|
||||
m_toolMgr->RunAction( ACTIONS::refreshPreview );
|
||||
}
|
||||
else
|
||||
|
@ -1155,7 +1169,7 @@ int BOARD_EDITOR_CONTROL::PlaceFootprint( const TOOL_EVENT& aEvent )
|
|||
}
|
||||
else if( fp && ( evt->IsMotion() || evt->IsAction( &ACTIONS::refreshPreview ) ) )
|
||||
{
|
||||
fp->SetPosition( wxPoint( cursorPos.x, cursorPos.y ) );
|
||||
fp->SetPosition( cursorPos );
|
||||
selection().SetReferencePoint( cursorPos );
|
||||
getView()->Update( &selection() );
|
||||
getView()->Update( fp );
|
||||
|
|
|
@ -518,13 +518,13 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
|
|||
|
||||
REENTRANCY_GUARD guard( &m_inDrawingTool );
|
||||
|
||||
COMMON_SETTINGS* common_settings = Pgm().GetCommonSettings();
|
||||
BOARD_ITEM* text = nullptr;
|
||||
bool ignorePrimePosition = false;
|
||||
const BOARD_DESIGN_SETTINGS& dsnSettings = m_frame->GetDesignSettings();
|
||||
BOARD_COMMIT commit( m_frame );
|
||||
SCOPED_DRAW_MODE scopedDrawMode( m_mode, MODE::TEXT );
|
||||
|
||||
bool resetCursor = aEvent.HasPosition(); // Detect if activated from a hotkey.
|
||||
|
||||
auto cleanup =
|
||||
[&]()
|
||||
{
|
||||
|
@ -559,8 +559,15 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
|
|||
// Set initial cursor
|
||||
setCursor();
|
||||
|
||||
if( !aEvent.IsReactivate() )
|
||||
if( aEvent.HasPosition() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( aEvent.Position() );
|
||||
}
|
||||
else if( common_settings->m_Input.immediate_actions && !aEvent.IsReactivate() )
|
||||
{
|
||||
m_toolMgr->PrimeTool( { 0, 0 } );
|
||||
ignorePrimePosition = true;
|
||||
}
|
||||
|
||||
// Main loop: keep receiving events
|
||||
while( TOOL_EVENT* evt = Wait() )
|
||||
|
@ -710,18 +717,27 @@ int DRAWING_TOOL::PlaceText( const TOOL_EVENT& aEvent )
|
|||
|
||||
m_controls->ForceCursorPosition( false );
|
||||
|
||||
// Reset cursor to the position before the dialog opened if activated from hotkey
|
||||
if( resetCursor )
|
||||
m_controls->SetCursorPosition( cursorPos, false );
|
||||
// If we started with a hotkey which has a position then warp back to that.
|
||||
// Otherwise update to the current mouse position pinned inside the autoscroll
|
||||
// boundaries.
|
||||
if( evt->IsPrime() && !ignorePrimePosition )
|
||||
{
|
||||
cursorPos = evt->Position();
|
||||
m_controls->WarpMouseCursor( cursorPos, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_controls->PinCursorInsideNonAutoscrollArea( true );
|
||||
cursorPos = m_controls->GetMousePosition();
|
||||
}
|
||||
|
||||
// Other events must be from hotkeys or mouse clicks, so always reset cursor
|
||||
resetCursor = true;
|
||||
m_toolMgr->RunAction( PCB_ACTIONS::refreshPreview );
|
||||
|
||||
m_controls->ShowCursor( true );
|
||||
m_controls->CaptureCursor( text != nullptr );
|
||||
m_controls->SetAutoPan( text != nullptr );
|
||||
}
|
||||
else if( text && evt->IsMotion() )
|
||||
else if( text && ( evt->IsMotion() || evt->IsAction( &PCB_ACTIONS::refreshPreview ) ) )
|
||||
{
|
||||
text->SetPosition( cursorPos );
|
||||
selection().SetReferencePoint( cursorPos );
|
||||
|
|
|
@ -102,7 +102,7 @@ std::unique_ptr<ZONE> ZONE_CREATE_HELPER::createNewZone( bool aKeepout )
|
|||
if( dialogResult == wxID_CANCEL )
|
||||
return nullptr;
|
||||
|
||||
controls->WarpCursor( controls->GetCursorPosition(), true );
|
||||
controls->WarpMouseCursor( controls->GetCursorPosition(), true );
|
||||
}
|
||||
|
||||
// The new zone is a ZONE if created in the board editor and a FP_ZONE if created in the
|
||||
|
|
Loading…
Reference in New Issue