27#include <wx/bmpbuttn.h>
28#include <wx/stattext.h>
31static constexpr const wxChar*
TRACE_COND = wxT(
"KI_TRACE_DRC_RULE_EDITOR" );
35 bool aTwoObjectConstraint ) :
41 wxLogTrace(
TRACE_COND, wxS(
"[DRC_RE_CONDITION_GROUP_PANEL] ctor START" ) );
45 wxString labelText = aTwoObjectConstraint ?
_(
"Where conditions match:" )
46 :
_(
"Where object matches:" );
47 m_labelText =
new wxStaticText(
this, wxID_ANY, labelText );
52 m_addBtn->SetToolTip(
_(
"Add another condition" ) );
71 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] expr='%s'" ), aConditionExpr );
80 if( aConditionExpr.IsEmpty() )
82 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] empty expression, setting to ANY" ) );
93 std::vector<std::pair<BOOL_OPERATOR, wxString>> parts;
97 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] tokenize failed, using single custom row" ) );
103 m_conditions[0].panel->ParseExpression( aConditionExpr );
108 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] tokenized into %zu parts" ), parts.size() );
111 for(
size_t i = 0; i < parts.size(); ++i )
113 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] part[%zu] op=%d expr='%s'" ),
114 i,
static_cast<int>( parts[i].first ), parts[i].second );
121 m_conditions[0].panel->ParseExpression( parts[i].second );
126 m_conditions.back().panel->ParseExpression( parts[i].second );
129 m_conditions.back().operatorChoice->SetSelection(
static_cast<int>( parts[i].first ) );
137 wxLogTrace(
TRACE_COND, wxS(
"[ParseCondition] done, HasCustomQuerySelected=%d" ),
148 wxString rowExpr =
m_conditions[i].panel->BuildExpression();
150 if( rowExpr.IsEmpty() )
175 bool hasCustom =
m_conditions[i].panel->HasCustomQuerySelected();
177 wxLogTrace(
TRACE_COND, wxS(
"[HasCustomQuerySelected] row[%zu] type=%d hasCustom=%d" ),
178 i,
static_cast<int>(
m_conditions[i].panel->GetConditionType() ), hasCustom ? 1 : 0 );
195 entry.
rowSizer =
new wxBoxSizer( wxHORIZONTAL );
200 wxArrayString operators;
201 operators.Add(
_(
"AND" ) );
202 operators.Add(
_(
"OR" ) );
203 operators.Add(
_(
"AND NOT" ) );
204 operators.Add(
_(
"OR NOT" ) );
206 entry.
operatorChoice =
new wxChoice(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize, operators );
212 opChoice->Bind( wxEVT_CHOICE,
213 [
this, opChoice]( wxCommandEvent& )
231 wxLogTrace(
TRACE_COND, wxS(
"[addConditionRow] creating row panel" ) );
233 wxLogTrace(
TRACE_COND, wxS(
"[addConditionRow] adding row panel to rowSizer" ) );
262 if( wxWindow* parent = GetParent() )
269 if( aIndex < 0 || aIndex >=
static_cast<int>(
m_conditions.size() ) )
284 entry.
panel->Destroy();
292 int newIndex =
static_cast<int>( i );
306 if( wxWindow* parent = GetParent() )
339 entry.panel->ShowDeleteButton( showDelete );
344 const wxString& aExpr, std::vector<std::pair<BOOL_OPERATOR, wxString>>& aParts )
346 wxString remaining = aExpr;
350 while( !remaining.IsEmpty() )
352 remaining.Trim(
false );
354 if( remaining.IsEmpty() )
360 if( remaining.StartsWith(
"&&" ) )
362 remaining = remaining.Mid( 2 ).Trim(
false );
364 if( remaining.StartsWith(
"!" ) )
367 remaining = remaining.Mid( 1 ).Trim(
false );
374 else if( remaining.StartsWith(
"||" ) )
376 remaining = remaining.Mid( 2 ).Trim(
false );
378 if( remaining.StartsWith(
"!" ) )
381 remaining = remaining.Mid( 1 ).Trim(
false );
397 bool inQuote =
false;
400 for(
size_t i = 0; i < remaining.length(); ++i )
402 wxChar c = remaining[i];
404 if( c ==
'\\' && i + 1 < remaining.length() )
425 if( depth == 0 && i + 1 < remaining.length() )
427 if( remaining.Mid( i, 2 ) ==
"&&" || remaining.Mid( i, 2 ) ==
"||" )
436 end = remaining.length();
438 wxString part = remaining.Left(
end ).Trim(
true ).Trim(
false );
439 aParts.push_back( { nextOp, part } );
441 remaining = remaining.Mid(
end );
445 return !aParts.empty();
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Information pertinent to a Pcbnew printed circuit board.
std::vector< CONDITION_ENTRY > m_conditions
bool HasCustomQuerySelected() const
wxStaticText * m_labelText
std::function< void()> m_changeCallback
void onAddClicked(wxCommandEvent &aEvent)
bool tokenizeCondition(const wxString &aExpr, std::vector< std::pair< BOOL_OPERATOR, wxString > > &aParts)
Tokenize a condition expression by boolean operators.
void ParseCondition(const wxString &aConditionExpr)
Parse a condition string and populate the UI.
DRC_RE_CONDITION_GROUP_PANEL(wxWindow *aParent, BOARD *aBoard, bool aTwoObjectConstraint)
STD_BITMAP_BUTTON * m_addBtn
void addConditionRow(BOOL_OPERATOR aOp=BOOL_OPERATOR::AND)
void removeConditionRow(int aIndex)
wxString BuildCondition() const
Build a condition string from the current UI state.
bool m_twoObjectConstraint
void updateDeleteButtonVisibility()
A single condition row in the condition group panel.
void SetDeleteCallback(std::function< void()> aCallback)
void SetChangeCallback(std::function< void()> aCallback)
static constexpr const wxChar * TRACE_COND
DRC_RE_CONDITION_ROW_PANEL * panel
wxChoice * operatorChoice
wxString result
Test unit parsing edge cases and error handling.