Browse Source

Many different fixes relating to GUItabbedTileBar drag and drop

Marko Pintera 12 years ago
parent
commit
92977fce75

+ 1 - 0
BansheeEngine/Include/BsGUIButtonBase.h

@@ -76,6 +76,7 @@ namespace BansheeEngine
 		TEXT_SPRITE_DESC getTextDesc() const;
 		TEXT_SPRITE_DESC getTextDesc() const;
 
 
 		void setState(GUIButtonState state);
 		void setState(GUIButtonState state);
+		GUIButtonState getState() const { return mActiveState; }
 	private:
 	private:
 		ImageSprite* mImageSprite;
 		ImageSprite* mImageSprite;
 		ImageSprite* mContentImageSprite;
 		ImageSprite* mContentImageSprite;

+ 3 - 0
CamelotClient/Include/BsGUITabButton.h

@@ -20,6 +20,7 @@ namespace BansheeEditor
 		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUIToggleGroupPtr& toggleGroup, CM::UINT32 index, const BS::GUIContent& content, const BS::GUIOptions& layoutOptions, const BS::GUIElementStyle* style = nullptr);
 		static GUITabButton* create(BS::GUIWidget& parent, const BS::GUIToggleGroupPtr& toggleGroup, CM::UINT32 index, const BS::GUIContent& content, const BS::GUIOptions& layoutOptions, const BS::GUIElementStyle* style = nullptr);
 
 
 		CM::UINT32 getIndex() const { return mIndex; }
 		CM::UINT32 getIndex() const { return mIndex; }
+		void _setDraggedState(bool active);
 
 
 		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragged;
 		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragged;
 		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragEnd;
 		boost::signal<void(CM::UINT32, const CM::Vector2I&)> onDragEnd;
@@ -29,6 +30,8 @@ namespace BansheeEditor
 	private:
 	private:
 		CM::UINT32 mIndex;
 		CM::UINT32 mIndex;
 		CM::Vector2I mDragStartPosition;
 		CM::Vector2I mDragStartPosition;
+		bool mDraggedState;
+		BS::GUIButtonState mInactiveState;
 
 
 		static const CM::UINT32 DRAG_MIN_DISTANCE;
 		static const CM::UINT32 DRAG_MIN_DISTANCE;
 
 

+ 2 - 1
CamelotClient/Include/BsGUITabbedTitleBar.h

@@ -24,6 +24,7 @@ namespace BansheeEditor
 		void addTab(const CM::HString& name);
 		void addTab(const CM::HString& name);
 		void insertTab(CM::UINT32 idx, const CM::HString& name);
 		void insertTab(CM::UINT32 idx, const CM::HString& name);
 		void removeTab(CM::UINT32 idx);
 		void removeTab(CM::UINT32 idx);
+		void setActive(CM::UINT32 idx);
 
 
 		boost::signal<void(CM::UINT32)> onTabActivated;
 		boost::signal<void(CM::UINT32)> onTabActivated;
 		boost::signal<void(CM::UINT32)> onTabClosed;
 		boost::signal<void(CM::UINT32)> onTabClosed;
@@ -69,7 +70,7 @@ namespace BansheeEditor
 
 
 		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
 		virtual bool mouseEvent(const BS::GUIMouseEvent& ev);
 
 
-		void tabToggled(CM::UINT32 tabIdx);
+		void tabToggled(CM::UINT32 tabIdx, bool toggledOn);
 		void tabClosed();
 		void tabClosed();
 		void tabDragged(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);
 		void tabDragged(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);
 		void tabDragEnd(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);
 		void tabDragEnd(CM::UINT32 tabIdx, const CM::Vector2I& dragPos);

+ 4 - 0
CamelotClient/Source/BsEditorWidgetContainer.cpp

@@ -73,7 +73,9 @@ namespace BansheeEditor
 		{
 		{
 			if(mWidgets.size() > 0)
 			if(mWidgets.size() > 0)
 			{
 			{
+				mActiveWidget = -1;
 				setActiveWidget(0);
 				setActiveWidget(0);
+				mTitleBar->setActive(0);
 			}
 			}
 		}
 		}
 	}
 	}
@@ -193,6 +195,8 @@ namespace BansheeEditor
 		EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
 		EditorWidget* draggedWidget = static_cast<EditorWidget*>(DragAndDropManager::instance().getDragData());
 
 
 		insert(idx, *draggedWidget);
 		insert(idx, *draggedWidget);
+		setActiveWidget(idx);
+		mTitleBar->setActive(idx);
 	}
 	}
 
 
 	void EditorWidgetContainer::tabDroppedCallback(bool wasDragProcessed)
 	void EditorWidgetContainer::tabDroppedCallback(bool wasDragProcessed)

+ 73 - 7
CamelotClient/Source/BsGUITabButton.cpp

@@ -19,7 +19,7 @@ namespace BansheeEditor
 	}
 	}
 
 
 	GUITabButton::GUITabButton(GUIWidget& parent, const GUIElementStyle* style, const GUIToggleGroupPtr& toggleGroup, CM::UINT32 index, const GUIContent& content, const GUILayoutOptions& layoutOptions)
 	GUITabButton::GUITabButton(GUIWidget& parent, const GUIElementStyle* style, const GUIToggleGroupPtr& toggleGroup, CM::UINT32 index, const GUIContent& content, const GUILayoutOptions& layoutOptions)
-		:GUIToggle(parent, style, content, toggleGroup, layoutOptions), mIndex(index)
+		:GUIToggle(parent, style, content, toggleGroup, layoutOptions), mIndex(index), mDraggedState(false)
 	{
 	{
 
 
 	}
 	}
@@ -68,14 +68,80 @@ namespace BansheeEditor
 		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, toggleGroup, index, content, GUILayoutOptions::create(layoutOptions, style));
 		return new (cm_alloc<GUITabButton, PoolAlloc>()) GUITabButton(parent, style, toggleGroup, index, content, GUILayoutOptions::create(layoutOptions, style));
 	}
 	}
 
 
-	bool GUITabButton::mouseEvent(const GUIMouseEvent& ev)
+	void GUITabButton::_setDraggedState(bool active) 
 	{
 	{
-		bool eventProcessed = GUIButtonBase::mouseEvent(ev);
+		if(mDraggedState == active)
+			return;
+
+		mDraggedState = active; 
+
+		if(mDraggedState)
+		{
+			mInactiveState = getState();
+
+			if(mInactiveState != GUIButtonState::Normal)
+				setState(GUIButtonState::Normal);
+		}
+		else
+		{
+			if(getState() != mInactiveState)
+				setState(mInactiveState);
+		}
+	}
+
+	bool GUITabButton::mouseEvent(const GUIMouseEvent& ev)
+	{	
+		if(ev.getType() == GUIMouseEventType::MouseOver)
+		{
+			GUIButtonState state = _isOn() ? GUIButtonState::HoverOn : GUIButtonState::Hover;
+
+			if(!mDraggedState)
+			{
+				setState(state);
+
+				if(!onHover.empty())
+					onHover();
+			}
+			else
+				mInactiveState = state;
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			GUIButtonState state = _isOn() ? GUIButtonState::NormalOn : GUIButtonState::Normal;
+
+			if(!mDraggedState)
+			{
+				setState(state);
 
 
-		if(ev.getType() == GUIMouseEventType::MouseUp)
+				if(!onOut.empty())
+					onOut();
+			}
+			else
+				mInactiveState = state;
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDown)
 		{
 		{
-			if(!mIsToggled)
-				toggleOn();
+			if(!mDraggedState)
+				setState(_isOn() ? GUIButtonState::ActiveOn : GUIButtonState::Active);
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseUp)
+		{
+			if(!mDraggedState)
+			{
+				setState(_isOn() ? GUIButtonState::HoverOn : GUIButtonState::Hover);
+
+				if(!onClick.empty())
+					onClick();
+
+				if(!mIsToggled)
+					toggleOn();
+			}
 
 
 			return true;
 			return true;
 		}
 		}
@@ -110,6 +176,6 @@ namespace BansheeEditor
 			return true;
 			return true;
 		}
 		}
 
 
-		return eventProcessed;
+		return false;
 	}
 	}
 }
 }

+ 49 - 23
CamelotClient/Source/BsGUITabbedTitleBar.cpp

@@ -93,7 +93,7 @@ namespace BansheeEditor
 
 
 		idx = Math::clamp(idx, 0U, (UINT32)mTabButtons.size());
 		idx = Math::clamp(idx, 0U, (UINT32)mTabButtons.size());
 
 
-		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx));
+		newTabToggle->onToggled.connect(boost::bind(&GUITabbedTitleBar::tabToggled, this, mUniqueTabIdx, _1));
 		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDragged, this, _1, _2));
 		newTabToggle->onDragged.connect(boost::bind(&GUITabbedTitleBar::tabDragged, this, _1, _2));
 		newTabToggle->onDragEnd.connect(boost::bind(&GUITabbedTitleBar::tabDragEnd, this, _1, _2));
 		newTabToggle->onDragEnd.connect(boost::bind(&GUITabbedTitleBar::tabDragEnd, this, _1, _2));
 
 
@@ -114,6 +114,11 @@ namespace BansheeEditor
 		mTabButtons.erase(mTabButtons.begin() + idx);
 		mTabButtons.erase(mTabButtons.begin() + idx);
 	}
 	}
 
 
+	void GUITabbedTitleBar::setActive(UINT32 idx)
+	{
+		mTabButtons[idx]->toggleOn();
+	}
+
 	bool GUITabbedTitleBar::mouseEvent(const GUIMouseEvent& event)
 	bool GUITabbedTitleBar::mouseEvent(const GUIMouseEvent& event)
 	{
 	{
 		if(event.getType() == GUIMouseEventType::MouseDragAndDropDragged)
 		if(event.getType() == GUIMouseEventType::MouseDragAndDropDragged)
@@ -169,7 +174,10 @@ namespace BansheeEditor
 
 
 				mTempDraggedWidget = draggedWidget;
 				mTempDraggedWidget = draggedWidget;
 
 
-				mInitialDragOffset = Math::roundToInt(mTabButtons[uniqueIdxToSeqIdx(mTempDraggedTabIdx)]->_getWidth() * 0.5f);
+				mDraggedBtn = mTabButtons[uniqueIdxToSeqIdx(mTempDraggedTabIdx)];
+				mDraggedBtn->_setDraggedState(true);
+
+				mInitialDragOffset = Math::roundToInt(mDraggedBtn->_getWidth() * 0.5f);
 				mDragInProgress = true;
 				mDragInProgress = true;
 			}
 			}
 
 
@@ -192,6 +200,8 @@ namespace BansheeEditor
 				removeTab(tabSeqIdx);
 				removeTab(tabSeqIdx);
 
 
 				mTempDraggedWidget = nullptr;
 				mTempDraggedWidget = nullptr;
+				mDragInProgress = false;
+				mDraggedBtn = nullptr;
 
 
 				if(!onTabDraggedOn.empty())
 				if(!onTabDraggedOn.empty())
 					onTabDraggedOn(tabSeqIdx);
 					onTabDraggedOn(tabSeqIdx);
@@ -206,6 +216,8 @@ namespace BansheeEditor
 				removeTab(uniqueIdxToSeqIdx(mTempDraggedTabIdx));
 				removeTab(uniqueIdxToSeqIdx(mTempDraggedTabIdx));
 
 
 				mTempDraggedWidget = nullptr;
 				mTempDraggedWidget = nullptr;
+				mDragInProgress = false;
+				mDraggedBtn = nullptr;
 			}
 			}
 		}
 		}
 
 
@@ -229,7 +241,7 @@ namespace BansheeEditor
 			mBackgroundImage->_setOffset(offset);
 			mBackgroundImage->_setOffset(offset);
 			mBackgroundImage->_setWidth(width - 2);
 			mBackgroundImage->_setWidth(width - 2);
 			mBackgroundImage->_setHeight(optimalSize.y);
 			mBackgroundImage->_setHeight(optimalSize.y);
-			mBackgroundImage->_setAreaDepth(areaDepth + 1);
+			mBackgroundImage->_setAreaDepth(areaDepth + 2);
 			mBackgroundImage->_setWidgetDepth(widgetDepth);
 			mBackgroundImage->_setWidgetDepth(widgetDepth);
 
 
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
@@ -248,11 +260,21 @@ namespace BansheeEditor
 			nonClientAreas.push_back(RectI(curX, curY, TAB_SPACING, tabBtnHeight));
 			nonClientAreas.push_back(RectI(curX, curY, TAB_SPACING, tabBtnHeight));
 			curX += TAB_SPACING;
 			curX += TAB_SPACING;
 
 
-			Vector2I offset(curX, curY);
+			Vector2I offset;
+			if(!mDragInProgress || mDraggedBtn != btn)
+			{
+				offset = Vector2I(curX, curY);
+			}
+			else if(mDragInProgress && mDraggedBtn == btn)
+			{
+				offset = btn->_getOffset();
+				offset.x = mDragBtnOffset;
+			}
+
 			btn->_setOffset(offset);
 			btn->_setOffset(offset);
 			btn->_setWidth(optimalSize.x);
 			btn->_setWidth(optimalSize.x);
 			btn->_setHeight(optimalSize.y);
 			btn->_setHeight(optimalSize.y);
-			btn->_setAreaDepth(areaDepth);
+			btn->_setAreaDepth(areaDepth + 1);
 			btn->_setWidgetDepth(widgetDepth);
 			btn->_setWidgetDepth(widgetDepth);
 
 
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
@@ -276,7 +298,7 @@ namespace BansheeEditor
 			mMinBtn->_setOffset(offset);
 			mMinBtn->_setOffset(offset);
 			mMinBtn->_setWidth(minBtnOptimalSize.x);
 			mMinBtn->_setWidth(minBtnOptimalSize.x);
 			mMinBtn->_setHeight(minBtnOptimalSize.y);
 			mMinBtn->_setHeight(minBtnOptimalSize.y);
-			mMinBtn->_setAreaDepth(areaDepth);
+			mMinBtn->_setAreaDepth(areaDepth + 1);
 			mMinBtn->_setWidgetDepth(widgetDepth);
 			mMinBtn->_setWidgetDepth(widgetDepth);
 
 
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
@@ -291,7 +313,7 @@ namespace BansheeEditor
 			mCloseBtn->_setOffset(offset);
 			mCloseBtn->_setOffset(offset);
 			mCloseBtn->_setWidth(closeBtnOptimalSize.x);
 			mCloseBtn->_setWidth(closeBtnOptimalSize.x);
 			mCloseBtn->_setHeight(closeBtnOptimalSize.y);
 			mCloseBtn->_setHeight(closeBtnOptimalSize.y);
-			mCloseBtn->_setAreaDepth(areaDepth);
+			mCloseBtn->_setAreaDepth(areaDepth + 1);
 			mCloseBtn->_setWidgetDepth(widgetDepth);
 			mCloseBtn->_setWidgetDepth(widgetDepth);
 
 
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
 			RectI elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
@@ -301,8 +323,11 @@ namespace BansheeEditor
 		Platform::setCaptionNonClientAreas(*mParentWindow, nonClientAreas);
 		Platform::setCaptionNonClientAreas(*mParentWindow, nonClientAreas);
 	}
 	}
 
 
-	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx)
+	void GUITabbedTitleBar::tabToggled(CM::UINT32 tabIdx, bool toggledOn)
 	{
 	{
+		if(!toggledOn)
+			return;
+
 		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
 		INT32 idx = uniqueIdxToSeqIdx(tabIdx);
 		if(idx != -1)
 		if(idx != -1)
 		{
 		{
@@ -336,10 +361,11 @@ namespace BansheeEditor
 			RectI bounds = getBounds();
 			RectI bounds = getBounds();
 			if(bounds.contains(dragPos))
 			if(bounds.contains(dragPos))
 			{
 			{
-				mDraggedBtn = mTabButtons[idx];
-
 				if(!mDragInProgress)
 				if(!mDragInProgress)
 				{
 				{
+					mDraggedBtn = mTabButtons[idx];
+					mDraggedBtn->_setDraggedState(false);
+
 					Vector2I offset = mDraggedBtn->_getOffset();
 					Vector2I offset = mDraggedBtn->_getOffset();
 					mInitialDragOffset = (dragPos.x - offset.x);
 					mInitialDragOffset = (dragPos.x - offset.x);
 
 
@@ -347,15 +373,6 @@ namespace BansheeEditor
 				}
 				}
 
 
 				mDragBtnOffset = dragPos.x - mInitialDragOffset;
 				mDragBtnOffset = dragPos.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);
 
 
 				for(INT32 i = 0; i < idx; i++)
 				for(INT32 i = 0; i < idx; i++)
 				{
 				{
@@ -368,8 +385,6 @@ namespace BansheeEditor
 						mTabButtons[i] = mTabButtons[idx];
 						mTabButtons[i] = mTabButtons[idx];
 						mTabButtons[idx] = temp;
 						mTabButtons[idx] = temp;
 
 
-						markContentAsDirty();
-
 						break;
 						break;
 					}
 					}
 				}
 				}
@@ -385,17 +400,22 @@ namespace BansheeEditor
 						mTabButtons[i] = mTabButtons[idx];
 						mTabButtons[i] = mTabButtons[idx];
 						mTabButtons[idx] = temp;
 						mTabButtons[idx] = temp;
 
 
-						markContentAsDirty();
-
 						break;
 						break;
 					}
 					}
 				}
 				}
+
+				markContentAsDirty();
 			}
 			}
 			else
 			else
 			{
 			{
 				mDragInProgress = false;
 				mDragInProgress = false;
+
+				if(mDraggedBtn != nullptr)
+					mDraggedBtn->_setDraggedState(false);
 				mDraggedBtn = nullptr;
 				mDraggedBtn = nullptr;
 
 
+				markContentAsDirty();
+
 				if(!onTabDraggedOff.empty())
 				if(!onTabDraggedOff.empty())
 					onTabDraggedOff(idx);
 					onTabDraggedOff(idx);
 			}
 			}
@@ -405,8 +425,14 @@ namespace BansheeEditor
 	void GUITabbedTitleBar::tabDragEnd(CM::UINT32 tabIdx, const Vector2I& dragPos)
 	void GUITabbedTitleBar::tabDragEnd(CM::UINT32 tabIdx, const Vector2I& dragPos)
 	{
 	{
 		mDragInProgress = false;
 		mDragInProgress = false;
+
+		if(mDraggedBtn != nullptr)
+			mDraggedBtn->_setDraggedState(false);
 		mDraggedBtn = nullptr;
 		mDraggedBtn = nullptr;
 
 
+		if(mActiveTabIdx != tabIdx)
+			tabToggled(tabIdx, true);
+
 		markContentAsDirty();
 		markContentAsDirty();
 	}
 	}
 
 

+ 5 - 2
EditorWindowDock.txt

@@ -1,6 +1,9 @@
 TODO:
 TODO:
- - Fix various issues with dragging windows onto tabbed title bar and test it properly
- - Also test for any new issues with the element container parenting system
+ - When dragging a tab and then releasing the drag over another tab, that tab becomes active
+ - When dragging a temp tab I drag it from its left side while it would be better to drag it from center
+ - Vector subscript out of range issue I'm not sure how to reproduce
+ - Clip tabs so that they don't overlap min/close buttons
+ - (Unrelated) Can't click and drag a scroll handle
 
 
 Resize sliders
 Resize sliders
  - Add a button between docked windows
  - Add a button between docked windows