Fix broken select connection behavior.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/19790

(cherry picked from commit 93cac7d0a5c6c94896b5f10c960ac9db4f58a436)
This commit is contained in:
Wayne Stambaugh 2025-05-01 17:02:21 -04:00
parent ae321bf186
commit c1b9d5fd85
7 changed files with 44 additions and 45 deletions

View File

@ -451,6 +451,20 @@ public:
return false; return false;
} }
/**
* Test if \a aPt is an end point of this schematic object.
*
* @note The end point test doe **not** imply electrical connectivity. See IsConnectable().
* In other words all connection points are end points but not all end points are
* connection points such as graphical lines and arcs. Override this method for all
* objects that have end points.
*
* @param aPt is the coordinate to test for an end point.
* @retval true if \a aPt is an end point.
* @retval false if \a aPt is not an end point.
*/
virtual bool IsEndPoint( const VECTOR2I& aPt ) const { return false; }
virtual bool IsDangling() const { return false; } virtual bool IsDangling() const { return false; }
virtual bool CanConnect( const SCH_ITEM* aItem ) const { return m_layer == aItem->GetLayer(); } virtual bool CanConnect( const SCH_ITEM* aItem ) const { return m_layer == aItem->GetLayer(); }

View File

@ -87,7 +87,7 @@ public:
return false; return false;
} }
bool IsEndPoint( const VECTOR2I& aPoint ) const bool IsEndPoint( const VECTOR2I& aPoint ) const override
{ {
return aPoint == m_start || aPoint == m_end; return aPoint == m_start || aPoint == m_end;
} }

View File

@ -439,33 +439,21 @@ std::set<SCH_ITEM*> SCH_SCREEN::MarkConnections( SCH_LINE* aSegment, bool aSecon
if( item->GetLayer() != line->GetLayer() ) if( item->GetLayer() != line->GetLayer() )
continue; continue;
// SCH_RTREE::Overlapping() included crossing lines.
if( !item->IsEndPoint( line->GetStartPoint() ) && !item->IsEndPoint( line->GetEndPoint() ) )
continue;
to_search.push( line );
retval.insert( line );
for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } ) for( VECTOR2I pt : { line->GetStartPoint(), line->GetEndPoint() } )
{ {
if( item->IsConnected( pt ) ) if( item->IsConnected( pt ) )
{ {
SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T ); SCH_ITEM* junction = GetItem( pt, 0, SCH_JUNCTION_T );
SCH_ITEM* pin = GetItem( pt, 0, SCH_PIN_T );
if( item->IsSelected() && aSecondPass ) if( aSecondPass && junction )
{ retval.insert( junction );
if( junction )
retval.insert( junction );
retval.insert( line );
to_search.push( line );
}
else if( !junction && !pin )
{
retval.insert( line );
to_search.push( line );
}
break;
}
else if( line->GetLayer() == LAYER_NOTES && item->GetLayer() == LAYER_NOTES )
{
retval.insert( line );
to_search.push( line );
} }
} }
} }

View File

@ -299,9 +299,13 @@ public:
/** /**
* Return all wires and junctions connected to \a aSegment which are not connected any * Return all wires and junctions connected to \a aSegment which are not connected any
* symbol pin. * symbol pin or all graphical lines connected to \a aSegement.
*
* @note This only works for line segments. It will need to be modified for connected arcs and/or
* Bezier curves.
* *
* @param aSegment The segment to test for connections. * @param aSegment The segment to test for connections.
* @return a set of all #SCH_ITEM objects connected to \a aSegment.
*/ */
std::set<SCH_ITEM*> MarkConnections( SCH_LINE* aSegment, bool aSecondPass ); std::set<SCH_ITEM*> MarkConnections( SCH_LINE* aSegment, bool aSecondPass );

View File

@ -137,6 +137,17 @@ bool SCH_SHAPE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) co
} }
bool SCH_SHAPE::IsEndPoint( const VECTOR2I& aPt ) const
{
SHAPE_T shape = GetShape();
if( ( shape == SHAPE_T::ARC ) || ( shape == SHAPE_T::BEZIER ) )
return ( aPt == GetStart() ) || ( aPt == GetEnd() );
return false;
}
void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts, void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed ) int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
{ {

View File

@ -50,6 +50,8 @@ public:
bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override; bool HitTest( const VECTOR2I& aPosition, int aAccuracy = 0 ) const override;
bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override; bool HitTest( const BOX2I& aRect, bool aContained, int aAccuracy = 0 ) const override;
bool IsEndPoint( const VECTOR2I& aPoint ) const override;
int GetPenWidth() const override { return GetStroke().GetWidth(); } int GetPenWidth() const override { return GetStroke().GetWidth(); }
bool HasLineStroke() const override { return true; } bool HasLineStroke() const override { return true; }

View File

@ -2260,8 +2260,6 @@ int SCH_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent )
if( m_selection.Empty() ) if( m_selection.Empty() )
return 0; return 0;
unsigned done = false;
m_frame->GetScreen()->ClearDrawingState(); m_frame->GetScreen()->ClearDrawingState();
for( EDA_ITEM* selItem : m_selection.GetItems() ) for( EDA_ITEM* selItem : m_selection.GetItems() )
@ -2271,26 +2269,10 @@ int SCH_SELECTION_TOOL::SelectConnection( const TOOL_EVENT& aEvent )
SCH_LINE* line = static_cast<SCH_LINE*>( selItem ); SCH_LINE* line = static_cast<SCH_LINE*>( selItem );
std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line, false ); std::set<SCH_ITEM*> conns = m_frame->GetScreen()->MarkConnections( line, line->IsConnectable() );
for( SCH_ITEM* item : conns ) for( SCH_ITEM* item : conns )
{
if( item->IsType( { SCH_ITEM_LOCATE_WIRE_T, SCH_ITEM_LOCATE_BUS_T,
SCH_ITEM_LOCATE_GRAPHIC_LINE_T } )
&& !item->IsSelected() )
{
done = true;
}
select( item ); select( item );
}
if( !done )
{
conns = m_frame->GetScreen()->MarkConnections( line, true );
for( SCH_ITEM* item : conns )
select( item );
}
} }
if( m_selection.GetSize() > 1 ) if( m_selection.GetSize() > 1 )
@ -2869,5 +2851,3 @@ void SCH_SELECTION_TOOL::setTransitions()
Go( &SCH_SELECTION_TOOL::disambiguateCursor, EVENTS::DisambiguatePoint ); Go( &SCH_SELECTION_TOOL::disambiguateCursor, EVENTS::DisambiguatePoint );
} }