KiCad PCB EDA Suite
Loading...
Searching...
No Matches
drc_rule_editor_utils.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) 2024 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 * or you may search the http://www.gnu.org website for the version 2 license,
20 * or you may write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 */
23
26#include <kiplatform/io.h>
27#include <reporter.h>
29#include <drc/drc_rule_parser.h>
30#include <drc_rules_lexer.h>
31#include <drc/drc_rule.h>
43#include <board.h>
44#include <wx/ffile.h>
45#include <wx/regex.h>
46#include <unordered_map>
47
48using CODE_MAP = std::unordered_map<DRC_RULE_EDITOR_CONSTRAINT_NAME, const char*>;
49using REVERSE_CODE_MAP = std::unordered_map<wxString, DRC_RULE_EDITOR_CONSTRAINT_NAME, wxStringHash, wxStringEqual>;
50
51static const CODE_MAP sCodeMap = { { MINIMUM_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_clearance ) },
52 { CREEPAGE_DISTANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_creepage ) },
53 { MINIMUM_CONNECTION_WIDTH, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_connection_width ) },
54 { COPPER_TO_HOLE_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_clearance ) },
55 { MINIMUM_THERMAL_RELIEF_SPOKE_COUNT, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_min_resolved_spokes ) },
56 { MINIMUM_ANNULAR_WIDTH, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_annular_width ) },
57 { COPPER_TO_EDGE_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_edge_clearance ) },
58 { COURTYARD_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_courtyard_clearance ) },
59 { PHYSICAL_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_physical_clearance ) },
60 { MINIMUM_DRILL_SIZE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_size ) },
61 { HOLE_SIZE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_size ) },
62 { HOLE_TO_HOLE_DISTANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_to_hole ) },
63 { MINIMUM_VIA_DIAMETER, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_via_diameter ) },
64 { VIA_STYLE, "via_style" },
65 { MINIMUM_TEXT_HEIGHT_AND_THICKNESS, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_text_height ) },
66 { SILK_TO_SILK_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_silk_clearance ) },
67 { SILK_TO_SOLDERMASK_CLEARANCE, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_silk_clearance ) },
68 { MINIMUM_SOLDERMASK_SLIVER, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_mask_sliver ) },
69 { SOLDERMASK_EXPANSION, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_mask_expansion ) },
70 { SOLDERPASTE_EXPANSION, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_paste_abs_margin ) },
71 { MATCHED_LENGTH_DIFF_PAIR, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_length ) },
72 { ROUTING_DIFF_PAIR, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_diff_pair_gap ) },
73 { ROUTING_WIDTH, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_track_width ) },
74 { MAXIMUM_VIA_COUNT, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_via_count ) },
75 { ABSOLUTE_LENGTH, DRC_RULES_LEXER::TokenName( DRCRULE_T::T_length ) },
76 { PERMITTED_LAYERS, "permitted_layers" },
77 { ALLOWED_ORIENTATION, "allowed_orientation" },
78 { VIAS_UNDER_SMD, "disallow_via" } };
79
81{
83 for( const auto& [type, code] : sCodeMap )
84 map.emplace( wxString::FromUTF8( code ), type );
85 return map;
86}();
87
88static std::vector<DRC_RULE_EDITOR_UTILS::RuleConverter>& GetRuleConverters()
89{
90 static std::vector<DRC_RULE_EDITOR_UTILS::RuleConverter> converters;
91 return converters;
92}
93
95{
96 GetRuleConverters().insert( GetRuleConverters().begin(), aConverter );
97}
98
100{
101 switch( aType )
102 {
103 case CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_clearance );
104 case EDGE_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_edge_clearance );
105 case HOLE_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_clearance );
106 case HOLE_TO_HOLE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_to_hole );
107 case HOLE_SIZE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_hole_size );
108 case TRACK_WIDTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_track_width );
109 case ANNULAR_WIDTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_annular_width );
110 case VIA_DIAMETER_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_via_diameter );
111 case DISALLOW_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_disallow );
112 case COURTYARD_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_courtyard_clearance );
113 case SILK_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_silk_clearance );
114 case TEXT_HEIGHT_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_text_height );
115 case TEXT_THICKNESS_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_text_thickness );
116 case TRACK_ANGLE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_track_angle );
117 case TRACK_SEGMENT_LENGTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_track_segment_length );
118 case CONNECTION_WIDTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_connection_width );
119 case VIA_DANGLING_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_via_dangling );
120 case ZONE_CONNECTION_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_zone_connection );
121 case THERMAL_RELIEF_GAP_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_thermal_relief_gap );
122 case THERMAL_SPOKE_WIDTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_thermal_spoke_width );
123 case MIN_RESOLVED_SPOKES_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_min_resolved_spokes );
124 case SOLDER_MASK_EXPANSION_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_mask_expansion );
125 case SOLDER_PASTE_ABS_MARGIN_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_paste_abs_margin );
126 case SOLDER_PASTE_REL_MARGIN_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_paste_rel_margin );
127 case LENGTH_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_length );
128 case SKEW_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_skew );
129 case VIA_COUNT_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_via_count );
130 case DIFF_PAIR_GAP_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_diff_pair_gap );
131 case MAX_UNCOUPLED_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_diff_pair_uncoupled );
132 case PHYSICAL_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_physical_clearance );
133 case PHYSICAL_HOLE_CLEARANCE_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_physical_hole_clearance );
134 case BRIDGED_MASK_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_bridged_mask );
135 case SOLDER_MASK_SLIVER_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_solder_mask_sliver );
136 case ASSERTION_CONSTRAINT: return DRC_RULES_LEXER::TokenName( DRCRULE_T::T_assertion );
137 default: return "";
138 }
139}
140
142{
143 static bool initialized = false;
144 if( initialized )
145 return;
146 initialized = true;
147
148 // Generic Converter
150 []( const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
151 {
152 if( aRule->m_Constraints.empty() ) return nullptr;
153
154 const auto& constraint = aRule->m_Constraints[0];
155 wxString code = GetConstraintCodeFromType( constraint.m_Type );
156
157 if( code.IsEmpty() ) return nullptr;
158
159 if( sCodeReverse.count( code ) )
160 {
161 auto type = sCodeReverse.at( code );
162
164 {
165 double val = constraint.GetValue().Min() / 1000000.0;
167 data->SetRuleName( aRule->m_Name );
168 data->SetNumericInputValue( val );
169 data->SetConstraintCode( code );
170 return data;
171 }
173 {
174 auto data = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0, true, aRule->m_Name );
175 data->SetConstraintCode( code );
176 return data;
177 }
178 else if( code == "track_width" )
179 {
180 double minW = constraint.GetValue().Min() / 1000000.0;
181 double optW = constraint.GetValue().Opt() / 1000000.0;
182 double maxW = constraint.GetValue().Max() / 1000000.0;
183
184 double tol = 0;
185 if( optW > 0 )
186 tol = std::max( optW - minW, maxW - optW );
187
188 auto data =
189 std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( 0, 0, aRule->m_Name, optW, tol );
190 data->SetConstraintCode( code );
191 return data;
192 }
193 }
194 return nullptr;
195 } );
196
197 // Via Style Converter
199 []( const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
200 {
201 auto diaConstraint = aRule->FindConstraint( VIA_DIAMETER_CONSTRAINT );
202 auto holeConstraint = aRule->FindConstraint( HOLE_SIZE_CONSTRAINT );
203
204 if( diaConstraint && holeConstraint )
205 {
206 double minDia = diaConstraint->GetValue().Min() / 1000000.0;
207 double maxDia = diaConstraint->GetValue().Max() / 1000000.0;
208
209 double minDrill = holeConstraint->GetValue().Min() / 1000000.0;
210 double maxDrill = holeConstraint->GetValue().Max() / 1000000.0;
211
213
214 if( aRule->m_Condition )
215 {
216 wxString expr = aRule->m_Condition->GetExpression();
217
218 if( expr.Contains( wxS( "'Micro'" ) ) )
219 viaType = VIA_STYLE_TYPE::MICRO;
220 else if( expr.Contains( wxS( "'Through'" ) ) )
221 viaType = VIA_STYLE_TYPE::THROUGH;
222 else if( expr.Contains( wxS( "'Blind'" ) ) )
223 viaType = VIA_STYLE_TYPE::BLIND;
224 else if( expr.Contains( wxS( "'Buried'" ) ) )
225 viaType = VIA_STYLE_TYPE::BURIED;
226 }
227
228 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name, minDia, maxDia,
229 minDrill, maxDrill, viaType );
230 data->SetConstraintCode( "via_style" );
231 return data;
232 }
233 return nullptr;
234 } );
235}
236
237
239{
240 auto it = sCodeMap.find( aConstraintType );
241 if( it != sCodeMap.end() )
242 return wxString::FromUTF8( it->second );
243
244 return wxString();
245}
246
247
248std::optional<DRC_RULE_EDITOR_CONSTRAINT_NAME> DRC_RULE_EDITOR_UTILS::GetConstraintTypeFromCode( const wxString& aCode )
249{
250 auto it = sCodeReverse.find( aCode );
251 if( it != sCodeReverse.end() )
252 return it->second;
253
254 return std::nullopt;
255}
256
257
262
263
265{
266 if( !aData )
267 return false;
268
269 auto type = GetConstraintTypeFromCode( aCode );
270 if( type )
271 {
272 aData->SetConstraintCode( GetConstraintCode( *type ) );
273 return true;
274 }
275
276 aData->SetConstraintCode( aCode );
277 return false;
278}
279
280
282{
283 switch( aConstraintType )
284 {
285 default: return false;
286 }
287}
288
289
291{
292 switch( aConstraintType )
293 {
299 case HOLE_SIZE:
314 return true;
315 default:
316 return false;
317 }
318}
319
320
321bool DRC_RULE_EDITOR_UTILS::ValidateNumericCtrl( wxTextCtrl* aTextCtrl, const wxString& aLabel, bool aCanBeZero,
322 int* aErrorCount, wxString* aValidationMessage )
323{
324 VALIDATOR_NUMERIC_CTRL validator( aCanBeZero );
325 aTextCtrl->SetValidator( validator );
326
327 if( !aTextCtrl->Validate() )
328 {
329 VALIDATOR_NUMERIC_CTRL* v = static_cast<VALIDATOR_NUMERIC_CTRL*>( aTextCtrl->GetValidator() );
330
331 switch( v->GetValidationState() )
332 {
334 {
335 ( *aErrorCount )++;
336 *aValidationMessage +=
338 wxString::Format( _( "%s should not be empty." ), aLabel ) );
339 return false;
340 }
342 {
343 ( *aErrorCount )++;
344 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
345 *aErrorCount, wxString::Format( _( "The value of %s must be a valid number." ), aLabel ) );
346 return false;
347 }
349 {
350 ( *aErrorCount )++;
351 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
352 *aErrorCount, wxString::Format( _( "The value of %s must be greater than 0." ), aLabel ) );
353 return false;
354 }
355 default: break;
356 }
357 }
358
359 return true;
360}
361
362
363bool DRC_RULE_EDITOR_UTILS::ValidateIntegerCtrl( wxTextCtrl* aTextCtrl, const wxString& aLabel, bool aCanBeZero,
364 int* aErrorCount, wxString* aValidationMessage )
365{
366 VALIDATOR_NUMERIC_CTRL validator( aCanBeZero, true );
367 aTextCtrl->SetValidator( validator );
368
369 if( !aTextCtrl->Validate() )
370 {
371 VALIDATOR_NUMERIC_CTRL* v = static_cast<VALIDATOR_NUMERIC_CTRL*>( aTextCtrl->GetValidator() );
372
373 switch( v->GetValidationState() )
374 {
376 {
377 ( *aErrorCount )++;
378 *aValidationMessage +=
380 wxString::Format( _( "%s should not be empty." ), aLabel ) );
381 return false;
382 }
384 {
385 ( *aErrorCount )++;
386 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
387 *aErrorCount, wxString::Format( _( "The value of %s must be a valid integer." ), aLabel ) );
388 return false;
389 }
391 {
392 ( *aErrorCount )++;
393 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
394 *aErrorCount, wxString::Format( _( "The value of %s must be greater than 0." ), aLabel ) );
395 return false;
396 }
397 default: break;
398 }
399 }
400
401 return true;
402}
403
404
405bool DRC_RULE_EDITOR_UTILS::ValidateComboCtrl( wxComboBox* aComboBox, const wxString& aLabel, int* aErrorCount,
406 wxString* aValidationMessage )
407{
408 VALIDATOR_COMBO_CTRL cmbCtrlValidator;
409 aComboBox->SetValidator( cmbCtrlValidator );
410
411 if( !aComboBox->Validate() )
412 {
413 VALIDATOR_COMBO_CTRL* v = static_cast<VALIDATOR_COMBO_CTRL*>( aComboBox->GetValidator() );
414
415 switch( v->GetValidationState() )
416 {
418 {
419 ( *aErrorCount )++;
420 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage( *aErrorCount,
421 wxString::Format( _( "Please choose %s." ), aLabel ) );
422 return false;
423 }
424 default: break;
425 }
426 }
427
428 return true;
429}
430
431
432bool DRC_RULE_EDITOR_UTILS::ValidateMinMaxCtrl( wxTextCtrl* aMinTextCtrl, wxTextCtrl* aMaxTextCtrl,
433 const wxString& aMinLabel, const wxString& aMaxLabel,
434 int* aErrorCount, wxString* aValidationMessage )
435{
436 aMinTextCtrl->SetName( "min" );
437 aMaxTextCtrl->SetName( "max" );
438
439 aMinTextCtrl->SetValidator( VALIDATE_MIN_MAX_CTRL( aMinTextCtrl, aMaxTextCtrl ) );
440
441 if( !aMinTextCtrl->Validate() )
442 {
443 VALIDATE_MIN_MAX_CTRL* v = static_cast<VALIDATE_MIN_MAX_CTRL*>( aMinTextCtrl->GetValidator() );
444
445 switch( v->GetValidationState() )
446 {
448 {
449 ( *aErrorCount )++;
450 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
451 *aErrorCount, wxString::Format( _( "%s value cannot be greater than %s value." ),
452 aMinLabel, aMaxLabel ) );
453 return false;
454 }
455 default: break;
456 }
457 }
458
459 aMinTextCtrl->SetName( "text" );
460 aMaxTextCtrl->SetName( "text" );
461
462 return true;
463}
464
465
466bool DRC_RULE_EDITOR_UTILS::ValidateMinPreferredMaxCtrl( wxTextCtrl* aMinTextCtrl, wxTextCtrl* aPreferredTextCtrl,
467 wxTextCtrl* aMaxTextCtrl, const wxString& aMinLabel,
468 const wxString& aPreferredLabel, const wxString& aMaxLabel,
469 int* aErrorCount, wxString* aValidationMessage )
470{
471 aMinTextCtrl->SetName( "min" );
472 aPreferredTextCtrl->SetName( "preferred" );
473 aMaxTextCtrl->SetName( "max" );
474
475 aMinTextCtrl->SetValidator( VALIDATE_MIN_PREFERRED_MAX_CTRL( aMinTextCtrl, aPreferredTextCtrl, aMaxTextCtrl ) );
476
477 if( !aMinTextCtrl->Validate() )
478 {
480 static_cast<VALIDATE_MIN_PREFERRED_MAX_CTRL*>( aMinTextCtrl->GetValidator() );
481
482 switch( v->GetValidationState() )
483 {
485 {
486 ( *aErrorCount )++;
487 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
488 *aErrorCount, wxString::Format( _( "%s value cannot be greater than %s value." ),
489 aMinLabel, aPreferredLabel ) );
490 return false;
491 }
493 {
494 ( *aErrorCount )++;
495 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
496 *aErrorCount, wxString::Format( _( "%s value cannot be greater than %s value." ),
497 aPreferredLabel, aMaxLabel ) );
498 return false;
499 }
501 {
502 ( *aErrorCount )++;
503 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
504 *aErrorCount, wxString::Format( _( "%s value cannot be greater than %s value." ),
505 aMinLabel, aMaxLabel ) );
506 return false;
507 }
508 default: break;
509 }
510 }
511
512 aMinTextCtrl->SetName( "text" );
513 aPreferredTextCtrl->SetName( "text" );
514 aMaxTextCtrl->SetName( "text" );
515
516 return true;
517}
518
519
520bool DRC_RULE_EDITOR_UTILS::ValidateCheckBoxCtrls( const std::vector<wxCheckBox*>& aCheckboxes, const wxString& aLabel,
521 int* aErrorCount, wxString* aValidationMessage )
522{
523 VALIDATE_CHECKBOX_LIST validator( aCheckboxes );
524
525 aCheckboxes[0]->SetValidator( validator );
526
527 if( !aCheckboxes[0]->Validate() )
528 {
529 VALIDATE_CHECKBOX_LIST* v = static_cast<VALIDATE_CHECKBOX_LIST*>( aCheckboxes[0]->GetValidator() );
530
531 switch( v->GetValidationState() )
532 {
534 {
535 ( *aErrorCount )++;
536 *aValidationMessage += DRC_RULE_EDITOR_UTILS::FormatErrorMessage(
537 *aErrorCount, wxString::Format( _( "Please select at least one option from %s list." ), aLabel ));
538 return false;
539 }
540 default: break;
541 }
542 }
543
544 return true;
545}
546
547
548wxString DRC_RULE_EDITOR_UTILS::FormatErrorMessage( int aErrorCount, const wxString& aErrorMessage )
549{
550 return wxString::Format( wxS( "%d. %s\n" ), aErrorCount, aErrorMessage );
551}
552
553
554// ==================== Pure Validators (No GUI Dependencies) ====================
555
556bool DRC_RULE_EDITOR_UTILS::ValidateNumericValue( double aValue, bool aCanBeZero, const wxString& aLabel,
557 VALIDATION_RESULT* aResult )
558{
559 if( !aCanBeZero && aValue <= 0.0 )
560 {
561 aResult->AddError( wxString::Format( _( "The value of %s must be greater than 0." ), aLabel ) );
562 return false;
563 }
564
565 return true;
566}
567
568
569bool DRC_RULE_EDITOR_UTILS::ValidateNumericString( const wxString& aValueStr, bool aCanBeZero,
570 bool aIntegerOnly, const wxString& aLabel,
571 VALIDATION_RESULT* aResult )
572{
573 if( aValueStr.IsEmpty() )
574 {
575 aResult->AddError( wxString::Format( _( "%s should not be empty." ), aLabel ) );
576 return false;
577 }
578
579 try
580 {
581 if( aIntegerOnly )
582 {
583 std::string stdStr = aValueStr.ToStdString();
584 size_t pos;
585 long intVal = std::stol( stdStr, &pos );
586
587 if( pos != stdStr.length() )
588 {
589 aResult->AddError( wxString::Format( _( "The value of %s must be a valid integer." ), aLabel ) );
590 return false;
591 }
592
593 if( !aCanBeZero && intVal <= 0 )
594 {
595 aResult->AddError( wxString::Format( _( "The value of %s must be greater than 0." ), aLabel ) );
596 return false;
597 }
598 }
599 else
600 {
601 std::string stdStr = aValueStr.ToStdString();
602 size_t pos;
603 double floatVal = std::stod( stdStr, &pos );
604
605 if( pos != stdStr.length() )
606 {
607 aResult->AddError( wxString::Format( _( "The value of %s must be a valid number." ), aLabel ) );
608 return false;
609 }
610
611 if( !aCanBeZero && floatVal <= 0.0 )
612 {
613 aResult->AddError( wxString::Format( _( "The value of %s must be greater than 0." ), aLabel ) );
614 return false;
615 }
616 }
617 }
618 catch( const std::exception& )
619 {
620 if( aIntegerOnly )
621 aResult->AddError( wxString::Format( _( "The value of %s must be a valid integer." ), aLabel ) );
622 else
623 aResult->AddError( wxString::Format( _( "The value of %s must be a valid number." ), aLabel ) );
624
625 return false;
626 }
627
628 return true;
629}
630
631
632bool DRC_RULE_EDITOR_UTILS::ValidateMinMax( double aMin, double aMax, const wxString& aMinLabel,
633 const wxString& aMaxLabel, VALIDATION_RESULT* aResult )
634{
635 if( aMin > aMax )
636 {
637 aResult->AddError( wxString::Format( _( "%s value cannot be greater than %s value." ), aMinLabel, aMaxLabel ));
638 return false;
639 }
640
641 return true;
642}
643
644
645bool DRC_RULE_EDITOR_UTILS::ValidateMinPreferredMax( double aMin, double aPreferred, double aMax,
646 const wxString& aMinLabel,
647 const wxString& aPrefLabel,
648 const wxString& aMaxLabel,
649 VALIDATION_RESULT* aResult )
650{
651 bool valid = true;
652
653 if( aMin > aPreferred )
654 {
655 aResult->AddError( wxString::Format( _( "%s value cannot be greater than %s value." ), aMinLabel, aPrefLabel ));
656 valid = false;
657 }
658
659 if( aPreferred > aMax )
660 {
661 aResult->AddError( wxString::Format( _( "%s value cannot be greater than %s value." ), aPrefLabel, aMaxLabel ));
662 valid = false;
663 }
664
665 if( aMin > aMax )
666 {
667 aResult->AddError( wxString::Format( _( "%s value cannot be greater than %s value." ), aMinLabel, aMaxLabel ));
668 valid = false;
669 }
670
671 return valid;
672}
673
674
675bool DRC_RULE_EDITOR_UTILS::ValidateAtLeastOneSelected( const std::vector<bool>& aSelected,
676 const wxString& aLabel,
677 VALIDATION_RESULT* aResult )
678{
679 for( bool selected : aSelected )
680 {
681 if( selected )
682 return true;
683 }
684
685 aResult->AddError( wxString::Format( _( "Please select at least one option from %s list." ), aLabel ) );
686 return false;
687}
688
689
690bool DRC_RULE_EDITOR_UTILS::ValidateSelection( int aSelectionIndex, const wxString& aLabel,
691 VALIDATION_RESULT* aResult )
692{
693 if( aSelectionIndex < 0 )
694 {
695 aResult->AddError( wxString::Format( _( "Please choose %s." ), aLabel ) );
696 return false;
697 }
698
699 return true;
700}
701
702
703std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> DRC_RULE_EDITOR_UTILS::ParseRules( const wxString& aRules )
704{
706
707 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
708 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
709
710 wxString rulesText = aRules;
711 if( !rulesText.Contains( "(version" ) )
712 rulesText.Prepend( "(version 1)\n" );
713
714 try
715 {
716 DRC_RULES_PARSER parser( rulesText, "Rule Editor Source" );
717 parser.Parse( parsedRules, nullptr );
718 }
719 catch( const IO_ERROR& )
720 {
721 }
722
723 for( const auto& rule : parsedRules )
724 {
725 std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> data;
726
727 for( const auto& converter : GetRuleConverters() )
728 {
729 data = converter( rule );
730 if( data )
731 break;
732 }
733
734 if( !data )
735 {
736 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, rule->m_Name );
737 customData->SetRuleText( wxString::Format( "(rule \"%s\" ...)", rule->m_Name ) );
738 data = customData;
739 }
740
741 if( rule->m_Condition )
742 data->SetRuleCondition( rule->m_Condition->GetExpression() );
743
744 rules.push_back( data );
745 }
746
747 return rules;
748}
749
750bool DRC_RULE_EDITOR_UTILS::SaveRules( const wxString& aFilename,
751 const std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>>& aRules,
752 const BOARD* aBoard )
753{
754 wxString content = wxT( "(version 1)\n" );
755
756 for( const auto& data : aRules )
757 {
758 if( !data )
759 continue;
760
762 ctx.ruleName = data->GetRuleName();
763 ctx.comment = data->GetComment();
764 ctx.conditionExpression = data->GetRuleCondition();
765 ctx.constraintCode = data->GetConstraintCode();
766
767 std::vector<PCB_LAYER_ID> layers = data->GetLayers();
768
769 if( !layers.empty() && aBoard )
770 {
771 wxString layerStr = "(layer";
772
773 for( PCB_LAYER_ID layer : layers )
774 layerStr += " \"" + aBoard->GetLayerName( layer ) + "\"";
775
776 layerStr += ")";
777 ctx.layerClause = layerStr;
778 }
779
780 content += data->GenerateRule( ctx ) + wxT( "\n" );
781 }
782
783 std::string utf8 = std::string( content.mb_str( wxConvUTF8 ) );
784 return KIPLATFORM::IO::AtomicWriteFile( aFilename, utf8.data(), utf8.size() );
785}
786
787
788// ==================== Layer Filtering ====================
789
791 DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType )
792{
793 switch( aConstraintType )
794 {
795 // COPPER_ONLY: Constraints that only apply to copper layers
800 case VIA_STYLE:
804 case ROUTING_WIDTH:
808 case ABSOLUTE_LENGTH:
810
811 // SILKSCREEN_ONLY: Constraints that only apply to silkscreen layers
814
815 // SOLDERMASK_ONLY: Constraints that only apply to soldermask layers
819
820 // SOLDERPASTE_ONLY: Constraints that only apply to solderpaste layers
823
824 // TOP_BOTTOM_ANY: Constraints with simplified top/bottom/any selection
827 case VIAS_UNDER_SMD:
830
831 // GENERAL_ANY_LAYER: Constraints that can apply to any layer type
833 case HOLE_SIZE:
838
839 // NO_LAYER_SELECTOR: Constraints where layer selection doesn't apply
841 case PERMITTED_LAYERS:
842 case CUSTOM_RULE:
844
845 default:
847 }
848}
849
850
852 bool aIsTop )
853{
854 switch( aConstraintType )
855 {
857 return wxString::Format( wxS( "(layer \"%s\")" ),
858 aIsTop ? wxS( "F.CrtYd" ) : wxS( "B.CrtYd" ) );
859
861 // Generates a condition to match silk on one side with mask on the same side
862 return wxString::Format( wxS( "(condition \"A.Layer == '%s' && B.Layer == '%s'\")" ),
863 aIsTop ? wxS( "F.SilkS" ) : wxS( "B.SilkS" ),
864 aIsTop ? wxS( "F.Mask" ) : wxS( "B.Mask" ) );
865
866 case VIAS_UNDER_SMD:
868 return wxString::Format( wxS( "(layer \"%s\")" ), aIsTop ? wxS( "F.Cu" ) : wxS( "B.Cu" ) );
869
870 default:
871 return wxEmptyString;
872 }
873}
874
875
876std::shared_ptr<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>
878{
879 switch( aType )
880 {
881 case COPPER_TO_EDGE_CLEARANCE: return std::make_shared<DRC_RE_COPPER_TO_EDGE_CLEARANCE_CONSTRAINT_DATA>();
882 case COPPER_TO_HOLE_CLEARANCE: return std::make_shared<DRC_RE_COPPER_TO_HOLE_CLEARANCE_CONSTRAINT_DATA>();
883 case COURTYARD_CLEARANCE: return std::make_shared<DRC_RE_COURTYARD_CLEARANCE_CONSTRAINT_DATA>();
884 case PHYSICAL_CLEARANCE: return std::make_shared<DRC_RE_PHYSICAL_CLEARANCE_CONSTRAINT_DATA>();
885 case CREEPAGE_DISTANCE: return std::make_shared<DRC_RE_CREEPAGE_DISTANCE_CONSTRAINT_DATA>();
886 case HOLE_SIZE: return std::make_shared<DRC_RE_HOLE_SIZE_CONSTRAINT_DATA>();
887 case HOLE_TO_HOLE_DISTANCE: return std::make_shared<DRC_RE_HOLE_TO_HOLE_DISTANCE_CONSTRAINT_DATA>();
888 case MAXIMUM_VIA_COUNT: return std::make_shared<DRC_RE_MAXIMUM_VIA_COUNT_CONSTRAINT_DATA>();
889 case MINIMUM_ANNULAR_WIDTH: return std::make_shared<DRC_RE_MINIMUM_ANNULAR_WIDTH_CONSTRAINT_DATA>();
890 case MINIMUM_CLEARANCE: return std::make_shared<DRC_RE_MINIMUM_CLEARANCE_CONSTRAINT_DATA>();
891 case MINIMUM_CONNECTION_WIDTH: return std::make_shared<DRC_RE_MINIMUM_CONNECTION_WIDTH_CONSTRAINT_DATA>();
892 case MINIMUM_SOLDERMASK_SLIVER: return std::make_shared<DRC_RE_MINIMUM_SOLDERMASK_SLIVER_CONSTRAINT_DATA>();
893 case MINIMUM_THERMAL_RELIEF_SPOKE_COUNT: return std::make_shared<DRC_RE_MINIMUM_THERMAL_SPOKE_COUNT_CONSTRAINT_DATA>();
894 case MINIMUM_DRILL_SIZE: return std::make_shared<DRC_RE_MINIMUM_DRILL_SIZE_CONSTRAINT_DATA>();
895 case MINIMUM_VIA_DIAMETER: return std::make_shared<DRC_RE_MINIMUM_VIA_DIAMETER_CONSTRAINT_DATA>();
896 case SILK_TO_SILK_CLEARANCE: return std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>();
897 case SILK_TO_SOLDERMASK_CLEARANCE: return std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>();
898 case SOLDERMASK_EXPANSION: return std::make_shared<DRC_RE_SOLDERMASK_EXPANSION_CONSTRAINT_DATA>();
899 case SOLDERPASTE_EXPANSION: return std::make_shared<DRC_RE_SOLDERPASTE_EXPANSION_CONSTRAINT_DATA>();
900 default: return std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>();
901 }
902}
903
904
905std::shared_ptr<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>
907 const DRC_RE_BASE_CONSTRAINT_DATA& aBase )
908{
909 switch( aType )
910 {
911 case COPPER_TO_EDGE_CLEARANCE: return std::make_shared<DRC_RE_COPPER_TO_EDGE_CLEARANCE_CONSTRAINT_DATA>( aBase );
912 case COPPER_TO_HOLE_CLEARANCE: return std::make_shared<DRC_RE_COPPER_TO_HOLE_CLEARANCE_CONSTRAINT_DATA>( aBase );
913 case COURTYARD_CLEARANCE: return std::make_shared<DRC_RE_COURTYARD_CLEARANCE_CONSTRAINT_DATA>( aBase );
914 case PHYSICAL_CLEARANCE: return std::make_shared<DRC_RE_PHYSICAL_CLEARANCE_CONSTRAINT_DATA>( aBase );
915 case CREEPAGE_DISTANCE: return std::make_shared<DRC_RE_CREEPAGE_DISTANCE_CONSTRAINT_DATA>( aBase );
916 case HOLE_SIZE: return std::make_shared<DRC_RE_HOLE_SIZE_CONSTRAINT_DATA>( aBase );
917 case HOLE_TO_HOLE_DISTANCE: return std::make_shared<DRC_RE_HOLE_TO_HOLE_DISTANCE_CONSTRAINT_DATA>( aBase );
918 case MAXIMUM_VIA_COUNT: return std::make_shared<DRC_RE_MAXIMUM_VIA_COUNT_CONSTRAINT_DATA>( aBase );
919 case MINIMUM_ANNULAR_WIDTH: return std::make_shared<DRC_RE_MINIMUM_ANNULAR_WIDTH_CONSTRAINT_DATA>( aBase );
920 case MINIMUM_CLEARANCE: return std::make_shared<DRC_RE_MINIMUM_CLEARANCE_CONSTRAINT_DATA>( aBase );
921 case MINIMUM_CONNECTION_WIDTH: return std::make_shared<DRC_RE_MINIMUM_CONNECTION_WIDTH_CONSTRAINT_DATA>( aBase );
922 case MINIMUM_SOLDERMASK_SLIVER: return std::make_shared<DRC_RE_MINIMUM_SOLDERMASK_SLIVER_CONSTRAINT_DATA>( aBase );
923 case MINIMUM_THERMAL_RELIEF_SPOKE_COUNT: return std::make_shared<DRC_RE_MINIMUM_THERMAL_SPOKE_COUNT_CONSTRAINT_DATA>( aBase );
924 case MINIMUM_DRILL_SIZE: return std::make_shared<DRC_RE_MINIMUM_DRILL_SIZE_CONSTRAINT_DATA>( aBase );
925 case MINIMUM_VIA_DIAMETER: return std::make_shared<DRC_RE_MINIMUM_VIA_DIAMETER_CONSTRAINT_DATA>( aBase );
926 case SILK_TO_SILK_CLEARANCE: return std::make_shared<DRC_RE_SILK_TO_SILK_CLEARANCE_CONSTRAINT_DATA>( aBase );
927 case SILK_TO_SOLDERMASK_CLEARANCE: return std::make_shared<DRC_RE_SILK_TO_SOLDERMASK_CLEARANCE_CONSTRAINT_DATA>( aBase );
928 case SOLDERMASK_EXPANSION: return std::make_shared<DRC_RE_SOLDERMASK_EXPANSION_CONSTRAINT_DATA>( aBase );
929 case SOLDERPASTE_EXPANSION: return std::make_shared<DRC_RE_SOLDERPASTE_EXPANSION_CONSTRAINT_DATA>( aBase );
930 default: return std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( aBase );
931 }
932}
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:323
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
Definition board.cpp:745
void SetConstraintCode(const wxString &aCode)
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
static bool IsNumericInputType(const DRC_RULE_EDITOR_CONSTRAINT_NAME &aConstraintType)
static wxString ConstraintToKicadDrc(DRC_RULE_EDITOR_CONSTRAINT_NAME aType)
Convert a constraint type into the keyword used in a .kicad_drc file.
static bool ValidateNumericValue(double aValue, bool aCanBeZero, const wxString &aLabel, VALIDATION_RESULT *aResult)
Validates a numeric value.
static bool ValidateAtLeastOneSelected(const std::vector< bool > &aSelected, const wxString &aLabel, VALIDATION_RESULT *aResult)
Validates that at least one option is selected.
static bool ValidateSelection(int aSelectionIndex, const wxString &aLabel, VALIDATION_RESULT *aResult)
Validates that a selection has been made (index >= 0).
static wxString GetConstraintCode(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType)
Translate a rule tree node type into the keyword used by the rules file for that constraint.
static bool ValidateNumericCtrl(wxTextCtrl *aTextCtrl, const wxString &aLabel, bool aCanBeZero, int *aErrorCount, wxString *aValidationMessage)
Validates a numeric input control, checking if the value is valid, non-empty, and greater than zero.
static bool ValidateMinMax(double aMin, double aMax, const wxString &aMinLabel, const wxString &aMaxLabel, VALIDATION_RESULT *aResult)
Validates that min <= max.
static bool ConstraintFromKicadDrc(const wxString &aCode, DRC_RE_BASE_CONSTRAINT_DATA *aData)
Populate a constraint data object using a keyword from a .kicad_drc file.
static bool ValidateMinPreferredMaxCtrl(wxTextCtrl *aMinTextCtrl, wxTextCtrl *aPreferredTextCtrl, wxTextCtrl *aMaxTextCtrl, const wxString &aMinLabel, const wxString &aPreferredLabel, const wxString &aMaxLabel, int *aErrorCount, wxString *aValidationMessage)
Validates the minimum, preferred, and maximum value controls, ensuring that:
static wxString FormatErrorMessage(int aErrorCount, const wxString &aErrorMessage)
static std::optional< DRC_RULE_EDITOR_CONSTRAINT_NAME > GetConstraintTypeFromCode(const wxString &aCode)
Resolve a constraint keyword from a rules file into the corresponding rule tree enumeration value.
static bool ValidateComboCtrl(wxComboBox *aComboBox, const wxString &aLabel, int *aErrorCount, wxString *aValidationMessage)
Validates a combo box control, ensuring that a selection has been made.
static bool SaveRules(const wxString &aFilename, const std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > &aRules, const BOARD *aBoard)
static void RegisterRuleConverter(RuleConverter aConverter)
static wxString TranslateTopBottomLayer(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType, bool aIsTop)
Translate a top/bottom selection to the appropriate layer clause or condition.
static bool ValidateCheckBoxCtrls(const std::vector< wxCheckBox * > &aCheckboxes, const wxString &aLabel, int *aErrorCount, wxString *aValidationMessage)
Validates a list of checkboxes, ensuring that at least one option is selected.
static bool ValidateNumericString(const wxString &aValueStr, bool aCanBeZero, bool aIntegerOnly, const wxString &aLabel, VALIDATION_RESULT *aResult)
Validates that a string represents a valid numeric value.
static bool ValidateMinMaxCtrl(wxTextCtrl *aMinTextCtrl, wxTextCtrl *aMaxTextCtrl, const wxString &aMinLabel, const wxString &aMaxLabel, int *aErrorCount, wxString *aValidationMessage)
Validates the minimum and maximum value controls, ensuring that the minimum value is not greater than...
std::function< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA >(const std::shared_ptr< DRC_RULE > &)> RuleConverter
static std::shared_ptr< DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA > CreateNumericConstraintData(DRC_RULE_EDITOR_CONSTRAINT_NAME aType)
static DRC_LAYER_CATEGORY GetLayerCategoryForConstraint(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType)
Get the layer category for a constraint type.
static bool ValidateMinPreferredMax(double aMin, double aPreferred, double aMax, const wxString &aMinLabel, const wxString &aPrefLabel, const wxString &aMaxLabel, VALIDATION_RESULT *aResult)
Validates that min <= preferred <= max.
static bool ValidateIntegerCtrl(wxTextCtrl *aTextCtrl, const wxString &aLabel, bool aCanBeZero, int *aErrorCount, wxString *aValidationMessage)
Validates an integer input control, ensuring the value is a valid integer, non-empty,...
static bool IsBoolInputType(const DRC_RULE_EDITOR_CONSTRAINT_NAME &aConstraintType)
static std::vector< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > > ParseRules(const wxString &aRules)
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
VALIDATION_STATE GetValidationState() const
VALIDATION_STATE GetValidationState() const
VALIDATION_STATE GetValidationState() const
VALIDATION_STATE GetValidationState() const
DRC_CONSTRAINT_T
Definition drc_rule.h:53
@ ANNULAR_WIDTH_CONSTRAINT
Definition drc_rule.h:67
@ BRIDGED_MASK_CONSTRAINT
Definition drc_rule.h:89
@ COURTYARD_CLEARANCE_CONSTRAINT
Definition drc_rule.h:61
@ VIA_DIAMETER_CONSTRAINT
Definition drc_rule.h:76
@ ZONE_CONNECTION_CONSTRAINT
Definition drc_rule.h:68
@ DIFF_PAIR_GAP_CONSTRAINT
Definition drc_rule.h:79
@ VIA_DANGLING_CONSTRAINT
Definition drc_rule.h:88
@ SOLDER_MASK_SLIVER_CONSTRAINT
Definition drc_rule.h:90
@ DISALLOW_CONSTRAINT
Definition drc_rule.h:75
@ TRACK_WIDTH_CONSTRAINT
Definition drc_rule.h:65
@ SILK_CLEARANCE_CONSTRAINT
Definition drc_rule.h:62
@ EDGE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:59
@ MIN_RESOLVED_SPOKES_CONSTRAINT
Definition drc_rule.h:71
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
Definition drc_rule.h:66
@ TEXT_THICKNESS_CONSTRAINT
Definition drc_rule.h:64
@ LENGTH_CONSTRAINT
Definition drc_rule.h:77
@ VIA_COUNT_CONSTRAINT
Definition drc_rule.h:82
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:84
@ CLEARANCE_CONSTRAINT
Definition drc_rule.h:55
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
Definition drc_rule.h:70
@ CONNECTION_WIDTH_CONSTRAINT
Definition drc_rule.h:86
@ THERMAL_RELIEF_GAP_CONSTRAINT
Definition drc_rule.h:69
@ MAX_UNCOUPLED_CONSTRAINT
Definition drc_rule.h:80
@ ASSERTION_CONSTRAINT
Definition drc_rule.h:85
@ SKEW_CONSTRAINT
Definition drc_rule.h:78
@ HOLE_CLEARANCE_CONSTRAINT
Definition drc_rule.h:57
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
Definition drc_rule.h:73
@ SOLDER_MASK_EXPANSION_CONSTRAINT
Definition drc_rule.h:72
@ TRACK_ANGLE_CONSTRAINT
Definition drc_rule.h:87
@ HOLE_SIZE_CONSTRAINT
Definition drc_rule.h:60
@ TEXT_HEIGHT_CONSTRAINT
Definition drc_rule.h:63
@ PHYSICAL_CLEARANCE_CONSTRAINT
Definition drc_rule.h:83
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
Definition drc_rule.h:74
@ HOLE_TO_HOLE_CONSTRAINT
Definition drc_rule.h:58
DRC_RULE_EDITOR_CONSTRAINT_NAME
@ ALLOWED_ORIENTATION
@ SILK_TO_SILK_CLEARANCE
@ ROUTING_DIFF_PAIR
@ SOLDERPASTE_EXPANSION
@ SILK_TO_SOLDERMASK_CLEARANCE
@ COURTYARD_CLEARANCE
@ MINIMUM_CONNECTION_WIDTH
@ SOLDERMASK_EXPANSION
@ MAXIMUM_VIA_COUNT
@ MINIMUM_ANNULAR_WIDTH
@ PHYSICAL_CLEARANCE
@ CREEPAGE_DISTANCE
@ ABSOLUTE_LENGTH
@ MINIMUM_CLEARANCE
@ MINIMUM_THERMAL_RELIEF_SPOKE_COUNT
@ PERMITTED_LAYERS
@ MINIMUM_TEXT_HEIGHT_AND_THICKNESS
@ COPPER_TO_HOLE_CLEARANCE
@ HOLE_TO_HOLE_DISTANCE
@ MINIMUM_DRILL_SIZE
@ MATCHED_LENGTH_DIFF_PAIR
@ COPPER_TO_EDGE_CLEARANCE
@ MINIMUM_SOLDERMASK_SLIVER
@ MINIMUM_VIA_DIAMETER
DRC_LAYER_CATEGORY
Layer categories for filtering the layer selector dropdown.
@ NO_LAYER_SELECTOR
Hide layer selector entirely.
@ TOP_BOTTOM_ANY
Simplified top/bottom/any selector with custom translation.
@ SOLDERMASK_ONLY
F_Mask, B_Mask.
@ GENERAL_ANY_LAYER
All layers + inner/outer synthetic.
@ SOLDERPASTE_ONLY
F_Paste, B_Paste.
@ COPPER_ONLY
Copper layers + inner/outer synthetic.
@ SILKSCREEN_ONLY
F_SilkS, B_SilkS.
static wxString GetConstraintCodeFromType(DRC_CONSTRAINT_T aType)
std::unordered_map< DRC_RULE_EDITOR_CONSTRAINT_NAME, const char * > CODE_MAP
static void RegisterDefaultConverters()
static const CODE_MAP sCodeMap
static const REVERSE_CODE_MAP sCodeReverse
std::unordered_map< wxString, DRC_RULE_EDITOR_CONSTRAINT_NAME, wxStringHash, wxStringEqual > REVERSE_CODE_MAP
static std::vector< DRC_RULE_EDITOR_UTILS::RuleConverter > & GetRuleConverters()
#define _(s)
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
bool AtomicWriteFile(const wxString &aTargetPath, const void *aData, size_t aSize, wxString *aError=nullptr)
Writes aData to aTargetPath via a sibling temp file, fsyncs the data and directory,...
Result of a validation operation.
void AddError(const wxString &aError)