1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-13 19:54:17 +02:00

Extracted event management from GuiHandler and CIntObject

This commit is contained in:
Ivan Savenko
2023-05-17 23:22:45 +03:00
parent 008a1ebec4
commit 1f513fd280
29 changed files with 518 additions and 365 deletions

View File

@@ -30,6 +30,7 @@ set(client_SRCS
gui/CGuiHandler.cpp
gui/CIntObject.cpp
gui/CursorHandler.cpp
gui/InterfaceEventDispatcher.cpp
gui/InterfaceObjectConfigurable.cpp
gui/FramerateManager.cpp
gui/NotificationHandler.cpp
@@ -164,6 +165,7 @@ set(client_HEADERS
gui/CIntObject.h
gui/CursorHandler.h
gui/InterfaceObjectConfigurable.h
gui/InterfaceEventDispatcher.h
gui/FramerateManager.h
gui/MouseButton.h
gui/NotificationHandler.h

View File

@@ -1872,7 +1872,7 @@ bool CPlayerInterface::capturedAllEvents()
return true;
}
bool needToLockAdventureMap = adventureInt && adventureInt->active && CGI->mh->hasOngoingAnimations();
bool needToLockAdventureMap = adventureInt && adventureInt->isActive() && CGI->mh->hasOngoingAnimations();
if (ignoreEvents || needToLockAdventureMap || isAutoFightOn)
{

View File

@@ -493,9 +493,9 @@ void ClientCommandManager::printInfoAboutInterfaceObject(const CIntObject *obj,
sbuffer << std::string(level, '\t');
sbuffer << typeid(*obj).name() << " *** ";
if (obj->active)
if (obj->isActive())
{
#define PRINT(check, text) if (obj->active & CIntObject::check) sbuffer << text
#define PRINT(check, text) if (obj->isActive(CIntObject::check)) sbuffer << text
PRINT(LCLICK, 'L');
PRINT(RCLICK, 'R');
PRINT(HOVER, 'H');

View File

@@ -52,7 +52,7 @@ AdventureMapInterface::AdventureMapInterface():
pos.x = pos.y = 0;
pos.w = GH.screenDimensions().x;
pos.h = GH.screenDimensions().y;
strongInterest = true; // handle all mouse move events to prevent dead mouse move space in fullscreen mode
setMoveEventStrongInterest(true); // handle all mouse move events to prevent dead mouse move space in fullscreen mode
shortcuts = std::make_shared<AdventureMapShortcuts>(*this);
@@ -179,7 +179,7 @@ void AdventureMapInterface::handleMapScrollingUpdate(uint32_t timePassed)
Point scrollDelta = scrollDirection * scrollDistance;
bool cursorInScrollArea = scrollDelta != Point(0,0);
bool scrollingActive = cursorInScrollArea && active && shortcuts->optionSidePanelActive() && !scrollingWasBlocked;
bool scrollingActive = cursorInScrollArea && isActive() && shortcuts->optionSidePanelActive() && !scrollingWasBlocked;
bool scrollingBlocked = GH.isKeyboardCtrlDown();
if (!scrollingWasActive && scrollingBlocked)
@@ -323,19 +323,19 @@ void AdventureMapInterface::setState(EAdventureState state)
void AdventureMapInterface::adjustActiveness()
{
bool widgetMustBeActive = active && shortcuts->optionSidePanelActive();
bool mapViewMustBeActive = active && (shortcuts->optionMapViewActive());
bool widgetMustBeActive = isActive() && shortcuts->optionSidePanelActive();
bool mapViewMustBeActive = isActive() && (shortcuts->optionMapViewActive());
if (widgetMustBeActive && !widget->active)
if (widgetMustBeActive && !widget->isActive())
widget->activate();
if (!widgetMustBeActive && widget->active)
if (!widgetMustBeActive && widget->isActive())
widget->deactivate();
if (mapViewMustBeActive && !widget->getMapView()->active)
if (mapViewMustBeActive && !widget->getMapView()->isActive())
widget->getMapView()->activate();
if (!mapViewMustBeActive && widget->getMapView()->active)
if (!mapViewMustBeActive && widget->getMapView()->isActive())
widget->getMapView()->deactivate();
}

View File

@@ -211,7 +211,7 @@ void CInGameConsole::textEdited(const std::string & inputtedText)
void CInGameConsole::startEnteringText()
{
if (!active)
if (!isActive())
return;
if (captureAllKeys)

View File

@@ -316,8 +316,7 @@ CInfoBar::CInfoBar(const Point & position): CInfoBar(Rect(position.x, position.y
void CInfoBar::setTimer(uint32_t msToTrigger)
{
if (!(active & TIME))
addUsedEvents(TIME);
addUsedEvents(TIME);
timerCounter = msToTrigger;
}

View File

@@ -131,7 +131,7 @@ void CMinimap::moveAdvMapSelection()
int3 newLocation = pixelToTile(GH.getCursorPosition() - pos.topLeft());
adventureInt->centerOnTile(newLocation);
if (!(adventureInt->active & GENERAL))
if (!(adventureInt->isActive() & GENERAL))
GH.windows().totalRedraw(); //redraw this as well as inactive adventure map
else
redraw();//redraw only this
@@ -159,7 +159,7 @@ void CMinimap::hover(bool on)
void CMinimap::mouseMoved(const Point & cursorPosition)
{
if(mouseState(MouseButton::LEFT))
if(isMouseButtonPressed(MouseButton::LEFT))
moveAdvMapSelection();
}

View File

@@ -39,7 +39,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
owner(owner)
{
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
strongInterest = true;
setMoveEventStrongInterest(true);
//preparing cells and hexes
cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY);

View File

@@ -692,7 +692,7 @@ std::optional<uint32_t> StackQueue::getHoveredUnitIdIfAny() const
{
for(const auto & stackBox : stackBoxes)
{
if(stackBox->hovered || stackBox->mouseState(MouseButton::RIGHT))
if(stackBox->isHovered() || stackBox->isMouseButtonPressed(MouseButton::RIGHT))
{
return stackBox->getBoundUnitID();
}

View File

@@ -16,6 +16,7 @@
#include "ShortcutHandler.h"
#include "FramerateManager.h"
#include "WindowHandler.h"
#include "InterfaceEventDispatcher.h"
#include "../CGameInfo.h"
#include "../render/Colors.h"
@@ -77,29 +78,9 @@ SSetCaptureState::~SSetCaptureState()
GH.defActionsDef = prevActions;
}
static inline void
processList(const ui16 mask, const ui16 flag, std::list<CIntObject*> *lst, std::function<void (std::list<CIntObject*> *)> cb)
{
if (mask & flag)
cb(lst);
}
void CGuiHandler::processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb)
{
processList(CIntObject::LCLICK,activityFlag,&lclickable,cb);
processList(CIntObject::RCLICK,activityFlag,&rclickable,cb);
processList(CIntObject::MCLICK,activityFlag,&mclickable,cb);
processList(CIntObject::HOVER,activityFlag,&hoverable,cb);
processList(CIntObject::MOVE,activityFlag,&motioninterested,cb);
processList(CIntObject::KEYBOARD,activityFlag,&keyinterested,cb);
processList(CIntObject::TIME,activityFlag,&timeinterested,cb);
processList(CIntObject::WHEEL,activityFlag,&wheelInterested,cb);
processList(CIntObject::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
processList(CIntObject::TEXTINPUT,activityFlag,&textInterested,cb);
}
void CGuiHandler::init()
{
eventDispatcherInstance = std::make_unique<InterfaceEventDispatcher>();
windowHandlerInstance = std::make_unique<WindowHandler>();
screenHandlerInstance = std::make_unique<ScreenHandler>();
shortcutsHandlerInstance = std::make_unique<ShortcutHandler>();
@@ -109,33 +90,9 @@ void CGuiHandler::init()
pointerSpeedMultiplier = settings["general"]["relativePointerSpeedMultiplier"].Float();
}
void CGuiHandler::handleElementActivate(CIntObject * elem, ui16 activityFlag)
{
processLists(activityFlag,[&](std::list<CIntObject*> * lst){
lst->push_front(elem);
});
elem->active_m |= activityFlag;
}
void CGuiHandler::handleElementDeActivate(CIntObject * elem, ui16 activityFlag)
{
processLists(activityFlag,[&](std::list<CIntObject*> * lst){
auto hlp = std::find(lst->begin(),lst->end(),elem);
assert(hlp != lst->end());
lst->erase(hlp);
});
elem->active_m &= ~activityFlag;
}
void CGuiHandler::updateTime()
{
int ms = framerateManager().getElapsedMilliseconds();
std::list<CIntObject*> hlp = timeinterested;
for (auto & elem : hlp)
{
if(!vstd::contains(timeinterested,elem)) continue;
(elem)->tick(ms);
}
eventDispatcher().updateTime(framerateManager().getElapsedMilliseconds());
}
void CGuiHandler::handleEvents()
@@ -365,18 +322,7 @@ void CGuiHandler::handleEventKeyDown(SDL_Event & current)
auto shortcutsVector = shortcutsHandler().translateKeycode(key.keysym.sym);
bool keysCaptured = false;
for(auto i = keyinterested.begin(); i != keyinterested.end() && continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if((*i)->captureThisKey(shortcut))
keysCaptured = true;
std::list<CIntObject *> miCopy = keyinterested;
for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if(vstd::contains(keyinterested, *i) && (!keysCaptured || (*i)->captureThisKey(shortcut)))
(**i).keyPressed(shortcut);
eventDispatcher().dispatchShortcutPressed(shortcutsVector);
}
void CGuiHandler::handleEventKeyUp(SDL_Event & current)
@@ -390,24 +336,12 @@ void CGuiHandler::handleEventKeyUp(SDL_Event & current)
auto shortcutsVector = shortcutsHandler().translateKeycode(key.keysym.sym);
bool keysCaptured = false;
for(auto i = keyinterested.begin(); i != keyinterested.end() && continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if((*i)->captureThisKey(shortcut))
keysCaptured = true;
std::list<CIntObject *> miCopy = keyinterested;
for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if(vstd::contains(keyinterested, *i) && (!keysCaptured || (*i)->captureThisKey(shortcut)))
(**i).keyReleased(shortcut);
eventDispatcher().dispatchShortcutReleased(shortcutsVector);
}
void CGuiHandler::handleEventMouseMotion(SDL_Event & current)
{
handleMouseMotion(current);
eventDispatcher().dispatchMouseMoved(Point(current.motion.x, current.motion.y));
}
void CGuiHandler::handleEventMouseButtonDown(SDL_Event & current)
@@ -415,68 +349,34 @@ void CGuiHandler::handleEventMouseButtonDown(SDL_Event & current)
switch(current.button.button)
{
case SDL_BUTTON_LEFT:
{
auto doubleClicked = false;
if(lastClick == getCursorPosition() && (SDL_GetTicks() - lastClickTime) < 300)
{
std::list<CIntObject*> hlp = doubleClickInterested;
for(auto i = hlp.begin(); i != hlp.end() && continueEventHandling; i++)
{
if(!vstd::contains(doubleClickInterested, *i)) continue;
if((*i)->pos.isInside(current.motion.x, current.motion.y))
{
(*i)->onDoubleClick();
doubleClicked = true;
}
}
}
lastClick = current.motion;
lastClickTime = SDL_GetTicks();
if(!doubleClicked)
handleMouseButtonClick(lclickable, MouseButton::LEFT, true);
eventDispatcher().dispatchMouseButtonPressed(MouseButton::LEFT, Point(current.button.x, current.button.y));
break;
}
case SDL_BUTTON_RIGHT:
handleMouseButtonClick(rclickable, MouseButton::RIGHT, true);
eventDispatcher().dispatchMouseButtonPressed(MouseButton::RIGHT, Point(current.button.x, current.button.y));
break;
case SDL_BUTTON_MIDDLE:
handleMouseButtonClick(mclickable, MouseButton::MIDDLE, true);
break;
default:
eventDispatcher().dispatchMouseButtonPressed(MouseButton::MIDDLE, Point(current.button.x, current.button.y));
break;
}
}
void CGuiHandler::handleEventMouseWheel(SDL_Event & current)
{
std::list<CIntObject*> hlp = wheelInterested;
for(auto i = hlp.begin(); i != hlp.end() && continueEventHandling; i++)
{
if(!vstd::contains(wheelInterested,*i)) continue;
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
int x = 0, y = 0;
SDL_GetMouseState(&x, &y);
(*i)->wheelScrolled(current.wheel.y < 0, (*i)->pos.isInside(x, y));
}
// SDL doesn't have the proper values for mouse positions on SDL_MOUSEWHEEL, refetch them
int x = 0, y = 0;
SDL_GetMouseState(&x, &y);
eventDispatcher().dispatchMouseScrolled(Point(current.wheel.x, current.wheel.y), Point(x, y));
}
void CGuiHandler::handleEventTextInput(SDL_Event & current)
{
for(auto it : textInterested)
{
it->textInputed(current.text.text);
}
eventDispatcher().dispatchTextInput(current.text.text);
}
void CGuiHandler::handleEventTextEditing(SDL_Event & current)
{
for(auto it : textInterested)
{
it->textEdited(current.edit.text);
}
eventDispatcher().dispatchTextEditing(current.text.text);
}
void CGuiHandler::handleEventMouseButtonUp(SDL_Event & current)
@@ -486,13 +386,13 @@ void CGuiHandler::handleEventMouseButtonUp(SDL_Event & current)
switch(current.button.button)
{
case SDL_BUTTON_LEFT:
handleMouseButtonClick(lclickable, MouseButton::LEFT, false);
eventDispatcher().dispatchMouseButtonReleased(MouseButton::LEFT, Point(current.button.x, current.button.y));
break;
case SDL_BUTTON_RIGHT:
handleMouseButtonClick(rclickable, MouseButton::RIGHT, false);
eventDispatcher().dispatchMouseButtonReleased(MouseButton::RIGHT, Point(current.button.x, current.button.y));
break;
case SDL_BUTTON_MIDDLE:
handleMouseButtonClick(mclickable, MouseButton::MIDDLE, false);
eventDispatcher().dispatchMouseButtonReleased(MouseButton::MIDDLE, Point(current.button.x, current.button.y));
break;
}
}
@@ -525,8 +425,9 @@ void CGuiHandler::handleEventFingerDown(SDL_Event & current)
else if(fingerCount == 2)
{
convertTouchToMouse(&current);
handleMouseMotion(current);
handleMouseButtonClick(rclickable, MouseButton::RIGHT, true);
eventDispatcher().dispatchMouseMoved(Point(current.button.x, current.button.y));
eventDispatcher().dispatchMouseButtonPressed(MouseButton::RIGHT, Point(current.button.x, current.button.y));
}
#endif //VCMI_IOS
}
@@ -550,78 +451,13 @@ void CGuiHandler::handleEventFingerUp(SDL_Event & current)
else if(multifinger)
{
convertTouchToMouse(&current);
handleMouseMotion(current);
handleMouseButtonClick(rclickable, MouseButton::RIGHT, false);
eventDispatcher().dispatchMouseMoved(Point(current.button.x, current.button.y));
eventDispatcher().dispatchMouseButtonReleased(MouseButton::RIGHT, Point(current.button.x, current.button.y));
multifinger = fingerCount != 0;
}
#endif //VCMI_IOS
}
void CGuiHandler::handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed)
{
auto hlp = interestedObjs;
for(auto i = hlp.begin(); i != hlp.end() && continueEventHandling; i++)
{
if(!vstd::contains(interestedObjs, *i)) continue;
auto prev = (*i)->mouseState(btn);
if(!isPressed)
(*i)->updateMouseState(btn, isPressed);
if((*i)->pos.isInside(getCursorPosition()))
{
if(isPressed)
(*i)->updateMouseState(btn, isPressed);
(*i)->click(btn, isPressed, prev);
}
else if(!isPressed)
(*i)->click(btn, boost::logic::indeterminate, prev);
}
}
void CGuiHandler::handleMouseMotion(const SDL_Event & current)
{
//sending active, hovered hoverable objects hover() call
std::vector<CIntObject*> hlp;
auto hoverableCopy = hoverable;
for(auto & elem : hoverableCopy)
{
if(elem->pos.isInside(getCursorPosition()))
{
if (!(elem)->hovered)
hlp.push_back((elem));
}
else if ((elem)->hovered)
{
(elem)->hover(false);
(elem)->hovered = false;
}
}
for(auto & elem : hlp)
{
elem->hover(true);
elem->hovered = true;
}
// do not send motion events for events outside our window
//if (current.motion.windowID == 0)
handleMoveInterested(current.motion);
}
void CGuiHandler::handleMoveInterested(const SDL_MouseMotionEvent & motion)
{
//sending active, MotionInterested objects mouseMoved() call
std::list<CIntObject*> miCopy = motioninterested;
for(auto & elem : miCopy)
{
if(elem->strongInterest || Rect::createAround(elem->pos, 1).isInside( motion.x, motion.y)) //checking bounds including border fixes bug #2476
{
(elem)->mouseMoved(Point(motion.x, motion.y));
}
}
}
void CGuiHandler::renderFrame()
{
@@ -781,6 +617,11 @@ IScreenHandler & CGuiHandler::screenHandler()
return *screenHandlerInstance;
}
InterfaceEventDispatcher & CGuiHandler::eventDispatcher()
{
return *eventDispatcherInstance;
}
WindowHandler & CGuiHandler::windows()
{
assert(windowHandlerInstance);

View File

@@ -31,6 +31,7 @@ class IShowActivatable;
class IShowable;
class IScreenHandler;
class WindowHandler;
class InterfaceEventDispatcher;
// TODO: event handling need refactoring
enum class EUserEvent
@@ -48,8 +49,7 @@ enum class EUserEvent
// Handles GUI logic and drawing
class CGuiHandler
{
public:
friend class InterfaceEventDispatcher;
private:
/// Fake no-op version status bar, for use in windows that have no status bar
@@ -65,28 +65,12 @@ private:
std::unique_ptr<WindowHandler> windowHandlerInstance;
std::atomic<bool> continueEventHandling;
using CIntObjectList = std::list<CIntObject *>;
//active GUI elements (listening for events
CIntObjectList lclickable;
CIntObjectList rclickable;
CIntObjectList mclickable;
CIntObjectList hoverable;
CIntObjectList keyinterested;
CIntObjectList motioninterested;
CIntObjectList timeinterested;
CIntObjectList wheelInterested;
CIntObjectList doubleClickInterested;
CIntObjectList textInterested;
std::unique_ptr<IScreenHandler> screenHandlerInstance;
std::unique_ptr<FramerateManager> framerateManagerInstance;
std::unique_ptr<InterfaceEventDispatcher> eventDispatcherInstance;
void handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed);
void processLists(const ui16 activityFlag, std::function<void (std::list<CIntObject*> *)> cb);
void handleCurrentEvent(SDL_Event &current);
void handleMouseMotion(const SDL_Event & current);
void handleMoveInterested( const SDL_MouseMotionEvent & motion );
void convertTouchToMouse(SDL_Event * current);
void fakeMoveCursor(float dx, float dy);
void fakeMouseButtonEventRelativeMode(bool down, bool right);
@@ -103,9 +87,6 @@ private:
void handleEventFingerDown(SDL_Event & current);
void handleEventFingerUp(SDL_Event & current);
public:
void handleElementActivate(CIntObject * elem, ui16 activityFlag);
void handleElementDeActivate(CIntObject * elem, ui16 activityFlag);
public:
/// returns current position of mouse cursor, relative to vcmi window
@@ -113,6 +94,7 @@ public:
ShortcutHandler & shortcutsHandler();
FramerateManager & framerateManager();
InterfaceEventDispatcher & eventDispatcher();
/// Returns current logical screen dimensions
/// May not match size of window if user has UI scaling different from 100%
@@ -166,7 +148,7 @@ public:
/// called whenever user selects different resolution, requiring to center/resize all windows
void onScreenResize();
void updateTime(); //handles timeInterested
void updateTime();
void handleEvents(); //takes events from queue and calls interested objects
void fakeMouseMove();
void breakEventHandling(); //current event won't be propagated anymore

View File

@@ -11,6 +11,7 @@
#include "CIntObject.h"
#include "CGuiHandler.h"
#include "InterfaceEventDispatcher.h"
#include "WindowHandler.h"
#include "Shortcut.h"
#include "../renderSDL/SDL_Extensions.h"
@@ -19,18 +20,59 @@
#include <SDL_pixels.h>
IShowActivatable::IShowActivatable()
AEventsReceiver::AEventsReceiver()
: activeState(0)
, hoveredState(false)
, strongInterestState(false)
{
type = 0;
}
bool AEventsReceiver::isHovered() const
{
return hoveredState;
}
bool AEventsReceiver::isActive() const
{
return activeState;
}
bool AEventsReceiver::isActive(int flags) const
{
return activeState & flags;
}
bool AEventsReceiver::isMouseButtonPressed(MouseButton btn) const
{
return currentMouseState.count(btn) ? currentMouseState.at(btn) : false;
}
void AEventsReceiver::setMoveEventStrongInterest(bool on)
{
strongInterestState = on;
}
void AEventsReceiver::activateEvents(ui16 what)
{
assert((what & GENERAL) || (activeState & GENERAL));
activeState |= GENERAL;
GH.eventDispatcher().handleElementActivate(this, what);
}
void AEventsReceiver::deactivateEvents(ui16 what)
{
if (what & GENERAL)
activeState &= ~GENERAL;
GH.eventDispatcher().handleElementDeActivate(this, what & activeState);
}
CIntObject::CIntObject(int used_, Point pos_):
parent_m(nullptr),
active_m(0),
parent(parent_m),
active(active_m)
type(0)
{
hovered = captureAllKeys = strongInterest = false;
captureAllKeys = false;
used = used_;
recActions = defActions = GH.defActionsDef;
@@ -46,7 +88,7 @@ CIntObject::CIntObject(int used_, Point pos_):
CIntObject::~CIntObject()
{
if(active_m)
if(isActive())
deactivate();
while(!children.empty())
@@ -76,25 +118,16 @@ void CIntObject::showAll(SDL_Surface * to)
for(auto & elem : children)
if(elem->recActions & SHOWALL)
elem->showAll(to);
}
}
void CIntObject::activate()
{
if (active_m)
{
if ((used | GENERAL) == active_m)
return;
else
{
logGlobal->warn("Warning: IntObject re-activated with mismatching used and active");
deactivate(); //FIXME: better to avoid such possibility at all
}
}
if (isActive())
return;
active_m |= GENERAL;
activate(used);
activateEvents(used | GENERAL);
assert(isActive());
if(defActions & ACTIVATE)
for(auto & elem : children)
@@ -102,20 +135,14 @@ void CIntObject::activate()
elem->activate();
}
void CIntObject::activate(ui16 what)
{
GH.handleElementActivate(this, what);
}
void CIntObject::deactivate()
{
if (!active_m)
if (!isActive())
return;
active_m &= ~ GENERAL;
deactivate(active_m);
deactivateEvents(ALL);
assert(!active_m);
assert(!isActive());
if(defActions & DEACTIVATE)
for(auto & elem : children)
@@ -123,11 +150,6 @@ void CIntObject::deactivate()
elem->deactivate();
}
void CIntObject::deactivate(ui16 what)
{
GH.handleElementDeActivate(this, what);
}
void CIntObject::click(MouseButton btn, tribool down, bool previousState)
{
switch(btn)
@@ -167,21 +189,21 @@ void CIntObject::printAtMiddleWBLoc( const std::string & text, int x, int y, EFo
void CIntObject::addUsedEvents(ui16 newActions)
{
if (active_m)
activate(~used & newActions);
if (isActive())
activateEvents(~used & newActions);
used |= newActions;
}
void CIntObject::removeUsedEvents(ui16 newActions)
{
if (active_m)
deactivate(used & newActions);
if (isActive())
deactivateEvents(used & newActions);
used &= ~newActions;
}
void CIntObject::disable()
{
if(active)
if(isActive())
deactivate();
recActions = DISPOSE;
@@ -189,7 +211,7 @@ void CIntObject::disable()
void CIntObject::enable()
{
if(!active_m && (!parent_m || parent_m->active))
if(!isActive() && (!parent_m || parent_m->isActive()))
{
activate();
redraw();
@@ -246,9 +268,9 @@ void CIntObject::addChild(CIntObject * child, bool adjustPosition)
if(adjustPosition)
child->moveBy(pos.topLeft(), adjustPosition);
if (!active && child->active)
if (!isActive() && child->isActive())
child->deactivate();
if (active && !child->active)
if (isActive()&& !child->isActive())
child->activate();
}
@@ -273,7 +295,7 @@ void CIntObject::redraw()
{
//currently most of calls come from active objects so this check won't affect them
//it should fix glitches when called by inactive elements located below active window
if (active)
if (isActive())
{
if (parent_m && (type & REDRAW_PARENT))
{
@@ -288,6 +310,11 @@ void CIntObject::redraw()
}
}
bool CIntObject::isInside(const Point & position)
{
return pos.isInside(position);
}
void CIntObject::onScreenResize()
{
center(pos, true);
@@ -330,23 +357,13 @@ CKeyShortcut::CKeyShortcut(EShortcut key)
void CKeyShortcut::keyPressed(EShortcut key)
{
if( assignedKey == key && assignedKey != EShortcut::NONE)
{
bool prev = mouseState(MouseButton::LEFT);
updateMouseState(MouseButton::LEFT, true);
clickLeft(true, prev);
}
clickLeft(true, false);
}
void CKeyShortcut::keyReleased(EShortcut key)
{
if( assignedKey == key && assignedKey != EShortcut::NONE)
{
bool prev = mouseState(MouseButton::LEFT);
updateMouseState(MouseButton::LEFT, false);
clickLeft(false, prev);
}
clickLeft(false, true);
}
WindowBase::WindowBase(int used_, Point pos_)

View File

@@ -16,6 +16,7 @@
struct SDL_Surface;
class CGuiHandler;
class CPicture;
class InterfaceEventDispatcher;
enum class EShortcut;
using boost::logic::tribool;
@@ -26,14 +27,14 @@ class IActivatable
public:
virtual void activate()=0;
virtual void deactivate()=0;
virtual ~IActivatable(){};
virtual ~IActivatable() = default;
};
class IUpdateable
{
public:
virtual void update()=0;
virtual ~IUpdateable(){};
virtual ~IUpdateable() = default;
};
// Defines a show method
@@ -46,36 +47,81 @@ public:
{
show(to);
}
virtual ~IShowable(){};
virtual ~IShowable() = default;
};
class IShowActivatable : public IShowable, public IActivatable
{
public:
//redraw parent flag - this int may be semi-transparent and require redraw of parent window
enum {REDRAW_PARENT=8};
int type; //bin flags using etype
IShowActivatable();
virtual ~IShowActivatable(){};
virtual void onScreenResize() = 0;
virtual ~IShowActivatable() = default;
};
class IEventsReceiver
{
public:
virtual void keyPressed(EShortcut key) = 0;
virtual void keyReleased(EShortcut key) = 0;
virtual bool captureThisKey(EShortcut key) = 0;
virtual void click(MouseButton btn, tribool down, bool previousState) = 0;
virtual void clickLeft(tribool down, bool previousState) = 0;
virtual void clickRight(tribool down, bool previousState) = 0;
virtual void clickMiddle(tribool down, bool previousState) = 0;
virtual void textInputed(const std::string & enteredText) = 0;
virtual void textEdited(const std::string & enteredText) = 0;
virtual void tick(uint32_t msPassed) = 0;
virtual void wheelScrolled(bool down, bool in) = 0;
virtual void mouseMoved(const Point & cursorPosition) = 0;
virtual void hover(bool on) = 0;
virtual void onDoubleClick() = 0;
virtual ~IEventsReceiver() = default;
};
class AEventsReceiver : public IEventsReceiver
{
friend class InterfaceEventDispatcher;
ui16 activeState;
std::map<MouseButton, bool> currentMouseState;
bool hoveredState; //for determining if object is hovered
bool strongInterestState; //if true - report all mouse movements, if not - only when hovered
protected:
void setMoveEventStrongInterest(bool on);
void activateEvents(ui16 what);
void deactivateEvents(ui16 what);
public:
AEventsReceiver();
// These are the arguments that can be used to determine what kind of input the CIntObject will receive
enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, MCLICK=1024, ALL=0xffff};
virtual bool isInside(const Point & position) = 0;
bool isHovered() const;
bool isActive() const;
bool isActive(int flags) const;
bool isMouseButtonPressed(MouseButton btn) const;
};
// Base UI element
class CIntObject : public IShowActivatable //interface object
class CIntObject : public IShowActivatable, public AEventsReceiver //interface object
{
ui16 used;//change via addUsed() or delUsed
std::map<MouseButton, bool> currentMouseState;
//non-const versions of fields to allow changing them in CIntObject
CIntObject *parent_m; //parent object
ui16 active_m;
protected:
//activate or deactivate specific action (LCLICK, RCLICK...)
void activate(ui16 what);
void deactivate(ui16 what);
public:
//redraw parent flag - this int may be semi-transparent and require redraw of parent window
enum {REDRAW_PARENT=8};
int type; //bin flags using etype
/*
* Functions and fields that supposed to be private but are not for now.
* Don't use them unless you really know what they are for
@@ -96,43 +142,35 @@ public:
CIntObject(int used=0, Point offset=Point());
virtual ~CIntObject();
void updateMouseState(MouseButton btn, bool state) { currentMouseState[btn] = state; }
bool mouseState(MouseButton btn) const { return currentMouseState.count(btn) ? currentMouseState.at(btn) : false; }
virtual void click(MouseButton btn, tribool down, bool previousState);
virtual void clickLeft(tribool down, bool previousState) {}
virtual void clickRight(tribool down, bool previousState) {}
virtual void clickMiddle(tribool down, bool previousState) {}
void click(MouseButton btn, tribool down, bool previousState) final;
void clickLeft(tribool down, bool previousState) override {}
void clickRight(tribool down, bool previousState) override {}
void clickMiddle(tribool down, bool previousState) override {}
//hover handling
/*const*/ bool hovered; //for determining if object is hovered
virtual void hover (bool on){}
void hover (bool on) override{}
//keyboard handling
bool captureAllKeys; //if true, only this object should get info about pressed keys
virtual void keyPressed(EShortcut key){}
virtual void keyReleased(EShortcut key){}
virtual bool captureThisKey(EShortcut key); //allows refining captureAllKeys against specific events (eg. don't capture ENTER)
void keyPressed(EShortcut key) override {}
void keyReleased(EShortcut key) override {}
bool captureThisKey(EShortcut key) override; //allows refining captureAllKeys against specific events (eg. don't capture ENTER)
virtual void textInputed(const std::string & enteredText){};
virtual void textEdited(const std::string & enteredText){};
void textInputed(const std::string & enteredText) override{};
void textEdited(const std::string & enteredText) override{};
//mouse movement handling
bool strongInterest; //if true - report all mouse movements, if not - only when hovered
virtual void mouseMoved (const Point & cursorPosition){}
void mouseMoved (const Point & cursorPosition) override{}
//time handling
virtual void tick(uint32_t msPassed){}
void tick(uint32_t msPassed) override {}
//mouse wheel
virtual void wheelScrolled(bool down, bool in){}
void wheelScrolled(bool down, bool in) override {}
//double click
virtual void onDoubleClick(){}
void onDoubleClick() override {}
// These are the arguments that can be used to determine what kind of input the CIntObject will receive
enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, TEXTINPUT=512, MCLICK=1024, ALL=0xffff};
const ui16 & active;
void addUsedEvents(ui16 newActions);
void removeUsedEvents(ui16 newActions);
@@ -162,7 +200,9 @@ public:
/// called only for windows whenever screen size changes
/// default behavior is to re-center, can be overriden
virtual void onScreenResize();
void onScreenResize() override;
bool isInside(const Point & position) 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
const Rect & center(const Point &p, bool propagate = true); //moves object so that point p will be in its center

View File

@@ -0,0 +1,229 @@
/*
* CGuiHandler.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 "InterfaceEventDispatcher.h"
#include "CIntObject.h"
#include "CGuiHandler.h"
#include "FramerateManager.h"
void InterfaceEventDispatcher::processList(const ui16 mask, const ui16 flag, CIntObjectList *lst, std::function<void (CIntObjectList *)> cb)
{
if (mask & flag)
cb(lst);
}
void InterfaceEventDispatcher::processLists(ui16 activityFlag, std::function<void (CIntObjectList *)> cb)
{
processList(AEventsReceiver::LCLICK,activityFlag,&lclickable,cb);
processList(AEventsReceiver::RCLICK,activityFlag,&rclickable,cb);
processList(AEventsReceiver::MCLICK,activityFlag,&mclickable,cb);
processList(AEventsReceiver::HOVER,activityFlag,&hoverable,cb);
processList(AEventsReceiver::MOVE,activityFlag,&motioninterested,cb);
processList(AEventsReceiver::KEYBOARD,activityFlag,&keyinterested,cb);
processList(AEventsReceiver::TIME,activityFlag,&timeinterested,cb);
processList(AEventsReceiver::WHEEL,activityFlag,&wheelInterested,cb);
processList(AEventsReceiver::DOUBLECLICK,activityFlag,&doubleClickInterested,cb);
processList(AEventsReceiver::TEXTINPUT,activityFlag,&textInterested,cb);
}
void InterfaceEventDispatcher::handleElementActivate(AEventsReceiver * elem, ui16 activityFlag)
{
processLists(activityFlag,[&](CIntObjectList * lst){
lst->push_front(elem);
});
elem->activeState |= activityFlag;
}
void InterfaceEventDispatcher::handleElementDeActivate(AEventsReceiver * elem, ui16 activityFlag)
{
processLists(activityFlag,[&](CIntObjectList * lst){
auto hlp = std::find(lst->begin(),lst->end(),elem);
assert(hlp != lst->end());
lst->erase(hlp);
});
elem->activeState &= ~activityFlag;
}
void InterfaceEventDispatcher::updateTime(uint32_t msPassed)
{
CIntObjectList hlp = timeinterested;
for (auto & elem : hlp)
{
if(!vstd::contains(timeinterested,elem)) continue;
(elem)->tick(msPassed);
}
}
void InterfaceEventDispatcher::dispatchShortcutPressed(const std::vector<EShortcut> & shortcutsVector)
{
bool keysCaptured = false;
for(auto i = keyinterested.begin(); i != keyinterested.end() && GH.continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if((*i)->captureThisKey(shortcut))
keysCaptured = true;
CIntObjectList miCopy = keyinterested;
for(auto i = miCopy.begin(); i != miCopy.end() && GH.continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if(vstd::contains(keyinterested, *i) && (!keysCaptured || (*i)->captureThisKey(shortcut)))
(**i).keyPressed(shortcut);
}
void InterfaceEventDispatcher::dispatchShortcutReleased(const std::vector<EShortcut> & shortcutsVector)
{
bool keysCaptured = false;
for(auto i = keyinterested.begin(); i != keyinterested.end() && GH.continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if((*i)->captureThisKey(shortcut))
keysCaptured = true;
CIntObjectList miCopy = keyinterested;
for(auto i = miCopy.begin(); i != miCopy.end() && GH.continueEventHandling; i++)
for(EShortcut shortcut : shortcutsVector)
if(vstd::contains(keyinterested, *i) && (!keysCaptured || (*i)->captureThisKey(shortcut)))
(**i).keyReleased(shortcut);
}
InterfaceEventDispatcher::CIntObjectList & InterfaceEventDispatcher::getListForMouseButton(MouseButton button)
{
switch (button)
{
case MouseButton::LEFT:
return lclickable;
case MouseButton::RIGHT:
return rclickable;
case MouseButton::MIDDLE:
return mclickable;
}
throw std::runtime_error("Invalid mouse button in getListForMouseButton");
}
void InterfaceEventDispatcher::dispatchMouseButtonPressed(const MouseButton & button, const Point & position)
{
// if (button == MouseButton::LEFT)
// {
// auto doubleClicked = false;
// if(lastClick == getCursorPosition() && (SDL_GetTicks() - lastClickTime) < 300)
// {
// std::list<CIntObject*> hlp = doubleClickInterested;
// for(auto i = hlp.begin(); i != hlp.end() && continueEventHandling; i++)
// {
// if(!vstd::contains(doubleClickInterested, *i)) continue;
// if((*i)->pos.isInside(current.motion.x, current.motion.y))
// {
// (*i)->onDoubleClick();
// doubleClicked = true;
// }
// }
// }
//
// lastClick = current.motion;
// lastClickTime = SDL_GetTicks();
//
// if(doubleClicked)
// return;
// }
handleMouseButtonClick(getListForMouseButton(button), button, true);
}
void InterfaceEventDispatcher::dispatchMouseButtonReleased(const MouseButton & button, const Point & position)
{
handleMouseButtonClick(getListForMouseButton(button), button, false);
}
void InterfaceEventDispatcher::handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed)
{
auto hlp = interestedObjs;
for(auto i = hlp.begin(); i != hlp.end() && GH.continueEventHandling; i++)
{
if(!vstd::contains(interestedObjs, *i)) continue;
auto prev = (*i)->isMouseButtonPressed(btn);
if(!isPressed)
(*i)->currentMouseState[btn] = isPressed;
if((*i)->isInside(GH.getCursorPosition()))
{
if(isPressed)
(*i)->currentMouseState[btn] = isPressed;
(*i)->click(btn, isPressed, prev);
}
else if(!isPressed)
(*i)->click(btn, boost::logic::indeterminate, prev);
}
}
void InterfaceEventDispatcher::dispatchMouseScrolled(const Point & distance, const Point & position)
{
CIntObjectList hlp = wheelInterested;
for(auto i = hlp.begin(); i != hlp.end() && GH.continueEventHandling; i++)
{
if(!vstd::contains(wheelInterested,*i))
continue;
(*i)->wheelScrolled(distance.y < 0, (*i)->isInside(position));
}
}
void InterfaceEventDispatcher::dispatchTextInput(const std::string & text)
{
for(auto it : textInterested)
{
it->textInputed(text);
}
}
void InterfaceEventDispatcher::dispatchTextEditing(const std::string & text)
{
for(auto it : textInterested)
{
it->textEdited(text);
}
}
void InterfaceEventDispatcher::dispatchMouseMoved(const Point & position)
{
//sending active, hovered hoverable objects hover() call
CIntObjectList hlp;
auto hoverableCopy = hoverable;
for(auto & elem : hoverableCopy)
{
if(elem->isInside(GH.getCursorPosition()))
{
if (!(elem)->isHovered())
hlp.push_back((elem));
}
else if ((elem)->isHovered())
{
(elem)->hover(false);
(elem)->hoveredState = false;
}
}
for(auto & elem : hlp)
{
elem->hover(true);
elem->hoveredState = true;
}
//sending active, MotionInterested objects mouseMoved() call
CIntObjectList miCopy = motioninterested;
for(auto & elem : miCopy)
{
if(elem->strongInterestState || elem->isInside(position)) //checking bounds including border fixes bug #2476
{
(elem)->mouseMoved(position);
}
}
}

View File

@@ -0,0 +1,59 @@
/*
* CGuiHandler.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
VCMI_LIB_NAMESPACE_BEGIN
class Point;
VCMI_LIB_NAMESPACE_END
class AEventsReceiver;
enum class MouseButton;
enum class EShortcut;
class InterfaceEventDispatcher
{
using CIntObjectList = std::list<AEventsReceiver *>;
//active GUI elements (listening for events
CIntObjectList lclickable;
CIntObjectList rclickable;
CIntObjectList mclickable;
CIntObjectList hoverable;
CIntObjectList keyinterested;
CIntObjectList motioninterested;
CIntObjectList timeinterested;
CIntObjectList wheelInterested;
CIntObjectList doubleClickInterested;
CIntObjectList textInterested;
CIntObjectList & getListForMouseButton(MouseButton button);
void handleMouseButtonClick(CIntObjectList & interestedObjs, MouseButton btn, bool isPressed);
void processList(const ui16 mask, const ui16 flag, CIntObjectList * lst, std::function<void(CIntObjectList *)> cb);
void processLists(ui16 activityFlag, std::function<void(CIntObjectList *)> cb);
public:
void handleElementActivate(AEventsReceiver * elem, ui16 activityFlag);
void handleElementDeActivate(AEventsReceiver * elem, ui16 activityFlag);
void updateTime(uint32_t msPassed); //handles timeInterested
void dispatchShortcutPressed(const std::vector<EShortcut> & shortcuts);
void dispatchShortcutReleased(const std::vector<EShortcut> & shortcuts);
void dispatchMouseButtonPressed(const MouseButton & button, const Point & position);
void dispatchMouseButtonReleased(const MouseButton & button, const Point & position);
void dispatchMouseScrolled(const Point & distance, const Point & position);
void dispatchMouseMoved(const Point & position);
void dispatchTextInput(const std::string & text);
void dispatchTextEditing(const std::string & text);
};

View File

@@ -109,12 +109,8 @@ void WindowHandler::simpleRedraw()
void WindowHandler::onScreenResize()
{
for(const auto & entry : windowsStack)
{
auto intObject = std::dynamic_pointer_cast<CIntObject>(entry);
entry->onScreenResize();
if(intObject)
intObject->onScreenResize();
}
totalRedraw();
}

View File

@@ -90,7 +90,7 @@ CSelectionBase::CSelectionBase(ESelectionScreen type)
void CSelectionBase::toggleTab(std::shared_ptr<CIntObject> tab)
{
if(curTab && curTab->active)
if(curTab && curTab->isActive())
{
curTab->deactivate();
curTab->recActions = 0;

View File

@@ -397,21 +397,16 @@ void TemplatesDropBox::ListItem::hover(bool on)
if(h && w)
{
if(w->getText().empty())
{
hovered = false;
h->visible = false;
}
else
{
h->visible = on;
}
}
redraw();
}
void TemplatesDropBox::ListItem::clickLeft(tribool down, bool previousState)
{
if(down && hovered)
if(down && isHovered())
{
dropBox.setTemplate(item);
}
@@ -469,19 +464,14 @@ void TemplatesDropBox::sliderMove(int slidPos)
redraw();
}
void TemplatesDropBox::hover(bool on)
{
hovered = on;
}
void TemplatesDropBox::clickLeft(tribool down, bool previousState)
{
if(down && !hovered)
if(down && !isActive())
{
auto w = widget<CSlider>("slider");
// pop the interface only if the mouse is not clicking on the slider
if (!w || !w->mouseState(MouseButton::LEFT))
if (!w || !w->isMouseButtonPressed(MouseButton::LEFT))
{
assert(GH.windows().isTopWindow(this));
GH.windows().popWindows(1);

View File

@@ -70,7 +70,6 @@ class TemplatesDropBox : public InterfaceObjectConfigurable
public:
TemplatesDropBox(RandomMapTab & randomMapTab, int3 size);
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override;
void setTemplate(const CRmgTemplate *);

View File

@@ -408,7 +408,7 @@ void SelectionTab::select(int position)
rememberCurrentSelection();
if(inputName && inputName->active)
if(inputName && inputName->isActive())
{
auto filename = *CResourceHandler::get("local")->getResourceName(ResourceID(curItems[py]->fileURI, EResType::CLIENT_SAVEGAME));
inputName->setText(filename.stem().string());

View File

@@ -119,7 +119,7 @@ void CCampaignScreen::CCampaignButton::show(SDL_Surface * to)
CIntObject::show(to);
// Play the campaign button video when the mouse cursor is placed over the button
if(hovered)
if(isHovered())
{
if(CCS->videoh->fname != video)
CCS->videoh->open(video);

View File

@@ -54,7 +54,7 @@ void CButton::update()
newPos = (int)image->size()-1;
image->setFrame(newPos);
if (active)
if (isActive())
redraw();
}
@@ -177,7 +177,7 @@ void CButton::clickLeft(tribool down, bool previousState)
CCS->soundh->playSound(soundBase::button);
setState(PRESSED);
}
else if(hoverable && hovered)
else if(hoverable && isHovered())
setState(HIGHLIGHTED);
else
setState(NORMAL);
@@ -492,7 +492,7 @@ void CVolumeSlider::moveTo(int id)
vstd::abetween<int>(id, 0, animImage->size() - 1);
animImage->setFrame(id);
animImage->moveTo(Point(pos.x + (animImage->pos.w + 1) * id, pos.y));
if (active)
if (isActive())
redraw();
}
@@ -550,7 +550,7 @@ void CVolumeSlider::wheelScrolled(bool down, bool in)
void CSlider::sliderClicked()
{
if(!(active & MOVE))
if(!isActive(MOVE))
addUsedEvents(MOVE);
}
@@ -688,11 +688,11 @@ void CSlider::clickLeft(tribool down, bool previousState)
return;
// if (rw>1) return;
// if (rw<0) return;
slider->clickLeft(true, slider->mouseState(MouseButton::LEFT));
slider->clickLeft(true, slider->isMouseButtonPressed(MouseButton::LEFT));
moveTo((int)(rw * positions + 0.5));
return;
}
if(active & MOVE)
if(isActive(MOVE))
removeUsedEvents(MOVE);
}
@@ -710,7 +710,7 @@ CSlider::CSlider(Point position, int totalw, std::function<void(int)> Moved, int
vstd::amax(value, 0);
vstd::amin(value, positions);
strongInterest = true;
setMoveEventStrongInterest(true);
pos.x += position.x;
pos.y += position.y;

View File

@@ -213,7 +213,7 @@ void CHeroArtPlace::showAll(SDL_Surface* to)
CIntObject::showAll(to);
}
if(marked && active)
if(marked && isActive())
{
// Draw vertical bars.
for(int i = 0; i < pos.h; ++i)

View File

@@ -169,7 +169,7 @@ void CArtifactsOfHeroBase::scrollBackpackForArtSet(int offset, const CArtifactSe
void CArtifactsOfHeroBase::safeRedraw()
{
if(active)
if(isActive())
{
if(parent)
parent->redraw();

View File

@@ -238,7 +238,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
if(artSetPtr)
{
const auto hero = artSetPtr->getHero();
if(artSetPtr->active)
if(artSetPtr->isActive())
{
if(pickedArtInst)
{

View File

@@ -35,7 +35,7 @@ std::shared_ptr<CIntObject> CObjectList::createItem(size_t index)
item->recActions = defActions;
addChild(item.get());
if (active)
if (isActive())
item->activate();
return item;
}
@@ -70,7 +70,7 @@ void CTabbedInt::reset()
activeTab = createItem(activeID);
activeTab->moveTo(pos.topLeft());
if(active)
if(isActive())
redraw();
}
@@ -107,7 +107,7 @@ void CListBox::updatePositions()
(elem)->moveTo(itemPos);
itemPos += itemOffset;
}
if (active)
if (isActive())
{
redraw();
if (slider)

View File

@@ -446,7 +446,7 @@ void CGStatusBar::clickLeft(tribool down, bool previousState)
{
if(!down)
{
if(LOCPLINT && LOCPLINT->cingconsole->active)
if(LOCPLINT && LOCPLINT->cingconsole->isActive())
LOCPLINT->cingconsole->startEnteringText();
}
}
@@ -749,7 +749,7 @@ void CFocusable::moveFocus()
if(i == focusables.end())
i = focusables.begin();
if((*i)->active)
if((*i)->isActive())
{
(*i)->giveFocus();
break;

View File

@@ -115,12 +115,12 @@ void CBuildingRect::hover(bool on)
{
if(on)
{
if(!(active & MOVE))
if(!isActive(MOVE))
addUsedEvents(MOVE);
}
else
{
if(active & MOVE)
if(isActive(MOVE))
removeUsedEvents(MOVE);
if(parent->selectedBuilding == this)
@@ -218,7 +218,7 @@ void CBuildingRect::showAll(SDL_Surface * to)
return;
CShowableAnim::showAll(to);
if(!active && parent->selectedBuilding == this && border)
if(!isActive() && parent->selectedBuilding == this && border)
border->draw(to, pos.x, pos.y);
}
@@ -1577,7 +1577,6 @@ void LabeledValue::hover(bool on)
else
{
GH.statusbar()->clear();
parent->hovered = false;
}
}

View File

@@ -972,6 +972,6 @@ std::shared_ptr<CIntObject> CHeroItem::onTabSelected(size_t index)
void CHeroItem::onArtChange(int tabIndex)
{
//redraw item after background change
if(active)
if(isActive())
redraw();
}