浏览代码

Use Scrollable class for all appropriate locations

Ivan Savenko 2 年之前
父节点
当前提交
0e36a3ab5a

+ 25 - 41
client/adventureMap/CList.cpp

@@ -82,9 +82,8 @@ void CList::CListItem::onSelect(bool on)
 }
 
 CList::CList(int Size, Rect widgetDimensions)
-	: CIntObject(WHEEL | GESTURE_PANNING, widgetDimensions.topLeft()),
+	: Scrollable(0, widgetDimensions.topLeft(), Orientation::VERTICAL),
 	size(Size),
-	panningDistanceAccumulated(0),
 	selected(nullptr)
 {
 	pos.w = widgetDimensions.w;
@@ -108,8 +107,7 @@ void CList::setScrollUpButton(std::shared_ptr<CButton> button)
 	addChild(button.get());
 
 	scrollUp = button;
-	scrollUp->addCallback(std::bind(&CListBox::moveToPrev, listBox));
-	scrollUp->addCallback(std::bind(&CList::update, this));
+	scrollUp->addCallback(std::bind(&CList::scrollPrev, this));
 	update();
 }
 
@@ -118,8 +116,29 @@ void CList::setScrollDownButton(std::shared_ptr<CButton> button)
 	addChild(button.get());
 
 	scrollDown = button;
-	scrollDown->addCallback(std::bind(&CList::update, this));
-	scrollDown->addCallback(std::bind(&CListBox::moveToNext, listBox));
+	scrollDown->addCallback(std::bind(&CList::scrollNext, this));
+	update();
+}
+
+void CList::scrollBy(int distance)
+{
+	if (distance < 0 && listBox->getPos() < -distance)
+		listBox->moveToPos(0);
+	else
+		listBox->moveToPos(static_cast<int>(listBox->getPos()) + distance);
+
+	update();
+}
+
+void CList::scrollPrev()
+{
+	listBox->moveToPrev();
+	update();
+}
+
+void CList::scrollNext()
+{
+	listBox->moveToNext();
 	update();
 }
 
@@ -188,41 +207,6 @@ void CList::selectPrev()
 		selectIndex(index-1);
 }
 
-void CList::panning(bool on)
-{
-	panningDistanceAccumulated = 0;
-}
-
-void CList::gesturePanning(const Point & distanceDelta)
-{
-	int panningDistanceSingle = 32;
-
-	panningDistanceAccumulated += distanceDelta.y;
-
-	while (-panningDistanceAccumulated > panningDistanceSingle )
-	{
-		listBox->moveToPrev();
-		panningDistanceAccumulated += panningDistanceSingle;
-	}
-
-	while (panningDistanceAccumulated > panningDistanceSingle )
-	{
-		listBox->moveToNext();
-		panningDistanceAccumulated -= panningDistanceSingle;
-	}
-
-	update();
-}
-
-void CList::wheelScrolled(int distance)
-{
-	if (distance < 0)
-		listBox->moveToNext();
-	if (distance > 0)
-		listBox->moveToPrev();
-	update();
-}
-
 CHeroList::CEmptyHeroItem::CEmptyHeroItem()
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);

+ 6 - 7
client/adventureMap/CList.h

@@ -9,7 +9,7 @@
  */
 #pragma once
 
-#include "../gui/CIntObject.h"
+#include "../widgets/Scrollable.h"
 #include "../../lib/FunctionList.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
@@ -24,7 +24,7 @@ class CButton;
 class CAnimImage;
 
 /// Base UI Element for hero\town lists
-class CList : public CIntObject
+class CList : public Scrollable
 {
 protected:
 	class CListItem : public CIntObject, public std::enable_shared_from_this<CListItem>
@@ -55,8 +55,6 @@ protected:
 
 private:
 	const size_t size;
-	/// How far have player moved finger/mouse via gesture so far.
-	int panningDistanceAccumulated;
 
 	//for selection\deselection
 	std::shared_ptr<CListItem> selected;
@@ -66,6 +64,10 @@ private:
 	std::shared_ptr<CButton> scrollUp;
 	std::shared_ptr<CButton> scrollDown;
 
+	void scrollBy(int distance) override;
+	void scrollPrev() override;
+	void scrollNext() override;
+
 protected:
 	std::shared_ptr<CListBox> listBox;
 
@@ -94,9 +96,6 @@ public:
 	void selectPrev();
 
 	void showAll(Canvas & to) override;
-	void panning(bool on) override;
-	void gesturePanning(const Point & distanceDelta) override;
-	void wheelScrolled(int distance) override;
 };
 
 /// List of heroes which is shown at the right of the adventure map screen

+ 1 - 4
client/gui/EventDispatcher.cpp

@@ -198,10 +198,8 @@ void EventDispatcher::dispatchMouseScrolled(const Point & distance, const Point
 		if(!vstd::contains(wheelInterested,i))
 			continue;
 
-		// ignore distance value and only provide its sign - we expect one scroll "event" to move sliders and such by 1 point,
-		// and not by system-specific "number of lines to scroll", which is what 'distance' represents
 		if (i->receiveEvent(position, AEventsReceiver::WHEEL))
-			i->wheelScrolled( std::clamp(distance.y, -1, 1));
+			i->wheelScrolled(distance.y);
 	}
 }
 
@@ -227,7 +225,6 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
 	{
 		if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE_PANNING))
 		{
-			assert(it->panningState == false);
 			it->panning(true);
 			it->panningState = true;
 		}

+ 8 - 34
client/lobby/OptionsTab.cpp

@@ -413,9 +413,8 @@ void OptionsTab::CPlayerOptionTooltipBox::genBonusWindow()
 }
 
 OptionsTab::SelectedBox::SelectedBox(Point position, PlayerSettings & settings, SelType type)
-	: CIntObject(RCLICK | WHEEL | GESTURE_PANNING, position)
+	: Scrollable(RCLICK, position, Orientation::HORIZONTAL)
 	, CPlayerSettingsHelper(settings, type)
-	, panningDistanceAccumulated(0)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
 
@@ -423,6 +422,8 @@ OptionsTab::SelectedBox::SelectedBox(Point position, PlayerSettings & settings,
 	subtitle = std::make_shared<CLabel>(23, 39, FONT_TINY, ETextAlignment::CENTER, Colors::WHITE, getName());
 
 	pos = image->pos;
+
+	setPanningStep(pos.w);
 }
 
 void OptionsTab::SelectedBox::update()
@@ -445,8 +446,11 @@ void OptionsTab::SelectedBox::clickRight(tribool down, bool previousState)
 	}
 }
 
-void OptionsTab::SelectedBox::wheelScrolled(int distance)
+void OptionsTab::SelectedBox::scrollBy(int distance)
 {
+	// FIXME: currently options tab is completely recreacted from scratch whenever we receive any information from server
+	// because of that, panning event gets interrupted (due to destruction of element)
+	// so, currently, gesture will always move selection only by 1, and then wait for recreation from server info
 	distance = std::clamp(distance, -1, 1);
 
 	switch(CPlayerSettingsHelper::type)
@@ -461,38 +465,8 @@ void OptionsTab::SelectedBox::wheelScrolled(int distance)
 			CSH->setPlayerOption(LobbyChangePlayerOption::BONUS, distance, settings.color);
 			break;
 	}
-}
-
-void OptionsTab::SelectedBox::panning(bool on)
-{
-	panningDistanceAccumulated = 0;
-}
-
-void OptionsTab::SelectedBox::gesturePanning(const Point & distanceDelta)
-{
-	// FIXME: currently options tab is completely recreacted from scratch whenever we receive any information from server
-	// because of that, panning event gets interrupted (due to destruction of element)
-	// so, currently, gesture will always move selection only by 1, and then wait for recreation from server info
-
-	int panningDistanceSingle = 48;
-
-	panningDistanceAccumulated += distanceDelta.x;
-
-	if (-panningDistanceAccumulated > panningDistanceSingle )
-	{
-		int scrollAmount = (-panningDistanceAccumulated) / panningDistanceSingle;
-		wheelScrolled(-scrollAmount);
-		panningDistanceAccumulated += scrollAmount * panningDistanceSingle;
-		removeUsedEvents(GESTURE_PANNING);
-	}
 
-	if (panningDistanceAccumulated > panningDistanceSingle )
-	{
-		int scrollAmount = panningDistanceAccumulated / panningDistanceSingle;
-		wheelScrolled(scrollAmount);
-		panningDistanceAccumulated += -scrollAmount * panningDistanceSingle;
-		removeUsedEvents(GESTURE_PANNING);
-	}
+	setScrollingEnabled(false);
 }
 
 OptionsTab::PlayerOptionsEntry::PlayerOptionsEntry(const PlayerSettings & S, const OptionsTab & parent)

+ 4 - 5
client/lobby/OptionsTab.h

@@ -16,6 +16,8 @@ struct PlayerSettings;
 struct PlayerInfo;
 VCMI_LIB_NAMESPACE_END
 
+#include "../widgets/Scrollable.h"
+
 class CSlider;
 class CLabel;
 class CMultiLineLabel;
@@ -93,17 +95,14 @@ public:
 	};
 
 	/// Image with current town/hero/bonus
-	struct SelectedBox : public CIntObject, public CPlayerSettingsHelper
+	struct SelectedBox : public Scrollable, public CPlayerSettingsHelper
 	{
 		std::shared_ptr<CAnimImage> image;
 		std::shared_ptr<CLabel> subtitle;
-		int panningDistanceAccumulated;
 
 		SelectedBox(Point position, PlayerSettings & settings, SelType type);
 		void clickRight(tribool down, bool previousState) override;
-		void wheelScrolled(int distance) override;
-		void gesturePanning(const Point & distanceDelta) override;
-		void panning(bool on) override;
+		void scrollBy(int distance) override;
 
 		void update();
 	};

+ 2 - 2
client/widgets/Scrollable.cpp

@@ -28,9 +28,9 @@ void Scrollable::panning(bool on)
 void Scrollable::wheelScrolled(int distance)
 {
 	if (orientation == Orientation::HORIZONTAL)
-		scrollBy(distance * 3);
+		scrollBy(distance * scrollStep);
 	else
-		scrollBy(-distance * 3);
+		scrollBy(-distance * scrollStep);
 }
 
 void Scrollable::gesturePanning(const Point & distanceDelta)

+ 1 - 1
client/widgets/Scrollable.h

@@ -21,7 +21,7 @@ enum class Orientation
 /// Simple class that provides scrolling functionality via either mouse wheel or touchscreen gesture
 class Scrollable : public CIntObject
 {
-	/// how many elements will be scrolled via one click, default = 1
+	/// how many elements will be scrolled via one wheel action, default = 1
 	int scrollStep;
 	/// How far player must move finger/mouse to move slider by 1 via gesture
 	int panningDistanceSingle;