GRID_HELPER: Keep edited items out of snap

Distinguish between the snap-from and snap-to items.  Previously, we
used the SELECTED or DRAGGED flags but the flagging arcitecture was
inherently fragile.  This specifies items directly that should not be
used as snap targets.

Fixes: lp:1802795
* https://bugs.launchpad.net/kicad/+bug/1802795
This commit is contained in:
Seth Hillbrand 2018-11-16 10:01:54 -08:00
parent b35b1bb644
commit 940353afde
4 changed files with 35 additions and 31 deletions

View File

@ -366,6 +366,16 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
controls->SetAutoPan( true );
auto curr_item = static_cast<BOARD_ITEM*>( selection.Front() );
std::vector<BOARD_ITEM*> sel_items;
for( auto it : selection )
{
auto item = dynamic_cast<BOARD_ITEM*>( it );
if( item )
sel_items.push_back( item );
}
bool restore_state = false;
VECTOR2I totalMovement;
GRID_HELPER grid( editFrame );
@ -385,7 +395,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
{
if( m_dragging && evt->Category() == TC_MOUSE )
{
m_cursor = grid.BestSnapAnchor( controls->GetMousePosition(), item_layers );
m_cursor = grid.BestSnapAnchor( controls->GetMousePosition(),
item_layers, sel_items );
controls->ForceCursorPosition(true, m_cursor );
VECTOR2I movement( m_cursor - prevPos );
selection.SetReferencePoint( m_cursor );
@ -438,15 +449,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
}
}
for( auto item : selection )
{
item->SetFlags( IS_DRAGGED ); //todo: flags structure rework
if( auto module = dyn_cast<MODULE*>( item ) )
module->RunOnChildren( [&] ( BOARD_ITEM* bitem )
{ bitem->SetFlags( IS_DRAGGED ); } );
}
editFrame->UndoRedoBlock( true );
m_cursor = controls->GetCursorPosition();
@ -567,15 +569,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( unselect || restore_state )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true );
for( auto item : selection )
{
item->ClearFlags( IS_DRAGGED ); //todo: flags structure rework
if( auto module = dyn_cast<MODULE*>( item ) )
module->RunOnChildren( [&] ( BOARD_ITEM* bitem )
{ bitem->SetFlags( IS_DRAGGED ); } );
}
if( restore_state )
m_commit->Revert();
else

View File

@ -226,7 +226,8 @@ VECTOR2I GRID_HELPER::BestDragOrigin( const VECTOR2I &aMousePos, BOARD_ITEM* aIt
}
std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea ) const
std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea,
const std::vector<BOARD_ITEM*> aSkip ) const
{
std::set<BOARD_ITEM*> items;
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
@ -241,14 +242,15 @@ std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea ) const
BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
// The item must be visible and on an active layer
// It cannot be moving as a moving item is being snapped _from_
// rather than considered a potential target
if( view->IsVisible( item )
&& ( !isHighContrast || activeLayers.count( it.second ) )
&& !item->IsDragging() )
&& ( !isHighContrast || activeLayers.count( it.second ) ) )
items.insert ( item );
}
for( auto ii : aSkip )
items.erase( ii );
return items;
}
@ -256,17 +258,22 @@ std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea ) const
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem )
{
LSET layers;
std::vector<BOARD_ITEM*> item;
if( aDraggedItem )
{
layers = aDraggedItem->GetLayerSet();
item.push_back( aDraggedItem );
}
else
layers = LSET::AllLayersMask();
return BestSnapAnchor( aOrigin, layers );
return BestSnapAnchor( aOrigin, layers, item );
}
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers )
VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
const std::vector<BOARD_ITEM*> aSkip )
{
double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale();
int snapRange = (int) ( m_snapSize / worldScale );
@ -275,7 +282,7 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLaye
clearAnchors();
for( BOARD_ITEM* item : queryVisible( bb ) )
for( BOARD_ITEM* item : queryVisible( bb, aSkip ) )
{
computeAnchors( item, aOrigin );
}

View File

@ -57,7 +57,8 @@ public:
VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, BOARD_ITEM* aItem );
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem );
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers );
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
const std::vector<BOARD_ITEM*> aSkip = {} );
void SetSnap( bool aSnap )
{
@ -94,7 +95,8 @@ private:
std::vector<ANCHOR> m_anchors;
std::set<BOARD_ITEM*> queryVisible( const BOX2I& aArea ) const;
std::set<BOARD_ITEM*> queryVisible( const BOX2I& aArea,
const std::vector<BOARD_ITEM*> aSkip ) const;
void addAnchor( const VECTOR2I& aPos, int aFlags = CORNER | SNAPPABLE, BOARD_ITEM* aItem = NULL )
{

View File

@ -364,7 +364,8 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
}
//TODO: unify the constraints to solve simultaneously instead of sequentially
m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(), snapLayers ) );
m_editedPoint->SetPosition( grid.BestSnapAnchor( evt->Position(),
snapLayers, { item } ) );
bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
@ -375,7 +376,8 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
else
m_editedPoint->ApplyConstraint();
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(), snapLayers ) );
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
snapLayers, { item } ) );
updateItem();
updatePoints();