Overhaul drag-select logic to handle children better.
Fixes https://gitlab.com/kicad/code/kicad/issues/6662
This commit is contained in:
parent
84e0feeee6
commit
0ad0627bb0
|
@ -1184,17 +1184,18 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
||||||
while( TOOL_EVENT* evt = Wait() )
|
while( TOOL_EVENT* evt = Wait() )
|
||||||
{
|
{
|
||||||
int width = area.GetEnd().x - area.GetOrigin().x;
|
int width = area.GetEnd().x - area.GetOrigin().x;
|
||||||
|
int height = area.GetEnd().y - area.GetOrigin().y;
|
||||||
|
|
||||||
/* Selection mode depends on direction of drag-selection:
|
/* Selection mode depends on direction of drag-selection:
|
||||||
* Left > Right : Select objects that are fully enclosed by selection
|
* Left > Right : Select objects that are fully enclosed by selection
|
||||||
* Right > Left : Select objects that are crossed by selection
|
* Right > Left : Select objects that are crossed by selection
|
||||||
*/
|
*/
|
||||||
bool windowSelection = width >= 0;
|
bool isWindowSelection = width >= 0;
|
||||||
|
|
||||||
if( view->IsMirroredX() )
|
if( view->IsMirroredX() )
|
||||||
windowSelection = !windowSelection;
|
isWindowSelection = !isWindowSelection;
|
||||||
|
|
||||||
m_frame->GetCanvas()->SetCurrentCursor( windowSelection ? KICURSOR::SELECT_WINDOW
|
m_frame->GetCanvas()->SetCurrentCursor( isWindowSelection ? KICURSOR::SELECT_WINDOW
|
||||||
: KICURSOR::SELECT_LASSO );
|
: KICURSOR::SELECT_LASSO );
|
||||||
|
|
||||||
if( evt->IsCancelInteractive() || evt->IsActivate() )
|
if( evt->IsCancelInteractive() || evt->IsActivate() )
|
||||||
|
@ -1227,79 +1228,68 @@ bool EE_SELECTION_TOOL::selectMultiple()
|
||||||
// End drawing the selection box
|
// End drawing the selection box
|
||||||
view->SetVisible( &area, false );
|
view->SetVisible( &area, false );
|
||||||
|
|
||||||
// Mark items within the selection box as selected
|
// Fetch items from the RTree that are in our area of interest
|
||||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
|
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> nearbyViewItems;
|
||||||
std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> children;
|
view->Query( area.ViewBBox(), nearbyViewItems );
|
||||||
|
|
||||||
// Filter the view items based on the selection box
|
// Build lists of nearby items and their children
|
||||||
BOX2I selectionBox = area.ViewBBox();
|
std::vector<SCH_ITEM*> nearbyItems;
|
||||||
view->Query( selectionBox, selectedItems ); // Get the list of selected items
|
std::vector<SCH_ITEM*> nearbyChildren;
|
||||||
|
|
||||||
// Some children aren't in the view; add them by hand.
|
for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : nearbyViewItems )
|
||||||
// DO NOT add them directly to selectedItems. If we add enough to cause the vector
|
|
||||||
// to grow it will re-allocate and invalidate the top-level for-loop iterator.
|
|
||||||
for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
|
|
||||||
{
|
{
|
||||||
SCH_SHEET* sheet = dynamic_cast<SCH_SHEET*>( pair.first );
|
SCH_ITEM* item = dynamic_cast<SCH_ITEM*>( pair.first );
|
||||||
|
|
||||||
if( sheet )
|
if( item )
|
||||||
{
|
{
|
||||||
int layer = pair.second;
|
item->ClearFlags( TEMP_SELECTED | STARTPOINT | ENDPOINT );
|
||||||
|
nearbyItems.push_back( item );
|
||||||
|
|
||||||
for( SCH_SHEET_PIN* pin : sheet->GetPins() )
|
item->RunOnChildren(
|
||||||
children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( pin, layer ) );
|
[&]( SCH_ITEM* aChild )
|
||||||
}
|
|
||||||
|
|
||||||
SCH_SYMBOL* symbol = dynamic_cast<SCH_SYMBOL*>( pair.first );
|
|
||||||
|
|
||||||
if( symbol )
|
|
||||||
{
|
{
|
||||||
int layer = pair.second;
|
nearbyChildren.push_back( aChild );
|
||||||
|
} );
|
||||||
for( SCH_FIELD& field : symbol->GetFields() )
|
|
||||||
children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( &field, layer ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
SCH_GLOBALLABEL* gLabel = dynamic_cast<SCH_GLOBALLABEL*>( pair.first );
|
|
||||||
|
|
||||||
if( gLabel )
|
|
||||||
{
|
|
||||||
int layer = pair.second;
|
|
||||||
SCH_FIELD* intersheetRef = gLabel->GetIntersheetRefs();
|
|
||||||
|
|
||||||
children.emplace_back( KIGFX::VIEW::LAYER_ITEM_PAIR( intersheetRef, layer ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedItems.insert( selectedItems.end(), children.begin(), children.end() );
|
EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
|
||||||
|
selectionRect.Normalize();
|
||||||
int height = area.GetEnd().y - area.GetOrigin().y;
|
|
||||||
|
|
||||||
bool anyAdded = false;
|
bool anyAdded = false;
|
||||||
bool anySubtracted = false;
|
bool anySubtracted = false;
|
||||||
|
auto selectItem =
|
||||||
// Construct an EDA_RECT to determine EDA_ITEM selection
|
[&]( SCH_ITEM* aItem )
|
||||||
EDA_RECT selectionRect( (wxPoint) area.GetOrigin(), wxSize( width, height ) );
|
|
||||||
|
|
||||||
selectionRect.Normalize();
|
|
||||||
|
|
||||||
for( KIGFX::VIEW::LAYER_ITEM_PAIR& pair : selectedItems )
|
|
||||||
{
|
{
|
||||||
EDA_ITEM* item = dynamic_cast<EDA_ITEM*>( pair.first );
|
if( m_subtractive || ( m_exclusive_or && aItem->IsSelected() ) )
|
||||||
|
|
||||||
if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) )
|
|
||||||
{
|
{
|
||||||
if( m_subtractive || ( m_exclusive_or && item->IsSelected() ) )
|
unselect( aItem );
|
||||||
{
|
|
||||||
unselect( item );
|
|
||||||
anySubtracted = true;
|
anySubtracted = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
select( item );
|
select( aItem );
|
||||||
item->SetFlags( STARTPOINT | ENDPOINT );
|
aItem->SetFlags( STARTPOINT | ENDPOINT );
|
||||||
anyAdded = true;
|
anyAdded = true;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for( SCH_ITEM* item : nearbyItems )
|
||||||
|
{
|
||||||
|
if( Selectable( item ) && item->HitTest( selectionRect, isWindowSelection ) )
|
||||||
|
{
|
||||||
|
item->SetFlags( TEMP_SELECTED );
|
||||||
|
selectItem( item );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( SCH_ITEM* item : nearbyChildren )
|
||||||
|
{
|
||||||
|
if( Selectable( item )
|
||||||
|
&& !item->GetParent()->HasFlag( TEMP_SELECTED )
|
||||||
|
&& item->HitTest( selectionRect, isWindowSelection ) )
|
||||||
|
{
|
||||||
|
selectItem( item );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue