Ember
Loading...
Searching...
No Matches
MainPanel.cpp
Go to the documentation of this file.
1#include "Panels/MainPanel.h"
2
3namespace Ember {
4namespace Monitor {
5
6MainPanel::MainPanel(wxWindow *parent) : EmberUI::Panel(parent, "MainPanel") { CreateLayout(); }
7
9 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
10
11 wxPanel *searchBar = new wxPanel(this, wxID_ANY);
12 searchBar->SetBackgroundColour(wxColour(45, 45, 45));
13 wxBoxSizer *searchSizer = new wxBoxSizer(wxHORIZONTAL);
14
15 m_searchCtrl = new wxSearchCtrl(searchBar, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(250, -1));
16 m_searchCtrl->SetDescriptiveText("Search nodes... (Ctrl+F)");
17 m_searchCtrl->ShowCancelButton(true);
18
19 m_searchStatus = new wxStaticText(searchBar, wxID_ANY, "");
20 m_searchStatus->SetForegroundColour(wxColour(150, 150, 150));
21
22 searchSizer->Add(m_searchCtrl, 0, wxALIGN_CENTER_VERTICAL | wxALL, 3);
23 searchSizer->Add(m_searchStatus, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 8);
24 searchBar->SetSizer(searchSizer);
25
26 sizer->Add(searchBar, 0, wxEXPAND);
27
29 m_treeCanvas->SetStatusProvider(this);
30 sizer->Add(m_treeCanvas, 1, wxEXPAND);
31
32 SetSizer(sizer);
33
34 m_searchCtrl->Bind(wxEVT_TEXT, &MainPanel::OnSearchText, this);
35 m_searchCtrl->Bind(wxEVT_SEARCHCTRL_SEARCH_BTN, &MainPanel::OnSearchEnter, this);
36 m_searchCtrl->Bind(wxEVT_TEXT_ENTER, &MainPanel::OnSearchEnter, this);
37 m_searchCtrl->Bind(wxEVT_SEARCHCTRL_CANCEL_BTN, &MainPanel::OnSearchCancel, this);
38}
39
40void MainPanel::OnSearchText(wxCommandEvent &event) {
41 wxString query = m_searchCtrl->GetValue();
42 if (query.IsEmpty()) {
43 m_searchResults.clear();
44 m_searchIndex = 0;
45 m_searchStatus->SetLabel("");
46 return;
47 }
49 if (!m_searchResults.empty()) {
50 m_searchIndex = 0;
52 } else {
53 m_searchStatus->SetLabel("No matches");
54 }
55}
56
57void MainPanel::OnSearchEnter(wxCommandEvent &event) {
58 if (m_searchResults.empty())
59 return;
62}
63
64void MainPanel::OnSearchCancel(wxCommandEvent &event) {
65 m_searchCtrl->SetValue("");
66 m_searchResults.clear();
67 m_searchIndex = 0;
68 m_searchStatus->SetLabel("");
69 m_treeCanvas->SetFocus();
70}
71
72void MainPanel::NavigateToResult(size_t index) {
73 if (index >= m_searchResults.size())
74 return;
75
77
78 EmberCore::ITreeNode *parent = node->GetParent();
79 while (parent) {
80 if (!parent->AreChildrenVisible()) {
81 parent->SetChildrenVisible(true);
82 }
83 parent = parent->GetParent();
84 }
85
86 m_treeCanvas->SetSelectedNode(node);
87 m_treeCanvas->CenterOnNode(node);
88 m_treeCanvas->MarkDirty();
89
90 m_searchStatus->SetLabel(wxString::Format("%zu of %zu", index + 1, m_searchResults.size()));
91}
92
93void MainPanel::CollectSearchResults(const wxString &query) {
94 m_searchResults.clear();
95 auto tree = m_treeCanvas->GetTree();
96 if (!tree || !tree->HasRootNode())
97 return;
98
99 wxString lowerQuery = query.Lower();
100 tree->GetRootNode()->Accept([&](EmberCore::ITreeNode *node) {
101 wxString name = node->GetName();
102 if (name.Lower().Contains(lowerQuery)) {
103 m_searchResults.push_back(node);
104 }
105 });
106}
107
108void MainPanel::SetTree(std::shared_ptr<Ember::Network::TCPTreeAdapter> adapter,
109 std::shared_ptr<Network::StateManager> stateManager) {
110 m_stateManager = stateManager;
111 m_adapter = std::move(adapter);
112 m_treeCanvas->SetTree(m_adapter);
113
114 m_searchResults.clear();
115 m_searchIndex = 0;
116 m_searchCtrl->SetValue("");
117 m_searchStatus->SetLabel("");
118
119 CallAfter([this]() { m_treeCanvas->CenterOnNode(m_treeCanvas->GetTree()->GetRootNode()); });
120}
121
123 m_stateManager.reset();
124 m_adapter.reset();
125 m_treeCanvas->SetTree(nullptr);
126 m_searchResults.clear();
127 m_searchIndex = 0;
128 m_searchCtrl->SetValue("");
129 m_searchStatus->SetLabel("");
130}
131
132int MainPanel::GetNodeStatus(int64_t nodeId) const {
133 if (!m_stateManager)
134 return 0;
135 return static_cast<int>(m_stateManager->GetNodeStatus(nodeId));
136}
137
138bool MainPanel::IsNodeInExecutionPath(int64_t nodeId) const {
139 if (!m_stateManager)
140 return false;
141
142 const auto &path = m_stateManager->GetExecutionPath();
143 for (auto id : path) {
144 if (id == nodeId)
145 return true;
146 }
147 return false;
148}
149
150void MainPanel::GetExecutionPathIds(std::set<int64_t> &outIds) const {
151 if (!m_stateManager)
152 return;
153
154 const auto &path = m_stateManager->GetExecutionPath();
155 outIds.insert(path.begin(), path.end());
156}
157
159 m_treeCanvas->SetNodeSelectionCallback(callback);
160}
161
162} // namespace Monitor
163} // namespace Ember
Abstract interface for tree nodes that can be visualized.
Definition ITreeNode.h:31
virtual ITreeNode * GetParent() const =0
virtual bool AreChildrenVisible() const =0
virtual void SetChildrenVisible(bool visible)=0
virtual const String & GetName() const =0
Panel(wxWindow *parent, const wxString &name="Panel", long style=wxTAB_TRAVERSAL)
Constructs the panel with optional name and style.
void OnSearchText(wxCommandEvent &event)
Definition MainPanel.cpp:40
bool IsNodeInExecutionPath(int64_t nodeId) const override
Returns true if the node is in the current execution path.
void NavigateToResult(size_t index)
Definition MainPanel.cpp:72
void ClearTree()
Clears the displayed tree.
std::shared_ptr< Ember::Network::TCPTreeAdapter > m_adapter
Definition MainPanel.h:60
void GetExecutionPathIds(std::set< int64_t > &outIds) const override
Fills outIds with node IDs in the execution path.
void SetTree(std::shared_ptr< Ember::Network::TCPTreeAdapter > adapter, std::shared_ptr< Network::StateManager > stateManager)
Loads the tree from the given adapter and state manager.
void CollectSearchResults(const wxString &query)
Definition MainPanel.cpp:93
void OnSearchEnter(wxCommandEvent &event)
Definition MainPanel.cpp:57
std::shared_ptr< Network::StateManager > m_stateManager
Definition MainPanel.h:61
MainPanel(wxWindow *parent)
Definition MainPanel.cpp:6
std::function< void(EmberCore::ITreeNode *)> NodeSelectionCallback
Definition MainPanel.h:41
wxStaticText * m_searchStatus
Definition MainPanel.h:55
void CreateLayout() override
Hook: creates the panel layout. Override to customize.
Definition MainPanel.cpp:8
int GetNodeStatus(int64_t nodeId) const override
Returns the status code for the given node.
std::vector< EmberCore::ITreeNode * > m_searchResults
Definition MainPanel.h:57
MonitorTreeCanvas * m_treeCanvas
Definition MainPanel.h:53
wxSearchCtrl * m_searchCtrl
Definition MainPanel.h:54
void OnSearchCancel(wxCommandEvent &event)
Definition MainPanel.cpp:64
void SetNodeSelectionCallback(NodeSelectionCallback callback)
Registers a callback invoked when a node is selected in the tree.
Tree canvas with status-aware coloring and a connection info overlay.
Definition Panel.h:8