diff --git a/include/property.h b/include/property.h index cfce121088..f1044d2fbf 100644 --- a/include/property.h +++ b/include/property.h @@ -170,8 +170,10 @@ private: size_t nextId = 0; public: - PROPERTY_BASE( const wxString& aName, PROPERTY_DISPLAY aDisplay = DEFAULT ) - : m_id( nextId ), m_name( aName ), m_display( aDisplay ), + PROPERTY_BASE( const wxString& aName, PROPERTY_DISPLAY aDisplay = DEFAULT ) : + m_id( nextId ), + m_name( aName ), + m_display( aDisplay ), m_availFunc( [](INSPECTABLE*)->bool { return true; } ) { ++nextId; diff --git a/pcbnew/dialogs/panel_setup_rules.cpp b/pcbnew/dialogs/panel_setup_rules.cpp index 9da10518ba..93d3393493 100644 --- a/pcbnew/dialogs/panel_setup_rules.cpp +++ b/pcbnew/dialogs/panel_setup_rules.cpp @@ -70,11 +70,13 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent ) STRING, SEXPR_OPEN, SEXPR_TOKEN, + STRUCT_REF }; std::stack sexprs; wxString partial; int context = NONE; + int expr_context = NONE; for( ; i < currentPos; ++i ) { @@ -83,20 +85,39 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent ) if( c == '\\' ) { i++; // skip escaped char - continue; } - - if( context == STRING ) + else if( context == STRING ) { if( c == '"' ) + { context = NONE; + } else - partial += c; - - continue; + { + if( expr_context == STRING ) + { + if( c == '\'' ) + expr_context = NONE; + else + partial += c; + } + else if( c == '\'' ) + { + partial = wxEmptyString; + expr_context = STRING; + } + else if( c == '.' ) + { + partial = wxEmptyString; + expr_context = STRUCT_REF; + } + else + { + partial += c; + } + } } - - if( c == '"' ) + else if( c == '"' ) { partial = wxEmptyString; context = STRING; @@ -153,20 +174,42 @@ void PANEL_SETUP_RULES::onScintillaCharAdded( wxStyledTextEvent &aEvent ) tokens = "condition constraint disallow"; else if( sexprs.top() == "constraint" ) tokens = "max min opt"; - - if( !tokens.IsEmpty() ) - m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, ' ' ) ); } else if( context == SEXPR_TOKEN ) { - if( sexprs.top() == "constraint" ) + if( sexprs.empty() ) + /* badly formed grammar */; + else if( sexprs.top() == "constraint" ) tokens = "annulus_width clearance hole track_width"; else if( sexprs.top() == "disallow" ) tokens = "buried_via graphic hole micro_via pad text track via zone"; - - if( !tokens.IsEmpty() ) - m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, ' ' ) ); } + else if( context == STRING && expr_context == STRUCT_REF ) + { + if( !sexprs.empty() && sexprs.top() == "condition" ) + { + PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); + std::set propNames; + + for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() ) + { + const PROPERTY_LIST& props = propMgr.GetProperties( cls.type ); + + for( PROPERTY_BASE* prop : props ) + { + wxString ref( prop->Name() ); + ref.Replace( " ", "_" ); + propNames.insert( ref ); + } + } + + for( const wxString& propName : propNames ) + tokens += " " + propName; + } + } + + if( !tokens.IsEmpty() ) + m_scintillaTricks->DoAutocomplete( partial, wxSplit( tokens, ' ' ) ); } diff --git a/pcbnew/pcb_expr_evaluator.cpp b/pcbnew/pcb_expr_evaluator.cpp index 5d436c9dad..af98297104 100644 --- a/pcbnew/pcb_expr_evaluator.cpp +++ b/pcbnew/pcb_expr_evaluator.cpp @@ -156,16 +156,17 @@ LIBEVAL::UCODE::FUNC_PTR PCB_EXPR_UCODE::createFuncCall( LIBEVAL::COMPILER* aCom LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, - const std::string& var, const std::string& field ) + const std::string& aVar, + const std::string& aField ) { PROPERTY_MANAGER& propMgr = PROPERTY_MANAGER::Instance(); PCB_EXPR_VAR_REF* vref = nullptr; - if( var == "A" ) + if( aVar == "A" ) { vref = new PCB_EXPR_VAR_REF( 0 ); } - else if( var == "B" ) + else if( aVar == "B" ) { vref = new PCB_EXPR_VAR_REF( 1 ); } @@ -175,9 +176,12 @@ LIBEVAL::VAR_REF* PCB_EXPR_UCODE::createVarRef( LIBEVAL::COMPILER *aCompiler, return vref; } - if( field.empty() ) // return reference to base object + if( aField.empty() ) // return reference to base object return vref; + std::string field( aField ); + std::replace( field.begin(), field.end(), '_', ' '); + for( const PROPERTY_MANAGER::CLASS_INFO& cls : propMgr.GetAllClasses() ) { if( propMgr.IsOfType( cls.type, TYPE_HASH( BOARD_ITEM ) ) ) diff --git a/pcbnew/pcb_expr_evaluator.h b/pcbnew/pcb_expr_evaluator.h index a26aec007a..d5a2f40314 100644 --- a/pcbnew/pcb_expr_evaluator.h +++ b/pcbnew/pcb_expr_evaluator.h @@ -41,7 +41,7 @@ class PCB_EXPR_UCODE : public LIBEVAL::UCODE { public: virtual LIBEVAL::VAR_REF* createVarRef( LIBEVAL::COMPILER *aCompiler, - const std::string& var, const std::string& field ) override; + const std::string& aVar, const std::string& aField ) override; virtual FUNC_PTR createFuncCall( LIBEVAL::COMPILER* aCompiler, const std::string& name ) override;