29#include <wx/treectrl.h>
30#include <wx/listctrl.h>
31#include <wx/stc/stc.h>
34#include <wx/dragimag.h>
37#include <wx/dcmemory.h>
38#include <wx/dcclient.h>
39#include <wx/dcbuffer.h>
52 wxSearchCtrl* search_widget =
new wxSearchCtrl( aParent, wxID_ANY );
54 search_widget->ShowSearchButton(
false );
55 search_widget->ShowCancelButton(
true );
57 search_widget->SetDescriptiveText( aDescriptiveText );
62 search_widget->SetMinSize( wxSize( -1, aParent->GetTextExtent( wxT(
"qb" ) ).y + 10 ) );
70 const wxSize& aInitialSize ) :
71 DIALOG_SHIM( aParent, wxID_ANY, aTitle, wxDefaultPosition, aInitialSize,
72 wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER ),
87 wxBoxSizer* mainSizer =
new wxBoxSizer( wxVERTICAL );
88 SetSizer( mainSizer );
90 wxBoxSizer* infoBarSizer =
new wxBoxSizer( wxHORIZONTAL );
93 infoBarSizer->Add(
m_infoBar, 0, wxEXPAND, 0 );
96 m_splitter =
new wxSplitterWindow(
this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
97 wxSP_3D | wxSP_LIVE_UPDATE | wxSP_3DSASH );
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 );
112 m_ruleTreeCtrl =
new wxTreeCtrl( treeCtrlPanel, wxID_ANY, wxDefaultPosition, wxDefaultSize,
113 wxTR_DEFAULT_STYLE | wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS );
118 treeCtrlFlags = ( treeCtrlFlags & ~wxBORDER_MASK ) | wxBORDER_NONE;
125 wxBoxSizer* actionButtonsSizer =
new wxBoxSizer( wxHORIZONTAL );
130 wxDefaultPosition, wxDefaultSize, 0 );
132 wxDefaultPosition, wxDefaultSize, 0 );
135 wxDefaultPosition, wxDefaultSize, 0 );
138 wxDefaultPosition, wxDefaultSize, 0 );
141 wxDefaultPosition, wxDefaultSize, 0 );
149 actionButtonsSizer->AddStretchSpacer( 1 );
155 treeCtrlSizer->Add( actionButtonsSizer, 0, wxBOTTOM | wxEXPAND, 5 );
157 treeCtrlPanel->Layout();
161 wxDefaultSize, wxVSCROLL | wxBORDER_NONE );
164 wxSystemSettings::GetColour( wxSYS_COLOUR_FRAMEBK ) );
169 treeCtrlPanel->Layout();
170 int minTreeWidth = treeCtrlPanel->GetBestSize().GetWidth();
173 if( minTreeWidth < 200 )
183 wxBoxSizer* m_sizerButtons =
new wxBoxSizer( wxHORIZONTAL );
185 wxStdDialogButtonSizer* m_sdbSizer =
new wxStdDialogButtonSizer();
192 m_sdbSizer->Realize();
194 m_sizerButtons->Add( m_sdbSizer, 1, wxEXPAND, 5 );
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 );
239 [
this]( wxSizeEvent& evt )
255 SetMinSize( wxSize( 400, 500 ) );
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,
275 if(
minSize.GetHeight() > 500 )
276 SetMinSize( wxSize(
minSize.GetWidth(), 500 ) );
278 wxLogTrace(
"debug_dlg_size",
"Show: size=%dx%d minSize=%dx%d",
279 GetSize().x, GetSize().y, GetMinSize().x, GetMinSize().y );
324 if( !DIALOG_SHIM::TransferDataToWindow() )
337 if( !DIALOG_SHIM::TransferDataFromWindow() )
346 if( aEvt.GetKeyCode() ==
'S' && aEvt.ControlDown() && !aEvt.ShiftDown() && !aEvt.AltDown() )
363 return currentDialog;
365 aParent = aParent->GetParent();
379 wxTreeItemId rootId =
m_ruleTreeCtrl->AddRoot( aNodes[0].m_nodeName );
385 std::vector<RULE_TREE_NODE> childNodes;
388 for(
const auto& child : childNodes )
430 int width = clientSize.GetWidth();
431 int height = std::max( clientSize.GetHeight(), bestSize.GetHeight() );
440 wxTreeItemId aParent )
448 std::vector<int>& existingChildren = std::get<1>( it->second );
449 existingChildren.push_back( aNode.
m_nodeId );
523 const std::vector<RULE_TREE_NODE>& aNodes,
const RULE_TREE_NODE& aNode,
524 wxTreeItemId aParent )
528 std::vector<RULE_TREE_NODE> childNodes;
531 for(
const auto& child : childNodes )
542 wxTreeItemId item = aEvent.GetItem();
552 if( !ruleTreeItemData )
579 menu.Bind( wxEVT_COMMAND_MENU_SELECTED,
580 [&]( wxCommandEvent& aCmd )
582 switch( aCmd.GetId() )
593 default: aCmd.Skip();
603 wxTreeItemId selectedItem = aEvent.GetItem();
608 if( !selectedItemData )
667 if( !selectedItem.IsOk() )
670 wxTreeItemId parent =
m_ruleTreeCtrl->GetItemParent( selectedItem );
675 wxTreeItemIdValue cookie;
676 wxTreeItemId current =
m_ruleTreeCtrl->GetFirstChild( parent, cookie );
677 wxTreeItemId previous;
678 wxTreeItemId beforePrevious;
680 while( current.IsOk() && current != selectedItem )
682 beforePrevious = previous;
687 if( !previous.IsOk() )
692 wxTreeItemId insertPosition = beforePrevious.IsOk() ? beforePrevious : wxTreeItemId();
695 parent, insertPosition,
m_ruleTreeCtrl->GetItemText( selectedItem ) );
699 wxTreeItemData* itemData =
m_ruleTreeCtrl->GetItemData( selectedItem );
729 if( !selectedItem.IsOk() )
732 wxTreeItemId parent =
m_ruleTreeCtrl->GetItemParent( selectedItem );
733 wxTreeItemIdValue cookie;
734 wxTreeItemId current =
m_ruleTreeCtrl->GetFirstChild( parent, cookie );
736 while( current.IsOk() && current != selectedItem )
749 wxTreeItemData* itemData =
m_ruleTreeCtrl->GetItemData( selectedItem );
777 wxPoint pt = aEvent.GetPosition();
782 if( flags & wxTREE_HITTEST_ONITEMBUTTON )
795 wxBitmap bitmap( 200, 30 );
796 dc.SelectObject( bitmap );
797 dc.SetBackground( *wxWHITE_BRUSH );
799 dc.SetFont( *wxNORMAL_FONT );
800 dc.DrawText(
text, 5, 5 );
801 dc.SelectObject( wxNullBitmap );
815 wxPoint currentPos = aEvent.GetPosition();
852 wxPoint pos = aEvent.GetPosition();
856 if( !targetItem.IsOk() )
860 wxTreeItemId targetParent =
m_ruleTreeCtrl->GetItemParent( targetItem );
862 if( draggedParent != targetParent )
865 if( draggedParent == targetParent )
867 wxTreeItemId newItem;
868 wxTreeItemIdValue cookie;
870 if( flags & wxTREE_HITTEST_ONITEMLABEL
871 && targetItem ==
m_ruleTreeCtrl->GetFirstChild( targetParent, cookie ) )
879 wxTreeItemId current =
m_ruleTreeCtrl->GetFirstChild( targetParent, cookie );
880 wxTreeItemId previous;
883 while( current.IsOk() && current != targetItem )
889 if( !previous.IsOk() )
897 wxTreeItemId nextSibling =
m_ruleTreeCtrl->GetNextChild( targetParent, cookie );
899 if( nextSibling.IsOk() )
903 targetParent, previous,
948 const auto searchStr = aEvent.GetString().Lower();
965 bool matches =
m_ruleTreeCtrl->GetItemText( aItem ).Lower().Contains( aFilter );
967 wxTreeItemIdValue cookie;
968 wxTreeItemId child =
m_ruleTreeCtrl->GetFirstChild( aItem, cookie );
969 bool hasVisibleChildren =
false;
971 std::vector<wxTreeItemId> itemsToDelete;
973 while( child.IsOk() )
977 hasVisibleChildren =
true;
981 itemsToDelete.push_back( child );
987 for(
const auto&
id : itemsToDelete )
992 return matches || hasVisibleChildren;
999 std::vector<int> children;
1001 wxTreeItemIdValue cookie;
1002 wxTreeItemId child =
m_ruleTreeCtrl->GetFirstChild( aItem, cookie );
1004 while( child.IsOk() )
1008 int childId = childItemData->
GetNodeId();
1010 children.push_back( childId );
1028 const auto& [itemText, children, itemId] = it->second;
1030 wxTreeItemId newItem;
1039 wxTreeItemId& treeItemId = std::get<2>( it->second );
1040 treeItemId = newItem;
1046 for(
const auto& childId : children )
1066 return currentTreeItemId;
1072 std::vector<RULE_TREE_NODE>& aResult )
1074 std::vector<RULE_TREE_NODE> filteredNodes;
1076 std::copy_if( aNodes.begin(), aNodes.end(), std::back_inserter( filteredNodes ),
1079 return node.m_nodeData->GetParentId() == aParentId;
1082 if( filteredNodes.size() > 0 )
1084 aResult.insert( aResult.end(), filteredNodes.begin(), filteredNodes.end() );
1089 wxTreeItemId aDest )
1091 wxTreeItemIdValue cookie;
1092 wxTreeItemId child =
m_ruleTreeCtrl->GetFirstChild( aSrc, cookie );
1094 while( child.IsOk() )
1096 wxTreeItemId newChild =
1121 if( !selectedItem.IsOk() )
1137 wxTreeItemId parent =
m_ruleTreeCtrl->GetItemParent( selectedItem );
1138 wxTreeItemIdValue cookie;
1139 wxTreeItemId firstChild =
m_ruleTreeCtrl->GetFirstChild( parent, cookie );
1140 wxTreeItemId lastChild = firstChild;
1142 while( lastChild.IsOk() )
1205 wxPostEvent(
this, wxCommandEvent( wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL ) );
wxBitmap KiBitmap(BITMAPS aBitmap, int aHeightTag)
Construct a wxBitmap from an image identifier Returns the image from the active theme if the image ha...
wxBitmapBundle KiBitmapBundle(BITMAPS aBitmap, int aMinHeight)
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)
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.
wxTreeItemId m_draggedItem
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,...
wxBitmapButton * m_addRuleButton
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.
wxTreeItemId m_previousId
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
wxTreeCtrl * m_ruleTreeCtrl
wxButton * m_cancelRuleButton
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.
wxButton * m_saveRuleButton
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.
bool m_enableDuplicateRule
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.
bool TransferDataToWindow() override
wxBitmapButton * m_deleteRuleButton
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.
wxSearchCtrl * m_filterSearch
int m_defaultSashPosition
virtual void DuplicateRule(RULE_TREE_ITEM_DATA *aRuleTreeItemData)=0
Pure virtual method to duplicate an existing rule in the tree.
bool TransferDataFromWindow() override
~RULE_EDITOR_DIALOG_BASE() override
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.
wxBitmapButton * m_copyRuleButton
void onFilterSearch(wxCommandEvent &aEvent)
Applies filter to the rule tree based on the search string.
wxBitmapButton * m_moveTreeItemUpButton
wxSplitterWindow * m_splitter
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.
wxDragImage * m_dragImage
virtual void OnCancel(wxCommandEvent &aEvent)=0
void updateRuleTreeActionButtonsState(RULE_TREE_ITEM_DATA *aRuleTreeItemData)
Updates the action buttons based on the current selection.
void finishInitialization()
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:
void SetBorders(bool aLeft, bool aRight, bool aTop, bool aBottom)
This file is part of the common library.
const int minSize
Push and Shove router track width and via size dialog.
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...
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.