Просмотр исходного кода

Added multiple tabs to windows (WIP)
Dock area is now displayed only over the content area of the widget

Marko Pintera 12 лет назад
Родитель
Сommit
48235497cb

+ 20 - 0
CamelotEditor/CamelotEditor.vcxproj

@@ -155,6 +155,7 @@
   </ItemDefinitionGroup>
   <ItemGroup>
     <ClCompile Include="GeneratedFiles\moc_CmQtDockOverlayWidget.cpp" />
+    <ClCompile Include="GeneratedFiles\moc_CmQtDynamicTabBar.cpp" />
     <ClCompile Include="GeneratedFiles\moc_CmQtEditor.cpp" />
     <ClCompile Include="GeneratedFiles\moc_CmQtEditorWidget.cpp" />
     <ClCompile Include="GeneratedFiles\moc_CmQtEditorWindow.cpp" />
@@ -180,6 +181,7 @@
     <ClCompile Include="Source\CmPreferences.cpp" />
     <ClCompile Include="Source\CmProjectPrefs.cpp" />
     <ClCompile Include="Source\CmQtDockOverlayWidget.cpp" />
+    <ClCompile Include="Source\CmQtDynamicTabBar.cpp" />
     <ClCompile Include="Source\CmQtEditor.cpp" />
     <ClCompile Include="Source\CmQtEditorWidget.cpp" />
     <ClCompile Include="Source\CmQtEditorWindow.cpp" />
@@ -332,6 +334,24 @@
       <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\moc_%(Filename).cpp</Outputs>
       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
     </CustomBuild>
+    <CustomBuild Include="Include\CmQtDynamicTabBar.h">
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\moc_%(Filename).cpp"  -DQT_NO_KEYWORDS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL  "-I.\GeneratedFiles" "-I.\Include" "-I.\Dependencies\Include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\CamelotCore\Include" "-I.\..\CamelotUtility\Include" "-I.\..\Dependencies\Include"</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Filename)...</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\GeneratedFiles\moc_%(Filename).cpp</Outputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\moc_%(Filename).cpp"  -DQT_NO_KEYWORDS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL  "-I.\GeneratedFiles" "-I.\Include" "-I.\Dependencies\Include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\CamelotCore\Include" "-I.\..\CamelotUtility\Include" "-I.\..\Dependencies\Include"</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Filename)...</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\GeneratedFiles\moc_%(Filename).cpp</Outputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\moc_%(Filename).cpp"  -DQT_NO_KEYWORDS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL  "-I.\GeneratedFiles" "-I.\Include" "-I.\Dependencies\Include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\CamelotCore\Include" "-I.\..\CamelotUtility\Include" "-I.\..\Dependencies\Include"</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Moc%27ing %(Filename)...</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\GeneratedFiles\moc_%(Filename).cpp</Outputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
+      <Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(QTDIR)\bin\moc.exe"  "%(FullPath)" -o ".\GeneratedFiles\moc_%(Filename).cpp"  -DQT_NO_KEYWORDS -DUNICODE -DWIN32 -DQT_LARGEFILE_SUPPORT -DQT_DLL  "-I.\GeneratedFiles" "-I.\Include" "-I.\Dependencies\Include" "-I.\GeneratedFiles\$(ConfigurationName)\." "-I.\..\CamelotCore\Include" "-I.\..\CamelotUtility\Include" "-I.\..\Dependencies\Include"</Command>
+      <Message Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Moc%27ing %(Filename)...</Message>
+      <Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\GeneratedFiles\moc_%(Filename).cpp</Outputs>
+      <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
+    </CustomBuild>
     <ClInclude Include="Include\CmSceneWidgetFactory.h" />
     <ClInclude Include="Include\CmWindowDockManager.h" />
     <CustomBuild Include="Include\CmQtNewProject.h">

+ 9 - 0
CamelotEditor/CamelotEditor.vcxproj.filters

@@ -111,6 +111,12 @@
     <ClCompile Include="GeneratedFiles\moc_CmQtEditorWidget.cpp">
       <Filter>Generated Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmQtDynamicTabBar.cpp">
+      <Filter>Source Files\Qt</Filter>
+    </ClCompile>
+    <ClCompile Include="GeneratedFiles\moc_CmQtDynamicTabBar.cpp">
+      <Filter>Generated Files</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="CmEditor.qrc">
@@ -140,6 +146,9 @@
     <CustomBuild Include="Include\CmQtHierarchyWidget.h">
       <Filter>Header Files\Qt</Filter>
     </CustomBuild>
+    <CustomBuild Include="Include\CmQtDynamicTabBar.h">
+      <Filter>Header Files\Qt</Filter>
+    </CustomBuild>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\CmEditorPrefs.h">

+ 4 - 1
CamelotEditor/Include/CmEditorPrerequisites.h

@@ -15,6 +15,7 @@ namespace CamelotEditor
 	class EditorWidgetFactory;
 	class QtEditorWindow;
 	class QtEditorWidget;
+	class QtDynamicTabBar;
 }
 
 // Qt
@@ -22,4 +23,6 @@ class QWidget;
 class QLabel;
 class QPushButton;
 class QSplitter;
-class QStackedWidget;
+class QStackedWidget;
+class QHBoxLayout;
+class QVBoxLayout;

+ 33 - 0
CamelotEditor/Include/CmQtDynamicTabBar.h

@@ -0,0 +1,33 @@
+#pragma once
+
+#include "CmEditorPrerequisites.h"
+#include <QtWidgets/QWidget>
+#include <QtWidgets/QPushButton>
+#include <boost/signal.hpp>
+
+namespace CamelotEditor
+{
+	class QtDynamicTabBar : public QWidget
+	{
+		Q_OBJECT
+
+	public:
+		QtDynamicTabBar(QWidget* parent);
+		virtual ~QtDynamicTabBar() { }
+
+		void addTab(const QString& name);
+		void insertTab(UINT32 idx, const QString& name);
+		void removeTab(UINT32 idx);
+
+		boost::signal<void(UINT32)> onTabSelected;
+
+	private:
+		QHBoxLayout* mHLayout;
+		vector<QPushButton*>::type mTabs;
+
+		void setupUi();
+		void updateTabs();
+
+		void tabSelected(UINT32 idx);
+	};
+}

+ 2 - 1
CamelotEditor/Include/CmQtEditorWindow.h

@@ -44,6 +44,7 @@ namespace CamelotEditor
 		QtEditorWidget* getWidget(UINT32 idx) const;
 
 		void setActiveWidget(UINT32 idx);
+		QWidget* getContentWidget() const;
 
 		boost::signal<void(QtEditorWindow*)> onClosed;
 	protected:
@@ -55,7 +56,7 @@ namespace CamelotEditor
 		bool mMoveMode;
 		QPoint mDragOffset;
 		QWidget* mTitleBar;
-		QLabel* mLblTitle;
+		QtDynamicTabBar* mTabBar;
 		QPushButton* mBtnClose;
 		QWidget* mCentralWidget;
 		QStackedWidget* mStackedWidget;

+ 80 - 0
CamelotEditor/Source/CmQtDynamicTabBar.cpp

@@ -0,0 +1,80 @@
+#include "CmQtDynamicTabBar.h"
+#include "CmException.h"
+#include <QtWidgets/QPushButton>
+#include <QtWidgets/QHBoxLayout>
+
+namespace CamelotEditor
+{
+	QtDynamicTabBar::QtDynamicTabBar(QWidget* parent)
+		:QWidget(parent), mHLayout(nullptr)
+	{
+		setupUi();
+	}
+
+	void QtDynamicTabBar::addTab(const QString& name)
+	{
+		QPushButton* newBtn = new QPushButton(this);
+		newBtn->setMaximumWidth(100);
+		newBtn->setText(name);
+
+		mTabs.push_back(newBtn);
+
+		updateTabs();
+	}
+
+	void QtDynamicTabBar::insertTab(UINT32 idx, const QString& name)
+	{
+		if(idx >= (UINT32)mTabs.size())
+			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) +". Valid range: 0 .. " + toString((UINT32)mTabs.size()));
+
+		QPushButton* newBtn = new QPushButton(this);
+		newBtn->setMaximumWidth(100);
+		newBtn->setText(name);
+
+		mTabs.insert(mTabs.begin() + idx, newBtn);
+
+		updateTabs();
+	}
+
+	void QtDynamicTabBar::removeTab(UINT32 idx)
+	{
+		if(idx >= (UINT32)mTabs.size())
+			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) +". Valid range: 0 .. " + toString((UINT32)mTabs.size()));
+
+		mTabs.erase(mTabs.begin() + idx);
+
+		updateTabs();
+	}
+
+	void QtDynamicTabBar::setupUi()
+	{
+		mHLayout = new QHBoxLayout(this);
+		mHLayout->setMargin(0);
+
+		setLayout(mHLayout);
+	}
+
+	void QtDynamicTabBar::updateTabs()
+	{
+		QLayoutItem* item;
+		while((item = mHLayout->takeAt(0)) != nullptr)
+			mHLayout->removeItem(item);
+
+		UINT32 idx = 0;
+		for(auto iter = mTabs.begin(); iter != mTabs.end(); ++iter)
+		{
+			(*iter)->disconnect();
+			/*connect(*iter, &QPushButton::clicked, std::bind(this, &QtDynamicTabBar::tabSelected, idx));*/
+			mHLayout->addWidget(*iter);
+
+			idx++;
+		}
+
+		mHLayout->addStretch(2);
+	}
+
+	void QtDynamicTabBar::tabSelected(UINT32 idx)
+	{
+		onTabSelected(idx);
+	}
+}

+ 14 - 5
CamelotEditor/Source/CmQtEditorWindow.cpp

@@ -12,6 +12,7 @@
 
 #include "CmDebug.h"
 #include "CmQtEditorWidget.h"
+#include "CmQtDynamicTabBar.h"
 #include "CmWindowDockManager.h"
 #include "CmEditorWindowManager.h"
 
@@ -38,14 +39,13 @@ namespace CamelotEditor
 		mTitleBar = new QWidget(this);
 		mTitleBar->setMouseTracking(true);
 
-		mLblTitle = new QLabel(this);
-		mLblTitle->setAttribute(Qt::WA_TransparentForMouseEvents);
+		mTabBar = new QtDynamicTabBar(this);
 		
 		mBtnClose = new QPushButton(this);
 		
 		QHBoxLayout* titleLayout = new QHBoxLayout(this);
 		titleLayout->setMargin(0);
-		titleLayout->addWidget(mLblTitle, 1);
+		titleLayout->addWidget(mTabBar, 1);
 		titleLayout->addWidget(mBtnClose);
 		mTitleBar->setLayout(titleLayout);
 
@@ -78,18 +78,19 @@ namespace CamelotEditor
 	{
 		connect(mBtnClose, SIGNAL(clicked()), this, SLOT(closeWidget()));
 		connect(mTimer, SIGNAL(timeout()), this, SLOT(timerUpdate()));
+		
+		mTabBar->onTabSelected.connect(boost::bind(&QtEditorWindow::setActiveWidget, this, _1));
 	}
 
 	void QtEditorWindow::retranslateUi()
 	{
-		mLblTitle->setText("No title");
 		mBtnClose->setText(tr("Close"));
 	}
 
 	void QtEditorWindow::setObjectNames()
 	{
 		mTitleBar->setObjectName(QStringLiteral("TitleBar"));
-		mLblTitle->setObjectName(QStringLiteral("LblTitle"));
+		mTabBar->setObjectName(QStringLiteral("TabBar"));
 		mBtnClose->setObjectName(QStringLiteral("BtnClose"));
 
 		mCentralWidget->setObjectName(QStringLiteral("CentralWidget"));
@@ -223,6 +224,7 @@ namespace CamelotEditor
 
 		widget->setParentWindow(this);
 		mEditorWidgets.push_back(widget);
+		mTabBar->addTab(widget->getName());
 	}
 
 	void QtEditorWindow::insertWidget(UINT32 idx, QtEditorWidget* widget)
@@ -238,6 +240,7 @@ namespace CamelotEditor
 
 		widget->setParentWindow(this);
 		mEditorWidgets.insert(mEditorWidgets.begin() + idx, widget);
+		mTabBar->insertTab(idx, widget->getName());
 	}
 
 	void QtEditorWindow::removeWidget(UINT32 idx)
@@ -246,6 +249,7 @@ namespace CamelotEditor
 			CM_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) +". Valid range: 0 .. " + toString((UINT32)mEditorWidgets.size()));
 
 		mEditorWidgets.erase(mEditorWidgets.begin() + idx);
+		mTabBar->removeTab(idx);
 	}
 
 	QtEditorWidget* QtEditorWindow::getWidget(UINT32 idx) const
@@ -263,6 +267,11 @@ namespace CamelotEditor
 		// TODO
 	}
 
+	QWidget* QtEditorWindow::getContentWidget() const
+	{ 
+		return mStackedWidget; 
+	}
+
 	void QtEditorWindow::enterEvent(QEvent *e)
 	{
 		mTimer->start(100);

+ 6 - 2
CamelotEditor/Source/CmWindowDockManager.cpp

@@ -33,7 +33,11 @@ namespace CamelotEditor
 
 		if(!window->isDocked())
 		{
-			QWidget* dragOverWidget = getDockedWindowAtPosition(mousePos);
+			QtEditorWindow* windowUnderMouse = getDockedWindowAtPosition(mousePos);
+			QWidget* dragOverWidget = nullptr;
+			if(windowUnderMouse != nullptr)
+				dragOverWidget = windowUnderMouse->getContentWidget();
+
 			if(dragOverWidget == nullptr && isPositionInDockArea(mousePos))
 				dragOverWidget = mCentralWidget;
 
@@ -87,7 +91,7 @@ namespace CamelotEditor
 			QtEditorWindow* windowUnderCursor = getDockedWindowAtPosition(mousePos);
 			if(windowUnderCursor != nullptr)
 			{
-				WindowDragDropLocation dropLocation = getDropLocationAtPosition(windowUnderCursor, mousePos);
+				WindowDragDropLocation dropLocation = getDropLocationAtPosition(windowUnderCursor->getContentWidget(), mousePos);
 				dockWindow(window, windowUnderCursor, dropLocation);
 			}
 			else

+ 4 - 2
TODOEditor.txt

@@ -30,8 +30,10 @@ TODO for next few days:
 
 Dock overlay widget colors need to be customizable
 
-Test if new docked widgets work
 Unique IDs for windows. Currently I don't guarantee IDs will be the same if user adds a window before I restore them from file.
 
 When restoring windows what happens why I try to restore an unloaded plugin?
- - A NullWindow?
+ - A NullWindow?
+
+ After I undock a window it needs to return itself to the default size
+  - Allow widgets to specify default size