Ember
Loading...
Searching...
No Matches
SidePanel.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <wx/sizer.h>
5
6namespace EmberUI {
7
10
11 SidePanel::SidePanel(wxWindow *parent, const wxString &panelName, bool autoLayout)
12 : Panel(parent, panelName), m_notebook(nullptr), m_activeTabIndex(-1) {
13 SetPanelType("SidePanel");
14 if (autoLayout) {
15 CreateLayout();
16 }
17}
18
20 if (m_notebook) {
21 while (m_notebook->GetPageCount() > 0) {
22 m_notebook->RemovePage(0);
23 }
24 }
25}
26
28 wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
29
31
32 if (m_notebook) {
33 sizer->Add(m_notebook, 1, wxEXPAND | wxALL, 2);
34 }
35
36 SetMainSizer(sizer);
37}
38
40 long style = wxAUI_NB_DEFAULT_STYLE;
41 style &= ~wxAUI_NB_TAB_MOVE;
42 style &= ~wxAUI_NB_TAB_EXTERNAL_MOVE;
43 style &= ~wxAUI_NB_TAB_SPLIT;
44
45 m_notebook = new wxAuiNotebook(this, ID_NOTEBOOK, wxDefaultPosition, wxDefaultSize, style);
46}
47
49 if (!tab || !m_notebook) {
50 return -1;
51 }
52
53 wxWindow *widget = tab->GetWidget();
54 wxString title = tab->GetTitle();
55
56 bool ok = m_notebook->AddPage(widget, title, true);
57 int index = ok ? static_cast<int>(m_notebook->GetPageCount()) - 1 : -1;
58
59 if (ok) {
60 tab->Initialize();
61 ITab *rawTab = tab.get();
62 m_tabs.push_back(std::move(tab));
63 m_activeTabIndex = index;
64 OnTabAdded(rawTab, index);
65 }
66
67 return index;
68}
69
71 if (index < 0 || index >= static_cast<int>(m_tabs.size()) || !m_notebook) {
72 return nullptr;
73 }
74
75 if (!m_notebook->RemovePage(index)) {
76 return nullptr;
77 }
78
79 ITabPtr removed = std::move(m_tabs[index]);
80 m_tabs.erase(m_tabs.begin() + index);
81
82 if (removed) {
83 removed->OnClosed();
84 OnTabRemoved(removed.get(), index);
85 }
86
87 if (m_activeTabIndex == index) {
88 m_activeTabIndex = m_tabs.empty() ? -1 : std::min(m_activeTabIndex, static_cast<int>(m_tabs.size()) - 1);
89 } else if (m_activeTabIndex > index) {
91 }
92
93 return removed;
94}
95
96ITab *SidePanel::GetTab(int index) const {
97 if (index < 0 || index >= static_cast<int>(m_tabs.size())) {
98 return nullptr;
99 }
100 return m_tabs[index].get();
101}
102
104 if (m_activeTabIndex < 0 || m_activeTabIndex >= static_cast<int>(m_tabs.size())) {
105 return nullptr;
106 }
107 return m_tabs[m_activeTabIndex].get();
108}
109
110bool SidePanel::SetActiveTab(int index) {
111 if (index < 0 || index >= static_cast<int>(m_tabs.size()) || !m_notebook) {
112 return false;
113 }
114 m_notebook->SetSelection(index);
115 m_activeTabIndex = index;
116 return true;
117}
118
119bool SidePanel::HasTabWithName(const wxString &name) const {
120 for (const auto &tab : m_tabs) {
121 if (tab && tab->GetTitle() == name) {
122 return true;
123 }
124 }
125 return false;
126}
127
129 if (!m_notebook) {
130 return;
131 }
132 while (m_notebook->GetPageCount() > 0) {
133 RemoveTab(0);
134 }
135 m_activeTabIndex = -1;
136}
137
141
142void SidePanel::OnTabChanged(wxAuiNotebookEvent &event) {
143 int sel = event.GetSelection();
144 if (sel != wxNOT_FOUND) {
145 m_activeTabIndex = sel;
146 ITab *tab = GetTab(sel);
147 if (tab) {
148 OnActiveTabChanged(tab, sel);
149 }
150 }
151 event.Skip();
152}
153
154void SidePanel::OnTabClosed(wxAuiNotebookEvent &event) {
155 int closedIndex = event.GetSelection();
156
157 if (closedIndex >= 0 && closedIndex < static_cast<int>(m_tabs.size())) {
158 if (m_tabs[closedIndex]) {
159 m_tabs[closedIndex]->OnClosed();
160 OnTabRemoved(m_tabs[closedIndex].get(), closedIndex);
161 }
162 m_tabs[closedIndex].release();
163 }
164
165 CallAfter([this, closedIndex]() {
166 if (closedIndex >= 0 && closedIndex < static_cast<int>(m_tabs.size())) {
167 m_tabs.erase(m_tabs.begin() + closedIndex);
168
169 if (m_activeTabIndex == closedIndex) {
171 m_tabs.empty() ? -1 : std::min(m_activeTabIndex, static_cast<int>(m_tabs.size()) - 1);
172 } else if (m_activeTabIndex > closedIndex) {
174 }
175 }
176 });
177
178 event.Skip();
179}
180
181} // namespace EmberUI
BehaviorTreeProjectDialog::OnProjectNameChanged BehaviorTreeProjectDialog::OnRemoveFiles wxEND_EVENT_TABLE() BehaviorTreeProjectDialog
std::unique_ptr< ITab > ITabPtr
Definition ITab.h:54
Base class for all panels with layout, theme, and state management.
Definition Panel.h:11
void SetMainSizer(wxSizer *sizer)
Sets the main sizer.
Definition Panel.cpp:138
Tabbed side panel using wxAuiNotebook.
Definition SidePanel.h:12
virtual ITabPtr RemoveTab(int index)
Removes the tab at the given index; returns the removed tab.
Definition SidePanel.cpp:70
bool HasTabWithName(const wxString &name) const
Returns true if a tab with the given name exists.
void OnTabChanged(wxAuiNotebookEvent &event)
std::vector< ITabPtr > m_tabs
Definition SidePanel.h:51
virtual void ClearAllTabs()
Removes all tabs.
virtual int AddTab(ITabPtr tab)
Adds a tab and returns its index.
Definition SidePanel.cpp:48
virtual void CreateNotebook()
Hook: creates the notebook control. Override to customize.
Definition SidePanel.cpp:39
ITab * GetActiveTab() const
Returns the currently active tab, or nullptr.
virtual ~SidePanel()
Definition SidePanel.cpp:19
virtual void OnTabRemoved(ITab *tab, int index)
Hook: called when a tab is removed.
void OnTabClosed(wxAuiNotebookEvent &event)
virtual void OnTabAdded(ITab *tab, int index)
Hook: called when a tab is added.
virtual bool SetActiveTab(int index)
Sets the active tab by index; returns true on success.
virtual void OnActiveTabChanged(ITab *tab, int index)
Hook: called when the active tab changes.
void CreateLayout() override
Creates the side panel layout with the notebook.
Definition SidePanel.cpp:27
wxAuiNotebook * m_notebook
Definition SidePanel.h:50
ITab * GetTab(int index) const
Returns the tab at the given index, or nullptr.
Definition SidePanel.cpp:96
Interface for tab-based UI components in the application.
Definition ITab.h:7
Definition Panel.h:8
wxBEGIN_EVENT_TABLE(Panel, wxPanel) EVT_SIZE(Panel
Definition Panel.cpp:8