KiCad PCB EDA Suite
Loading...
Searching...
No Matches
board_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, you may find one here:
18 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19 */
20
22
23#include <eda_text.h>
24#include <footprint.h>
25#include <pcb_barcode.h>
26#include <pcb_field.h>
27#include <pcb_text.h>
28#include <pcb_textbox.h>
29
30
32 m_board( aBoard )
33{
34 m_tracker.SetSourceKeyExtractor(
35 [this]( EDA_ITEM* aItem ) -> std::vector<TEXT_VAR_REF_KEY>
36 { return ExtractSourceKeys( aItem ); } );
37}
38
39
41{
42 if( !aItem )
43 return;
44
45 // Route the dynamic_cast through the pcbnew DSO where RTTI for EDA_TEXT is
46 // visible. The kicommon-side tracker stays RTTI-free.
47 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
48
49 if( !text )
50 {
51 // PCB_BARCODE wraps an EDA_TEXT internally; register the barcode itself
52 // (not its inner PCB_TEXT) so invalidation callbacks receive the barcode
53 // as the dependent and the view can repaint it.
54 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
55 {
56 m_tracker.RegisterItem( aItem, FilterTrackable( bc->GetTextVarReferences() ) );
57 return;
58 }
59
60 // FOOTPRINTs aren't themselves EDA_TEXT. Walk both their fields AND
61 // their graphical items — silkscreen/copper/courtyard layers can
62 // carry PCB_TEXT/PCB_TEXTBOX that reference `${...}`.
63 if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem ) )
64 {
65 for( PCB_FIELD* field : fp->GetFields() )
66 registerItem( field );
67
68 for( BOARD_ITEM* child : fp->GraphicalItems() )
69 registerItem( child );
70 }
71
72 return;
73 }
74
75 m_tracker.RegisterItem( aItem, FilterTrackable( text->GetTextVarReferences() ) );
76}
77
78
80{
81 if( !aItem )
82 return;
83
84 m_tracker.UnregisterItem( aItem );
85
86 if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem ) )
87 {
88 for( PCB_FIELD* field : fp->GetFields() )
89 m_tracker.UnregisterItem( field );
90
91 for( BOARD_ITEM* child : fp->GraphicalItems() )
92 unregisterItem( child );
93 }
94}
95
96
101
102
103void BOARD_TEXT_VAR_ADAPTER::OnBoardItemsAdded( BOARD&, std::vector<BOARD_ITEM*>& aItems )
104{
105 for( BOARD_ITEM* item : aItems )
106 registerItem( item );
107}
108
109
114
115
116void BOARD_TEXT_VAR_ADAPTER::OnBoardItemsRemoved( BOARD&, std::vector<BOARD_ITEM*>& aItems )
117{
118 for( BOARD_ITEM* item : aItems )
119 unregisterItem( item );
120}
121
122
124{
125 if( !aItem )
126 return;
127
128 // Re-register the item's own refs (its text may have changed), then fan
129 // out any cross-ref keys this item could source so dependents refresh.
130 EDA_TEXT* text = dynamic_cast<EDA_TEXT*>( aItem );
131
132 if( text )
133 {
134 std::vector<TEXT_VAR_REF_KEY> updated = FilterTrackable( text->GetTextVarReferences() );
135 m_tracker.HandleItemChanged( aItem, updated );
136 }
137 else if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
138 {
139 m_tracker.HandleItemChanged( aItem, FilterTrackable( bc->GetTextVarReferences() ) );
140 }
141 else
142 {
143 // Non-text item (e.g., FOOTPRINT) — its own children were registered
144 // separately on add, so we only need the fan-out for source keys.
145 m_tracker.HandleItemChanged( aItem, {} );
146
147 if( FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem ) )
148 {
149 // Footprint fields may themselves have been edited (value/ref
150 // change). Re-register each so the dependency graph stays current.
151 for( PCB_FIELD* field : fp->GetFields() )
152 {
153 std::vector<TEXT_VAR_REF_KEY> fieldRefs = FilterTrackable( field->GetTextVarReferences() );
154 m_tracker.RegisterItem( field, fieldRefs );
155 }
156
157 // Graphical items (silkscreen text etc.) may also reference
158 // text vars and may have been edited out-of-band.
159 for( BOARD_ITEM* child : fp->GraphicalItems() )
160 {
161 if( EDA_TEXT* childText = dynamic_cast<EDA_TEXT*>( child ) )
162 {
163 m_tracker.RegisterItem( child,
164 FilterTrackable( childText->GetTextVarReferences() ) );
165 }
166 }
167 }
168 }
169}
170
171
172void BOARD_TEXT_VAR_ADAPTER::OnBoardItemsChanged( BOARD& aBoard, std::vector<BOARD_ITEM*>& aItems )
173{
174 for( BOARD_ITEM* item : aItems )
175 OnBoardItemChanged( aBoard, item );
176}
177
178
180 std::vector<BOARD_ITEM*>& aAdded,
181 std::vector<BOARD_ITEM*>& aRemoved,
182 std::vector<BOARD_ITEM*>& aChanged )
183{
184 // Apply in order: remove, add, change. Removals first so re-added items
185 // with recycled pointers don't collide in the index. Changes last so
186 // fan-outs see the updated board state.
187 for( BOARD_ITEM* item : aRemoved )
188 unregisterItem( item );
189
190 for( BOARD_ITEM* item : aAdded )
191 registerItem( item );
192
193 for( BOARD_ITEM* item : aChanged )
194 OnBoardItemChanged( aBoard, item );
195}
196
197
199{
200 m_tracker.Clear();
201
202 for( FOOTPRINT* fp : m_board.Footprints() )
203 registerItem( fp );
204
205 for( BOARD_ITEM* item : m_board.Drawings() )
206 registerItem( item );
207}
208
209
210std::vector<TEXT_VAR_REF_KEY> BOARD_TEXT_VAR_ADAPTER::ExtractSourceKeys( EDA_ITEM* aItem ) const
211{
212 std::vector<TEXT_VAR_REF_KEY> out;
213
214 FOOTPRINT* fp = dynamic_cast<FOOTPRINT*>( aItem );
215
216 if( !fp )
217 return out;
218
219 // A footprint U1 sources `${U1:<FIELDNAME>}` for every named field it
220 // carries. This is a conservative over-approximation — an edit to any
221 // footprint field fans out to every dependent on ${U1:*}, even if the
222 // specific field they reference wasn't the one that changed. The blast
223 // radius is bounded by the number of actual dependents, so over-
224 // invalidation is cheap relative to the alternative (per-field diff
225 // against a pre-image snapshot, which would couple the adapter to the
226 // commit system).
227 const wxString refdes = fp->GetReference();
228
229 if( refdes.IsEmpty() )
230 return out;
231
232 out.reserve( fp->GetFields().size() );
233
234 for( PCB_FIELD* field : fp->GetFields() )
235 {
238 key.primary = refdes;
239 key.secondary = field->GetName();
240 out.push_back( key );
241 }
242
243 return out;
244}
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
void OnBoardItemsAdded(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void OnBoardItemRemoved(BOARD &aBoard, BOARD_ITEM *aItem) override
void OnBoardCompositeUpdate(BOARD &aBoard, std::vector< BOARD_ITEM * > &aAdded, std::vector< BOARD_ITEM * > &aRemoved, std::vector< BOARD_ITEM * > &aChanged) override
void OnBoardItemsChanged(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void unregisterItem(BOARD_ITEM *aItem)
void OnBoardItemChanged(BOARD &aBoard, BOARD_ITEM *aItem) override
void OnBoardItemsRemoved(BOARD &aBoard, std::vector< BOARD_ITEM * > &aItems) override
void registerItem(BOARD_ITEM *aItem)
void RebuildIndex()
Scan the whole board and register every text-bearing item.
void OnBoardItemAdded(BOARD &aBoard, BOARD_ITEM *aItem) override
std::vector< TEXT_VAR_REF_KEY > ExtractSourceKeys(EDA_ITEM *aItem) const
Return the keys aItem could source as a cross-reference target.
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:100
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:93
void GetFields(std::vector< PCB_FIELD * > &aVector, bool aVisibleOnly) const
Populate a std::vector with PCB_TEXTs.
const wxString & GetReference() const
Definition footprint.h:829
BARCODE class definition.
Identifies a single resolvable source that a text item's ${...} reference depends on.
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...