33bool isTitleBlockField(
const wxString& aName )
35 return aName == wxT(
"ISSUE_DATE" ) || aName == wxT(
"REVISION" )
36 || aName == wxT(
"TITLE" ) || aName == wxT(
"COMPANY" )
37 || aName == wxT(
"COMMENT1" ) || aName == wxT(
"COMMENT2" )
38 || aName == wxT(
"COMMENT3" ) || aName == wxT(
"COMMENT4" )
39 || aName == wxT(
"COMMENT5" ) || aName == wxT(
"COMMENT6" )
40 || aName == wxT(
"COMMENT7" ) || aName == wxT(
"COMMENT8" )
41 || aName == wxT(
"COMMENT9" ) || aName == wxT(
"PROJECTNAME" )
42 || aName == wxT(
"PAPER" ) || aName == wxT(
"KICAD_VERSION" );
49bool isSpecial(
const wxString& aName )
51 return aName == wxT(
"SHEETNAME" ) || aName == wxT(
"SHEETPATH" )
52 || aName == wxT(
"FILENAME" ) || aName == wxT(
"FILEPATH" )
53 || aName == wxT(
"#" ) || aName == wxT(
"##" )
54 || aName == wxT(
"CURRENT_DATE" ) || aName == wxT(
"LAYER" )
55 || aName == wxT(
"KICAD_VERSION" );
64 const int colonPos = aToken.Find(
':' );
65 const bool hasColon = colonPos != wxNOT_FOUND && colonPos > 0
66 && colonPos < static_cast<int>( aToken.length() ) - 1;
70 const wxString
left = aToken.Left( colonPos );
71 const wxString
right = aToken.Mid( colonPos + 1 );
75 if(
left == wxT(
"OP" ) )
92 if( aToken == wxT(
"OP" ) )
99 if( isTitleBlockField( aToken ) )
106 if( isSpecial( aToken ) )
122std::vector<TEXT_VAR_REF_KEY>
FilterTrackable(
const std::vector<TEXT_VAR_REF_KEY>& aRefs )
124 std::vector<TEXT_VAR_REF_KEY> out;
125 out.reserve( aRefs.size() );
129 if( ref.IsTrackable() )
130 out.push_back( ref );
139 std::hash<std::string> hasher;
141 auto mix = []( std::size_t& aSeed, std::size_t aValue )
144 aSeed ^= aValue + 0x9E3779B97F4A7C15ULL + ( aSeed << 6 ) + ( aSeed >> 2 );
150 mix( h,
static_cast<std::size_t
>( aKey.
kind ) );
151 mix( h, hasher( aKey.
primary.ToStdString( wxConvUTF8 ) ) );
152 mix( h, hasher( aKey.
secondary.ToStdString( wxConvUTF8 ) ) );
158 const std::vector<TEXT_VAR_REF_KEY>& aKeys )
163 std::unique_lock lock(
m_mutex );
171 depIt->second.erase( aItem );
173 if( depIt->second.empty() )
196 std::unique_lock lock(
m_mutex );
207 depIt->second.erase( aItem );
209 if( depIt->second.empty() )
219 const std::function<
void(
EDA_ITEM* )>& aFn )
const
226 std::vector<EDA_ITEM*> snapshot;
229 std::shared_lock lock(
m_mutex );
236 snapshot.reserve( it->second.size() );
237 snapshot.assign( it->second.begin(), it->second.end() );
247 std::unique_lock lock(
m_mutex );
256 std::shared_lock lock(
m_mutex );
260 return it ==
m_dependents.end() ? 0u : it->second.size();
266 std::shared_lock lock(
m_mutex );
273 std::shared_lock lock(
m_mutex );
275 std::vector<TEXT_VAR_REF_KEY> keys;
279 keys.push_back( key );
315 const std::vector<TEXT_VAR_REF_KEY>& aKeys )
320 m_index.Register( aItem, aKeys );
343 const std::vector<TEXT_VAR_REF_KEY>& aUpdatedKeys )
355 std::initializer_list<TEXT_VAR_REF_KEY::KIND> aKinds )
360 const std::vector<TEXT_VAR_REF_KEY> all =
m_index.GetRegisteredKeys();
400 std::vector<InvalidateCallback> snapshot;
411 snapshot.push_back( cb );
414 m_index.ForEachDependent( aKey,
418 cb( dependent, aKey );
A base class for most all the KiCad significant classes used in schematics and boards.
std::vector< TEXT_VAR_REF_KEY > GetRegisteredKeys() const
Enumerate every key currently present in the forward index.
std::unordered_map< TEXT_VAR_REF_KEY, std::unordered_set< EDA_ITEM * >, TEXT_VAR_REF_KEY_HASH > m_dependents
void Clear()
Drop every entry.
std::size_t ItemCount() const
std::size_t DependentCount(const TEXT_VAR_REF_KEY &aKey) const
void Register(EDA_ITEM *aItem, const std::vector< TEXT_VAR_REF_KEY > &aKeys)
Replace the key set for aItem with aKeys.
std::unordered_map< EDA_ITEM *, std::vector< TEXT_VAR_REF_KEY > > m_itemKeys
std::shared_mutex m_mutex
void Unregister(EDA_ITEM *aItem)
Remove aItem from the index entirely.
void ForEachDependent(const TEXT_VAR_REF_KEY &aKey, const std::function< void(EDA_ITEM *)> &aFn) const
Invoke aFn exactly once per item registered under aKey.
void HandleItemChanged(EDA_ITEM *aItem, const std::vector< TEXT_VAR_REF_KEY > &aUpdatedKeys)
Handle a composite change for aItem: register its updated keys and fan out invalidation for every key...
void InvalidateVariantScoped()
Invalidate every source whose resolved value can differ between variants: CROSS_REF (footprint/symbol...
void RegisterItem(EDA_ITEM *aItem, const std::vector< TEXT_VAR_REF_KEY > &aKeys)
Register aItem in the index.
SourceKeyExtractor m_extractSourceKeys
void UnregisterItem(EDA_ITEM *aItem)
Remove aItem from the index.
std::function< void(EDA_ITEM *aDependent, const TEXT_VAR_REF_KEY &aKey)> InvalidateCallback
Called when a dependent item should recompute its resolved text.
std::unordered_map< ListenerHandle, InvalidateCallback > m_invalidateListeners
void SetSourceKeyExtractor(SourceKeyExtractor aExtractor)
ListenerHandle AddInvalidateListener(InvalidateCallback aCallback)
Register a listener that fires for every invalidation.
TEXT_VAR_DEPENDENCY_INDEX m_index
void InvalidateByKind(std::initializer_list< TEXT_VAR_REF_KEY::KIND > aKinds)
Fan out invalidation for every registered key whose KIND is one of the supplied set.
void InvalidateProjectScoped()
Invalidate every non-item source: title-block, special, project/env vars, and LOCAL (which may be a p...
std::size_t ListenerHandle
Opaque handle returned by AddInvalidateListener and consumed by RemoveInvalidateListener.
TEXT_VAR_TRACKER(SourceKeyExtractor aSourceKeyExtractor={})
ListenerHandle m_nextListenerHandle
void RemoveInvalidateListener(ListenerHandle aHandle)
Drop a previously-registered listener.
void fanOutSourceKeys(EDA_ITEM *aItem)
std::function< std::vector< TEXT_VAR_REF_KEY >(EDA_ITEM *)> SourceKeyExtractor
Return the keys aItem could source as a cross-reference target.
void InvalidateKey(const TEXT_VAR_REF_KEY &aKey)
Fan out invalidation for a single explicit key — used when a non-item source changes (e....
std::shared_mutex m_listenersMutex
std::size_t operator()(const TEXT_VAR_REF_KEY &aKey) const
Identifies a single resolvable source that a text item's ${...} reference depends on.
static TEXT_VAR_REF_KEY FromToken(const wxString &aToken)
Parse a raw token (the text between ${ and }) into a key using lexical classification only — no looku...
KIND
Categorizes a reference by the source that will produce its value.
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...