1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-13 22:06:58 +02:00

Merge pull request #2222 from IvanSavenko/fix_long_touch_gesture

Improvements for long tap (right-click) handling
This commit is contained in:
Ivan Savenko 2023-06-21 17:19:10 +03:00 committed by GitHub
commit 849ce1124d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
73 changed files with 458 additions and 394 deletions

View File

@ -67,6 +67,11 @@
"vcmi.systemOptions.scalingButton.help" : "{Interface Scaling}\n\nChanges scaling of in-game interface",
"vcmi.systemOptions.scalingMenu.hover" : "Select Interface Scaling",
"vcmi.systemOptions.scalingMenu.help" : "Change in-game interface scaling.",
"vcmi.systemOptions.longTouchButton.hover" : "Long Touch Interval: %d ms", // Translation note: "ms" = "milliseconds"
"vcmi.systemOptions.longTouchButton.help" : "{Long Touch Interval}\n\nWhen using touchscreen, popup windows will appear after touching screen for specified duration, in milliseconds",
"vcmi.systemOptions.longTouchMenu.hover" : "Select Long Touch Interval",
"vcmi.systemOptions.longTouchMenu.help" : "Change duration of long touch interval.",
"vcmi.systemOptions.longTouchMenu.entry" : "%d milliseconds",
"vcmi.systemOptions.framerateButton.hover" : "Show FPS",
"vcmi.systemOptions.framerateButton.help" : "{Show FPS}\n\nToggle the visibility of the Frames Per Second counter in the corner of the game window",

View File

@ -42,10 +42,6 @@
"vcmi.systemOptions.fullscreenBorderless.help" : "{На весь екран (безрамкове вікно)}\n\nЯкщо обрано, VCMI працюватиме у режимі безрамкового вікна на весь екран. У цьому режимі гра завжди використовує ту саму роздільну здатність, що й робочий стіл, ігноруючи вибрану роздільну здатність",
"vcmi.systemOptions.fullscreenExclusive.hover" : "На весь екран (ексклюзивний режим)",
"vcmi.systemOptions.fullscreenExclusive.help" : "{На весь екран (ексклюзивний режим)}\n\nnЯкщо вибрано, VCMI працюватиме у ексклюзивному повноекранному режимі. У цьому режимі гра змінюватиме роздільну здатність монітора на вибрану роздільну здатність",
"vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна",
"vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу",
"vcmi.systemOptions.fullscreenButton.hover" : "Повноекранний режим",
"vcmi.systemOptions.fullscreenButton.help" : "{Повноекранний режим}\n\n Якщо обрано, VCMI буде запускатися в режимі на весь екран, інакше — віконний режим",
"vcmi.systemOptions.resolutionButton.hover" : "Роздільна здатність: %wx%h",
"vcmi.systemOptions.resolutionButton.help" : "{Роздільна здатність}\n\n Зміна розширення екрану в грі. Аби зміни набули чинності необхідно перезавантажити гру.",
"vcmi.systemOptions.resolutionMenu.hover" : "Обрати роздільну здатність",
@ -54,9 +50,16 @@
"vcmi.systemOptions.scalingButton.help" : "{Масштабування інтерфейсу}\n\nЗмінити масштабування ігрового інтерфейсу",
"vcmi.systemOptions.scalingMenu.hover" : "Виберіть масштабування інтерфейсу",
"vcmi.systemOptions.scalingMenu.help" : "Змінити масштабування ігрового інтерфейсу.",
"vcmi.systemOptions.longTouchButton.hover" : "Інтервал довгого дотику: %d мс", // Translation note: "ms" = "milliseconds"
"vcmi.systemOptions.longTouchButton.help" : "{Інтервал довгого дотику}\n\nПри використанні сенсорного екрану спливаючі вікна з'являтимуться після дотику до екрану протягом заданої тривалості, в мілісекундах",
"vcmi.systemOptions.longTouchMenu.hover" : "Виберіть інтервал довгого дотику",
"vcmi.systemOptions.longTouchMenu.help" : "Змінити тривалість інтервалу довгого дотику.",
"vcmi.systemOptions.longTouchMenu.entry" : "%d мілісекунд",
"vcmi.systemOptions.framerateButton.hover" : "Лічильник кадрів",
"vcmi.systemOptions.framerateButton.help" : "{Лічильник кадрів}\n\n Перемикає видимість лічильника кадрів на секунду у кутку ігрового вікна",
"vcmi.adventureOptions.infoBarPick.help" : "{Повідомлення у панелі статусу}\n\nЗа можливості, повідомлення про відвідування об'єктів карти пригод будуть відображені у панелі статусу замість окремого вікна",
"vcmi.adventureOptions.infoBarPick.hover" : "Повідомлення у панелі статусу",
"vcmi.adventureOptions.numericQuantities.hover" : "Числовий показник кількості",
"vcmi.adventureOptions.numericQuantities.help" : "{Числовий показник кількості}\n\n Показує приблизну кількість ворожих істот у числовому форматі А-Б.",
"vcmi.adventureOptions.forceMovementInfo.hover" : "Завжди показувати вартість руху",
@ -89,6 +92,8 @@
"vcmi.battleOptions.animationsSpeed6.help": "Встановити миттєву швидкість анімації",
"vcmi.battleOptions.movementHighlightOnHover.hover": "Підсвічувати зону руху істоти",
"vcmi.battleOptions.movementHighlightOnHover.help": "{Підсвічувати зону руху істоти}\n\nПідсвічувати можливу зону руху істоти при наведенні курсора миші на неї",
"vcmi.battleOptions.rangedFullDamageLimitHighlightOnHover.hover": "Межа повного шкоди пострілом",
"vcmi.battleOptions.rangedFullDamageLimitHighlightOnHover.help": "{Межа повного шкоди пострілом}\n\nПідсвічувати зону у якій створіння може завдавати максимальної шкоди пострілом при наведенні на неї курсору миші.",
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Пропускати вступну музику",
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Пропускати вступну музику}\n\n Пропускати коротку музику, яка грає на початку кожної битви перед початком дії. Також можна пропустити, натиснувши клавішу ESC.",

View File

@ -284,10 +284,9 @@ void CInfoBar::clickLeft(tribool down, bool previousState)
}
}
void CInfoBar::clickRight(tribool down, bool previousState)
void CInfoBar::showPopupWindow()
{
if (down)
CRClickPopup::createAndPush(CGI->generaltexth->allTexts[109]);
CRClickPopup::createAndPush(CGI->generaltexth->allTexts[109]);
}
void CInfoBar::hover(bool on)
@ -299,7 +298,7 @@ void CInfoBar::hover(bool on)
}
CInfoBar::CInfoBar(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER, position.topLeft()),
: CIntObject(LCLICK | SHOW_POPUP | HOVER, position.topLeft()),
timerCounter(0),
state(EMPTY)
{

View File

@ -155,7 +155,7 @@ private:
void tick(uint32_t msPassed) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
void playNewDaySound();

View File

@ -31,7 +31,7 @@
#include "../../lib/mapObjects/CGTownInstance.h"
CList::CListItem::CListItem(CList * Parent)
: CIntObject(LCLICK | RCLICK | HOVER),
: CIntObject(LCLICK | SHOW_POPUP | HOVER),
parent(Parent),
selection()
{
@ -40,10 +40,9 @@ CList::CListItem::CListItem(CList * Parent)
CList::CListItem::~CListItem() = default;
void CList::CListItem::clickRight(tribool down, bool previousState)
void CList::CListItem::showPopupWindow()
{
if (down == true)
showTooltip();
showTooltip();
}
void CList::CListItem::clickLeft(tribool down, bool previousState)

View File

@ -35,7 +35,7 @@ protected:
CListItem(CList * parent);
~CListItem();
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void clickLeft(tribool down, bool previousState) override;
void hover(bool on) override;
void onSelect(bool on);

View File

@ -88,7 +88,7 @@ void CMinimapInstance::showAll(Canvas & to)
}
CMinimap::CMinimap(const Rect & position)
: CIntObject(LCLICK | RCLICK | HOVER | MOVE | GESTURE_PANNING, position.topLeft()),
: CIntObject(LCLICK | SHOW_POPUP | HOVER | MOVE | GESTURE, position.topLeft()),
level(0)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -149,10 +149,9 @@ void CMinimap::clickLeft(tribool down, bool previousState)
moveAdvMapSelection(GH.getCursorPosition());
}
void CMinimap::clickRight(tribool down, bool previousState)
void CMinimap::showPopupWindow()
{
if (down)
CRClickPopup::createAndPush(CGI->generaltexth->zelp[291].second);
CRClickPopup::createAndPush(CGI->generaltexth->zelp[291].second);
}
void CMinimap::hover(bool on)
@ -165,7 +164,7 @@ void CMinimap::hover(bool on)
void CMinimap::mouseMoved(const Point & cursorPosition)
{
if(isMouseButtonPressed(MouseButton::LEFT))
if(isMouseLeftButtonPressed())
moveAdvMapSelection(cursorPosition);
}

View File

@ -45,7 +45,7 @@ class CMinimap : public CIntObject
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover (bool on) override;
void mouseMoved (const Point & cursorPosition) override;

View File

@ -34,8 +34,6 @@ CResDataBar::CResDataBar(const std::string & imageName, const Point & position)
pos.w = background->pos.w;
pos.h = background->pos.h;
addUsedEvents(RCLICK);
}
CResDataBar::CResDataBar(const std::string & defname, int x, int y, int offx, int offy, int resdist, int datedist):

View File

@ -155,7 +155,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
updateAccessibleHexes();
addUsedEvents(LCLICK | RCLICK | MOVE | TIME | GESTURE_PANNING);
addUsedEvents(LCLICK | SHOW_POPUP | MOVE | TIME | GESTURE);
}
void BattleFieldController::activate()
@ -176,7 +176,7 @@ void BattleFieldController::createHeroes()
owner.defendingHero = std::make_shared<BattleHero>(owner, owner.defendingHeroInstance, true);
}
void BattleFieldController::panning(bool on, const Point & initialPosition, const Point & finalPosition)
void BattleFieldController::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
if (!on && pos.isInside(finalPosition))
clickLeft(false, false);
@ -219,16 +219,12 @@ void BattleFieldController::clickLeft(tribool down, bool previousState)
}
}
void BattleFieldController::clickRight(tribool down, bool previousState)
void BattleFieldController::showPopupWindow()
{
if(down)
{
BattleHex selectedHex = getHoveredHex();
BattleHex selectedHex = getHoveredHex();
if (selectedHex != BattleHex::INVALID)
owner.actionsController->onHexRightClicked(selectedHex);
}
if (selectedHex != BattleHex::INVALID)
owner.actionsController->onHexRightClicked(selectedHex);
}
void BattleFieldController::renderBattlefield(Canvas & canvas)
@ -858,7 +854,7 @@ void BattleFieldController::show(Canvas & to)
renderBattlefield(to);
if (isActive() && isPanning() && getHoveredHex() != BattleHex::INVALID)
if (isActive() && isGesturing() && getHoveredHex() != BattleHex::INVALID)
{
auto cursorIndex = CCS->curh->get<Cursor::Combat>();
auto imageIndex = static_cast<size_t>(cursorIndex);

View File

@ -88,11 +88,11 @@ class BattleFieldController : public CIntObject
bool isPixelInHex(Point const & position);
size_t selectBattleCursor(BattleHex myNumber);
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void mouseMoved(const Point & cursorPosition) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void activate() override;
void showAll(Canvas & to) override;

View File

@ -652,14 +652,6 @@ StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
void StackQueue::show(Canvas & to)
{
auto unitIdsToHighlight = owner.stacksController->getHoveredStacksUnitIds();
for(auto & stackBox : stackBoxes)
{
bool isBoundUnitCurrentlyHovered = vstd::contains(unitIdsToHighlight, stackBox->getBoundUnitID());
stackBox->toggleHighlight(isBoundUnitCurrentlyHovered);
}
if (embedded)
showAll(to);
CIntObject::show(to);
@ -692,7 +684,7 @@ std::optional<uint32_t> StackQueue::getHoveredUnitIdIfAny() const
{
for(const auto & stackBox : stackBoxes)
{
if(stackBox->isHovered() || stackBox->isMouseButtonPressed(MouseButton::RIGHT))
if(stackBox->isHovered())
{
return stackBox->getBoundUnitID();
}
@ -702,7 +694,7 @@ std::optional<uint32_t> StackQueue::getHoveredUnitIdIfAny() const
}
StackQueue::StackBox::StackBox(StackQueue * owner):
CIntObject(RCLICK | HOVER), owner(owner)
CIntObject(SHOW_POPUP | HOVER), owner(owner)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
background = std::make_shared<CPicture>(owner->embedded ? "StackQueueSmall" : "StackQueueLarge");
@ -783,15 +775,24 @@ std::optional<uint32_t> StackQueue::StackBox::getBoundUnitID() const
return boundUnitID;
}
void StackQueue::StackBox::toggleHighlight(bool value)
bool StackQueue::StackBox::isBoundUnitHighlighted() const
{
highlighted = value;
auto unitIdsToHighlight = owner->owner.stacksController->getHoveredStacksUnitIds();
return vstd::contains(unitIdsToHighlight, getBoundUnitID());
}
void StackQueue::StackBox::showAll(Canvas & to)
{
CIntObject::showAll(to);
if(isBoundUnitHighlighted())
to.drawBorder(background->pos, Colors::CYAN, 2);
}
void StackQueue::StackBox::show(Canvas & to)
{
if(highlighted)
to.drawBorder(background->pos, Colors::CYAN, 2);
CIntObject::show(to);
if(isBoundUnitHighlighted())
to.drawBorder(background->pos, Colors::CYAN, 2);
}

View File

@ -167,20 +167,21 @@ class StackQueue : public CIntObject
{
StackQueue * owner;
std::optional<uint32_t> boundUnitID;
bool highlighted = false;
public:
std::shared_ptr<CPicture> background;
std::shared_ptr<CAnimImage> icon;
std::shared_ptr<CLabel> amount;
std::shared_ptr<CAnimImage> stateIcon;
void show(Canvas & to) override;
void showAll(Canvas & to) override;
bool isBoundUnitHighlighted() const;
public:
StackBox(StackQueue * owner);
void setUnit(const battle::Unit * unit, size_t turn = 0);
void toggleHighlight(bool value);
std::optional<uint32_t> getBoundUnitID() const;
void show(Canvas & to) override;
};
static const int QUEUE_SIZE = 10;

View File

@ -49,6 +49,7 @@ void InputHandler::handleCurrentEvent(const SDL_Event & current)
return keyboardHandler->handleEventKeyDown(current.key);
case SDL_KEYUP:
return keyboardHandler->handleEventKeyUp(current.key);
#ifndef VCMI_EMULATE_TOUCHSCREEN_WITH_MOUSE
case SDL_MOUSEMOTION:
return mouseHandler->handleEventMouseMotion(current.motion);
case SDL_MOUSEBUTTONDOWN:
@ -57,6 +58,7 @@ void InputHandler::handleCurrentEvent(const SDL_Event & current)
return mouseHandler->handleEventMouseButtonUp(current.button);
case SDL_MOUSEWHEEL:
return mouseHandler->handleEventMouseWheel(current.wheel);
#endif
case SDL_TEXTINPUT:
return textHandler->handleEventTextInput(current.text);
case SDL_TEXTEDITING:

View File

@ -42,10 +42,10 @@ void InputSourceMouse::handleEventMouseButtonDown(const SDL_MouseButtonEvent & b
if(button.clicks > 1)
GH.events().dispatchMouseDoubleClick(position);
else
GH.events().dispatchMouseButtonPressed(MouseButton::LEFT, position);
GH.events().dispatchMouseLeftButtonPressed(position);
break;
case SDL_BUTTON_RIGHT:
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, position);
GH.events().dispatchShowPopup(position);
break;
case SDL_BUTTON_MIDDLE:
middleClickPosition = position;
@ -66,10 +66,10 @@ void InputSourceMouse::handleEventMouseButtonUp(const SDL_MouseButtonEvent & but
switch(button.button)
{
case SDL_BUTTON_LEFT:
GH.events().dispatchMouseButtonReleased(MouseButton::LEFT, position);
GH.events().dispatchMouseLeftButtonReleased(position);
break;
case SDL_BUTTON_RIGHT:
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, position);
GH.events().dispatchClosePopup(position);
break;
case SDL_BUTTON_MIDDLE:
GH.events().dispatchGesturePanningEnded(middleClickPosition, position);

View File

@ -20,6 +20,7 @@
#include "../gui/CGuiHandler.h"
#include "../gui/EventDispatcher.h"
#include "../gui/MouseButton.h"
#include "../gui/WindowHandler.h"
#include <SDL_events.h>
#include <SDL_hints.h>
@ -30,13 +31,18 @@ InputSourceTouch::InputSourceTouch()
{
params.useRelativeMode = settings["general"]["userRelativePointer"].Bool();
params.relativeModeSpeedFactor = settings["general"]["relativePointerSpeedMultiplier"].Float();
params.longTouchTimeMilliseconds = settings["general"]["longTouchTimeMilliseconds"].Float();
if (params.useRelativeMode)
state = TouchState::RELATIVE_MODE;
else
state = TouchState::IDLE;
#ifdef VCMI_EMULATE_TOUCHSCREEN_WITH_MOUSE
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "1");
#else
SDL_SetHint(SDL_HINT_MOUSE_TOUCH_EVENTS, "0");
#endif
SDL_SetHint(SDL_HINT_TOUCH_MOUSE_EVENTS, "0");
}
@ -92,6 +98,9 @@ void InputSourceTouch::handleEventFingerMotion(const SDL_TouchFingerEvent & tfin
void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinger)
{
// FIXME: better place to update potentially changed settings?
params.longTouchTimeMilliseconds = settings["general"]["longTouchTimeMilliseconds"].Float();
lastTapTimeTicks = tfinger.timestamp;
switch(state)
@ -100,8 +109,10 @@ void InputSourceTouch::handleEventFingerDown(const SDL_TouchFingerEvent & tfinge
{
if(tfinger.x > 0.5)
{
MouseButton button = tfinger.y < 0.5 ? MouseButton::RIGHT : MouseButton::LEFT;
GH.events().dispatchMouseButtonPressed(button, GH.getCursorPosition());
if (tfinger.y < 0.5)
GH.events().dispatchShowPopup(GH.getCursorPosition());
else
GH.events().dispatchMouseLeftButtonPressed(GH.getCursorPosition());
}
break;
}
@ -138,8 +149,10 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
{
if(tfinger.x > 0.5)
{
MouseButton button = tfinger.y < 0.5 ? MouseButton::RIGHT : MouseButton::LEFT;
GH.events().dispatchMouseButtonReleased(button, GH.getCursorPosition());
if (tfinger.y < 0.5)
GH.events().dispatchClosePopup(GH.getCursorPosition());
else
GH.events().dispatchMouseLeftButtonReleased(GH.getCursorPosition());
}
break;
}
@ -151,8 +164,8 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
case TouchState::TAP_DOWN_SHORT:
{
GH.input().setCursorPosition(convertTouchToMouse(tfinger));
GH.events().dispatchMouseButtonPressed(MouseButton::LEFT, convertTouchToMouse(tfinger));
GH.events().dispatchMouseButtonReleased(MouseButton::LEFT, convertTouchToMouse(tfinger));
GH.events().dispatchMouseLeftButtonPressed(convertTouchToMouse(tfinger));
GH.events().dispatchMouseLeftButtonReleased(convertTouchToMouse(tfinger));
state = TouchState::IDLE;
break;
}
@ -186,7 +199,7 @@ void InputSourceTouch::handleEventFingerUp(const SDL_TouchFingerEvent & tfinger)
if (SDL_GetNumTouchFingers(tfinger.touchId) == 0)
{
GH.input().setCursorPosition(convertTouchToMouse(tfinger));
GH.events().dispatchMouseButtonReleased(MouseButton::RIGHT, convertTouchToMouse(tfinger));
GH.events().dispatchClosePopup(convertTouchToMouse(tfinger));
state = TouchState::IDLE;
}
break;
@ -199,10 +212,12 @@ void InputSourceTouch::handleUpdate()
if ( state == TouchState::TAP_DOWN_SHORT)
{
uint32_t currentTime = SDL_GetTicks();
if (currentTime > lastTapTimeTicks + params.longPressTimeMilliseconds)
if (currentTime > lastTapTimeTicks + params.longTouchTimeMilliseconds)
{
state = TouchState::TAP_DOWN_LONG;
GH.events().dispatchMouseButtonPressed(MouseButton::RIGHT, GH.getCursorPosition());
GH.events().dispatchShowPopup(GH.getCursorPosition());
if (GH.windows().isTopWindowPopup())
state = TouchState::TAP_DOWN_LONG;
}
}
}

View File

@ -12,6 +12,9 @@
#include "../../lib/Point.h"
// Debug option. If defined, mouse events will instead generate touch events, allowing testing of touch input on desktop
// #define VCMI_EMULATE_TOUCHSCREEN_WITH_MOUSE
enum class MouseButton;
struct SDL_TouchFingerEvent;
@ -33,7 +36,7 @@ enum class TouchState
// DOWN -> transition to TAP_DOWN_DOUBLE
// MOTION -> transition to TAP_DOWN_PANNING
// UP -> transition to IDLE, emit onLeftClickDown and onLeftClickUp
// on timer -> transition to TAP_DOWN_LONG, emit onRightClickDown event
// on timer -> transition to TAP_DOWN_LONG, emit showPopup() event
TAP_DOWN_SHORT,
// single finger is moving across screen
@ -57,17 +60,8 @@ enum class TouchState
// right-click popup is active, waiting for new tap to hide popup
// DOWN -> ignored
// MOTION -> ignored
// UP -> transition to IDLE, generate onRightClickUp() event
// UP -> transition to IDLE, generate closePopup() event
TAP_DOWN_LONG_AWAIT,
// Possible transitions:
// -> DOUBLE
// -> PANNING -> IDLE
// IDLE -> DOWN_SHORT -> IDLE
// -> LONG -> IDLE
// -> DOUBLE -> PANNING
// -> IDLE
};
struct TouchInputParameters
@ -76,7 +70,7 @@ struct TouchInputParameters
double relativeModeSpeedFactor = 1.0;
/// tap for period longer than specified here will be qualified as "long tap", triggering corresponding gesture
uint32_t longPressTimeMilliseconds = 750;
uint32_t longTouchTimeMilliseconds = 750;
/// moving finger for distance larger than specified will be qualified as panning gesture instead of long press
uint32_t panningSensitivityThreshold = 10;

View File

@ -90,7 +90,7 @@ void CIntObject::deactivate()
if (!isActive())
return;
deactivateEvents(ALL);
deactivateEvents(used | GENERAL);
assert(!isActive());
@ -239,6 +239,11 @@ void CIntObject::onScreenResize()
center(pos, true);
}
bool CIntObject::isPopupWindow() const
{
return false;
}
const Rect & CIntObject::center( const Rect &r, bool propagate )
{
pos.w = r.w;

View File

@ -34,6 +34,7 @@ public:
virtual void show(Canvas & to) = 0;
virtual void showAll(Canvas & to) = 0;
virtual bool isPopupWindow() const = 0;
virtual void onScreenResize() = 0;
virtual ~IShowActivatable() = default;
};
@ -93,10 +94,16 @@ public:
//request complete redraw of this object
void redraw() override;
/// returns true if this element is a popup window
/// called only for windows
bool isPopupWindow() const override;
/// called only for windows whenever screen size changes
/// default behavior is to re-center, can be overriden
void onScreenResize() override;
/// returns true if UI elements wants to handle event of specific type (LCLICK, SHOW_POPUP ...)
/// by default, usedEvents inside UI elements are always handled
bool receiveEvent(const Point & position, int eventType) const override;
const Rect & center(const Rect &r, bool propagate = true); //sets pos so that r will be in the center of screen, assigns sizes of r to pos, returns new position

View File

@ -14,6 +14,7 @@
#include "FramerateManager.h"
#include "CGuiHandler.h"
#include "MouseButton.h"
#include "WindowHandler.h"
#include "../../lib/Point.h"
@ -27,7 +28,7 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb)
};
processList(AEventsReceiver::LCLICK, lclickable);
processList(AEventsReceiver::RCLICK, rclickable);
processList(AEventsReceiver::SHOW_POPUP, rclickable);
processList(AEventsReceiver::HOVER, hoverable);
processList(AEventsReceiver::MOVE, motioninterested);
processList(AEventsReceiver::KEYBOARD, keyinterested);
@ -35,7 +36,7 @@ void EventDispatcher::processLists(ui16 activityFlag, const Functor & cb)
processList(AEventsReceiver::WHEEL, wheelInterested);
processList(AEventsReceiver::DOUBLECLICK, doubleClickInterested);
processList(AEventsReceiver::TEXTINPUT, textInterested);
processList(AEventsReceiver::GESTURE_PANNING, panningInterested);
processList(AEventsReceiver::GESTURE, panningInterested);
}
void EventDispatcher::activateElement(AEventsReceiver * elem, ui16 activityFlag)
@ -112,18 +113,6 @@ void EventDispatcher::dispatchShortcutReleased(const std::vector<EShortcut> & sh
}
}
EventDispatcher::EventReceiversList & EventDispatcher::getListForMouseButton(MouseButton button)
{
switch (button)
{
case MouseButton::LEFT:
return lclickable;
case MouseButton::RIGHT:
return rclickable;
}
throw std::runtime_error("Invalid mouse button in getListForMouseButton");
}
void EventDispatcher::dispatchMouseDoubleClick(const Point & position)
{
bool doubleClicked = false;
@ -142,50 +131,64 @@ void EventDispatcher::dispatchMouseDoubleClick(const Point & position)
}
if(!doubleClicked)
dispatchMouseButtonPressed(MouseButton::LEFT, position);
handleLeftButtonClick(true);
}
void EventDispatcher::dispatchMouseButtonPressed(const MouseButton & button, const Point & position)
void EventDispatcher::dispatchMouseLeftButtonPressed(const Point & position)
{
handleMouseButtonClick(getListForMouseButton(button), button, true);
handleLeftButtonClick(true);
}
void EventDispatcher::dispatchMouseButtonReleased(const MouseButton & button, const Point & position)
void EventDispatcher::dispatchMouseLeftButtonReleased(const Point & position)
{
handleMouseButtonClick(getListForMouseButton(button), button, false);
handleLeftButtonClick(false);
}
void EventDispatcher::handleMouseButtonClick(EventReceiversList & interestedObjs, MouseButton btn, bool isPressed)
void EventDispatcher::dispatchShowPopup(const Point & position)
{
auto hlp = interestedObjs;
auto hlp = rclickable;
for(auto & i : hlp)
{
if(!vstd::contains(interestedObjs, i))
if(!vstd::contains(rclickable, i))
continue;
auto prev = i->isMouseButtonPressed(btn);
if( !i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::LCLICK))
continue;
i->showPopupWindow();
}
}
void EventDispatcher::dispatchClosePopup(const Point & position)
{
if (GH.windows().isTopWindowPopup())
GH.windows().popWindows(1);
assert(!GH.windows().isTopWindowPopup());
}
void EventDispatcher::handleLeftButtonClick(bool isPressed)
{
auto hlp = lclickable;
for(auto & i : hlp)
{
if(!vstd::contains(lclickable, i))
continue;
auto prev = i->isMouseLeftButtonPressed();
if(!isPressed)
i->currentMouseState[btn] = isPressed;
i->mouseClickedState = isPressed;
if( btn == MouseButton::LEFT && i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::LCLICK))
if( i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::LCLICK))
{
if(isPressed)
i->currentMouseState[btn] = isPressed;
i->mouseClickedState = isPressed;
i->clickLeft(isPressed, prev);
}
else if( btn == MouseButton::RIGHT && i->receiveEvent(GH.getCursorPosition(), AEventsReceiver::RCLICK))
{
if(isPressed)
i->currentMouseState[btn] = isPressed;
i->clickRight(isPressed, prev);
}
else if(!isPressed)
{
if (btn == MouseButton::LEFT)
i->clickLeft(boost::logic::indeterminate, prev);
if (btn == MouseButton::RIGHT)
i->clickRight(boost::logic::indeterminate, prev);
i->clickLeft(boost::logic::indeterminate, prev);
}
}
}
@ -225,9 +228,9 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
for(auto it : copied)
{
if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE_PANNING))
if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE))
{
it->panning(true, initialPosition, initialPosition);
it->gesture(true, initialPosition, initialPosition);
it->panningState = true;
}
}
@ -239,9 +242,9 @@ void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition,
for(auto it : copied)
{
if (it->isPanning())
if (it->isGesturing())
{
it->panning(false, initialPosition, finalPosition);
it->gesture(false, initialPosition, finalPosition);
it->panningState = false;
}
}
@ -253,7 +256,7 @@ void EventDispatcher::dispatchGesturePanning(const Point & initialPosition, cons
for(auto it : copied)
{
if (it->isPanning())
if (it->isGesturing())
it->gesturePanning(initialPosition, currentPosition, lastUpdateDistance);
}
}
@ -262,7 +265,7 @@ void EventDispatcher::dispatchGesturePinch(const Point & initialPosition, double
{
for(auto it : panningInterested)
{
if (it->isPanning())
if (it->isGesturing())
it->gesturePinch(initialPosition, distance);
}
}

View File

@ -34,9 +34,8 @@ class EventDispatcher
EventReceiversList textInterested;
EventReceiversList panningInterested;
EventReceiversList & getListForMouseButton(MouseButton button);
void handleLeftButtonClick(bool isPressed);
void handleMouseButtonClick(EventReceiversList & interestedObjs, MouseButton btn, bool isPressed);
template<typename Functor>
void processLists(ui16 activityFlag, const Functor & cb);
@ -56,12 +55,15 @@ public:
void dispatchShortcutReleased(const std::vector<EShortcut> & shortcuts);
/// Mouse events
void dispatchMouseButtonPressed(const MouseButton & button, const Point & position);
void dispatchMouseButtonReleased(const MouseButton & button, const Point & position);
void dispatchMouseLeftButtonPressed(const Point & position);
void dispatchMouseLeftButtonReleased(const Point & position);
void dispatchMouseScrolled(const Point & distance, const Point & position);
void dispatchMouseDoubleClick(const Point & position);
void dispatchMouseMoved(const Point & distance);
void dispatchShowPopup(const Point & position);
void dispatchClosePopup(const Point & position);
void dispatchGesturePanningStarted(const Point & initialPosition);
void dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition);
void dispatchGesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance);

View File

@ -18,6 +18,7 @@ AEventsReceiver::AEventsReceiver()
: activeState(0)
, hoveredState(false)
, panningState(false)
, mouseClickedState(false)
{
}
@ -26,7 +27,7 @@ bool AEventsReceiver::isHovered() const
return hoveredState;
}
bool AEventsReceiver::isPanning() const
bool AEventsReceiver::isGesturing() const
{
return panningState;
}
@ -36,9 +37,9 @@ bool AEventsReceiver::isActive() const
return activeState;
}
bool AEventsReceiver::isMouseButtonPressed(MouseButton btn) const
bool AEventsReceiver::isMouseLeftButtonPressed() const
{
return currentMouseState.count(btn) ? currentMouseState.at(btn) : false;
return mouseClickedState;
}
void AEventsReceiver::activateEvents(ui16 what)
@ -52,6 +53,13 @@ void AEventsReceiver::activateEvents(ui16 what)
void AEventsReceiver::deactivateEvents(ui16 what)
{
if (what & GENERAL)
{
assert((what & activeState) == activeState);
activeState &= ~GENERAL;
// sanity check to avoid unexpected behavior if assertion above fails (e.g. in release)
// if element is deactivated (has GENERAL flag) then all existing active events should also be deactivated
what = activeState;
}
GH.events().deactivateElement(this, what & activeState);
}

View File

@ -14,7 +14,6 @@ class Point;
VCMI_LIB_NAMESPACE_END
class EventDispatcher;
enum class MouseButton;
enum class EShortcut;
using boost::logic::tribool;
@ -24,10 +23,10 @@ class AEventsReceiver
{
friend class EventDispatcher;
std::map<MouseButton, bool> currentMouseState;
ui16 activeState;
bool hoveredState;
bool panningState;
bool mouseClickedState;
protected:
/// Activates particular events for this UI element. Uses unnamed enum from this class
@ -36,12 +35,13 @@ protected:
void deactivateEvents(ui16 what);
virtual void clickLeft(tribool down, bool previousState) {}
virtual void clickRight(tribool down, bool previousState) {}
virtual void showPopupWindow() {}
virtual void clickDouble() {}
/// Called when user pans screen by specified distance
virtual void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) {}
/// Called when user pitches screen, requesting scaling by specified factor
virtual void gesturePinch(const Point & centerPosition, double lastUpdateFactor) {}
virtual void wheelScrolled(int distance) {}
@ -50,8 +50,8 @@ protected:
/// Called when UI element hover status changes
virtual void hover(bool on) {}
/// Called when UI element panning gesture status changes
virtual void panning(bool on, const Point & initialPosition, const Point & finalPosition) {}
/// Called when UI element gesture status changes
virtual void gesture(bool on, const Point & initialPosition, const Point & finalPosition) {}
virtual void textInputed(const std::string & enteredText) {}
virtual void textEdited(const std::string & enteredText) {}
@ -71,17 +71,30 @@ public:
virtual ~AEventsReceiver() = default;
/// These are the arguments that can be used to determine what kind of input UI element will receive
enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, GESTURE_PANNING=1024, ALL=0xffff};
enum
{
LCLICK = 1,
SHOW_POPUP = 2,
HOVER = 4,
MOVE = 8,
KEYBOARD = 16,
TIME = 32,
GENERAL = 64,
WHEEL = 128,
DOUBLECLICK = 256,
TEXTINPUT = 512,
GESTURE = 1024,
};
/// Returns true if element is currently hovered by mouse
bool isHovered() const;
/// Returns true if panning/swiping gesture is currently active
bool isPanning() const;
bool isGesturing() const;
/// Returns true if element is currently active and may receive events
bool isActive() const;
/// Returns true if particular mouse button was pressed when inside this element
bool isMouseButtonPressed(MouseButton btn) const;
/// Returns true if left mouse button was pressed when inside this element
bool isMouseLeftButtonPressed() const;
};

View File

@ -48,6 +48,14 @@ void WindowHandler::pushWindow(std::shared_ptr<IShowActivatable> newInt)
totalRedraw();
}
bool WindowHandler::isTopWindowPopup() const
{
if (windowsStack.empty())
return false;
return windowsStack.back()->isPopupWindow();
}
void WindowHandler::popWindows(int howMany)
{
if(!howMany)

View File

@ -43,6 +43,9 @@ public:
/// pops one or more windows - deactivates top, deletes and removes given number of windows, activates new front
void popWindows(int howMany);
/// returns true if current top window is a right-click popup
bool isTopWindowPopup() const;
/// removes given windows from the top and activates next
void popWindow(std::shared_ptr<IShowActivatable> top);

View File

@ -447,7 +447,7 @@ void CBonusSelection::decreaseDifficulty()
}
CBonusSelection::CRegion::CRegion(int id, bool accessible, bool selectable, const CampaignRegions & campDsc)
: CIntObject(LCLICK | RCLICK), idOfMapAndRegion(id), accessible(accessible), selectable(selectable)
: CIntObject(LCLICK | SHOW_POPUP), idOfMapAndRegion(id), accessible(accessible), selectable(selectable)
{
OBJ_CONSTRUCTION;
static const std::string colors[2][8] =
@ -507,7 +507,7 @@ void CBonusSelection::CRegion::clickLeft(tribool down, bool previousState)
}
}
void CBonusSelection::CRegion::clickRight(tribool down, bool previousState)
void CBonusSelection::CRegion::showPopupWindow()
{
// FIXME: For some reason "down" is only ever contain indeterminate_value
auto text = CSH->si->campState->camp->scenarios[idOfMapAndRegion].regionText;

View File

@ -46,7 +46,7 @@ public:
CRegion(int id, bool accessible, bool selectable, const CampaignRegions & campDsc);
void updateState();
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
};
void createBonusesIcons();

View File

@ -341,7 +341,7 @@ void CChatBox::addNewMessage(const std::string & text)
}
CFlagBox::CFlagBox(const Rect & rect)
: CIntObject(RCLICK)
: CIntObject(SHOW_POPUP)
{
pos += rect.topLeft();
pos.w = rect.w;
@ -378,9 +378,9 @@ void CFlagBox::recreate()
}
}
void CFlagBox::clickRight(tribool down, bool previousState)
void CFlagBox::showPopupWindow()
{
if(down && SEL->getMapInfo())
if(SEL->getMapInfo())
GH.windows().createAndPushWindow<CFlagBoxTooltipBox>(iconsTeamFlags);
}

View File

@ -135,7 +135,7 @@ class CFlagBox : public CIntObject
public:
CFlagBox(const Rect & rect);
void recreate();
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void showTeamsPopup();
class CFlagBoxTooltipBox : public CWindowObject

View File

@ -413,7 +413,7 @@ void OptionsTab::CPlayerOptionTooltipBox::genBonusWindow()
}
OptionsTab::SelectedBox::SelectedBox(Point position, PlayerSettings & settings, SelType type)
: Scrollable(RCLICK, position, Orientation::HORIZONTAL)
: Scrollable(SHOW_POPUP, position, Orientation::HORIZONTAL)
, CPlayerSettingsHelper(settings, type)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
@ -432,18 +432,15 @@ void OptionsTab::SelectedBox::update()
subtitle->setText(getName());
}
void OptionsTab::SelectedBox::clickRight(tribool down, bool previousState)
void OptionsTab::SelectedBox::showPopupWindow()
{
if(down)
{
// cases when we do not need to display a message
if(settings.castle == -2 && CPlayerSettingsHelper::type == TOWN)
return;
if(settings.hero == -2 && !SEL->getPlayerInfo(settings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO)
return;
// cases when we do not need to display a message
if(settings.castle == -2 && CPlayerSettingsHelper::type == TOWN)
return;
if(settings.hero == -2 && !SEL->getPlayerInfo(settings.color.getNum()).hasCustomMainHero() && CPlayerSettingsHelper::type == HERO)
return;
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(*this);
}
GH.windows().createAndPushWindow<CPlayerOptionTooltipBox>(*this);
}
void OptionsTab::SelectedBox::scrollBy(int distance)

View File

@ -101,7 +101,7 @@ public:
std::shared_ptr<CLabel> subtitle;
SelectedBox(Point position, PlayerSettings & settings, SelType type);
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void scrollBy(int distance) override;
void update();

View File

@ -474,7 +474,7 @@ void TemplatesDropBox::clickLeft(tribool down, bool previousState)
auto w = widget<CSlider>("slider");
// pop the interface only if the mouse is not clicking on the slider
if (!w || !w->isMouseButtonPressed(MouseButton::LEFT))
if (!w || !w->isMouseLeftButtonPressed())
{
assert(GH.windows().isTopWindow(this));
GH.windows().popWindows(1);

View File

@ -20,7 +20,7 @@
#include "../../lib/filesystem/Filesystem.h"
CreditsScreen::CreditsScreen(Rect rect)
: CIntObject(LCLICK | RCLICK), positionCounter(0)
: CIntObject(LCLICK), positionCounter(0)
{
pos.w = rect.w;
pos.h = rect.h;
@ -43,15 +43,10 @@ void CreditsScreen::show(Canvas & to)
//end of credits, close this screen
if(credits->textSize.y + 600 < positionCounter / 2)
clickRight(false, false);
clickLeft(false, false);
}
void CreditsScreen::clickLeft(tribool down, bool previousState)
{
clickRight(down, previousState);
}
void CreditsScreen::clickRight(tribool down, bool previousState)
{
CTabbedInt * menu = dynamic_cast<CTabbedInt *>(parent);
assert(menu);

View File

@ -22,5 +22,4 @@ public:
CreditsScreen(Rect rect);
void show(Canvas & to) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
};

View File

@ -33,7 +33,7 @@ MapViewActions::MapViewActions(MapView & owner, const std::shared_ptr<MapViewMod
pos.w = model->getPixelsVisibleDimensions().x;
pos.h = model->getPixelsVisibleDimensions().y;
addUsedEvents(LCLICK | RCLICK | GESTURE_PANNING | HOVER | MOVE | WHEEL);
addUsedEvents(LCLICK | SHOW_POPUP | GESTURE | HOVER | MOVE | WHEEL);
}
void MapViewActions::setContext(const std::shared_ptr<IMapRendererContext> & context)
@ -55,11 +55,11 @@ void MapViewActions::clickLeft(tribool down, bool previousState)
adventureInt->onTileLeftClicked(tile);
}
void MapViewActions::clickRight(tribool down, bool previousState)
void MapViewActions::showPopupWindow()
{
int3 tile = model->getTileAtPoint(GH.getCursorPosition() - pos.topLeft());
if(down && context->isInMap(tile))
if(context->isInMap(tile))
adventureInt->onTileRightClicked(tile);
}
@ -91,7 +91,7 @@ void MapViewActions::gesturePinch(const Point & centerPosition, double lastUpdat
pinchZoomFactor = newZoom;
}
void MapViewActions::panning(bool on, const Point & initialPosition, const Point & finalPosition)
void MapViewActions::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
pinchZoomFactor = 1.0;
}

View File

@ -32,11 +32,11 @@ public:
void setContext(const std::shared_ptr<IMapRendererContext> & context);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void gesturePinch(const Point & centerPosition, double lastUpdateFactor) override;
void hover(bool on) override;
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void mouseMoved(const Point & cursorPosition) override;
void wheelScrolled(int distance) override;
};

View File

@ -199,9 +199,9 @@ void CButton::clickLeft(tribool down, bool previousState)
}
}
void CButton::clickRight(tribool down, bool previousState)
void CButton::showPopupWindow()
{
if(down && helpBox.size()) //there is no point to show window with nothing inside...
if(helpBox.size()) //there is no point to show window with nothing inside...
CRClickPopup::createAndPush(helpBox);
}
@ -236,7 +236,7 @@ CButton::CButton(Point position, const std::string &defName, const std::pair<std
callback(Callback)
{
defActions = 255-DISPOSE;
addUsedEvents(LCLICK | RCLICK | HOVER | KEYBOARD);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER | KEYBOARD);
stateToIndex[0] = 0;
stateToIndex[1] = 1;

View File

@ -102,7 +102,7 @@ public:
void setPlayerColor(PlayerColor player);
/// CIntObject overrides
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void clickLeft(tribool down, bool previousState) override;
void hover (bool on) override;
void showAll(Canvas & to) override;

View File

@ -72,11 +72,6 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
LRClickableAreaWTextComp::clickLeft(down, previousState);
}
void CArtPlace::clickRight(tribool down, bool previousState)
{
LRClickableAreaWTextComp::clickRight(down, previousState);
}
const CArtifactInstance * CArtPlace::getArt()
{
return ourArt;
@ -132,10 +127,10 @@ void CCommanderArtPlace::clickLeft(tribool down, bool previousState)
LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.commanderWindow.artifactMessage"), [this]() { returnArtToHeroCallback(); }, []() {});
}
void CCommanderArtPlace::clickRight(tribool down, bool previousState)
void CCommanderArtPlace::showPopupWindow()
{
if(ourArt && text.size() && down)
CArtPlace::clickRight(down, previousState);
if(ourArt && text.size())
CArtPlace::showPopupWindow();
}
void CCommanderArtPlace::setArtifact(const CArtifactInstance * art)
@ -197,13 +192,10 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState)
leftClickCallback(*this);
}
void CHeroArtPlace::clickRight(tribool down, bool previousState)
void CHeroArtPlace::showPopupWindow()
{
if(down)
{
if(rightClickCallback)
rightClickCallback(*this);
}
if(rightClickCallback)
rightClickCallback(*this);
}
void CHeroArtPlace::showAll(Canvas & to)

View File

@ -42,7 +42,6 @@ protected:
public:
CArtPlace(Point position, const CArtifactInstance * Art = nullptr);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
const CArtifactInstance * getArt();
virtual void setArtifact(const CArtifactInstance * art)=0;
@ -60,7 +59,7 @@ protected:
public:
CCommanderArtPlace(Point position, const CGHeroInstance * commanderOwner, ArtifactPosition artSlot, const CArtifactInstance * Art = nullptr);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void setArtifact(const CArtifactInstance * art) override;
};
@ -79,7 +78,7 @@ public:
void selectSlot(bool on);
bool isMarked() const;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void showAll(Canvas & to) override;
void setArtifact(const CArtifactInstance * art) override;
void addCombinedArtInfo(std::map<const CArtifact*, int> & arts);

View File

@ -54,7 +54,7 @@ void CComponent::init(Etype Type, int Subtype, int Val, ESize imageSize, EFonts
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
addUsedEvents(RCLICK);
addUsedEvents(SHOW_POPUP);
compType = Type;
subtype = Subtype;
@ -258,9 +258,9 @@ void CComponent::setSurface(std::string defName, int imgPos)
image = std::make_shared<CAnimImage>(defName, imgPos);
}
void CComponent::clickRight(tribool down, bool previousState)
void CComponent::showPopupWindow()
{
if(down && !getDescription().empty())
if(!getDescription().empty())
CRClickPopup::createAndPush(getDescription());
}

View File

@ -65,7 +65,7 @@ public:
CComponent(Etype Type, int Subtype, int Val = 0, ESize imageSize=large, EFonts font = FONT_SMALL);
CComponent(const Component &c, ESize imageSize=large, EFonts font = FONT_SMALL);
void clickRight(tribool down, bool previousState) override; //call-in
void showPopupWindow() override; //call-in
};
/// component that can be selected or deselected

View File

@ -286,9 +286,9 @@ bool CGarrisonSlot::mustForceReselection() const
return false;
}
void CGarrisonSlot::clickRight(tribool down, bool previousState)
void CGarrisonSlot::showPopupWindow()
{
if(creature && down)
if(creature)
{
GH.windows().createAndPushWindow<CStackWindow>(myStack, true);
}
@ -357,13 +357,13 @@ void CGarrisonSlot::update()
{
if(getObj() != nullptr)
{
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
myStack = getObj()->getStackPtr(ID);
creature = myStack ? myStack->type : nullptr;
}
else
{
removeUsedEvents(LCLICK | RCLICK | HOVER);
removeUsedEvents(LCLICK | SHOW_POPUP | HOVER);
myStack = nullptr;
creature = nullptr;
}

View File

@ -58,7 +58,7 @@ public:
bool our() const;
SlotID getSlot() const { return ID; }
bool ally() const;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void clickLeft(tribool down, bool previousState) override;
void update();
CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * creature_ = nullptr);

View File

@ -200,7 +200,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns
return;
}
if(artPlace.text.size())
artPlace.LRClickableAreaWTextComp::clickRight(boost::logic::tribool::true_value, false);
artPlace.LRClickableAreaWTextComp::showPopupWindow();
}
}
// Altar window, Market window right click handler
@ -209,7 +209,7 @@ void CWindowWithArtifacts::rightClickArtPlaceHero(CArtifactsOfHeroBase & artsIns
std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMarket>>)
{
if(artPlace.getArt() && artPlace.text.size())
artPlace.LRClickableAreaWTextComp::clickRight(boost::logic::tribool::true_value, false);
artPlace.LRClickableAreaWTextComp::showPopupWindow();
}
}, artSetWeak.value());
}

View File

@ -57,9 +57,9 @@ void LRClickableAreaWText::clickLeft(tribool down, bool previousState)
LOCPLINT->showInfoDialog(text);
}
}
void LRClickableAreaWText::clickRight(tribool down, bool previousState)
void LRClickableAreaWText::showPopupWindow()
{
if (down && !text.empty())
if (!text.empty())
CRClickPopup::createAndPush(text);
}
@ -82,7 +82,7 @@ LRClickableAreaWText::~LRClickableAreaWText()
void LRClickableAreaWText::init()
{
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
}
void LRClickableAreaWTextComp::clickLeft(tribool down, bool previousState)
@ -108,22 +108,19 @@ std::shared_ptr<CComponent> LRClickableAreaWTextComp::createComponent() const
return std::shared_ptr<CComponent>();
}
void LRClickableAreaWTextComp::clickRight(tribool down, bool previousState)
void LRClickableAreaWTextComp::showPopupWindow()
{
if(down)
if(auto comp = createComponent())
{
if(auto comp = createComponent())
{
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
return;
}
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
return;
}
LRClickableAreaWText::clickRight(down, previousState); //only if with-component variant not occurred
LRClickableAreaWText::showPopupWindow(); //only if with-component variant not occurred
}
CHeroArea::CHeroArea(int x, int y, const CGHeroInstance * _hero)
: CIntObject(LCLICK | RCLICK | HOVER),
: CIntObject(LCLICK | HOVER),
hero(_hero)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -143,12 +140,6 @@ void CHeroArea::clickLeft(tribool down, bool previousState)
LOCPLINT->openHeroWindow(hero);
}
void CHeroArea::clickRight(tribool down, bool previousState)
{
if(hero && (!down) && previousState)
LOCPLINT->openHeroWindow(hero);
}
void CHeroArea::hover(bool on)
{
if (on && hero)
@ -169,12 +160,6 @@ void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)
}
}
void LRClickableAreaOpenTown::clickRight(tribool down, bool previousState)
{
if(town && (!down) && previousState)
LOCPLINT->openTownWindow(town);//TODO: popup?
}
LRClickableAreaOpenTown::LRClickableAreaOpenTown(const Rect & Pos, const CGTownInstance * Town)
: LRClickableAreaWTextComp(Pos, -1), town(Town)
{

View File

@ -49,7 +49,7 @@ public:
void init();
virtual void clickLeft(tribool down, bool previousState) override;
virtual void clickRight(tribool down, bool previousState) override;
virtual void showPopupWindow() override;
};
/// base class for hero/town/garrison tooltips
@ -136,7 +136,6 @@ public:
CHeroArea(int x, int y, const CGHeroInstance * _hero);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void hover(bool on) override;
};
@ -147,7 +146,7 @@ public:
int baseType;
int bonusValue;
virtual void clickLeft(tribool down, bool previousState) override;
virtual void clickRight(tribool down, bool previousState) override;
virtual void showPopupWindow() override;
LRClickableAreaWTextComp(const Rect &Pos = Rect(0,0,0,0), int BaseType = -1);
std::shared_ptr<CComponent> createComponent() const;
@ -159,7 +158,6 @@ class LRClickableAreaOpenTown: public LRClickableAreaWTextComp
public:
const CGTownInstance * town;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
LRClickableAreaOpenTown(const Rect & Pos, const CGTownInstance * Town);
};

View File

@ -12,7 +12,7 @@
#include "Scrollable.h"
Scrollable::Scrollable(int used, Point position, Orientation orientation)
: CIntObject(used | WHEEL | GESTURE_PANNING, position)
: CIntObject(used | WHEEL | GESTURE, position)
, scrollStep(1)
, panningDistanceSingle(32)
, panningDistanceAccumulated(0)
@ -20,7 +20,7 @@ Scrollable::Scrollable(int used, Point position, Orientation orientation)
{
}
void Scrollable::panning(bool on, const Point & initialPosition, const Point & finalPosition)
void Scrollable::gesture(bool on, const Point & initialPosition, const Point & finalPosition)
{
panningDistanceAccumulated = 0;
}
@ -88,7 +88,7 @@ void Scrollable::setPanningStep(int to)
void Scrollable::setScrollingEnabled(bool on)
{
if (on)
addUsedEvents(WHEEL | GESTURE_PANNING);
addUsedEvents(WHEEL | GESTURE);
else
removeUsedEvents(WHEEL | GESTURE_PANNING);
removeUsedEvents(WHEEL | GESTURE);
}

View File

@ -33,7 +33,7 @@ class Scrollable : public CIntObject
protected:
Scrollable(int used, Point position, Orientation orientation);
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void wheelScrolled(int distance) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;

View File

@ -142,7 +142,7 @@ void CSlider::clickLeft(tribool down, bool previousState)
return;
// if (rw>1) return;
// if (rw<0) return;
slider->clickLeft(true, slider->isMouseButtonPressed(MouseButton::LEFT));
slider->clickLeft(true, slider->isMouseLeftButtonPressed());
scrollTo((int)(rw * positions + 0.5));
return;
}
@ -151,7 +151,7 @@ void CSlider::clickLeft(tribool down, bool previousState)
bool CSlider::receiveEvent(const Point &position, int eventType) const
{
if (eventType != WHEEL && eventType != GESTURE_PANNING)
if (eventType != WHEEL && eventType != GESTURE)
{
return CIntObject::receiveEvent(position, eventType);
}

View File

@ -69,7 +69,7 @@ CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance * Town
area(nullptr),
stateTimeCounter(BUILD_ANIMATION_FINISHED_TIMEPOINT)
{
addUsedEvents(LCLICK | RCLICK | HOVER | TIME);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER | TIME);
pos.x += str->pos.x;
pos.y += str->pos.y;
@ -141,9 +141,9 @@ void CBuildingRect::clickLeft(tribool down, bool previousState)
}
}
void CBuildingRect::clickRight(tribool down, bool previousState)
void CBuildingRect::showPopupWindow()
{
if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding) || getBuilding() == nullptr)
if((!area) || (this!=parent->selectedBuilding) || getBuilding() == nullptr)
return;
if( !area->isTransparent(GH.getCursorPosition() - pos.topLeft()) ) //inside building image
{
@ -328,7 +328,7 @@ CHeroGSlot::CHeroGSlot(int x, int y, int updown, const CGHeroInstance * h, HeroS
set(h);
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
}
CHeroGSlot::~CHeroGSlot() = default;
@ -415,9 +415,9 @@ void CHeroGSlot::clickLeft(tribool down, bool previousState)
}
}
void CHeroGSlot::clickRight(tribool down, bool previousState)
void CHeroGSlot::showPopupWindow()
{
if(hero && down)
if(hero)
{
GH.windows().createAndPushWindow<CInfoBoxPopup>(Point(pos.x + 175, pos.y + 100), hero);
}
@ -1007,7 +1007,7 @@ CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, boo
level = -1;
return;//No creature
}
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
ui32 creatureID = town->creatures[level].second.back();
creature = CGI->creh->objects[creatureID];
@ -1089,15 +1089,12 @@ std::string CCreaInfo::genGrowthText()
return descr;
}
void CCreaInfo::clickRight(tribool down, bool previousState)
void CCreaInfo::showPopupWindow()
{
if(down)
{
if (showAvailable)
GH.windows().createAndPushWindow<CDwellingInfoBox>(GH.screenDimensions().x / 2, GH.screenDimensions().y / 2, town, level);
else
CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->getId()));
}
if (showAvailable)
GH.windows().createAndPushWindow<CDwellingInfoBox>(GH.screenDimensions().x / 2, GH.screenDimensions().y / 2, town, level);
else
CRClickPopup::createAndPush(genGrowthText(), std::make_shared<CComponent>(CComponent::creature, creature->getId()));
}
bool CCreaInfo::getShowAvailable()
@ -1110,7 +1107,7 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance * Town, bool townH
building(nullptr)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
addUsedEvents(RCLICK | HOVER);
addUsedEvents(SHOW_POPUP | HOVER);
pos.x += posX;
pos.y += posY;
int buildID;
@ -1144,9 +1141,9 @@ void CTownInfo::hover(bool on)
}
}
void CTownInfo::clickRight(tribool down, bool previousState)
void CTownInfo::showPopupWindow()
{
if(building && down)
if(building)
{
auto c = std::make_shared<CComponent>(CComponent::building, building->town->faction->getIndex(), building->bid);
CRClickPopup::createAndPush(CInfoWindow::genText(building->getNameTranslated(), building->getDescriptionTranslated()), c);
@ -1342,7 +1339,7 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance *
building(Building)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
pos.x += x;
pos.y += y;
pos.w = 154;
@ -1396,10 +1393,9 @@ void CHallInterface::CBuildingBox::clickLeft(tribool down, bool previousState)
GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,0);
}
void CHallInterface::CBuildingBox::clickRight(tribool down, bool previousState)
void CHallInterface::CBuildingBox::showPopupWindow()
{
if(down)
GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,1);
GH.windows().createAndPushWindow<CBuildWindow>(town,building,state,1);
}
CHallInterface::CHallInterface(const CGTownInstance * Town):
@ -1668,7 +1664,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
pos.h = 126;
if(!town->creatures[level].second.empty())
addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present
addUsedEvents(LCLICK | HOVER);//Activate only if dwelling is present
icons = std::make_shared<CPicture>("TPCAINFO", 261, 3);
@ -1758,11 +1754,6 @@ void CFortScreen::RecruitArea::clickLeft(tribool down, bool previousState)
LOCPLINT->castleInt->builds->enterDwelling(level);
}
void CFortScreen::RecruitArea::clickRight(tribool down, bool previousState)
{
clickLeft(down, false); //r-click does same as l-click - opens recr. window
}
CMageGuildScreen::CMageGuildScreen(CCastleInterface * owner,std::string imagem)
: CStatusbarWindow(BORDERED, imagem)
{
@ -1807,7 +1798,7 @@ CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
pos += position;
image = std::make_shared<CAnimImage>("SPELLSCR", spell->id);
pos = image->pos;
@ -1819,10 +1810,9 @@ void CMageGuildScreen::Scroll::clickLeft(tribool down, bool previousState)
LOCPLINT->showInfoDialog(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
}
void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState)
void CMageGuildScreen::Scroll::showPopupWindow()
{
if(down)
CRClickPopup::createAndPush(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
CRClickPopup::createAndPush(spell->getDescriptionTranslated(0), std::make_shared<CComponent>(CComponent::spell, spell->id));
}
void CMageGuildScreen::Scroll::hover(bool on)

View File

@ -67,7 +67,7 @@ public:
bool operator<(const CBuildingRect & p2) const;
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void mouseMoved (const Point & cursorPosition) override;
void tick(uint32_t msPassed) override;
void show(Canvas & to) override;
@ -112,7 +112,7 @@ public:
void hover (bool on) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void deactivate() override;
};
@ -192,7 +192,7 @@ public:
void update();
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
bool getShowAvailable();
};
@ -207,7 +207,7 @@ public:
CTownInfo(int posX, int posY, const CGTownInstance * town, bool townHall);
void hover(bool on) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
};
/// Class which manages the castle window
@ -274,7 +274,7 @@ class CHallInterface : public CStatusbarWindow
CBuildingBox(int x, int y, const CGTownInstance * Town, const CBuilding * Building);
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
};
const CGTownInstance * town;
@ -346,7 +346,6 @@ class CFortScreen : public CStatusbarWindow
void creaturesChangedEventHandler();
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
};
std::shared_ptr<CLabel> title;
std::vector<std::shared_ptr<RecruitArea>> recAreas;
@ -372,7 +371,7 @@ class CMageGuildScreen : public CStatusbarWindow
public:
Scroll(Point position, const CSpell *Spell);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
};
std::shared_ptr<CPicture> window;

View File

@ -120,12 +120,6 @@ void CCommanderSkillIcon::clickLeft(tribool down, bool previousState)
callback();
}
void CCommanderSkillIcon::clickRight(tribool down, bool previousState)
{
if(down)
LRClickableAreaWText::clickRight(down, previousState);
}
static std::string skillToFile(int skill, int level, bool selected)
{
// FIXME: is this a correct hadling?

View File

@ -38,7 +38,6 @@ public:
std::function<void()> callback;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void setObject(std::shared_ptr<CIntObject> object);
};

View File

@ -49,7 +49,7 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IIn
name(nullptr)
{
assert(data);
addUsedEvents(LCLICK | RCLICK);
addUsedEvents(LCLICK | SHOW_POPUP);
EFonts font = (size < SIZE_MEDIUM)? FONT_SMALL: FONT_MEDIUM;
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -90,18 +90,15 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IIn
InfoBox::~InfoBox() = default;
void InfoBox::clickRight(tribool down, bool previousState)
void InfoBox::showPopupWindow()
{
if (down)
{
std::shared_ptr<CComponent> comp;
std::string text;
data->prepareMessage(text, comp);
if (comp)
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
else if (!text.empty())
CRClickPopup::createAndPush(text);
}
std::shared_ptr<CComponent> comp;
std::string text;
data->prepareMessage(text, comp);
if (comp)
CRClickPopup::createAndPush(text, CInfoWindow::TCompsInfo(1, comp));
else if (!text.empty())
CRClickPopup::createAndPush(text);
}
void InfoBox::clickLeft(tribool down, bool previousState)
@ -602,7 +599,7 @@ void CKingdomInterface::generateMinesList(const std::vector<const CGObjectInstan
std::string value = std::to_string(minesCount[i]);
auto data = std::make_shared<InfoBoxCustom>(value, "", "OVMINES", i, CGI->generaltexth->translate("core.minename", i));
minesBox[i] = std::make_shared<InfoBox>(Point(20+i*80, 31+footerPos), InfoBox::POS_INSIDE, InfoBox::SIZE_SMALL, data);
minesBox[i]->removeUsedEvents(LCLICK|RCLICK); //fixes #890 - mines boxes ignore clicks
minesBox[i]->removeUsedEvents(LCLICK|SHOW_POPUP); //fixes #890 - mines boxes ignore clicks
}
incomeArea = std::make_shared<CHoverableArea>();
incomeArea->pos = Rect(pos.x+580, pos.y+31+footerPos, 136, 68);

View File

@ -73,7 +73,7 @@ public:
InfoBox(Point position, InfoPos Pos, InfoSize Size, std::shared_ptr<IInfoBoxData> Data);
~InfoBox();
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void clickLeft(tribool down, bool previousState) override;
//Update object if data may have changed

View File

@ -43,7 +43,7 @@
CSpellWindow::InteractiveArea::InteractiveArea(const Rect & myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner)
{
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
pos = myRect;
onLeft = funcL;
hoverText = CGI->generaltexth->zelp[helpTextId].first;
@ -57,10 +57,9 @@ void CSpellWindow::InteractiveArea::clickLeft(tribool down, bool previousState)
onLeft();
}
void CSpellWindow::InteractiveArea::clickRight(tribool down, bool previousState)
void CSpellWindow::InteractiveArea::showPopupWindow()
{
if (down)
CRClickPopup::createAndPush(helpText);
CRClickPopup::createAndPush(helpText);
}
void CSpellWindow::InteractiveArea::hover(bool on)
@ -453,7 +452,7 @@ CSpellWindow::SpellArea::SpellArea(Rect pos, CSpellWindow * owner)
{
this->pos = pos;
this->owner = owner;
addUsedEvents(LCLICK | RCLICK | HOVER);
addUsedEvents(LCLICK | SHOW_POPUP | HOVER);
schoolLevel = -1;
mySpell = nullptr;
@ -541,9 +540,9 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState)
}
}
void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState)
void CSpellWindow::SpellArea::showPopupWindow()
{
if(mySpell && down)
if(mySpell)
{
std::string dmgInfo;
auto causedDmg = owner->myInt->cb->estimateSpellDamage(mySpell, owner->myHero);

View File

@ -45,7 +45,7 @@ class CSpellWindow : public CWindowObject
void setSpell(const CSpell * spell);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
};
@ -58,7 +58,7 @@ class CSpellWindow : public CWindowObject
std::string helpText;
public:
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
InteractiveArea(const Rect &myRect, std::function<void()> funcL, int helpTextId, CSpellWindow * _owner);

View File

@ -38,7 +38,7 @@
#include "../../lib/mapObjects/CGMarket.h"
CTradeWindow::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial)
: CIntObject(LCLICK | HOVER | RCLICK, pos),
: CIntObject(LCLICK | HOVER | SHOW_POPUP, pos),
type(EType(-1)),// set to invalid, will be corrected in setType
id(ID),
serial(Serial),
@ -263,12 +263,10 @@ void CTradeWindow::CTradeableItem::hover(bool on)
}
}
void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
void CTradeWindow::CTradeableItem::showPopupWindow()
{
if(down)
switch(type)
{
switch(type)
{
case CREATURE:
case CREATURE_PLACEHOLDER:
//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl));
@ -279,7 +277,6 @@ void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState)
if(id >= 0)
CRClickPopup::createAndPush(CGI->artifacts()->getByIndex(id)->getDescriptionTranslated());
break;
}
}
}

View File

@ -56,7 +56,7 @@ public:
void showAllAt(const Point & dstPos, const std::string & customSub, Canvas & to);
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
void showAll(Canvas & to) override;
void clickLeft(tribool down, bool previousState) override;

View File

@ -34,7 +34,7 @@
#include <SDL_surface.h>
CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt):
WindowBase(getUsedEvents(options_), Point()),
WindowBase(0, Point()),
options(options_),
background(createBg(imageName, options & PLAYER_COLORED))
{
@ -55,7 +55,7 @@ CWindowObject::CWindowObject(int options_, std::string imageName, Point centerAt
}
CWindowObject::CWindowObject(int options_, std::string imageName):
WindowBase(getUsedEvents(options_), Point()),
WindowBase(0, Point()),
options(options_),
background(createBg(imageName, options_ & PLAYER_COLORED))
{
@ -75,7 +75,11 @@ CWindowObject::CWindowObject(int options_, std::string imageName):
setShadow(true);
}
CWindowObject::~CWindowObject() = default;
CWindowObject::~CWindowObject()
{
if(options & RCLICK_POPUP)
CCS->curh->show();
}
std::shared_ptr<CPicture> CWindowObject::createBg(std::string imageName, bool playerColored)
{
@ -103,13 +107,6 @@ void CWindowObject::setBackground(std::string filename)
updateShadow();
}
int CWindowObject::getUsedEvents(int options)
{
if (options & RCLICK_POPUP)
return RCLICK;
return 0;
}
void CWindowObject::updateShadow()
{
setShadow(false);
@ -235,10 +232,9 @@ void CWindowObject::showAll(Canvas & to)
CMessage::drawBorder(color, to.getInternalSurface(), pos.w+28, pos.h+29, pos.x-14, pos.y-15);
}
void CWindowObject::clickRight(tribool down, bool previousState)
bool CWindowObject::isPopupWindow() const
{
close();
CCS->curh->show();
return options & RCLICK_POPUP;
}
CStatusbarWindow::CStatusbarWindow(int options, std::string imageName, Point centerAt) : CWindowObject(options, imageName, centerAt)

View File

@ -16,7 +16,6 @@ class CGStatusBar;
class CWindowObject : public WindowBase
{
std::shared_ptr<CPicture> createBg(std::string imageName, bool playerColored);
int getUsedEvents(int options);
std::vector<std::shared_ptr<CPicture>> shadowParts;
@ -28,7 +27,7 @@ protected:
std::shared_ptr<CPicture> background;
//Used only if RCLICK_POPUP was set
void clickRight(tribool down, bool previousState) override;
bool isPopupWindow() const override;
//To display border
void updateShadow();
void setBackground(std::string filename);

View File

@ -114,7 +114,7 @@ void CreaturePurchaseCard::initView()
}
CreaturePurchaseCard::CCreatureClickArea::CCreatureClickArea(const Point & position, const std::shared_ptr<CCreaturePic> creaturePic, const CCreature * creatureOnTheCard)
: CIntObject(RCLICK),
: CIntObject(SHOW_POPUP),
creatureOnTheCard(creatureOnTheCard)
{
pos.x += position.x;
@ -123,8 +123,7 @@ CreaturePurchaseCard::CCreatureClickArea::CCreatureClickArea(const Point & posit
pos.h = CREATURE_HEIGHT;
}
void CreaturePurchaseCard::CCreatureClickArea::clickRight(tribool down, bool previousState)
void CreaturePurchaseCard::CCreatureClickArea::showPopupWindow()
{
if (down)
GH.windows().createAndPushWindow<CStackWindow>(creatureOnTheCard, true);
GH.windows().createAndPushWindow<CStackWindow>(creatureOnTheCard, true);
}

View File

@ -49,7 +49,7 @@ private:
{
public:
CCreatureClickArea(const Point & pos, const std::shared_ptr<CCreaturePic> creaturePic, const CCreature * creatureOnTheCard);
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
const CCreature * creatureOnTheCard;
// These are obtained by guessing and checking. I'm not sure how the other numbers

View File

@ -75,7 +75,7 @@
#include "../lib/TextOperations.h"
CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount)
: CIntObject(LCLICK | RCLICK),
: CIntObject(LCLICK | SHOW_POPUP),
parent(window),
selected(false),
creature(crea),
@ -100,10 +100,9 @@ void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousSta
parent->select(this->shared_from_this());
}
void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState)
void CRecruitmentWindow::CCreatureCard::showPopupWindow()
{
if(down)
GH.windows().createAndPushWindow<CStackWindow>(creature, true);
GH.windows().createAndPushWindow<CStackWindow>(creature, true);
}
void CRecruitmentWindow::CCreatureCard::showAll(Canvas & to)
@ -557,14 +556,14 @@ void CTavernWindow::HeroPortrait::clickLeft(tribool down, bool previousState)
*_sel = _id;
}
void CTavernWindow::HeroPortrait::clickRight(tribool down, bool previousState)
void CTavernWindow::HeroPortrait::showPopupWindow()
{
if(h && down)
if(h)
GH.windows().createAndPushWindow<CRClickPopupInt>(std::make_shared<CHeroWindow>(h));
}
CTavernWindow::HeroPortrait::HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H)
: CIntObject(LCLICK | RCLICK | HOVER),
: CIntObject(LCLICK | SHOW_POPUP | HOVER),
h(H), _sel(&sel), _id(id)
{
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@ -1237,7 +1236,7 @@ CTransformerWindow::CTransformerWindow(const IMarket * _market, const CGHeroInst
}
CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int Y)
: CIntObject(LCLICK | RCLICK | HOVER),
: CIntObject(LCLICK | SHOW_POPUP | HOVER),
ID(_ID),
parent(_parent)
{
@ -1266,12 +1265,9 @@ void CUniversityWindow::CItem::clickLeft(tribool down, bool previousState)
}
}
void CUniversityWindow::CItem::clickRight(tribool down, bool previousState)
void CUniversityWindow::CItem::showPopupWindow()
{
if(down)
{
CRClickPopup::createAndPush(CGI->skillh->getByIndex(ID)->getDescriptionTranslated(1), std::make_shared<CComponent>(CComponent::secskill, ID, 1));
}
CRClickPopup::createAndPush(CGI->skillh->getByIndex(ID)->getDescriptionTranslated(1), std::make_shared<CComponent>(CComponent::secskill, ID, 1));
}
void CUniversityWindow::CItem::hover(bool on)

View File

@ -60,7 +60,7 @@ class CRecruitmentWindow : public CStatusbarWindow
CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount);
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void showAll(Canvas & to) override;
};
@ -206,7 +206,7 @@ public:
const CGHeroInstance * h;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover (bool on) override;
HeroPortrait(int & sel, int id, int x, int y, const CGHeroInstance * H);
@ -418,7 +418,7 @@ class CUniversityWindow : public CStatusbarWindow
void showAll(Canvas & to) override;
void clickLeft(tribool down, bool previousState) override;
void clickRight(tribool down, bool previousState) override;
void showPopupWindow() override;
void hover(bool on) override;
int state();//0=can't learn, 1=learned, 2=can learn
CItem(CUniversityWindow * _parent, int _ID, int X, int Y);

View File

@ -288,12 +288,9 @@ void CInfoPopup::init(int x, int y)
vstd::amin(pos.y, GH.screenDimensions().y - bitmap->h);
}
void CRClickPopup::clickRight(tribool down, bool previousState)
bool CRClickPopup::isPopupWindow() const
{
if(down)
return;
close();
return true;
}
void CRClickPopup::close()
@ -309,9 +306,8 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom
auto temp = std::make_shared<CInfoWindow>(txt, player, comps);
temp->center(GH.getCursorPosition()); //center on mouse
#ifdef VCMI_IOS
// TODO: enable also for android?
temp->moveBy({0, -temp->pos.h / 2});
#ifdef VCMI_MOBILE
temp->moveBy({0, -temp->pos.h / 2});
#endif
temp->fitToScreen(10);
@ -342,15 +338,6 @@ void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p,
}
}
CRClickPopup::CRClickPopup()
{
addUsedEvents(RCLICK);
}
CRClickPopup::~CRClickPopup()
{
}
CRClickPopupInt::CRClickPopupInt(std::shared_ptr<CIntObject> our)
{
CCS->curh->hide();

View File

@ -76,10 +76,7 @@ class CRClickPopup : public WindowBase
{
public:
virtual void close();
void clickRight(tribool down, bool previousState) override;
CRClickPopup();
virtual ~CRClickPopup();
bool isPopupWindow() const override;
static std::shared_ptr<WindowBase> createInfoWin(Point position, const CGObjectInstance * specific);
static void createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());

View File

@ -12,7 +12,6 @@
#include "../../battle/BattleInterface.h"
#include "../../gui/CGuiHandler.h"
#include "../../eventsSDL/InputHandler.h"
#include "../../../lib/CConfigHandler.h"
#include "../../../lib/filesystem/ResourceID.h"
#include "../../../lib/CGeneralTextHandler.h"
@ -24,8 +23,6 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
type |= REDRAW_PARENT;
//addConditional("touchscreen", GH.input().hasTouchInputDevice());
const JsonNode config(ResourceID("config/widgets/settings/battleOptionsTab.json"));
addCallback("viewGridChanged", [this, owner](bool value)
{

View File

@ -8,24 +8,25 @@
*
*/
#include "StdInc.h"
#include "GeneralOptionsTab.h"
#include "../../../lib/CGeneralTextHandler.h"
#include "../../../lib/filesystem/ResourceID.h"
#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"
#include "CMusicHandler.h"
#include "CPlayerInterface.h"
#include "windows/GUIClasses.h"
#include "CServerHandler.h"
#include "render/IScreenHandler.h"
#include "windows/GUIClasses.h"
#include "../../eventsSDL/InputHandler.h"
#include "../../gui/CGuiHandler.h"
#include "../../gui/WindowHandler.h"
#include "../../widgets/Buttons.h"
#include "../../widgets/Images.h"
#include "../../widgets/Slider.h"
#include "../../widgets/TextControls.h"
#include "../../../lib/CGeneralTextHandler.h"
#include "../../../lib/filesystem/ResourceID.h"
static void setIntSetting(std::string group, std::string field, int value)
{
@ -52,6 +53,22 @@ static std::string scalingToLabelString( int scaling)
return string;
}
static std::string longTouchToEntryString( int duration)
{
std::string string = CGI->generaltexth->translate("vcmi.systemOptions.longTouchMenu.entry");
boost::replace_all(string, "%d", std::to_string(duration));
return string;
}
static std::string longTouchToLabelString( int duration)
{
std::string string = CGI->generaltexth->translate("vcmi.systemOptions.longTouchButton.hover");
boost::replace_all(string, "%d", std::to_string(duration));
return string;
}
static std::string resolutionToEntryString( int w, int h)
{
std::string string = "%wx%h";
@ -79,6 +96,7 @@ GeneralOptionsTab::GeneralOptionsTab()
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
type |= REDRAW_PARENT;
addConditional("touchscreen", GH.input().hasTouchInputDevice());
#ifdef VCMI_MOBILE
addConditional("mobile", true);
addConditional("desktop", false);
@ -127,6 +145,10 @@ GeneralOptionsTab::GeneralOptionsTab()
{
selectGameScaling();
});
addCallback("setLongTouchDuration", [this](int dummyValue)
{
selectLongTouchDuration();
});
addCallback("framerateChanged", [](bool value)
{
setBoolSetting("video", "showfps", value);
@ -150,6 +172,10 @@ GeneralOptionsTab::GeneralOptionsTab()
std::shared_ptr<CLabel> scalingLabel = widget<CLabel>("scalingLabel");
scalingLabel->setText(scalingToLabelString(currentResolution["scaling"].Integer()));
std::shared_ptr<CLabel> longTouchLabel = widget<CLabel>("longTouchLabel");
if (longTouchLabel)
longTouchLabel->setText(longTouchToLabelString(settings["general"]["longTouchTimeMilliseconds"].Integer()));
std::shared_ptr<CToggleButton> spellbookAnimationCheckbox = widget<CToggleButton>("spellbookAnimationCheckbox");
spellbookAnimationCheckbox->setSelected(settings["video"]["spellbookAnimation"].Bool());
@ -324,3 +350,48 @@ void GeneralOptionsTab::setGameScaling(int index)
widget<CLabel>("scalingLabel")->setText(scalingToLabelString(scaling));
}
void GeneralOptionsTab::selectLongTouchDuration()
{
longTouchDurations = { 500, 750, 1000, 1250, 1500, 1750, 2000 };
std::vector<std::string> items;
size_t currentIndex = 0;
size_t i = 0;
for(const auto & it : longTouchDurations)
{
auto resolutionStr = longTouchToEntryString(it);
if(widget<CLabel>("longTouchLabel")->getText() == longTouchToLabelString(it))
currentIndex = i;
items.push_back(std::move(resolutionStr));
++i;
}
GH.windows().createAndPushWindow<CObjectListWindow>(
items,
nullptr,
CGI->generaltexth->translate("vcmi.systemOptions.longTouchMenu.hover"),
CGI->generaltexth->translate("vcmi.systemOptions.longTouchMenu.help"),
[this](int index)
{
setLongTouchDuration(index);
},
currentIndex
);
}
void GeneralOptionsTab::setLongTouchDuration(int index)
{
assert(index >= 0 && index < longTouchDurations.size());
if ( index < 0 || index >= longTouchDurations.size() )
return;
int scaling = longTouchDurations[index];
Settings longTouchTime = settings.write["general"]["longTouchTimeMilliseconds"];
longTouchTime->Float() = scaling;
widget<CLabel>("longTouchLabel")->setText(longTouchToLabelString(scaling));
}

View File

@ -20,6 +20,7 @@ private:
std::vector<Point> supportedResolutions;
std::vector<int> supportedScaling;
std::vector<int> longTouchDurations;
void setFullscreenMode( bool on, bool exclusive);
@ -29,6 +30,9 @@ private:
void selectGameScaling();
void setGameScaling(int index);
void selectLongTouchDuration();
void setLongTouchDuration(int index);
public:
GeneralOptionsTab();

View File

@ -21,15 +21,19 @@
"playerName",
"music",
"sound",
"saveRandomMaps",
"lastMap",
"language",
"gameDataLanguage",
"saveRandomMaps",
"lastSave",
"lastSettingsTab"
"lastCampaign",
"saveFrequency",
"notifications",
"extraDump",
"userRelativePointer",
"relativePointerSpeedMultiplier",
"lastSettingsTab"
"longTouchTimeMilliseconds"
],
"properties" : {
"playerName" : {
@ -93,6 +97,10 @@
"relativePointerSpeedMultiplier" : {
"type" : "number",
"default" : 1
},
"longTouchTimeMilliseconds" : {
"type" : "number",
"default" : 1000
}
}
},
@ -102,13 +110,12 @@
"default" : {},
"required" : [
"resolution",
"bitsPerPixel",
"fullscreen",
"realFullscreen",
"cursor",
"showIntro",
"spellbookAnimation",
"driver",
"showIntro",
"displayIndex",
"showfps",
"targetfps"
@ -125,10 +132,6 @@
},
"default" : {"width" : 800, "height" : 600, "scaling" : 100 }
},
"bitsPerPixel" : {
"type" : "number",
"default" : 32
},
"fullscreen" : {
"type" : "boolean",
"default" : false

View File

@ -52,6 +52,11 @@
},
{
"text": "core.genrltxt.577"
},
{
"name": "longTouchLabel",
"text": "vcmi.systemOptions.longTouchButton.hover",
"created" : "touchscreen"
}
]
},
@ -95,6 +100,13 @@
"help": "core.help.364",
"callback": "spellbookAnimationChanged"
},
{
"name": "longTouchButton",
"type": "buttonGear",
"help": "vcmi.systemOptions.longTouchButton",
"callback": "setLongTouchDuration",
"created" : "touchscreen"
}
]
},
/////////////////////////////////////// Right section - Audio Settings