mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Moved slider class to a separate file
This commit is contained in:
		| @@ -99,6 +99,8 @@ set(client_SRCS | ||||
| 	widgets/MiscWidgets.cpp | ||||
| 	widgets/ObjectLists.cpp | ||||
| 	widgets/TextControls.cpp | ||||
| 	widgets/Scrollable.cpp | ||||
| 	widgets/Slider.cpp | ||||
| 	widgets/CArtifactsOfHeroBase.cpp | ||||
| 	widgets/CArtifactsOfHeroMain.cpp | ||||
| 	widgets/CArtifactsOfHeroKingdom.cpp | ||||
| @@ -251,6 +253,8 @@ set(client_HEADERS | ||||
| 	widgets/MiscWidgets.h | ||||
| 	widgets/ObjectLists.h | ||||
| 	widgets/TextControls.h | ||||
| 	widgets/Scrollable.h | ||||
| 	widgets/Slider.h | ||||
| 	widgets/CArtifactsOfHeroBase.h | ||||
| 	widgets/CArtifactsOfHeroMain.h | ||||
| 	widgets/CArtifactsOfHeroKingdom.h | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|   | ||||
| @@ -28,10 +28,11 @@ | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../mainmenu/CMainMenu.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|   | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|   | ||||
| @@ -21,6 +21,7 @@ | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|   | ||||
| @@ -22,6 +22,7 @@ | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/GUIClasses.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|   | ||||
| @@ -472,343 +472,3 @@ int CToggleGroup::getSelected() const | ||||
| { | ||||
| 	return selectedID; | ||||
| } | ||||
|  | ||||
| void CSlider::sliderClicked() | ||||
| { | ||||
| 	addUsedEvents(MOVE); | ||||
| } | ||||
|  | ||||
| void CSlider::mouseMoved (const Point & cursorPosition) | ||||
| { | ||||
| 	double v = 0; | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		if(	std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2+40  ||  std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2  ) | ||||
| 			return; | ||||
| 		v = cursorPosition.x - pos.x - 24; | ||||
| 		v *= positions; | ||||
| 		v /= (pos.w - 48); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if(std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2+40  ||  std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2  ) | ||||
| 			return; | ||||
| 		v = cursorPosition.y - pos.y - 24; | ||||
| 		v *= positions; | ||||
| 		v /= (pos.h - 48); | ||||
| 	} | ||||
| 	v += 0.5; | ||||
| 	if(v!=value) | ||||
| 	{ | ||||
| 		moveTo(static_cast<int>(v)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CSlider::setScrollStep(int to) | ||||
| { | ||||
| 	scrollStep = to; | ||||
| } | ||||
|  | ||||
| void CSlider::setScrollBounds(const Rect & bounds ) | ||||
| { | ||||
| 	scrollBounds = bounds; | ||||
| } | ||||
|  | ||||
| void CSlider::clearScrollBounds() | ||||
| { | ||||
| 	scrollBounds = std::nullopt; | ||||
| } | ||||
|  | ||||
| int CSlider::getAmount() const | ||||
| { | ||||
| 	return amount; | ||||
| } | ||||
|  | ||||
| int CSlider::getValue() const | ||||
| { | ||||
| 	return value; | ||||
| } | ||||
|  | ||||
| int CSlider::getCapacity() const | ||||
| { | ||||
| 	return capacity; | ||||
| } | ||||
|  | ||||
| void CSlider::moveLeft() | ||||
| { | ||||
| 	moveTo(value-1); | ||||
| } | ||||
|  | ||||
| void CSlider::moveRight() | ||||
| { | ||||
| 	moveTo(value+1); | ||||
| } | ||||
|  | ||||
| void CSlider::moveBy(int amount) | ||||
| { | ||||
| 	moveTo(value + amount); | ||||
| } | ||||
|  | ||||
| void CSlider::updateSliderPos() | ||||
| { | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		if(positions) | ||||
| 		{ | ||||
| 			double part = static_cast<double>(value) / positions; | ||||
| 			part*=(pos.w-48); | ||||
| 			int newPos = static_cast<int>(part + pos.x + 16 - slider->pos.x); | ||||
| 			slider->moveBy(Point(newPos, 0)); | ||||
| 		} | ||||
| 		else | ||||
| 			slider->moveTo(Point(pos.x+16, pos.y)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if(positions) | ||||
| 		{ | ||||
| 			double part = static_cast<double>(value) / positions; | ||||
| 			part*=(pos.h-48); | ||||
| 			int newPos = static_cast<int>(part + pos.y + 16 - slider->pos.y); | ||||
| 			slider->moveBy(Point(0, newPos)); | ||||
| 		} | ||||
| 		else | ||||
| 			slider->moveTo(Point(pos.x, pos.y+16)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CSlider::moveTo(int to) | ||||
| { | ||||
| 	vstd::amax(to, 0); | ||||
| 	vstd::amin(to, positions); | ||||
|  | ||||
| 	//same, old position? | ||||
| 	if(value == to) | ||||
| 		return; | ||||
| 	value = to; | ||||
|  | ||||
| 	updateSliderPos(); | ||||
|  | ||||
| 	moved(to); | ||||
| } | ||||
|  | ||||
| void CSlider::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down && !slider->isBlocked()) | ||||
| 	{ | ||||
| 		double pw = 0; | ||||
| 		double rw = 0; | ||||
| 		if(horizontal) | ||||
| 		{ | ||||
| 			pw = GH.getCursorPosition().x-pos.x-25; | ||||
| 			rw = pw / static_cast<double>(pos.w - 48); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			pw = GH.getCursorPosition().y-pos.y-24; | ||||
| 			rw = pw / (pos.h-48); | ||||
| 		} | ||||
| 		if(pw < -8  ||  pw > (horizontal ? pos.w : pos.h) - 40) | ||||
| 			return; | ||||
| 		// 		if (rw>1) return; | ||||
| 		// 		if (rw<0) return; | ||||
| 		slider->clickLeft(true, slider->isMouseButtonPressed(MouseButton::LEFT)); | ||||
| 		moveTo((int)(rw * positions  +  0.5)); | ||||
| 		return; | ||||
| 	} | ||||
| 	removeUsedEvents(MOVE); | ||||
| } | ||||
|  | ||||
| bool CSlider::receiveEvent(const Point &position, int eventType) const | ||||
| { | ||||
| 	if (eventType != WHEEL && eventType != GESTURE_PANNING) | ||||
| 	{ | ||||
| 		return CIntObject::receiveEvent(position, eventType); | ||||
| 	} | ||||
|  | ||||
| 	if (!scrollBounds) | ||||
| 		return true; | ||||
|  | ||||
| 	Rect testTarget = *scrollBounds + pos.topLeft(); | ||||
|  | ||||
| 	return testTarget.isInside(position); | ||||
| } | ||||
|  | ||||
| void CSlider::setPanningStep(int to) | ||||
| { | ||||
| 	panningDistanceSingle = to; | ||||
| } | ||||
|  | ||||
| void CSlider::panning(bool on) | ||||
| { | ||||
| 	panningDistanceAccumulated = 0; | ||||
| } | ||||
|  | ||||
| void CSlider::gesturePanning(const Point & distanceDelta) | ||||
| { | ||||
| 	if (horizontal) | ||||
| 		panningDistanceAccumulated += -distanceDelta.x; | ||||
| 	else | ||||
| 		panningDistanceAccumulated += distanceDelta.y; | ||||
|  | ||||
| 	if (-panningDistanceAccumulated > panningDistanceSingle ) | ||||
| 	{ | ||||
| 		int scrollAmount = (-panningDistanceAccumulated) / panningDistanceSingle; | ||||
| 		moveBy(-scrollAmount); | ||||
| 		panningDistanceAccumulated += scrollAmount * panningDistanceSingle; | ||||
| 	} | ||||
|  | ||||
| 	if (panningDistanceAccumulated > panningDistanceSingle ) | ||||
| 	{ | ||||
| 		int scrollAmount = panningDistanceAccumulated / panningDistanceSingle; | ||||
| 		moveBy(scrollAmount); | ||||
| 		panningDistanceAccumulated += -scrollAmount * panningDistanceSingle; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style) | ||||
| 	: CIntObject(LCLICK | RCLICK | WHEEL | GESTURE_PANNING ), | ||||
| 	capacity(Capacity), | ||||
| 	horizontal(Horizontal), | ||||
| 	amount(Amount), | ||||
| 	value(Value), | ||||
| 	scrollStep(1), | ||||
| 	moved(Moved), | ||||
| 	panningDistanceAccumulated(0), | ||||
| 	panningDistanceSingle(32) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
| 	setAmount(amount); | ||||
| 	vstd::amax(value, 0); | ||||
| 	vstd::amin(value, positions); | ||||
|  | ||||
| 	pos.x += position.x; | ||||
| 	pos.y += position.y; | ||||
|  | ||||
| 	if(style == BROWN) | ||||
| 	{ | ||||
| 		std::string name = horizontal ? "IGPCRDIV.DEF" : "OVBUTN2.DEF"; | ||||
| 		//NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...) | ||||
|  | ||||
| 		left = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
| 		right = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
| 		slider = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
|  | ||||
| 		left->setImageOrder(0, 1, 1, 1); | ||||
| 		right->setImageOrder(2, 3, 3, 3); | ||||
| 		slider->setImageOrder(4, 4, 4, 4); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		left = std::make_shared<CButton>(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip()); | ||||
| 		right = std::make_shared<CButton>(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip()); | ||||
| 		slider = std::make_shared<CButton>(Point(), "SCNRBSL.DEF", CButton::tooltip()); | ||||
| 	} | ||||
| 	slider->actOnDown = true; | ||||
| 	slider->soundDisabled = true; | ||||
| 	left->soundDisabled = true; | ||||
| 	right->soundDisabled = true; | ||||
|  | ||||
| 	if (horizontal) | ||||
| 		right->moveBy(Point(totalw - right->pos.w, 0)); | ||||
| 	else | ||||
| 		right->moveBy(Point(0, totalw - right->pos.h)); | ||||
|  | ||||
| 	left->addCallback(std::bind(&CSlider::moveLeft,this)); | ||||
| 	right->addCallback(std::bind(&CSlider::moveRight,this)); | ||||
| 	slider->addCallback(std::bind(&CSlider::sliderClicked,this)); | ||||
|  | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		pos.h = slider->pos.h; | ||||
| 		pos.w = totalw; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		pos.w = slider->pos.w; | ||||
| 		pos.h = totalw; | ||||
| 	} | ||||
|  | ||||
| 	updateSliderPos(); | ||||
| } | ||||
|  | ||||
| CSlider::~CSlider() = default; | ||||
|  | ||||
| void CSlider::block( bool on ) | ||||
| { | ||||
| 	left->block(on); | ||||
| 	right->block(on); | ||||
| 	slider->block(on); | ||||
| } | ||||
|  | ||||
| void CSlider::setAmount( int to ) | ||||
| { | ||||
| 	amount = to; | ||||
| 	positions = to - capacity; | ||||
| 	vstd::amax(positions, 0); | ||||
| } | ||||
|  | ||||
| void CSlider::showAll(Canvas & to) | ||||
| { | ||||
| 	to.drawColor(pos, Colors::BLACK); | ||||
| 	CIntObject::showAll(to); | ||||
| } | ||||
|  | ||||
| void CSlider::wheelScrolled(int distance) | ||||
| { | ||||
| 	// vertical slider -> scrolling up move slider upwards | ||||
| 	// horizontal slider -> scrolling up moves slider towards right | ||||
| 	bool positive = ((distance < 0) != horizontal); | ||||
|  | ||||
| 	moveTo(value + 3 * (positive ? +scrollStep : -scrollStep)); | ||||
| } | ||||
|  | ||||
| void CSlider::keyPressed(EShortcut key) | ||||
| { | ||||
| 	int moveDest = value; | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case EShortcut::MOVE_UP: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_LEFT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_DOWN: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_RIGHT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_PAGE_UP: | ||||
| 		moveDest = value - capacity + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_PAGE_DOWN: | ||||
| 		moveDest = value + capacity - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_FIRST: | ||||
| 		moveDest = 0; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_LAST: | ||||
| 		moveDest = amount - capacity; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	moveTo(moveDest); | ||||
| } | ||||
|  | ||||
| void CSlider::moveToMin() | ||||
| { | ||||
| 	moveTo(0); | ||||
| } | ||||
|  | ||||
| void CSlider::moveToMax() | ||||
| { | ||||
| 	moveTo(amount); | ||||
| } | ||||
|   | ||||
| @@ -181,94 +181,3 @@ public: | ||||
| 	void setSelectedOnly(int id); | ||||
| 	int getSelected() const; | ||||
| }; | ||||
|  | ||||
| /// A typical slider which can be orientated horizontally/vertically. | ||||
| class CSlider : public CIntObject | ||||
| { | ||||
| 	//if vertical then left=up | ||||
| 	std::shared_ptr<CButton> left; | ||||
| 	std::shared_ptr<CButton> right; | ||||
| 	std::shared_ptr<CButton> slider; | ||||
|  | ||||
| 	std::optional<Rect> scrollBounds; | ||||
|  | ||||
| 	/// how many elements are visible simultaneously | ||||
| 	int capacity; | ||||
| 	/// number of highest position, or 0 if there is only one | ||||
| 	int positions; | ||||
| 	/// if true, then slider is not vertical but horizontal | ||||
| 	bool horizontal; | ||||
| 	/// total amount of elements in the list | ||||
| 	int amount; | ||||
| 	/// topmost vislble (first active) element | ||||
| 	int value; | ||||
| 	/// how many elements will be scrolled via one click, default = 1 | ||||
| 	int scrollStep; | ||||
|  | ||||
| 	/// How far player must move finger/mouse to move slider by 1 via gesture | ||||
| 	int panningDistanceSingle; | ||||
| 	/// How far have player moved finger/mouse via gesture so far. | ||||
| 	int panningDistanceAccumulated; | ||||
|  | ||||
| 	CFunctionList<void(int)> moved; | ||||
|  | ||||
| 	void updateSliderPos(); | ||||
| 	void sliderClicked(); | ||||
|  | ||||
| public: | ||||
| 	enum EStyle | ||||
| 	{ | ||||
| 		BROWN, | ||||
| 		BLUE | ||||
| 	}; | ||||
|  | ||||
| 	void block(bool on); | ||||
|  | ||||
| 	/// Controls how many items wil be scrolled via one click | ||||
| 	void setScrollStep(int to); | ||||
|  | ||||
| 	/// Controls size of panning step needed to move list by 1 item | ||||
| 	void setPanningStep(int to); | ||||
|  | ||||
| 	/// If set, mouse scroll will only scroll slider when inside of this area | ||||
| 	void setScrollBounds(const Rect & bounds ); | ||||
| 	void clearScrollBounds(); | ||||
|  | ||||
| 	/// Value modifiers | ||||
| 	void moveLeft(); | ||||
| 	void moveRight(); | ||||
| 	void moveTo(int value); | ||||
| 	void moveBy(int amount); | ||||
| 	void moveToMin(); | ||||
| 	void moveToMax(); | ||||
|  | ||||
| 	/// Amount modifier | ||||
| 	void setAmount(int to); | ||||
|  | ||||
| 	/// Accessors | ||||
| 	int getAmount() const; | ||||
| 	int getValue() const; | ||||
| 	int getCapacity() const; | ||||
|  | ||||
| 	void addCallback(std::function<void(int)> callback); | ||||
|  | ||||
| 	bool receiveEvent(const Point & position, int eventType) const override; | ||||
|  | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void wheelScrolled(int distance) override; | ||||
| 	void gesturePanning(const Point & distanceDelta) override; | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void mouseMoved (const Point & cursorPosition) override; | ||||
| 	void showAll(Canvas & to) override; | ||||
| 	void panning(bool on) override; | ||||
|  | ||||
| 	 /// @param position coordinates of slider | ||||
| 	 /// @param length length of slider ribbon, including left/right buttons | ||||
| 	 /// @param Moved function that will be called whenever slider moves | ||||
| 	 /// @param Capacity maximal number of visible at once elements | ||||
| 	 /// @param Amount total amount of elements, including not visible | ||||
| 	 /// @param Value starting position | ||||
| 	CSlider(Point position, int length, std::function<void(int)> Moved, int Capacity, int Amount, | ||||
| 		int Value=0, bool Horizontal=true, EStyle style = BROWN); | ||||
| 	~CSlider(); | ||||
| }; | ||||
|   | ||||
| @@ -11,7 +11,7 @@ | ||||
| #include "ObjectLists.h" | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "Buttons.h" | ||||
| #include "Slider.h" | ||||
|  | ||||
| CObjectList::CObjectList(CreateFunc create) | ||||
| 	: createObject(create) | ||||
|   | ||||
							
								
								
									
										12
									
								
								client/widgets/Scrollable.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								client/widgets/Scrollable.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /* | ||||
|  * Scrollable.cpp, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "StdInc.h" | ||||
| #include "Scrollable.h" | ||||
							
								
								
									
										13
									
								
								client/widgets/Scrollable.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								client/widgets/Scrollable.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
|  * Scrollable.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "../gui/CIntObject.h" | ||||
							
								
								
									
										359
									
								
								client/widgets/Slider.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										359
									
								
								client/widgets/Slider.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,359 @@ | ||||
| /* | ||||
|  * Slider.cpp, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #include "StdInc.h" | ||||
| #include "Slider.h" | ||||
|  | ||||
| #include "Buttons.h" | ||||
|  | ||||
| #include "../gui/MouseButton.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../render/Canvas.h" | ||||
|  | ||||
| void CSlider::sliderClicked() | ||||
| { | ||||
| 	addUsedEvents(MOVE); | ||||
| } | ||||
|  | ||||
| void CSlider::mouseMoved (const Point & cursorPosition) | ||||
| { | ||||
| 	double v = 0; | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		if(	std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2+40  ||  std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2  ) | ||||
| 			return; | ||||
| 		v = cursorPosition.x - pos.x - 24; | ||||
| 		v *= positions; | ||||
| 		v /= (pos.w - 48); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if(std::abs(cursorPosition.x-(pos.x+pos.w/2)) > pos.w/2+40  ||  std::abs(cursorPosition.y-(pos.y+pos.h/2)) > pos.h/2  ) | ||||
| 			return; | ||||
| 		v = cursorPosition.y - pos.y - 24; | ||||
| 		v *= positions; | ||||
| 		v /= (pos.h - 48); | ||||
| 	} | ||||
| 	v += 0.5; | ||||
| 	if(v!=value) | ||||
| 	{ | ||||
| 		moveTo(static_cast<int>(v)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CSlider::setScrollStep(int to) | ||||
| { | ||||
| 	scrollStep = to; | ||||
| } | ||||
|  | ||||
| void CSlider::setScrollBounds(const Rect & bounds ) | ||||
| { | ||||
| 	scrollBounds = bounds; | ||||
| } | ||||
|  | ||||
| void CSlider::clearScrollBounds() | ||||
| { | ||||
| 	scrollBounds = std::nullopt; | ||||
| } | ||||
|  | ||||
| int CSlider::getAmount() const | ||||
| { | ||||
| 	return amount; | ||||
| } | ||||
|  | ||||
| int CSlider::getValue() const | ||||
| { | ||||
| 	return value; | ||||
| } | ||||
|  | ||||
| int CSlider::getCapacity() const | ||||
| { | ||||
| 	return capacity; | ||||
| } | ||||
|  | ||||
| void CSlider::moveLeft() | ||||
| { | ||||
| 	moveTo(value-1); | ||||
| } | ||||
|  | ||||
| void CSlider::moveRight() | ||||
| { | ||||
| 	moveTo(value+1); | ||||
| } | ||||
|  | ||||
| void CSlider::moveBy(int amount) | ||||
| { | ||||
| 	moveTo(value + amount); | ||||
| } | ||||
|  | ||||
| void CSlider::updateSliderPos() | ||||
| { | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		if(positions) | ||||
| 		{ | ||||
| 			double part = static_cast<double>(value) / positions; | ||||
| 			part*=(pos.w-48); | ||||
| 			int newPos = static_cast<int>(part + pos.x + 16 - slider->pos.x); | ||||
| 			slider->moveBy(Point(newPos, 0)); | ||||
| 		} | ||||
| 		else | ||||
| 			slider->moveTo(Point(pos.x+16, pos.y)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		if(positions) | ||||
| 		{ | ||||
| 			double part = static_cast<double>(value) / positions; | ||||
| 			part*=(pos.h-48); | ||||
| 			int newPos = static_cast<int>(part + pos.y + 16 - slider->pos.y); | ||||
| 			slider->moveBy(Point(0, newPos)); | ||||
| 		} | ||||
| 		else | ||||
| 			slider->moveTo(Point(pos.x, pos.y+16)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CSlider::moveTo(int to) | ||||
| { | ||||
| 	vstd::amax(to, 0); | ||||
| 	vstd::amin(to, positions); | ||||
|  | ||||
| 	//same, old position? | ||||
| 	if(value == to) | ||||
| 		return; | ||||
| 	value = to; | ||||
|  | ||||
| 	updateSliderPos(); | ||||
|  | ||||
| 	moved(to); | ||||
| } | ||||
|  | ||||
| void CSlider::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down && !slider->isBlocked()) | ||||
| 	{ | ||||
| 		double pw = 0; | ||||
| 		double rw = 0; | ||||
| 		if(horizontal) | ||||
| 		{ | ||||
| 			pw = GH.getCursorPosition().x-pos.x-25; | ||||
| 			rw = pw / static_cast<double>(pos.w - 48); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			pw = GH.getCursorPosition().y-pos.y-24; | ||||
| 			rw = pw / (pos.h-48); | ||||
| 		} | ||||
| 		if(pw < -8  ||  pw > (horizontal ? pos.w : pos.h) - 40) | ||||
| 			return; | ||||
| 		// 		if (rw>1) return; | ||||
| 		// 		if (rw<0) return; | ||||
| 		slider->clickLeft(true, slider->isMouseButtonPressed(MouseButton::LEFT)); | ||||
| 		moveTo((int)(rw * positions  +  0.5)); | ||||
| 		return; | ||||
| 	} | ||||
| 	removeUsedEvents(MOVE); | ||||
| } | ||||
|  | ||||
| bool CSlider::receiveEvent(const Point &position, int eventType) const | ||||
| { | ||||
| 	if (eventType != WHEEL && eventType != GESTURE_PANNING) | ||||
| 	{ | ||||
| 		return CIntObject::receiveEvent(position, eventType); | ||||
| 	} | ||||
|  | ||||
| 	if (!scrollBounds) | ||||
| 		return true; | ||||
|  | ||||
| 	Rect testTarget = *scrollBounds + pos.topLeft(); | ||||
|  | ||||
| 	return testTarget.isInside(position); | ||||
| } | ||||
|  | ||||
| void CSlider::setPanningStep(int to) | ||||
| { | ||||
| 	panningDistanceSingle = to; | ||||
| } | ||||
|  | ||||
| void CSlider::panning(bool on) | ||||
| { | ||||
| 	panningDistanceAccumulated = 0; | ||||
| } | ||||
|  | ||||
| void CSlider::gesturePanning(const Point & distanceDelta) | ||||
| { | ||||
| 	if (horizontal) | ||||
| 		panningDistanceAccumulated += -distanceDelta.x; | ||||
| 	else | ||||
| 		panningDistanceAccumulated += distanceDelta.y; | ||||
|  | ||||
| 	if (-panningDistanceAccumulated > panningDistanceSingle ) | ||||
| 	{ | ||||
| 		int scrollAmount = (-panningDistanceAccumulated) / panningDistanceSingle; | ||||
| 		moveBy(-scrollAmount); | ||||
| 		panningDistanceAccumulated += scrollAmount * panningDistanceSingle; | ||||
| 	} | ||||
|  | ||||
| 	if (panningDistanceAccumulated > panningDistanceSingle ) | ||||
| 	{ | ||||
| 		int scrollAmount = panningDistanceAccumulated / panningDistanceSingle; | ||||
| 		moveBy(scrollAmount); | ||||
| 		panningDistanceAccumulated += -scrollAmount * panningDistanceSingle; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int Capacity, int Amount, int Value, bool Horizontal, CSlider::EStyle style) | ||||
| 	: CIntObject(LCLICK | RCLICK | WHEEL | GESTURE_PANNING ), | ||||
| 	capacity(Capacity), | ||||
| 	horizontal(Horizontal), | ||||
| 	amount(Amount), | ||||
| 	value(Value), | ||||
| 	scrollStep(1), | ||||
| 	moved(Moved), | ||||
| 	panningDistanceAccumulated(0), | ||||
| 	panningDistanceSingle(32) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
| 	setAmount(amount); | ||||
| 	vstd::amax(value, 0); | ||||
| 	vstd::amin(value, positions); | ||||
|  | ||||
| 	pos.x += position.x; | ||||
| 	pos.y += position.y; | ||||
|  | ||||
| 	if(style == BROWN) | ||||
| 	{ | ||||
| 		std::string name = horizontal ? "IGPCRDIV.DEF" : "OVBUTN2.DEF"; | ||||
| 		//NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...) | ||||
|  | ||||
| 		left = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
| 		right = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
| 		slider = std::make_shared<CButton>(Point(), name, CButton::tooltip()); | ||||
|  | ||||
| 		left->setImageOrder(0, 1, 1, 1); | ||||
| 		right->setImageOrder(2, 3, 3, 3); | ||||
| 		slider->setImageOrder(4, 4, 4, 4); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		left = std::make_shared<CButton>(Point(), horizontal ? "SCNRBLF.DEF" : "SCNRBUP.DEF", CButton::tooltip()); | ||||
| 		right = std::make_shared<CButton>(Point(), horizontal ? "SCNRBRT.DEF" : "SCNRBDN.DEF", CButton::tooltip()); | ||||
| 		slider = std::make_shared<CButton>(Point(), "SCNRBSL.DEF", CButton::tooltip()); | ||||
| 	} | ||||
| 	slider->actOnDown = true; | ||||
| 	slider->soundDisabled = true; | ||||
| 	left->soundDisabled = true; | ||||
| 	right->soundDisabled = true; | ||||
|  | ||||
| 	if (horizontal) | ||||
| 		right->moveBy(Point(totalw - right->pos.w, 0)); | ||||
| 	else | ||||
| 		right->moveBy(Point(0, totalw - right->pos.h)); | ||||
|  | ||||
| 	left->addCallback(std::bind(&CSlider::moveLeft,this)); | ||||
| 	right->addCallback(std::bind(&CSlider::moveRight,this)); | ||||
| 	slider->addCallback(std::bind(&CSlider::sliderClicked,this)); | ||||
|  | ||||
| 	if(horizontal) | ||||
| 	{ | ||||
| 		pos.h = slider->pos.h; | ||||
| 		pos.w = totalw; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		pos.w = slider->pos.w; | ||||
| 		pos.h = totalw; | ||||
| 	} | ||||
|  | ||||
| 	updateSliderPos(); | ||||
| } | ||||
|  | ||||
| CSlider::~CSlider() = default; | ||||
|  | ||||
| void CSlider::block( bool on ) | ||||
| { | ||||
| 	left->block(on); | ||||
| 	right->block(on); | ||||
| 	slider->block(on); | ||||
| } | ||||
|  | ||||
| void CSlider::setAmount( int to ) | ||||
| { | ||||
| 	amount = to; | ||||
| 	positions = to - capacity; | ||||
| 	vstd::amax(positions, 0); | ||||
| } | ||||
|  | ||||
| void CSlider::showAll(Canvas & to) | ||||
| { | ||||
| 	to.drawColor(pos, Colors::BLACK); | ||||
| 	CIntObject::showAll(to); | ||||
| } | ||||
|  | ||||
| void CSlider::wheelScrolled(int distance) | ||||
| { | ||||
| 	// vertical slider -> scrolling up move slider upwards | ||||
| 	// horizontal slider -> scrolling up moves slider towards right | ||||
| 	bool positive = ((distance < 0) != horizontal); | ||||
|  | ||||
| 	moveTo(value + 3 * (positive ? +scrollStep : -scrollStep)); | ||||
| } | ||||
|  | ||||
| void CSlider::keyPressed(EShortcut key) | ||||
| { | ||||
| 	int moveDest = value; | ||||
| 	switch(key) | ||||
| 	{ | ||||
| 	case EShortcut::MOVE_UP: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_LEFT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_DOWN: | ||||
| 		if (!horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_RIGHT: | ||||
| 		if (horizontal) | ||||
| 			moveDest = value + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_PAGE_UP: | ||||
| 		moveDest = value - capacity + scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_PAGE_DOWN: | ||||
| 		moveDest = value + capacity - scrollStep; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_FIRST: | ||||
| 		moveDest = 0; | ||||
| 		break; | ||||
| 	case EShortcut::MOVE_LAST: | ||||
| 		moveDest = amount - capacity; | ||||
| 		break; | ||||
| 	default: | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	moveTo(moveDest); | ||||
| } | ||||
|  | ||||
| void CSlider::moveToMin() | ||||
| { | ||||
| 	moveTo(0); | ||||
| } | ||||
|  | ||||
| void CSlider::moveToMax() | ||||
| { | ||||
| 	moveTo(amount); | ||||
| } | ||||
							
								
								
									
										107
									
								
								client/widgets/Slider.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								client/widgets/Slider.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,107 @@ | ||||
| /* | ||||
|  * Slider.h, part of VCMI engine | ||||
|  * | ||||
|  * Authors: listed in file AUTHORS in main folder | ||||
|  * | ||||
|  * License: GNU General Public License v2.0 or later | ||||
|  * Full text of license available in license.txt file, in main folder | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Scrollable.h" | ||||
| #include "../../lib/FunctionList.h" | ||||
|  | ||||
| class CButton; | ||||
|  | ||||
| /// A typical slider which can be orientated horizontally/vertically. | ||||
| class CSlider : public CIntObject | ||||
| { | ||||
| 	//if vertical then left=up | ||||
| 	std::shared_ptr<CButton> left; | ||||
| 	std::shared_ptr<CButton> right; | ||||
| 	std::shared_ptr<CButton> slider; | ||||
|  | ||||
| 	std::optional<Rect> scrollBounds; | ||||
|  | ||||
| 	/// how many elements are visible simultaneously | ||||
| 	int capacity; | ||||
| 	/// number of highest position, or 0 if there is only one | ||||
| 	int positions; | ||||
| 	/// if true, then slider is not vertical but horizontal | ||||
| 	bool horizontal; | ||||
| 	/// total amount of elements in the list | ||||
| 	int amount; | ||||
| 	/// topmost vislble (first active) element | ||||
| 	int value; | ||||
| 	/// how many elements will be scrolled via one click, default = 1 | ||||
| 	int scrollStep; | ||||
|  | ||||
| 	/// How far player must move finger/mouse to move slider by 1 via gesture | ||||
| 	int panningDistanceSingle; | ||||
| 	/// How far have player moved finger/mouse via gesture so far. | ||||
| 	int panningDistanceAccumulated; | ||||
|  | ||||
| 	CFunctionList<void(int)> moved; | ||||
|  | ||||
| 	void updateSliderPos(); | ||||
| 	void sliderClicked(); | ||||
|  | ||||
| public: | ||||
| 	enum EStyle | ||||
| 	{ | ||||
| 		BROWN, | ||||
| 		BLUE | ||||
| 	}; | ||||
|  | ||||
| 	void block(bool on); | ||||
|  | ||||
| 	/// Controls how many items wil be scrolled via one click | ||||
| 	void setScrollStep(int to); | ||||
|  | ||||
| 	/// Controls size of panning step needed to move list by 1 item | ||||
| 	void setPanningStep(int to); | ||||
|  | ||||
| 	/// If set, mouse scroll will only scroll slider when inside of this area | ||||
| 	void setScrollBounds(const Rect & bounds ); | ||||
| 	void clearScrollBounds(); | ||||
|  | ||||
| 	/// Value modifiers | ||||
| 	void moveLeft(); | ||||
| 	void moveRight(); | ||||
| 	void moveTo(int value); | ||||
| 	void moveBy(int amount); | ||||
| 	void moveToMin(); | ||||
| 	void moveToMax(); | ||||
|  | ||||
| 	/// Amount modifier | ||||
| 	void setAmount(int to); | ||||
|  | ||||
| 	/// Accessors | ||||
| 	int getAmount() const; | ||||
| 	int getValue() const; | ||||
| 	int getCapacity() const; | ||||
|  | ||||
| 	void addCallback(std::function<void(int)> callback); | ||||
|  | ||||
| 	bool receiveEvent(const Point & position, int eventType) const override; | ||||
|  | ||||
| 	void keyPressed(EShortcut key) override; | ||||
| 	void wheelScrolled(int distance) override; | ||||
| 	void gesturePanning(const Point & distanceDelta) override; | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void mouseMoved (const Point & cursorPosition) override; | ||||
| 	void showAll(Canvas & to) override; | ||||
| 	void panning(bool on) override; | ||||
|  | ||||
| 	 /// @param position coordinates of slider | ||||
| 	 /// @param length length of slider ribbon, including left/right buttons | ||||
| 	 /// @param Moved function that will be called whenever slider moves | ||||
| 	 /// @param Capacity maximal number of visible at once elements | ||||
| 	 /// @param Amount total amount of elements, including not visible | ||||
| 	 /// @param Value starting position | ||||
| 	CSlider(Point position, int length, std::function<void(int)> Moved, int Capacity, int Amount, | ||||
| 		int Value=0, bool Horizontal=true, EStyle style = BROWN); | ||||
| 	~CSlider(); | ||||
| }; | ||||
| @@ -10,7 +10,7 @@ | ||||
| #include "StdInc.h" | ||||
| #include "TextControls.h" | ||||
|  | ||||
| #include "Buttons.h" | ||||
| #include "Slider.h" | ||||
| #include "Images.h" | ||||
|  | ||||
| #include "../CPlayerInterface.h" | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "../windows/InfoWindows.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../render/CAnimation.h" | ||||
|   | ||||
| @@ -15,9 +15,10 @@ | ||||
|  | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../adventureMap/AdventureMapInterface.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/CComponent.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../adventureMap/AdventureMapInterface.h" | ||||
| #include "../adventureMap/CMinimap.h" | ||||
| #include "../render/Canvas.h" | ||||
| #include "../renderSDL/SDL_Extensions.h" | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../windows/InfoWindows.h" | ||||
|  | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
| #include "../gui/TextAlignment.h" | ||||
| #include "../gui/WindowHandler.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/CreatureCostBox.h" | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,6 @@ | ||||
| #include "../CVideoHandler.h" | ||||
| #include "../CServerHandler.h" | ||||
|  | ||||
| //#include "../adventureMap/CResDataBar.h" | ||||
| #include "../battle/BattleInterfaceClasses.h" | ||||
| #include "../battle/BattleInterface.h" | ||||
|  | ||||
| @@ -35,6 +34,7 @@ | ||||
| #include "../widgets/MiscWidgets.h" | ||||
| #include "../widgets/CreatureCostBox.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../widgets/TextControls.h" | ||||
| #include "../widgets/ObjectLists.h" | ||||
|  | ||||
|   | ||||
| @@ -13,6 +13,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| #include "../widgets/CreatureCostBox.h" | ||||
| #include "../widgets/Slider.h" | ||||
| #include "../gui/CGuiHandler.h" | ||||
| #include "../gui/Shortcut.h" | ||||
| #include "../../CCallback.h" | ||||
|   | ||||
| @@ -16,6 +16,7 @@ | ||||
| #include "../../gui/CGuiHandler.h" | ||||
| #include "../../gui/WindowHandler.h" | ||||
| #include "../../widgets/Buttons.h" | ||||
| #include "../../widgets/Slider.h" | ||||
| #include "../../widgets/TextControls.h" | ||||
| #include "../../widgets/Images.h" | ||||
| #include "CGameInfo.h" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user