!XT (Code) Update copyright headers in Code/Sandbox.
[CRYENGINE.git] / Code / Sandbox / Plugins / EditorCommon / DockingSystem / DockableContainer.cpp
blob6461be66efc884acf33a882e0112b895b59cda98
1 // Copyright 2001-2018 Crytek GmbH / Crytek Group. All rights reserved.
3 #include "StdAfx.h"
4 #include "DockableContainer.h"
5 #include "QTrackingTooltip.h"
6 #include "Menu/AbstractMenu.h"
8 QToolWindowManagerClassFactory* CDockableContainer::s_dockingFactory = nullptr;
10 CDockableContainer::CDockableContainer(QWidget* parent, QVariantMap startingLayout /*= QVariantMap()*/)
11 : QWidget(parent), m_startingLayout(startingLayout), m_toolManager(nullptr), m_defaultLayoutCallback(nullptr), m_pMenu(nullptr)
15 CDockableContainer::~CDockableContainer()
17 if (m_toolManager)
19 disconnect(m_layoutChangedConnection);
22 for (auto& pair : m_spawned)
24 disconnect(pair.second.m_widget, 0, this, 0);
26 m_spawned.clear();
29 void CDockableContainer::Register(QString name, std::function<QWidget*()> factory, bool isUnique, bool isInternal)
31 m_registry[name] = FactoryInfo(factory, isUnique, isInternal);
34 QWidget* CDockableContainer::Spawn(QString name, QString forceObjectName)
36 auto it = m_registry.find(name);
37 if (it != m_registry.end())
39 if (it->second.m_isUnique)
41 for (auto wi : m_spawned)
43 if (wi.second.m_spawnName == name)
45 // Already created, return existing instance
46 return wi.second.m_widget;
50 QWidget* w = it->second.m_factory();
51 if (forceObjectName.isEmpty())
53 w->setObjectName(CreateObjectName(name));
55 else
57 w->setObjectName(forceObjectName);
59 m_spawned[w->objectName()] = WidgetInstance(w, name);
60 connect(w, &QObject::destroyed, this, &CDockableContainer::OnWidgetDestroyed);
62 return w;
64 return nullptr;
67 QWidget* CDockableContainer::SpawnWidget(QString name, const QToolWindowAreaTarget& target)
69 return SpawnWidget(name, "", target);
72 QWidget* CDockableContainer::SpawnWidget(QString name, QWidget* pTargetWidget, const QToolWindowAreaTarget& target)
74 IToolWindowArea* pToolArea = m_toolManager->areaOf(pTargetWidget);
75 if (pToolArea)
77 return SpawnWidget(name, "", pToolArea, target.reference, target.index, target.geometry);
79 return nullptr;
82 QWidget* CDockableContainer::SpawnWidget(QString name, QString objectName, const QToolWindowAreaTarget& target)
84 return SpawnWidget(name, objectName, target.area, target.reference, target.index, target.geometry);
87 QWidget* CDockableContainer::SpawnWidget(QString name, IToolWindowArea* area /*= nullptr*/, QToolWindowAreaReference reference /*= QToolWindowAreaTarget::Combine*/, int index /*= -1*/, QRect geometry /*= QRect()*/)
89 return SpawnWidget(name, "", area, reference, index, geometry);
92 QWidget* CDockableContainer::SpawnWidget(QString name, QString objectName, IToolWindowArea* area /*= nullptr*/, QToolWindowAreaReference reference /*= QToolWindowManager::AreaReference::Combine*/, int index /*= -1*/, QRect geometry /*= QRect()*/)
94 QWidget* w = Spawn(name, objectName);
95 if (w)
97 if (!m_toolManager->ownsToolWindow(w)) //If it's already owned, this is a single-instance widget, so don't move it
99 m_toolManager->addToolWindow(w, area, reference, index, geometry);
101 m_toolManager->bringToFront(w);
103 return w;
106 void CDockableContainer::SetDefaultLayoutCallback(std::function<void(CDockableContainer*)> callback)
108 m_defaultLayoutCallback = callback;
111 void CDockableContainer::SetMenu(CAbstractMenu* pAbstractMenu)
113 m_pMenu = pAbstractMenu;
116 void CDockableContainer::SetSplitterSizes(QWidget* widget, QList<int> sizes)
118 m_toolManager->resizeSplitter(widget, sizes);
121 QVariantMap CDockableContainer::GetState() const
123 QVariantMap result;
124 if (m_toolManager)
126 QVariantMap stateMap;
127 for (auto sw : m_spawned)
129 CDockableContainer::WidgetInstance& w = sw.second;
130 if (m_toolManager->areaOf(w.m_widget))
132 QVariantMap toolData;
133 toolData.insert("class", w.m_spawnName);
134 IStateSerializable* ssw = qobject_cast<IStateSerializable*>(w.m_widget);
135 if (ssw)
137 toolData.insert("state", ssw->GetState());
139 stateMap[w.m_widget->objectName()] = toolData;
142 result["Windows"] = stateMap;
143 result["ToolsLayout"] = m_toolManager->saveState();
145 return result;
148 void CDockableContainer::SetState(const QVariantMap& state)
150 if (!m_toolManager)
152 m_startingLayout = state;
153 return;
155 auto lock = m_toolManager->getNotifyLock(false);
156 m_toolManager->hide();
157 m_toolManager->clear();
158 m_spawned.clear();
159 QVariantMap openToolsMap = state.value("Windows").toMap();
160 for (QVariantMap::const_iterator iter = openToolsMap.begin(); iter != openToolsMap.end(); ++iter)
162 QString key = iter.key();
163 QVariantMap v = iter.value().toMap();
164 QString className = v.value("class").toString();
165 QVariantMap toolState = v.value("state", QVariantMap()).toMap();
167 QWidget* w = SpawnWidget(className, key);
168 IStateSerializable* ssw = qobject_cast<IStateSerializable*>(w);
169 if (w)
171 if (!toolState.empty() && ssw)
173 ssw->SetState(toolState);
178 m_toolManager->restoreState(state["ToolsLayout"]);
179 BuildWindowMenu();
180 m_toolManager->show();
181 m_startingLayout = QVariantMap();
184 void CDockableContainer::OnWidgetDestroyed(QObject* pObject)
186 auto it = m_spawned.find(pObject->objectName());
187 if (it != m_spawned.end() && it->second.m_widget == pObject)
189 m_spawned.erase(it);
190 BuildWindowMenu();
194 QString CDockableContainer::CreateObjectName(QString title) const
196 QString result = title;
197 while (m_spawned.find(result) != m_spawned.end())
199 int i = qrand();
200 result = QString::asprintf("%s#%d", title.toStdString().c_str(), i);
202 return result;
205 void CDockableContainer::showEvent(QShowEvent* event)
207 // Construct everything in the show event to ensure owner is fully constructed
208 if (m_toolManager)
210 return;
213 QVariantMap config = CEditorDialog::s_config;
214 config[QTWM_RELEASE_POLICY] = rcpDelete;
215 m_toolManager = new QToolWindowManager(this, config, s_dockingFactory);
216 connect(m_toolManager, &QToolWindowManager::updateTrackingTooltip, [](const QString& str, const QPoint& p) { QTrackingTooltip::ShowTextTooltip(str, p); });
217 setLayout(new QVBoxLayout());
218 layout()->setContentsMargins(0, 0, 0, 0);
219 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
220 layout()->addWidget(m_toolManager);
221 if (!m_startingLayout.isEmpty())
223 SetState(m_startingLayout);
225 else
227 m_defaultLayoutCallback(this);
230 m_layoutChangedConnection = connect(m_toolManager, &QToolWindowManager::layoutChanged, [=]() { OnLayoutChange(GetState()); BuildWindowMenu(); });
231 BuildWindowMenu();
234 void CDockableContainer::BuildWindowMenu()
236 if (!m_pMenu)
238 return;
241 m_pMenu->Clear();
243 CAbstractMenu* addMenu = nullptr;
244 for (auto it : m_registry)
246 if (it.second.m_isInternal)
248 continue;
251 if (!addMenu)
253 addMenu = m_pMenu->CreateMenu("&Add Pane");
256 QString s = it.first;
257 QAction* action = addMenu->CreateAction(s);
258 connect(action, &QAction::triggered, [=]() { return SpawnWidget(s); });
261 QAction* action = m_pMenu->CreateAction("&Reset layout");
262 connect(action, &QAction::triggered, [=] { ResetLayout(); });
264 int sec = m_pMenu->GetNextEmptySection();
266 foreach(QWidget* q, m_toolManager->toolWindows())
268 QAction* action = m_pMenu->CreateAction(q->windowTitle(), sec);
269 connect(action, &QAction::triggered, [=] { m_toolManager->bringToFront(q); });
273 void CDockableContainer::ResetLayout()
275 QToolWindowManager::QTWMNotifyLock lock = m_toolManager->getNotifyLock();
276 m_toolManager->hide();
277 m_toolManager->clear();
278 m_spawned.clear();
279 m_defaultLayoutCallback(this);
280 m_toolManager->show();
283 CDockableContainer::FactoryInfo::FactoryInfo(std::function<QWidget*()> factory, bool isUnique, bool isInternal) : m_factory(factory), m_isUnique(isUnique), m_isInternal(isInternal)
287 CDockableContainer::WidgetInstance::WidgetInstance(QWidget* widget, QString spawnName) : m_widget(widget), m_spawnName(spawnName)