Ember
Loading...
Searching...
No Matches
NavigatorTab.h
Go to the documentation of this file.
1#pragma once
2
3#include "Interfaces/ITab.h"
5#include <functional>
6#include <map>
7#include <memory>
8#include <set>
9#include <string>
10#include <vector>
11#include <wx/simplebook.h>
12#include <wx/srchctrl.h>
13#include <wx/vlbox.h>
14#include <wx/wx.h>
15
16namespace EmberCore {
17class BehaviorTree;
18class Blackboard;
19class Node;
20class ITreeStructure;
21} // namespace EmberCore
22
23namespace EmberUI {
24
25class NavigatorTab;
26
29 std::function<bool()> canViewInCurrentScene;
30 std::function<void()> refreshVisualization;
31 std::function<void(EmberCore::ITreeNode *)> centerOnNode;
32 std::function<void(const std::string &)> openInNewScene;
33 std::function<void()> onTabClosed;
34};
35
38 public:
39 using ContextMenuPopulator = std::function<void(EmberCore::ITreeNode *, wxMenu &)>;
40 using ContextMenuHandler = std::function<void(int, EmberCore::ITreeNode *)>;
41 using NodeActivatedHandler = std::function<void(EmberCore::ITreeNode *)>;
42
43 NavigatorHierarchyView(wxWindow *parent, const EmberUI::TreeHierarchyConfig &config);
44
51
52 protected:
53 void OnPopulateContextMenu(EmberCore::ITreeNode *node, wxMenu &menu) override;
54 void OnContextMenuCommand(int id, EmberCore::ITreeNode *node) override;
55 void OnNodeActivated(EmberCore::ITreeNode *node) override;
56
57 private:
61};
62
64class NavigatorTreeListBox : public wxVListBox {
65 public:
66 NavigatorTreeListBox(NavigatorTab *owner, wxWindow *parent, wxWindowID id);
67
68 private:
69 void OnDrawItem(wxDC &dc, const wxRect &rect, size_t n) const override;
70 wxCoord OnMeasureItem(size_t n) const override;
71 void OnDrawBackground(wxDC &dc, const wxRect &rect, size_t n) const override;
72 void OnLeftDown(wxMouseEvent &event);
73 void OnLeftDClick(wxMouseEvent &event);
74 void OnRightDown(wxMouseEvent &event);
75
77};
78
80class SearchResultsListBox : public wxVListBox {
81 public:
82 SearchResultsListBox(NavigatorTab *owner, wxWindow *parent, wxWindowID id);
83
84 private:
85 void OnDrawItem(wxDC &dc, const wxRect &rect, size_t n) const override;
86 wxCoord OnMeasureItem(size_t n) const override;
87 void OnDrawBackground(wxDC &dc, const wxRect &rect, size_t n) const override;
88 void OnLeftDClick(wxMouseEvent &event);
89 void OnRightDown(wxMouseEvent &event);
90
92};
93
95class NavigatorTab : public wxPanel, public ITab {
96 public:
97 using TreeSelectionCallback = std::function<void(const std::string &treeId)>;
98
99 NavigatorTab(wxWindow *parent);
100
101 void SetCallbacks(NavigatorCallbacks cb) { m_callbacks = std::move(cb); }
102 void SetEditingEnabled(bool enabled) { m_editingEnabled = enabled; }
103 bool IsEditingEnabled() const { return m_editingEnabled; }
104
105 protected:
106 NavigatorTab(wxWindow *parent, bool deferLayout);
107 void InitLayout();
108 virtual NavigatorHierarchyView *CreateHierarchyView(wxWindow *parent, const TreeHierarchyConfig &cfg);
110
111 public:
112 // ITab interface
113 wxWindow *GetWidget() override { return this; }
114 wxString GetTitle() const override { return "Navigator"; }
115 wxString GetTabType() const override { return "Navigator"; }
116 void OnClosed() override;
117 void OnActivated() override;
118
120 void UpdateTreeList(const std::map<std::string, std::shared_ptr<EmberCore::BehaviorTree>> &trees,
121 const std::string &currentTreeId);
123 void SetCurrentTree(const std::string &treeId);
124 void ClearTreeList();
126 void SetMainTreeId(const std::string &id);
127
128 void SetBlackboards(const std::map<std::string, std::shared_ptr<EmberCore::Blackboard>> &bbs);
129 void SetBlackboardSelectionCallback(std::function<void(const std::string &)> cb);
130 void OnBlackboardClicked(const std::string &bbId);
131
133 void SetActiveTree(std::shared_ptr<EmberCore::ITreeStructure> tree, const std::string &treeId);
135 void SelectNodeById(size_t nodeId);
136 void RefreshHierarchy();
137
138 void SetLayoutInvalidationCallback(std::function<void()> cb);
139 void SetNodeSelectionCallback(std::function<void(EmberCore::ITreeNode *)> cb);
140
142 void DrillIntoTree(const std::string &treeId);
144 void NavigateBack();
145
146 // Tree list data access (for the list box drawing)
148
164
167 enum class Type { Tree, Node };
169 std::string treeId;
170 std::string nodeName;
171 size_t nodeId;
172 };
173
174 const std::vector<FlatEntry> &GetFlatList() const { return m_flatList; }
175 const std::vector<SearchResult> &GetSearchResults() const { return m_searchResults; }
176 const std::string &GetCurrentTreeId() const { return m_currentTreeId; }
177 const std::string &GetBrowsedTreeId() const { return m_browsedTreeId; }
178
179 void ToggleCollapse(const std::string &treeId);
181 bool IsCollapsed(const std::string &treeId) const;
182 bool IsSectionCollapsed(SectionType section) const;
183 int GetToggleHitX(int depth, bool isCurrent) const;
184
185 void ShowTreeContextMenu(int itemIndex, const wxPoint &pos);
186 void ShowSearchContextMenu(int resultIndex, const wxPoint &pos);
187 bool IsActiveTree(const std::string &treeId) const { return treeId == m_currentTreeId; }
188 void ClearSearch();
189
190 private:
191 void UpdateBreadcrumb();
192 void UpdateStatusLabel();
193
194 struct TreeInfo {
195 std::string id;
198 std::set<std::string> subtreeRefs;
199 };
200
201 void CollectSubTreeRefs(EmberCore::Node *node, std::set<std::string> &refs) const;
202 void CollectAllReachableSubtrees(const std::string &treeId, std::set<std::string> &reachable) const;
203 void BuildFlatList();
204 void FlattenTree(const std::string &treeId, int depth, std::set<std::string> &visited, bool isLastChild,
205 std::vector<bool> parentHasMore);
206 int FindItemByTreeId(const std::string &treeId) const;
207
208 void PerformGlobalSearch(const wxString &query);
209
210 void OnHierarchyContextMenu(EmberCore::ITreeNode *node, wxMenu &menu);
215
216 void OnTreeListContextViewInCurrent(wxCommandEvent &event);
217 void OnTreeListContextOpenNewScene(wxCommandEvent &event);
218 void OnTreeListContextBrowse(wxCommandEvent &event);
219 void OnTreeListContextExpand(wxCommandEvent &event);
220 void OnTreeListContextCollapse(wxCommandEvent &event);
221
222 void OnSearchTextChanged(wxCommandEvent &event);
223 void OnSearchEnter(wxCommandEvent &event);
224
225 void OnBackClicked(wxCommandEvent &event);
226
227 void CollapseAllTrees();
228 void ExpandAllTrees();
229
230 // UI components
231 wxSearchCtrl *m_searchCtrl = nullptr;
232 wxPanel *m_breadcrumbPanel = nullptr;
233 wxButton *m_backBtn = nullptr;
234 wxStaticText *m_breadcrumbLabel = nullptr;
235 wxSimplebook *m_book = nullptr;
239 wxStaticText *m_statusLabel = nullptr;
240
241 enum class ViewPage { TreeList = 0, Hierarchy = 1, Search = 2 };
244
245 std::map<std::string, TreeInfo> m_treeInfoMap;
246 std::vector<FlatEntry> m_flatList;
247 std::set<std::string> m_collapsedTrees;
251
252 std::vector<SearchResult> m_searchResults;
254
255 std::map<std::string, std::shared_ptr<EmberCore::BehaviorTree>> m_projectTrees;
256 std::string m_currentTreeId;
257 std::string m_mainTreeId;
258 std::string m_browsedTreeId;
260
261 std::shared_ptr<EmberCore::ITreeStructure> m_activeTreeAdapter;
262
263 std::map<std::string, std::shared_ptr<EmberCore::Blackboard>> m_blackboards;
264 std::function<void(const std::string &)> m_blackboardSelectionCallback;
265
267 bool m_editingEnabled = true;
270
271 enum {
272 ID_SEARCH_CTRL = wxID_HIGHEST + 300,
281 ID_CTX_ADD_CHILD = wxID_HIGHEST + 350,
286 };
287
289};
290
291} // namespace EmberUI
Represents a complete behavior tree data structure.
Represents a blackboard containing multiple entries.
Abstract interface for tree nodes that can be visualized.
Definition ITreeNode.h:31
Abstract interface for tree structures that can be visualized.
Represents a node in a behavior tree structure.
Definition Node.h:20
TreeHierarchyTab subclass with context menu and node activation hooks.
std::function< void(EmberCore::ITreeNode *, wxMenu &)> ContextMenuPopulator
std::function< void(int, EmberCore::ITreeNode *)> ContextMenuHandler
NodeActivatedHandler m_activatedHandler
void SetContextMenuPopulator(ContextMenuPopulator cb)
Sets callback to populate context menu for a node.
void OnPopulateContextMenu(EmberCore::ITreeNode *node, wxMenu &menu) override
Hook to populate context menu for a node.
std::function< void(EmberCore::ITreeNode *)> NodeActivatedHandler
ContextMenuPopulator m_contextPopulator
void OnNodeActivated(EmberCore::ITreeNode *node) override
Hook called when a node is double-clicked/activated.
ContextMenuHandler m_contextHandler
void SetContextMenuHandler(ContextMenuHandler cb)
Sets callback to handle context menu command.
void SetNodeActivatedHandler(NodeActivatedHandler cb)
Sets callback invoked when a node is activated (double-click).
void OnContextMenuCommand(int id, EmberCore::ITreeNode *node) override
Hook to handle context menu command.
NavigatorHierarchyView(wxWindow *parent, const EmberUI::TreeHierarchyConfig &config)
Main navigator tab with tree list, hierarchy view, search, and breadcrumb navigation.
void ToggleCollapse(const std::string &treeId)
std::vector< SearchResult > m_searchResults
std::string m_contextMenuTreeId
EmberCore::Node * GetMutableNode(EmberCore::ITreeNode *inode) const
void SetEditingEnabled(bool enabled)
NavigatorCallbacks m_callbacks
void OnHierarchyContextCommand(int id, EmberCore::ITreeNode *node)
NavigatorHierarchyView * m_hierarchyView
const std::string & GetCurrentTreeId() const
wxStaticText * m_breadcrumbLabel
wxString GetTitle() const override
Returns the display title of the tab.
bool IsEditingEnabled() const
TreeSelectionCallback m_treeSelectionCallback
wxWindow * GetWidget() override
Returns the wxWidgets window used as the tab content.
void SetBlackboards(const std::map< std::string, std::shared_ptr< EmberCore::Blackboard > > &bbs)
std::function< void(EmberCore::ITreeNode *)> m_nodeSelectionCallback
std::string m_browsedTreeId
void ShowTreeContextMenu(int itemIndex, const wxPoint &pos)
std::vector< FlatEntry > m_flatList
void OnClosed() override
Called when the tab is closed.
void SetMainTreeId(const std::string &id)
wxString GetTabType() const override
Returns the tab type identifier.
SearchResultsListBox * m_searchListBox
wxStaticText * m_statusLabel
void OnTreeListContextExpand(wxCommandEvent &event)
bool IsCollapsed(const std::string &treeId) const
void PerformGlobalSearch(const wxString &query)
std::shared_ptr< EmberCore::ITreeStructure > m_activeTreeAdapter
NavigatorTreeListBox * m_treeListBox
void OnTreeListContextBrowse(wxCommandEvent &event)
void SetCurrentTree(const std::string &treeId)
Sets the currently selected tree in the list.
void FlattenTree(const std::string &treeId, int depth, std::set< std::string > &visited, bool isLastChild, std::vector< bool > parentHasMore)
void OnHierarchySelectionChanged(EmberCore::ITreeNode *node)
bool IsSectionCollapsed(SectionType section) const
void SetNodeSelectionCallback(std::function< void(EmberCore::ITreeNode *)> cb)
void OnTreeListContextOpenNewScene(wxCommandEvent &event)
void SelectNodeById(size_t nodeId)
Selects the node with the given ID in the hierarchy.
std::map< std::string, std::shared_ptr< EmberCore::Blackboard > > m_blackboards
wxSearchCtrl * m_searchCtrl
const std::vector< FlatEntry > & GetFlatList() const
void SetTreeSelectionCallback(TreeSelectionCallback callback)
void CollectAllReachableSubtrees(const std::string &treeId, std::set< std::string > &reachable) const
void OnBackClicked(wxCommandEvent &event)
void OnActivated() override
Called when the tab becomes active.
void OnSearchEnter(wxCommandEvent &event)
void SetActiveTree(std::shared_ptr< EmberCore::ITreeStructure > tree, const std::string &treeId)
Sets the active tree for hierarchy view and drills into it.
const std::string & GetBrowsedTreeId() const
void OnSearchTextChanged(wxCommandEvent &event)
void OnHierarchyNodeActivated(EmberCore::ITreeNode *node)
void OnTreeListContextCollapse(wxCommandEvent &event)
std::function< void(const std::string &treeId)> TreeSelectionCallback
void UpdateTreeList(const std::map< std::string, std::shared_ptr< EmberCore::BehaviorTree > > &trees, const std::string &currentTreeId)
Updates tree list from project trees and sets current tree.
void CollectSubTreeRefs(EmberCore::Node *node, std::set< std::string > &refs) const
bool IsActiveTree(const std::string &treeId) const
void SetBlackboardSelectionCallback(std::function< void(const std::string &)> cb)
void OnBlackboardClicked(const std::string &bbId)
void SetCallbacks(NavigatorCallbacks cb)
std::map< std::string, std::shared_ptr< EmberCore::BehaviorTree > > m_projectTrees
std::string m_currentTreeId
std::set< std::string > m_collapsedTrees
void NavigateBack()
Navigates back in breadcrumb history.
void OnHierarchyContextMenu(EmberCore::ITreeNode *node, wxMenu &menu)
NavigatorHierarchyView * GetHierarchyView() const
void DrillIntoTree(const std::string &treeId)
Drills into a subtree (updates breadcrumb and hierarchy).
int GetToggleHitX(int depth, bool isCurrent) const
std::map< std::string, TreeInfo > m_treeInfoMap
void OnTreeListContextViewInCurrent(wxCommandEvent &event)
void ToggleSectionCollapse(SectionType section)
virtual NavigatorHierarchyView * CreateHierarchyView(wxWindow *parent, const TreeHierarchyConfig &cfg)
NavigatorTab(wxWindow *parent)
void SetLayoutInvalidationCallback(std::function< void()> cb)
std::function< void(const std::string &)> m_blackboardSelectionCallback
const std::vector< SearchResult > & GetSearchResults() const
int FindItemByTreeId(const std::string &treeId) const
void ShowSearchContextMenu(int resultIndex, const wxPoint &pos)
wxSimplebook * m_book
Virtual list box for the tree list (main tree, other trees, blackboards).
void OnDrawBackground(wxDC &dc, const wxRect &rect, size_t n) const override
wxCoord OnMeasureItem(size_t n) const override
void OnDrawItem(wxDC &dc, const wxRect &rect, size_t n) const override
void OnLeftDown(wxMouseEvent &event)
void OnRightDown(wxMouseEvent &event)
NavigatorTreeListBox(NavigatorTab *owner, wxWindow *parent, wxWindowID id)
void OnLeftDClick(wxMouseEvent &event)
Virtual list box for search results (trees and nodes).
void OnLeftDClick(wxMouseEvent &event)
void OnRightDown(wxMouseEvent &event)
void OnDrawBackground(wxDC &dc, const wxRect &rect, size_t n) const override
void OnDrawItem(wxDC &dc, const wxRect &rect, size_t n) const override
wxCoord OnMeasureItem(size_t n) const override
SearchResultsListBox(NavigatorTab *owner, wxWindow *parent, wxWindowID id)
Base class for hierarchy tabs operating on ITreeNode.
Interface for tab-based UI components in the application.
Definition ITab.h:7
Main types header for EmberCore.
Definition Panel.h:8
Callbacks for navigator actions (view, refresh, center, open scene, close).
std::function< bool()> canViewInCurrentScene
std::function< void(EmberCore::ITreeNode *)> centerOnNode
std::function< void()> refreshVisualization
std::function< void()> onTabClosed
std::function< void(const std::string &)> openInNewScene
Flattened tree list entry for display in NavigatorTreeListBox.
std::vector< bool > parentHasMore
Search result (tree or node) for display in SearchResultsListBox.
std::set< std::string > subtreeRefs
Configuration for TreeHierarchyTab appearance and behavior.