Don't allow selection crossing a parent/child relationship.
Fixes https://gitlab.com/kicad/code/kicad/issues/8292 Fixes https://gitlab.com/kicad/code/kicad/issues/7255
This commit is contained in:
parent
e06a3cf3b4
commit
5bf37a9b24
|
@ -296,7 +296,7 @@ int EDIT_TOOL::Drag( const TOOL_EVENT& aEvent )
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
},
|
},
|
||||||
!m_isFootprintEditor /* prompt user regarding locked items */ );
|
!m_isFootprintEditor /* prompt user regarding locked items */ );
|
||||||
|
|
||||||
|
@ -1439,7 +1439,7 @@ int EDIT_TOOL::Rotate( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
},
|
},
|
||||||
!m_dragging && !m_isFootprintEditor /* prompt user regarding locked items */ );
|
!m_dragging && !m_isFootprintEditor /* prompt user regarding locked items */ );
|
||||||
|
|
||||||
|
@ -1574,7 +1574,7 @@ int EDIT_TOOL::Mirror( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
},
|
},
|
||||||
!m_dragging && !m_isFootprintEditor /* prompt user regarding locked items */ );
|
!m_dragging && !m_isFootprintEditor /* prompt user regarding locked items */ );
|
||||||
|
|
||||||
|
@ -1698,7 +1698,7 @@ int EDIT_TOOL::Flip( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
},
|
},
|
||||||
!m_dragging && !m_isFootprintEditor/* prompt user regarding locked items */ );
|
!m_dragging && !m_isFootprintEditor/* prompt user regarding locked items */ );
|
||||||
|
|
||||||
|
@ -1991,7 +1991,7 @@ int EDIT_TOOL::MoveExact( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
},
|
},
|
||||||
!m_isFootprintEditor /* prompt user regarding locked items */ );
|
!m_isFootprintEditor /* prompt user regarding locked items */ );
|
||||||
|
|
||||||
|
@ -2113,7 +2113,7 @@ int EDIT_TOOL::Duplicate( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( selection.Empty() )
|
if( selection.Empty() )
|
||||||
|
@ -2280,7 +2280,7 @@ int EDIT_TOOL::CreateArray( const TOOL_EVENT& aEvent )
|
||||||
for( BOARD_ITEM* item : added_items )
|
for( BOARD_ITEM* item : added_items )
|
||||||
aCollector.Append( item );
|
aCollector.Append( item );
|
||||||
|
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
if( selection.Empty() )
|
if( selection.Empty() )
|
||||||
|
|
|
@ -202,7 +202,7 @@ int GLOBAL_EDIT_TOOL::RemoveUnusedPads( const TOOL_EVENT& aEvent )
|
||||||
PCB_SELECTION& selection = m_selectionTool->RequestSelection(
|
PCB_SELECTION& selection = m_selectionTool->RequestSelection(
|
||||||
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
|
[]( const VECTOR2I& aPt, GENERAL_COLLECTOR& aCollector, PCB_SELECTION_TOOL* sTool )
|
||||||
{
|
{
|
||||||
sTool->FilterCollectorForGroups( aCollector );
|
sTool->FilterCollectorForHierarchy( aCollector );
|
||||||
} );
|
} );
|
||||||
DIALOG_UNUSED_PAD_LAYERS dlg( editFrame, selection, *m_commit );
|
DIALOG_UNUSED_PAD_LAYERS dlg( editFrame, selection, *m_commit );
|
||||||
|
|
||||||
|
|
|
@ -707,7 +707,7 @@ bool PCB_SELECTION_TOOL::selectPoint( const VECTOR2I& aWhere, bool aOnDrag,
|
||||||
// Apply the stateful filter
|
// Apply the stateful filter
|
||||||
FilterCollectedItems( collector );
|
FilterCollectedItems( collector );
|
||||||
|
|
||||||
FilterCollectorForGroups( collector );
|
FilterCollectorForHierarchy( collector );
|
||||||
|
|
||||||
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
|
// Apply some ugly heuristics to avoid disambiguation menus whenever possible
|
||||||
if( collector.GetCount() > 1 && !m_skip_heuristics )
|
if( collector.GetCount() > 1 && !m_skip_heuristics )
|
||||||
|
@ -809,8 +809,8 @@ bool PCB_SELECTION_TOOL::selectMultiple()
|
||||||
if( view->IsMirroredX() )
|
if( view->IsMirroredX() )
|
||||||
windowSelection = !windowSelection;
|
windowSelection = !windowSelection;
|
||||||
|
|
||||||
m_frame->GetCanvas()->SetCurrentCursor(
|
m_frame->GetCanvas()->SetCurrentCursor( windowSelection ? KICURSOR::SELECT_WINDOW
|
||||||
windowSelection ? KICURSOR::SELECT_WINDOW : KICURSOR::SELECT_LASSO );
|
: KICURSOR::SELECT_LASSO );
|
||||||
|
|
||||||
if( evt->IsCancelInteractive() || evt->IsActivate() )
|
if( evt->IsCancelInteractive() || evt->IsActivate() )
|
||||||
{
|
{
|
||||||
|
@ -872,7 +872,7 @@ bool PCB_SELECTION_TOOL::selectMultiple()
|
||||||
// Apply the stateful filter
|
// Apply the stateful filter
|
||||||
FilterCollectedItems( collector );
|
FilterCollectedItems( collector );
|
||||||
|
|
||||||
FilterCollectorForGroups( collector );
|
FilterCollectorForHierarchy( collector );
|
||||||
|
|
||||||
for( EDA_ITEM* i : collector )
|
for( EDA_ITEM* i : collector )
|
||||||
{
|
{
|
||||||
|
@ -2515,11 +2515,22 @@ void PCB_SELECTION_TOOL::GuessSelectionCandidates( GENERAL_COLLECTOR& aCollector
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PCB_SELECTION_TOOL::FilterCollectorForGroups( GENERAL_COLLECTOR& aCollector ) const
|
void PCB_SELECTION_TOOL::FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollector ) const
|
||||||
{
|
{
|
||||||
std::unordered_set<BOARD_ITEM*> toAdd;
|
std::unordered_set<BOARD_ITEM*> toAdd;
|
||||||
|
|
||||||
// If any element is a member of a group, replace those elements with the top containing group.
|
// Set TEMP_SELECTED on all parents which are included in the GENERAL_COLLECTOR. This
|
||||||
|
// algorithm is O3n, whereas checking for the parent inclusion could potentially be On^2.
|
||||||
|
|
||||||
|
for( int j = 0; j < aCollector.GetCount(); j++ )
|
||||||
|
{
|
||||||
|
if( aCollector[j]->GetParent() )
|
||||||
|
aCollector[j]->GetParent()->ClearFlags( TEMP_SELECTED );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int j = 0; j < aCollector.GetCount(); j++ )
|
||||||
|
aCollector[j]->SetFlags( TEMP_SELECTED );
|
||||||
|
|
||||||
for( int j = 0; j < aCollector.GetCount(); )
|
for( int j = 0; j < aCollector.GetCount(); )
|
||||||
{
|
{
|
||||||
BOARD_ITEM* item = aCollector[j];
|
BOARD_ITEM* item = aCollector[j];
|
||||||
|
@ -2529,6 +2540,8 @@ void PCB_SELECTION_TOOL::FilterCollectorForGroups( GENERAL_COLLECTOR& aCollector
|
||||||
if( !m_isFootprintEditor && parent && parent->Type() == PCB_FOOTPRINT_T )
|
if( !m_isFootprintEditor && parent && parent->Type() == PCB_FOOTPRINT_T )
|
||||||
start = parent;
|
start = parent;
|
||||||
|
|
||||||
|
// If any element is a member of a group, replace those elements with the top containing
|
||||||
|
// group.
|
||||||
PCB_GROUP* aTop = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, m_isFootprintEditor );
|
PCB_GROUP* aTop = PCB_GROUP::TopLevelGroup( start, m_enteredGroup, m_isFootprintEditor );
|
||||||
|
|
||||||
if( aTop )
|
if( aTop )
|
||||||
|
@ -2536,6 +2549,8 @@ void PCB_SELECTION_TOOL::FilterCollectorForGroups( GENERAL_COLLECTOR& aCollector
|
||||||
if( aTop != item )
|
if( aTop != item )
|
||||||
{
|
{
|
||||||
toAdd.insert( aTop );
|
toAdd.insert( aTop );
|
||||||
|
aTop->SetFlags( TEMP_SELECTED );
|
||||||
|
|
||||||
aCollector.Remove( item );
|
aCollector.Remove( item );
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -2548,6 +2563,14 @@ void PCB_SELECTION_TOOL::FilterCollectorForGroups( GENERAL_COLLECTOR& aCollector
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Footprints are a bit easier as they can't be nested.
|
||||||
|
if( parent && parent->GetFlags() & TEMP_SELECTED )
|
||||||
|
{
|
||||||
|
// Remove children of selected items
|
||||||
|
aCollector.Remove( item );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
++j;
|
++j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,10 +186,14 @@ public:
|
||||||
*/
|
*/
|
||||||
void ExitGroup( bool aSelectGroup = false );
|
void ExitGroup( bool aSelectGroup = false );
|
||||||
|
|
||||||
void FilterCollectorForGroups( GENERAL_COLLECTOR& aCollector ) const;
|
|
||||||
|
|
||||||
PCB_GROUP* GetEnteredGroup() { return m_enteredGroup; }
|
PCB_GROUP* GetEnteredGroup() { return m_enteredGroup; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* In general we don't want to select both a parent and any of it's children. This includes
|
||||||
|
* both footprints and their items, and groups and their members.
|
||||||
|
*/
|
||||||
|
void FilterCollectorForHierarchy( GENERAL_COLLECTOR& aCollector ) const;
|
||||||
|
|
||||||
///< Apply the SELECTION_FILTER_OPTIONS to a collection of items
|
///< Apply the SELECTION_FILTER_OPTIONS to a collection of items
|
||||||
void FilterCollectedItems( GENERAL_COLLECTOR& aCollector );
|
void FilterCollectedItems( GENERAL_COLLECTOR& aCollector );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue