43#include <idf_parser.h>
45#include <wx/stc/stc.h>
84 switch( aConstraintType )
92 default:
return false;
98 wxString* aConstraintTitle,
99 std::shared_ptr<DRC_RE_BASE_CONSTRAINT_DATA> aConstraintData ) :
135 wxBoxSizer* buttonSizer =
new wxBoxSizer( wxHORIZONTAL );
139 bContentSizer->Add( buttonSizer, 0, wxALIGN_RIGHT | wxALL, 2 );
150 [
this]( wxKeyEvent& aEvent )
155 [
this]( wxStyledTextEvent& aEvent )
184 m_nameCtrl->Bind( wxEVT_TEXT, [
this]( wxCommandEvent& )
203 m_netNameRegex.Compile(
"^NetName\\s*[!=]=\\s*$", wxRE_ADVANCED );
204 m_typeRegex.Compile(
"^Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
205 m_viaTypeRegex.Compile(
"^Via_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
206 m_padTypeRegex.Compile(
"^Pad_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
207 m_pinTypeRegex.Compile(
"^Pin_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
208 m_fabPropRegex.Compile(
"^Fabrication_Property\\s*[!=]=\\s*$", wxRE_ADVANCED );
209 m_shapeRegex.Compile(
"^Shape\\s*[!=]=\\s*$", wxRE_ADVANCED );
214 m_hJustRegex.Compile(
"^Horizontal_Justification\\s*[!=]=\\s*$", wxRE_ADVANCED );
215 m_vJustRegex.Compile(
"^Vertical_Justification\\s*[!=]=\\s*$", wxRE_ADVANCED );
252 return wxEmptyString;
256 return wxEmptyString;
267 if( layerValue >= 0 &&
m_board )
269 return wxEmptyString;
310 for( wxWindow* win = GetParent(); win; win = win->GetParent() )
314 units = frame->GetUserUnits();
319 switch( aConstraintType )
324 dynamic_pointer_cast<DRC_RE_VIA_STYLE_CONSTRAINT_DATA>(
m_constraintData ).get(),
330 dynamic_pointer_cast<DRC_RE_MINIMUM_TEXT_HEIGHT_THICKNESS_CONSTRAINT_DATA>(
m_constraintData ).get(),
336 dynamic_pointer_cast<DRC_RE_ROUTING_DIFF_PAIR_CONSTRAINT_DATA>(
m_constraintData ).get(),
342 dynamic_pointer_cast<DRC_RE_ROUTING_WIDTH_CONSTRAINT_DATA>(
m_constraintData ).get(),
348 dynamic_pointer_cast<DRC_RE_PERMITTED_LAYERS_CONSTRAINT_DATA>(
m_constraintData ).get() );
353 dynamic_pointer_cast<DRC_RE_ALLOWED_ORIENTATION_CONSTRAINT_DATA>(
m_constraintData ).get() );
357 aParent, dynamic_pointer_cast<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA>(
m_constraintData ) );
363 dynamic_pointer_cast<DRC_RE_ABSOLUTE_LENGTH_TWO_CONSTRAINT_DATA>(
m_constraintData ).get(),
371 dynamic_pointer_cast<DRC_RE_NUMERIC_INPUT_CONSTRAINT_DATA>(
m_constraintData ).get(),
378 dynamic_pointer_cast<DRC_RE_BOOL_INPUT_CONSTRAINT_DATA>(
m_constraintData ).get() );
476 if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKey() ==
' ' )
491 if( beginning.StartsWith( wxT(
"(condition " ) ) )
493 startPos = lineStart;
498 enum class EXPR_CONTEXT_T :
int
508 std::stack<wxString> sexprs;
511 EXPR_CONTEXT_T context = EXPR_CONTEXT_T::NONE;
512 EXPR_CONTEXT_T expr_context = EXPR_CONTEXT_T::NONE;
514 for(
int i = startPos; i < currentPos; ++i )
522 else if( context == EXPR_CONTEXT_T::STRING )
526 context = EXPR_CONTEXT_T::NONE;
530 if( expr_context == EXPR_CONTEXT_T::STRING )
533 expr_context = EXPR_CONTEXT_T::NONE;
540 partial = wxEmptyString;
541 expr_context = EXPR_CONTEXT_T::STRING;
545 partial = wxEmptyString;
546 expr_context = EXPR_CONTEXT_T::STRUCT_REF;
557 partial = wxEmptyString;
558 context = EXPR_CONTEXT_T::STRING;
562 if( context == EXPR_CONTEXT_T::SEXPR_OPEN && !partial.IsEmpty() )
565 sexprs.push( partial );
568 partial = wxEmptyString;
569 context = EXPR_CONTEXT_T::SEXPR_OPEN;
573 context = EXPR_CONTEXT_T::NONE;
577 if( context == EXPR_CONTEXT_T::SEXPR_OPEN && !partial.IsEmpty() )
580 sexprs.push( partial );
582 if( partial == wxT(
"condition" ) )
584 context = EXPR_CONTEXT_T::SEXPR_STRING;
588 context = EXPR_CONTEXT_T::NONE;
591 partial = wxEmptyString;
595 context = EXPR_CONTEXT_T::NONE;
605 if( context == EXPR_CONTEXT_T::SEXPR_OPEN )
609 tokens = wxT(
"condition" );
612 else if( context == EXPR_CONTEXT_T::SEXPR_TOKEN )
619 else if( context == EXPR_CONTEXT_T::SEXPR_STRING && !sexprs.empty() && sexprs.top() == wxT(
"condition" ) )
623 else if( context == EXPR_CONTEXT_T::STRING && !sexprs.empty() && sexprs.top() == wxT(
"condition" ) )
625 if( expr_context == EXPR_CONTEXT_T::STRUCT_REF )
628 std::set<wxString> propNames;
632 const std::vector<PROPERTY_BASE*>& props = propMgr.
GetProperties( cls.type );
639 if( prop->IsHiddenFromRulesEditor() )
642 wxString ref( prop->Name() );
643 ref.Replace( wxT(
" " ), wxT(
"_" ) );
644 propNames.insert( ref );
648 for(
const wxString& propName : propNames )
649 tokens += wxT(
"|" ) + propName;
655 if( !funcSig.Contains(
"DEPRECATED" ) )
656 tokens += wxT(
"|" ) + funcSig;
659 else if( expr_context == EXPR_CONTEXT_T::STRING )
664 std::shared_ptr<NET_SETTINGS>& netSettings = bds.
m_NetSettings;
666 for(
const auto& [
name, netclass] : netSettings->GetNetclasses() )
667 tokens += wxT(
"|" ) +
name;
671 for(
const wxString& netnameCandidate :
m_board->GetNetClassAssignmentCandidates() )
672 tokens += wxT(
"|" ) + netnameCandidate;
676 tokens = wxT(
"Bitmap|"
692 tokens = wxT(
"Through|"
698 tokens = wxT(
"Through-hole|"
701 "NPTH, mechanical" );
705 tokens = wxT(
"Input|"
720 tokens = wxT(
"None|"
722 "Fiducial, global to board|"
723 "Fiducial, local to footprint|"
730 tokens = wxT(
"Segment|"
739 tokens = wxT(
"Circle|"
744 "Chamfered rectangle|"
749 tokens = wxT(
"Inherited|"
753 "Thermal reliefs for PTH" );
757 tokens = wxT(
"Inherited|"
764 tokens = wxT(
"Default|"
773 tokens = wxT(
"Left|"
786 if( !tokens.IsEmpty() )
799 std::vector<wxString> msg;
805 msg.emplace_back( t );
810 msg.emplace_back( t );
815 msg.emplace_back( t );
820 msg.emplace_back( t );
825 msg.emplace_back( t );
830 msg.emplace_back( t );
835 msg.emplace_back( t );
840 msg.emplace_back( t );
843 wxString msg_txt = wxEmptyString;
845 for( wxString i : msg )
846 msg_txt << wxGetTranslation( i );
849 msg_txt.Replace( wxT(
"Ctrl+" ), wxT(
"Cmd+" ) );
851 const wxString& msGg_txt = msg_txt;
856 wxString html_txt = wxEmptyString;
859 html_txt.Replace( wxS(
"<td" ), wxS(
"<td valign=top" ) );
873 if( condition.IsEmpty() )
875 wxString msg =
_(
"ERROR: No condition text provided for validation." );
883 std::vector<std::shared_ptr<DRC_RULE>> dummyRules;
884 wxString ruleTemplate =
L"(version 1)\n(rule default\n (condition \"%s\")\n)";
885 wxString formattedRule = wxString::Format( ruleTemplate, condition );
891 wxString msg = wxString::Format( wxT(
"%s <a href='%d:%d'>%s</a>" ),
904 wxString link =
event.GetLinkInfo().GetHref();
906 long line = 0, offset = 0;
910 if( parts.size() > 1 )
912 parts[0].ToLong( &line );
913 parts[1].ToLong( &offset );
928 menu.Append( wxID_UNDO,
_(
"Undo" ) );
929 menu.Append( wxID_REDO,
_(
"Redo" ) );
931 menu.AppendSeparator();
933 menu.Append( 1,
_(
"Cut" ) );
934 menu.Append( 2,
_(
"Copy" ) );
935 menu.Append( 3,
_(
"Paste" ) );
936 menu.Append( 4,
_(
"Delete" ) );
938 menu.AppendSeparator();
940 menu.Append( 5,
_(
"Select All" ) );
942 menu.AppendSeparator();
944 menu.Append( wxID_ZOOM_IN,
_(
"Zoom In" ) );
945 menu.Append( wxID_ZOOM_OUT,
_(
"Zoom Out" ) );
948 switch( GetPopupMenuSelectionFromUser( menu ) )
984 wxS(
"Show Matches clicked: nodeId=%d, rule='%s', code='%s'" ),
998 m_btnShowMatches->SetLabel( wxString::Format(
_(
"Show Matches (%d)" ), matchCount ) );
1028 m_layerIDs.push_back(
static_cast<int>(
id ) );
1070 m_layerIDs.push_back(
static_cast<int>(
id ) );
1087 return wxEmptyString;
1091 if( selection <= 0 )
1092 return wxEmptyString;
1094 size_t index =
static_cast<size_t>( selection - 1 );
1097 return wxEmptyString;
1102 if( layerValue < 0 )
1104 switch( layerValue )
1107 return wxS(
"(layer outer)" );
1110 return wxS(
"(layer inner)" );
1119 return wxEmptyString;
1125 wxString clause = wxString::Format( wxS(
"(layer \"%s\")" ),
m_board->GetLayerName( layerId ) );
1140 if( layerValue < 0 )
1142 switch( layerValue )
1157 const wxString& aLayerSource )
1160 if( aLayerSource == wxS(
"outer" ) )
1162 for(
size_t i = 0; i <
m_layerIDs.size(); ++i )
1172 if( aLayerSource == wxS(
"inner" ) )
1174 for(
size_t i = 0; i <
m_layerIDs.size(); ++i )
1185 if( !aLayers.empty() )
1191 if( isFront || isBack )
1195 for(
size_t i = 0; i <
m_layerIDs.size(); ++i )
1207 if( aLayers.empty() )
1214 int target =
static_cast<int>( aLayers.front() );
1216 for(
size_t i = 0; i <
m_layerIDs.size(); ++i )
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Container for design settings for a BOARD object.
std::shared_ptr< NET_SETTINGS > m_NetSettings
Information pertinent to a Pcbnew printed circuit board.
Overlay panel for absolute length constraints showing min, opt, and max length fields positioned over...
Overlay panel for allowed orientation constraints showing checkboxes for each orientation angle posit...
Container panel that manages multiple condition rows with boolean operators.
Simple panel used for editing custom rule text.
Overlay panel for minimum text height and thickness constraints showing text dimension fields positio...
Overlay panel for permitted layers constraints showing checkboxes for top and bottom layer selection ...
Overlay panel for differential pair routing constraints showing gap, width, and uncoupled length fiel...
Overlay panel for routing width constraints showing min/preferred/max width fields positioned over a ...
Overlay panel for via style constraints showing via diameter and hole size fields positioned over a d...
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
static bool IsNumericInputType(const DRC_RULE_EDITOR_CONSTRAINT_NAME &aConstraintType)
static wxString FormatErrorMessage(int aErrorCount, const wxString &aErrorMessage)
static wxString TranslateTopBottomLayer(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType, bool aIsTop)
Translate a top/bottom selection to the appropriate layer clause or condition.
static DRC_LAYER_CATEGORY GetLayerCategoryForConstraint(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType)
Get the layer category for a constraint type.
static bool IsBoolInputType(const DRC_RULE_EDITOR_CONSTRAINT_NAME &aConstraintType)
The base frame for deriving all KiCad main window classes.
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
wxBoxSizer * m_conditionControlsSizer
wxBoxSizer * bContentSizer
PANEL_DRC_RULE_EDITOR_BASE(wxWindow *parent, wxWindowID id=wxID_ANY, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(-1,-1), long style=wxTAB_TRAVERSAL, const wxString &name=wxEmptyString)
wxStaticText * m_staticText711
wxStaticText * m_constraintHeaderTitle
wxTextCtrl * m_commentCtrl
wxBoxSizer * m_LayersComboBoxSizer
wxStaticLine * m_staticline111
WX_HTML_REPORT_BOX * m_syntaxErrorReport
wxBoxSizer * m_constraintContentSizer
wxBitmapButton * m_checkSyntaxBtnCtrl
wxStyledTextCtrl * m_textConditionCtrl
std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > m_constraintData
void onCloseButtonClicked(wxCommandEvent &aEvent)
Handles the close button click event, invoking the close callback.
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
void ResetShowMatchesButton()
PANEL_DRC_RULE_EDITOR(wxWindow *aParent, BOARD *aBoard, DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType, wxString *aConstraintTitle, std::shared_ptr< DRC_RE_BASE_CONSTRAINT_DATA > aConstraintData)
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
Handles character addition in the Scintilla text control, performing auto-complete and context-sensit...
void onShowMatchesButtonClicked(wxCommandEvent &aEvent)
void onCheckSyntax(wxCommandEvent &aEvent) override
Checks the syntax of the DRC rule condition and reports any errors.
std::function< void(int aNodeId)> m_callBackSave
wxString m_validationMessage
HTML_MESSAGE_BOX * m_helpWindow
wxString getSelectedLayerSource() const
void onContextMenu(wxMouseEvent &aEvent) override
Handles right-click context menu actions for text editing (undo, redo, cut, copy, paste,...
bool TransferDataFromWindow() override
void onRemoveButtonClicked(wxCommandEvent &aEvent)
Handles the remove button click event, invoking the remove callback.
wxString * m_constraintTitle
void setSelectedLayers(const std::vector< PCB_LAYER_ID > &aLayers, const wxString &aLayerSource=wxEmptyString)
DRC_LAYER_CATEGORY m_layerCategory
wxButton * m_btnShowMatches
std::function< bool(int aNodeId, wxString aRuleName)> m_callBackRuleNameValidation
void onSyntaxHelp(wxHyperlinkEvent &aEvent) override
Displays a modeless help window with syntax and rule documentation.
std::vector< int > m_layerIDs
~PANEL_DRC_RULE_EDITOR() override
wxChoice * m_layerListChoiceCtrl
void populateLayerSelector(DRC_LAYER_CATEGORY aCategory)
wxRegEx m_zoneConnStyleRegex
DRC_RULE_EDITOR_CONSTRAINT_NAME m_constraintType
void Cancel(wxCommandEvent &aEvent)
wxRegEx m_padConnectionsRegex
bool m_validationSucceeded
void onErrorLinkClicked(wxHtmlLinkEvent &aEvent) override
Handles clicks on error links in the syntax error report and navigates to the error location.
std::function< void(int aNodeId)> m_callBackRemove
void OnEnterKey(wxCommandEvent &aEvent) override
std::function< int(int aNodeId)> m_callBackShowMatches
bool TransferDataToWindow() override
DRC_RE_CONDITION_GROUP_PANEL * m_conditionGroupPanel
std::unique_ptr< SCINTILLA_TRICKS > m_scintillaTricks
void Save(wxCommandEvent &aEvent)
void onSaveButtonClicked(wxCommandEvent &aEvent)
Handles the save button click event, validating inputs and invoking the save callback if valid.
DRC_RULE_EDITOR_CONTENT_PANEL_BASE * getConstraintPanel(wxWindow *aParent, const DRC_RULE_EDITOR_CONSTRAINT_NAME &aConstraintType)
std::vector< PCB_LAYER_ID > getSelectedLayers()
wxString buildLayerClause() const
std::function< void(int aNodeId)> m_callBackClose
bool ValidateInputs(int *aErrorCount, wxString *aValidationMessage) override
DRC_RULE_EDITOR_CONTENT_PANEL_BASE * m_constraintPanel
const wxArrayString GetSignatures() const
static PCBEXPR_BUILTIN_FUNCTIONS & Instance()
Provide class metadata.Helper macro to map type hashes to names.
const std::vector< PROPERTY_BASE * > & GetProperties(TYPE_ID aType) const
Return all properties for a specific type.
CLASSES_INFO GetAllClasses()
static PROPERTY_MANAGER & Instance()
void SetModified()
Marks the dialog as modified, indicating unsaved changes.
void RefreshContentScrollArea()
Recalculates the scrolled content area's virtual size based on the current content panel's best size,...
static RULE_EDITOR_DIALOG_BASE * GetDialog(wxWindow *aWindow)
Static method to retrieve the rule editor dialog instance associated with a given window.
This file is part of the common library.
DRC_RULE_EDITOR_CONSTRAINT_NAME
@ MINIMUM_TEXT_HEIGHT_AND_THICKNESS
@ COPPER_TO_HOLE_CLEARANCE
@ MATCHED_LENGTH_DIFF_PAIR
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.
@ LAYER_SEL_BOTTOM
Context-dependent back/bottom layer.
@ LAYER_SEL_OUTER
External copper layers (F_Cu + B_Cu)
@ LAYER_SEL_TOP
Context-dependent front/top layer.
@ LAYER_SEL_INNER
Internal copper layers (In1_Cu through In30_Cu)
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
PCB_LAYER_ID
A quick note on layer IDs:
static bool constraintNeedsTwoObjects(DRC_RULE_EDITOR_CONSTRAINT_NAME aConstraintType)
static constexpr const wxChar * KI_TRACE_DRC_RULE_EDITOR
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
void ConvertMarkdown2Html(const wxString &aMarkdownInput, wxString &aHtmlOutput)
A filename or source description, a problem input line, a line number, a byte offset,...
int lineNumber
at which line number, 1 based index.
const wxString ParseProblem()
int byteIndex
at which byte offset within the line, 1 based index
wxString conditionExpression