ソースを参照

More refactoring of input selection

Marko Pintera 12 年 前
コミット
b5b886dc7e

+ 2 - 6
BansheeEngine/Include/BsGUIInputBox.h

@@ -5,15 +5,10 @@
 #include "BsImageSprite.h"
 #include "BsImageSprite.h"
 #include "BsTextSprite.h"
 #include "BsTextSprite.h"
 #include "BsGUIInputCaret.h"
 #include "BsGUIInputCaret.h"
+#include "BsGUIInputSelection.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	enum class SelectionDir
-	{
-		Left,
-		Right
-	};
-
 	class BS_EXPORT GUIInputBox : public GUIElement
 	class BS_EXPORT GUIInputBox : public GUIElement
 	{
 	{
 	public:
 	public:
@@ -97,6 +92,7 @@ namespace BansheeEngine
 		void moveSelectionRight(bool skipnewLine);
 		void moveSelectionRight(bool skipnewLine);
 		void moveSelectionUp();
 		void moveSelectionUp();
 		void moveSelectionDown();
 		void moveSelectionDown();
+		void moveSelectionToCaret(CM::UINT32 caretPos);
 		bool isSelectionEmpty() const;
 		bool isSelectionEmpty() const;
 		void selectAll();
 		void selectAll();
 
 

+ 24 - 0
BansheeEngine/Include/BsGUIInputSelection.h

@@ -5,6 +5,12 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	enum class SelectionDir
+	{
+		Left,
+		Right
+	};
+
 	class BS_EXPORT GUIInputSelection
 	class BS_EXPORT GUIInputSelection
 	{
 	{
 	public:
 	public:
@@ -15,6 +21,22 @@ namespace BansheeEngine
 		void updateText(const TEXT_SPRITE_DESC& textDesc);
 		void updateText(const TEXT_SPRITE_DESC& textDesc);
 		void updateSprite(const CM::Int2& offset);
 		void updateSprite(const CM::Int2& offset);
 
 
+		void showSelection(CM::UINT32 anchorCaretPos, SelectionDir dir);
+		void clearSelection();
+
+		void moveSelectionToCaret(CM::UINT32 caretPos);
+		bool isSelectionEmpty() const;
+		void selectAll();
+
+		void selectionDragStart(CM::UINT32 caretPos);
+		void selectionDragUpdate(CM::UINT32 caretPos);
+		void selectionDragEnd();
+
+		CM::UINT32 getSelectionStart() const { return mSelectionStart; }
+		CM::UINT32 getSelectionEnd() const { return mSelectionEnd; }
+
+		CM::UINT32 caretPosToSelectionChar(CM::UINT32 caretPos, SelectionDir dir) const;
+
 	private:
 	private:
 		CM::UINT32 mSelectionStart;
 		CM::UINT32 mSelectionStart;
 		CM::UINT32 mSelectionEnd;
 		CM::UINT32 mSelectionEnd;
@@ -27,5 +49,7 @@ namespace BansheeEngine
 
 
 		CM::Vector<CM::Rect>::type getSelectionRects() const;
 		CM::Vector<CM::Rect>::type getSelectionRects() const;
 		bool isNewlineChar(CM::UINT32 charIdx) const;
 		bool isNewlineChar(CM::UINT32 charIdx) const;
+
+		CM::UINT32 getCharIdxAtCaretPos(CM::UINT32 caretPos) const;
 	};
 	};
 }
 }

+ 134 - 59
BansheeEngine/Source/BsGUIInputBox.cpp

@@ -362,45 +362,6 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
-	void GUIInputBox::selectionDragStart(UINT32 caretPos)
-	{
-		clearSelection();
-
-		showSelection(caretPos, SelectionDir::Left); 
-		mSelectionDragAnchor = caretPos;
-	}
-
-	void GUIInputBox::selectionDragUpdate(UINT32 caretPos)
-	{
-		if(caretPos < mSelectionDragAnchor)
-		{
-			mSelectionStart = mInputCaret->getCharIdxAtCaretPos(caretPos);
-			mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
-
-			mSelectionAnchor = mSelectionStart;
-		}
-
-		if(caretPos > mSelectionDragAnchor)
-		{
-			mSelectionStart = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
-			mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(caretPos);
-
-			mSelectionAnchor = mSelectionEnd;
-		}
-
-		if(caretPos == mSelectionDragAnchor)
-		{
-			mSelectionStart = mSelectionAnchor;
-			mSelectionEnd = mSelectionAnchor;
-		}
-	}
-
-	void GUIInputBox::selectionDragEnd()
-	{
-		if(isSelectionEmpty())
-			clearSelection();
-	}
-
 	bool GUIInputBox::keyEvent(const GUIKeyEvent& ev)
 	bool GUIInputBox::keyEvent(const GUIKeyEvent& ev)
 	{
 	{
 		if(ev.getType() == GUIKeyEventType::KeyDown)
 		if(ev.getType() == GUIKeyEventType::KeyDown)
@@ -577,22 +538,50 @@ namespace BansheeEngine
 
 
 						showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
 						showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
 					}
 					}
-
-					moveSelectionUp();
-					scrollTextToCaret();
-
-					markAsDirty();
-					return true;
 				}
 				}
 				else
 				else
 				{
 				{
 					clearSelection();
 					clearSelection();
-					mInputCaret->moveCaretUp();
-					scrollTextToCaret();
+				}
 
 
-					markAsDirty();
-					return true;
+				mInputCaret->moveCaretUp();
+				scrollTextToCaret();
+
+				if(ev.isShiftDown())
+				{
+					moveSelectionToCaret(mInputCaret->getCaretPos());
 				}
 				}
+
+				markAsDirty();
+				return true;
+
+				//if(ev.isShiftDown())
+				//{
+				//	if(!mSelectionShown)
+				//	{
+				//		if(isNewlineChar(caretPosToSelectionChar(mInputCaret->getCaretPos(), SelectionDir::Right)))
+				//		{
+				//			mInputCaret->moveCaretLeft();
+				//		}
+
+				//		showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
+				//	}
+
+				//	moveSelectionUp();
+				//	scrollTextToCaret();
+
+				//	markAsDirty();
+				//	return true;
+				//}
+				//else
+				//{
+				//	clearSelection();
+				//	mInputCaret->moveCaretUp();
+				//	scrollTextToCaret();
+
+				//	markAsDirty();
+				//	return true;
+				//}
 			}
 			}
 
 
 			if(ev.getKey() == BC_DOWN)
 			if(ev.getKey() == BC_DOWN)
@@ -608,22 +597,50 @@ namespace BansheeEngine
 
 
 						showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
 						showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
 					}
 					}
-
-					moveSelectionDown();
-					scrollTextToCaret();
-
-					markAsDirty();
-					return true;
 				}
 				}
 				else
 				else
 				{
 				{
 					clearSelection();
 					clearSelection();
-					mInputCaret->moveCaretDown();
-					scrollTextToCaret();
+				}
 
 
-					markAsDirty();
-					return true;
+				mInputCaret->moveCaretDown();
+				scrollTextToCaret();
+
+				if(ev.isShiftDown())
+				{
+					moveSelectionToCaret(mInputCaret->getCaretPos());
 				}
 				}
+
+				markAsDirty();
+				return true;
+
+				//if(ev.isShiftDown())
+				//{
+				//	if(!mSelectionShown)
+				//	{
+				//		if(isNewlineChar(caretPosToSelectionChar(mInputCaret->getCaretPos(), SelectionDir::Left)))
+				//		{
+				//			mInputCaret->moveCaretRight();
+				//		}
+
+				//		showSelection(mInputCaret->getCaretPos(), SelectionDir::Left);
+				//	}
+
+				//	moveSelectionDown();
+				//	scrollTextToCaret();
+
+				//	markAsDirty();
+				//	return true;
+				//}
+				//else
+				//{
+				//	clearSelection();
+				//	mInputCaret->moveCaretDown();
+				//	scrollTextToCaret();
+
+				//	markAsDirty();
+				//	return true;
+				//}
 			}
 			}
 
 
 			if(ev.getKey() == BC_RETURN)
 			if(ev.getKey() == BC_RETURN)
@@ -797,6 +814,45 @@ namespace BansheeEngine
 		return false;
 		return false;
 	}
 	}
 
 
+	void GUIInputBox::selectionDragStart(UINT32 caretPos)
+	{
+		clearSelection();
+
+		showSelection(caretPos, SelectionDir::Left); 
+		mSelectionDragAnchor = caretPos;
+	}
+
+	void GUIInputBox::selectionDragUpdate(UINT32 caretPos)
+	{
+		if(caretPos < mSelectionDragAnchor)
+		{
+			mSelectionStart = mInputCaret->getCharIdxAtCaretPos(caretPos);
+			mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
+
+			mSelectionAnchor = mSelectionStart;
+		}
+
+		if(caretPos > mSelectionDragAnchor)
+		{
+			mSelectionStart = mInputCaret->getCharIdxAtCaretPos(mSelectionDragAnchor);
+			mSelectionEnd = mInputCaret->getCharIdxAtCaretPos(caretPos);
+
+			mSelectionAnchor = mSelectionEnd;
+		}
+
+		if(caretPos == mSelectionDragAnchor)
+		{
+			mSelectionStart = mSelectionAnchor;
+			mSelectionEnd = mSelectionAnchor;
+		}
+	}
+
+	void GUIInputBox::selectionDragEnd()
+	{
+		if(isSelectionEmpty())
+			clearSelection();
+	}
+
 	void GUIInputBox::moveSelectionLeft(bool skipNewline) 
 	void GUIInputBox::moveSelectionLeft(bool skipNewline) 
 	{
 	{
 		SelectionDir newlineTestSelectionDir;
 		SelectionDir newlineTestSelectionDir;
@@ -956,6 +1012,25 @@ namespace BansheeEngine
 			clearSelection();
 			clearSelection();
 	}
 	}
 
 
+	void GUIInputBox::moveSelectionToCaret(UINT32 caretPos)
+	{
+		UINT32 charIdx = caretPosToSelectionChar(caretPos, SelectionDir::Left);
+
+		if(charIdx > mSelectionAnchor)
+		{
+			mSelectionStart = mSelectionAnchor;
+			mSelectionEnd = charIdx;
+		}
+		else
+		{
+			mSelectionStart = charIdx;
+			mSelectionEnd = mSelectionAnchor;
+		}
+
+		if(mSelectionStart == mSelectionEnd)
+			clearSelection();
+	}
+
 	void GUIInputBox::selectAll()
 	void GUIInputBox::selectAll()
 	{
 	{
 		mSelectionStart = 0;
 		mSelectionStart = 0;

+ 6 - 0
BansheeEngine/Source/BsGUIInputCaret.cpp

@@ -80,7 +80,10 @@ namespace BansheeEngine
 			lineIdx++;	
 			lineIdx++;	
 
 
 		if(lineIdx == 0)
 		if(lineIdx == 0)
+		{
+			moveCaretToStart();
 			return;
 			return;
+		}
 
 
 		Int2 caretCoords = getCaretPosition(mTextDesc.offset);
 		Int2 caretCoords = getCaretPosition(mTextDesc.offset);
 		caretCoords.y -= getCaretHeight();
 		caretCoords.y -= getCaretHeight();
@@ -102,7 +105,10 @@ namespace BansheeEngine
 			lineIdx++;					  
 			lineIdx++;					  
 
 
 		if(lineIdx == (mTextSprite->getNumLines() - 1))
 		if(lineIdx == (mTextSprite->getNumLines() - 1))
+		{
+			moveCaretToEnd();
 			return;
 			return;
+		}
 
 
 		Int2 caretCoords = getCaretPosition(mTextDesc.offset);
 		Int2 caretCoords = getCaretPosition(mTextDesc.offset);
 		caretCoords.y += getCaretHeight();
 		caretCoords.y += getCaretHeight();

+ 102 - 0
BansheeEngine/Source/BsGUIInputSelection.cpp

@@ -160,6 +160,102 @@ namespace BansheeEngine
 		return selectionRects;
 		return selectionRects;
 	}
 	}
 
 
+	void GUIInputSelection::showSelection(CM::UINT32 anchorCaretPos, SelectionDir dir)
+	{
+		UINT32 charIdx = caretPosToSelectionChar(anchorCaretPos, dir);
+
+		mSelectionStart = charIdx;
+		mSelectionEnd = charIdx;
+		mSelectionAnchor = charIdx;
+	}
+
+	void GUIInputSelection::clearSelection()
+	{
+		for(auto& sprite : mSprites)
+			cm_delete(sprite);
+
+		mSprites.clear();
+	}
+
+	UINT32 GUIInputSelection::caretPosToSelectionChar(UINT32 caretPos, SelectionDir dir) const
+	{
+		UINT32 charIdx = getCharIdxAtCaretPos(caretPos);
+
+		if(dir == SelectionDir::Right)
+			charIdx = (UINT32)std::max(0, (INT32)(charIdx - 1));
+
+		return charIdx;
+	}
+
+	void GUIInputSelection::selectionDragStart(UINT32 caretPos)
+	{
+		clearSelection();
+
+		showSelection(caretPos, SelectionDir::Left); 
+		mSelectionDragAnchor = caretPos;
+	}
+
+	void GUIInputSelection::selectionDragUpdate(UINT32 caretPos)
+	{
+		if(caretPos < mSelectionDragAnchor)
+		{
+			mSelectionStart = getCharIdxAtCaretPos(caretPos);
+			mSelectionEnd = getCharIdxAtCaretPos(mSelectionDragAnchor);
+
+			mSelectionAnchor = mSelectionStart;
+		}
+
+		if(caretPos > mSelectionDragAnchor)
+		{
+			mSelectionStart = getCharIdxAtCaretPos(mSelectionDragAnchor);
+			mSelectionEnd = getCharIdxAtCaretPos(caretPos);
+
+			mSelectionAnchor = mSelectionEnd;
+		}
+
+		if(caretPos == mSelectionDragAnchor)
+		{
+			mSelectionStart = mSelectionAnchor;
+			mSelectionEnd = mSelectionAnchor;
+		}
+	}
+
+	void GUIInputSelection::selectionDragEnd()
+	{
+		if(isSelectionEmpty())
+			clearSelection();
+	}
+
+	void GUIInputSelection::moveSelectionToCaret(UINT32 caretPos)
+	{
+		UINT32 charIdx = caretPosToSelectionChar(caretPos, SelectionDir::Left);
+
+		if(charIdx > mSelectionAnchor)
+		{
+			mSelectionStart = mSelectionAnchor;
+			mSelectionEnd = charIdx;
+		}
+		else
+		{
+			mSelectionStart = charIdx;
+			mSelectionEnd = mSelectionAnchor;
+		}
+
+		if(mSelectionStart == mSelectionEnd)
+			clearSelection();
+	}
+
+	void GUIInputSelection::selectAll()
+	{
+		mSelectionStart = 0;
+		mSelectionEnd = (UINT32)mTextDesc.text.size();
+	}
+
+	bool GUIInputSelection::isSelectionEmpty() const
+	{
+		return mSelectionStart == mSelectionEnd;
+	}
+
 	bool GUIInputSelection::isNewlineChar(CM::UINT32 charIdx) const
 	bool GUIInputSelection::isNewlineChar(CM::UINT32 charIdx) const
 	{
 	{
 		if(mTextDesc.text[charIdx] == '\n')
 		if(mTextDesc.text[charIdx] == '\n')
@@ -167,4 +263,10 @@ namespace BansheeEngine
 
 
 		return false;
 		return false;
 	}
 	}
+
+	CM::UINT32 GUIInputSelection::getCharIdxAtCaretPos(CM::UINT32 caretPos) const
+	{
+		// TODO - Needs to be implemented in the base class
+		return 0;
+	}
 }
 }