KiCad PCB EDA Suite
Loading...
Searching...
No Matches
net_settings.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 (C) 2020 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Jon Evans <[email protected]>
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include <algorithm>
23#include <limits>
24
25#include <json_common.h>
26
28#include <settings/parameters.h>
30#include <string_utils.h>
31#include <base_units.h>
32#include <unordered_set>
33
34
35// const int netSettingsSchemaVersion = 0;
36// const int netSettingsSchemaVersion = 1; // new overbar syntax
37// const int netSettingsSchemaVersion = 2; // exclude buses from netclass members
38// const int netSettingsSchemaVersion = 3; // netclass assignment patterns
39// const int netSettingsSchemaVersion = 4; // netclass ordering
40const int netSettingsSchemaVersion = 5; // Tuning profile names
41
42
43static std::optional<int> getInPcbUnits( const nlohmann::json& aObj, const std::string& aKey,
44 std::optional<int> aDefault = std::optional<int>() )
45{
46 if( aObj.contains( aKey ) && aObj[aKey].is_number() )
47 return pcbIUScale.mmToIU( aObj[aKey].get<double>() );
48 else
49 return aDefault;
50};
51
52
53static std::optional<int> getInSchUnits( const nlohmann::json& aObj, const std::string& aKey,
54 std::optional<int> aDefault = std::optional<int>() )
55{
56 if( aObj.contains( aKey ) && aObj[aKey].is_number() )
57 return schIUScale.MilsToIU( aObj[aKey].get<double>() );
58 else
59 return aDefault;
60};
61
62
63NET_SETTINGS::NET_SETTINGS( JSON_SETTINGS* aParent, const std::string& aPath ) :
64 NESTED_SETTINGS( "net_settings", netSettingsSchemaVersion, aParent, aPath, false )
65{
66 m_defaultNetClass = std::make_shared<NETCLASS>( NETCLASS::Default, true );
67 m_defaultNetClass->SetDescription( _( "This is the default net class." ) );
68 m_defaultNetClass->SetPriority( std::numeric_limits<int>::max() );
69
70 auto saveNetclass =
71 []( nlohmann::json& json_array, const std::shared_ptr<NETCLASS>& nc )
72 {
73 // Note: we're in common/, but we do happen to know which of these
74 // fields are used in which units system.
75 nlohmann::json nc_json = { { "name", nc->GetName().ToUTF8() },
76 { "priority", nc->GetPriority() },
77 { "schematic_color", nc->GetSchematicColor( true ) },
78 { "pcb_color", nc->GetPcbColor( true ) },
79 { "tuning_profile", nc->GetDelayProfile() } };
80
81 auto saveInPcbUnits =
82 []( nlohmann::json& json, const std::string& aKey, int aValue )
83 {
84 json.push_back( { aKey, pcbIUScale.IUTomm( aValue ) } );
85 };
86
87 if( nc->HasWireWidth() )
88 nc_json.push_back(
89 { "wire_width", schIUScale.IUToMils( nc->GetWireWidth() ) } );
90
91 if( nc->HasBusWidth() )
92 nc_json.push_back( { "bus_width", schIUScale.IUToMils( nc->GetBusWidth() ) } );
93
94 if( nc->HasLineStyle() )
95 nc_json.push_back( { "line_style", nc->GetLineStyle() } );
96
97 if( nc->HasClearance() )
98 saveInPcbUnits( nc_json, "clearance", nc->GetClearance() );
99
100 if( nc->HasTrackWidth() )
101 saveInPcbUnits( nc_json, "track_width", nc->GetTrackWidth() );
102
103 if( nc->HasViaDiameter() )
104 saveInPcbUnits( nc_json, "via_diameter", nc->GetViaDiameter() );
105
106 if( nc->HasViaDrill() )
107 saveInPcbUnits( nc_json, "via_drill", nc->GetViaDrill() );
108
109 if( nc->HasuViaDiameter() )
110 saveInPcbUnits( nc_json, "microvia_diameter", nc->GetuViaDiameter() );
111
112 if( nc->HasuViaDrill() )
113 saveInPcbUnits( nc_json, "microvia_drill", nc->GetuViaDrill() );
114
115 if( nc->HasDiffPairWidth() )
116 saveInPcbUnits( nc_json, "diff_pair_width", nc->GetDiffPairWidth() );
117
118 if( nc->HasDiffPairGap() )
119 saveInPcbUnits( nc_json, "diff_pair_gap", nc->GetDiffPairGap() );
120
121 if( nc->HasDiffPairViaGap() )
122 saveInPcbUnits( nc_json, "diff_pair_via_gap", nc->GetDiffPairViaGap() );
123
124 json_array.push_back( nc_json );
125 };
126
127 auto readNetClass =
128 []( const nlohmann::json& entry )
129 {
130 wxString name = entry["name"];
131
132 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( name, false );
133
134 int priority = entry["priority"];
135 nc->SetPriority( priority );
136
137 nc->SetDelayProfile( entry["tuning_profile"] );
138
139 if( auto value = getInPcbUnits( entry, "clearance" ) )
140 nc->SetClearance( *value );
141
142 if( auto value = getInPcbUnits( entry, "track_width" ) )
143 nc->SetTrackWidth( *value );
144
145 if( auto value = getInPcbUnits( entry, "via_diameter" ) )
146 nc->SetViaDiameter( *value );
147
148 if( auto value = getInPcbUnits( entry, "via_drill" ) )
149 nc->SetViaDrill( *value );
150
151 if( auto value = getInPcbUnits( entry, "microvia_diameter" ) )
152 nc->SetuViaDiameter( *value );
153
154 if( auto value = getInPcbUnits( entry, "microvia_drill" ) )
155 nc->SetuViaDrill( *value );
156
157 if( auto value = getInPcbUnits( entry, "diff_pair_width" ) )
158 nc->SetDiffPairWidth( *value );
159
160 if( auto value = getInPcbUnits( entry, "diff_pair_gap" ) )
161 nc->SetDiffPairGap( *value );
162
163 if( auto value = getInPcbUnits( entry, "diff_pair_via_gap" ) )
164 nc->SetDiffPairViaGap( *value );
165
166 if( auto value = getInSchUnits( entry, "wire_width" ) )
167 nc->SetWireWidth( *value );
168
169 if( auto value = getInSchUnits( entry, "bus_width" ) )
170 nc->SetBusWidth( *value );
171
172 if( entry.contains( "line_style" ) && entry["line_style"].is_number() )
173 nc->SetLineStyle( entry["line_style"].get<int>() );
174
175 if( entry.contains( "pcb_color" ) && entry["pcb_color"].is_string() )
176 nc->SetPcbColor( entry["pcb_color"].get<KIGFX::COLOR4D>() );
177
178 if( entry.contains( "schematic_color" )
179 && entry["schematic_color"].is_string() )
180 {
181 nc->SetSchematicColor( entry["schematic_color"].get<KIGFX::COLOR4D>() );
182 }
183
184 return nc;
185 };
186
187 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "classes",
188 [&]() -> nlohmann::json
189 {
190 nlohmann::json ret = nlohmann::json::array();
191
192 if( m_defaultNetClass )
193 saveNetclass( ret, m_defaultNetClass );
194
195 for( const auto& [name, netclass] : m_netClasses )
196 saveNetclass( ret, netclass );
197
198 return ret;
199 },
200 [&]( const nlohmann::json& aJson )
201 {
202 if( !aJson.is_array() )
203 return;
204
205 m_netClasses.clear();
206
207 for( const nlohmann::json& entry : aJson )
208 {
209 if( !entry.is_object() || !entry.contains( "name" ) )
210 continue;
211
212 std::shared_ptr<NETCLASS> nc = readNetClass( entry );
213
214 if( nc->IsDefault() )
215 m_defaultNetClass = nc;
216 else
217 m_netClasses[nc->GetName()] = nc;
218 }
219 },
220 {} ) );
221
222 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "net_colors",
223 [&]() -> nlohmann::json
224 {
225 nlohmann::json ret = {};
226
227 for( const auto& [netname, color] : m_netColorAssignments )
228 {
229 std::string key( netname.ToUTF8() );
230 ret[ std::move( key ) ] = color;
231 }
232
233 return ret;
234 },
235 [&]( const nlohmann::json& aJson )
236 {
237 if( !aJson.is_object() )
238 return;
239
240 m_netColorAssignments.clear();
241
242 for( const auto& pair : aJson.items() )
243 {
244 wxString key( pair.key().c_str(), wxConvUTF8 );
245 m_netColorAssignments[std::move( key )] = pair.value().get<KIGFX::COLOR4D>();
246 }
247 },
248 {} ) );
249
250 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "netclass_assignments",
251 [&]() -> nlohmann::json
252 {
253 nlohmann::json ret = {};
254
255 for( const auto& [netname, netclassNames] : m_netClassLabelAssignments )
256 {
257 nlohmann::json netclassesJson = nlohmann::json::array();
258
259 for( const auto& netclass : netclassNames )
260 {
261 std::string netclassStr( netclass.ToUTF8() );
262 netclassesJson.push_back( std::move( netclassStr ) );
263 }
264
265 std::string key( netname.ToUTF8() );
266 ret[std::move( key )] = netclassesJson;
267 }
268
269 return ret;
270 },
271 [&]( const nlohmann::json& aJson )
272 {
273 if( !aJson.is_object() )
274 return;
275
276 m_netClassLabelAssignments.clear();
277
278 for( const auto& pair : aJson.items() )
279 {
280 wxString key( pair.key().c_str(), wxConvUTF8 );
281
282 for( const auto& netclassName : pair.value() )
283 m_netClassLabelAssignments[key].insert( netclassName.get<wxString>() );
284 }
285 },
286 {} ) );
287
288 m_params.emplace_back( new PARAM_LAMBDA<nlohmann::json>( "netclass_patterns",
289 [&]() -> nlohmann::json
290 {
291 nlohmann::json ret = nlohmann::json::array();
292
293 for( const auto& [matcher, netclassName] : m_netClassPatternAssignments )
294 {
295 nlohmann::json pattern_json = {
296 { "pattern", matcher->GetPattern().ToUTF8() },
297 { "netclass", netclassName.ToUTF8() }
298 };
299
300 ret.push_back( std::move( pattern_json ) );
301 }
302
303 return ret;
304 },
305 [&]( const nlohmann::json& aJson )
306 {
307 if( !aJson.is_array() )
308 return;
309
310 m_netClassPatternAssignments.clear();
311
312 for( const nlohmann::json& entry : aJson )
313 {
314 if( !entry.is_object() )
315 continue;
316
317 if( entry.contains( "pattern" ) && entry["pattern"].is_string()
318 && entry.contains( "netclass" ) && entry["netclass"].is_string() )
319 {
320 wxString pattern = entry["pattern"].get<wxString>();
321 wxString netclass = entry["netclass"].get<wxString>();
322
323 m_netClassPatternAssignments.push_back(
324 { std::make_unique<EDA_COMBINED_MATCHER>( pattern, CTX_NETCLASS ),
325 netclass } );
326 }
327 }
328 },
329 {} ) );
330
331 registerMigration( 0, 1, std::bind( &NET_SETTINGS::migrateSchema0to1, this ) );
332 registerMigration( 1, 2, std::bind( &NET_SETTINGS::migrateSchema1to2, this ) );
333 registerMigration( 2, 3, std::bind( &NET_SETTINGS::migrateSchema2to3, this ) );
334 registerMigration( 3, 4, std::bind( &NET_SETTINGS::migrateSchema3to4, this ) );
335 registerMigration( 4, 5, std::bind( &NET_SETTINGS::migrateSchema4to5, this ) );
336}
337
338
340{
341 // Release early before destroying members
342 if( m_parent )
343 {
345 m_parent = nullptr;
346 }
347}
348
349
350bool NET_SETTINGS::operator==( const NET_SETTINGS& aOther ) const
351{
352 if( !std::equal( std::begin( m_netClasses ), std::end( m_netClasses ),
353 std::begin( aOther.m_netClasses ) ) )
354 return false;
355
356 if( !std::equal( std::begin( m_netClassPatternAssignments ),
358 std::begin( aOther.m_netClassPatternAssignments ) ) )
359 return false;
360
361 if( !std::equal( std::begin( m_netClassLabelAssignments ),
362 std::end( m_netClassLabelAssignments ),
363 std::begin( aOther.m_netClassLabelAssignments ) ) )
364 return false;
365
366
367 if( !std::equal( std::begin( m_netColorAssignments ), std::end( m_netColorAssignments ),
368 std::begin( aOther.m_netColorAssignments ) ) )
369 return false;
370
371 return true;
372}
373
374
376{
377 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
378 {
379 for( auto& netClass : m_internals->At( "classes" ).items() )
380 {
381 if( netClass.value().contains( "nets" ) && netClass.value()["nets"].is_array() )
382 {
383 nlohmann::json migrated = nlohmann::json::array();
384
385 for( auto& net : netClass.value()["nets"].items() )
386 migrated.push_back( ConvertToNewOverbarNotation( net.value().get<wxString>() ) );
387
388 netClass.value()["nets"] = migrated;
389 }
390 }
391 }
392
393 return true;
394}
395
396
398{
399 return true;
400}
401
402
404{
405 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
406 {
407 nlohmann::json patterns = nlohmann::json::array();
408
409 for( auto& netClass : m_internals->At( "classes" ).items() )
410 {
411 if( netClass.value().contains( "name" )
412 && netClass.value().contains( "nets" )
413 && netClass.value()["nets"].is_array() )
414 {
415 wxString netClassName = netClass.value()["name"].get<wxString>();
416
417 for( auto& net : netClass.value()["nets"].items() )
418 {
419 nlohmann::json pattern_json = {
420 { "pattern", net.value().get<wxString>() },
421 { "netclass", netClassName }
422 };
423
424 patterns.push_back( pattern_json );
425 }
426 }
427 }
428
429 m_internals->SetFromString( "netclass_patterns", patterns );
430 }
431
432 return true;
433}
434
435
437{
438 // Add priority field to netclasses
439 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
440 {
441 int priority = 0;
442
443 for( auto& netClass : m_internals->At( "classes" ).items() )
444 {
445 if( netClass.value()["name"].get<wxString>() == NETCLASS::Default )
446 netClass.value()["priority"] = std::numeric_limits<int>::max();
447 else
448 netClass.value()["priority"] = priority++;
449 }
450 }
451
452 // Move netclass assignments to a list
453 if( m_internals->contains( "netclass_assignments" )
454 && m_internals->At( "netclass_assignments" ).is_object() )
455 {
456 nlohmann::json migrated = {};
457
458 for( const auto& pair : m_internals->At( "netclass_assignments" ).items() )
459 {
460 nlohmann::json netclassesJson = nlohmann::json::array();
461
462 if( pair.value().get<wxString>() != wxEmptyString )
463 netclassesJson.push_back( pair.value() );
464
465 migrated[pair.key()] = netclassesJson;
466 }
467
468 m_internals->SetFromString( "netclass_assignments", migrated );
469 }
470
471 return true;
472}
473
474
476{
477 // Add tuning profile name field to netclasses
478 if( m_internals->contains( "classes" ) && m_internals->At( "classes" ).is_array() )
479 {
480 const wxString emptyStr = "";
481
482 for( auto& netClass : m_internals->At( "classes" ).items() )
483 netClass.value()["tuning_profile"] = emptyStr.ToUTF8();
484 }
485
486 return true;
487}
488
489
490void NET_SETTINGS::SetDefaultNetclass( std::shared_ptr<NETCLASS> netclass )
491{
492 m_defaultNetClass = netclass;
493}
494
495
496std::shared_ptr<NETCLASS> NET_SETTINGS::GetDefaultNetclass()
497{
498 return m_defaultNetClass;
499}
500
501
502bool NET_SETTINGS::HasNetclass( const wxString& netclassName ) const
503{
504 return m_netClasses.find( netclassName ) != m_netClasses.end();
505}
506
507
508void NET_SETTINGS::SetNetclass( const wxString& netclassName, std::shared_ptr<NETCLASS>& netclass )
509{
510 m_netClasses[netclassName] = netclass;
511}
512
513
514void NET_SETTINGS::SetNetclasses( const std::map<wxString, std::shared_ptr<NETCLASS>>& netclasses )
515{
516 m_netClasses = netclasses;
518}
519
520
521const std::map<wxString, std::shared_ptr<NETCLASS>>& NET_SETTINGS::GetNetclasses() const
522{
523 return m_netClasses;
524}
525
526
527const std::map<wxString, std::shared_ptr<NETCLASS>>& NET_SETTINGS::GetCompositeNetclasses() const
528{
530}
531
532
534{
535 m_netClasses.clear();
536 m_impicitNetClasses.clear();
538}
539
540
541const std::map<wxString, std::set<wxString>>& NET_SETTINGS::GetNetclassLabelAssignments() const
542{
544}
545
546
548{
550}
551
552
553void NET_SETTINGS::ClearNetclassLabelAssignment( const wxString& netName )
554{
555 m_netClassLabelAssignments.erase( netName );
556}
557
558
559void NET_SETTINGS::SetNetclassLabelAssignment( const wxString& netName,
560 const std::set<wxString>& netclasses )
561{
562 m_netClassLabelAssignments[netName] = netclasses;
563}
564
565
567 const std::set<wxString>& netclasses )
568{
569 m_netClassLabelAssignments[netName].insert( netclasses.begin(), netclasses.end() );
570}
571
572
573bool NET_SETTINGS::HasNetclassLabelAssignment( const wxString& netName ) const
574{
575 return m_netClassLabelAssignments.find( netName ) != m_netClassLabelAssignments.end();
576}
577
578
579void NET_SETTINGS::SetNetclassPatternAssignment( const wxString& pattern, const wxString& netclass )
580{
581 // Avoid exact duplicates - these shouldn't cause problems, due to later de-duplication
582 // but they are unnecessary.
583 for( auto& assignment : m_netClassPatternAssignments )
584 {
585 if( assignment.first->GetPattern() == pattern && assignment.second == netclass )
586 return;
587 }
588
589 // No assignment, add a new one
591 { std::make_unique<EDA_COMBINED_MATCHER>( pattern, CTX_NETCLASS ), netclass } );
592
594}
595
596
598 std::vector<std::pair<std::unique_ptr<EDA_COMBINED_MATCHER>, wxString>>&& netclassPatterns )
599{
600 m_netClassPatternAssignments = std::move( netclassPatterns );
602}
603
604
605std::vector<std::pair<std::unique_ptr<EDA_COMBINED_MATCHER>, wxString>>&
607{
609}
610
611
613{
615}
616
617
618void NET_SETTINGS::ClearCacheForNet( const wxString& netName )
619{
620 if( m_effectiveNetclassCache.count( netName ) )
621 {
622 wxString compositeNetclassName = m_effectiveNetclassCache[netName]->GetName();
623 m_compositeNetClasses.erase( compositeNetclassName );
624 m_effectiveNetclassCache.erase( netName );
625 }
626}
627
628
630{
632 m_compositeNetClasses.clear();
633}
634
635
636void NET_SETTINGS::SetNetColorAssignment( const wxString& netName, const KIGFX::COLOR4D& color )
637{
638 m_netColorAssignments[netName] = color;
639}
640
641
642const std::map<wxString, KIGFX::COLOR4D>& NET_SETTINGS::GetNetColorAssignments() const
643{
645}
646
647
649{
650 m_netColorAssignments.clear();
651}
652
653
654bool NET_SETTINGS::HasEffectiveNetClass( const wxString& aNetName ) const
655{
656 return m_effectiveNetclassCache.count( aNetName ) > 0;
657}
658
659
660std::shared_ptr<NETCLASS> NET_SETTINGS::GetCachedEffectiveNetClass( const wxString& aNetName ) const
661{
662 return m_effectiveNetclassCache.at( aNetName );
663}
664
665
666std::shared_ptr<NETCLASS> NET_SETTINGS::GetEffectiveNetClass( const wxString& aNetName )
667{
668 // Lambda to fetch an explicit netclass. Returns a nullptr if not found
669 auto getExplicitNetclass = [this]( const wxString& netclass ) -> std::shared_ptr<NETCLASS>
670 {
671 if( netclass == NETCLASS::Default )
672 return m_defaultNetClass;
673
674 auto ii = m_netClasses.find( netclass );
675
676 if( ii == m_netClasses.end() )
677 return {};
678 else
679 return ii->second;
680 };
681
682 // Lambda to fetch or create an implicit netclass (defined with a label, but not configured)
683 // These are needed as while they do not provide any netclass parameters, they do now appear in
684 // DRC matching strings as an assigned netclass.
685 auto getOrAddImplicitNetcless = [this]( const wxString& netclass ) -> std::shared_ptr<NETCLASS>
686 {
687 auto ii = m_impicitNetClasses.find( netclass );
688
689 if( ii == m_impicitNetClasses.end() )
690 {
691 std::shared_ptr<NETCLASS> nc = std::make_shared<NETCLASS>( netclass, false );
692 nc->SetPriority( std::numeric_limits<int>::max() - 1 ); // Priority > default netclass
693 m_impicitNetClasses[netclass] = nc;
694 return nc;
695 }
696 else
697 {
698 return ii->second;
699 }
700 };
701
702 // <no net> is forced to be part of the default netclass.
703 if( aNetName.IsEmpty() )
704 return m_defaultNetClass;
705
706 // First check if we have a cached resolved netclass
707 auto cacheItr = m_effectiveNetclassCache.find( aNetName );
708
709 if( cacheItr != m_effectiveNetclassCache.end() )
710 return cacheItr->second;
711
712 // No cache found - build a vector of all netclasses assigned to or matching this net
713 std::unordered_set<std::shared_ptr<NETCLASS>> resolvedNetclasses;
714
715 // First find explicit netclass assignments
716 auto it = m_netClassLabelAssignments.find( aNetName );
717
718 if( it != m_netClassLabelAssignments.end() && it->second.size() > 0 )
719 {
720 for( const wxString& netclassName : it->second )
721 {
722 std::shared_ptr<NETCLASS> netclass = getExplicitNetclass( netclassName );
723
724 if( netclass )
725 {
726 resolvedNetclasses.insert( std::move( netclass ) );
727 }
728 else
729 {
730 resolvedNetclasses.insert( getOrAddImplicitNetcless( netclassName ) );
731 }
732 }
733 }
734
735 // Now find any pattern-matched netclass assignments
736 for( const auto& [matcher, netclassName] : m_netClassPatternAssignments )
737 {
738 if( matcher->StartsWith( aNetName ) )
739 {
740 std::shared_ptr<NETCLASS> netclass = getExplicitNetclass( netclassName );
741
742 if( netclass )
743 {
744 resolvedNetclasses.insert( std::move( netclass ) );
745 }
746 else
747 {
748 resolvedNetclasses.insert( getOrAddImplicitNetcless( netclassName ) );
749 }
750 }
751 }
752
753 // Handle zero resolved netclasses
754 if( resolvedNetclasses.size() == 0 )
755 {
757
758 return m_defaultNetClass;
759 }
760
761 // Make and cache the effective netclass. Note that makeEffectiveNetclass will add the default
762 // netclass to resolvedNetclasses if it is needed to complete the netclass paramters set. It
763 // will also sort resolvedNetclasses by priority order.
764 std::vector<NETCLASS*> netclassPtrs;
765
766 for( const std::shared_ptr<NETCLASS>& nc : resolvedNetclasses )
767 netclassPtrs.push_back( nc.get() );
768
769 wxString name;
770 name.Printf( "Effective for net: %s", aNetName );
771 std::shared_ptr<NETCLASS> effectiveNetclass = std::make_shared<NETCLASS>( name, false );
772 makeEffectiveNetclass( effectiveNetclass, netclassPtrs );
773
774 if( netclassPtrs.size() == 1 )
775 {
776 // No defaults were added - just return the primary netclass
777 m_effectiveNetclassCache[aNetName] = *resolvedNetclasses.begin();
778 return *resolvedNetclasses.begin();
779 }
780 else
781 {
782 effectiveNetclass->SetConstituentNetclasses( std::move( netclassPtrs ) );
783
784 m_compositeNetClasses[effectiveNetclass->GetName()] = effectiveNetclass;
785 m_effectiveNetclassCache[aNetName] = effectiveNetclass;
786
787 return effectiveNetclass;
788 }
789}
790
791
793{
794 for( auto& [ncName, nc] : m_compositeNetClasses )
795 {
796 // Note this needs to be a copy in case we now need to add the default netclass
797 std::vector<NETCLASS*> constituents = nc->GetConstituentNetclasses();
798
799 wxASSERT( constituents.size() > 0 );
800
801 // If the last netclass is Default, remove it (it will be re-added if still needed)
802 if( ( *constituents.rbegin() )->GetName() == NETCLASS::Default )
803 {
804 constituents.pop_back();
805 }
806
807 // Remake the netclass from original constituents
808 nc->ResetParameters();
809 makeEffectiveNetclass( nc, constituents );
810 nc->SetConstituentNetclasses( std::move( constituents ) );
811 }
812}
813
814
815void NET_SETTINGS::makeEffectiveNetclass( std::shared_ptr<NETCLASS>& effectiveNetclass,
816 std::vector<NETCLASS*>& constituentNetclasses ) const
817{
818 // Sort the resolved netclasses by priority (highest first), with same-priority netclasses
819 // ordered alphabetically
820 std::sort( constituentNetclasses.begin(), constituentNetclasses.end(),
821 []( NETCLASS* nc1, NETCLASS* nc2 )
822 {
823 int p1 = nc1->GetPriority();
824 int p2 = nc2->GetPriority();
825
826 if( p1 < p2 )
827 return true;
828
829 if (p1 == p2)
830 return nc1->GetName().Cmp( nc2->GetName() ) < 0;
831
832 return false;
833 } );
834
835 // Iterate from lowest priority netclass and fill effective netclass parameters
836 for( auto itr = constituentNetclasses.rbegin(); itr != constituentNetclasses.rend(); ++itr )
837 {
838 NETCLASS* nc = *itr;
839
840 if( nc->HasClearance() )
841 {
842 effectiveNetclass->SetClearance( nc->GetClearance() );
843 effectiveNetclass->SetClearanceParent( nc );
844 }
845
846 if( nc->HasTrackWidth() )
847 {
848 effectiveNetclass->SetTrackWidth( nc->GetTrackWidth() );
849 effectiveNetclass->SetTrackWidthParent( nc );
850 }
851
852 if( nc->HasViaDiameter() )
853 {
854 effectiveNetclass->SetViaDiameter( nc->GetViaDiameter() );
855 effectiveNetclass->SetViaDiameterParent( nc );
856 }
857
858 if( nc->HasViaDrill() )
859 {
860 effectiveNetclass->SetViaDrill( nc->GetViaDrill() );
861 effectiveNetclass->SetViaDrillParent( nc );
862 }
863
864 if( nc->HasuViaDiameter() )
865 {
866 effectiveNetclass->SetuViaDiameter( nc->GetuViaDiameter() );
867 effectiveNetclass->SetuViaDiameterParent( nc );
868 }
869
870 if( nc->HasuViaDrill() )
871 {
872 effectiveNetclass->SetuViaDrill( nc->GetuViaDrill() );
873 effectiveNetclass->SetuViaDrillParent( nc );
874 }
875
876 if( nc->HasDiffPairWidth() )
877 {
878 effectiveNetclass->SetDiffPairWidth( nc->GetDiffPairWidth() );
879 effectiveNetclass->SetDiffPairWidthParent( nc );
880 }
881
882 if( nc->HasDiffPairGap() )
883 {
884 effectiveNetclass->SetDiffPairGap( nc->GetDiffPairGap() );
885 effectiveNetclass->SetDiffPairGapParent( nc );
886 }
887
888 if( nc->HasDiffPairViaGap() )
889 {
890 effectiveNetclass->SetDiffPairViaGap( nc->GetDiffPairViaGap() );
891 effectiveNetclass->SetDiffPairViaGapParent( nc );
892 }
893
894 if( nc->HasWireWidth() )
895 {
896 effectiveNetclass->SetWireWidth( nc->GetWireWidth() );
897 effectiveNetclass->SetWireWidthParent( nc );
898 }
899
900 if( nc->HasBusWidth() )
901 {
902 effectiveNetclass->SetBusWidth( nc->GetBusWidth() );
903 effectiveNetclass->SetBusWidthParent( nc );
904 }
905
906 if( nc->HasLineStyle() )
907 {
908 effectiveNetclass->SetLineStyle( nc->GetLineStyle() );
909 effectiveNetclass->SetLineStyleParent( nc );
910 }
911
912 COLOR4D pcbColor = nc->GetPcbColor();
913
914 if( pcbColor != COLOR4D::UNSPECIFIED )
915 {
916 effectiveNetclass->SetPcbColor( pcbColor );
917 effectiveNetclass->SetPcbColorParent( nc );
918 }
919
920 COLOR4D schColor = nc->GetSchematicColor();
921
922 if( schColor != COLOR4D::UNSPECIFIED )
923 {
924 effectiveNetclass->SetSchematicColor( schColor );
925 effectiveNetclass->SetSchematicColorParent( nc );
926 }
927
928 if( nc->HasDelayProfile() )
929 {
930 effectiveNetclass->SetDelayProfile( nc->GetDelayProfile() );
931 effectiveNetclass->SetDelayProfileParent( nc );
932 }
933 }
934
935 // Fill in any required defaults
936 if( addMissingDefaults( effectiveNetclass.get() ) )
937 constituentNetclasses.push_back( m_defaultNetClass.get() );
938}
939
940
942{
943 bool addedDefault = false;
944
945 if( !nc->HasClearance() )
946 {
947 addedDefault = true;
948 nc->SetClearance( m_defaultNetClass->GetClearance() );
950 }
951
952 if( !nc->HasTrackWidth() )
953 {
954 addedDefault = true;
955 nc->SetTrackWidth( m_defaultNetClass->GetTrackWidth() );
957 }
958
959 if( !nc->HasViaDiameter() )
960 {
961 addedDefault = true;
962 nc->SetViaDiameter( m_defaultNetClass->GetViaDiameter() );
964 }
965
966 if( !nc->HasViaDrill() )
967 {
968 addedDefault = true;
969 nc->SetViaDrill( m_defaultNetClass->GetViaDrill() );
971 }
972
973 if( !nc->HasuViaDiameter() )
974 {
975 addedDefault = true;
976 nc->SetuViaDiameter( m_defaultNetClass->GetuViaDiameter() );
978 }
979
980 if( !nc->HasuViaDrill() )
981 {
982 addedDefault = true;
983 nc->SetuViaDrill( m_defaultNetClass->GetuViaDrill() );
985 }
986
987 if( !nc->HasDiffPairWidth() )
988 {
989 addedDefault = true;
990 nc->SetDiffPairWidth( m_defaultNetClass->GetDiffPairWidth() );
992 }
993
994 if( !nc->HasDiffPairGap() )
995 {
996 addedDefault = true;
997 nc->SetDiffPairGap( m_defaultNetClass->GetDiffPairGap() );
999 }
1000
1001 // Currently this is only on the default netclass, and not editable in the setup panel
1002 // if( !nc->HasDiffPairViaGap() )
1003 // {
1004 // addedDefault = true;
1005 // nc->SetDiffPairViaGap( m_defaultNetClass->GetDiffPairViaGap() );
1006 // nc->SetDiffPairViaGapParent( m_defaultNetClass.get() );
1007 // }
1008
1009 if( !nc->HasWireWidth() )
1010 {
1011 addedDefault = true;
1012 nc->SetWireWidth( m_defaultNetClass->GetWireWidth() );
1014 }
1015
1016 if( !nc->HasBusWidth() )
1017 {
1018 addedDefault = true;
1019 nc->SetBusWidth( m_defaultNetClass->GetBusWidth() );
1021 }
1022
1023 // The tuning profile can be empty - only fill if a default tuning profile is set
1024 if( !nc->HasDelayProfile() && m_defaultNetClass->HasDelayProfile() )
1025 {
1026 addedDefault = true;
1027 nc->SetDelayProfile( m_defaultNetClass->GetDelayProfile() );
1029 }
1030
1031 return addedDefault;
1032}
1033
1034
1035std::shared_ptr<NETCLASS> NET_SETTINGS::GetNetClassByName( const wxString& aNetClassName ) const
1036{
1037 auto ii = m_netClasses.find( aNetClassName );
1038
1039 if( ii == m_netClasses.end() )
1040 return m_defaultNetClass;
1041 else
1042 return ii->second;
1043}
1044
1045
1046static bool isSuperSubOverbar( wxChar c )
1047{
1048 return c == '_' || c == '^' || c == '~';
1049}
1050
1051
1052bool NET_SETTINGS::ParseBusVector( const wxString& aBus, wxString* aName,
1053 std::vector<wxString>* aMemberList )
1054{
1055 auto isDigit = []( wxChar c )
1056 {
1057 static wxString digits( wxT( "0123456789" ) );
1058 return digits.Contains( c );
1059 };
1060
1061 size_t busLen = aBus.length();
1062 size_t i = 0;
1063 wxString prefix;
1064 wxString suffix;
1065 wxString tmp;
1066 long begin = 0;
1067 long end = 0;
1068 int braceNesting = 0;
1069
1070 prefix.reserve( busLen );
1071
1072 // Parse prefix
1073 //
1074 for( ; i < busLen; ++i )
1075 {
1076 if( aBus[i] == '{' )
1077 {
1078 if( i > 0 && isSuperSubOverbar( aBus[i-1] ) )
1079 braceNesting++;
1080 else
1081 return false;
1082 }
1083 else if( aBus[i] == '}' )
1084 {
1085 braceNesting--;
1086 }
1087
1088 if( aBus[i] == ' ' || aBus[i] == ']' )
1089 return false;
1090
1091 if( aBus[i] == '[' )
1092 break;
1093
1094 prefix += aBus[i];
1095 }
1096
1097 // Parse start number
1098 //
1099 i++; // '[' character
1100
1101 if( i >= busLen )
1102 return false;
1103
1104 for( ; i < busLen; ++i )
1105 {
1106 if( aBus[i] == '.' && i + 1 < busLen && aBus[i+1] == '.' )
1107 {
1108 tmp.ToLong( &begin );
1109 i += 2;
1110 break;
1111 }
1112
1113 if( !isDigit( aBus[i] ) )
1114 return false;
1115
1116 tmp += aBus[i];
1117 }
1118
1119 // Parse end number
1120 //
1121 tmp = wxEmptyString;
1122
1123 if( i >= busLen )
1124 return false;
1125
1126 for( ; i < busLen; ++i )
1127 {
1128 if( aBus[i] == ']' )
1129 {
1130 tmp.ToLong( &end );
1131 ++i;
1132 break;
1133 }
1134
1135 if( !isDigit( aBus[i] ) )
1136 return false;
1137
1138 tmp += aBus[i];
1139 }
1140
1141 // Parse suffix
1142 //
1143 for( ; i < busLen; ++i )
1144 {
1145 if( aBus[i] == '}' )
1146 {
1147 braceNesting--;
1148 suffix += aBus[i];
1149 }
1150 else
1151 {
1152 return false;
1153 }
1154 }
1155
1156 if( braceNesting != 0 )
1157 return false;
1158
1159 if( begin == end )
1160 return false;
1161 else if( begin > end )
1162 std::swap( begin, end );
1163
1164 if( aName )
1165 *aName = prefix;
1166
1167 if( aMemberList )
1168 {
1169 for( long idx = begin; idx <= end; ++idx )
1170 {
1171 wxString str = prefix;
1172 str << idx;
1173 str << suffix;
1174
1175 aMemberList->emplace_back( str );
1176 }
1177 }
1178
1179 return true;
1180}
1181
1182
1183bool NET_SETTINGS::ParseBusGroup( const wxString& aGroup, wxString* aName,
1184 std::vector<wxString>* aMemberList )
1185{
1186 size_t groupLen = aGroup.length();
1187 size_t i = 0;
1188 wxString prefix;
1189 wxString tmp;
1190 int braceNesting = 0;
1191
1192 prefix.reserve( groupLen );
1193
1194 // Parse prefix
1195 //
1196 for( ; i < groupLen; ++i )
1197 {
1198 if( aGroup[i] == '{' )
1199 {
1200 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1201 braceNesting++;
1202 else
1203 break;
1204 }
1205 else if( aGroup[i] == '}' )
1206 {
1207 braceNesting--;
1208 }
1209
1210 if( aGroup[i] == ' ' || aGroup[i] == '[' || aGroup[i] == ']' )
1211 return false;
1212
1213 prefix += aGroup[i];
1214 }
1215
1216 if( braceNesting != 0 )
1217 return false;
1218
1219 if( aName )
1220 *aName = prefix;
1221
1222 // Parse members
1223 //
1224 i++; // '{' character
1225
1226 if( i >= groupLen )
1227 return false;
1228
1229 for( ; i < groupLen; ++i )
1230 {
1231 if( aGroup[i] == '{' )
1232 {
1233 if( i > 0 && isSuperSubOverbar( aGroup[i-1] ) )
1234 braceNesting++;
1235 else
1236 return false;
1237 }
1238 else if( aGroup[i] == '}' )
1239 {
1240 if( braceNesting )
1241 {
1242 braceNesting--;
1243 }
1244 else
1245 {
1246 if( aMemberList && !tmp.IsEmpty() )
1247 aMemberList->push_back( EscapeString( tmp, CTX_NETNAME ) );
1248
1249 return true;
1250 }
1251 }
1252
1253 // Commas aren't strictly legal, but we can be pretty sure what the author had in mind.
1254 if( aGroup[i] == ' ' || aGroup[i] == ',' )
1255 {
1256 if( aMemberList && !tmp.IsEmpty() )
1257 aMemberList->push_back( EscapeString( tmp, CTX_NETNAME ) );
1258
1259 tmp.Clear();
1260 continue;
1261 }
1262
1263 tmp += aGroup[i];
1264 }
1265
1266 return false;
1267}
int color
Definition: DXF_plotter.cpp:63
const char * name
Definition: DXF_plotter.cpp:62
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:114
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:112
void ReleaseNestedSettings(NESTED_SETTINGS *aSettings)
Saves and frees a nested settings object, if it exists within this one.
std::unique_ptr< JSON_SETTINGS_INTERNALS > m_internals
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
NESTED_SETTINGS is a JSON_SETTINGS that lives inside a JSON_SETTINGS.
JSON_SETTINGS * m_parent
A pointer to the parent object to load and store from.
A collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:45
void SetViaDiameter(int aDia)
Definition: netclass.h:135
void SetViaDrill(int aSize)
Definition: netclass.h:143
bool HasLineStyle() const
Definition: netclass.h:233
void SetDelayProfileParent(NETCLASS *aParent)
Definition: netclass.h:247
int GetViaDiameter() const
Definition: netclass.h:133
int GetViaDrill() const
Definition: netclass.h:141
void SetWireWidthParent(NETCLASS *parent)
Definition: netclass.h:208
static const char Default[]
the name of the default NETCLASS
Definition: netclass.h:47
void SetuViaDrillParent(NETCLASS *parent)
Definition: netclass.h:161
bool HasDelayProfile() const
Definition: netclass.h:244
bool HasBusWidth() const
Definition: netclass.h:211
bool HasuViaDrill() const
Definition: netclass.h:156
void SetDiffPairWidthParent(NETCLASS *parent)
Definition: netclass.h:169
void SetuViaDiameter(int aSize)
Definition: netclass.h:151
void SetDiffPairWidth(int aSize)
Definition: netclass.h:167
int HasViaDrill() const
Definition: netclass.h:140
int GetDiffPairViaGap() const
Definition: netclass.h:181
void SetViaDrillParent(NETCLASS *parent)
Definition: netclass.h:145
void SetDiffPairGapParent(NETCLASS *parent)
Definition: netclass.h:177
int GetDiffPairGap() const
Definition: netclass.h:173
int GetuViaDrill() const
Definition: netclass.h:157
bool HasViaDiameter() const
Definition: netclass.h:132
int GetLineStyle() const
Definition: netclass.h:234
bool HasDiffPairWidth() const
Definition: netclass.h:164
bool HasuViaDiameter() const
Definition: netclass.h:148
void SetTrackWidthParent(NETCLASS *parent)
Definition: netclass.h:129
int GetuViaDiameter() const
Definition: netclass.h:149
bool HasTrackWidth() const
Definition: netclass.h:124
void SetViaDiameterParent(NETCLASS *parent)
Definition: netclass.h:137
int GetDiffPairWidth() const
Definition: netclass.h:165
void SetuViaDrill(int aSize)
Definition: netclass.h:159
void SetDelayProfile(const wxString &aDelayProfile)
Definition: netclass.h:245
int GetWireWidth() const
Definition: netclass.h:204
void SetDiffPairGap(int aSize)
Definition: netclass.h:175
void SetBusWidthParent(NETCLASS *parent)
Definition: netclass.h:216
void SetClearance(int aClearance)
Definition: netclass.h:119
COLOR4D GetPcbColor(bool aIsForSave=false) const
Definition: netclass.h:189
bool HasDiffPairGap() const
Definition: netclass.h:172
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition: netclass.h:219
void SetBusWidth(int aWidth)
Definition: netclass.h:214
wxString GetDelayProfile() const
Definition: netclass.h:246
void SetClearanceParent(NETCLASS *parent)
Definition: netclass.h:121
int GetTrackWidth() const
Definition: netclass.h:125
void SetWireWidth(int aWidth)
Definition: netclass.h:206
bool HasWireWidth() const
Definition: netclass.h:203
int GetClearance() const
Definition: netclass.h:117
void SetuViaDiameterParent(NETCLASS *parent)
Definition: netclass.h:153
void SetTrackWidth(int aWidth)
Definition: netclass.h:127
bool HasDiffPairViaGap() const
Definition: netclass.h:180
int GetBusWidth() const
Definition: netclass.h:212
bool HasClearance() const
Definition: netclass.h:116
NET_SETTINGS stores various net-related settings in a project context.
Definition: net_settings.h:39
void ClearAllCaches()
Clears the effective netclass cache for all nets.
std::map< wxString, std::shared_ptr< NETCLASS > > m_compositeNetClasses
Map of netclass names to netclass definitions for.
Definition: net_settings.h:223
bool addMissingDefaults(NETCLASS *nc) const
Adds any missing fields to the given netclass from the default netclass.
void ClearNetColorAssignments()
Clears all net name to color assignments Calling user is responsible for resetting the effective netc...
bool operator==(const NET_SETTINGS &aOther) const
void ClearCacheForNet(const wxString &netName)
Clears effective netclass cache for the given net.
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const wxString &aNetName)
Fetches the effective (may be aggregate) netclass for the given net name.
bool HasEffectiveNetClass(const wxString &aNetName) const
Determines if an effective netclass for the given net name has been cached.
void ClearNetclassLabelAssignments()
Clears all net name to netclasses assignments Calling user is responsible for resetting the effective...
void ClearNetclassLabelAssignment(const wxString &netName)
Clears a specific net name to netclass assignment Calling user is responsible for resetting the effec...
void ClearNetclassPatternAssignments()
Clears all netclass pattern assignments.
std::map< wxString, KIGFX::COLOR4D > m_netColorAssignments
A map of fully-qualified net names to colors used in the board context.
Definition: net_settings.h:242
void SetNetclasses(const std::map< wxString, std::shared_ptr< NETCLASS > > &netclasses)
Sets all netclass Calling this method will reset the effective netclass calculation caches.
bool HasNetclassLabelAssignment(const wxString &netName) const
Determines if a given net name has netclasses assigned.
void SetNetclassLabelAssignment(const wxString &netName, const std::set< wxString > &netclasses)
Sets a net name to netclasses assignment Calling user is responsible for resetting the effective netc...
std::shared_ptr< NETCLASS > m_defaultNetClass
The default netclass.
Definition: net_settings.h:209
virtual ~NET_SETTINGS()
static bool ParseBusGroup(const wxString &aGroup, wxString *name, std::vector< wxString > *aMemberList)
Parse a bus group label into the name and a list of components.
void ClearNetclasses()
Clears all netclasses Calling this method will reset the effective netclass calculation caches.
std::map< wxString, std::shared_ptr< NETCLASS > > m_impicitNetClasses
Map of netclass names to netclass definitions for implicit netclasses.
Definition: net_settings.h:231
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetCompositeNetclasses() const
Gets all composite (multiple assignment / missing defaults) netclasses.
std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > m_netClassPatternAssignments
List of net class pattern assignments.
Definition: net_settings.h:219
bool migrateSchema3to4()
bool migrateSchema0to1()
std::map< wxString, std::shared_ptr< NETCLASS > > m_effectiveNetclassCache
Cache of nets to pattern-matched netclasses.
Definition: net_settings.h:234
void SetNetclassPatternAssignments(std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > &&netclassPatterns)
Sets all netclass pattern assignments Calling user is responsible for resetting the effective netclas...
void SetNetclassPatternAssignment(const wxString &pattern, const wxString &netclass)
Sets a netclass pattern assignment Calling this method will reset the effective netclass calculation ...
bool migrateSchema2to3()
std::map< wxString, std::shared_ptr< NETCLASS > > m_netClasses
Map of netclass names to netclass definitions.
Definition: net_settings.h:212
const std::map< wxString, std::set< wxString > > & GetNetclassLabelAssignments() const
Gets all current net name to netclasses assignments.
const std::map< wxString, std::shared_ptr< NETCLASS > > & GetNetclasses() const
Gets all netclasses.
std::shared_ptr< NETCLASS > GetDefaultNetclass()
Gets the default netclass for the project.
static bool ParseBusVector(const wxString &aBus, wxString *aName, std::vector< wxString > *aMemberList)
Parse a bus vector (e.g.
const std::map< wxString, KIGFX::COLOR4D > & GetNetColorAssignments() const
Gets all net name to color assignments.
bool migrateSchema1to2()
std::vector< std::pair< std::unique_ptr< EDA_COMBINED_MATCHER >, wxString > > & GetNetclassPatternAssignments()
Gets the netclass pattern assignments.
void RecomputeEffectiveNetclasses()
Recomputes the internal values of all aggregate effective netclasses Called when a value of a user-de...
std::shared_ptr< NETCLASS > GetCachedEffectiveNetClass(const wxString &aNetName) const
Returns an already cached effective netclass for the given net name.
bool migrateSchema4to5()
std::map< wxString, std::set< wxString > > m_netClassLabelAssignments
Map of net names to resolved netclasses.
Definition: net_settings.h:215
void SetNetclass(const wxString &netclassName, std::shared_ptr< NETCLASS > &netclass)
Sets the given netclass Calling user is responsible for resetting the effective netclass calculation ...
void makeEffectiveNetclass(std::shared_ptr< NETCLASS > &effectiveNetclass, std::vector< NETCLASS * > &netclasses) const
Creates an effective aggregate netclass from the given constituent netclasses.
void AppendNetclassLabelAssignment(const wxString &netName, const std::set< wxString > &netclasses)
Apppends to a net name to netclasses assignment Calling user is responsible for resetting the effecti...
void SetDefaultNetclass(std::shared_ptr< NETCLASS > netclass)
Sets the default netclass for the project Calling user is responsible for resetting the effective net...
std::shared_ptr< NETCLASS > GetNetClassByName(const wxString &aNetName) const
Get a NETCLASS object from a given Netclass name string.
void SetNetColorAssignment(const wxString &netName, const KIGFX::COLOR4D &color)
Sets a net to color assignment Calling user is responsible for resetting the effective netclass calcu...
NET_SETTINGS(JSON_SETTINGS *aParent, const std::string &aPath)
bool HasNetclass(const wxString &netclassName) const
Determines if the given netclass exists.
Like a normal param, but with custom getter and setter functions.
Definition: parameters.h:295
bool isDigit(char cc)
Definition: dsnlexer.cpp:468
#define _(s)
@ CTX_NETCLASS
nlohmann::json json
Definition: gerbview.cpp:50
static bool isSuperSubOverbar(wxChar c)
const int netSettingsSchemaVersion
static std::optional< int > getInSchUnits(const nlohmann::json &aObj, const std::string &aKey, std::optional< int > aDefault=std::optional< int >())
static std::optional< int > getInPcbUnits(const nlohmann::json &aObj, const std::string &aKey, std::optional< int > aDefault=std::optional< int >())
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_NETNAME
Definition: string_utils.h:53
constexpr double IUTomm(int iu) const
Definition: base_units.h:90
constexpr int IUToMils(int iu) const
Definition: base_units.h:103
constexpr int MilsToIU(int mils) const
Definition: base_units.h:97
constexpr int mmToIU(double mm) const
Definition: base_units.h:92
VECTOR2I end