KiCad PCB EDA Suite
Loading...
Searching...
No Matches
rule_editor_dialog_base.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20
22#include <widgets/wx_infobar.h>
23#include <widgets/wx_panel.h>
24#include <widgets/ui_common.h>
25
26#include <wx/button.h>
27#include <wx/grid.h>
28#include <wx/sizer.h>
29#include <wx/treectrl.h>
30#include <wx/listctrl.h>
31#include <wx/stc/stc.h>
32#include <wx/menu.h>
33#include <wx/log.h>
34#include <wx/dragimag.h> // For wxDragImage
35#include <wx/wx.h>
36#include <wx/dnd.h>
37#include <wx/dcmemory.h> // Include for wxMemoryDC
38#include <wx/dcclient.h> // Include for wxClientDC if needed
39#include <wx/dcbuffer.h> // Include for double-buffered drawing
40#include <wx/bitmap.h>
41
42#include <confirm.h>
43#include <paths.h>
44#include <bitmaps.h>
45#include <launch_ext.h>
46#include <algorithm>
48
49
50static wxSearchCtrl* CreateTextFilterBox( wxWindow* aParent, const wxString& aDescriptiveText )
51{
52 wxSearchCtrl* search_widget = new wxSearchCtrl( aParent, wxID_ANY );
53
54 search_widget->ShowSearchButton( false );
55 search_widget->ShowCancelButton( true );
56
57 search_widget->SetDescriptiveText( aDescriptiveText );
58
59#ifdef __WXGTK__
60 // wxSearchCtrl vertical height is not calculated correctly on some GTK setups
61 // See https://gitlab.com/kicad/code/kicad/-/issues/9019
62 search_widget->SetMinSize( wxSize( -1, aParent->GetTextExtent( wxT( "qb" ) ).y + 10 ) );
63#endif
64
65 return search_widget;
66}
67
68
69RULE_EDITOR_DIALOG_BASE::RULE_EDITOR_DIALOG_BASE( wxWindow* aParent, const wxString& aTitle,
70 const wxSize& aInitialSize ) :
71 DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, aInitialSize,
72 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
73 m_isDragging( false ),
74 m_enableMoveUp( false ),
75 m_enableMoveDown( false ),
76 m_enableAddRule( false ),
77 m_enableDuplicateRule( false ),
78 m_enableDeleteRule( false ),
79 m_modified( false ),
81 m_title( aTitle ),
82 m_selectedData( nullptr ),
83 m_previousId( nullptr ),
84 m_draggedItem( nullptr ),
85 m_dragImage( nullptr )
86{
87 wxBoxSizer* mainSizer = new wxBoxSizer( wxVERTICAL );
88 SetSizer( mainSizer );
89
90 wxBoxSizer* infoBarSizer = new wxBoxSizer( wxHORIZONTAL );
91
92 m_infoBar = new WX_INFOBAR( this );
93 infoBarSizer->Add( m_infoBar, 0, wxEXPAND, 0 );
94
95 // Add the tree panel to the content sizer
96 m_splitter = new wxSplitterWindow( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
97 wxSP_3D | wxSP_LIVE_UPDATE | wxSP_3DSASH );
98 m_splitter->SetMinimumPaneSize( 50 ); // Set a minimum pane size
99
100 // Create the tree control panel
101 WX_PANEL* treeCtrlPanel =
102 new WX_PANEL( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxBORDER_NONE | wxTAB_TRAVERSAL );
103 treeCtrlPanel->SetBorders( true, true, true, true );
104 wxBoxSizer* treeCtrlSizer = new wxBoxSizer( wxVERTICAL );
105 treeCtrlPanel->SetSizer( treeCtrlSizer );
106
107 // Add a search text box above the tree control
108 m_filterSearch = CreateTextFilterBox( treeCtrlPanel, _( "Type filter text" ) );
109 treeCtrlSizer->Add( m_filterSearch, 0, wxEXPAND | wxBOTTOM, 5 );
110
111 // Create the tree control and set its font
112 m_ruleTreeCtrl = new wxTreeCtrl( treeCtrlPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
113 wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS );
114 m_ruleTreeCtrl->SetFont( KIUI::GetControlFont( this ) );
115
116 // Adjust the tree control's window style to remove the border
117 long treeCtrlFlags = m_ruleTreeCtrl->GetWindowStyleFlag();
118 treeCtrlFlags = ( treeCtrlFlags & ~wxBORDER_MASK ) | wxBORDER_NONE;
119 m_ruleTreeCtrl->SetWindowStyleFlag( treeCtrlFlags );
120
121 // Add the tree control to its sizer
122 treeCtrlSizer->Add( m_ruleTreeCtrl, 1, wxEXPAND | wxBOTTOM, 5 );
123
124 // Create a sizer for the action buttons
125 wxBoxSizer* actionButtonsSizer = new wxBoxSizer( wxHORIZONTAL );
126
127 // Create the action buttons
129 new wxBitmapButton( treeCtrlPanel, wxID_ANY, KiBitmapBundle( BITMAPS::small_plus ),
130 wxDefaultPosition, wxDefaultSize, 0 );
131 m_copyRuleButton = new wxBitmapButton( treeCtrlPanel, wxID_ANY, KiBitmapBundle( BITMAPS::copy ),
132 wxDefaultPosition, wxDefaultSize, 0 );
134 new wxBitmapButton( treeCtrlPanel, wxID_ANY, KiBitmapBundle( BITMAPS::small_up ),
135 wxDefaultPosition, wxDefaultSize, 0 );
137 new wxBitmapButton( treeCtrlPanel, wxID_ANY, KiBitmapBundle( BITMAPS::small_down ),
138 wxDefaultPosition, wxDefaultSize, 0 );
140 new wxBitmapButton( treeCtrlPanel, wxID_ANY, KiBitmapBundle( BITMAPS::small_trash ),
141 wxDefaultPosition, wxDefaultSize, 0 );
142
143 actionButtonsSizer->Add( m_addRuleButton, 0, wxLEFT | wxRIGHT, 5 );
144 actionButtonsSizer->Add( m_copyRuleButton, 0, wxLEFT | wxRIGHT, 5 );
145 actionButtonsSizer->Add( m_moveTreeItemUpButton, 0, wxLEFT | wxRIGHT, 5 );
146 actionButtonsSizer->Add( m_moveTreeItemDownButton, 0, wxLEFT | wxRIGHT, 5 );
147
148 // Add a spacer between the "Move" buttons and the "Delete" button
149 actionButtonsSizer->AddStretchSpacer( 1 ); // Spacer between the Move and Delete buttons
150
151 // Add the "Delete" button at the end
152 actionButtonsSizer->Add( m_deleteRuleButton, 0, wxRIGHT, 5 );
153
154 // Add the action buttons sizer to the tree control sizer
155 treeCtrlSizer->Add( actionButtonsSizer, 0, wxBOTTOM | wxEXPAND, 5 );
156
157 treeCtrlPanel->Layout();
158
159 // Create a scrolled window for the dynamic content panel
160 m_scrolledContentWin = new wxScrolledWindow( m_splitter, wxID_ANY, wxDefaultPosition,
161 wxDefaultSize, wxVSCROLL | wxBORDER_NONE );
162 m_scrolledContentWin->SetScrollRate( 0, 10 );
163 m_scrolledContentWin->SetBackgroundColour(
164 wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
165 m_contentPanel = nullptr;
166
167 // Add the tree control panel to the splitter.
168 // Calculate the minimum tree panel width based on the tree control's best size.
169 treeCtrlPanel->Layout();
170 int minTreeWidth = treeCtrlPanel->GetBestSize().GetWidth();
171
172 // Ensure a reasonable minimum width for the tree panel
173 if( minTreeWidth < 200 )
174 minTreeWidth = 200;
175
176 m_defaultSashPosition = minTreeWidth;
177
178 m_splitter->SplitVertically( treeCtrlPanel, m_scrolledContentWin, m_defaultSashPosition );
179
180 // Set gravity to 0 so the tree panel maintains its size and the content panel resizes
181 m_splitter->SetSashGravity( 0.0 );
182
183 wxBoxSizer* m_sizerButtons = new wxBoxSizer( wxHORIZONTAL );
184
185 wxStdDialogButtonSizer* m_sdbSizer = new wxStdDialogButtonSizer();
186 m_cancelRuleButton = new wxButton( this, wxID_CANCEL );
187 m_cancelRuleButton->SetLabelText( _( "Close" ) );
188 m_sdbSizer->AddButton( m_cancelRuleButton );
189 m_saveRuleButton = new wxButton( this, wxID_OK );
190 m_saveRuleButton->SetLabelText( _( "Save" ) );
191 m_sdbSizer->AddButton( m_saveRuleButton );
192 m_sdbSizer->Realize();
193
194 m_sizerButtons->Add( m_sdbSizer, 1, wxEXPAND, 5 );
195
196
197 // Add the info bar sizer to the main sizer
198 mainSizer->Add( infoBarSizer, 0, wxEXPAND, 0 );
199 mainSizer->Add( m_splitter, 1, wxEXPAND | wxBOTTOM, 5 );
200 mainSizer->Add( m_sizerButtons, 0, wxALL | wxEXPAND, 5 );
201 if( aInitialSize != wxDefaultSize )
202 SetSize( aInitialSize );
203
204 Layout();
205
206 // Bind the context menu event
207 m_filterSearch->Bind( wxEVT_COMMAND_TEXT_UPDATED, &RULE_EDITOR_DIALOG_BASE::onFilterSearch,
208 this );
209 m_ruleTreeCtrl->Bind( wxEVT_TREE_ITEM_RIGHT_CLICK,
211 m_ruleTreeCtrl->Bind( wxEVT_TREE_SEL_CHANGED,
213 m_ruleTreeCtrl->Bind( wxEVT_TREE_ITEM_ACTIVATED,
218
221 this );
223 this );
224 m_moveTreeItemDownButton->Bind( wxEVT_BUTTON,
227 this );
228 m_saveRuleButton->Bind( wxEVT_BUTTON, &RULE_EDITOR_DIALOG_BASE::OnSave, this );
229 m_cancelRuleButton->Bind( wxEVT_BUTTON, &RULE_EDITOR_DIALOG_BASE::OnCancel, this );
230
231 // Initially disable Save button until modifications are made
232 m_saveRuleButton->Enable( false );
233
234 this->Bind( wxEVT_SIZE, &RULE_EDITOR_DIALOG_BASE::onResize, this );
235
236 this->Bind( wxEVT_CLOSE_WINDOW, &RULE_EDITOR_DIALOG_BASE::onClose, this );
237
238 m_scrolledContentWin->Bind( wxEVT_SIZE,
239 [this]( wxSizeEvent& evt )
240 {
242 evt.Skip();
243 } );
244}
245
246
248{
250
251 // finishDialogSettings() calls GetSizer()->SetSizeHints() which inflates the dialog
252 // to the full unconstrained best size of the scrolled content area. Reset to the
253 // caller's initial size and a reasonable minimum so Show() doesn't inherit the
254 // inflated values.
255 SetMinSize( wxSize( 400, 500 ) );
256 SetSize( m_initialSize );
257
258 wxLogTrace( "debug_dlg_size", "finishInitialization: size=%dx%d minSize=%dx%d bestSize=%dx%d",
259 GetSize().x, GetSize().y, GetMinSize().x, GetMinSize().y, GetBestSize().x,
260 GetBestSize().y );
261}
262
263
265{
266 bool ret = DIALOG_SHIM::Show( show );
267
268 if( show )
269 {
270 // DIALOG_SHIM::Show() sets SetMinSize(GetBestSize()) which includes the unconstrained
271 // height of the scrolled content area. Cap the minimum to a usable value so the user
272 // can resize the dialog smaller.
273 wxSize minSize = GetMinSize();
274
275 if( minSize.GetHeight() > 500 )
276 SetMinSize( wxSize( minSize.GetWidth(), 500 ) );
277
278 wxLogTrace( "debug_dlg_size", "Show: size=%dx%d minSize=%dx%d",
279 GetSize().x, GetSize().y, GetMinSize().x, GetMinSize().y );
280 }
281
282 return ret;
283}
284
285
287{
288 m_filterSearch->Unbind( wxEVT_COMMAND_TEXT_UPDATED, &RULE_EDITOR_DIALOG_BASE::onFilterSearch, this );
289 m_ruleTreeCtrl->Unbind( wxEVT_TREE_ITEM_RIGHT_CLICK, &RULE_EDITOR_DIALOG_BASE::onRuleTreeItemRightClick, this );
290 m_ruleTreeCtrl->Unbind( wxEVT_TREE_SEL_CHANGED, &RULE_EDITOR_DIALOG_BASE::onRuleTreeItemSelectionChanged, this );
291 m_ruleTreeCtrl->Unbind( wxEVT_TREE_ITEM_ACTIVATED, &RULE_EDITOR_DIALOG_BASE::onRuleTreeItemActivated, this );
292 m_ruleTreeCtrl->Unbind( wxEVT_LEFT_DOWN, &RULE_EDITOR_DIALOG_BASE::onRuleTreeItemLeftDown, this );
294 m_ruleTreeCtrl->Unbind( wxEVT_LEFT_UP, &RULE_EDITOR_DIALOG_BASE::onRuleTreeItemLeftUp, this );
295
301 m_saveRuleButton->Unbind( wxEVT_BUTTON, &RULE_EDITOR_DIALOG_BASE::OnSave, this );
302 m_cancelRuleButton->Unbind( wxEVT_BUTTON, &RULE_EDITOR_DIALOG_BASE::OnCancel, this );
303
304 this->Unbind( wxEVT_SIZE, &RULE_EDITOR_DIALOG_BASE::onResize, this );
305 this->Unbind( wxEVT_CLOSE_WINDOW, &RULE_EDITOR_DIALOG_BASE::onClose, this );
306
307 m_selectedData = nullptr;
308 m_previousId = nullptr;
309
310 if( m_dragImage )
311 {
312 delete m_dragImage;
313 m_dragImage = nullptr;
314 }
315}
316
317
319{
321
322 // Call TransferDataToWindow() only once:
323 // this is enough on wxWidgets 3.1
324 if( !DIALOG_SHIM::TransferDataToWindow() )
325 return false;
326
327 return true;
328}
329
330
332{
333 bool ret = true;
334
335 // Call TransferDataFromWindow() only once:
336 // this is enough on wxWidgets 3.1
337 if( !DIALOG_SHIM::TransferDataFromWindow() )
338 ret = false;
339
340 return ret;
341}
342
343
345{
346 if( aEvt.GetKeyCode() == 'S' && aEvt.ControlDown() && !aEvt.ShiftDown() && !aEvt.AltDown() )
347 {
348 wxCommandEvent evt;
349 OnSave( evt );
350 return;
351 }
352
354}
355
356
358{
359 while( aParent )
360 {
361 if( RULE_EDITOR_DIALOG_BASE* currentDialog =
362 dynamic_cast<RULE_EDITOR_DIALOG_BASE*>( aParent ) )
363 return currentDialog;
364
365 aParent = aParent->GetParent();
366 }
367
368 return nullptr;
369}
370
371
372void RULE_EDITOR_DIALOG_BASE::InitRuleTreeItems( const std::vector<RULE_TREE_NODE>& aNodes )
373{
374 if( aNodes.empty() )
375 return;
376
377 m_defaultTreeItems = aNodes;
378
379 wxTreeItemId rootId = m_ruleTreeCtrl->AddRoot( aNodes[0].m_nodeName );
380
381 RULE_TREE_ITEM_DATA* itemData =
382 new RULE_TREE_ITEM_DATA( aNodes[0].m_nodeId, nullptr, rootId );
383 m_ruleTreeCtrl->SetItemData( rootId, itemData );
384
385 std::vector<RULE_TREE_NODE> childNodes;
386 getRuleTreeChildNodes( aNodes, aNodes[0].m_nodeId, childNodes );
387
388 for( const auto& child : childNodes )
389 {
390 populateRuleTreeCtrl( aNodes, child, rootId );
391 }
392
393 m_treeHistoryData.clear();
394 saveRuleTreeState( m_ruleTreeCtrl->GetRootItem(), m_defaultTreeItems[0].m_nodeId );
395
396 m_ruleTreeCtrl->SelectItem( m_ruleTreeCtrl->GetFirstVisibleItem() );
397 m_ruleTreeCtrl->CollapseAll();
398}
399
400
401void RULE_EDITOR_DIALOG_BASE::SetContentPanel( wxPanel* aContentPanel )
402{
403 if( m_contentPanel )
404 {
406 m_contentPanel->Destroy();
407 m_contentPanel = nullptr;
408 }
409
410 m_contentPanel = aContentPanel;
411 m_scrolledContentWin->SetBackgroundColour( m_contentPanel->GetBackgroundColour() );
412
414
415 Layout();
416 CallAfter( [this]() { RefreshContentScrollArea(); } );
417 Refresh();
418}
419
420
422{
424 return;
425
426 m_contentPanel->Layout();
427
428 wxSize clientSize = m_scrolledContentWin->GetClientSize();
429 wxSize bestSize = m_contentPanel->GetBestSize();
430 int width = clientSize.GetWidth();
431 int height = std::max( clientSize.GetHeight(), bestSize.GetHeight() );
432
433 m_contentPanel->SetSize( width, height );
434 m_scrolledContentWin->SetVirtualSize( width, height );
435 m_scrolledContentWin->Refresh();
436}
437
438
440 wxTreeItemId aParent )
441{
442 wxTreeItemId currentTreeItemId = appendRuleTreeItem( aNode, aParent );
443
444 auto it = m_treeHistoryData.find( aNode.m_nodeData->GetParentId() );
445
446 if( it != m_treeHistoryData.end() )
447 {
448 std::vector<int>& existingChildren = std::get<1>( it->second );
449 existingChildren.push_back( aNode.m_nodeId );
450
451 m_treeHistoryData[aNode.m_nodeId] = { aNode.m_nodeName,
452 {},
453 currentTreeItemId };
454 }
455
456 m_ruleTreeCtrl->SelectItem( currentTreeItemId );
457}
458
459
460void RULE_EDITOR_DIALOG_BASE::UpdateRuleTreeItemText( wxTreeItemId aItemId, wxString aItemText )
461{
462 m_ruleTreeCtrl->SetItemText( aItemId, aItemText );
463}
464
465
467{
468 m_ruleTreeCtrl->Enable( aEnable );
469 m_filterSearch->Enable( aEnable );
470
472
474 {
475 if( !aEnable )
476 {
477 m_cancelRuleButton->SetLabelText( _( "Cancel" ) );
478 }
479 else if( m_modified )
480 {
481 m_cancelRuleButton->SetLabelText( _( "Discard" ) );
482 }
483 else
484 {
485 m_cancelRuleButton->SetLabelText( _( "Close" ) );
486 }
487 }
488}
489
490
492{
493 m_modified = true;
494
495 if( m_saveRuleButton )
496 m_saveRuleButton->Enable( true );
497
498 if( m_cancelRuleButton && m_ruleTreeCtrl->IsEnabled() )
499 m_cancelRuleButton->SetLabelText( _( "Discard" ) );
500}
501
502
504{
505 m_modified = false;
506
507 if( m_saveRuleButton )
508 m_saveRuleButton->Enable( false );
509
510 if( m_cancelRuleButton && m_ruleTreeCtrl->IsEnabled() )
511 m_cancelRuleButton->SetLabelText( _( "Close" ) );
512}
513
514
515void RULE_EDITOR_DIALOG_BASE::DeleteRuleTreeItem( wxTreeItemId aItemId, const int& aNodeId )
516{
517 m_ruleTreeCtrl->Delete( aItemId );
518 m_treeHistoryData.erase( aNodeId );
519}
520
521
523 const std::vector<RULE_TREE_NODE>& aNodes, const RULE_TREE_NODE& aNode,
524 wxTreeItemId aParent )
525{
526 wxTreeItemId currentId = appendRuleTreeItem( aNode, aParent );
527
528 std::vector<RULE_TREE_NODE> childNodes;
529 getRuleTreeChildNodes( aNodes, aNode.m_nodeId, childNodes );
530
531 for( const auto& child : childNodes )
532 {
533 populateRuleTreeCtrl( aNodes, child, currentId );
534 }
535
536 m_ruleTreeCtrl->Expand( currentId );
537}
538
539
541{
542 wxTreeItemId item = aEvent.GetItem();
543
544 if( !item.IsOk() )
545 return;
546
547 m_ruleTreeCtrl->SelectItem( item );
548
549 RULE_TREE_ITEM_DATA* ruleTreeItemData =
550 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( item ) );
551
552 if( !ruleTreeItemData )
553 return;
554
555 updateRuleTreeActionButtonsState( ruleTreeItemData );
556
557 wxMenu menu;
558
559 if( m_enableAddRule )
560 KIUI::AddMenuItem( &menu, ID_NEWRULE, _( "New Rule" ), KiBitmap( BITMAPS::small_plus ) );
561
562 if( m_enableAddRule )
563 KIUI::AddMenuItem( &menu, ID_COPYRULE, _( "Copy Rule" ), KiBitmap( BITMAPS::copy ) );
564
566 KIUI::AddMenuItem( &menu, ID_DELETERULE, _( "Delete Rule" ),
568
569 if( isEnabled( ruleTreeItemData,
571 && m_enableMoveUp )
572 KIUI::AddMenuItem( &menu, ID_MOVEUP, _( "Move Up" ), KiBitmap( BITMAPS::small_up ) );
573
574 if( isEnabled( ruleTreeItemData,
577 KIUI::AddMenuItem( &menu, ID_MOVEDOWN, _( "Move Down" ), KiBitmap( BITMAPS::small_down ) );
578
579 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
580 [&]( wxCommandEvent& aCmd )
581 {
582 switch( aCmd.GetId() )
583 {
584 case ID_NEWRULE: onNewRuleOptionClick( aCmd ); break;
585
586 case ID_COPYRULE: onDuplicateRuleOptionClick( aCmd ); break;
587
588 case ID_DELETERULE: onDeleteRuleOptionClick( aCmd ); break;
589
590 case ID_MOVEUP: onMoveUpRuleOptionClick( aCmd ); break;
591
592 case ID_MOVEDOWN: onMoveDownRuleOptionClick( aCmd ); break;
593 default: aCmd.Skip();
594 }
595 } );
596
597 PopupMenu( &menu );
598}
599
600
602{
603 wxTreeItemId selectedItem = aEvent.GetItem();
604
605 RULE_TREE_ITEM_DATA* selectedItemData =
606 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( selectedItem ) );
607
608 if( !selectedItemData )
609 return;
610
611 if( m_selectedData )
612 {
613 if( m_selectedData->GetNodeId() == selectedItemData->GetNodeId() )
614 {
615 m_selectedData = selectedItemData;
616 updateRuleTreeActionButtonsState( selectedItemData );
617 return;
618 }
619
620 m_previousId = m_selectedData->GetTreeItemId();
621 }
622
623 m_selectedData = selectedItemData;
624
626
627 updateRuleTreeActionButtonsState( selectedItemData );
628}
629
631{
632 RULE_TREE_ITEM_DATA* itemData =
633 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( aEvent.GetItem() ) );
634
635 if( itemData &&
637 {
638 AddNewRule( itemData );
639 }
640}
641
642
644{
646}
647
648
653
654
656{
657 RemoveRule( m_selectedData->GetNodeId() );
658}
659
660
662{
663 if( !m_enableMoveUp )
664 return;
665
666 wxTreeItemId selectedItem = m_ruleTreeCtrl->GetSelection();
667 if( !selectedItem.IsOk() )
668 return;
669
670 wxTreeItemId parent = m_ruleTreeCtrl->GetItemParent( selectedItem );
671
672 if( !parent.IsOk() )
673 return;
674
675 wxTreeItemIdValue cookie;
676 wxTreeItemId current = m_ruleTreeCtrl->GetFirstChild( parent, cookie );
677 wxTreeItemId previous;
678 wxTreeItemId beforePrevious;
679
680 while( current.IsOk() && current != selectedItem )
681 {
682 beforePrevious = previous;
683 previous = current;
684 current = m_ruleTreeCtrl->GetNextChild( parent, cookie );
685 }
686
687 if( !previous.IsOk() )
688 {
689 return;
690 }
691
692 wxTreeItemId insertPosition = beforePrevious.IsOk() ? beforePrevious : wxTreeItemId();
693
694 wxTreeItemId newItem = m_ruleTreeCtrl->InsertItem(
695 parent, insertPosition, m_ruleTreeCtrl->GetItemText( selectedItem ) );
696
697 moveRuleTreeItemChildrensTooOnDrag( selectedItem, newItem );
698
699 wxTreeItemData* itemData = m_ruleTreeCtrl->GetItemData( selectedItem );
700
701 if( itemData )
702 {
703 RULE_TREE_ITEM_DATA* ruleTreeItemData = dynamic_cast<RULE_TREE_ITEM_DATA*>( itemData );
704 ruleTreeItemData->SetTreeItemId( newItem );
705
706 m_ruleTreeCtrl->SetItemData( newItem, itemData );
707 m_ruleTreeCtrl->SetItemData( selectedItem, nullptr ); // Detach data from the old item
708
709 saveRuleTreeState( newItem, ruleTreeItemData->GetNodeId() );
710
711 m_ruleTreeCtrl->SelectItem( newItem );
712
713 m_ruleTreeCtrl->Expand( newItem );
714 m_ruleTreeCtrl->ExpandAllChildren( newItem );
715 }
716
717 m_ruleTreeCtrl->DeleteChildren( selectedItem );
718 m_ruleTreeCtrl->Delete( selectedItem );
719}
720
721
723{
724 if( !m_enableMoveDown )
725 return;
726
727 wxTreeItemId selectedItem = m_ruleTreeCtrl->GetSelection();
728
729 if( !selectedItem.IsOk() )
730 return;
731
732 wxTreeItemId parent = m_ruleTreeCtrl->GetItemParent( selectedItem );
733 wxTreeItemIdValue cookie;
734 wxTreeItemId current = m_ruleTreeCtrl->GetFirstChild( parent, cookie );
735
736 while( current.IsOk() && current != selectedItem )
737 {
738 current = m_ruleTreeCtrl->GetNextChild( parent, cookie );
739 }
740
741 wxTreeItemId next = m_ruleTreeCtrl->GetNextChild( parent, cookie );
742
743 if( !next.IsOk() )
744 {
745 return;
746 }
747
748 wxString itemText = m_ruleTreeCtrl->GetItemText( selectedItem );
749 wxTreeItemData* itemData = m_ruleTreeCtrl->GetItemData( selectedItem );
750
751 wxTreeItemId newItem = m_ruleTreeCtrl->InsertItem( parent, next, itemText );
752
753 moveRuleTreeItemChildrensTooOnDrag( selectedItem, newItem );
754
755 if( itemData )
756 {
757 RULE_TREE_ITEM_DATA* ruleTreeItemData = dynamic_cast<RULE_TREE_ITEM_DATA*>( itemData );
758 ruleTreeItemData->SetTreeItemId( newItem );
759
760 m_ruleTreeCtrl->SetItemData( newItem, itemData );
761 m_ruleTreeCtrl->SetItemData( selectedItem, nullptr ); // Detach data
762
763 saveRuleTreeState( newItem, ruleTreeItemData->GetNodeId() );
764
765 m_ruleTreeCtrl->SelectItem( newItem );
766
767 m_ruleTreeCtrl->Expand( newItem );
768 }
769
770 m_ruleTreeCtrl->DeleteChildren( selectedItem );
771 m_ruleTreeCtrl->Delete( selectedItem );
772}
773
774
776{
777 wxPoint pt = aEvent.GetPosition();
778 int flags;
779 wxTreeItemId item = m_ruleTreeCtrl->HitTest( pt, flags );
780
781 // Check if click is on the expand/collapse button
782 if( flags & wxTREE_HITTEST_ONITEMBUTTON )
783 {
784 // Prevent wxEVT_LEFT_DOWN from propagating further
785 aEvent.Skip();
786 return;
787 }
788
789 if( item.IsOk() )
790 {
791 m_draggedItem = item;
792
793 wxString text = m_ruleTreeCtrl->GetItemText( item );
794 wxMemoryDC dc;
795 wxBitmap bitmap( 200, 30 );
796 dc.SelectObject( bitmap );
797 dc.SetBackground( *wxWHITE_BRUSH );
798 dc.Clear();
799 dc.SetFont( *wxNORMAL_FONT );
800 dc.DrawText( text, 5, 5 );
801 dc.SelectObject( wxNullBitmap );
802
803 m_dragImage = new wxDragImage( bitmap );
804 m_isDragging = false;
805 }
806
807 aEvent.Skip();
808}
809
810
812{
813 if( aEvent.Dragging() && m_draggedItem.IsOk() && m_dragImage )
814 {
815 wxPoint currentPos = aEvent.GetPosition();
816
817 if( !m_isDragging )
818 {
819 if( !m_dragImage->BeginDrag( wxPoint( 0, 0 ), m_ruleTreeCtrl, true ) )
820 {
821 delete m_dragImage;
822 m_dragImage = nullptr;
823 return;
824 }
825
826 m_dragImage->Show();
827 m_isDragging = true;
828 }
829 else
830 {
831 m_dragImage->Move( currentPos );
832 }
833 }
834
835 aEvent.Skip();
836}
837
838
840{
841 if( m_draggedItem.IsOk() && m_isDragging )
842 {
843 if( m_dragImage )
844 {
845 m_dragImage->Hide();
846 m_dragImage->EndDrag();
847 delete m_dragImage;
848 m_dragImage = nullptr;
849 m_isDragging = false;
850 }
851
852 wxPoint pos = aEvent.GetPosition();
853 int flags;
854 wxTreeItemId targetItem = m_ruleTreeCtrl->HitTest( pos, flags );
855
856 if( !targetItem.IsOk() )
857 return;
858
859 wxTreeItemId draggedParent = m_ruleTreeCtrl->GetItemParent( m_draggedItem );
860 wxTreeItemId targetParent = m_ruleTreeCtrl->GetItemParent( targetItem );
861
862 if( draggedParent != targetParent )
863 return;
864
865 if( draggedParent == targetParent )
866 {
867 wxTreeItemId newItem;
868 wxTreeItemIdValue cookie;
869
870 if( flags & wxTREE_HITTEST_ONITEMLABEL
871 && targetItem == m_ruleTreeCtrl->GetFirstChild( targetParent, cookie ) )
872 {
873 // Prepend item as the first child of target parent
874 newItem = m_ruleTreeCtrl->PrependItem(
875 targetParent, m_ruleTreeCtrl->GetItemText( m_draggedItem ) );
876 }
877 else
878 {
879 wxTreeItemId current = m_ruleTreeCtrl->GetFirstChild( targetParent, cookie );
880 wxTreeItemId previous;
881
882 // Traverse through siblings to find the position of the target item
883 while( current.IsOk() && current != targetItem )
884 {
885 previous = current;
886 current = m_ruleTreeCtrl->GetNextChild( targetParent, cookie );
887 }
888
889 if( !previous.IsOk() )
890 {
891 // If no previous item, insert as the first child
892 newItem = m_ruleTreeCtrl->PrependItem(
893 targetParent, m_ruleTreeCtrl->GetItemText( m_draggedItem ) );
894 }
895 else
896 {
897 wxTreeItemId nextSibling = m_ruleTreeCtrl->GetNextChild( targetParent, cookie );
898
899 if( nextSibling.IsOk() )
900 {
901 // If there is a next sibling, insert after the previous item
902 newItem = m_ruleTreeCtrl->InsertItem(
903 targetParent, previous,
904 m_ruleTreeCtrl->GetItemText( m_draggedItem ) );
905 }
906 else
907 {
908 // If no next sibling, append the item as the last child
909 newItem = m_ruleTreeCtrl->AppendItem(
910 targetParent, m_ruleTreeCtrl->GetItemText( m_draggedItem ) );
911 }
912 }
913 }
914
916
917 wxTreeItemData* itemData = m_ruleTreeCtrl->GetItemData( m_draggedItem );
918
919 if( itemData )
920 {
921 RULE_TREE_ITEM_DATA* ruleTreeItemData =
922 dynamic_cast<RULE_TREE_ITEM_DATA*>( itemData );
923 ruleTreeItemData->SetTreeItemId( newItem );
924
925 m_ruleTreeCtrl->SetItemData( newItem, ruleTreeItemData );
926 m_ruleTreeCtrl->SetItemData( m_draggedItem, nullptr );
927
928 saveRuleTreeState( newItem, ruleTreeItemData->GetNodeId() );
929
930 m_ruleTreeCtrl->SelectItem( newItem );
931
932 m_ruleTreeCtrl->Expand( newItem );
933 }
934
935 m_ruleTreeCtrl->DeleteChildren( m_draggedItem );
936 m_ruleTreeCtrl->Delete( m_draggedItem );
937 }
938
939 m_draggedItem = nullptr;
940 }
941
942 aEvent.Skip();
943}
944
945
946void RULE_EDITOR_DIALOG_BASE::onFilterSearch( wxCommandEvent& aEvent )
947{
948 const auto searchStr = aEvent.GetString().Lower();
949
950 m_ruleTreeCtrl->DeleteAllItems();
951
952 restoreRuleTree( nullptr, m_defaultTreeItems[0].m_nodeId );
953
954 wxTreeItemId root = m_ruleTreeCtrl->GetRootItem();
955
956 if( root.IsOk() )
957 {
958 filterRuleTree( root, searchStr );
959 }
960}
961
962
963bool RULE_EDITOR_DIALOG_BASE::filterRuleTree( const wxTreeItemId& aItem, const wxString& aFilter )
964{
965 bool matches = m_ruleTreeCtrl->GetItemText( aItem ).Lower().Contains( aFilter );
966
967 wxTreeItemIdValue cookie;
968 wxTreeItemId child = m_ruleTreeCtrl->GetFirstChild( aItem, cookie );
969 bool hasVisibleChildren = false;
970
971 std::vector<wxTreeItemId> itemsToDelete;
972
973 while( child.IsOk() )
974 {
975 if( filterRuleTree( child, aFilter ) )
976 {
977 hasVisibleChildren = true;
978 }
979 else
980 {
981 itemsToDelete.push_back( child );
982 }
983
984 child = m_ruleTreeCtrl->GetNextChild( aItem, cookie );
985 }
986
987 for( const auto& id : itemsToDelete )
988 {
989 m_ruleTreeCtrl->Delete( id );
990 }
991
992 return matches || hasVisibleChildren;
993}
994
995
996void RULE_EDITOR_DIALOG_BASE::saveRuleTreeState( const wxTreeItemId& aItem, const int& aNodeId )
997{
998 wxString itemText = m_ruleTreeCtrl->GetItemText( aItem );
999 std::vector<int> children;
1000
1001 wxTreeItemIdValue cookie;
1002 wxTreeItemId child = m_ruleTreeCtrl->GetFirstChild( aItem, cookie );
1003
1004 while( child.IsOk() )
1005 {
1006 RULE_TREE_ITEM_DATA* childItemData =
1007 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( child ) );
1008 int childId = childItemData->GetNodeId();
1009
1010 children.push_back( childId );
1011
1012 saveRuleTreeState( child, childId );
1013
1014 child = m_ruleTreeCtrl->GetNextChild( aItem, cookie );
1015 }
1016
1017 m_treeHistoryData[aNodeId] = { itemText, children, aItem };
1018}
1019
1020
1021void RULE_EDITOR_DIALOG_BASE::restoreRuleTree( const wxTreeItemId& aParent, const int& aNodeId )
1022{
1023 auto it = m_treeHistoryData.find( aNodeId );
1024
1025 if( it == m_treeHistoryData.end() )
1026 return;
1027
1028 const auto& [itemText, children, itemId] = it->second;
1029
1030 wxTreeItemId newItem;
1031
1032 if( aParent )
1033 newItem = m_ruleTreeCtrl->AppendItem( aParent, itemText );
1034 else
1035 newItem = m_ruleTreeCtrl->AddRoot( itemText );
1036
1037 if( newItem )
1038 {
1039 wxTreeItemId& treeItemId = std::get<2>( it->second );
1040 treeItemId = newItem;
1041 }
1042
1043 RULE_TREE_ITEM_DATA* itemData = new RULE_TREE_ITEM_DATA( aNodeId, aParent, newItem );
1044 m_ruleTreeCtrl->SetItemData( newItem, itemData );
1045
1046 for( const auto& childId : children )
1047 {
1048 restoreRuleTree( newItem, childId );
1049 }
1050
1051 // Don't expand the root item because it is hidden
1052 if( aParent )
1053 m_ruleTreeCtrl->Expand( newItem );
1054}
1055
1056
1057wxTreeItemId RULE_EDITOR_DIALOG_BASE::appendRuleTreeItem( const RULE_TREE_NODE& aNode, wxTreeItemId aParent )
1058{
1059 wxTreeItemId currentTreeItemId = m_ruleTreeCtrl->AppendItem( aParent, aNode.m_nodeName );
1060
1061 RULE_TREE_ITEM_DATA* itemData = new RULE_TREE_ITEM_DATA( aNode.m_nodeId, aParent, currentTreeItemId );
1062 m_ruleTreeCtrl->SetItemData( currentTreeItemId, itemData );
1063
1064 m_ruleTreeCtrl->Expand( currentTreeItemId );
1065
1066 return currentTreeItemId;
1067}
1068
1069
1070void RULE_EDITOR_DIALOG_BASE::getRuleTreeChildNodes( const std::vector<RULE_TREE_NODE>& aNodes,
1071 int aParentId,
1072 std::vector<RULE_TREE_NODE>& aResult )
1073{
1074 std::vector<RULE_TREE_NODE> filteredNodes;
1075
1076 std::copy_if( aNodes.begin(), aNodes.end(), std::back_inserter( filteredNodes ),
1077 [&aParentId]( const RULE_TREE_NODE& node )
1078 {
1079 return node.m_nodeData->GetParentId() == aParentId;
1080 } );
1081
1082 if( filteredNodes.size() > 0 )
1083 {
1084 aResult.insert( aResult.end(), filteredNodes.begin(), filteredNodes.end() );
1085 }
1086}
1087
1089 wxTreeItemId aDest )
1090{
1091 wxTreeItemIdValue cookie;
1092 wxTreeItemId child = m_ruleTreeCtrl->GetFirstChild( aSrc, cookie );
1093
1094 while( child.IsOk() )
1095 {
1096 wxTreeItemId newChild =
1097 m_ruleTreeCtrl->AppendItem( aDest, m_ruleTreeCtrl->GetItemText( child ) );
1098
1099 RULE_TREE_ITEM_DATA* ruleTreeItemData =
1100 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( child ) );
1101 ruleTreeItemData->SetParentTreeItemId( aDest );
1102 ruleTreeItemData->SetTreeItemId( newChild );
1103
1104 m_ruleTreeCtrl->SetItemData( newChild, ruleTreeItemData );
1105 m_ruleTreeCtrl->SetItemData( child, nullptr );
1106
1107 moveRuleTreeItemChildrensTooOnDrag( child, newChild );
1108
1109 child = m_ruleTreeCtrl->GetNextChild( aSrc, cookie );
1110 }
1111}
1112
1113
1115{
1116 wxTreeItemId selectedItem = m_ruleTreeCtrl->GetSelection();
1117
1118 m_enableMoveUp = false;
1119 m_enableMoveDown = false;
1120
1121 if( !selectedItem.IsOk() )
1122 return;
1123
1124 if( selectedItem == m_ruleTreeCtrl->GetRootItem() )
1125 return;
1126
1127 RULE_TREE_ITEM_DATA* itemData =
1128 dynamic_cast<RULE_TREE_ITEM_DATA*>( m_ruleTreeCtrl->GetItemData( selectedItem ) );
1129
1130 if( !itemData ||
1133 {
1134 return;
1135 }
1136
1137 wxTreeItemId parent = m_ruleTreeCtrl->GetItemParent( selectedItem );
1138 wxTreeItemIdValue cookie;
1139 wxTreeItemId firstChild = m_ruleTreeCtrl->GetFirstChild( parent, cookie );
1140 wxTreeItemId lastChild = firstChild;
1141
1142 while( lastChild.IsOk() )
1143 {
1144 wxTreeItemId next = m_ruleTreeCtrl->GetNextChild( parent, cookie );
1145
1146 if( !next.IsOk() )
1147 break;
1148
1149 lastChild = next;
1150 }
1151
1152 m_enableMoveUp = ( selectedItem != firstChild );
1153 m_enableMoveDown = ( selectedItem != lastChild );
1154}
1155
1156
1158{
1159 wxTreeItemId selectedItem = m_ruleTreeCtrl->GetSelection();
1160
1161 if( !selectedItem.IsOk() || !m_ruleTreeCtrl->IsEnabled() )
1162 {
1163 m_addRuleButton->Enable( false );
1164 m_copyRuleButton->Enable( false );
1165 m_moveTreeItemUpButton->Enable( false );
1166 m_moveTreeItemDownButton->Enable( false );
1167 m_deleteRuleButton->Enable( false );
1168
1169 return;
1170 }
1171
1172 m_enableAddRule = false;
1173 m_enableDuplicateRule = false;
1174 m_enableDeleteRule = false;
1175
1177 m_enableAddRule = true;
1178
1180 m_enableDuplicateRule = true;
1181
1183 m_enableDeleteRule = true;
1184
1186
1192}
1193
1194
1195void RULE_EDITOR_DIALOG_BASE::onResize( wxSizeEvent& event )
1196{
1197 Layout();
1198
1199 event.Skip();
1200}
1201
1202
1203void RULE_EDITOR_DIALOG_BASE::onClose( wxCloseEvent& aEvt )
1204{
1205 wxPostEvent( this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
1206}
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
Definition bitmap.cpp:104
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
Definition bitmap.cpp:110
bool Show(bool show) override
void resetUndoRedoForNewContent(wxWindowList &aChildren)
Reset undo/redo tracking after dynamically replacing child panels.
void unregisterUnitBinders(wxWindow *aWindow)
Remove UNIT_BINDER registrations for a window and all its descendants.
void finishDialogSettings()
In all dialogs, we must call the same functions to fix minimal dlg size, the default position and per...
DIALOG_SHIM(wxWindow *aParent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE|wxRESIZE_BORDER, const wxString &name=wxDialogNameStr)
wxSize m_initialSize
virtual void OnCharHook(wxKeyEvent &aEvt)
int GetParentId()
Get the parent ID of the rule.
void populateRuleTreeCtrl(const std::vector< RULE_TREE_NODE > &aRuleTreeNodes, const RULE_TREE_NODE &aRuleTreeNode, wxTreeItemId aParentTreeItemId)
Populates the rule tree with nodes and their children.
void onRuleTreeItemSelectionChanged(wxTreeEvent &aEvent)
Updates action buttons based on the selected tree item.
void moveRuleTreeItemChildrensTooOnDrag(wxTreeItemId aSrcTreeItemId, wxTreeItemId aDestTreeItemId)
Recursively moves all child nodes of a source item to a destination during drag.
void DeleteRuleTreeItem(wxTreeItemId aItemId, const int &aNodeId)
Deletes a tree item and removes its corresponding node from history.
void onRuleTreeItemMouseMotion(wxMouseEvent &aEvent)
Handles drag motion to move the item along with the cursor.
void UpdateRuleTreeItemText(wxTreeItemId aItemId, wxString aItemText)
Updates the text of a specified rule tree item.
void onNewRuleOptionClick(wxCommandEvent &aEvent)
Creates a new rule when the "New Rule" option is clicked.
void onRuleTreeItemLeftDown(wxMouseEvent &aEvent)
Initiates drag operation for a tree item on mouse down.
void onMoveUpRuleOptionClick(wxCommandEvent &aEvent)
Moves a rule item up in the tree when "Move Up" is clicked.
virtual void RuleTreeItemSelectionChanged(RULE_TREE_ITEM_DATA *aCurrentRuleTreeItemData)=0
Pure virtual method to handle tree item selection changes.
void onClose(wxCloseEvent &aEvt)
bool Show(bool show) override
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,...
void onMoveDownRuleOptionClick(wxCommandEvent &aEvent)
Moves a rule item down in the tree when "Move Down" is clicked.
void AppendNewRuleTreeItem(const RULE_TREE_NODE &aRuleTreeNode, wxTreeItemId aParentTreeItemId)
Adds a new rule tree item under the specified parent and updates the tree history.
void InitRuleTreeItems(const std::vector< RULE_TREE_NODE > &aRuleTreeNodes)
Initializes the rule tree by adding nodes, setting up the structure, and saving its state.
void saveRuleTreeState(const wxTreeItemId &aItem, const int &aNodeId=0)
Saves the state of a tree item to history.
static RULE_EDITOR_DIALOG_BASE * GetDialog(wxWindow *aWindow)
Static method to retrieve the rule editor dialog instance associated with a given window.
void onRuleTreeItemLeftUp(wxMouseEvent &aEvent)
Completes the drag operation on mouse release.
void onRuleTreeItemActivated(wxTreeEvent &aEvent)
Handles double-click activation of a tree item.
void SetContentPanel(wxPanel *aContentPanel)
Replaces the current content panel with a new one based on the selected constraint type.
virtual void OnSave(wxCommandEvent &aEvent)=0
void OnCharHook(wxKeyEvent &aEvt) override
std::vector< RULE_TREE_NODE > m_defaultTreeItems
virtual void AddNewRule(RULE_TREE_ITEM_DATA *aRuleTreeItemData)=0
Pure virtual method to add a new rule to the tree.
void onDuplicateRuleOptionClick(wxCommandEvent &aEvent)
Duplicates the selected rule when "Duplicate Rule" is clicked.
wxScrolledWindow * m_scrolledContentWin
void ClearModified()
Clears the modified flag, typically after saving.
RULE_TREE_ITEM_DATA * m_selectedData
void restoreRuleTree(const wxTreeItemId &aParent, const int &aNodeId)
Restores a tree item from history and appends it under a parent.
RULE_EDITOR_DIALOG_BASE(wxWindow *aParent, const wxString &aTitle, const wxSize &aInitialSize=wxDefaultSize)
virtual void RemoveRule(int aNodeId)=0
Pure virtual method to remove a rule from the tree.
wxTreeItemId appendRuleTreeItem(const RULE_TREE_NODE &aRuleTreeNode, wxTreeItemId aParentTreeItemId)
Appends a new rule item to the tree.
std::unordered_map< int, std::tuple< wxString, std::vector< int >, wxTreeItemId > > m_treeHistoryData
void onResize(wxSizeEvent &event)
void onDeleteRuleOptionClick(wxCommandEvent &aEvent)
Deletes the selected rule when "Delete Rule" is clicked.
virtual void DuplicateRule(RULE_TREE_ITEM_DATA *aRuleTreeItemData)=0
Pure virtual method to duplicate an existing rule in the tree.
void onRuleTreeItemRightClick(wxTreeEvent &aEvent)
Handles right-click on a rule tree item to create a context menu.
void getRuleTreeChildNodes(const std::vector< RULE_TREE_NODE > &aNodes, int aParentId, std::vector< RULE_TREE_NODE > &aResult)
Retrieves child nodes of a given parent node.
void onFilterSearch(wxCommandEvent &aEvent)
Applies filter to the rule tree based on the search string.
virtual bool isEnabled(RULE_TREE_ITEM_DATA *aRuleTreeItemData, RULE_EDITOR_TREE_CONTEXT_OPT aOption)=0
Pure virtual method to verify if a context menu option for a rule tree item should be enabled.
void updateRuleTreeItemMoveOptionState()
Updates the state of move options (up/down) for the selected item.
virtual void OnCancel(wxCommandEvent &aEvent)=0
void updateRuleTreeActionButtonsState(RULE_TREE_ITEM_DATA *aRuleTreeItemData)
Updates the action buttons based on the current selection.
void SetControlsEnabled(bool aEnable)
Enables or disables controls within the rule editor dialog.
bool filterRuleTree(const wxTreeItemId &aItem, const wxString &aFilter)
Recursively filters tree items to show only those matching the filter.
wxBitmapButton * m_moveTreeItemDownButton
A class representing additional data associated with a wxTree item.
void SetTreeItemId(wxTreeItemId aTreeItemId)
void SetParentTreeItemId(wxTreeItemId aParentTreeItemId)
A modified version of the wxInfoBar class that allows us to:
Definition wx_infobar.h:77
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
Definition wx_panel.h:39
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
#define _(s)
KICOMMON_API wxFont GetControlFont(wxWindow *aWindow)
KICOMMON_API wxMenuItem * AddMenuItem(wxMenu *aMenu, int aId, const wxString &aText, const wxBitmapBundle &aImage, wxItemKind aType=wxITEM_NORMAL)
Create and insert a menu item with an icon into aMenu.
static wxSearchCtrl * CreateTextFilterBox(wxWindow *aParent, const wxString &aDescriptiveText)
Helper function to add a filter box to a panel, with some sensible defaults for that purpose.
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
CITER next(CITER it)
Definition ptree.cpp:124
static wxSearchCtrl * CreateTextFilterBox(wxWindow *aParent, const wxString &aDescriptiveText)
Structure representing a node in a rule tree, collection of this used for building the rule tree.
std::shared_ptr< RULE_EDITOR_DATA_BASE > m_nodeData
Functions to provide common constants and other functions to assist in making a consistent UI.