KiCad PCB EDA Suite
Loading...
Searching...
No Matches
schematic_text_var_adapter.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
21
22#include <algorithm>
23#include <set>
24#include <eda_text.h>
25#include <sch_field.h>
26#include <sch_item.h>
27#include <sch_screen.h>
28#include <sch_sheet.h>
29#include <sch_sheet_path.h>
30#include <sch_symbol.h>
31
32
34 m_schematic( aSchematic )
35{
36 m_tracker.SetSourceKeyExtractor(
37 [this]( EDA_ITEM* aItem ) -> std::vector<TEXT_VAR_REF_KEY>
38 {
39 return ExtractSourceKeys( aItem );
40 } );
41}
42
43
45{
46 // Fields, sheet pins and table cells live in their owner's storage and can move without
47 // a notification, so only the screen item that owns them is ever indexed
48 if( aItem && aItem->IsType( { SCH_FIELD_T, SCH_SHEET_PIN_T, SCH_TABLECELL_T } ) )
49 return dynamic_cast<SCH_ITEM*>( aItem->GetParent() );
50
51 return aItem;
52}
53
54
55std::vector<TEXT_VAR_REF_KEY> SCHEMATIC_TEXT_VAR_ADAPTER::collectKeys( SCH_ITEM* aItem )
56{
57 std::vector<TEXT_VAR_REF_KEY> keys;
58
59 auto collect =
60 [&]( SCH_ITEM* aTextItem )
61 {
62 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aTextItem );
63
64 if( !text )
65 return;
66
67 for( const TEXT_VAR_REF_KEY& key : FilterTrackable( text->GetTextVarReferences() ) )
68 {
69 if( std::find( keys.begin(), keys.end(), key ) == keys.end() )
70 keys.push_back( key );
71 }
72 };
73
74 collect( aItem );
75
76 // Group members are screen items in their own right
77 if( aItem->Type() != SCH_GROUP_T )
78 aItem->RunOnChildren( collect, RECURSE_MODE::NO_RECURSE );
79
80 return keys;
81}
82
83
84std::vector<TEXT_VAR_REF_KEY> SCHEMATIC_TEXT_VAR_ADAPTER::trackKeys( SCH_ITEM* aItem )
85{
86 std::vector<TEXT_VAR_REF_KEY> keys = collectKeys( aItem );
87
88 if( keys.empty() )
89 m_registered.erase( aItem );
90 else
91 m_registered.insert( aItem );
92
93 return keys;
94}
95
96
98{
99 m_tracker.RegisterItem( aItem, trackKeys( aItem ) );
100}
101
102
104{
105 // Also fans out ${REFDES:FIELD} for symbols, which source cross-references
106 m_tracker.HandleItemChanged( aItem, trackKeys( aItem ) );
107}
108
109
110void SCHEMATIC_TEXT_VAR_ADAPTER::noteSheets( const std::vector<SCH_ITEM*>& aItems )
111{
112 // A sheet add or remove forces a rebuild because a new screen can reuse a freed one's address.
113 // Changed sheets keep their old screen alive in the undo image, so the screen set catches them
114 for( SCH_ITEM* item : aItems )
115 {
116 if( item && item->Type() == SCH_SHEET_T )
117 m_hierarchyChanged = true;
118 }
119}
120
121
122void SCHEMATIC_TEXT_VAR_ADAPTER::OnSchItemsAdded( SCHEMATIC&, std::vector<SCH_ITEM*>& aItems )
123{
124 noteSheets( aItems );
125
126 for( SCH_ITEM* item : aItems )
127 {
128 if( SCH_ITEM* tracked = trackedItem( item ) )
129 registerItem( tracked );
130 }
131}
132
133
134void SCHEMATIC_TEXT_VAR_ADAPTER::OnSchItemsRemoved( SCHEMATIC&, std::vector<SCH_ITEM*>& aItems )
135{
136 noteSheets( aItems );
137
138 for( SCH_ITEM* item : aItems )
139 {
140 SCH_ITEM* tracked = trackedItem( item );
141
142 if( tracked == item )
143 {
144 m_tracker.UnregisterItem( item );
145 m_registered.erase( item );
146 }
147 else if( tracked )
148 {
149 // A child left its owner, which stays on the screen
150 handleItemChanged( tracked );
151 }
152 }
153}
154
155
156void SCHEMATIC_TEXT_VAR_ADAPTER::OnSchItemsChanged( SCHEMATIC&, std::vector<SCH_ITEM*>& aItems )
157{
158 for( SCH_ITEM* item : aItems )
159 {
160 if( SCH_ITEM* tracked = trackedItem( item ) )
161 handleItemChanged( tracked );
162 }
163}
164
165
167{
168 std::set<SCH_SCREEN*> screens;
169
170 for( const SCH_SHEET_PATH& path : m_schematic.Hierarchy() )
171 {
172 if( SCH_SCREEN* screen = path.LastScreen() )
173 screens.insert( screen );
174 }
175
176 return screens;
177}
178
179
187
188
190{
191 // The drawing sheet shares this tracker, so drop only what this adapter owns.
192 // Stale pointers are never dereferenced, only used as keys
193 for( SCH_ITEM* item : m_registered )
194 m_tracker.UnregisterItem( item );
195
196 m_registered.clear();
198 m_hierarchyChanged = false;
199
200 for( SCH_SCREEN* screen : m_indexedScreens )
201 {
202 for( SCH_ITEM* item : screen->Items() )
203 registerItem( item );
204 }
205}
206
207
208std::vector<TEXT_VAR_REF_KEY> SCHEMATIC_TEXT_VAR_ADAPTER::ExtractSourceKeys( EDA_ITEM* aItem ) const
209{
210 std::vector<TEXT_VAR_REF_KEY> out;
211
212 SCH_SYMBOL* sym = dynamic_cast<SCH_SYMBOL*>( aItem );
213
214 if( !sym )
215 return out;
216
217 auto addKey =
218 [&]( const wxString& aPrimary )
219 {
220 if( aPrimary.IsEmpty() )
221 return;
222
225 key.primary = aPrimary;
226
227 if( std::find( out.begin(), out.end(), key ) == out.end() )
228 out.push_back( key );
229 };
230
231 // Must match the KIID path SCHEMATIC::ConvertRefsToKIIDs writes into stored text
232 auto addInstance =
233 [&]( const SCH_SHEET_PATH& aPath )
234 {
235 KIID_PATH path = aPath.Path();
236 path.push_back( sym->m_Uuid );
237
238 addKey( sym->GetRef( &aPath, false ) );
239 addKey( path.AsString() );
240 };
241
242 const SCH_SHEET_LIST& hierarchy = m_schematic.Hierarchy();
243
244 if( hierarchy.empty() )
245 {
246 addInstance( m_schematic.CurrentSheet() );
247 return out;
248 }
249
250 // GetRef falls back to the REFERENCE field on paths that are not instances of this
251 // symbol, so only visit paths that actually show the symbol's screen
252 const SCH_SCREEN* parentScreen = dynamic_cast<const SCH_SCREEN*>( sym->GetParent() );
253
254 for( const SCH_SHEET_PATH& path : hierarchy )
255 {
256 if( path.LastScreen() == parentScreen )
257 addInstance( path );
258 }
259
260 return out;
261}
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM * GetParent() const
Definition eda_item.h:112
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
static SCH_ITEM * trackedItem(SCH_ITEM *aItem)
std::vector< TEXT_VAR_REF_KEY > ExtractSourceKeys(EDA_ITEM *aItem) const
Return the keys aItem could source as a cross-reference target.
void noteSheets(const std::vector< SCH_ITEM * > &aItems)
void OnSchItemsChanged(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
void SyncToHierarchy()
Rebuild only if a sheet was added or removed, or the set of screens in the hierarchy differs from the...
std::vector< TEXT_VAR_REF_KEY > trackKeys(SCH_ITEM *aItem)
SCHEMATIC_TEXT_VAR_ADAPTER(SCHEMATIC &aSchematic)
void OnSchItemsRemoved(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
std::set< SCH_SCREEN * > m_indexedScreens
std::set< SCH_SCREEN * > hierarchyScreens() const
static std::vector< TEXT_VAR_REF_KEY > collectKeys(SCH_ITEM *aItem)
void RebuildIndex()
Walk every sheet in the hierarchy and register text-bearing items.
void OnSchItemsAdded(SCHEMATIC &aSch, std::vector< SCH_ITEM * > &aItems) override
std::unordered_set< SCH_ITEM * > m_registered
Holds all the data relating to one schematic.
Definition schematic.h:149
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
virtual void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode)
Definition sch_item.h:678
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
Definition sch_item.h:185
A container for handling SCH_SHEET_PATH objects in a flattened hierarchy.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Schematic symbol object.
Definition sch_symbol.h:73
const wxString GetRef(const SCH_SHEET_PATH *aSheet, bool aIncludeUnit=false) const override
@ NO_RECURSE
Definition eda_item.h:52
Definition of the SCH_SHEET_PATH and SCH_SHEET_LIST classes for Eeschema.
Identifies a single resolvable source that a text item's ${...} reference depends on.
std::string path
std::vector< TEXT_VAR_REF_KEY > FilterTrackable(const std::vector< TEXT_VAR_REF_KEY > &aRefs)
Filter aRefs down to the subset that should be registered in the index (drops OP and any future non-t...
@ SCH_GROUP_T
Definition typeinfo.h:169
@ SCH_SHEET_T
Definition typeinfo.h:171