Răsfoiți Sursa

Title bar tab button is now movable

Marko Pintera 12 ani în urmă
părinte
comite
dd41ba65df

+ 1 - 0
BansheeEngine/Include/BsGUIElement.h

@@ -107,6 +107,7 @@ namespace BansheeEngine
 		bool _isDestroyed() const { return mIsDestroyed; }
 
 		const CM::RectI& _getClippedBounds() const { return mClippedBounds; }
+		const CM::RectI& _getClipRect() const { return mClipRect; }
 		CM::UINT32 _getDepth() const { return mDepth; }
 		GUIWidget& _getParentWidget() const { return *mParent; }
 		virtual bool _isInBounds(const CM::Vector2I position) const;

+ 2 - 1
CamelotClient/Include/BsGUITabButton.h

@@ -21,7 +21,8 @@ namespace BansheeEditor
 
 		CM::UINT32 getIndex() const { return mIndex; }
 
-		boost::signal<void(CM::UINT32)> onDragged;
+		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragged;
+		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragEnd;
 	protected:
 		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
 

+ 9 - 3
CamelotClient/Include/BsGUITabbedTitleBar.h

@@ -1,6 +1,7 @@
 #pragma once
 
 #include "BsEditorPrerequisites.h"
+#include "CmRectI.h"
 #include <boost/signal.hpp>
 
 namespace BansheeEditor
@@ -35,8 +36,12 @@ namespace BansheeEditor
 		BS::GUIButton* mMinBtn;
 		BS::GUIButton* mCloseBtn;
 		CM::RenderWindow* mParentWindow;
-		CM::INT32 mX, mY;
-		CM::UINT32 mWidth, mHeight;
+		CM::RectI mArea;
+
+		bool mDragInProgress;
+		GUITabButton* mDraggedBtn;
+		CM::INT32 mDragBtnOffset;
+		CM::INT32 mInitialDragOffset;
 
 		const BS::GUIElementStyle* mCloseBtnStyle;
 		const BS::GUIElementStyle* mMinimizeBtnStyle;
@@ -46,7 +51,8 @@ namespace BansheeEditor
 
 		void tabToggled(CM::UINT32 tabIdx);
 		void tabClosed();
-		void tabDraggedOff(CM::UINT32 tabIdx);
+		void tabDragged(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);
+		void tabDragEnd(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);
 		void tabDraggedOn(CM::UINT32 tabIdx);
 
 		CM::INT32 uniqueIdxToSeqIdx(CM::UINT32 uniqueIdx) const;

+ 11 - 1
CamelotClient/Source/BsGUITabButton.cpp

@@ -85,7 +85,17 @@ namespace BansheeEditor
 			if(dist > DRAG_MIN_DISTANCE)
 			{
 				if(!onDragged.empty())
-					onDragged(mIndex);
+					onDragged(mIndex, ev.getPosition());
+			}
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDragEnd)
+		{
+			UINT32 dist = mDragStartPosition.manhattanDist(ev.getPosition());
+
+			if(dist > DRAG_MIN_DISTANCE)
+			{
+				if(!onDragEnd.empty())
+					onDragEnd(mIndex, ev.getPosition());
 			}
 		}
 

+ 56 - 11
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -22,7 +22,7 @@ namespace BansheeEditor
 	GUITabbedTitleBar::GUITabbedTitleBar(BS::GUIWidget* parent, CM::RenderWindow* parentWindow)
 		:mParentWindow(parentWindow), mMinBtn(nullptr), mCloseBtn(nullptr), mCloseBtnStyle(nullptr),
 		mMinimizeBtnStyle(nullptr), mParentWidget(parent), mBackgroundArea(nullptr), mUniqueTabIdx(0), mActiveTabIdx(0),
-		mX(0), mY(0), mWidth(0), mHeight(0)
+		mDragInProgress(false), mDraggedBtn(nullptr), mDragBtnOffset(0), mInitialDragOffset(0)
 	{
 		mBackgroundArea = GUIArea::create(*parent, 0, 0, 1, 13, 9900);
 		GUITexture* titleBarBg = GUITexture::create(*parent, parent->getSkin().getStyle("TitleBarBackground"));
@@ -64,7 +64,8 @@ namespace BansheeEditor
 		idx = Math::clamp(idx, 0U, (UINT32)mTabButtons.size());
 
 		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
-		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDraggedOff, this, _1));
+		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDragged, this, _1, _2));
+		newTabToggle->onDragEnd.connect(boost::bind(&GUITabbedTitleBar::tabDragEnd, this, _1, _2));
 
 		mTabButtons.insert(mTabButtons.begin() + idx, newTabToggle);
 
@@ -101,6 +102,9 @@ namespace BansheeEditor
 			curX += TAB_SPACING;
 
 			Vector2I offset(curX, curY);
+			if(mDragInProgress && btn == mDraggedBtn)
+				offset.x = mDragBtnOffset;
+			
 			btn->_setOffset(offset);
 			btn->_setWidth(optimalSize.x);
 			btn->_setHeight(optimalSize.y);
@@ -155,22 +159,22 @@ namespace BansheeEditor
 
 	void GUITabbedTitleBar::setPosition(INT32 x, INT32 y)
 	{
-		mX = x;
-		mY = y;
+		mArea.x = x;
+		mArea.y = y;
 
 		mBackgroundArea->setPosition(x, y);
 
-		updateLayout(mX, mY, mWidth, mHeight, RectI(mX, mY, mWidth, mHeight), mParentWidget->getDepth());
+		updateLayout(mArea.x, mArea.y, mArea.width, mArea.height, RectI(mArea.x, mArea.y, mArea.width, mArea.height), mParentWidget->getDepth());
 	}
 
 	void GUITabbedTitleBar::setSize(UINT32 width, UINT32 height)
 	{
-		mWidth = width;
-		mHeight = height;
+		mArea.width = width;
+		mArea.height = height;
 
 		mBackgroundArea->setSize(width, height);
 
-		updateLayout(mX, mY, mWidth, mHeight, RectI(mX, mY, mWidth, mHeight), mParentWidget->getDepth());
+		updateLayout(mArea.x, mArea.y, mArea.width, mArea.height, RectI(mArea.x, mArea.y, mArea.width, mArea.height), mParentWidget->getDepth());
 	}
 
 	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
@@ -200,16 +204,57 @@ namespace BansheeEditor
 		}
 	}
 
-	void GUITabbedTitleBar::tabDraggedOff(CM::UINT32 tabIdx)
+	void GUITabbedTitleBar::tabDragged(CM::UINT32 tabIdx, const Vector2I& dragPos)
 	{
 		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
 		if(idx != -1)
 		{
-			if(!onTabDraggedOff.empty())
-				onTabDraggedOff(idx);
+			if(mArea.contains(dragPos))
+			{
+				mDraggedBtn = mTabButtons[idx];
+
+				if(!mDragInProgress)
+				{
+					Vector2I offset = mDraggedBtn->_getOffset();
+					mInitialDragOffset = (dragPos.x - offset.x);
+
+					mDragInProgress = true;
+				}
+
+				mDragBtnOffset = dragPos.x - mArea.x - mInitialDragOffset;
+				
+				Vector2I offset = mDraggedBtn->_getOffset();
+				INT32 diff = mDragBtnOffset - offset.x;
+				offset.x += diff;
+				mDraggedBtn->_setOffset(offset);
+
+				RectI clipRect = mDraggedBtn->_getClipRect();
+				clipRect.x -= diff;
+				mDraggedBtn->_setClipRect(clipRect);
+
+				mDragInProgress = true;
+
+				// TODO - If position overlaps another button permanently move the tab
+			}
+			else
+			{
+				mDragInProgress = false;
+				mDraggedBtn = nullptr;
+
+				if(!onTabDraggedOff.empty())
+					onTabDraggedOff(idx);
+			}
 		}
 	}
 
+	void GUITabbedTitleBar::tabDragEnd(CM::UINT32 tabIdx, const Vector2I& dragPos)
+	{
+		mDragInProgress = false;
+		mDraggedBtn = nullptr;
+
+		updateLayout(mArea.x, mArea.y, mArea.width, mArea.height, RectI(mArea.x, mArea.y, mArea.width, mArea.height), mParentWidget->getDepth());
+	}
+
 	void GUITabbedTitleBar::tabDraggedOn(CM::UINT32 tabIdx)
 	{
 		INT32 idx = uniqueIdxToSeqIdx(tabIdx);