34bool isTitleBlockField(
const wxString& aName )
36 return aName == wxT(
"ISSUE_DATE" ) || aName == wxT(
"REVISION" )
37 || aName == wxT(
"TITLE" ) || aName == wxT(
"COMPANY" )
38 || aName == wxT(
"COMMENT1" ) || aName == wxT(
"COMMENT2" )
39 || aName == wxT(
"COMMENT3" ) || aName == wxT(
"COMMENT4" )
40 || aName == wxT(
"COMMENT5" ) || aName == wxT(
"COMMENT6" )
41 || aName == wxT(
"COMMENT7" ) || aName == wxT(
"COMMENT8" )
42 || aName == wxT(
"COMMENT9" ) || aName == wxT(
"PROJECTNAME" )
43 || aName == wxT(
"PAPER" ) || aName == wxT(
"KICAD_VERSION" );
50bool isSpecial(
const wxString& aName )
52 return aName == wxT(
"SHEETNAME" ) || aName == wxT(
"SHEETPATH" )
53 || aName == wxT(
"FILENAME" ) || aName == wxT(
"FILEPATH" )
54 || aName == wxT(
"#" ) || aName == wxT(
"##" )
55 || aName == wxT(
"CURRENT_DATE" ) || aName == wxT(
"LAYER" )
56 || aName == wxT(
"KICAD_VERSION" );
65 const int colonPos = aToken.Find(
':' );
66 const bool hasColon = colonPos != wxNOT_FOUND && colonPos > 0
67 && colonPos < static_cast<int>( aToken.length() ) - 1;
71 const wxString
left = aToken.Left( colonPos );
72 const wxString
right = aToken.Mid( colonPos + 1 );
76 if(
left == wxT(
"OP" ) )
93 if( aToken == wxT(
"OP" ) )
100 if( isTitleBlockField( aToken ) )
107 if( isSpecial( aToken ) )
123std::vector<TEXT_VAR_REF_KEY>
FilterTrackable(
const std::vector<TEXT_VAR_REF_KEY>& aRefs )
125 std::vector<TEXT_VAR_REF_KEY> out;
126 out.reserve( aRefs.size() );
130 if( ref.IsTrackable() )
131 out.push_back( ref );
140 std::hash<std::string> hasher;
142 auto mix = []( std::size_t& aSeed, std::size_t aValue )
145 aSeed ^= aValue + 0x9E3779B97F4A7C15ULL + ( aSeed << 6 ) + ( aSeed >> 2 );
151 mix( h,
static_cast<std::size_t
>( aKey.
kind ) );
152 mix( h, hasher( aKey.
primary.ToStdString( wxConvUTF8 ) ) );
153 mix( h, hasher( aKey.
secondary.ToStdString( wxConvUTF8 ) ) );
159 const std::vector<TEXT_VAR_REF_KEY>& aKeys )
164 std::unique_lock lock(
m_mutex );
172 depIt->second.erase( aItem );
174 if( depIt->second.empty() )
197 std::unique_lock lock(
m_mutex );
208 depIt->second.erase( aItem );
210 if( depIt->second.empty() )
220 const std::function<
void(
EDA_ITEM* )>& aFn )
const
227 std::vector<EDA_ITEM*> snapshot;
230 std::shared_lock lock(
m_mutex );
237 snapshot.reserve( it->second.size() );
238 snapshot.assign( it->second.begin(), it->second.end() );
248 std::unique_lock lock(
m_mutex );
257 std::shared_lock lock(
m_mutex );
261 return it ==
m_dependents.end() ? 0u : it->second.size();
267 std::shared_lock lock(
m_mutex );
274 std::shared_lock lock(
m_mutex );
276 std::vector<TEXT_VAR_REF_KEY> keys;
280 keys.push_back( key );
316 const std::vector<TEXT_VAR_REF_KEY>& aKeys )
321 m_index.Register( aItem, aKeys );
344 const std::vector<TEXT_VAR_REF_KEY>& aUpdatedKeys )
356 std::initializer_list<TEXT_VAR_REF_KEY::KIND> aKinds )
361 const std::vector<TEXT_VAR_REF_KEY> all =
m_index.GetRegisteredKeys();
401 std::vector<InvalidateCallback> snapshot;
412 snapshot.push_back( cb );
415 m_index.ForEachDependent( aKey,
419 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...