36#include <wx/stc/stc.h>
40 wxWindow* aParent, std::shared_ptr<DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA> aConstraintData ) :
46 wxBoxSizer* sizer =
new wxBoxSizer( wxVERTICAL );
48 m_textCtrl =
new wxStyledTextCtrl(
this, wxID_ANY );
49 sizer->Add(
m_textCtrl, 1, wxEXPAND | wxALL, 5 );
57 [
this]( wxStyledTextEvent& )
68 []( wxKeyEvent& aEvent )
73 [
this]( wxStyledTextEvent& aEvent )
97 text = wxS(
" (constraint clearance (min 0.2mm))" );
119 (void) aValidationMessage;
133 if( body.Trim().IsEmpty() )
134 return wxEmptyString;
136 wxString ruleName = aContext.
ruleName;
137 ruleName.Replace( wxS(
"\"" ), wxS(
"\\\"" ) );
140 rule << wxS(
"(rule \"" ) << ruleName << wxS(
"\"\n" );
142 if( !aContext.
comment.IsEmpty() )
144 wxArrayString lines = wxSplit( aContext.
comment,
'\n',
'\0' );
146 for(
const wxString& line : lines )
151 rule << wxS(
"\t# " ) << line << wxS(
"\n" );
155 rule << body << wxS(
")" );
170 if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKey() ==
' ' )
181 enum class EXPR_CONTEXT_T :
int
189 std::stack<wxString> sexprs;
191 EXPR_CONTEXT_T context = EXPR_CONTEXT_T::NONE;
193 for(
int i = startPos; i < currentPos; ++i )
201 else if( context == EXPR_CONTEXT_T::STRING )
204 context = EXPR_CONTEXT_T::NONE;
208 partial = wxEmptyString;
209 context = EXPR_CONTEXT_T::STRING;
213 if( context == EXPR_CONTEXT_T::SEXPR_OPEN && !partial.IsEmpty() )
216 sexprs.push( partial );
219 partial = wxEmptyString;
220 context = EXPR_CONTEXT_T::SEXPR_OPEN;
224 if( !sexprs.empty() )
227 context = EXPR_CONTEXT_T::NONE;
231 if( context == EXPR_CONTEXT_T::SEXPR_OPEN && !partial.IsEmpty() )
234 sexprs.push( partial );
235 context = EXPR_CONTEXT_T::SEXPR_TOKEN;
236 partial = wxEmptyString;
240 context = EXPR_CONTEXT_T::NONE;
250 if( context == EXPR_CONTEXT_T::SEXPR_OPEN )
254 tokens = wxT(
"condition|constraint|layer|severity" );
256 else if( sexprs.top() == wxT(
"rule" ) )
259 tokens = wxT(
"condition|constraint|layer|severity" );
261 else if( sexprs.top() == wxT(
"constraint" ) )
264 tokens = wxT(
"min|max|opt" );
267 else if( context == EXPR_CONTEXT_T::SEXPR_TOKEN )
269 if( !sexprs.empty() && sexprs.top() == wxT(
"constraint" ) )
272 tokens = wxT(
"annular_width|"
276 "courtyard_clearance|"
279 "diff_pair_uncoupled|"
287 "min_resolved_spokes|"
288 "physical_clearance|"
289 "physical_hole_clearance|"
294 "thermal_relief_gap|"
295 "thermal_spoke_width|"
297 "track_segment_length|"
303 else if( !sexprs.empty() && sexprs.top() == wxT(
"layer" ) )
306 tokens = wxT(
"inner|outer" );
308 else if( !sexprs.empty() && sexprs.top() == wxT(
"severity" ) )
311 tokens = wxT(
"error|warning|ignore|exclusion" );
315 if( !tokens.IsEmpty() )
331 ruleName.Replace( wxS(
"\"" ), wxS(
"\\\"" ) );
332 wxString rulesText = wxString::Format( wxS(
"(version 1)\n(rule \"%s\"\n%s)" ), ruleName, body );
334 if( body.Trim().IsEmpty() )
336#if wxCHECK_VERSION( 3, 3, 2 )
337 m_tipWindow = wxTipWindow::New(
this,
_(
"No rule text to check." ) );
339 m_tipWindow =
new wxTipWindow(
this,
_(
"No rule text to check." ) );
349 std::vector<std::shared_ptr<DRC_RULE>> dummyRules;
352 parser.
Parse( dummyRules, &reporter );
356 reporter.
Report( wxString::Format(
_(
"ERROR at line %d, column %d: %s" ),
371 message =
_(
"Syntax check passed with warnings:\n" ) + reporter.
GetMessages();
375 message =
_(
"Syntax OK" );
378#if wxCHECK_VERSION( 3, 3, 2 )
bool TransferDataFromWindow() override
wxStyledTextCtrl * m_textCtrl
bool TransferDataToWindow() override
wxTipWindow * m_tipWindow
~DRC_RE_CUSTOM_RULE_PANEL() override
void UpdateRuleName(const wxString &aName)
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
bool ValidateInputs(int *aErrorCount, wxString *aValidationMessage) override
wxString GenerateRule(const RULE_GENERATION_CONTEXT &aContext) override
std::shared_ptr< DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA > m_constraintData
std::unique_ptr< SCINTILLA_TRICKS > m_scintillaTricks
wxButton * m_checkSyntaxBtn
DRC_RE_CUSTOM_RULE_PANEL(wxWindow *aParent, std::shared_ptr< DRC_RE_CUSTOM_RULE_CONSTRAINT_DATA > aConstraintData)
void onCheckSyntax(wxCommandEvent &aEvent)
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
virtual bool HasMessageOfSeverity(int aSeverityMask) const
Returns true if the reporter has one or more messages matching the specified severity mask.
virtual bool HasMessage() const
Returns true if any messages were reported.
void SetModified()
Marks the dialog as modified, indicating unsaved changes.
static RULE_EDITOR_DIALOG_BASE * GetDialog(wxWindow *aWindow)
Static method to retrieve the rule editor dialog instance associated with a given window.
A wrapper for reporting to a wxString object.
REPORTER & Report(const wxString &aText, SEVERITY aSeverity=RPT_SEVERITY_UNDEFINED) override
Report a string with a given severity.
const wxString & GetMessages() const
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