KiCad PCB EDA Suite
Loading...
Searching...
No Matches
match_properties.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 modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * 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 <board.h>
23#include <eda_item.h>
24#include <footprint.h>
25#include <i18n_utility.h>
26#include <pad.h>
27#include <pcb_barcode.h>
28#include <pcb_dimension.h>
29#include <pcb_reference_image.h>
30#include <pcb_shape.h>
31#include <pcb_table.h>
32#include <pcb_tablecell.h>
33#include <pcb_target.h>
34#include <pcb_text.h>
35#include <pcb_textbox.h>
36#include <pcb_track.h>
37#include <properties/property.h>
40#include <zone.h>
41
42#include <map>
43
44
45struct FAMILY
46{
49 wxString m_Label;
50};
51
52
54static const std::map<wxString, FAMILY>& families()
55{
56 // clang-format off
57 static const std::map<wxString, FAMILY> families = {
58 { wxS( "route" ), { TYPE_HASH( PCB_TRACK ), _HKI( "Tracks and Arcs" ) } },
59 { wxS( "via" ), { TYPE_HASH( PCB_VIA ), _HKI( "Vias" ) } },
60 { wxS( "pad" ), { TYPE_HASH( PAD ), _HKI( "Pads" ) } },
61 { wxS( "shape" ), { TYPE_HASH( PCB_SHAPE ), _HKI( "Graphics" ) } },
62 { wxS( "text" ), { TYPE_HASH( PCB_TEXT ), _HKI( "Text" ) } },
63 { wxS( "textbox" ), { TYPE_HASH( PCB_TEXTBOX ), _HKI( "Text Boxes" ) } },
64 { wxS( "dimension" ), { TYPE_HASH( PCB_DIM_ALIGNED ), _HKI( "Dimensions" ) } },
65 { wxS( "zone" ), { TYPE_HASH( ZONE ), _HKI( "Zones" ) } },
66 { wxS( "rule_area" ), { TYPE_HASH( ZONE ), _HKI( "Rule Areas" ) } },
67 { wxS( "footprint" ), { TYPE_HASH( FOOTPRINT ), _HKI( "Footprints" ) } },
68 { wxS( "table" ), { TYPE_HASH( PCB_TABLE ), _HKI( "Tables" ) } },
69 { wxS( "table_cell" ), { TYPE_HASH( PCB_TABLECELL ), _HKI( "Table Cells" ) } },
70 { wxS( "target" ), { TYPE_HASH( PCB_TARGET ), _HKI( "Targets" ) } },
71 { wxS( "reference_image" ), { TYPE_HASH( PCB_REFERENCE_IMAGE ), _HKI( "Reference Images" ) } },
72 { wxS( "barcode" ), { TYPE_HASH( PCB_BARCODE ), _HKI( "Barcodes" ) } }
73 };
74 // clang-format on
75
76 return families;
77}
78
79
83{
84 wxString m_Label;
85 std::map<wxString, wxString> m_Names;
86};
87
88
90static const wxString COMMON_FAMILY = wxS( "common" );
91
92
95static const std::map<wxString, COMMON_PROPERTY>& commonProperties()
96{
97 // clang-format off
98 static const std::map<wxString, COMMON_PROPERTY> common = {
99 { wxS( "Layer" ), { _HKI( "Layer" ), {
100 { wxS( "barcode" ), wxS( "Layer" ) },
101 { wxS( "dimension" ), wxS( "Layer" ) },
102 { wxS( "shape" ), wxS( "Layer" ) },
103 { wxS( "table" ), wxS( "Layer" ) },
104 { wxS( "target" ), wxS( "Layer" ) },
105 { wxS( "text" ), wxS( "Layer" ) },
106 { wxS( "textbox" ), wxS( "Layer" ) },
107 { wxS( "reference_image" ), wxS( "Associated Layer" ) } } } },
108
109 { wxS( "Line Width" ), { _HKI( "Line Width" ), {
110 { wxS( "route" ), wxS( "Width" ) },
111 { wxS( "shape" ), wxS( "Line Width" ) },
112 { wxS( "table" ), wxS( "Border Width" ) },
113 { wxS( "target" ), wxS( "Width" ) } } } },
114
115 { wxS( "Soldermask" ), { _HKI( "Soldermask" ), {
116 { wxS( "route" ), wxS( "Soldermask" ) },
117 { wxS( "shape" ), wxS( "Soldermask" ) } } } },
118
119 { wxS( "Soldermask Margin Override" ), { _HKI( "Soldermask Margin Override" ), {
120 { wxS( "pad" ), wxS( "Soldermask Margin Override" ) },
121 { wxS( "route" ), wxS( "Soldermask Margin Override" ) },
122 { wxS( "shape" ), wxS( "Soldermask Margin Override" ) } } } },
123
124 // Fill is registered on text boxes and table cells but its availability func refuses
125 // both, so claiming it here would pair kinds over something that can never apply.
126
127 { wxS( "Font" ), { _HKI( "Font" ), {
128 { wxS( "dimension" ), wxS( "Font" ) },
129 { wxS( "table_cell" ), wxS( "Font" ) },
130 { wxS( "text" ), wxS( "Font" ) },
131 { wxS( "textbox" ), wxS( "Font" ) } } } },
132
133 { wxS( "Text Width" ), { _HKI( "Text Width" ), {
134 { wxS( "dimension" ), wxS( "Width" ) },
135 { wxS( "table_cell" ), wxS( "Width" ) },
136 { wxS( "text" ), wxS( "Width" ) },
137 { wxS( "textbox" ), wxS( "Width" ) } } } },
138
139 { wxS( "Text Height" ), { _HKI( "Text Height" ), {
140 { wxS( "dimension" ), wxS( "Height" ) },
141 { wxS( "table_cell" ), wxS( "Height" ) },
142 { wxS( "text" ), wxS( "Height" ) },
143 { wxS( "textbox" ), wxS( "Height" ) } } } },
144
145 { wxS( "Text Thickness" ), { _HKI( "Text Thickness" ), {
146 { wxS( "dimension" ), wxS( "Thickness" ) },
147 { wxS( "table_cell" ), wxS( "Thickness" ) },
148 { wxS( "text" ), wxS( "Thickness" ) },
149 { wxS( "textbox" ), wxS( "Thickness" ) } } } },
150
151 { wxS( "Bold" ), { _HKI( "Bold" ), {
152 { wxS( "dimension" ), wxS( "Bold" ) },
153 { wxS( "table_cell" ), wxS( "Bold" ) },
154 { wxS( "text" ), wxS( "Bold" ) },
155 { wxS( "textbox" ), wxS( "Bold" ) } } } },
156
157 { wxS( "Italic" ), { _HKI( "Italic" ), {
158 { wxS( "dimension" ), wxS( "Italic" ) },
159 { wxS( "table_cell" ), wxS( "Italic" ) },
160 { wxS( "text" ), wxS( "Italic" ) },
161 { wxS( "textbox" ), wxS( "Italic" ) } } } },
162
163 { wxS( "Horizontal Justification" ), { _HKI( "Horizontal Justification" ), {
164 { wxS( "dimension" ), wxS( "Horizontal Justification" ) },
165 { wxS( "table_cell" ), wxS( "Horizontal Justification" ) },
166 { wxS( "text" ), wxS( "Horizontal Justification" ) },
167 { wxS( "textbox" ), wxS( "Horizontal Justification" ) } } } },
168
169 { wxS( "Vertical Justification" ), { _HKI( "Vertical Justification" ), {
170 { wxS( "dimension" ), wxS( "Vertical Justification" ) },
171 { wxS( "table_cell" ), wxS( "Vertical Justification" ) },
172 { wxS( "text" ), wxS( "Vertical Justification" ) },
173 { wxS( "textbox" ), wxS( "Vertical Justification" ) } } } },
174
175 { wxS( "Knockout" ), { _HKI( "Knockout" ), {
176 { wxS( "barcode" ), wxS( "Knockout" ) },
177 { wxS( "dimension" ), wxS( "Knockout" ) },
178 { wxS( "table_cell" ), wxS( "Knockout" ) },
179 { wxS( "text" ), wxS( "Knockout" ) },
180 { wxS( "textbox" ), wxS( "Knockout" ) } } } }
181 };
182 // clang-format on
183
184 return common;
185}
186
187
189static const std::map<wxString, std::map<wxString, wxString>>& commonReach();
190
191
199
200
202static wxString familyPrefix( const EDA_ITEM& aItem )
203{
204 const wxString family = MATCH_PROPERTIES_CATALOG::Family( aItem );
205
206 return family.IsEmpty() ? wxString() : family + wxS( "/" );
207}
208
209
211{
212 switch( aItem.Type() )
213 {
214 case PCB_TRACE_T:
215 case PCB_ARC_T: return wxS( "route" );
216 case PCB_VIA_T: return wxS( "via" );
217 case PCB_PAD_T: return wxS( "pad" );
218 case PCB_SHAPE_T: return wxS( "shape" );
219 case PCB_TEXT_T:
220 case PCB_FIELD_T: return wxS( "text" );
221 case PCB_TEXTBOX_T: return wxS( "textbox" );
223 case PCB_DIM_LEADER_T:
224 case PCB_DIM_CENTER_T:
225 case PCB_DIM_RADIAL_T:
226 case PCB_DIM_ORTHOGONAL_T: return wxS( "dimension" );
227 case PCB_FOOTPRINT_T: return wxS( "footprint" );
228 case PCB_TABLE_T: return wxS( "table" );
229 case PCB_TABLECELL_T: return wxS( "table_cell" );
230 case PCB_TARGET_T: return wxS( "target" );
231 case PCB_REFERENCE_IMAGE_T: return wxS( "reference_image" );
232 case PCB_BARCODE_T: return wxS( "barcode" );
233 case PCB_ZONE_T: return static_cast<const ZONE&>( aItem ).GetIsRuleArea() ? wxS( "rule_area" ) : wxS( "zone" );
234 default: return wxEmptyString;
235 }
236}
237
238
239wxString MATCH_PROPERTIES_CATALOG::FamilyLabel( const wxString& aFamily )
240{
241 if( aFamily == COMMON_FAMILY )
242 return _( "Common to Several Kinds" );
243
244 auto entry = families().find( aFamily );
245
246 return entry == families().end() ? aFamily : wxGetTranslation( entry->second.m_Label );
247}
248
249
250std::set<wxString> MATCH_PROPERTIES_CATALOG::FamiliesFor( const wxString& aKey )
251{
252 const wxString family = aKey.BeforeFirst( '/' );
253
254 if( family != COMMON_FAMILY )
255 return { family };
256
257 auto entry = commonReach().find( aKey.AfterFirst( '/' ) );
258
259 if( entry == commonReach().end() )
260 return {};
261
262 std::set<wxString> families;
263
264 for( const auto& [name, property] : entry->second )
265 families.insert( name );
266
267 return families;
268}
269
270
271bool MATCH_PROPERTIES_CATALOG::PropertyIsRegistered( const wxString& aFamily, const wxString& aName )
272{
273 auto entry = families().find( aFamily );
274
275 if( entry == families().end() )
276 return false;
277
278 return PROPERTY_MANAGER::Instance().GetProperty( entry->second.m_Type, aName ) != nullptr;
279}
280
281
282wxString MATCH_PROPERTIES_CATALOG::PropertyLabel( const wxString& aKey )
283{
284 if( aKey.BeforeFirst( '/' ) == COMMON_FAMILY )
285 {
286 auto entry = commonProperties().find( aKey.AfterFirst( '/' ) );
287
288 if( entry != commonProperties().end() )
289 return wxGetTranslation( entry->second.m_Label );
290 }
291
292 // wxGetTranslation() returns its own argument for a missing msgid, so the name it is given
293 // has to outlive the call.
294 const wxString name = aKey.AfterFirst( '/' );
295
296 return wxGetTranslation( name );
297}
298
299
300wxString MATCH_PROPERTIES_CATALOG::DisplayLabel( const wxString& aKey )
301{
302 return wxString::Format( wxS( "%s — %s" ), FamilyLabel( aKey.BeforeFirst( '/' ) ), PropertyLabel( aKey ) );
303}
304
305
306bool MATCH_PROPERTIES_CATALOG::Compatible( const EDA_ITEM& aSource, const EDA_ITEM& aTarget )
307{
308 const wxString source = Family( aSource );
309 const wxString target = Family( aTarget );
310
311 if( source.IsEmpty() || target.IsEmpty() )
312 return false;
313
314 if( source == target )
315 return true;
316
317 // Different kinds still meet over anything they both understand.
318 for( const auto& [key, families] : commonReach() )
319 {
320 if( families.contains( source ) && families.contains( target ) )
321 return true;
322 }
323
324 return false;
325}
326
327
328std::vector<EDA_ITEM*> MATCH_PROPERTIES_CATALOG::CompatibleTargets( const EDA_ITEM& aSource,
329 const std::vector<EDA_ITEM*>& aCandidates )
330{
331 std::vector<EDA_ITEM*> targets;
332
333 for( EDA_ITEM* candidate : aCandidates )
334 {
335 if( candidate && candidate != &aSource && Compatible( aSource, *candidate ) )
336 targets.push_back( candidate );
337 }
338
339 return targets;
340}
341
342
343bool MATCH_PROPERTIES_CATALOG::AnyEnabledFor( const EDA_ITEM& aItem, const std::set<wxString>& aEnabledKeys )
344{
345 const wxString prefix = familyPrefix( aItem );
346
347 if( prefix.IsEmpty() )
348 return false;
349
350 auto it = aEnabledKeys.lower_bound( prefix );
351
352 if( it != aEnabledKeys.end() && it->StartsWith( prefix ) )
353 return true;
354
355 const wxString family = Family( aItem );
356
357 for( const auto& [key, families] : commonReach() )
358 {
359 if( families.contains( family ) && aEnabledKeys.contains( COMMON_FAMILY + wxS( "/" ) + key ) )
360 return true;
361 }
362
363 return false;
364}
365
366
368static std::vector<PENDING_PROPERTY> plan( const EDA_ITEM& aSource, const EDA_ITEM& aTarget,
369 const std::set<wxString>& aEnabledKeys )
370{
371 std::vector<PENDING_PROPERTY> pending;
372 const wxString prefix = familyPrefix( aSource );
373 const wxString sourceFamily = MATCH_PROPERTIES_CATALOG::Family( aSource );
374 const wxString targetFamily = MATCH_PROPERTIES_CATALOG::Family( aTarget );
375 const bool acrossKinds = sourceFamily != targetFamily;
377 EDA_ITEM* source = const_cast<EDA_ITEM*>( &aSource );
378 const TYPE_ID sourceType = TYPE_HASH( aSource );
379 const TYPE_ID targetType = TYPE_HASH( aTarget );
380
381 auto stage =
382 [&]( const wxString& aSourceName, const wxString& aTargetName, bool aOptional )
383 {
384 PROPERTY_BASE* sourceProperty = mgr.GetProperty( sourceType, aSourceName );
385 PROPERTY_BASE* targetProperty = mgr.GetProperty( targetType, aTargetName );
386
387 if( !sourceProperty || !targetProperty )
388 return;
389
390 // The enabled set is persisted and hand-editable. It can name a stale property.
391 if( !sourceProperty->IsCopyable() || sourceProperty->IsHiddenFromPropertiesManager()
392 || !mgr.IsAvailableFor( sourceType, sourceProperty, source )
393 || !mgr.IsWriteableFor( sourceType, sourceProperty, source ) )
394 {
395 return;
396 }
397
398 pending.push_back( { targetProperty, aSource.Get( sourceProperty ), aOptional } );
399 };
400
401 // Enabled keys are the short list. Walk their prefix range, not every property of the type.
402 // GetProperty() is a linear scan, so one lookup per property is quadratic.
403 if( !acrossKinds )
404 {
405 for( auto it = aEnabledKeys.lower_bound( prefix ); it != aEnabledKeys.end() && it->StartsWith( prefix );
406 ++it )
407 {
408 const wxString name = it->Mid( prefix.length() );
409
410 stage( name, name, false );
411 }
412 }
413
414 // A common property is registered under a different name in each family, and crossing kinds
415 // it may simply not fit. Those are dropped rather than reported.
416 for( const auto& [key, families] : commonReach() )
417 {
418 auto sourceName = families.find( sourceFamily );
419 auto targetName = families.find( targetFamily );
420
421 if( sourceName == families.end() || targetName == families.end() )
422 continue;
423
424 if( !aEnabledKeys.contains( COMMON_FAMILY + wxS( "/" ) + key ) )
425 continue;
426
427 stage( sourceName->second, targetName->second, acrossKinds );
428 }
429
430 return pending;
431}
432
433
435 const std::set<wxString>& aEnabledKeys )
436{
438
439 if( !Compatible( aSource, aTarget ) )
440 {
441 result.m_Error = _( "The source and target have no properties in common." );
442 return result;
443 }
444
446 const TYPE_ID targetType = TYPE_HASH( aTarget );
447 std::unique_ptr<EDA_ITEM> staged( aTarget.Clone() );
448 std::vector<PENDING_PROPERTY> pending = plan( aSource, aTarget, aEnabledKeys );
449 std::vector<std::pair<PROPERTY_BASE*, bool>> stagedProperties;
450
451 // Setting one property can make another writeable. Sweep until nothing moves. What is
452 // still pending does not apply to this target. Drop it.
453 for( bool madeProgress = true; madeProgress; )
454 {
455 madeProgress = false;
456
457 for( auto it = pending.begin(); it != pending.end(); )
458 {
459 PROPERTY_BASE* targetProperty = it->m_Property;
460
461 if( !mgr.IsAvailableFor( targetType, targetProperty, staged.get() )
462 || !mgr.IsWriteableFor( targetType, targetProperty, staged.get() ) )
463 {
464 ++it;
465 continue;
466 }
467
468 if( !staged->Set( targetProperty, it->m_Value, false ) )
469 {
470 // Between two kinds of item the same idea can still be held differently. That
471 // is a property this target does not take, not a failure of the copy.
472 if( it->m_Optional )
473 {
474 it = pending.erase( it );
475 madeProgress = true;
476 continue;
477 }
478
479 result.m_Error = wxString::Format( _( "Could not apply property '%s' to the target item." ),
480 wxGetTranslation( targetProperty->Name() ) );
481 return result;
482 }
483
484 stagedProperties.push_back( { targetProperty, it->m_Optional } );
485 it = pending.erase( it );
486 madeProgress = true;
487 }
488 }
489
490 // A later property can turn a staged one read-only again. A validator means nothing until
491 // the item is finished. Re-check both before touching the real item.
492 std::vector<std::pair<PROPERTY_BASE*, wxAny>> apply;
493
494 for( const auto& [targetProperty, optional] : stagedProperties )
495 {
496 if( !mgr.IsAvailableFor( targetType, targetProperty, staged.get() )
497 || !mgr.IsWriteableFor( targetType, targetProperty, staged.get() ) )
498 {
499 continue;
500 }
501
502 wxAny stagedValue = staged->Get( targetProperty );
503
504 if( targetProperty->Validate( wxAny( stagedValue ), staged.get() ) )
505 {
506 // Across kinds a value that does not suit the target is nothing to report, the
507 // same as one that would not stage.
508 if( optional )
509 continue;
510
511 result.m_Error = wxString::Format( _( "The value for property '%s' is not valid for the target item." ),
512 wxGetTranslation( targetProperty->Name() ) );
513 return result;
514 }
515
516 apply.emplace_back( targetProperty, std::move( stagedValue ) );
517 }
518
519 for( auto& [targetProperty, value] : apply )
520 {
521 if( !KiWxAnyEquals( aTarget.Get( targetProperty ), value, targetProperty )
522 && aTarget.Set( targetProperty, value ) )
523 {
524 ++result.m_Changed;
525 }
526 }
527
528 return result;
529}
530
531
532const std::set<wxString>& MATCH_PROPERTIES_CATALOG::AllSafeKeys()
533{
534 // PROPERTY_MANAGER registrations are static. The answer cannot change after the first ask.
535 static const std::set<wxString> keys = []
536 {
537 std::set<wxString> result;
539
540 // Zones and rule areas are one item type, told apart by a flag. Ask a rule area which
541 // properties it offers.
542 BOARD board;
543 ZONE ruleArea( &board );
544 ruleArea.SetIsRuleArea( true );
545
546 for( const auto& [family, entry] : families() )
547 {
548 const TYPE_ID type = entry.m_Type;
549 const bool ruleAreaFamily = family == wxS( "rule_area" );
550
551 for( PROPERTY_BASE* property : mgr.GetProperties( type ) )
552 {
553 if( !property->IsCopyable() || property->IsHiddenFromPropertiesManager() )
554 continue;
555
556 if( type == TYPE_HASH( ZONE )
557 && mgr.IsAvailableFor( type, property, &ruleArea ) != ruleAreaFamily )
558 {
559 continue;
560 }
561
562 result.insert( family + wxS( "/" ) + property->Name() );
563 }
564 }
565
566 // A common property stands in for the per-family entries it covers, so the same idea is
567 // not offered twice under different names.
568 for( const auto& [key, common] : commonProperties() )
569 {
570 std::vector<wxString> covered;
571
572 for( const auto& [family, name] : common.m_Names )
573 {
574 const wxString familyKey = family + wxS( "/" ) + name;
575
576 if( result.contains( familyKey ) )
577 covered.push_back( familyKey );
578 }
579
580 // One family is not something in common; leave it where it was.
581 if( covered.size() < 2 )
582 continue;
583
584 for( const wxString& familyKey : covered )
585 result.erase( familyKey );
586
587 result.insert( COMMON_FAMILY + wxS( "/" ) + key );
588 }
589
590 return result;
591 }();
592
593 return keys;
594}
595
596
597const std::map<wxString, std::map<wxString, wxString>>& commonReach()
598{
599 static const std::map<wxString, std::map<wxString, wxString>> reach = []
600 {
601 std::map<wxString, std::map<wxString, wxString>> result;
602
603 // AllSafeKeys() decided which families a common key really covers. Rebuild that same
604 // decision here so the two cannot drift.
605 for( const auto& [key, common] : commonProperties() )
606 {
607 if( !MATCH_PROPERTIES_CATALOG::AllSafeKeys().contains( COMMON_FAMILY + wxS( "/" ) + key ) )
608 continue;
609
610 for( const auto& [family, name] : common.m_Names )
611 {
613 result[key][family] = name;
614 }
615 }
616
617 return result;
618 }();
619
620 return reach;
621}
622
623
624const std::set<wxString>& MATCH_PROPERTIES_CATALOG::DefaultKeys()
625{
626 static const std::set<wxString> keys = {
627 wxS( "common/Layer" ), wxS( "common/Line Width" ), wxS( "shape/Fill" ),
628 wxS( "common/Soldermask" ), wxS( "common/Soldermask Margin Override" ),
629 wxS( "common/Font" ), wxS( "common/Text Width" ), wxS( "common/Text Height" ),
630 wxS( "common/Text Thickness" ), wxS( "common/Bold" ), wxS( "common/Italic" ),
631 wxS( "shape/Line Style" ), wxS( "via/Diameter" ), wxS( "via/Hole" ),
632 wxS( "zone/Fill Mode" ), wxS( "table/Border Style" )
633 };
634
635 return keys;
636}
const char * name
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:409
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:98
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual EDA_ITEM * Clone() const
Create a duplicate of this item with linked list members set to NULL.
Definition eda_item.cpp:278
wxAny Get(PROPERTY_BASE *aProperty) const
bool Set(PROPERTY_BASE *aProperty, wxAny &aValue, bool aNotify=true)
Definition pad.h:61
For better understanding of the points that make a dimension:
Object to handle a bitmap image that can be inserted in a PCB.
bool IsHiddenFromPropertiesManager() const
Definition property.h:324
bool IsCopyable() const
True for a property that says how an item looks, not what or where it is.
Definition property.h:358
const wxString & Name() const
Definition property.h:221
Provide class metadata.Helper macro to map type hashes to names.
const std::vector< PROPERTY_BASE * > & GetProperties(TYPE_ID aType) const
Return all properties for a specific type.
bool IsWriteableFor(TYPE_ID aItemClass, PROPERTY_BASE *aProp, INSPECTABLE *aItem)
Checks overriden availability and original availability of a property, returns false if the property ...
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE * GetProperty(TYPE_ID aType, const wxString &aProperty) const
Return a property for a specific type.
bool IsAvailableFor(TYPE_ID aItemClass, PROPERTY_BASE *aProp, INSPECTABLE *aItem)
Checks overriden availability and original availability of a property, returns false if the property ...
Handle a list of polygons defining a copper zone.
Definition zone.h:70
void SetIsRuleArea(bool aEnable)
Definition zone.h:808
#define _(s)
Some functions to handle hotkeys in KiCad.
static std::vector< PENDING_PROPERTY > plan(const EDA_ITEM &aSource, const EDA_ITEM &aTarget, const std::set< wxString > &aEnabledKeys)
Target properties to write, paired with values read off the source.
static wxString familyPrefix(const EDA_ITEM &aItem)
Empty if the item has no family. Never matches a key.
static const std::map< wxString, COMMON_PROPERTY > & commonProperties()
Keyed by the name the settings use after the prefix.
static const wxString COMMON_FAMILY
The prefix common keys carry in the enabled set, in place of a family.
static const std::map< wxString, std::map< wxString, wxString > > & commonReach()
The families a common property actually reaches, once the unregistered ones are dropped.
static const std::map< wxString, FAMILY > & families()
Keyed by the names Family() returns. Every family there must appear here.
MATCH_PROPERTIES_RESULT Copy(const EDA_ITEM &aSource, EDA_ITEM &aTarget, const std::set< wxString > &aEnabledKeys)
bool Compatible(const EDA_ITEM &aSource, const EDA_ITEM &aTarget)
const std::set< wxString > & AllSafeKeys()
Every property Match Properties may copy, keyed as "family/Property Name".
bool PropertyIsRegistered(const wxString &aFamily, const wxString &aName)
Whether aFamily registers a property of that name. Used to prune the common table.
wxString PropertyLabel(const wxString &aKey)
The translated property name alone, without the family it belongs to.
const std::set< wxString > & DefaultKeys()
The subset enabled until the user says otherwise.
bool AnyEnabledFor(const EDA_ITEM &aItem, const std::set< wxString > &aEnabledKeys)
True if any enabled key names a property of this item's family.
std::vector< EDA_ITEM * > CompatibleTargets(const EDA_ITEM &aSource, const std::vector< EDA_ITEM * > &aCandidates)
wxString FamilyLabel(const wxString &aFamily)
The translated name of a family, for the heading of its group.
std::set< wxString > FamiliesFor(const wxString &aKey)
The families a key reaches. One for a family key, several for a common one.
wxString Family(const EDA_ITEM &aItem)
wxString DisplayLabel(const wxString &aKey)
#define _HKI(x)
Definition page_info.cpp:40
BARCODE class definition.
#define TYPE_HASH(x)
Definition property.h:74
size_t TYPE_ID
Unique type identifier.
A property that means the same thing in more than one family.
std::map< wxString, wxString > m_Names
family -> the name it is registered under there
TYPE_ID m_Type
One item type carrying every property the family advertises.
wxString m_Label
One value staged for the target. Optional entries are dropped if they will not go.
PROPERTY_BASE * m_Property
VECTOR2I end
wxString result
Test unit parsing edge cases and error handling.
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition typeinfo.h:98
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition typeinfo.h:95
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition typeinfo.h:89
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition typeinfo.h:96
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition typeinfo.h:100
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:84
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition typeinfo.h:81
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:82
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:93
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition typeinfo.h:99
@ PCB_TABLECELL_T
class PCB_TABLECELL, PCB_TEXTBOX for use in tables
Definition typeinfo.h:87
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition typeinfo.h:78
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition typeinfo.h:94
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition typeinfo.h:90
@ PCB_TABLE_T
class PCB_TABLE, table of PCB_TABLECELLs
Definition typeinfo.h:86
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition typeinfo.h:88
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition typeinfo.h:97
bool KiWxAnyEquals(const wxAny &aA, const wxAny &aB, const PROPERTY_BASE *aProperty)
Compare two wxAny values for equality across the KiCad property type set.