2
0
Эх сурвалжийг харах

Clicking the scroll buttons works

Marko Pintera 12 жил өмнө
parent
commit
6a893cc149

+ 3 - 0
BansheeEngine/Include/BsGUIButton.h

@@ -3,6 +3,7 @@
 #include "BsPrerequisites.h"
 #include "BsGUIElement.h"
 #include "BsImageSprite.h"
+#include "boost/signal.hpp"
 
 namespace BansheeEngine
 {
@@ -13,6 +14,8 @@ namespace BansheeEngine
 
 		static GUIButton* create(GUIWidget& parent, const CM::WString& text, const GUIElementStyle* style = nullptr);
 		static GUIButton* create(GUIWidget& parent, const CM::WString& text, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+	
+		boost::signal<void()> onClick;
 	protected:
 		~GUIButton();
 

+ 12 - 1
BansheeEngine/Include/BsGUIScrollBar.h

@@ -10,12 +10,19 @@ namespace BansheeEngine
 	class BS_EXPORT GUIScrollBar : public GUIElement
 	{
 	public:
-		boost::signal<void(float newPosition)> scrollPositionChanged;
+		boost::signal<void(float newPosition)> onScrollPositionChanged;
 
 		void setHandleSize(CM::UINT32 size);
 		void setScrollPos(float pct);
 
+		/**
+		 * @brief	Sets a page size that is used for determining how far to jump
+		 * 			when clicking on the scrollbar empty space.
+		 */
+		void setPageSize(CM::UINT32 size);
+
 		CM::UINT32 getMaxHandleSize() const;
+		CM::UINT32 getScrollableSize() const;
 	protected:
 		GUIScrollBar(GUIWidget& parent, bool horizontal, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
 		virtual ~GUIScrollBar();
@@ -59,6 +66,10 @@ namespace BansheeEngine
 		GUIScrollBarHandle* mHandleBtn;
 		bool mHorizontal;
 
+		static const CM::UINT32 ButtonScrollAmount;
+
 		void handleMoved(float handlePct);
+		void upButtonClicked();
+		void downButtonClicked();
 	};
 }

+ 8 - 1
BansheeEngine/Include/BsGUIScrollBarHandle.h

@@ -18,10 +18,14 @@ namespace BansheeEngine
 
 		void setHandleSize(CM::UINT32 size);
 		void setHandlePos(float pct);
+		void setPageSize(CM::UINT32 size);
+
+		CM::UINT32 getScrollableSize() const;
+		float getHandlePos() const;
 
 		CM::UINT32 getMaxSize() const;
 
-		boost::signal<void(float newPosition)> handleMoved;
+		boost::signal<void(float newPosition)> onHandleMoved;
 	protected:
 		~GUIScrollBarHandle();
 
@@ -62,6 +66,9 @@ namespace BansheeEngine
 		CM::INT32 mDragStartPos;
 		bool mMouseOverHandle;
 		bool mHandleDragged;
+		CM::UINT32 mPageSize;
+
+		static const CM::UINT32 DefaultPageScrollAmount;
 
 		GUIScrollBarHandle(GUIWidget& parent, bool horizontal, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
 

+ 3 - 0
BansheeEngine/Include/BsGUIToggle.h

@@ -3,6 +3,7 @@
 #include "BsPrerequisites.h"
 #include "BsGUIElement.h"
 #include "BsImageSprite.h"
+#include "boost/signal.hpp"
 
 namespace BansheeEngine
 {
@@ -13,6 +14,8 @@ namespace BansheeEngine
 
 		static GUIToggle* create(GUIWidget& parent, const CM::WString& text, const GUIElementStyle* style = nullptr);
 		static GUIToggle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const CM::WString& text, const GUIElementStyle* style = nullptr);
+	
+		boost::signal<void(bool)> onToggled;
 	protected:
 		~GUIToggle();
 

+ 3 - 0
BansheeEngine/Source/BsGUIButton.cpp

@@ -192,6 +192,9 @@ namespace BansheeEngine
 			mImageDesc.texture = mStyle->hover.texture;
 			markContentAsDirty();
 
+			if(!onClick.empty())
+				onClick();
+
 			return true;
 		}
 		

+ 2 - 1
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -80,7 +80,7 @@ namespace BansheeEngine
 			if(mVertScroll == nullptr)
 			{
 				mVertScroll = GUIScrollBarVert::create(_getParentWidget());
-				mVertScroll->scrollPositionChanged.connect(boost::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
+				mVertScroll->onScrollPositionChanged.connect(boost::bind(&GUIScrollArea::vertScrollUpdate, this, _1));
 			}
 
 			Int2 offset(x + contentWidth, y);
@@ -107,6 +107,7 @@ namespace BansheeEngine
 
 			mVertScroll->setHandleSize(newHandleSize);
 			mVertScroll->setScrollPos(newScrollPct);
+			mVertScroll->setPageSize(mHeight);
 		}
 		else
 		{

+ 41 - 4
BansheeEngine/Source/BsGUIScrollBar.cpp

@@ -14,6 +14,8 @@ using namespace CamelotFramework;
 
 namespace BansheeEngine
 {
+	const UINT32 GUIScrollBar::ButtonScrollAmount = 10;
+
 	GUIScrollBar::GUIScrollBar(GUIWidget& parent, bool horizontal, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
 		:GUIElement(parent, style, layoutOptions), mHorizontal(horizontal)
 	{
@@ -46,7 +48,10 @@ namespace BansheeEngine
 		mLayout->addElement(mDownBtn);
 		mLayout->addSpace(2);
 
-		mHandleBtn->handleMoved.connect(boost::bind(&GUIScrollBar::handleMoved, this, _1));
+		mHandleBtn->onHandleMoved.connect(boost::bind(&GUIScrollBar::handleMoved, this, _1));
+
+		mUpBtn->onClick.connect(boost::bind(&GUIScrollBar::upButtonClicked, this));
+		mDownBtn->onClick.connect(boost::bind(&GUIScrollBar::downButtonClicked, this));
 	}
 
 	GUIScrollBar::~GUIScrollBar()
@@ -106,8 +111,30 @@ namespace BansheeEngine
 
 	void GUIScrollBar::handleMoved(float handlePct)
 	{
-		if(!scrollPositionChanged.empty())
-			scrollPositionChanged(handlePct);
+		if(!onScrollPositionChanged.empty())
+			onScrollPositionChanged(handlePct);
+	}
+
+	void GUIScrollBar::upButtonClicked()
+	{
+		float handleOffset = ButtonScrollAmount / (float)mHandleBtn->getScrollableSize();
+		float newHandlePos = std::max(0.0f, mHandleBtn->getHandlePos() - handleOffset);
+
+		mHandleBtn->setHandlePos(newHandlePos);
+
+		if(!onScrollPositionChanged.empty())
+			onScrollPositionChanged(newHandlePos);
+	}
+
+	void GUIScrollBar::downButtonClicked()
+	{
+		float handleOffset = ButtonScrollAmount / (float)mHandleBtn->getScrollableSize();
+		float newHandlePos = std::min(1.0f, mHandleBtn->getHandlePos() + handleOffset);
+
+		mHandleBtn->setHandlePos(newHandlePos);
+
+		if(!onScrollPositionChanged.empty())
+			onScrollPositionChanged(newHandlePos);
 	}
 
 	void GUIScrollBar::setHandleSize(UINT32 size)
@@ -120,8 +147,18 @@ namespace BansheeEngine
 		mHandleBtn->setHandlePos(pct);
 	}
 
-	CM::UINT32 GUIScrollBar::getMaxHandleSize() const
+	UINT32 GUIScrollBar::getMaxHandleSize() const
 	{
 		return mHandleBtn->getMaxSize();
 	}
+
+	UINT32 GUIScrollBar::getScrollableSize() const
+	{
+		return mHandleBtn->getScrollableSize();
+	}
+
+	void GUIScrollBar::setPageSize(UINT32 size)
+	{
+		mHandleBtn->setPageSize(size);
+	}
 }

+ 54 - 3
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -12,6 +12,8 @@ using namespace CamelotFramework;
 
 namespace BansheeEngine
 {
+	const UINT32 GUIScrollBarHandle::DefaultPageScrollAmount = 100;
+
 	const String& GUIScrollBarHandle::getGUITypeName()
 	{
 		static String name = "ScrollBarHandle";
@@ -20,7 +22,7 @@ namespace BansheeEngine
 
 	GUIScrollBarHandle::GUIScrollBarHandle(GUIWidget& parent, bool horizontal, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
 		:GUIElement(parent, style, layoutOptions), mHorizontal(horizontal), mHandleSize(2), mMouseOverHandle(false), mHandlePos(0), mDragStartPos(0),
-		mHandleDragged(false)
+		mHandleDragged(false), mPageSize(DefaultPageScrollAmount)
 	{
 		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
 		mCurTexture = style->normal.texture;
@@ -67,6 +69,22 @@ namespace BansheeEngine
 		markContentAsDirty();
 	}
 
+	void GUIScrollBarHandle::setPageSize(UINT32 size)
+	{
+		mPageSize = size;
+	}
+
+	float GUIScrollBarHandle::getHandlePos() const
+	{
+		UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
+		return (float)mHandlePos / maxScrollAmount;
+	}
+
+	UINT32 GUIScrollBarHandle::getScrollableSize() const
+	{
+		return getMaxSize() - mHandleSize;
+	}
+
 	UINT32 GUIScrollBarHandle::getNumRenderElements() const
 	{
 		return mImageSprite->getNumRenderElements();
@@ -208,10 +226,10 @@ namespace BansheeEngine
 			UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
 			mHandlePos = Math::Clamp(mHandlePos, 0, (INT32)maxScrollAmount);
 
-			if(!handleMoved.empty())
+			if(!onHandleMoved.empty())
 			{
 				float pct = (float)mHandlePos / maxScrollAmount;
-				handleMoved(pct);
+				onHandleMoved(pct);
 			}
 
 			markContentAsDirty();
@@ -233,6 +251,39 @@ namespace BansheeEngine
 			else
 				mCurTexture = mStyle->normal.texture;
 
+			// If we clicked above or below the scroll handle, scroll by one page
+			INT32 handleOffset = 0;
+			if(mHorizontal)
+			{
+				INT32 handleLeft = (INT32)mOffset.x + mHandlePos;
+				INT32 handleRight = handleLeft + mHandleSize;
+
+				if(ev.getPosition().x < handleLeft)
+					handleOffset -= mPageSize;
+				else if(ev.getPosition().x > handleRight)
+					handleOffset += mPageSize;
+			}
+			else
+			{
+				INT32 handleTop = (INT32)mOffset.y + mHandlePos;
+				INT32 handleBottom = handleTop + mHandleSize;
+
+				if(ev.getPosition().y < handleTop)
+					handleOffset -= mPageSize;
+				else if(ev.getPosition().y > handleBottom)
+					handleOffset += mPageSize;
+			}
+
+			mHandlePos += handleOffset;
+			UINT32 maxScrollAmount = getMaxSize() - mHandleSize;
+			mHandlePos = Math::Clamp(mHandlePos, 0, (INT32)maxScrollAmount);
+
+			if(!onHandleMoved.empty())
+			{
+				float pct = (float)mHandlePos / maxScrollAmount;
+				onHandleMoved(pct);
+			}
+
 			markContentAsDirty();
 			return true;
 		}

+ 4 - 0
BansheeEngine/Source/BsGUIToggle.cpp

@@ -206,6 +206,10 @@ namespace BansheeEngine
 				mImageDesc.texture = mStyle->normal.texture;
 
 			markContentAsDirty();
+
+			if(!onToggled.empty())
+				onToggled(mIsToggled);
+
 			return true;
 		}
 

+ 7 - 0
CamelotUtility/Include/CmMath.h

@@ -579,6 +579,13 @@ namespace CamelotFramework
 			return std::max(std::min(val, maxval), minval);
 		}
 
+		/** Clamp a value within an inclusive range. */
+		template <typename T>
+		static T Clamp01(T val)
+		{
+			return std::max(std::min(val, (T)1), (T)0);
+		}
+
 		static Matrix4 makeViewMatrix(const Vector3& position, const Quaternion& orientation, 
 			const Matrix4* reflectMatrix = 0);
 

+ 0 - 1
TODO.txt

@@ -35,7 +35,6 @@ IMMEDIATE:
 - Clicking on the scroll buttons does nothing
 - Clicking on the empty scroll area doesn't do anything
 - Hover colors of the scroll bar are wrong
-- Add horizontal scrollbar
 
 TextBox needed elements:
  - Key-repeat? Pressing left/right/up/down arrows doesn't repeat the keys (also delete/backspace)