Add wires between selected wires and unselected junctions when dragging.

Also fixes a bug where the auto-start-wire stuff was messing up the seleciton
when the selection tool wasn't at the top of the tool stack.

Fixes https://gitlab.com/kicad/code/kicad/issues/5960
This commit is contained in:
Jeff Young 2020-10-12 10:32:51 +01:00
parent 1bcefe420a
commit 0efe073dec
3 changed files with 45 additions and 29 deletions

View File

@ -496,7 +496,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
ClearSelection(); ClearSelection();
} }
else if( evt->IsMotion() && !m_isLibEdit ) else if( evt->IsMotion() && !m_isLibEdit && m_frame->ToolStackIsEmpty() )
{ {
EE_COLLECTOR collector; EE_COLLECTOR collector;
@ -540,7 +540,7 @@ int EE_SELECTION_TOOL::Main( const TOOL_EVENT& aEvent )
item = m_frame->GetItem( rolloverItem ); item = m_frame->GetItem( rolloverItem );
if( item && m_frame->ToolStackIsEmpty() ) if( item )
{ {
item->SetFlags( IS_ROLLOVER ); item->SetFlags( IS_ROLLOVER );
lastRolloverItem = rolloverItem; lastRolloverItem = rolloverItem;

View File

@ -121,7 +121,7 @@ protected:
// IS_SELECTED flag should not be set on undo items which were added for // IS_SELECTED flag should not be set on undo items which were added for
// a drag operation. // a drag operation.
if( selected && aItem->HasFlag( TEMP_SELECTED )) if( selected && aItem->HasFlag( TEMP_SELECTED ) )
aItem->ClearSelected(); aItem->ClearSelected();
if( m_isLibEdit ) if( m_isLibEdit )

View File

@ -195,7 +195,7 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
m_specialCaseLabels.clear(); m_specialCaseLabels.clear();
internalPoints.clear(); internalPoints.clear();
for( auto it : m_frame->GetScreen()->Items() ) for( SCH_ITEM* it : m_frame->GetScreen()->Items() )
{ {
it->ClearFlags( TEMP_SELECTED ); it->ClearFlags( TEMP_SELECTED );
@ -210,18 +210,18 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
{ {
// Add connections to the selection for a drag. // Add connections to the selection for a drag.
// //
for( EDA_ITEM* item : selection ) for( EDA_ITEM* edaItem : selection )
{ {
SCH_ITEM* item = static_cast<SCH_ITEM*>( edaItem );
std::vector<wxPoint> connections; std::vector<wxPoint> connections;
if( item->Type() == SCH_LINE_T ) if( item->Type() == SCH_LINE_T )
static_cast<SCH_LINE*>( item )->GetSelectedPoints( connections ); static_cast<SCH_LINE*>( item )->GetSelectedPoints( connections );
else else
connections = static_cast<SCH_ITEM*>( item )->GetConnectionPoints(); connections = item->GetConnectionPoints();
for( wxPoint point : connections ) for( wxPoint point : connections )
getConnectedDragItems( static_cast<SCH_ITEM*>( item ), point, getConnectedDragItems( item, point, m_dragAdditions );
m_dragAdditions );
} }
m_selectionTool->AddItemsToSel( &m_dragAdditions, QUIET_MODE ); m_selectionTool->AddItemsToSel( &m_dragAdditions, QUIET_MODE );
@ -503,9 +503,20 @@ int SCH_MOVE_TOOL::Main( const TOOL_EVENT& aEvent )
void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoint, void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoint,
EDA_ITEMS& aList ) EDA_ITEMS& aList )
{ {
EE_RTREE& items = m_frame->GetScreen()->Items(); EE_RTREE& items = m_frame->GetScreen()->Items();
EE_RTREE::EE_TYPE itemsOverlapping = items.Overlapping( aOriginalItem->GetBoundingBox() );
bool ptHasJunction = false;
for( SCH_ITEM *test : items.Overlapping( aOriginalItem->GetBoundingBox() ) ) for( SCH_ITEM* item : itemsOverlapping )
{
if( item->Type() == SCH_JUNCTION_T && item->IsConnected( aPoint ) )
{
ptHasJunction = true;
break;
}
}
for( SCH_ITEM *test : itemsOverlapping )
{ {
if( test == aOriginalItem || test->IsSelected() || !test->CanConnect( aOriginalItem ) ) if( test == aOriginalItem || test->IsSelected() || !test->CanConnect( aOriginalItem ) )
continue; continue;
@ -516,9 +527,12 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
{ {
case SCH_LINE_T: case SCH_LINE_T:
{ {
// Select the connected end of wires/bus connections. // Select the connected end of wires/bus connections that don't have a junction to
// isolate them from the drag
if( ptHasJunction )
break;
SCH_LINE* testLine = static_cast<SCH_LINE*>( test ); SCH_LINE* testLine = static_cast<SCH_LINE*>( test );
wxPoint otherEnd;
if( testLine->GetStartPoint() == aPoint ) if( testLine->GetStartPoint() == aPoint )
{ {
@ -526,7 +540,6 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
aList.push_back( testLine ); aList.push_back( testLine );
testLine->SetFlags( STARTPOINT | TEMP_SELECTED ); testLine->SetFlags( STARTPOINT | TEMP_SELECTED );
otherEnd = testLine->GetEndPoint();
} }
else if( testLine->GetEndPoint() == aPoint ) else if( testLine->GetEndPoint() == aPoint )
{ {
@ -534,7 +547,6 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
aList.push_back( testLine ); aList.push_back( testLine );
testLine->SetFlags( ENDPOINT | TEMP_SELECTED ); testLine->SetFlags( ENDPOINT | TEMP_SELECTED );
otherEnd = testLine->GetStartPoint();
} }
else else
{ {
@ -544,22 +556,26 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
// Since only one end is going to move, the movement vector of any labels attached // Since only one end is going to move, the movement vector of any labels attached
// to it is scaled by the proportion of the line length the label is from the moving // to it is scaled by the proportion of the line length the label is from the moving
// end. // end.
for( SCH_ITEM* item : m_frame->GetScreen()->Items().OfType( SCH_LABEL_T ) ) for( SCH_ITEM* item : itemsOverlapping )
{ {
if( item->IsSelected() ) if( item->Type() == SCH_LABEL_T )
continue; // These will be moved on their own because they're selected
if( item->CanConnect( testLine ) && testLine->HitTest( item->GetPosition(), 1 ) )
{ {
SCH_TEXT* label = static_cast<SCH_TEXT*>( item ); SCH_TEXT* label = static_cast<SCH_TEXT*>( item );
if( !label->HasFlag( TEMP_SELECTED ) ) if( label->IsSelected() )
aList.push_back( label ); continue; // These will be moved on their own because they're selected
SPECIAL_CASE_LABEL_INFO info; if( label->CanConnect( testLine )
info.attachedLine = testLine; && testLine->HitTest( label->GetPosition(), 1 ) )
info.originalLabelPos = label->GetPosition(); {
m_specialCaseLabels[label] = info; if( !label->HasFlag( TEMP_SELECTED ) )
aList.push_back( label );
SPECIAL_CASE_LABEL_INFO info;
info.attachedLine = testLine;
info.originalLabelPos = label->GetPosition();
m_specialCaseLabels[label] = info;
}
} }
} }
@ -572,10 +588,11 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
break; break;
case SCH_COMPONENT_T: case SCH_COMPONENT_T:
case SCH_JUNCTION_T:
if( test->IsConnected( aPoint ) ) if( test->IsConnected( aPoint ) )
{ {
// Add a new wire between the component and the selected item so the selected // Add a new wire between the component or junction and the selected item so
// item can be dragged. // the selected item can be dragged.
SCH_LINE* newWire = new SCH_LINE( aPoint, LAYER_WIRE ); SCH_LINE* newWire = new SCH_LINE( aPoint, LAYER_WIRE );
newWire->SetFlags( IS_NEW ); newWire->SetFlags( IS_NEW );
m_frame->AddToScreen( newWire, m_frame->GetScreen() ); m_frame->AddToScreen( newWire, m_frame->GetScreen() );
@ -586,8 +603,7 @@ void SCH_MOVE_TOOL::getConnectedDragItems( SCH_ITEM* aOriginalItem, wxPoint aPoi
break; break;
case SCH_NO_CONNECT_T: case SCH_NO_CONNECT_T:
case SCH_JUNCTION_T: // Select no-connects that are connected to items being moved.
// Select no-connects and junctions that are connected to items being moved.
if( !test->HasFlag( TEMP_SELECTED ) && test->IsConnected( aPoint ) ) if( !test->HasFlag( TEMP_SELECTED ) && test->IsConnected( aPoint ) )
{ {
aList.push_back( test ); aList.push_back( test );