During LoadExistingRules, each call to AppendNewRuleTreeItem triggered SelectItem, which fired the selection-changed handler. That handler created a full PANEL_DRC_RULE_EDITOR per rule, compiling 14 regex patterns, instantiating Scintilla, running layout, then immediately destroying it when the next rule was appended. Also fix other potential slow downs
507 lines
16 KiB
C++
507 lines
16 KiB
C++
/*
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
*
|
|
* Copyright (C) 2024 KiCad Developers, see AUTHORS.txt for contributors.
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation, either version 3 of the License, or (at your
|
|
* option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef RULE_EDITOR_DIALOG_BASE_H
|
|
#define RULE_EDITOR_DIALOG_BASE_H
|
|
|
|
#include <wx/treectrl.h>
|
|
#include <wx/srchctrl.h>
|
|
#include <wx/bmpbuttn.h>
|
|
#include <wx/splitter.h>
|
|
#include <wx/scrolwin.h>
|
|
|
|
#include <variant>
|
|
#include <optional>
|
|
#include <unordered_map>
|
|
|
|
#include <dialog_shim.h>
|
|
#include <dialogs/rule_editor_data_base.h>
|
|
#include <widgets/std_bitmap_button.h>
|
|
|
|
class WX_INFOBAR;
|
|
|
|
/**
|
|
* Enumeration representing the available context menu options for the rule editor tree.
|
|
*/
|
|
enum RULE_EDITOR_TREE_CONTEXT_OPT
|
|
{
|
|
ADD_RULE = 0,
|
|
DUPLICATE_RULE,
|
|
DELETE_RULE,
|
|
MOVE_UP,
|
|
MOVE_DOWN,
|
|
};
|
|
|
|
/**
|
|
* Structure representing a node in a rule tree, collection of this used for building the rule tree.
|
|
*/
|
|
struct RULE_TREE_NODE
|
|
{
|
|
int m_nodeId;
|
|
wxString m_nodeName;
|
|
int m_nodeType;
|
|
int m_nodeLevel;
|
|
std::optional<int> m_nodeTypeMap;
|
|
std::vector<RULE_TREE_NODE> m_childNodes;
|
|
std::shared_ptr<RULE_EDITOR_DATA_BASE> m_nodeData;
|
|
};
|
|
|
|
|
|
/**
|
|
* A class representing additional data associated with a wxTree item.
|
|
* This class is used to store and manage metadata for individual items in a wxTree,
|
|
* linking each tree item to its corresponding node ID and parent tree item.
|
|
*/
|
|
class RULE_TREE_ITEM_DATA : public wxTreeItemData
|
|
{
|
|
public:
|
|
explicit RULE_TREE_ITEM_DATA( int aNodeId, wxTreeItemId aParentTreeItemId,
|
|
wxTreeItemId aTreeItemId ) :
|
|
m_nodeId( aNodeId ),
|
|
m_treeItemId( aTreeItemId ),
|
|
m_parentTreeItemId( aParentTreeItemId )
|
|
{
|
|
}
|
|
|
|
int GetNodeId() const { return m_nodeId; }
|
|
|
|
wxTreeItemId GetParentTreeItemId() const { return m_parentTreeItemId; }
|
|
|
|
void SetParentTreeItemId( wxTreeItemId aParentTreeItemId )
|
|
{
|
|
m_parentTreeItemId = aParentTreeItemId;
|
|
}
|
|
|
|
wxTreeItemId GetTreeItemId() const { return m_treeItemId; }
|
|
|
|
void SetTreeItemId( wxTreeItemId aTreeItemId ) { m_treeItemId = aTreeItemId; }
|
|
|
|
private:
|
|
int m_nodeId;
|
|
wxTreeItemId m_treeItemId;
|
|
wxTreeItemId m_parentTreeItemId;
|
|
};
|
|
|
|
|
|
class RULE_EDITOR_DIALOG_BASE : public DIALOG_SHIM
|
|
{
|
|
friend class DIALOG_DRC_RULE_EDITOR;
|
|
|
|
public:
|
|
RULE_EDITOR_DIALOG_BASE( wxWindow* aParent, const wxString& aTitle,
|
|
const wxSize& aInitialSize = wxDefaultSize );
|
|
|
|
~RULE_EDITOR_DIALOG_BASE() override;
|
|
|
|
/**
|
|
* Enumeration representing the available context menu options for the rule editor tree.
|
|
*/
|
|
enum RULE_EDITOR_TREE_CONTEXT_OPT_ID
|
|
{
|
|
ID_NEWRULE = wxID_HIGHEST + 1,
|
|
ID_COPYRULE,
|
|
ID_DELETERULE,
|
|
ID_MOVEUP,
|
|
ID_MOVEDOWN
|
|
};
|
|
|
|
/**
|
|
* Gets the tree control used for displaying and managing rules.
|
|
*
|
|
* @return A pointer to the wxTreeCtrl instance.
|
|
*/
|
|
wxTreeCtrl* GetRuleTreeCtrl() { return m_ruleTreeCtrl; }
|
|
|
|
/**
|
|
* Marks the dialog as modified, indicating unsaved changes.
|
|
* Updates button states to reflect that changes can be discarded or saved.
|
|
*/
|
|
void SetModified();
|
|
|
|
/**
|
|
* Clears the modified flag, typically after saving.
|
|
* Updates button states to reflect no unsaved changes.
|
|
*/
|
|
void ClearModified();
|
|
|
|
/**
|
|
* Returns whether the dialog has unsaved changes.
|
|
*/
|
|
bool IsModified() const { return m_modified; }
|
|
|
|
/**
|
|
* Static method to retrieve the rule editor dialog instance associated with a given window.
|
|
*
|
|
* @param aWindow The window for which the dialog is being retrieved.
|
|
*
|
|
* @return A pointer to the RULE_EDITOR_DIALOG_BASE instance, or nullptr if not found.
|
|
*/
|
|
static RULE_EDITOR_DIALOG_BASE* GetDialog( wxWindow* aWindow );
|
|
|
|
/**
|
|
* Pure virtual method to get the default rule tree items.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @return A vector of default RULE_TREE_NODE items.
|
|
*/
|
|
virtual std::vector<RULE_TREE_NODE> GetDefaultRuleTreeItems() = 0;
|
|
|
|
/**
|
|
* Pure virtual method to add a new rule to the tree.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aRuleTreeItemData The data associated with the new rule.
|
|
*/
|
|
virtual void AddNewRule( RULE_TREE_ITEM_DATA* aRuleTreeItemData ) = 0;
|
|
|
|
/**
|
|
* Pure virtual method to duplicate an existing rule in the tree.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aRuleTreeItemData The data of the rule to duplicate.
|
|
*/
|
|
virtual void DuplicateRule( RULE_TREE_ITEM_DATA* aRuleTreeItemData ) = 0;
|
|
|
|
/**
|
|
* Pure virtual method to remove a rule from the tree.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aNodeId The ID of the rule node to remove.
|
|
*/
|
|
virtual void RemoveRule( int aNodeId ) = 0;
|
|
|
|
/**
|
|
* Pure virtual method to handle tree item selection changes.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aCurrentRuleTreeItemData The data of the newly selected rule tree item.
|
|
*/
|
|
virtual void RuleTreeItemSelectionChanged( RULE_TREE_ITEM_DATA* aCurrentRuleTreeItemData ) = 0;
|
|
|
|
/**
|
|
* Pure virtual method to update the rule tree item data.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aRuleTreeItemData The data of the rule tree item to be updated.
|
|
*/
|
|
virtual void UpdateRuleTypeTreeItemData( RULE_TREE_ITEM_DATA* aRuleTreeItemData ) = 0;
|
|
|
|
/**
|
|
* Pure virtual method to verify if a context menu option for a rule tree item should be enabled.
|
|
* Must be implemented by derived classes.
|
|
*
|
|
* @param aRuleTreeItemData The data of the rule tree item to check.
|
|
* @param aOption The context menu option to verify.
|
|
*
|
|
* @return true if the option should be enabled, false otherwise.
|
|
*/
|
|
virtual bool isEnabled( RULE_TREE_ITEM_DATA* aRuleTreeItemData,
|
|
RULE_EDITOR_TREE_CONTEXT_OPT aOption ) = 0;
|
|
|
|
/**
|
|
* Initializes the rule tree by adding nodes, setting up the structure, and saving its state.
|
|
*
|
|
* @param aRuleTreeNodes A vector of rule tree nodes with their IDs, names, and child nodes.
|
|
*/
|
|
void InitRuleTreeItems( const std::vector<RULE_TREE_NODE>& aRuleTreeNodes );
|
|
|
|
/**
|
|
* Retrieves the current content panel.
|
|
*
|
|
* @return A pointer to the current content panel.
|
|
*/
|
|
wxPanel* GetContentPanel() { return m_contentPanel; }
|
|
|
|
/**
|
|
* Replaces the current content panel with a new one based on the selected constraint type.
|
|
*
|
|
* @param aContentPanel The new content panel to replace the existing one.
|
|
*/
|
|
void SetContentPanel( wxPanel* aContentPanel );
|
|
|
|
/**
|
|
* Recalculates the scrolled content area's virtual size based on the current
|
|
* content panel's best size, and updates the scrollbar accordingly.
|
|
*/
|
|
void RefreshContentScrollArea();
|
|
|
|
/**
|
|
* Adds a new rule tree item under the specified parent and updates the tree history.
|
|
*
|
|
* @param aRuleTreeNode The node data to add.
|
|
* @param aParentTreeItemId The parent item's ID.
|
|
*/
|
|
void AppendNewRuleTreeItem( const RULE_TREE_NODE& aRuleTreeNode,
|
|
wxTreeItemId aParentTreeItemId );
|
|
|
|
/**
|
|
* Retrieves the currently selected rule tree item data.
|
|
*
|
|
* @return A pointer to the currently selected rule tree item data.
|
|
*/
|
|
RULE_TREE_ITEM_DATA* GetCurrentlySelectedRuleTreeItemData() { return m_selectedData; }
|
|
|
|
/**
|
|
* Retrieves the previously selected rule tree item ID.
|
|
*
|
|
* @return The ID of the previously selected rule tree item.
|
|
*/
|
|
wxTreeItemId GetPreviouslySelectedRuleTreeItemId() { return m_previousId; }
|
|
|
|
/**
|
|
* Updates the text of a specified rule tree item.
|
|
*
|
|
* @param aItemId The ID of the tree item to update.
|
|
* @param aItemText The new text to set for the tree item.
|
|
*/
|
|
void UpdateRuleTreeItemText( wxTreeItemId aItemId, wxString aItemText );
|
|
|
|
/**
|
|
* Enables or disables controls within the rule editor dialog.
|
|
*
|
|
* @param aEnable true to enable the controls, false to disable them.
|
|
*/
|
|
void SetControlsEnabled( bool aEnable );
|
|
|
|
/**
|
|
* Deletes a tree item and removes its corresponding node from history.
|
|
*
|
|
* @param aItemId The tree item ID to delete.
|
|
* @param aNodeId The node ID to remove from history.
|
|
*/
|
|
void DeleteRuleTreeItem( wxTreeItemId aItemId, const int& aNodeId );
|
|
|
|
virtual void OnSave( wxCommandEvent& aEvent ) = 0;
|
|
|
|
virtual void OnCancel( wxCommandEvent& aEvent ) = 0;
|
|
|
|
bool Show( bool show ) override;
|
|
|
|
protected:
|
|
void finishInitialization();
|
|
|
|
bool TransferDataToWindow() override;
|
|
|
|
bool TransferDataFromWindow() override;
|
|
|
|
void OnCharHook( wxKeyEvent& aEvt ) override;
|
|
|
|
private:
|
|
/**
|
|
* Populates the rule tree with nodes and their children.
|
|
*
|
|
* @param aRuleTreeNodes All rule tree nodes.
|
|
* @param aRuleTreeNode Current node to add.
|
|
* @param aParentTreeItemId Parent item ID for the current node.
|
|
*/
|
|
void populateRuleTreeCtrl( const std::vector<RULE_TREE_NODE>& aRuleTreeNodes,
|
|
const RULE_TREE_NODE& aRuleTreeNode,
|
|
wxTreeItemId aParentTreeItemId );
|
|
|
|
/**
|
|
* Handles right-click on a rule tree item to create a context menu.
|
|
*
|
|
* @param aEvent The right-click event.
|
|
*/
|
|
void onRuleTreeItemRightClick( wxTreeEvent& aEvent );
|
|
|
|
/**
|
|
* Updates action buttons based on the selected tree item.
|
|
*
|
|
* @param aEvent The selection change event.
|
|
*/
|
|
void onRuleTreeItemSelectionChanged( wxTreeEvent& aEvent );
|
|
|
|
/**
|
|
* Handles double-click activation of a tree item.
|
|
* Creates a new rule of the activated type when appropriate.
|
|
*/
|
|
void onRuleTreeItemActivated( wxTreeEvent& aEvent );
|
|
|
|
/**
|
|
* Creates a new rule when the "New Rule" option is clicked.
|
|
*
|
|
* @param aEvent The command event triggered by the click.
|
|
*/
|
|
void onNewRuleOptionClick( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Duplicates the selected rule when "Duplicate Rule" is clicked.
|
|
*
|
|
* @param aEvent The command event triggered by the click.
|
|
*/
|
|
void onDuplicateRuleOptionClick( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Deletes the selected rule when "Delete Rule" is clicked.
|
|
*
|
|
* @param aEvent The command event triggered by the click.
|
|
*/
|
|
void onDeleteRuleOptionClick( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Moves a rule item up in the tree when "Move Up" is clicked.
|
|
*
|
|
* @param aEvent The command event triggered by the click.
|
|
*/
|
|
void onMoveUpRuleOptionClick( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Moves a rule item down in the tree when "Move Down" is clicked.
|
|
*
|
|
* @param aEvent The command event triggered by the click.
|
|
*/
|
|
void onMoveDownRuleOptionClick( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Initiates drag operation for a tree item on mouse down.
|
|
*
|
|
* @param aEvent The mouse down event.
|
|
*/
|
|
void onRuleTreeItemLeftDown( wxMouseEvent& aEvent );
|
|
|
|
/**
|
|
* Handles drag motion to move the item along with the cursor.
|
|
*
|
|
* @param aEvent The mouse motion event during drag.
|
|
*/
|
|
void onRuleTreeItemMouseMotion( wxMouseEvent& aEvent );
|
|
|
|
/**
|
|
* Completes the drag operation on mouse release.
|
|
*
|
|
* @param aEvent The mouse release event.
|
|
*/
|
|
void onRuleTreeItemLeftUp( wxMouseEvent& aEvent );
|
|
|
|
/**
|
|
* Applies filter to the rule tree based on the search string.
|
|
*
|
|
* @param aEvent The command event containing the filter string.
|
|
*/
|
|
void onFilterSearch( wxCommandEvent& aEvent );
|
|
|
|
/**
|
|
* Recursively filters tree items to show only those matching the filter.
|
|
*
|
|
* @param aItem The tree item to check.
|
|
* @param aFilter The filter string.
|
|
* @return True if the item matches the filter or has visible children.
|
|
*/
|
|
bool filterRuleTree( const wxTreeItemId& aItem, const wxString& aFilter );
|
|
|
|
/**
|
|
* Saves the state of a tree item to history.
|
|
*
|
|
* @param aItem The item to save.
|
|
* @param aNodeId The node ID (optional).
|
|
*/
|
|
void saveRuleTreeState( const wxTreeItemId& aItem, const int& aNodeId = 0 );
|
|
|
|
/**
|
|
* Restores a tree item from history and appends it under a parent.
|
|
*
|
|
* @param aParent The parent item to append to.
|
|
* @param aNodeId The node ID to restore.
|
|
*/
|
|
void restoreRuleTree( const wxTreeItemId& aParent, const int& aNodeId );
|
|
|
|
/**
|
|
* Appends a new rule item to the tree.
|
|
*
|
|
* @param aRuleTreeNode The rule tree node for the new item.
|
|
* @param aParentTreeItemId Parent item ID.
|
|
* @return The newly created tree item ID.
|
|
*/
|
|
wxTreeItemId appendRuleTreeItem( const RULE_TREE_NODE& aRuleTreeNode,
|
|
wxTreeItemId aParentTreeItemId );
|
|
|
|
/**
|
|
* Retrieves child nodes of a given parent node.
|
|
*
|
|
* @param aNodes List of all nodes.
|
|
* @param aParentId The parent node ID.
|
|
* @param aResult A vector to store child nodes.
|
|
*/
|
|
void getRuleTreeChildNodes( const std::vector<RULE_TREE_NODE>& aNodes, int aParentId,
|
|
std::vector<RULE_TREE_NODE>& aResult );
|
|
|
|
/**
|
|
* Recursively moves all child nodes of a source item to a destination during drag.
|
|
*
|
|
* @param aSrcTreeItemId Source item ID.
|
|
* @param aDestTreeItemId Destination item ID.
|
|
*/
|
|
void moveRuleTreeItemChildrensTooOnDrag( wxTreeItemId aSrcTreeItemId,
|
|
wxTreeItemId aDestTreeItemId );
|
|
|
|
/**
|
|
* Updates the state of move options (up/down) for the selected item.
|
|
*/
|
|
void updateRuleTreeItemMoveOptionState();
|
|
|
|
/**
|
|
* Updates the action buttons based on the current selection.
|
|
*/
|
|
void updateRuleTreeActionButtonsState( RULE_TREE_ITEM_DATA* aRuleTreeItemData );
|
|
|
|
void onResize( wxSizeEvent& event );
|
|
|
|
void onClose( wxCloseEvent& aEvt );
|
|
|
|
protected:
|
|
wxTreeCtrl* m_ruleTreeCtrl;
|
|
WX_INFOBAR* m_infoBar;
|
|
wxPanel* m_contentPanel;
|
|
wxScrolledWindow* m_scrolledContentWin;
|
|
wxSplitterWindow* m_splitter;
|
|
wxSearchCtrl* m_filterSearch;
|
|
wxTextCtrl* m_filterText;
|
|
wxBoxSizer* m_buttonsSizer;
|
|
STD_BITMAP_BUTTON* m_addRuleButton;
|
|
STD_BITMAP_BUTTON* m_copyRuleButton;
|
|
STD_BITMAP_BUTTON* m_moveTreeItemUpButton;
|
|
STD_BITMAP_BUTTON* m_moveTreeItemDownButton;
|
|
STD_BITMAP_BUTTON* m_deleteRuleButton;
|
|
wxButton* m_saveRuleButton;
|
|
wxButton* m_cancelRuleButton;
|
|
|
|
private:
|
|
bool m_isDragging;
|
|
bool m_enableMoveUp;
|
|
bool m_enableMoveDown;
|
|
bool m_enableAddRule;
|
|
bool m_enableDuplicateRule;
|
|
bool m_enableDeleteRule;
|
|
bool m_modified;
|
|
bool m_suppressSelectionEvents;
|
|
int m_defaultSashPosition;
|
|
|
|
wxString m_title;
|
|
std::vector<RULE_TREE_NODE> m_defaultTreeItems;
|
|
RULE_TREE_ITEM_DATA* m_selectedData;
|
|
wxTreeItemId m_previousId;
|
|
wxTreeItemId m_draggedItem;
|
|
wxTreeItemId m_dropTargetItem;
|
|
|
|
std::unordered_map<int, std::tuple<wxString, std::vector<int>, wxTreeItemId>> m_treeHistoryData;
|
|
};
|
|
|
|
#endif //RULE_EDITOR_DIALOG_BASE_H
|