43#include <unordered_map>
45using CODE_MAP = std::unordered_map<DRC_RULE_EDITOR_CONSTRAINT_NAME, const char*>;
46using REVERSE_CODE_MAP = std::unordered_map<wxString, DRC_RULE_EDITOR_CONSTRAINT_NAME, wxStringHash, wxStringEqual>;
89 for(
const auto& [type, code] :
sCodeMap )
90 map.emplace( wxString::FromUTF8( code ), type );
96 static std::vector<DRC_RULE_EDITOR_UTILS::RuleConverter> converters;
148 static bool initialized =
false;
155 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
157 if( aRule->m_Constraints.empty() )
return nullptr;
159 const auto& constraint = aRule->m_Constraints[0];
162 if( code.IsEmpty() )
return nullptr;
170 double val = constraint.GetValue().Min() / 1000000.0;
171 auto data = std::make_shared<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>( 0, 0, val, aRule->m_Name );
172 data->SetConstraintCode( code );
177 auto data = std::make_shared<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>( 0, 0,
true, aRule->m_Name );
178 data->SetConstraintCode( code );
181 else if( code ==
"track_width" )
183 double minW = constraint.GetValue().Min() / 1000000.0;
184 double optW = constraint.GetValue().Opt() / 1000000.0;
185 double maxW = constraint.GetValue().Max() / 1000000.0;
187 auto data = std::make_shared<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>( 0, 0, aRule->m_Name, minW, optW, maxW );
188 data->SetConstraintCode( code );
197 [](
const std::shared_ptr<DRC_RULE>& aRule ) -> std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>
202 if( diaConstraint && holeConstraint )
204 double minDia = diaConstraint->GetValue().Min() / 1000000.0;
205 double optDia = diaConstraint->GetValue().Opt() / 1000000.0;
206 double maxDia = diaConstraint->GetValue().Max() / 1000000.0;
208 double minDrill = holeConstraint->GetValue().Min() / 1000000.0;
209 double optDrill = holeConstraint->GetValue().Opt() / 1000000.0;
210 double maxDrill = holeConstraint->GetValue().Max() / 1000000.0;
212 auto data = std::make_shared<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>( 0, 0, aRule->m_Name,
213 minDia, maxDia, optDia, minDrill, maxDrill, optDrill );
214 data->SetConstraintCode(
"via_style" );
224 auto it =
sCodeMap.find( aConstraintType );
226 return wxString::FromUTF8( it->second );
267 switch( aConstraintType )
270 default:
return false;
277 switch( aConstraintType )
315 int* aErrorCount, std::string* aValidationMessage )
318 aTextCtrl->SetValidator( validator );
320 if( !aTextCtrl->Validate() )
329 *aValidationMessage +=
337 *aErrorCount,
"The value of " + aLabel +
" should be valid numeric value !!" );
344 *aErrorCount,
"The value of " + aLabel +
" must be greater than 0 !!" );
356 int* aErrorCount, std::string* aValidationMessage )
359 aTextCtrl->SetValidator( validator );
361 if( !aTextCtrl->Validate() )
370 *aValidationMessage +=
378 *aErrorCount,
"The value of " + aLabel +
" should be valid integer value !!" );
385 *aErrorCount,
"The value of " + aLabel +
" must be greater than 0 !!" );
397 std::string* aValidationMessage )
400 aComboBox->SetValidator( cmbCtrlValidator );
402 if( !aComboBox->Validate() )
423 std::string aMinLabel, std::string aMaxLabel,
int* aErrorCount,
424 std::string* aValidationMessage )
426 aMinTextCtrl->SetName(
"min" );
427 aMaxTextCtrl->SetName(
"max" );
431 if( !aMinTextCtrl->Validate() )
441 *aErrorCount, aMinLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
448 aMinTextCtrl->SetName(
"text" );
449 aMaxTextCtrl->SetName(
"text" );
456 wxTextCtrl* aMaxTextCtrl, std::string aMinLabel,
457 std::string aPreferredLabel, std::string aMaxLabel,
458 int* aErrorCount, std::string* aValidationMessage )
460 aMinTextCtrl->SetName(
"min" );
461 aPreferredTextCtrl->SetName(
"preferred" );
462 aMaxTextCtrl->SetName(
"max" );
466 if( !aMinTextCtrl->Validate() )
477 *aErrorCount, aMinLabel +
" value cannot be greater than " + aPreferredLabel +
" value" );
484 *aErrorCount, aPreferredLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
491 *aErrorCount, aMinLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
498 aMinTextCtrl->SetName(
"text" );
499 aPreferredTextCtrl->SetName(
"text" );
500 aMaxTextCtrl->SetName(
"text" );
507 int* aErrorCount, std::string* aValidationMessage )
511 aCheckboxes[0]->SetValidator( validator );
513 if( !aCheckboxes[0]->Validate() )
523 *aErrorCount,
"Please select at least one option from " + aLabel +
" list" );
536 return std::to_string( aErrorCount ) +
". " + aErrorMessage +
"\n";
545 if( !aCanBeZero && aValue <= 0.0 )
547 aResult->
AddError(
"The value of " + aLabel +
" must be greater than 0" );
556 bool aIntegerOnly,
const std::string& aLabel,
559 if( aValueStr.empty() )
561 aResult->
AddError( aLabel +
" should not be empty" );
570 long intVal = std::stol( aValueStr, &pos );
572 if( pos != aValueStr.length() )
574 aResult->
AddError(
"The value of " + aLabel +
" should be a valid integer value" );
578 if( !aCanBeZero && intVal <= 0 )
580 aResult->
AddError(
"The value of " + aLabel +
" must be greater than 0" );
587 double floatVal = std::stod( aValueStr, &pos );
589 if( pos != aValueStr.length() )
591 aResult->
AddError(
"The value of " + aLabel +
" should be a valid numeric value" );
595 if( !aCanBeZero && floatVal <= 0.0 )
597 aResult->
AddError(
"The value of " + aLabel +
" must be greater than 0" );
602 catch(
const std::exception& )
605 aResult->
AddError(
"The value of " + aLabel +
" should be a valid integer value" );
607 aResult->
AddError(
"The value of " + aLabel +
" should be a valid numeric value" );
621 aResult->
AddError( aMinLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
630 const std::string& aMinLabel,
631 const std::string& aPrefLabel,
632 const std::string& aMaxLabel,
637 if( aMin > aPreferred )
639 aResult->
AddError( aMinLabel +
" value cannot be greater than " + aPrefLabel +
" value" );
643 if( aPreferred > aMax )
645 aResult->
AddError( aPrefLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
651 aResult->
AddError( aMinLabel +
" value cannot be greater than " + aMaxLabel +
" value" );
660 const std::string& aLabel,
663 for(
bool selected : aSelected )
669 aResult->
AddError(
"Please select at least one option from " + aLabel +
" list" );
677 if( aSelectionIndex < 0 )
679 aResult->
AddError(
"Please choose " + aLabel );
691 std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>> rules;
692 std::vector<std::shared_ptr<DRC_RULE>> parsedRules;
694 wxString rulesText = aRules;
695 if( !rulesText.Contains(
"(version" ) )
696 rulesText.Prepend(
"(version 1)\n" );
701 parser.
Parse( parsedRules,
nullptr );
707 for(
const auto& rule : parsedRules )
709 std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> data;
713 data = converter( rule );
720 auto customData = std::make_shared<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>( 0, 0, rule->m_Name );
721 customData->SetRuleText( wxString::Format(
"(rule \"%s\" ...)", rule->m_Name ) );
725 if( rule->m_Condition )
726 data->SetRuleCondition( rule->m_Condition->GetExpression() );
728 rules.push_back( data );
735 const std::vector<std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA>>& aRules,
736 const BOARD* aBoard )
738 wxFFile file( aFilename,
"w" );
740 if( !file.IsOpened() )
743 file.Write(
"(version 1)\n" );
745 for(
const auto& data : aRules )
752 ctx.
comment = data->GetComment();
756 std::vector<PCB_LAYER_ID> layers = data->GetLayers();
758 if( !layers.empty() && aBoard )
760 wxString layerStr =
"(layer";
763 layerStr +=
" \"" + aBoard->
GetLayerName( layer ) +
"\"";
769 wxString ruleText = data->GenerateRule( ctx );
770 file.Write( ruleText +
"\n" );
Information pertinent to a Pcbnew printed circuit board.
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
void SetConstraintCode(wxString aCode)
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
static bool ValidateMinPreferredMax(double aMin, double aPreferred, double aMax, const std::string &aMinLabel, const std::string &aPrefLabel, const std::string &aMaxLabel, VALIDATION_RESULT *aResult)
Validates that min <= preferred <= max.
static bool ValidateMinMaxCtrl(wxTextCtrl *aMinTextCtrl, wxTextCtrl *aMaxTextCtrl, std::string aMinLabel, std::string aMaxLabel, int *aErrorCount, std::string *aValidationMessage)
Validates the minimum and maximum value controls, ensuring that the minimum value is not greater than...
static bool ValidateMinMax(double aMin, double aMax, const std::string &aMinLabel, const std::string &aMaxLabel, VALIDATION_RESULT *aResult)
Validates that min <= max.
static bool ValidateNumericValue(double aValue, bool aCanBeZero, const std::string &aLabel, VALIDATION_RESULT *aResult)
Validates a numeric value.
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 ValidateComboCtrl(wxComboBox *aComboBox, std::string aLabel, int *aErrorCount, std::string *aValidationMessage)
Validates a combo box control, ensuring that a selection has been made.
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 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 ValidateSelection(int aSelectionIndex, const std::string &aLabel, VALIDATION_RESULT *aResult)
Validates that a selection has been made (index >= 0).
static bool ValidateNumericString(const std::string &aValueStr, bool aCanBeZero, bool aIntegerOnly, const std::string &aLabel, VALIDATION_RESULT *aResult)
Validates that a string represents a valid numeric value.
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 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 bool ValidateIntegerCtrl(wxTextCtrl *aTextCtrl, std::string aLabel, bool aCanBeZero, int *aErrorCount, std::string *aValidationMessage)
Validates an integer input control, ensuring the value is a valid integer, non-empty,...
static bool ValidateNumericCtrl(wxTextCtrl *aTextCtrl, std::string aLabel, bool aCanBeZero, int *aErrorCount, std::string *aValidationMessage)
Validates a numeric input control, checking if the value is valid, non-empty, and greater than zero.
std::function< std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA >(const std::shared_ptr< DRC_RULE > &)> RuleConverter
static bool ValidateCheckBoxCtrls(const std::vector< wxCheckBox * > &aCheckboxes, std::string aLabel, int *aErrorCount, std::string *aValidationMessage)
Validates a list of checkboxes, ensuring that at least one option is selected.
static std::string FormatErrorMessage(const int &aErrorCount, const std::string aErrorMessage)
static bool ValidateAtLeastOneSelected(const std::vector< bool > &aSelected, const std::string &aLabel, VALIDATION_RESULT *aResult)
Validates that at least one option is selected.
static bool ValidateMinPreferredMaxCtrl(wxTextCtrl *aMinTextCtrl, wxTextCtrl *aPreferredTextCtrl, wxTextCtrl *aMaxTextCtrl, std::string aMinLabel, std::string aPreferredLabel, std::string aMaxLabel, int *aErrorCount, std::string *aValidationMessage)
Validates the minimum, preferred, and maximum value controls, ensuring that:
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
@ PreferredGreaterThanMax
@ MinGreaterThanPreferred
VALIDATION_STATE GetValidationState() const
VALIDATION_STATE GetValidationState() const
@ ANNULAR_WIDTH_CONSTRAINT
@ BRIDGED_MASK_CONSTRAINT
@ COURTYARD_CLEARANCE_CONSTRAINT
@ VIA_DIAMETER_CONSTRAINT
@ ZONE_CONNECTION_CONSTRAINT
@ DIFF_PAIR_GAP_CONSTRAINT
@ VIA_DANGLING_CONSTRAINT
@ SILK_CLEARANCE_CONSTRAINT
@ EDGE_CLEARANCE_CONSTRAINT
@ MIN_RESOLVED_SPOKES_CONSTRAINT
@ TRACK_SEGMENT_LENGTH_CONSTRAINT
@ TEXT_THICKNESS_CONSTRAINT
@ PHYSICAL_HOLE_CLEARANCE_CONSTRAINT
@ THERMAL_SPOKE_WIDTH_CONSTRAINT
@ CONNECTION_WIDTH_CONSTRAINT
@ THERMAL_RELIEF_GAP_CONSTRAINT
@ MAX_UNCOUPLED_CONSTRAINT
@ HOLE_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_ABS_MARGIN_CONSTRAINT
@ SOLDER_MASK_EXPANSION_CONSTRAINT
@ PHYSICAL_CLEARANCE_CONSTRAINT
@ SOLDER_PASTE_REL_MARGIN_CONSTRAINT
@ HOLE_TO_HOLE_CONSTRAINT
DRC_RULE_EDITOR_CONSTRAINT_NAME
@ MINIMUM_SOLDERMASK_SILVER
@ SILK_TO_SOLDERMASK_CLEARANCE
@ BOARD_OUTLINE_CLEARANCE
@ MINIMUM_CONNECTION_WIDTH
@ MINIMUM_THERMAL_RELIEF_SPOKE_COUNT
@ MINIMUM_TEXT_HEIGHT_AND_THICKNESS
@ COPPER_TO_HOLE_CLEARANCE
@ MAXIMUM_ALLOWED_DEVIATION
@ MATCHED_LENGTH_DIFF_PAIR
@ COPPER_TO_EDGE_CLEARANCE
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()
PCB_LAYER_ID
A quick note on layer IDs:
wxString conditionExpression
Result of a validation operation.
void AddError(const std::string &aError)