Fix handling of SCH_PINs on multi-unit parts

Fixes https://gitlab.com/kicad/code/kicad/issues/3770
This commit is contained in:
Jon Evans 2020-01-16 21:33:16 -05:00
parent 0645442704
commit ac875e26a8
19 changed files with 191 additions and 126 deletions

View File

@ -396,20 +396,14 @@ void CONNECTION_GRAPH::Recalculate( const SCH_SHEET_LIST& aSheetList, bool aUnco
}
updateItemConnectivity( sheet, items );
// UpdateDanglingState() also adds connected items for SCH_TEXT
sheet.LastScreen()->TestDanglingEnds( &sheet );
}
update_items.Stop();
wxLogTrace( "CONN_PROFILE", "UpdateItemConnectivity() %0.4f ms", update_items.msecs() );
PROF_COUNTER tde;
// IsDanglingStateChanged() also adds connected items for things like SCH_TEXT
SCH_SCREENS schematic;
schematic.TestDanglingEnds();
tde.Stop();
wxLogTrace( "CONN_PROFILE", "TestDanglingEnds() %0.4f ms", tde.msecs() );
PROF_COUNTER build_graph;
buildConnectionGraph();
@ -442,7 +436,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
{
std::vector< wxPoint > points;
item->GetConnectionPoints( points );
item->ConnectedItems().clear();
item->ConnectedItems( aSheet ).clear();
if( item->Type() == SCH_SHEET_T )
{
@ -453,7 +447,7 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
pin->InitializeConnection( aSheet );
}
pin->ConnectedItems().clear();
pin->ConnectedItems( aSheet ).clear();
pin->Connection( aSheet )->Reset();
connection_map[ pin->GetTextPos() ].push_back( pin );
@ -465,26 +459,31 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
SCH_COMPONENT* component = static_cast<SCH_COMPONENT*>( item );
TRANSFORM t = component->GetTransform();
// Assumption: we don't need to call UpdatePins() here because anything
// that would change the pins of the component will have called it already
// TODO(JE) right now this relies on GetSchPins() returning good SCH_PIN pointers
// that contain good LIB_PIN pointers. Since these get invalidated whenever the
// library component is refreshed, the current solution as of ed025972 is to just
// rebuild the SCH_PIN list when the component is refreshed, and then re-run the
// connectivity calculations. This is slow and should be improved before release.
// See https://gitlab.com/kicad/code/kicad/issues/3784
for( SCH_PIN& pin : component->GetPins() )
for( SCH_PIN* pin : component->GetSchPins( &aSheet ) )
{
pin.InitializeConnection( aSheet );
pin->InitializeConnection( aSheet );
wxPoint pos = t.TransformCoordinate( pin.GetPosition() ) + component->GetPosition();
wxPoint pos = t.TransformCoordinate( pin->GetPosition() ) +
component->GetPosition();
// because calling the first time is not thread-safe
pin.GetDefaultNetName( aSheet );
pin.ConnectedItems().clear();
pin->GetDefaultNetName( aSheet );
pin->ConnectedItems( aSheet ).clear();
// Invisible power pins need to be post-processed later
if( pin.IsPowerConnection() && !pin.IsVisible() )
m_invisible_power_pins.emplace_back( std::make_pair( aSheet, &pin ) );
if( pin->IsPowerConnection() && !pin->IsVisible() )
m_invisible_power_pins.emplace_back( std::make_pair( aSheet, pin ) );
connection_map[ pos ].push_back( &pin );
m_items.insert( &pin );
connection_map[ pos ].push_back( pin );
m_items.insert( pin );
}
}
else
@ -580,8 +579,8 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
else
bus_entry->m_connected_bus_items[1] = bus;
bus_entry->ConnectedItems().insert( bus );
bus->ConnectedItems().insert( bus_entry );
bus_entry->ConnectedItems( aSheet ).insert( bus );
bus->ConnectedItems( aSheet ).insert( bus_entry );
}
}
}
@ -594,8 +593,8 @@ void CONNECTION_GRAPH::updateItemConnectivity( SCH_SHEET_PATH aSheet,
connected_item->ConnectionPropagatesTo( test_item ) &&
test_item->ConnectionPropagatesTo( connected_item ) )
{
connected_item->ConnectedItems().insert( test_item );
test_item->ConnectedItems().insert( connected_item );
connected_item->ConnectedItems( aSheet ).insert( test_item );
test_item->ConnectedItems( aSheet ).insert( connected_item );
}
// Set up the link between the bus entry net and the bus
@ -688,8 +687,8 @@ void CONNECTION_GRAPH::buildConnectionGraph()
return ( conn->SubgraphCode() == 0 );
};
std::copy_if( item->ConnectedItems().begin(),
item->ConnectedItems().end(),
std::copy_if( item->ConnectedItems( sheet ).begin(),
item->ConnectedItems( sheet ).end(),
std::back_inserter( members ), get_items );
for( auto connected_item : members )
@ -706,8 +705,8 @@ void CONNECTION_GRAPH::buildConnectionGraph()
connected_conn->SetSubgraphCode( subgraph->m_code );
subgraph->AddItem( connected_item );
std::copy_if( connected_item->ConnectedItems().begin(),
connected_item->ConnectedItems().end(),
std::copy_if( connected_item->ConnectedItems( sheet ).begin(),
connected_item->ConnectedItems( sheet ).end(),
std::back_inserter( members ), get_items );
}
}
@ -913,15 +912,15 @@ void CONNECTION_GRAPH::buildConnectionGraph()
for( const auto& it : m_invisible_power_pins )
{
SCH_PIN* pin = it.second;
SCH_SHEET_PATH sheet = it.first;
SCH_PIN* pin = it.second;
if( !pin->ConnectedItems().empty() && !pin->GetLibPin()->GetParent()->IsPower() )
if( !pin->ConnectedItems( sheet ).empty() && !pin->GetLibPin()->GetParent()->IsPower() )
{
// ERC will warn about this: user has wired up an invisible pin
continue;
}
SCH_SHEET_PATH sheet = it.first;
SCH_CONNECTION* connection = pin->Connection( sheet );
if( !connection )

View File

@ -551,7 +551,7 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets( bool aUseGraph )
}
// Netlist ordering: Net name, then ref des, then pin name
std::sort( sorted_items.begin(), sorted_items.end(), []( auto a, auto b ) {
std::sort( sorted_items.begin(), sorted_items.end(), [] ( auto a, auto b ) {
auto ref_a = a.first->GetParentComponent()->GetRef( &a.second );
auto ref_b = b.first->GetParentComponent()->GetRef( &b.second );
@ -561,6 +561,17 @@ XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets( bool aUseGraph )
return ref_a < ref_b;
} );
// Some duplicates can exist, for example on multi-unit parts with duplicated
// pins across units. If the user connects the pins on each unit, they will
// appear on separate subgraphs. Remove those here:
sorted_items.erase( std::unique( sorted_items.begin(), sorted_items.end(),
[] ( auto a, auto b ) {
auto ref_a = a.first->GetParentComponent()->GetRef( &a.second );
auto ref_b = b.first->GetParentComponent()->GetRef( &b.second );
return ref_a == ref_b && a.first->GetNumber() == b.first->GetNumber();
} ), sorted_items.end() );
for( const auto& pair : sorted_items )
{
SCH_PIN* pin = pair.first;

View File

@ -187,7 +187,8 @@ void SCH_BUS_ENTRY_BASE::Rotate( wxPoint aPosition )
}
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
bool previousStateStart = m_isDanglingStart;
bool previousStateEnd = m_isDanglingEnd;
@ -249,7 +250,8 @@ bool SCH_BUS_WIRE_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aI
}
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_BUS_BUS_ENTRY::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
bool previousStateStart = m_isDanglingStart;
bool previousStateEnd = m_isDanglingEnd;

View File

@ -157,7 +157,8 @@ public:
BITMAP_DEF GetMenuImage() const override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
/**
* Pointer to the bus item (usually a bus wire) connected to this bus-wire
@ -201,7 +202,8 @@ public:
BITMAP_DEF GetMenuImage() const override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
/**
* Pointer to the bus items (usually bus wires) connected to this bus-bus

View File

@ -456,31 +456,26 @@ void SCH_COMPONENT::ResolveAll(
}
void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
void SCH_COMPONENT::UpdatePins()
{
m_pins.clear();
m_pinMap.clear();
if( m_part )
{
SCH_PIN_MAP map;
unsigned i = 0;
for( LIB_PIN* libPin = m_part->GetNextPin(); libPin; libPin = m_part->GetNextPin( libPin ) )
{
wxASSERT( libPin->Type() == LIB_PIN_T );
if( libPin->GetUnit() && m_unit && ( m_unit != libPin->GetUnit() ) )
continue;
if( libPin->GetConvert() && m_convert && ( m_convert != libPin->GetConvert() ) )
continue;
m_pins.emplace_back( SCH_PIN( libPin, this ) );
m_pins.push_back( std::unique_ptr<SCH_PIN>( new SCH_PIN( libPin, this ) ) );
m_pinMap[ libPin ] = i;
if( aSheet )
m_pins[ i ].InitializeConnection( *aSheet );
++i;
}
}
@ -490,7 +485,7 @@ void SCH_COMPONENT::UpdatePins( SCH_SHEET_PATH* aSheet )
SCH_CONNECTION* SCH_COMPONENT::GetConnectionForPin( LIB_PIN* aPin, const SCH_SHEET_PATH& aSheet )
{
if( m_pinMap.count( aPin ) )
return m_pins[ m_pinMap.at( aPin ) ].Connection( aSheet );
return m_pins[ m_pinMap[aPin] ]->Connection( aSheet );
return nullptr;
}
@ -757,7 +752,7 @@ void SCH_COMPONENT::SetTimeStamp( timestamp_t aNewTimeStamp )
}
int SCH_COMPONENT::GetUnitSelection( SCH_SHEET_PATH* aSheet )
int SCH_COMPONENT::GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const
{
wxString path = GetPath( aSheet );
wxString h_path, h_multi;
@ -785,7 +780,7 @@ int SCH_COMPONENT::GetUnitSelection( SCH_SHEET_PATH* aSheet )
}
void SCH_COMPONENT::SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection )
void SCH_COMPONENT::SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection )
{
wxString path = GetPath( aSheet );
@ -978,6 +973,27 @@ void SCH_COMPONENT::GetPins( std::vector<LIB_PIN*>& aPinsList )
}
SCH_PIN_PTRS SCH_COMPONENT::GetSchPins( const SCH_SHEET_PATH* aSheet ) const
{
if( aSheet == nullptr )
aSheet = g_CurrentSheet;
// TODO(JE) if this works, consider caching in m_sheet_pins
int unit = GetUnitSelection( aSheet );
SCH_PIN_PTRS ptrs;
for( const auto& p : m_pins )
{
if( unit && p->GetLibPin()->GetUnit() && ( p->GetLibPin()->GetUnit() != unit ) )
continue;
ptrs.push_back( p.get() );
}
return ptrs;
}
void SCH_COMPONENT::SwapData( SCH_ITEM* aItem )
{
wxCHECK_RET( (aItem != NULL) && (aItem->Type() == SCH_COMPONENT_T),
@ -1508,16 +1524,17 @@ void SCH_COMPONENT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
}
bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
bool changed = false;
for( SCH_PIN& pin : m_pins )
for( auto& pin : m_pins )
{
bool previousState = pin.IsDangling();
pin.SetIsDangling( true );
bool previousState = pin->IsDangling();
pin->SetIsDangling( true );
wxPoint pos = m_transform.TransformCoordinate( pin.GetPosition() ) + m_Pos;
wxPoint pos = m_transform.TransformCoordinate( pin->GetPosition() ) + m_Pos;
for( DANGLING_END_ITEM& each_item : aItemList )
{
@ -1539,7 +1556,7 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
case JUNCTION_END:
if( pos == each_item.GetPosition() )
pin.SetIsDangling( false );
pin->SetIsDangling( false );
break;
@ -1547,11 +1564,11 @@ bool SCH_COMPONENT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemLi
break;
}
if( !pin.IsDangling() )
if( !pin->IsDangling() )
break;
}
changed = ( changed || ( previousState != pin.IsDangling() ) );
changed = ( changed || ( previousState != pin->IsDangling() ) );
}
return changed;
@ -1569,8 +1586,8 @@ wxPoint SCH_COMPONENT::GetPinPhysicalPosition( const LIB_PIN* Pin ) const
void SCH_COMPONENT::GetConnectionPoints( std::vector< wxPoint >& aPoints ) const
{
for( const SCH_PIN& pin : m_pins )
aPoints.push_back( m_transform.TransformCoordinate( pin.GetPosition() ) + m_Pos );
for( const auto& pin : m_pins )
aPoints.push_back( m_transform.TransformCoordinate( pin->GetPosition() ) + m_Pos );
}
@ -1648,9 +1665,9 @@ SEARCH_RESULT SCH_COMPONENT::Visit( INSPECTOR aInspector, void* aTestData,
if( stype == SCH_LOCATE_ANY_T || stype == SCH_PIN_T )
{
for( SCH_PIN& pin : m_pins )
for( auto& pin : m_pins )
{
if( SEARCH_RESULT::QUIT == aInspector( &pin, (void*) this ) )
if( SEARCH_RESULT::QUIT == aInspector( pin.get(), (void*) this ) )
return SEARCH_RESULT::QUIT;
}
}
@ -1821,9 +1838,9 @@ bool SCH_COMPONENT::doIsConnected( const wxPoint& aPosition ) const
{
wxPoint new_pos = m_transform.InverseTransform().TransformCoordinate( aPosition - m_Pos );
for( const SCH_PIN& pin : m_pins )
for( const auto& pin : m_pins )
{
if( pin.GetPosition() == new_pos )
if( pin->GetPosition() == new_pos )
return true;
}
@ -1858,9 +1875,9 @@ void SCH_COMPONENT::Plot( PLOTTER* aPlotter )
bool SCH_COMPONENT::HasBrightenedPins()
{
for( const SCH_PIN& pin : m_pins )
for( const auto& pin : m_pins )
{
if( pin.IsBrightened() )
if( pin->IsBrightened() )
return true;
}
@ -1870,30 +1887,30 @@ bool SCH_COMPONENT::HasBrightenedPins()
void SCH_COMPONENT::ClearBrightenedPins()
{
for( SCH_PIN& pin : m_pins )
pin.ClearBrightened();
for( auto& pin : m_pins )
pin->ClearBrightened();
}
void SCH_COMPONENT::BrightenPin( LIB_PIN* aPin )
{
if( m_pinMap.count( aPin ) )
m_pins[ m_pinMap.at( aPin ) ].SetBrightened();
m_pins[ m_pinMap.at( aPin ) ]->SetBrightened();
}
void SCH_COMPONENT::ClearHighlightedPins()
{
for( SCH_PIN& pin : m_pins )
pin.ClearHighlighted();
for( auto& pin : m_pins )
pin->ClearHighlighted();
}
bool SCH_COMPONENT::HasHighlightedPins()
{
for( const SCH_PIN& pin : m_pins )
for( const auto& pin : m_pins )
{
if( pin.IsHighlighted() )
if( pin->IsHighlighted() )
return true;
}
@ -1904,7 +1921,7 @@ bool SCH_COMPONENT::HasHighlightedPins()
void SCH_COMPONENT::HighlightPin( LIB_PIN* aPin )
{
if( m_pinMap.count( aPin ) )
m_pins[ m_pinMap.at( aPin ) ].SetHighlighted();
m_pins[ m_pinMap.at( aPin ) ]->SetHighlighted();
}

View File

@ -68,7 +68,9 @@ class SYMBOL_LIB_TABLE;
/// A container for several SCH_PIN items
typedef std::vector<SCH_PIN> SCH_PINS;
typedef std::vector<std::unique_ptr<SCH_PIN>> SCH_PINS;
typedef std::vector<SCH_PIN*> SCH_PIN_PTRS;
/// A map from the library pin pointer to the SCH_PIN's index
typedef std::unordered_map<LIB_PIN*, unsigned> SCH_PIN_MAP;
@ -112,8 +114,8 @@ private:
///< A flattened copy of a LIB_PART found in the PROJECT's libraries to for this component.
std::unique_ptr< LIB_PART > m_part;
SCH_PINS m_pins; ///< the component's pins
SCH_PIN_MAP m_pinMap; ///< the component's pins mapped by LIB_PIN*.
SCH_PINS m_pins; ///< a SCH_PIN for every LIB_PIN (across all units)
SCH_PIN_MAP m_pinMap; ///< the component's pins mapped by LIB_PIN*
AUTOPLACED m_fieldsAutoplaced; ///< indicates status of field autoplacement
@ -225,9 +227,9 @@ public:
int GetUnit() const { return m_unit; }
/**
* Updates the local cache of SCH_PIN_CONNECTION objects for each pin
* Updates the cache of SCH_PIN objects for each pin
*/
void UpdatePins( SCH_SHEET_PATH* aSheet = nullptr );
void UpdatePins();
/**
* Retrieves the connection for a given pin of the component
@ -475,7 +477,13 @@ public:
*/
void GetPins( std::vector<LIB_PIN*>& aPinsList );
SCH_PINS& GetPins() { return m_pins; }
/**
* Retrieves a list of the SCH_PINs for the given sheet path.
* Since a component can have a different unit on a different instance of a sheet,
* this list returns the subset of pins that exist on a given sheet.
* @return a vector of pointers (non-owning) to SCH_PINs
*/
SCH_PIN_PTRS GetSchPins( const SCH_SHEET_PATH* aSheet = nullptr ) const;
/**
* Print a component
@ -537,10 +545,10 @@ public:
int aMulti );
// returns the unit selection, for the given sheet path.
int GetUnitSelection( SCH_SHEET_PATH* aSheet );
int GetUnitSelection( const SCH_SHEET_PATH* aSheet ) const;
// Set the unit selection, for the given sheet path.
void SetUnitSelection( SCH_SHEET_PATH* aSheet, int aUnitSelection );
void SetUnitSelection( const SCH_SHEET_PATH* aSheet, int aUnitSelection );
// Geometric transforms (used in block operations):
@ -576,7 +584,8 @@ public:
*
* @return true if any pin's state has changed.
*/
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
wxPoint GetPinPhysicalPosition( const LIB_PIN* Pin ) const;

View File

@ -1039,7 +1039,7 @@ void SCH_EDIT_FRAME::AddItemToScreenAndUndoList( SCH_ITEM* aItem, bool aUndoAppe
TestDanglingEnds();
for( SCH_ITEM* item : aItem->ConnectedItems() )
for( SCH_ITEM* item : aItem->ConnectedItems( *g_CurrentSheet ) )
RefreshItem( item );
}
@ -1172,14 +1172,15 @@ void SCH_EDIT_FRAME::FixupJunctions()
GetCurrentSheet().UpdateAllScreenReferences();
auto screen = GetCurrentSheet().LastScreen();
for( auto aItem : screen->Items().OfType( SCH_COMPONENT_T ) )
{
auto cmp = static_cast<SCH_COMPONENT*>( aItem );
auto xform = cmp->GetTransform();
for( const SCH_PIN& pin : cmp->GetPins() )
for( const SCH_PIN* pin : cmp->GetSchPins( &sheet ) )
{
auto pos = cmp->GetPosition() + xform.TransformCoordinate( pin.GetPosition() );
auto pos = cmp->GetPosition() + xform.TransformCoordinate( pin->GetPosition() );
// Test if a _new_ junction is needed, and add it if missing
if( screen->IsJunctionNeeded( pos, true ) )

View File

@ -85,8 +85,8 @@ SCH_ITEM* SCH_ITEM::Duplicate( bool doClone )
{
SCH_COMPONENT* component = (SCH_COMPONENT*) newItem;
for( SCH_PIN& pin : component->GetPins() )
pin.ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED );
for( SCH_PIN* pin : component->GetSchPins() )
pin->ClearFlags( SELECTED | HIGHLIGHTED | BRIGHTENED );
std::vector<SCH_FIELD*> fields;
component->GetFields( fields, false );
@ -135,15 +135,15 @@ SCH_CONNECTION* SCH_ITEM::Connection( const SCH_SHEET_PATH& aSheet ) const
}
std::unordered_set<SCH_ITEM*>& SCH_ITEM::ConnectedItems()
ITEM_SET& SCH_ITEM::ConnectedItems( const SCH_SHEET_PATH& aSheet )
{
return m_connected_items;
return m_connected_items[ aSheet ];
}
void SCH_ITEM::AddConnectionTo( SCH_ITEM* aItem )
void SCH_ITEM::AddConnectionTo( const SCH_SHEET_PATH& aSheet, SCH_ITEM* aItem )
{
m_connected_items.insert( aItem );
m_connected_items[ aSheet ].insert( aItem );
}

View File

@ -126,6 +126,8 @@ public:
};
typedef std::unordered_set<SCH_ITEM*> ITEM_SET;
/**
* SCH_ITEM
* is a base class for any item which can be embedded within the SCHEMATIC
@ -143,8 +145,8 @@ protected:
wxPoint m_storedPos; ///< a temporary variable used in some move commands
///> to store a initial pos (of the item or mouse cursor)
/// Stores pointers to other items that are connected to this one (schematic only)
std::unordered_set<SCH_ITEM*> m_connected_items;
/// Stores pointers to other items that are connected to this one, per sheet
std::unordered_map<SCH_SHEET_PATH, ITEM_SET> m_connected_items;
/// Stores connectivity information, per sheet
std::unordered_map<SCH_SHEET_PATH, SCH_CONNECTION*> m_connection_map;
@ -301,10 +303,18 @@ public:
* always returns false. Only override the method if the item can be tested for a
* dangling state.
*
* If aSheet is passed a non-null pointer to a SCH_SHEET_PATH, the overrided method can
* optionally use it to update sheet-local connectivity information
*
* @param aItemList - List of items to test item against.
* @param aSheet - Sheet path to update connections for
* @return True if the dangling state has changed from it's current setting.
*/
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) { return false; }
virtual bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr )
{
return false;
}
virtual bool IsDangling() const { return false; }
@ -351,14 +361,14 @@ public:
SCH_CONNECTION* Connection( const SCH_SHEET_PATH& aPath ) const;
/**
* Retrieves the set of items connected to this item (schematic only)
* Retrieves the set of items connected to this item on the given sheet
*/
std::unordered_set<SCH_ITEM*>& ConnectedItems();
ITEM_SET& ConnectedItems( const SCH_SHEET_PATH& aPath );
/**
* Adds a connection link between this item and another
*/
void AddConnectionTo( SCH_ITEM* aItem );
void AddConnectionTo( const SCH_SHEET_PATH& aPath, SCH_ITEM* aItem );
/**
* Creates a new connection object associated with this object

View File

@ -534,7 +534,8 @@ void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
}
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
bool previousStartState = m_startIsDangling;
bool previousEndState = m_endIsDangling;
@ -559,7 +560,7 @@ bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
if( m_end == item.GetPosition() )
m_endIsDangling = false;
if( (m_startIsDangling == false) && (m_endIsDangling == false) )
if( !m_startIsDangling && !m_endIsDangling )
break;
}
}

View File

@ -178,7 +178,8 @@ public:
void GetEndPoints( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
bool IsStartDangling() const { return m_startIsDangling; }
bool IsEndDangling() const { return m_endIsDangling; }

View File

@ -1329,17 +1329,17 @@ void SCH_PAINTER::draw( SCH_COMPONENT *aComp, int aLayer )
// Copy the pin info from the component to the temp pins
LIB_PINS tempPins;
tempPart.GetPins( tempPins, aComp->GetUnit(), aComp->GetConvert() );
const SCH_PINS& compPins = aComp->GetPins();
const SCH_PIN_PTRS compPins = aComp->GetSchPins();
for( unsigned i = 0; i < tempPins.size() && i < compPins.size(); ++ i )
{
LIB_PIN* tempPin = tempPins[ i ];
const SCH_PIN& compPin = compPins[ i ];
const SCH_PIN* compPin = compPins[ i ];
tempPin->ClearFlags();
tempPin->SetFlags( compPin.GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
tempPin->SetFlags( compPin->GetFlags() ); // SELECTED, HIGHLIGHTED, BRIGHTENED
if( compPin.IsDangling() )
if( compPin->IsDangling() )
tempPin->SetFlags( IS_DANGLING );
}

View File

@ -785,7 +785,7 @@ void SCH_SCREEN::GetHierarchicalItems( EDA_ITEMS& aItems )
}
bool SCH_SCREEN::TestDanglingEnds()
bool SCH_SCREEN::TestDanglingEnds( const SCH_SHEET_PATH* aPath )
{
std::vector< DANGLING_END_ITEM > endPoints;
bool hasStateChanged = false;
@ -795,7 +795,7 @@ bool SCH_SCREEN::TestDanglingEnds()
for( auto item : Items() )
{
if( item->UpdateDanglingState( endPoints ) )
if( item->UpdateDanglingState( endPoints, aPath ) )
hasStateChanged = true;
}

View File

@ -285,9 +285,10 @@ public:
/**
* Test all of the connectable objects in the schematic for unused connection points.
* @param aPath is a sheet path to pass to UpdateDanglingState if desired
* @return True if any connection state changes were made.
*/
bool TestDanglingEnds();
bool TestDanglingEnds( const SCH_SHEET_PATH* aPath = nullptr );
/**
* Return all wires and junctions connected to \a aSegment which are not connected any

View File

@ -757,7 +757,8 @@ void SCH_SHEET::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
}
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_SHEET::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
bool changed = false;

View File

@ -509,7 +509,8 @@ public:
void GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
bool IsConnectable() const override { return true; }

View File

@ -328,7 +328,8 @@ void SCH_TEXT::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
}
bool SCH_TEXT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
bool SCH_TEXT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath )
{
// Normal text labels cannot be tested for dangling ends.
if( Type() == SCH_TEXT_T )
@ -355,8 +356,8 @@ bool SCH_TEXT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
{
m_isDangling = false;
if( item.GetType() != PIN_END )
m_connected_items.insert( static_cast< SCH_ITEM* >( item.GetItem() ) );
if( aPath && item.GetType() != PIN_END )
m_connected_items[ *aPath ].insert( static_cast<SCH_ITEM*>( item.GetItem() ) );
}
break;
@ -385,9 +386,12 @@ bool SCH_TEXT::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList )
// Add the line to the connected items, since it won't be picked
// up by a search of intersecting connection points
auto sch_item = static_cast< SCH_ITEM* >( item.GetItem() );
AddConnectionTo( sch_item );
sch_item->AddConnectionTo( this );
if( aPath )
{
auto sch_item = static_cast<SCH_ITEM*>( item.GetItem() );
AddConnectionTo( *aPath, sch_item );
sch_item->AddConnectionTo( *aPath, this );
}
}
}
break;
@ -669,7 +673,9 @@ bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
{
if( *p == SCH_LABEL_LOCATE_WIRE_T )
{
for( SCH_ITEM* connection : m_connected_items )
wxASSERT( m_connected_items.count( *g_CurrentSheet ) );
for( SCH_ITEM* connection : m_connected_items.at( *g_CurrentSheet ) )
{
if( connection->IsType( wireTypes ) )
return true;
@ -677,7 +683,9 @@ bool SCH_LABEL::IsType( const KICAD_T aScanTypes[] ) const
}
else if ( *p == SCH_LABEL_LOCATE_BUS_T )
{
for( SCH_ITEM* connection : m_connected_items )
wxASSERT( m_connected_items.count( *g_CurrentSheet ) );
for( SCH_ITEM* connection : m_connected_items.at( *g_CurrentSheet ) )
{
if( connection->IsType( busTypes ) )
return true;

View File

@ -299,7 +299,8 @@ public:
void GetEndPoints( std::vector< DANGLING_END_ITEM >& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList ) override;
bool UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemList,
const SCH_SHEET_PATH* aPath = nullptr ) override;
bool IsDangling() const override { return m_isDangling; }
void SetIsDangling( bool aIsDangling ) { m_isDangling = aIsDangling; }

View File

@ -1199,14 +1199,14 @@ void EE_SELECTION_TOOL::highlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* aGr
// represented in the LIB_PART and will inherit the settings of the parent component.)
if( itemType == SCH_COMPONENT_T )
{
SCH_PINS& pins = static_cast<SCH_COMPONENT*>( aItem )->GetPins();
SCH_PIN_PTRS pins = static_cast<SCH_COMPONENT*>( aItem )->GetSchPins( g_CurrentSheet );
for( SCH_PIN& pin : pins )
for( SCH_PIN* pin : pins )
{
if( aMode == SELECTED )
pin.SetSelected();
pin->SetSelected();
else if( aMode == BRIGHTENED )
pin.SetBrightened();
pin->SetBrightened();
}
std::vector<SCH_FIELD*> fields;
@ -1256,14 +1256,14 @@ void EE_SELECTION_TOOL::unhighlight( EDA_ITEM* aItem, int aMode, EE_SELECTION* a
// represented in the LIB_PART.)
if( itemType == SCH_COMPONENT_T )
{
SCH_PINS& pins = static_cast<SCH_COMPONENT*>( aItem )->GetPins();
SCH_PIN_PTRS pins = static_cast<SCH_COMPONENT*>( aItem )->GetSchPins( g_CurrentSheet );
for( SCH_PIN& pin : pins )
for( SCH_PIN* pin : pins )
{
if( aMode == SELECTED )
pin.ClearSelected();
pin->ClearSelected();
else if( aMode == BRIGHTENED )
pin.ClearBrightened();
pin->ClearBrightened();
}
std::vector<SCH_FIELD*> fields;