Fix handling of SCH_PINs on multi-unit parts
Fixes https://gitlab.com/kicad/code/kicad/issues/3770
This commit is contained in:
parent
0645442704
commit
ac875e26a8
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 ) )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue