Browse Source

Draggable selection works

Marko Pintera 12 years ago
parent
commit
573a51bee5

+ 1 - 0
BansheeEngine/Include/BsGUIInputBox.h

@@ -73,6 +73,7 @@ namespace BansheeEngine
 		CM::UINT32 mSelectionStart;
 		CM::UINT32 mSelectionStart;
 		CM::UINT32 mSelectionEnd;
 		CM::UINT32 mSelectionEnd;
 		CM::UINT32 mSelectionAnchor;
 		CM::UINT32 mSelectionAnchor;
+		CM::UINT32 mSelectionDragAnchor;
 		bool mCaretShown;
 		bool mCaretShown;
 		bool mSelectionShown;
 		bool mSelectionShown;
 
 

+ 1 - 0
BansheeEngine/Include/BsGUIInputCaret.h

@@ -31,6 +31,7 @@ namespace BansheeEngine
 		void moveCaretToChar(CM::UINT32 charIdx, CaretPos caretPos);
 		void moveCaretToChar(CM::UINT32 charIdx, CaretPos caretPos);
 
 
 		CM::UINT32 getCharIdxAtCaretPos() const;
 		CM::UINT32 getCharIdxAtCaretPos() const;
+		CM::UINT32 getCharIdxAtCaretPos(CM::UINT32 caretPos) const;
 		CM::Int2 getCaretPosition(const CM::Int2& offset) const;
 		CM::Int2 getCaretPosition(const CM::Int2& offset) const;
 		CM::UINT32 getCaretHeight() const;
 		CM::UINT32 getCaretHeight() const;
 
 

+ 36 - 5
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -27,7 +27,7 @@ namespace BansheeEngine
 	GUIInputBox::GUIInputBox(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions, bool multiline)
 	GUIInputBox::GUIInputBox(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions, bool multiline)
 		:GUIElement(parent, style, layoutOptions), mInputCursorSet(false), mDragInProgress(false),
 		:GUIElement(parent, style, layoutOptions), mInputCursorSet(false), mDragInProgress(false),
 		mSelectionStart(0), mSelectionEnd(0), mSelectionAnchor(0), mInputCaret(nullptr), mCaretShown(false), 
 		mSelectionStart(0), mSelectionEnd(0), mSelectionAnchor(0), mInputCaret(nullptr), mCaretShown(false), 
-		mSelectionShown(false), mIsMultiline(multiline)
+		mSelectionShown(false), mIsMultiline(multiline), mSelectionDragAnchor(0)
 	{
 	{
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 		mTextSprite = cm_new<TextSprite, PoolAlloc>();
 		mTextSprite = cm_new<TextSprite, PoolAlloc>();
@@ -316,6 +316,10 @@ namespace BansheeEngine
 		else if(ev.getType() == GUIMouseEventType::MouseUp)
 		else if(ev.getType() == GUIMouseEventType::MouseUp)
 		{
 		{
 			mImageDesc.texture = mStyle->hover.texture;
 			mImageDesc.texture = mStyle->hover.texture;
+
+			if(mSelectionStart == mSelectionEnd)
+				clearSelection();
+
 			markAsDirty();
 			markAsDirty();
 
 
 			return true;
 			return true;
@@ -340,18 +344,45 @@ namespace BansheeEngine
 		}
 		}
 		else if(ev.getType() == GUIMouseEventType::MouseDrag)
 		else if(ev.getType() == GUIMouseEventType::MouseDrag)
 		{
 		{
+			Rect bounds = getTextBounds();
 			if(mText.size() > 0)
 			if(mText.size() > 0)
 				mInputCaret->moveCaretToPos(ev.getPosition());
 				mInputCaret->moveCaretToPos(ev.getPosition());
 			else
 			else
 				mInputCaret->moveCaretToStart();
 				mInputCaret->moveCaretToStart();
 
 
-			scrollTextToCaret();
+			if(!mSelectionShown)
+			{
+				showSelection(getCaretSelectionCharIdx(SelectionDir::Left));
+				mSelectionDragAnchor = mInputCaret->getCaretPos();
+			}
 
 
+			UINT32 curCaretPos = mInputCaret->getCaretPos();
+			if(curCaretPos < mSelectionDragAnchor)
+			{
+				mSelectionStart = mInputCaret->getCharIdxAtCaretPos(curCaretPos);
+				mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
+
+				mSelectionAnchor = mSelectionStart;
+			}
+
+			if(curCaretPos > mSelectionDragAnchor)
+			{
+				mSelectionStart = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
+				mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(curCaretPos);
+
+				mSelectionAnchor = mSelectionEnd;
+			}
+
+			if(curCaretPos == mSelectionDragAnchor)
+			{
+				mSelectionStart = mSelectionAnchor;
+				mSelectionEnd = mSelectionAnchor;
+			}
+
+			scrollTextToCaret();
 
 
-			// TODO - Update selection
-			//  - If mouse is over control, place selection marker there (make sure start < end)
-			//  - Else move the selection by a certain amount of pixels depending on drag amount
 			markAsDirty();
 			markAsDirty();
+			return true;
 		}
 		}
 
 
 		return false;
 		return false;

+ 20 - 4
BansheeEngine/Source/BsGUIInputCaret.cpp

@@ -128,6 +128,12 @@ namespace BansheeEngine
 		{
 		{
 			UINT32 numLines = mTextSprite->getNumLines();
 			UINT32 numLines = mTextSprite->getNumLines();
 
 
+			if(numLines == 0)
+			{
+				mCaretPos = 0;
+				return;
+			}
+
 			UINT32 curPos = 0;
 			UINT32 curPos = 0;
 			for(UINT32 i = 0; i < numLines; i++)
 			for(UINT32 i = 0; i < numLines; i++)
 			{
 			{
@@ -143,7 +149,12 @@ namespace BansheeEngine
 				curPos += numChars;
 				curPos += numChars;
 			}
 			}
 
 
-			mCaretPos = curPos;
+			const SpriteLineDesc& firstLine = mTextSprite->getLineDesc(0);
+
+			if(pos.y < firstLine.getLineYStart()) // Before first line
+				mCaretPos = 0;
+			else // After last line
+				mCaretPos = curPos - 1;
 		}
 		}
 	}
 	}
 
 
@@ -187,6 +198,11 @@ namespace BansheeEngine
 	}
 	}
 
 
 	UINT32 GUIInputCaret::getCharIdxAtCaretPos() const
 	UINT32 GUIInputCaret::getCharIdxAtCaretPos() const
+	{
+		return getCharIdxAtCaretPos(mCaretPos);
+	}
+
+	UINT32 GUIInputCaret::getCharIdxAtCaretPos(UINT32 caretPos) const
 	{
 	{
 		if(mTextDesc.text.size() == 0)
 		if(mTextDesc.text.size() == 0)
 			return 0;
 			return 0;
@@ -198,21 +214,21 @@ namespace BansheeEngine
 		{
 		{
 			const SpriteLineDesc& lineDesc = mTextSprite->getLineDesc(i);
 			const SpriteLineDesc& lineDesc = mTextSprite->getLineDesc(i);
 
 
-			if(curPos == mCaretPos)
+			if(curPos == caretPos)
 				return lineDesc.getStartChar();
 				return lineDesc.getStartChar();
 
 
 			curPos++; // Move past line start position
 			curPos++; // Move past line start position
 
 
 			UINT32 numChars = lineDesc.getEndChar() - lineDesc.getStartChar();
 			UINT32 numChars = lineDesc.getEndChar() - lineDesc.getStartChar();
 			UINT32 numCaretPositions = lineDesc.getEndChar(false) - lineDesc.getStartChar();
 			UINT32 numCaretPositions = lineDesc.getEndChar(false) - lineDesc.getStartChar();
-			if(mCaretPos >= (curPos + numCaretPositions))
+			if(caretPos >= (curPos + numCaretPositions))
 			{
 			{
 				curCharIdx += numChars;
 				curCharIdx += numChars;
 				curPos += numCaretPositions;
 				curPos += numCaretPositions;
 				continue;
 				continue;
 			}
 			}
 
 
-			UINT32 diff = mCaretPos - curPos; 
+			UINT32 diff = caretPos - curPos; 
 			curCharIdx += diff + 1; // Character after the caret
 			curCharIdx += diff + 1; // Character after the caret
 
 
 			return curCharIdx;
 			return curCharIdx;