Ember
Loading...
Searching...
No Matches
SidePanel.cpp
Go to the documentation of this file.
1#include "App/MainFrame.h"
8#include "Utils/Logger.h"
10#include <algorithm>
11#include <ctime>
12#include <fstream>
13#include <typeinfo>
14#include <wx/artprov.h>
15#include <wx/bmpbuttn.h>
16#include <wx/filename.h>
17#include <wx/menu.h>
18#include <wx/sizer.h>
19
20#ifdef HAVE_WXSVG
21#include <wxSVG/imagsvg.h>
22#include <wxSVG/svg.h>
23#endif
24
27 EVT_AUINOTEBOOK_PAGE_CLOSE(SidePanel::ID_BASE_NOTEBOOK, SidePanel::OnTabClosed)
30
31 SidePanel::SidePanel(wxWindow *parent, MainFrame *mainFrame, const wxString &panelName,
32 EmberForge::PanelType panelType, EmberForge::PanelDescriptor *parentDescriptor)
33 : EmberUI::SidePanel(parent, panelName, false), m_mainFrame(mainFrame), m_panelName(panelName),
34 m_tabBarButtonsEnabled(true), m_isInitializing(true),
35 m_descriptor(panelType, parentDescriptor ? parentDescriptor->GetHierarchyLevel() + 1 : 0, parentDescriptor) {
36 LOG_INFO("Panel", std::string("Creating side panel: ") + m_panelName.ToStdString() +
37 " (Type: " + m_descriptor.GetDisplayName().ToStdString() +
38 ", Level: " + std::to_string(m_descriptor.GetHierarchyLevel()) + ")");
39 DoCreateLayout();
40}
41
43 LOG_INFO("Panel", std::string("Destroying side panel: ") + m_panelName.ToStdString());
44
45 if (m_notebook) {
46 while (m_notebook->GetPageCount() > 0) {
47 m_notebook->RemovePage(0);
48 }
49 }
50}
51
53
55 wxBoxSizer *mainSizer = new wxBoxSizer(wxVERTICAL);
56
59
60 if (m_notebook) {
61 mainSizer->Add(m_notebook, 1, wxEXPAND | wxALL, 2);
62 }
63
64 SetSizer(mainSizer);
65
66 LOG_INFO("Panel", std::string("Layout created for side panel: ") + m_panelName.ToStdString());
67}
68
70 LOG_INFO("Panel", std::string("Calling OnPanelSpecificSetup() for ") + m_panelName.ToStdString() +
71 " (type: " + std::string(typeid(*this).name()) + ")");
73 LOG_INFO("Panel", std::string("OnPanelSpecificSetup() completed for ") + m_panelName.ToStdString());
74
75 if (m_notebook) {
76 LOG_INFO("Panel", std::string("Notebook has ") + std::to_string(m_notebook->GetPageCount()) +
77 " pages after OnPanelSpecificSetup()");
78 }
79}
80
82
84 long style = wxAUI_NB_DEFAULT_STYLE;
85 style &= ~wxAUI_NB_TAB_MOVE;
86 style &= ~wxAUI_NB_TAB_EXTERNAL_MOVE;
87 style &= ~wxAUI_NB_TAB_SPLIT;
88
89 m_notebook = new EmberForge::CustomAuiNotebook(this, ID_BASE_NOTEBOOK, wxDefaultPosition, wxDefaultSize, style);
90
91 Bind(EmberForge::EVT_TAB_ART_ADD_BUTTON, &SidePanel::OnTabBarAddButtonClicked, this);
92 Bind(EmberForge::EVT_TAB_ART_MENU_BUTTON, &SidePanel::OnTabBarMenuButtonClicked, this);
93
94 LOG_TRACE("Panel", std::string("Created CustomAuiNotebook for ") + m_panelName.ToStdString() +
95 " with integrated tab bar buttons");
96}
97
99
101 LOG_TRACE("Panel", std::string("Event handlers set up for %s") + m_panelName.ToStdString());
102}
103
105 LOG_INFO("Panel", std::string("Base OnPanelSpecificSetup() called for %s") + m_panelName.ToStdString());
106}
107
109 LOG_INFO("Panel", std::string("*** RestoreAndEnsureTabs() called for ") + m_panelName.ToStdString() + " ***");
110
111 if (GetRememberLastTab()) {
112 const auto &lastOpenTabs = GetLastOpenTabs();
113 if (!lastOpenTabs.empty()) {
114 LOG_INFO("Panel", wxString::Format("Restoring %zu saved tabs", lastOpenTabs.size()).ToStdString());
115 for (const auto &tabTypeStr : lastOpenTabs) {
117 CreateAndAddTab(tabType);
118 }
119 }
120 }
121
122 if (!m_notebook || m_notebook->GetPageCount() == 0) {
123 LOG_INFO("Panel", "No tabs exist, trying to create a default tab");
124
125 auto supportedTypes = GetSupportedTabTypes();
126 for (const auto &tabType : supportedTypes) {
127 size_t countBefore = m_notebook ? m_notebook->GetPageCount() : 0;
128 CreateAndAddTab(tabType);
129 size_t countAfter = m_notebook ? m_notebook->GetPageCount() : 0;
130
131 if (countAfter > countBefore) {
132 LOG_INFO("Panel", wxString::Format("Created fallback tab: %s",
134 .ToStdString());
135 break;
136 }
137 }
138
139 if (m_notebook && m_notebook->GetPageCount() == 0) {
140 LOG_ERROR("Panel", std::string("Failed to create any default tab for ") + m_panelName.ToStdString() +
141 " - all supported types at max instances");
142 }
143 }
144
146
147 if (m_notebook && m_notebook->GetPageCount() > 0) {
148 std::string tabToActivate = GetRememberLastTab() ? GetLastActiveTab() : GetDefaultActiveTab();
149
151 wxString targetTabName = EmberForge::TabFactory::GetTabDisplayName(targetTabType);
152
153 int targetIndex = 0;
154 for (size_t i = 0; i < m_notebook->GetPageCount(); ++i) {
155 if (m_notebook->GetPageText(i) == targetTabName) {
156 targetIndex = static_cast<int>(i);
157 break;
158 }
159 }
160
161 m_notebook->SetSelection(targetIndex);
162 LOG_INFO("Panel", wxString::Format("Set active tab to '%s' (index %d) [rememberLastTab=%s], total tabs: %d",
163 targetTabName, targetIndex, GetRememberLastTab() ? "true" : "false",
164 static_cast<int>(m_notebook->GetPageCount()))
165 .ToStdString());
166 }
167
168 LOG_INFO("Panel", std::string("RestoreAndEnsureTabs() completed for ") + m_panelName.ToStdString());
169}
170
172 if (!tab || !m_notebook) {
173 LOG_ERROR("Panel", std::string("Cannot add null tab to %s") + m_panelName.ToStdString());
174 return -1;
175 }
176
177 wxString tabTitle = tab->GetTitle();
178
179 int index = EmberUI::SidePanel::AddTab(std::move(tab));
180
181 if (index >= 0) {
182 LOG_INFO("Panel", std::string("Added tab '") + tabTitle.ToStdString() + "' to " + m_panelName.ToStdString() +
183 " at index " + std::to_string(index));
184 SaveState();
185
187 std::string configPath = EmberForge::AppPreferences::GetDefaultConfigPath();
188 if (prefManager.GetPreferences().SaveToFile(configPath)) {
189 LOG_INFO("Panel", "Saved tab state to disk after tab addition");
190 } else {
191 LOG_ERROR("Panel", "Failed to save tab state to disk after tab addition");
192 }
193 } else {
194 LOG_ERROR("Panel",
195 std::string("Failed to add tab '") + tabTitle.ToStdString() + "' to " + m_panelName.ToStdString());
196 }
197 return index;
198}
199
201 if (index < 0 || index >= static_cast<int>(m_tabs.size()) || !m_notebook) {
202 LOG_ERROR("Panel",
203 std::string("Invalid tab index ") + std::to_string(index) + " for " + m_panelName.ToStdString());
204 return nullptr;
205 }
206
207 ITabPtr removed = EmberUI::SidePanel::RemoveTab(index);
208 if (removed) {
209 LOG_INFO("Panel",
210 std::string("Removed tab at index ") + std::to_string(index) + " from " + m_panelName.ToStdString());
211 } else {
212 LOG_ERROR("Panel", std::string("Failed to remove tab at index ") + std::to_string(index) + " from " +
213 m_panelName.ToStdString());
214 }
215 return removed;
216}
217
218bool SidePanel::SetActiveTab(int index) {
219 bool result = EmberUI::SidePanel::SetActiveTab(index);
220 if (result) {
221 LOG_TRACE("Panel",
222 std::string("Set active tab to index ") + std::to_string(index) + " in " + m_panelName.ToStdString());
223 }
224 return result;
225}
226
228 if (!m_notebook) {
229 return;
230 }
231
232 wxString defaultTabName = EmberForge::TabFactory::GetTabDisplayName(defaultTabType);
233 LOG_INFO("Panel", std::string("Resetting ") + m_panelName.ToStdString() +
234 " to default tab: " + defaultTabName.ToStdString());
235
236 wxWindow *defaultTabWindow = nullptr;
237 for (size_t i = 0; i < m_notebook->GetPageCount(); ++i) {
238 if (m_notebook->GetPageText(i) == defaultTabName) {
239 defaultTabWindow = m_notebook->GetPage(i);
240 break;
241 }
242 }
243
244 for (int i = static_cast<int>(m_notebook->GetPageCount()) - 1; i >= 0; --i) {
245 if (m_notebook->GetPage(i) != defaultTabWindow) {
246 RemoveTab(i);
247 }
248 }
249
250 if (defaultTabWindow == nullptr) {
251 CreateAndAddTab(defaultTabType);
252 }
253
254 if (m_notebook->GetPageCount() > 0) {
255 m_notebook->SetSelection(0);
257 }
258
259 LOG_INFO("Panel", std::string("Reset ") + m_panelName.ToStdString() +
260 " complete, tab count: " + std::to_string(m_notebook->GetPageCount()));
261}
262
263void SidePanel::ResetToDefaultTabs(const std::vector<EmberForge::TabType> &defaultTabTypes) {
264 if (!m_notebook || defaultTabTypes.empty()) {
265 return;
266 }
267
268 LOG_INFO("Panel", std::string("Resetting ") + m_panelName.ToStdString() + " to " +
269 std::to_string(defaultTabTypes.size()) + " default tabs");
270
271 while (m_notebook->GetPageCount() > 0) {
272 RemoveTab(0);
273 }
274
275 for (const auto &tabType : defaultTabTypes) {
276 CreateAndAddTab(tabType);
277 }
278
279 if (m_notebook->GetPageCount() > 0) {
280 m_notebook->SetSelection(0);
282 }
283
284 LOG_INFO("Panel", std::string("Reset ") + m_panelName.ToStdString() +
285 " complete, tab count: " + std::to_string(m_notebook->GetPageCount()));
286}
287
289 if (!m_notebook) {
290 return;
291 }
292
293 LOG_INFO("Panel", std::string("Clearing all tabs from ") + m_panelName.ToStdString());
294
296}
297
298void SidePanel::OnTabChanged(wxAuiNotebookEvent &event) {
299 int newSelection = event.GetSelection();
300 if (newSelection != wxNOT_FOUND) {
301 m_activeTabIndex = newSelection;
302 LOG_TRACE("Panel", std::string("Tab changed to index ") + std::to_string(newSelection) + " in " +
303 m_panelName.ToStdString());
304
305 SaveState();
306
307 if (!m_isInitializing) {
309 std::string configPath = EmberForge::AppPreferences::GetDefaultConfigPath();
310 if (prefManager.GetPreferences().SaveToFile(configPath)) {
311 LOG_TRACE("Panel", "Saved active tab state to disk after tab change");
312 } else {
313 LOG_ERROR("Panel", "Failed to save active tab state to disk after tab change");
314 }
315 }
316 }
317 event.Skip();
318}
319
320void SidePanel::OnTabClosed(wxAuiNotebookEvent &event) {
321 int closedIndex = event.GetSelection();
322 LOG_INFO("Panel", std::string("Tab at index ") + std::to_string(closedIndex) + " closed");
323
324 if (closedIndex >= 0 && closedIndex < static_cast<int>(m_tabs.size())) {
325 if (m_tabs[closedIndex]) {
326 m_tabs[closedIndex]->OnClosed();
327 }
328 m_tabs[closedIndex].release();
329 }
330
331 CallAfter([this, closedIndex]() {
332 if (closedIndex >= 0 && closedIndex < static_cast<int>(m_tabs.size())) {
333 m_tabs.erase(m_tabs.begin() + closedIndex);
334
335 if (m_activeTabIndex == closedIndex) {
337 m_tabs.empty() ? -1 : std::min(m_activeTabIndex, static_cast<int>(m_tabs.size()) - 1);
338 } else if (m_activeTabIndex > closedIndex) {
340 }
341
342 SaveState();
343
345 std::string configPath = EmberForge::AppPreferences::GetDefaultConfigPath();
346 if (prefManager.GetPreferences().SaveToFile(configPath)) {
347 LOG_INFO("Panel", "Saved tab state to disk after tab removal");
348 } else {
349 LOG_ERROR("Panel", "Failed to save tab state to disk after tab removal");
350 }
351 }
352 });
353
354 event.Skip();
355}
356
357void SidePanel::OnAddTabButtonClickedInternal(wxCommandEvent &event) {
358 LOG_INFO("Panel", std::string("Add tab button clicked in %s") + m_panelName.ToStdString());
359
361
362 if (event.GetSkipped()) {
364 }
365}
366
367void SidePanel::OnTabBarAddButtonClicked(wxCommandEvent &event) {
368 LOG_INFO("Panel", std::string("Tab bar add button clicked in %s") + m_panelName.ToStdString());
369
370 wxCommandEvent addEvent;
372}
373
374void SidePanel::OnTabBarMenuButtonClicked(wxCommandEvent &event) {
375 LOG_INFO("Panel", std::string("Tab bar menu button clicked in %s") + m_panelName.ToStdString());
376
377 wxCommandEvent menuEvent;
378 OnMenuButtonClicked(menuEvent);
379}
380
381void SidePanel::OnMenuButtonClicked(wxCommandEvent &event) {
382 LOG_INFO("Panel", std::string("Menu button clicked in %s") + m_panelName.ToStdString());
383
384 wxMenu *mainMenu = new wxMenu();
385
386 mainMenu->Append(ID_BASE_HIDE_PANEL_MENU_ITEM, "Hide Panel", "Hide this panel from view");
387 mainMenu->AppendSeparator();
388 mainMenu->Append(ID_BASE_PREFERENCES_MENU_ITEM, "Preferences...", "Open preferences for this panel");
389
390 PopupMenu(mainMenu);
391 delete mainMenu;
392}
393
394void SidePanel::OnHidePanelClicked(wxCommandEvent &event) {
395 LOG_INFO("Panel", std::string("Hide panel clicked in %s") + m_panelName.ToStdString());
396
397 if (!m_mainFrame) {
398 LOG_ERROR("Panel", "Cannot hide panel - no MainFrame reference");
399 return;
400 }
401
402 wxAuiManager *auiManager = m_mainFrame->GetAuiManager();
403 if (!auiManager) {
404 LOG_ERROR("Panel", "Cannot hide panel - no AUI manager");
405 return;
406 }
407
408 wxString paneName = m_descriptor.GetPaneName();
409
410 wxAuiPaneInfo &pane = auiManager->GetPane(paneName);
411 if (pane.IsOk()) {
412 pane.Hide();
413 auiManager->Update();
414 m_mainFrame->UpdatePanelToggleButtons();
415 LOG_INFO("Panel", std::string("Panel hidden: ") + m_panelName.ToStdString());
416 }
417}
418
419void SidePanel::OnPanelPreferencesClicked(wxCommandEvent &event) {
420 LOG_INFO("Panel", std::string("Preferences clicked in %s") + m_panelName.ToStdString());
421
422 if (!m_mainFrame) {
423 LOG_ERROR("Panel", "Cannot open preferences - no MainFrame reference");
424 return;
425 }
426
427 wxString sectionName = m_descriptor.GetDisplayName();
428
430 dialog.SelectSection(sectionName);
431
432 int result = dialog.ShowModal();
433 if (result == wxID_OK) {
434 LOG_INFO("Panel", std::string("Preferences applied for ") + m_panelName.ToStdString());
435 m_mainFrame->RefreshPreferences();
436 }
437}
438
440 if (!m_notebook || !m_mainFrame) {
441 LOG_ERROR("Panel",
442 std::string("Cannot create tab - missing notebook or mainframe in %s") + m_panelName.ToStdString());
443 return;
444 }
445
446 wxString tabName = EmberForge::TabFactory::GetTabDisplayName(tabType);
447 EmberForge::PanelType panelType = m_descriptor.GetType();
448
449 if (!EmberForge::TabFactory::IsTabAllowedInPanel(tabType, panelType)) {
450 LOG_WARNING("Panel",
451 std::string("Tab '") + tabName.ToStdString() + "' is not allowed in " + m_panelName.ToStdString());
452 return;
453 }
454
456 LOG_WARNING("Panel",
457 std::string("Tab '") + tabName.ToStdString() + "' already exists in " + m_panelName.ToStdString());
458 return;
459 }
460
461 int maxInstances = EmberForge::TabFactory::GetMaxGlobalInstances(tabType);
462 if (maxInstances > 0) {
463 int currentCount = m_mainFrame->CountTabGlobally(tabName);
464 if (currentCount >= maxInstances) {
465 LOG_WARNING("Panel", std::string("Tab '") + tabName.ToStdString() + "' has reached max instances (" +
466 std::to_string(maxInstances) + ")");
467 return;
468 }
469 }
470
472 if (tab) {
473 AddTab(std::move(tab));
474 LOG_INFO("Panel",
475 std::string("Created and added tab '") + tabName.ToStdString() + "' to " + m_panelName.ToStdString());
476 } else {
477 LOG_ERROR("Panel",
478 std::string("Failed to create tab '") + tabName.ToStdString() + "' for " + m_panelName.ToStdString());
479 }
480}
481
483 auto supportedTypes = GetSupportedTabTypes();
484 if (supportedTypes.empty()) {
485 LOG_WARNING("Panel", std::string("No supported tab types for %s") + m_panelName.ToStdString());
486 return;
487 }
488
489 wxMenu menu;
490 EmberForge::PanelType panelType = m_descriptor.GetType();
491 int validItems = 0;
492
493 for (size_t i = 0; i < supportedTypes.size(); ++i) {
494 EmberForge::TabType tabType = supportedTypes[i];
495
496 if (!EmberForge::TabFactory::IsTabAllowedInPanel(tabType, panelType)) {
497 continue;
498 }
499
500 wxString displayName = EmberForge::TabFactory::GetTabDisplayName(tabType);
501 wxString tooltip = EmberForge::TabFactory::GetTabTooltip(tabType);
502
503 int menuId = ID_BASE_LAST + static_cast<int>(i);
504 wxMenuItem *item = menu.Append(menuId, displayName, tooltip);
505 validItems++;
506
507 bool existsInThisPanel =
509
510 int maxInstances = EmberForge::TabFactory::GetMaxGlobalInstances(tabType);
511 int currentCount = m_mainFrame->CountTabGlobally(displayName);
512 bool atMaxInstances = (maxInstances > 0) && (currentCount >= maxInstances);
513
514 if (existsInThisPanel || atMaxInstances) {
515 item->Enable(false);
516 if (atMaxInstances && !existsInThisPanel) {
517 if (maxInstances == 1) {
518 item->SetItemLabel(displayName + " (open in another panel)");
519 } else {
520 item->SetItemLabel(displayName + " (max " + std::to_string(maxInstances) + " reached)");
521 }
522 }
523 }
524
525 menu.Bind(
526 wxEVT_COMMAND_MENU_SELECTED, [this, tabType](wxCommandEvent &) { CreateAndAddTab(tabType); }, menuId);
527 }
528
529 if (validItems == 0) {
530 wxMenuItem *item = menu.Append(wxID_ANY, "(No tabs available for this panel)");
531 item->Enable(false);
532 }
533
534 PopupMenu(&menu);
535
536 LOG_TRACE("Panel", std::string("Showed tab creation menu for ") + m_panelName.ToStdString() + " with " +
537 std::to_string(validItems) + " options");
538}
539
541 if (m_tabBarButtonsEnabled == enabled) {
542 return;
543 }
544
545 m_tabBarButtonsEnabled = enabled;
546
547 if (m_notebook) {
549 LOG_INFO("Panel", std::string("Tab bar buttons ") + (enabled ? "enabled" : "disabled") + " for " +
550 m_panelName.ToStdString());
551 }
552}
553
556 LOG_INFO("Panel", std::string("Tab bar buttons toggled to ") + (m_tabBarButtonsEnabled ? "enabled" : "disabled") +
557 " for " + m_panelName.ToStdString());
558}
559
561 LOG_INFO("SidePanel", std::string("Base ApplyPreferences called for ") + m_panelName.ToStdString() +
562 " - derived class should override this");
563}
564
566 LOG_INFO("SidePanel", std::string("Base SaveState called for ") + m_panelName.ToStdString() +
567 " - derived class should override this");
568}
569
571 LOG_INFO("SidePanel", std::string("Base RestoreState called for ") + m_panelName.ToStdString() +
572 " - derived class should override this");
573}
BehaviorTreeProjectDialog::OnProjectNameChanged BehaviorTreeProjectDialog::OnRemoveFiles wxEND_EVENT_TABLE() BehaviorTreeProjectDialog
wxBEGIN_EVENT_TABLE(SidePanel, EmberUI::SidePanel) EVT_AUINOTEBOOK_PAGE_CHANGED(SidePanel
Definition SidePanel.cpp:25
std::unique_ptr< ITab > ITabPtr
Definition ITab.h:54
#define LOG_ERROR(category, message)
Definition Logger.h:116
#define LOG_TRACE(category, message)
Definition Logger.h:113
#define LOG_WARNING(category, message)
Definition Logger.h:115
#define LOG_INFO(category, message)
Definition Logger.h:114
MainFrame::OnExit EVT_MENU(wxID_ABOUT, MainFrame::OnAbout) EVT_MENU(ID_NewProject
Centralized resource path management for EmberForge.
static AppPreferencesManager & GetInstance()
static EmberCore::String GetDefaultConfigPath()
Custom wxAuiNotebook that integrates Add Tab and Menu buttons into the tab bar.
void SetTabBarButtonsEnabled(bool enabled)
Enable or disable the integrated tab bar buttons.
static wxString GetTabDisplayName(TabType type)
Get the display name for a tab type.
static wxString GetTabTooltip(TabType type)
Get the tooltip text for a tab type.
static std::unique_ptr< ITab > CreateTab(TabType type, wxWindow *parent, MainFrame *mainFrame=nullptr)
Create a tab of the specified type.
static int GetMaxGlobalInstances(TabType type)
Get the maximum number of instances allowed globally across all panels.
static bool IsTabAllowedInPanel(TabType tabType, EmberForge::PanelType panelType)
Check if a tab type is allowed in a specific panel type.
static bool AllowMultipleInstances(TabType type)
Check if a tab type can be created multiple times within a single panel.
static TabType StringToTabType(const std::string &str)
Convert string identifier to tab type.
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.
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 bool SetActiveTab(int index)
Sets the active tab by index; returns true on success.
wxAuiNotebook * m_notebook
Definition SidePanel.h:50
Main application window for EmberForge.
Definition MainFrame.h:67
Preferences dialog for configuring EmberForge application settings.
bool SelectSection(const wxString &sectionName)
Select a section in the preferences tree by name.
void SetTabBarButtonsEnabled(bool enabled)
@ ID_BASE_PREFERENCES_MENU_ITEM
@ ID_BASE_HIDE_PANEL_MENU_ITEM
void FinishSetup()
Definition SidePanel.cpp:69
virtual void ApplyPreferences()
void DoCreateNotebook()
Definition SidePanel.cpp:83
bool SetActiveTab(int index) override
Sets the active tab by index; returns true on success.
void OnTabChanged(wxAuiNotebookEvent &event)
virtual const std::vector< std::string > & GetLastOpenTabs() const =0
void OnHidePanelClicked(wxCommandEvent &event)
void DoCreateLayout()
Definition SidePanel.cpp:54
void ResetToDefaultTab(EmberForge::TabType defaultTabType)
void RestoreAndEnsureTabs()
bool m_tabBarButtonsEnabled
void ClearAllTabs() override
Removes all tabs.
virtual void SetupEventHandlers()
Definition SidePanel.cpp:98
virtual ~SidePanel()
Definition SidePanel.cpp:42
void OnPanelPreferencesClicked(wxCommandEvent &event)
EmberForge::CustomAuiNotebook * GetCustomNotebook() const
virtual void OnMenuButtonClicked(wxCommandEvent &event)
virtual void OnPanelSpecificSetup()
void DoSetupEventHandlers()
void OnAddTabButtonClickedInternal(wxCommandEvent &event)
MainFrame * m_mainFrame
void OnTabClosed(wxAuiNotebookEvent &event)
virtual std::string GetLastActiveTab() const =0
void ShowTabCreationMenu()
wxString m_panelName
void ToggleTabBarButtons()
virtual void OnAddTabButtonClicked(wxCommandEvent &event)
virtual void RestoreState()
void OnTabBarMenuButtonClicked(wxCommandEvent &event)
virtual bool GetRememberLastTab() const =0
void CreateAndAddTab(EmberForge::TabType tabType)
virtual void SaveState()
EmberForge::PanelDescriptor m_descriptor
void ResetToDefaultTabs(const std::vector< EmberForge::TabType > &defaultTabTypes)
void CreateNotebook() override
Hook: creates the notebook control. Override to customize.
Definition SidePanel.cpp:81
bool m_isInitializing
virtual std::vector< EmberForge::TabType > GetSupportedTabTypes() const
void OnTabBarAddButtonClicked(wxCommandEvent &event)
void CreateLayout() override
Creates the side panel layout with the notebook.
Definition SidePanel.cpp:52
int AddTab(ITabPtr tab) override
Adds a tab and returns its index.
virtual std::string GetDefaultActiveTab() const =0
ITabPtr RemoveTab(int index) override
Removes the tab at the given index; returns the removed tab.
PanelType
Defines the type of panel in the UI hierarchy.
TabType
Enumeration of available tab types.
Definition TabFactory.h:17
Definition Panel.h:8