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 ); controls->SetAutoPan( true );
auto curr_item = static_cast<BOARD_ITEM*>( selection.Front() ); 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; bool restore_state = false;
VECTOR2I totalMovement; VECTOR2I totalMovement;
GRID_HELPER grid( editFrame ); GRID_HELPER grid( editFrame );
@ -385,7 +395,8 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
if( m_dragging && evt->Category() == TC_MOUSE ) 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 ); controls->ForceCursorPosition(true, m_cursor );
VECTOR2I movement( m_cursor - prevPos ); VECTOR2I movement( m_cursor - prevPos );
selection.SetReferencePoint( m_cursor ); 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 ); editFrame->UndoRedoBlock( true );
m_cursor = controls->GetCursorPosition(); m_cursor = controls->GetCursorPosition();
@ -567,15 +569,6 @@ int EDIT_TOOL::Main( const TOOL_EVENT& aEvent )
if( unselect || restore_state ) if( unselect || restore_state )
m_toolMgr->RunAction( PCB_ACTIONS::selectionClear, true ); 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 ) if( restore_state )
m_commit->Revert(); m_commit->Revert();
else 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::set<BOARD_ITEM*> items;
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems; 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 ); BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
// The item must be visible and on an active layer // 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 ) if( view->IsVisible( item )
&& ( !isHighContrast || activeLayers.count( it.second ) ) && ( !isHighContrast || activeLayers.count( it.second ) ) )
&& !item->IsDragging() )
items.insert ( item ); items.insert ( item );
} }
for( auto ii : aSkip )
items.erase( ii );
return items; 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 ) VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem )
{ {
LSET layers; LSET layers;
std::vector<BOARD_ITEM*> item;
if( aDraggedItem ) if( aDraggedItem )
{
layers = aDraggedItem->GetLayerSet(); layers = aDraggedItem->GetLayerSet();
item.push_back( aDraggedItem );
}
else else
layers = LSET::AllLayersMask(); 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(); double worldScale = m_frame->GetGalCanvas()->GetGAL()->GetWorldScale();
int snapRange = (int) ( m_snapSize / worldScale ); int snapRange = (int) ( m_snapSize / worldScale );
@ -275,7 +282,7 @@ VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLaye
clearAnchors(); clearAnchors();
for( BOARD_ITEM* item : queryVisible( bb ) ) for( BOARD_ITEM* item : queryVisible( bb, aSkip ) )
{ {
computeAnchors( item, aOrigin ); computeAnchors( item, aOrigin );
} }

View File

@ -57,7 +57,8 @@ public:
VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, BOARD_ITEM* aItem ); VECTOR2I BestDragOrigin( const VECTOR2I& aMousePos, BOARD_ITEM* aItem );
VECTOR2I BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem ); 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 ) void SetSnap( bool aSnap )
{ {
@ -94,7 +95,8 @@ private:
std::vector<ANCHOR> m_anchors; 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 ) 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 //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 ); bool enableAltConstraint = !!evt->Modifier( MD_CTRL );
if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint if( enableAltConstraint != (bool) m_altConstraint ) // alternative constraint
@ -375,7 +376,8 @@ int POINT_EDITOR::OnSelectionChange( const TOOL_EVENT& aEvent )
else else
m_editedPoint->ApplyConstraint(); m_editedPoint->ApplyConstraint();
m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(), snapLayers ) ); m_editedPoint->SetPosition( grid.BestSnapAnchor( m_editedPoint->GetPosition(),
snapLayers, { item } ) );
updateItem(); updateItem();
updatePoints(); updatePoints();