Separate net updating from Edit Tracks & Vias into a second pass.

Fixes https://gitlab.com/kicad/code/kicad/issues/6858
This commit is contained in:
Jeff Young 2020-12-27 16:35:07 +00:00
parent 10e51bfea7
commit 1579ce9f9e
1 changed files with 70 additions and 54 deletions

View File

@ -23,6 +23,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#include <core/kicad_algo.h>
#include <dialogs/dialog_track_via_properties.h> #include <dialogs/dialog_track_via_properties.h>
#include <pcb_layer_box_selector.h> #include <pcb_layer_box_selector.h>
#include <tools/pcb_selection_tool.h> #include <tools/pcb_selection_tool.h>
@ -330,8 +331,7 @@ bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& cha
if( changingPads.size() == 1 ) if( changingPads.size() == 1 )
{ {
PAD* pad = *changingPads.begin(); PAD* pad = *changingPads.begin();
msg.Printf( _( "This will change the net assigned to %s pad %s to %s.\n" msg.Printf( _( "Changing the net will also update %s pad %s to %s." ),
"Do you wish to continue?" ),
pad->GetParent()->GetReference(), pad->GetParent()->GetReference(),
pad->GetName(), pad->GetName(),
m_netSelector->GetValue() ); m_netSelector->GetValue() );
@ -340,8 +340,7 @@ bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& cha
{ {
PAD* pad1 = *changingPads.begin(); PAD* pad1 = *changingPads.begin();
PAD* pad2 = *( ++changingPads.begin() ); PAD* pad2 = *( ++changingPads.begin() );
msg.Printf( _( "This will change the net assigned to %s pad %s and %s pad %s to %s.\n" msg.Printf( _( "Changing the net will also update %s pad %s and %s pad %s to %s." ),
"Do you wish to continue?" ),
pad1->GetParent()->GetReference(), pad1->GetParent()->GetReference(),
pad1->GetName(), pad1->GetName(),
pad2->GetParent()->GetReference(), pad2->GetParent()->GetReference(),
@ -350,14 +349,13 @@ bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& cha
} }
else else
{ {
msg.Printf( _( "This will change the net assigned to %lu connected pads to %s.\n" msg.Printf( _( "Changing the net will also update %lu connected pads to %s." ),
"Do you wish to continue?" ),
static_cast<unsigned long>( changingPads.size() ), static_cast<unsigned long>( changingPads.size() ),
m_netSelector->GetValue() ); m_netSelector->GetValue() );
} }
KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING ); KIDIALOG dlg( this, msg, _( "Confirmation" ), wxOK | wxCANCEL | wxICON_WARNING );
dlg.SetOKLabel( _( "Continue" ) ); dlg.SetOKCancelLabels( _( "Change Nets" ), _( "Leave Nets Unchanged" ) );
dlg.DoNotShowCheckbox( __FILE__, __LINE__ ); dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
return dlg.ShowModal() == wxID_OK; return dlg.ShowModal() == wxID_OK;
@ -366,41 +364,8 @@ bool DIALOG_TRACK_VIA_PROPERTIES::confirmPadChange( const std::vector<PAD*>& cha
bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow() bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
{ {
auto connectivity = m_frame->GetBoard()->GetConnectivity();
int newNetCode = m_netSelector->GetSelectedNetcode();
std::vector<PAD*> changingPads;
if ( !m_netSelector->IsIndeterminate() )
{
std::set<PAD*> connectedPads;
for( EDA_ITEM* item : m_items )
{
const KICAD_T ourTypes[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_FOOTPRINT_T, EOT };
auto connectedItems = connectivity->GetConnectedItems( static_cast<BOARD_CONNECTED_ITEM*>( item ), ourTypes, true );
for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
{
if( citem->Type() == PCB_PAD_T )
connectedPads.insert( static_cast<PAD*>( citem ) );
}
}
for( PAD* pad : connectedPads )
{
if( pad->GetNetCode() != newNetCode )
changingPads.push_back( pad );
}
}
// Run validations: // Run validations:
if( changingPads.size() )
{
if( !confirmPadChange( changingPads ) )
return false;
}
if( m_vias ) if( m_vias )
{ {
if( !m_viaDiameter.Validate( GEOMETRY_MIN_SIZE, INT_MAX ) if( !m_viaDiameter.Validate( GEOMETRY_MIN_SIZE, INT_MAX )
@ -432,6 +397,9 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
} }
// If we survived that, then save the changes: // If we survived that, then save the changes:
//
// We don't bother with updating the nets at this point as it will be useless (any connected
// pads will simply drive their existing nets back onto the track segments and vias).
bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED; bool changeLock = m_lockedCbox->Get3StateValue() != wxCHK_UNDETERMINED;
bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED; bool setLock = m_lockedCbox->Get3StateValue() == wxCHK_CHECKED;
@ -473,9 +441,6 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
if( changeLock ) if( changeLock )
t->SetLocked( setLock ); t->SetLocked( setLock );
if ( !m_netSelector->IsIndeterminate() )
t->SetNetCode( m_netSelector->GetSelectedNetcode() );
break; break;
} }
@ -525,7 +490,7 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
switch( v->GetViaType() ) switch( v->GetViaType() )
{ {
default: default:
wxFAIL_MSG("Unhandled via type"); wxFAIL_MSG( "Unhandled via type" );
KI_FALLTHROUGH; KI_FALLTHROUGH;
case VIATYPE::THROUGH: case VIATYPE::THROUGH:
@ -549,9 +514,6 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
v->SetDrill( m_viaDrill.GetValue() ); v->SetDrill( m_viaDrill.GetValue() );
} }
if ( !m_netSelector->IsIndeterminate() )
v->SetNetCode( m_netSelector->GetSelectedNetcode() );
if( changeLock ) if( changeLock )
v->SetLocked( setLock ); v->SetLocked( setLock );
@ -564,19 +526,73 @@ bool DIALOG_TRACK_VIA_PROPERTIES::TransferDataFromWindow()
} }
} }
m_commit.Push( _( "Edit track/via properties" ) );
// Pushing the commit will have updated the connectivity so we can now test to see if we
// need to update any pad nets.
auto connectivity = m_frame->GetBoard()->GetConnectivity();
int newNetCode = m_netSelector->GetSelectedNetcode();
bool updateNets = false;
std::vector<PAD*> changingPads;
if ( !m_netSelector->IsIndeterminate() ) if ( !m_netSelector->IsIndeterminate() )
{ {
// Commit::Push() will rebuild connectivitiy propagating nets from connected pads updateNets = true;
// outwards. We therefore have to update the connected pads in order for the net
// change to "stick". for( EDA_ITEM* item : m_items )
for( PAD* pad : changingPads )
{ {
m_commit.Modify( pad ); const KICAD_T ourTypes[] = { PCB_TRACE_T, PCB_PAD_T, PCB_VIA_T, PCB_FOOTPRINT_T, EOT };
pad->SetNetCode( m_netSelector->GetSelectedNetcode() ); BOARD_CONNECTED_ITEM* boardItem = static_cast<BOARD_CONNECTED_ITEM*>( item );
auto connectedItems = connectivity->GetConnectedItems( boardItem, ourTypes, true );
for ( BOARD_CONNECTED_ITEM* citem : connectedItems )
{
if( citem->Type() == PCB_PAD_T )
{
PAD* pad = static_cast<PAD*>( citem );
if( pad->GetNetCode() != newNetCode && !alg::contains( changingPads, citem ) )
changingPads.push_back( pad );
}
}
} }
} }
m_commit.Push( _( "Edit track/via properties" ) ); if( changingPads.size() && !confirmPadChange( changingPads ) )
updateNets = false;
if( updateNets )
{
for( EDA_ITEM* item : m_items )
{
m_commit.Modify( item );
switch( item->Type() )
{
case PCB_TRACE_T:
case PCB_ARC_T:
static_cast<TRACK*>( item )->SetNetCode( newNetCode );
break;
case PCB_VIA_T:
static_cast<VIA*>( item )->SetNetCode( newNetCode );
break;
default:
wxASSERT( false );
break;
}
}
for( PAD* pad : changingPads )
{
m_commit.Modify( pad );
pad->SetNetCode( newNetCode );
}
m_commit.Push( _( "Updating nets" ) );
}
return true; return true;
} }