45#include <unordered_map> 
   55            [
this]( wxKeyEvent& aEvent )
 
   58                             wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_OK ) );
 
   61            [
this]( wxStyledTextEvent& aEvent )
 
   70    m_typeRegex.Compile( 
"^Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   71    m_viaTypeRegex.Compile( 
"^Via_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   72    m_padTypeRegex.Compile( 
"^Pad_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   73    m_pinTypeRegex.Compile( 
"^Pin_Type\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   74    m_fabPropRegex.Compile( 
"^Fabrication_Property\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   75    m_shapeRegex.Compile( 
"^Shape\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   80    m_hJustRegex.Compile( 
"^Horizontal_Justification\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   81    m_vJustRegex.Compile( 
"^Vertical_Justification\\s*[!=]=\\s*$", wxRE_ADVANCED );
 
   85    m_textEditor->SetZoom( 
Pgm().GetCommonSettings()->m_Appearance.text_editor_zoom );
 
 
  106    if( aEvent.GetKeyCode() == WXK_ESCAPE && !
m_textEditor->AutoCompActive() )
 
  110            if( 
IsOK( wxGetTopLevelParent( 
this ), 
_( 
"Cancel Changes?" ) ) )
 
 
  128    menu.Append( wxID_UNDO, 
_( 
"Undo" ) );
 
  129    menu.Append( wxID_REDO, 
_( 
"Redo" ) );
 
  131    menu.AppendSeparator();
 
  133    menu.Append( 1, 
_( 
"Cut" ) );       
 
  134    menu.Append( 2, 
_( 
"Copy" ) );      
 
  135    menu.Append( 3, 
_( 
"Paste" ) );
 
  136    menu.Append( 4, 
_( 
"Delete" ) );
 
  138    menu.AppendSeparator();
 
  140    menu.Append( 5, 
_( 
"Select All" ) );
 
  142    menu.AppendSeparator();
 
  144    menu.Append( wxID_ZOOM_IN, 
_( 
"Zoom In" ) );
 
  145    menu.Append( wxID_ZOOM_OUT, 
_( 
"Zoom Out" ) );
 
  148    switch( GetPopupMenuSelectionFromUser( menu ) )
 
 
  193    if( aEvent.GetModifiers() == wxMOD_CONTROL && aEvent.GetKey() == 
' ' )
 
  207    for( 
int line = 
m_textEditor->LineFromPosition( currentPos ); line > 0; line-- )
 
  210        wxString beginning = 
m_textEditor->GetTextRange( lineStart, lineStart + 10 );
 
  212        if( beginning.StartsWith( wxT( 
"(rule " ) ) )
 
  214            startPos = lineStart;
 
  229    auto isDisallowToken =
 
  230            []( 
const wxString& token ) -> 
bool 
  232                return token == wxT( 
"blind_via" )
 
  233                    || token == wxT( 
"buried_via" )
 
  234                    || token == wxT( 
"graphic" )
 
  235                    || token == wxT( 
"hole" )
 
  236                    || token == wxT( 
"micro_via" )
 
  237                    || token == wxT( 
"pad" )
 
  238                    || token == wxT( 
"text" )
 
  239                    || token == wxT( 
"through_via" )
 
  240                    || token == wxT( 
"track" )
 
  241                    || token == wxT( 
"via" )
 
  242                    || token == wxT( 
"zone" );
 
  245    auto isConstraintTypeToken =
 
  246            []( 
const wxString& token ) -> 
bool 
  248                return token == wxT( 
"annular_width" )
 
  249                    || token == wxT( 
"assertion" )
 
  250                    || token == wxT( 
"clearance" )
 
  251                    || token == wxT( 
"connection_width" )
 
  252                    || token == wxT( 
"courtyard_clearance" )
 
  253                    || token == wxT( 
"diff_pair_gap" )
 
  254                    || token == wxT( 
"diff_pair_uncoupled" )
 
  255                    || token == wxT( 
"disallow" )
 
  256                    || token == wxT( 
"edge_clearance" )
 
  257                    || token == wxT( 
"length" )
 
  258                    || token == wxT( 
"hole_clearance" )
 
  259                    || token == wxT( 
"hole_size" )
 
  260                    || token == wxT( 
"hole_to_hole" )
 
  261                    || token == wxT( 
"min_resolved_spokes" )
 
  262                    || token == wxT( 
"physical_clearance" )
 
  263                    || token == wxT( 
"physical_hole_clearance" )
 
  264                    || token == wxT( 
"silk_clearance" )
 
  265                    || token == wxT( 
"skew" )
 
  266                    || token == wxT( 
"solder_mask_expansion" )
 
  267                    || token == wxT( 
"solder_paste_abs_margin" )
 
  268                    || token == wxT( 
"solder_paste_rel_margin" )
 
  269                    || token == wxT( 
"text_height" )
 
  270                    || token == wxT( 
"text_thickness" )
 
  271                    || token == wxT( 
"thermal_relief_gap" )
 
  272                    || token == wxT( 
"thermal_spoke_width" )
 
  273                    || token == wxT( 
"track_width" )
 
  274                    || token == wxT( 
"track_angle" )
 
  275                    || token == wxT( 
"track_segment_length" )
 
  276                    || token == wxT( 
"via_count" )
 
  277                    || token == wxT( 
"via_diameter" )
 
  278                    || token == wxT( 
"zone_connection" );
 
  281    std::stack<wxString> sexprs;
 
  284    wxString             constraintType;
 
  285    int                  context = NO_CONTEXT;
 
  286    int                  expr_context = NO_CONTEXT;
 
  288    for( 
int i = startPos; i < currentPos; ++i )
 
  296        else if( context == 
STRING )
 
  300                context = NO_CONTEXT;
 
  304                if( expr_context == 
STRING )
 
  307                        expr_context = NO_CONTEXT;
 
  314                    partial = wxEmptyString;
 
  319                    partial = wxEmptyString;
 
  320                    expr_context = STRUCT_REF;
 
  331            partial = wxEmptyString;
 
  336            if( context == SEXPR_OPEN && !partial.IsEmpty() )
 
  339                sexprs.push( partial );
 
  342            partial = wxEmptyString;
 
  343            context = SEXPR_OPEN;
 
  347            while( !sexprs.empty() && ( sexprs.top() == wxT( 
"assertion" )
 
  348                                     || sexprs.top() == wxT( 
"disallow" )
 
  349                                     || isDisallowToken( sexprs.top() )
 
  350                                     || sexprs.top() == wxT( 
"min_resolved_spokes" )
 
  351                                     || sexprs.top() == wxT( 
"zone_connection" ) ) )
 
  356            if( !sexprs.empty() )
 
  359                if( partial == wxT( 
"within_diff_pairs" ) )
 
  361                    partial = wxEmptyString;
 
  365                    if( sexprs.top() == wxT( 
"constraint" ) )
 
  367                        constraintType = wxEmptyString;
 
  374            context = NO_CONTEXT;
 
  378            if( context == SEXPR_OPEN && !partial.IsEmpty() )
 
  381                sexprs.push( partial );
 
  383                if(    partial == wxT( 
"constraint" )
 
  384                    || partial == wxT( 
"layer" )
 
  385                    || partial == wxT( 
"severity" ) )
 
  387                    context = SEXPR_TOKEN;
 
  389                else if( partial == wxT( 
"rule" )
 
  390                      || partial == wxT( 
"condition" ) )
 
  392                    context = SEXPR_STRING;
 
  396                    context = NO_CONTEXT;
 
  399                partial = wxEmptyString;
 
  402            else if( partial == wxT( 
"disallow" )
 
  403                  || isDisallowToken( partial )
 
  404                  || partial == wxT( 
"min_resolved_spokes" )
 
  405                  || partial == wxT( 
"zone_connection" ) )
 
  408                sexprs.push( partial );
 
  410                partial = wxEmptyString;
 
  411                context = SEXPR_TOKEN;
 
  414            else if( partial == wxT( 
"assertion" ) )
 
  417                sexprs.push( partial );
 
  419                partial = wxEmptyString;
 
  420                context = SEXPR_STRING;
 
  423            else if( isConstraintTypeToken( partial ) )
 
  425                constraintType = partial;
 
  428            context = NO_CONTEXT;
 
  438    if( context == SEXPR_OPEN )
 
  442            tokens = wxT( 
"rule|" 
  445        else if( sexprs.top() == wxT( 
"rule" ) )
 
  447            tokens = wxT( 
"condition|" 
  452        else if( sexprs.top() == wxT( 
"constraint" ) )
 
  454            if( constraintType == wxT( 
"skew" ) )
 
  455                tokens = wxT( 
"max|min|opt|within_diff_pairs" );
 
  457                tokens = wxT( 
"max|min|opt" );
 
  460    else if( context == SEXPR_TOKEN )
 
  466        else if( sexprs.top() == wxT( 
"constraint" ) )
 
  468            tokens = wxT( 
"annular_width|" 
  473                          "courtyard_clearance|" 
  476                          "diff_pair_uncoupled|" 
  483                          "min_resolved_spokes|" 
  484                          "physical_clearance|" 
  485                          "physical_hole_clearance|" 
  488                          "solder_mask_expansion|" 
  489                          "solder_paste_abs_margin|" 
  490                          "solder_paste_rel_margin|" 
  493                          "thermal_relief_gap|" 
  494                          "thermal_spoke_width|" 
  497                          "track_segment_length|" 
  502        else if( sexprs.top() == wxT( 
"disallow" ) || isDisallowToken( sexprs.top() ) )
 
  504            tokens = wxT( 
"buried_via|" 
  515        else if( sexprs.top() == wxT( 
"zone_connection" ) )
 
  517            tokens = wxT( 
"none|solid|thermal_reliefs" );
 
  519        else if( sexprs.top() == wxT( 
"min_resolved_spokes" ) )
 
  521            tokens = wxT( 
"0|1|2|3|4" );
 
  523        else if( sexprs.top() == wxT( 
"layer" ) )
 
  525            tokens = wxT( 
"inner|outer|\"x\"" );
 
  527        else if( sexprs.top() == wxT( 
"severity" ) )
 
  529            tokens = wxT( 
"warning|error|ignore|exclusion" );
 
  532    else if( context == SEXPR_STRING && !sexprs.empty()
 
  533            && ( sexprs.top() == wxT( 
"condition" ) || sexprs.top() == wxT( 
"assertion" ) ) )
 
  537    else if( context == 
STRING && !sexprs.empty()
 
  538            && ( sexprs.top() == wxT( 
"condition" ) || sexprs.top() == wxT( 
"assertion" ) ) )
 
  540        if( expr_context == STRUCT_REF )
 
  543            std::set<wxString> propNames;
 
  547                const std::vector<PROPERTY_BASE*>& props = propMgr.
GetProperties( cls.type );
 
  554                    if( prop->IsHiddenFromRulesEditor() )
 
  557                    wxString ref( prop->Name() );
 
  558                    ref.Replace( wxT( 
" " ), wxT( 
"_" ) );
 
  559                    propNames.insert( ref );
 
  563            for( 
const wxString& propName : propNames )
 
  564                tokens += wxT( 
"|" ) + propName;
 
  570                if( !funcSig.Contains( 
"DEPRECATED" ) )
 
  571                    tokens += wxT( 
"|" ) + funcSig;
 
  574        else if( expr_context == 
STRING )
 
  579                std::shared_ptr<NET_SETTINGS>& netSettings = bds.
m_NetSettings;
 
  581                for( 
const auto& [
name, netclass] : netSettings->GetNetclasses() )
 
  582                    tokens += wxT( 
"|" ) + 
name;
 
  589                    tokens += wxT( 
"|" ) + netnameCandidate;
 
  593                tokens = wxT( 
"Bitmap|" 
  609                tokens = wxT( 
"Through|" 
  616                tokens = wxT( 
"Through-hole|" 
  619                              "NPTH, mechanical" );
 
  623                tokens = wxT( 
"Input|" 
  638                tokens = wxT( 
"None|" 
  640                              "Fiducial, global to board|" 
  641                              "Fiducial, local to footprint|" 
  648                tokens = wxT( 
"Segment|" 
  657                tokens = wxT( 
"Circle|" 
  662                              "Chamfered rectangle|" 
  667                tokens = wxT( 
"Inherited|" 
  671                              "Thermal reliefs for PTH" );
 
  675                tokens = wxT( 
"Inherited|" 
  682                tokens = wxT( 
"Default|" 
  691                tokens = wxT( 
"Left|" 
  704    if( !tokens.IsEmpty() )
 
 
  715        std::vector<std::shared_ptr<DRC_RULE>> dummyRules;
 
  717        std::function<bool( wxString* )> 
resolver =
 
  718                [&]( wxString* token ) -> 
bool 
  720                    if( 
m_frame->GetBoard()->ResolveTextVar( token, 0 ) )
 
  727        rulesText = 
m_frame->GetBoard()->ConvertCrossReferencesToKIIDs( rulesText );
 
  737        m_errorsReport->Report( wxString::Format( wxT( 
"%s <a href='%d:%d'>%s</a>%s" ),
 
 
  756    std::unordered_map<wxString, wxString> seenConditions;
 
  757    std::regex                             netclassPattern( 
"NetClass\\s*[!=]=\\s*\"?([^\"\\s]+)\"?" );
 
  759    for( 
const auto& rule : aRules )
 
  763        if( rule->m_Condition )
 
  764            condition = rule->m_Condition->GetExpression();
 
  766        condition.Trim( 
true ).Trim( 
false );
 
  768        if( seenConditions.count( condition ) )
 
  770            m_errorsReport->Report( wxString::Format( 
_( 
"Rules '%s' and '%s' share the same condition." ),
 
  772                                                      seenConditions[condition] ),
 
  777            seenConditions[condition] = rule->m_Name;
 
  780        std::string          condUtf8 = condition.ToStdString();
 
  781        std::sregex_iterator it( condUtf8.begin(), condUtf8.end(), netclassPattern );
 
  782        std::sregex_iterator 
end;
 
  784        for( ; it != 
end; ++it )
 
  786            wxString ncName = wxString::FromUTF8( ( *it )[1].str() );
 
  790                m_errorsReport->Report( wxString::Format( 
_( 
"Rule '%s' references undefined netclass '%s'." ),
 
  797        if( !rule->m_LayerSource.IsEmpty() )
 
  799            LSET invalid = rule->m_LayerCondition & ~enabledLayers;
 
  807                    if( !badLayers.IsEmpty() )
 
  813                m_errorsReport->Report( wxString::Format( 
_( 
"Rule '%s' references undefined layer(s): %s." ),
 
 
  825    wxString      link = 
event.GetLinkInfo().GetHref();
 
  827    long          line = 0, offset = 0;
 
  831    if( parts.size() > 1 )
 
  833        parts[0].ToLong( &line );
 
  834        parts[1].ToLong( &offset );
 
  837    int pos = 
m_textEditor->PositionFromLine( line - 1 ) + ( offset - 1 );
 
 
  847    wxFileName rulesFile( 
m_frame->GetDesignRulesPath() );
 
  849    if( rulesFile.FileExists() )
 
  851        wxTextFile file( rulesFile.GetFullPath() );
 
  855            for ( wxString str = file.GetFirstLine(); !file.Eof(); str = file.GetNextLine() )
 
  863            wxCommandEvent 
dummy;
 
  874    if( 
m_frame->Prj().IsNullProject() )
 
  877        m_textEditor->AddText( 
_( 
"Design rules cannot be added without a project" ) );
 
 
  890    if( 
m_frame->Prj().IsNullProject() )
 
  893    wxString rulesFilepath = 
m_frame->GetDesignRulesPath();
 
  899            m_frame->GetBoard()->GetDesignSettings().m_DRCEngine->InitEngine( rulesFilepath );
 
 
  921    std::vector<wxString> msg;
 
  927    msg.emplace_back( t );
 
  931    msg.emplace_back( t );
 
  935    msg.emplace_back( t );
 
  939    msg.emplace_back( t );
 
  943    msg.emplace_back( t );
 
  947    msg.emplace_back( t );
 
  951    msg.emplace_back( t );
 
  955    msg.emplace_back( t );
 
  959    msg.emplace_back( t );
 
  963    msg.emplace_back( t );
 
  965    wxString msg_txt = wxEmptyString;
 
  967    for( wxString i : msg )
 
  968        msg_txt << wxGetTranslation( i );
 
  971    msg_txt.Replace( wxT( 
"Ctrl+" ), wxT( 
"Cmd+" ) );
 
  973    const wxString& msGg_txt = msg_txt;
 
  978    wxString html_txt = wxEmptyString;
 
  981    html_txt.Replace( wxS( 
"<td" ), wxS( 
"<td valign=top" ) );
 
 
  990    if( !
m_frame->Prj().IsNullProject() )
 
  997        if( absFile.FileExists() )
 
  999            wxTextFile file( absFile.GetFullPath() );
 
 1005                for ( wxString str = file.GetFirstLine(); !file.Eof(); str = file.GetNextLine() )
 
 1013                wxCommandEvent 
dummy;
 
 
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.
 
std::set< wxString > GetNetClassAssignmentCandidates() const
Return the set of netname candidates for netclass assignment.
 
const wxString & GetFileName() const
 
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Return the name of a aLayer.
 
PROJECT * GetProject() const
 
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
 
const LSET & GetEnabledLayers() const
A proxy function that calls the corresponding function in m_BoardSettings.
 
void Parse(std::vector< std::shared_ptr< DRC_RULE > > &aRules, REPORTER *aReporter)
 
LSET is a set of PCB_LAYER_IDs.
 
LSEQ Seq(const LSEQ &aSequence) const
Return an LSEQ from the union of this LSET and a desired sequence.
 
bool HasNetclass(const wxString &netclassName) const
Determines if the given netclass exists.
 
static PAGED_DIALOG * GetDialog(wxWindow *aWindow)
 
STD_BITMAP_BUTTON * m_compileButton
 
wxStyledTextCtrl * m_textEditor
 
PANEL_SETUP_RULES_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)
 
WX_HTML_REPORT_BOX * m_errorsReport
 
bool TransferDataToWindow() override
 
void OnErrorLinkClicked(wxHtmlLinkEvent &event) override
 
void checkPlausibility(const std::vector< std::shared_ptr< DRC_RULE > > &aRules)
 
void onScintillaCharAdded(wxStyledTextEvent &aEvent)
 
void ImportSettingsFrom(BOARD *aBoard)
 
void OnContextMenu(wxMouseEvent &event) override
 
~PANEL_SETUP_RULES() override
 
HTML_MESSAGE_BOX * m_helpWindow
 
void OnCompile(wxCommandEvent &event) override
 
wxRegEx m_padConnectionsRegex
 
wxRegEx m_zoneConnStyleRegex
 
bool TransferDataFromWindow() override
 
void OnSyntaxHelp(wxHyperlinkEvent &aEvent) override
 
PANEL_SETUP_RULES(wxWindow *aParentWindow, PCB_EDIT_FRAME *aFrame)
 
void onCharHook(wxKeyEvent &aEvent)
 
SCINTILLA_TRICKS * m_scintillaTricks
 
const wxArrayString GetSignatures() const
 
static PCBEXPR_BUILTIN_FUNCTIONS & Instance()
 
The main frame for Pcbnew.
 
virtual COMMON_SETTINGS * GetCommonSettings() const
 
virtual const wxString AbsolutePath(const wxString &aFileName) const
Fix up aFileName if it is relative to the project's directory to be an absolute path and filename.
 
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()
 
Add cut/copy/paste, dark theme, autocomplete and brace highlighting to a wxStyleTextCtrl instance.
 
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
 
bool IsOK(wxWindow *aParent, const wxString &aMessage)
Display a yes/no dialog with aMessage and returns the user response.
 
This file is part of the common library.
 
static FILENAME_RESOLVER * resolver
 
static const std::string DesignRulesFileExtension
 
PCB_LAYER_ID
A quick note on layer IDs:
 
PGM_BASE & Pgm()
The global program "get" accessor.
 
std::vector< FAB_LAYER_COLOR > dummy
 
bool ConvertSmartQuotesAndDashes(wxString *aString)
Convert curly quotes and em/en dashes to straight quotes and dashes.
 
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
 
Definition of file extensions used in Kicad.