Browse Source

Updated tree view auto expand functionality

Marko Pintera 12 years ago
parent
commit
15ad1a70cf

+ 5 - 0
CamelotClient/Include/BsGUISceneTreeView.h

@@ -28,6 +28,8 @@ namespace BansheeEditor
 			bool mIsSelected;
 			bool mIsDirty;
 			bool mIsVisible;
+
+			bool isParentRec(TreeElement* element) const;
 		};
 
 		struct InteractableElement
@@ -121,6 +123,7 @@ namespace BansheeEditor
 		BS::GUITexture* mDragHighlight;
 		BS::GUITexture* mDragSepHighlight;
 
+		CM::Stack<TreeElement*>::type mAutoExpandedElements;
 		TreeElement* mMouseOverDragElement;
 		float mMouseOverDragElementTime;
 
@@ -144,6 +147,8 @@ namespace BansheeEditor
 		void unselectElement(TreeElement* element);
 		void unselectAll();
 
+		void temporarilyExpandElement(const GUISceneTreeView::InteractableElement* mouseOverElement);
+
 		void onEditAccepted();
 		void onEditCanceled();
 

+ 85 - 38
CamelotClient/Source/BsGUISceneTreeView.cpp

@@ -60,6 +60,36 @@ namespace BansheeEditor
 		mChildren.clear();
 	}
 
+	bool GUISceneTreeView::TreeElement::isParentRec(TreeElement* element) const
+	{
+		TreeElement* curParent = mParent;
+		while(curParent != nullptr)
+		{
+			if(curParent == element)
+				return true;
+
+			curParent = curParent->mParent;
+		}
+
+		return false;
+	}
+
+	GUISceneTreeView::TreeElement* GUISceneTreeView::InteractableElement::getTreeElement() const
+	{
+		if(!isTreeElement())
+			return nullptr;
+
+		UINT32 sortedIdx = (index - 1) / 2;
+
+		auto findIter = std::find_if(parent->mChildren.begin(), parent->mChildren.end(),
+			[&](const TreeElement* x) { return x->mSortedIdx == sortedIdx; });
+
+		if(findIter != parent->mChildren.end())
+			return *findIter;
+
+		return nullptr;
+	}
+
 	GUISceneTreeView::GUISceneTreeView(GUIWidget& parent, GUIElementStyle* backgroundStyle, GUIElementStyle* elementBtnStyle, 
 		GUIElementStyle* foldoutBtnStyle, GUIElementStyle* selectionBackgroundStyle, GUIElementStyle* editBoxStyle, 
 		BS::GUIElementStyle* dragHighlightStyle, BS::GUIElementStyle* dragSepHighlightStyle, const GUILayoutOptions& layoutOptions)
@@ -135,30 +165,7 @@ namespace BansheeEditor
 		if(DragAndDropManager::instance().isDragInProgress() && DragAndDropManager::instance().getDragTypeId() == (UINT32)DragAndDropType::SceneObject)
 		{
 			const GUISceneTreeView::InteractableElement* element = findElementUnderCoord(mDragPosition);
-			if(element == nullptr || !element->isTreeElement())
-			{
-				mMouseOverDragElementTime = gTime().getTime();
-				mMouseOverDragElement = nullptr;
-			}
-			else
-			{
-				TreeElement* treeElement = element->getTreeElement();
-
-				if(mMouseOverDragElement == treeElement)
-				{
-					float timeDiff = gTime().getTime() - mMouseOverDragElementTime;
-					if(timeDiff >= AUTO_EXPAND_DELAY_SEC)
-					{
-						if(mMouseOverDragElement != nullptr)
-							mMouseOverDragElement->mIsExpanded = true;
-					}
-				}
-				else
-				{
-					mMouseOverDragElementTime = gTime().getTime();
-					mMouseOverDragElement = treeElement;
-				}
-			}
+			temporarilyExpandElement(element);
 		}
 
 		// NOTE - Instead of iterating through every visible element and comparing it with internal values,
@@ -327,6 +334,9 @@ namespace BansheeEditor
 							_registerChildElement(current->mFoldoutBtn);
 
 							current->mFoldoutBtn->onToggled.connect(boost::bind(&GUISceneTreeView::elementToggled, this, current, _1));
+
+							if(current->mIsExpanded)
+								current->mFoldoutBtn->toggleOn();
 						}
 					}
 					else
@@ -1092,25 +1102,62 @@ namespace BansheeEditor
 			return nullptr;
 	}
 
-	const String& GUISceneTreeView::getGUITypeName()
+	void GUISceneTreeView::temporarilyExpandElement(const GUISceneTreeView::InteractableElement* mouseOverElement)
 	{
-		static String typeName = "SceneTreeView";
-		return typeName;
-	}
+		TreeElement* treeElement = nullptr;
+		if(mouseOverElement != nullptr && mouseOverElement->isTreeElement())
+			treeElement = mouseOverElement->getTreeElement();
 
-	GUISceneTreeView::TreeElement* GUISceneTreeView::InteractableElement::getTreeElement() const
-	{
-		if(!isTreeElement())
-			return nullptr;
+		if(treeElement == nullptr || treeElement != mMouseOverDragElement)
+		{
+			while(!mAutoExpandedElements.empty())
+			{
+				TreeElement* autoExpandedElement = mAutoExpandedElements.top();
 
-		UINT32 sortedIdx = (index - 1) / 2;
+				bool unexpandElement = false;
+				if(mouseOverElement != nullptr && mouseOverElement->parent != nullptr)
+				{
+					if(mouseOverElement->parent != autoExpandedElement && !mouseOverElement->parent->isParentRec(autoExpandedElement))
+						unexpandElement = true;
+					else
+						break;
+				}
+				else
+					unexpandElement = true;
 
-		auto findIter = std::find_if(parent->mChildren.begin(), parent->mChildren.end(),
-			[&](const TreeElement* x) { return x->mSortedIdx == sortedIdx; });
+				if(unexpandElement)
+				{
+					autoExpandedElement->mIsExpanded = false;
+					if(autoExpandedElement->mFoldoutBtn != nullptr)
+						autoExpandedElement->mFoldoutBtn->toggleOff();
 
-		if(findIter != parent->mChildren.end())
-			return *findIter;
+					mAutoExpandedElements.pop();
+				}
+			}
 
-		return nullptr;
+			mMouseOverDragElement = treeElement;
+			mMouseOverDragElementTime = gTime().getTime();
+		}
+		else
+		{
+			if(mMouseOverDragElement != nullptr && !mMouseOverDragElement->mIsExpanded)
+			{
+				float timeDiff = gTime().getTime() - mMouseOverDragElementTime;
+				if(timeDiff >= AUTO_EXPAND_DELAY_SEC)
+				{
+					mAutoExpandedElements.push(mMouseOverDragElement);
+					mMouseOverDragElement->mIsExpanded = true;
+
+					if(mMouseOverDragElement->mFoldoutBtn != nullptr)
+						mMouseOverDragElement->mFoldoutBtn->toggleOn();
+				}
+			}
+		}
+	}
+
+	const String& GUISceneTreeView::getGUITypeName()
+	{
+		static String typeName = "SceneTreeView";
+		return typeName;
 	}
 }

+ 1 - 1
TreeView.txt

@@ -1,6 +1,6 @@
 TODO:
  - Callback on tree item select
- - When dragging in tree view automatically expand mouse over elements
+ - when update() deletes elements it won't remove them from mAutoExpandedElements or mMouseOverDragElement.
  - When I select elements in tree view via arrow keys, make sure to automatically scroll the scroll-area so that element becomes visible
  - Context menu with rename/copy/paste/duplicate
  - Delete with Undo/Redo support