From 63e638cfab0590bf570cc7d649ceedfbde681650 Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Tue, 12 Jul 2022 10:46:45 -0700 Subject: [PATCH] Enforce group selection to abide by L/R behavior When selecting greedy (right to left), selecting any part of the group will get the whole group. When selecting left to right, we must select all items in the group to get the grouped items unless we are in the group itself Fixes https://gitlab.com/kicad/code/kicad/issues/11902 (cherry picked from commit e87ba10a5ac428d6c5823e9a4da601231a53ad1a) --- pcbnew/tools/pcb_selection_tool.cpp | 32 +++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/pcbnew/tools/pcb_selection_tool.cpp b/pcbnew/tools/pcb_selection_tool.cpp index 23ba659a38..20982b06ee 100644 --- a/pcbnew/tools/pcb_selection_tool.cpp +++ b/pcbnew/tools/pcb_selection_tool.cpp @@ -797,12 +797,12 @@ bool PCB_SELECTION_TOOL::selectMultiple() * Left > Right : Select objects that are fully enclosed by selection * Right > Left : Select objects that are crossed by selection */ - bool windowSelection = width >= 0 ? true : false; + bool greedySelection = width >= 0 ? false : true; if( view->IsMirroredX() ) - windowSelection = !windowSelection; + greedySelection = !greedySelection; - m_frame->GetCanvas()->SetCurrentCursor( windowSelection ? KICURSOR::SELECT_WINDOW + m_frame->GetCanvas()->SetCurrentCursor( !greedySelection ? KICURSOR::SELECT_WINDOW : KICURSOR::SELECT_LASSO ); if( evt->IsCancelInteractive() || evt->IsActivate() ) @@ -853,13 +853,37 @@ bool PCB_SELECTION_TOOL::selectMultiple() selectionRect.Normalize(); GENERAL_COLLECTOR collector; + std::set group_items; + + for( PCB_GROUP* group : board()->Groups() ) + { + // The currently entered group does not get limited + if( m_enteredGroup == group ) + continue; + + std::unordered_set& newset = group->GetItems(); + + // If we are not greedy and have selected the whole group, add just one item + // to allow it to be promoted to the group later + if( !greedySelection && selectionRect.Contains( group->GetBoundingBox() ) + && newset.size() ) + { + collector.Append( *newset.begin() ); + } + + for( BOARD_ITEM* group_item : newset ) + group_items.emplace( group_item ); + } for( auto it = candidates.begin(), it_end = candidates.end(); it != it_end; ++it ) { BOARD_ITEM* item = static_cast( it->first ); - if( item && Selectable( item ) && item->HitTest( selectionRect, windowSelection ) ) + if( item && Selectable( item ) && item->HitTest( selectionRect, !greedySelection ) + && ( greedySelection || !group_items.count( item ) ) ) + { collector.Append( item ); + } } // Apply the stateful filter