From e20a11cbb31a311b0c57db0c0ea29c7b904cc3df Mon Sep 17 00:00:00 2001 From: John Beard Date: Thu, 23 May 2024 11:25:28 +0800 Subject: [PATCH] Eeschema: Fix selection of items inside filled shapes The selection heuristic broke down when one item was a filled shape. Because all hit tests would succeed with distance 0 for these shapes, they would always be considered the closest item to the exclusion of all else, which made it very hard to click on a graphic inside a filled shape. Now, recognise when an item would be "dominating" and decline to promote it to the "closet" spot. It will still be selectable if there are no other items nearby, or if there are multiple shapes. (cherry picked from commit fd4c15517f6d1f914e61207cea2c447db16e3807) --- eeschema/tools/ee_selection_tool.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/eeschema/tools/ee_selection_tool.cpp b/eeschema/tools/ee_selection_tool.cpp index 735b231440..b3871937e5 100644 --- a/eeschema/tools/ee_selection_tool.cpp +++ b/eeschema/tools/ee_selection_tool.cpp @@ -1472,6 +1472,11 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const BOX2I bbox = item->GetBoundingBox(); int dist = INT_MAX / 4; + // A dominating item is one that would unfairly win distance tests + // and mask out other items. For example, a filled rectangle "wins" + // with a zero distance over anything inside it. + bool dominating = false; + if( exactHits.count( item ) ) { if( item->Type() == SCH_PIN_T || item->Type() == SCH_JUNCTION_T ) @@ -1528,6 +1533,9 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const delete s; } + + // Filled shapes win hit tests anywhere inside them + dominating = shape->IsFilled(); } else if( symbol ) { @@ -1551,15 +1559,21 @@ void EE_SELECTION_TOOL::GuessSelectionCandidates( EE_COLLECTOR& collector, const rect.Collide( poss, collector.m_Threshold, &dist ); } - if( dist == closestDist ) + // Don't promote dominating items to be the closest item + // (they'll always win) - they'll still be available for selection, but they + // won't boot out worthy competitors. + if ( !dominating ) { - if( item->GetParent() == closest ) + if( dist == closestDist ) + { + if( item->GetParent() == closest ) + closest = item; + } + else if( dist < closestDist ) + { + closestDist = dist; closest = item; - } - else if( dist < closestDist ) - { - closestDist = dist; - closest = item; + } } }