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