Commit 62587b5f authored by Stefan Majewsky's avatar Stefan Majewsky

Move the event-sequence maintenance from InteractorManager to Interactor.

svn path=/trunk/KDE/kdegames/palapeli/; revision=1118464
parent af5d7f6e
......@@ -4,9 +4,9 @@ set_directory_properties(PROPERTIES COMPILE_DEFINITIONS USE_LOCAL_LIBPALA)
set(palapeli_SRCS
config/configdialog.cpp
config/elidinglabel.cpp
config/mouseinputbutton.cpp
config/triggerconfigwidget.cpp
config/triggerlistview.cpp
#config/mouseinputbutton.cpp
#config/triggerconfigwidget.cpp
#config/triggerlistview.cpp
creator/propertywidget.cpp
creator/puzzlecreator.cpp
creator/slicerconfwidget.cpp
......
......@@ -43,22 +43,14 @@ QList<Palapeli::ConstraintInteractor::Side> Palapeli::ConstraintInteractor::touc
return result;
}
bool Palapeli::ConstraintInteractor::acceptMousePosition(const QPoint& pos)
bool Palapeli::ConstraintInteractor::startInteraction(const Palapeli::MouseEvent& event)
{
if (!scene())
return false;
if (!m_draggingSides.isEmpty())
return true; //dragging in progress
//check mouse position
return !touchingSides(view()->mapToScene(pos)).isEmpty();
}
void Palapeli::ConstraintInteractor::mousePressEvent(const Palapeli::MouseEvent& event)
{
if (!scene())
return;
//determine touching sides
m_draggingSides = touchingSides(event.scenePos);
if (m_draggingSides.isEmpty())
return false;
//record the position where we grabbed the handles (more precisely: its distance to the sides of the scene rect)
m_baseSceneRectOffset = QPointF();
const QRectF sceneRect = scene()->sceneRect();
......@@ -70,9 +62,10 @@ void Palapeli::ConstraintInteractor::mousePressEvent(const Palapeli::MouseEvent&
m_baseSceneRectOffset.ry() = event.scenePos.y() - sceneRect.top();
else if (m_draggingSides.contains(BottomSide))
m_baseSceneRectOffset.ry() = event.scenePos.y() - sceneRect.bottom();
return true;
}
void Palapeli::ConstraintInteractor::mouseMoveEvent(const Palapeli::MouseEvent& event)
void Palapeli::ConstraintInteractor::continueInteraction(const Palapeli::MouseEvent& event)
{
//in this method, we need the scene() as Palapeli::Scene for the piecesBoundingRect
Palapeli::Scene* scene = qobject_cast<Palapeli::Scene*>(this->scene());
......@@ -92,7 +85,7 @@ void Palapeli::ConstraintInteractor::mouseMoveEvent(const Palapeli::MouseEvent&
scene->setSceneRect(sceneRect | scene->piecesBoundingRect());
}
void Palapeli::ConstraintInteractor::mouseReleaseEvent(const Palapeli::MouseEvent& event)
void Palapeli::ConstraintInteractor::stopInteraction(const Palapeli::MouseEvent& event)
{
Q_UNUSED(event)
m_draggingSides.clear();
......
......@@ -28,10 +28,9 @@ namespace Palapeli
public:
ConstraintInteractor(QGraphicsView* view);
protected:
virtual bool acceptMousePosition(const QPoint& pos);
virtual void mousePressEvent(const Palapeli::MouseEvent& event);
virtual void mouseMoveEvent(const Palapeli::MouseEvent& event);
virtual void mouseReleaseEvent(const Palapeli::MouseEvent& event);
virtual bool startInteraction(const Palapeli::MouseEvent& event);
virtual void continueInteraction(const Palapeli::MouseEvent& event);
virtual void stopInteraction(const Palapeli::MouseEvent& event);
private:
enum Side { LeftSide = 0, RightSide, TopSide, BottomSide };
QList<Side> touchingSides(const QPointF& scenePos) const;
......
......@@ -18,10 +18,11 @@
#include "interactor.h"
Palapeli::Interactor::Interactor(Palapeli::InteractorTypes types, QGraphicsView* view)
: m_types(types)
Palapeli::Interactor::Interactor(Palapeli::InteractorType type, QGraphicsView* view)
: m_type(type)
, m_view(view)
, m_scene(view->scene())
, m_active(false)
, m_category(NoCategory)
{
}
......@@ -30,19 +31,9 @@ Palapeli::Interactor::~Interactor()
{
}
bool Palapeli::Interactor::isMouseInteractor() const
Palapeli::InteractorType Palapeli::Interactor::interactorType() const
{
return m_types && Palapeli::MouseInteractor;
}
bool Palapeli::Interactor::isWheelInteractor() const
{
return m_types && Palapeli::WheelInteractor;
}
Palapeli::InteractorTypes Palapeli::Interactor::interactorTypes() const
{
return m_types;
return m_type;
}
Palapeli::Interactor::Category Palapeli::Interactor::category() const
......@@ -73,6 +64,7 @@ void Palapeli::Interactor::updateScene()
QGraphicsScene* newScene = m_view->scene();
if (oldScene != newScene)
{
setInactive();
m_scene = newScene;
sceneChangeEvent(oldScene, newScene);
}
......@@ -88,32 +80,40 @@ QGraphicsScene* Palapeli::Interactor::scene() const
return m_scene;
}
bool Palapeli::Interactor::handleEvent(const Palapeli::MouseEvent& event, QEvent::Type type)
bool Palapeli::Interactor::isActive() const
{
return m_active;
}
void Palapeli::Interactor::setInactive()
{
//resend last event as release event
if (m_active)
{
stopInteraction(m_lastMouseEvent);
m_active = false;
}
}
void Palapeli::Interactor::sendEvent(const Palapeli::MouseEvent& event, Palapeli::EventProcessingFlags flags)
{
if (!acceptMousePosition(event.pos))
return false;
switch (type)
//conclude interaction
if (flags & Palapeli::EventConcludesInteraction || !(flags & Palapeli::EventMatches))
{
case QEvent::MouseMove:
mouseMoveEvent(event);
return true;
case QEvent::MouseButtonPress:
case QEvent::KeyPress:
mousePressEvent(event);
return true;
case QEvent::MouseButtonRelease:
case QEvent::KeyRelease:
mouseReleaseEvent(event);
return true;
default:
return false;
setInactive();
return;
}
//check if caller attempts to start new interaction chain while an old one is still in progress
if (flags & Palapeli::EventStartsInteraction)
setInactive();
//handle event, thereby starting a new interaction if necessary
if (m_active)
continueInteraction(event);
else
m_active = startInteraction(event);
}
bool Palapeli::Interactor::handleEvent(const Palapeli::WheelEvent& event)
void Palapeli::Interactor::sendEvent(const Palapeli::WheelEvent& event)
{
if (!acceptMousePosition(event.pos))
return false;
wheelEvent(event);
return true;
doInteraction(event);
}
......@@ -30,10 +30,9 @@ namespace Palapeli
{
enum InteractorType
{
MouseInteractor = 0x1,
WheelInteractor = 0x2
MouseInteractor = 1,
WheelInteractor = 2
};
Q_DECLARE_FLAGS(InteractorTypes, InteractorType)
class Interactor
{
......@@ -46,35 +45,40 @@ namespace Palapeli
Category category() const;
QString description() const;
QIcon icon() const;
Palapeli::InteractorType interactorType() const;
bool isMouseInteractor() const;
bool isWheelInteractor() const;
Palapeli::InteractorTypes interactorTypes() const;
bool isActive() const;
void setInactive();
void sendEvent(const Palapeli::MouseEvent& event, Palapeli::EventProcessingFlags flags);
void sendEvent(const Palapeli::WheelEvent& event);
bool handleEvent(const Palapeli::MouseEvent& event, QEvent::Type type);
bool handleEvent(const Palapeli::WheelEvent& event);
///Call this method when the view for this interactor sets a different scene.
void updateScene();
protected:
Interactor(Palapeli::InteractorTypes types, QGraphicsView* view);
Interactor(Palapeli::InteractorType type, QGraphicsView* view);
void setMetadata(Category category, const QString& description, const QIcon& icon);
QGraphicsView* view() const;
QGraphicsScene* scene() const;
///This method is always called shortly before an event is delivered to the interactor. The parameter \a pos is the position of the mouse cursor on the view. Return false to abort event processing in this interactor. The default implementation returns true, indicating that the interactor handles all events, regardless of the mouse position.
virtual bool acceptMousePosition(const QPoint& pos) { Q_UNUSED(pos) return true; }
virtual void mouseMoveEvent(const Palapeli::MouseEvent& event) { Q_UNUSED(event) }
virtual void mousePressEvent(const Palapeli::MouseEvent& event) { Q_UNUSED(event) }
virtual void mouseReleaseEvent(const Palapeli::MouseEvent& event) { Q_UNUSED(event) }
virtual void wheelEvent(const Palapeli::WheelEvent& event) { Q_UNUSED(event) }
///This corresponds to a mousePressEvent. Return false unless you want to accept this interaction. The default implementation does nothing and accepts all interactions.
virtual bool startInteraction(const Palapeli::MouseEvent& event) { Q_UNUSED(event) return true; }
///This corresponds to a mouseMoveEvent.
virtual void continueInteraction(const Palapeli::MouseEvent& event) { Q_UNUSED(event) }
///This corresponds to a mouseRelease.
virtual void stopInteraction(const Palapeli::MouseEvent& event) { Q_UNUSED(event) }
///This corresponds to a wheelEvent
virtual void doInteraction(const Palapeli::WheelEvent& event) { Q_UNUSED(event) }
///This method is called whenever the view() changes its scene. Both parameters may be null pointers, indicating that the view had no scene up to now, or that the view will have no scene after this operation.
virtual void sceneChangeEvent(QGraphicsScene* oldScene, QGraphicsScene* newScene) { Q_UNUSED(oldScene) Q_UNUSED(newScene) }
private:
Palapeli::InteractorTypes m_types;
Palapeli::InteractorType m_type;
//context
QGraphicsView* m_view;
QGraphicsScene* m_scene;
//state
bool m_active;
Palapeli::MouseEvent m_lastMouseEvent;
//metadata
Category m_category;
QString m_description;
......@@ -82,7 +86,6 @@ namespace Palapeli
};
}
Q_DECLARE_OPERATORS_FOR_FLAGS(Palapeli::InteractorTypes)
Q_DECLARE_METATYPE(Palapeli::Interactor*)
#endif // PALAPELI_INTERACTOR_H
......@@ -57,8 +57,7 @@ void Palapeli::InteractorManager::updateScene()
}
/*
* We start with the simple case: Wheel events are delivered to all interactors
* that accept them.
* Wheel events are delivered to all interactors that accept them.
*/
void Palapeli::InteractorManager::handleEvent(QWheelEvent* event)
{
......@@ -66,28 +65,19 @@ void Palapeli::InteractorManager::handleEvent(QWheelEvent* event)
Palapeli::WheelEvent pEvent(m_view, event->pos(), event->delta());
//try to handle event
foreach (const Palapeli::AssociatedInteractorTrigger& aTrigger, m_triggers)
{
if (!testTrigger(aTrigger.first, event))
continue;
if (aTrigger.second->handleEvent(pEvent))
return;
}
if (testTrigger(aTrigger.first, event) & Palapeli::EventMatches)
aTrigger.second->sendEvent(pEvent);
}
/*
* Unlike wheel events, mouse events are not just delivered to all interactors
* that may accept them. Mouse interactions usually consist of a series of
* press-move-move-...-release events, and we deliver all events of one series
* to exactly one interactor. The only exception is that events with multiple
* buttons can be delivered to multiple interactors to handle all buttons.
* that may accept them. Mouse interactions usually consist of a sequence of
* press-move-move-...-release events, and we deliver all events of one sequence
* to exactly one interactor. The Interactor class manages the activity flag
* involved in this operation, and completes incomplete event sequences.
*/
void Palapeli::InteractorManager::handleEvent(QMouseEvent* event)
{
//determine all triggers which are activated by this event
QList<Palapeli::AssociatedInteractorTrigger> matchingTriggers(m_triggers);
for (int i = 0; i < matchingTriggers.size(); ++i)
if (!testTrigger(matchingTriggers[i].first, event))
matchingTriggers.removeAt(i--); //decrement because another trigger is at this index after the removeAt()
//convert event
Palapeli::MouseEvent pEvent(m_view, event->pos());
//save button state (this information is needed for key events *following* this event, but not available from them)
......@@ -95,142 +85,149 @@ void Palapeli::InteractorManager::handleEvent(QMouseEvent* event)
if (event->type() != QEvent::MouseButtonRelease)
m_buttons |= event->button();
m_mousePos = event->pos();
//find all keys which need to be handled
QMap<Qt::MouseButton, QEvent::Type> unhandledButtons;
switch (event->type())
//check which triggers are activated by this event
QMap<Palapeli::Interactor*, EventContext> interactorData;
foreach (const Palapeli::AssociatedInteractorTrigger& trigger, m_triggers)
{
case QEvent::MouseButtonPress:
case QEvent::MouseButtonRelease:
unhandledButtons.insert(event->button(), event->type());
//FALL THROUGH (We need to interpret press/release events as move events for all other buttons, in order to keep the active triggers.)
case QEvent::MouseMove:
foreach (Qt::MouseButton button, Palapeli::analyzeFlags(event->buttons()))
if (!unhandledButtons.contains(button))
unhandledButtons.insert(button, QEvent::MouseMove);
unhandledButtons.insert(Qt::NoButton, QEvent::MouseMove);
break;
default:
return;
//NOTE: One interactor may have multiple triggers, so we OR stuff together.
const Palapeli::EventProcessingFlags flags = testTrigger(trigger.first, event);
interactorData[trigger.second].flags |= flags;
if (flags & Palapeli::EventMatches)
interactorData[trigger.second].triggeringButtons |= trigger.first.button();
}
//further processing in a method which is shared with the KeyEvent handler
handleMouseEvent(pEvent, matchingTriggers, unhandledButtons);
handleEventCommon(pEvent, interactorData, event->buttons() | event->button());
}
/*
* We also need to process KeyPress and KeyRelease events for all triggers with
* NoButton and NoOrientation. The MousePress-MouseMove-...-MouseRelease event
* series becomes KeyPress-MouseMove-...-KeyRelease in this case (where KeyPress
* and KeyRelease are for modifiers).
* We also need to process KeyPress and KeyRelease events for modifier changes.
*/
void Palapeli::InteractorManager::handleEvent(QKeyEvent* event)
{
//determine all triggers which are activated by this event
QList<Palapeli::AssociatedInteractorTrigger> matchingTriggers(m_triggers);
for (int i = 0; i < matchingTriggers.size(); ++i)
if (!testTrigger(matchingTriggers[i].first, event))
matchingTriggers.removeAt(i--); //decrement because another trigger is at this index after the removeAt()
//convert event
Palapeli::MouseEvent pEvent(m_view, m_mousePos);
//find all keys which need to be handled
QMap<Qt::MouseButton, QEvent::Type> unhandledButtons;
foreach (Qt::MouseButton button, Palapeli::analyzeFlags(m_buttons))
unhandledButtons.insert(button, event->type());
unhandledButtons.insert(Qt::NoButton, event->type());
//further processing in a method which is shared with the MouseEvent handler
handleMouseEvent(pEvent, matchingTriggers, unhandledButtons);
//check which triggers are activated by this event
QMap<Palapeli::Interactor*, EventContext> interactorData;
foreach (const Palapeli::AssociatedInteractorTrigger& trigger, m_triggers)
{
//NOTE: One interactor may have multiple triggers, so we OR all flags together.
interactorData[trigger.second].flags |= testTrigger(trigger.first, event);
interactorData[trigger.second].triggeringButtons |= trigger.first.button();
}
//further processing in a method which is shared with the KeyEvent handler
handleEventCommon(pEvent, interactorData, m_buttons);
}
/*
* This is the common base for handleEvent(QMouseEvent*) and handleEvent(QKeyEvent*).
*/
void Palapeli::InteractorManager::handleMouseEvent(const Palapeli::MouseEvent& pEvent, QList<Palapeli::AssociatedInteractorTrigger>& matchingTriggers, QMap<Qt::MouseButton, QEvent::Type>& unhandledButtons)
void Palapeli::InteractorManager::handleEventCommon(const Palapeli::MouseEvent& pEvent, QMap<Palapeli::Interactor*, EventContext>& interactorData, Qt::MouseButtons unhandledButtons)
{
//try to use active triggers where possible
QList<Palapeli::AssociatedInteractorTrigger> activeTriggersCopy(m_activeTriggers);
foreach (const Palapeli::AssociatedInteractorTrigger& activeTrigger, activeTriggersCopy)
{
const Qt::MouseButton triggerButton = activeTrigger.first.button();
QEvent::Type eventType = unhandledButtons.value(triggerButton, QEvent::None);
bool keepTrigger = matchingTriggers.contains(activeTrigger);
if (keepTrigger && eventType != QEvent::None)
//event matches active trigger -> deliver event
keepTrigger = activeTrigger.second->handleEvent(pEvent, eventType);
else
keepTrigger = false;
//check if event has been accepted
if (keepTrigger)
{
if (triggerButton != Qt::NoButton)
unhandledButtons.remove(triggerButton);
}
if (eventType == QEvent::MouseButtonRelease)
m_activeTriggers.removeAll(activeTrigger);
else if (!keepTrigger)
foreach (Palapeli::Interactor* interactor, m_interactors)
if (interactor->isActive())
{
activeTrigger.second->handleEvent(pEvent, QEvent::MouseButtonRelease);
m_activeTriggers.removeAll(activeTrigger);
//fetch flags, and remove them to mark this interactor as processed
EventContext context = interactorData.value(interactor);
interactorData.remove(interactor);
//send event, mark button as processed
if ((unhandledButtons & context.triggeringButtons) || context.triggeringButtons == Qt::NoButton)
{
interactor->sendEvent(pEvent, context.flags);
if (interactor->isActive())
unhandledButtons &= ~context.triggeringButtons;
}
}
matchingTriggers.removeAll(activeTrigger); //no need to check this trigger again below
}
//try to find matching triggers for those buttons that have not been handled by the active triggers, and make these triggers active
foreach (const Palapeli::AssociatedInteractorTrigger& trigger, matchingTriggers)
//try to activate interactors with matching triggers
QMutableMapIterator<Palapeli::Interactor*, EventContext> iter(interactorData);
while (iter.hasNext())
{
const Qt::MouseButton triggerButton = trigger.first.button();
QEvent::Type eventType = unhandledButtons.value(triggerButton, QEvent::None);
if (eventType == QEvent::None)
continue; //this trigger button has been handled by an active trigger
//try to handle this event
bool eventHandled = true;
if (eventType == QEvent::MouseMove)
//always start with mousePressEvent
eventHandled = trigger.second->handleEvent(pEvent, QEvent::MouseButtonPress);
if (eventHandled)
eventHandled = trigger.second->handleEvent(pEvent, eventType);
if (eventHandled)
Palapeli::Interactor* interactor = iter.next().key();
const EventContext context = iter.value();
//send event, mark button as processed
if ((unhandledButtons & context.triggeringButtons) || context.triggeringButtons == Qt::NoButton)
{
if (triggerButton != Qt::NoButton)
unhandledButtons.remove(triggerButton);
m_activeTriggers << trigger;
interactor->sendEvent(pEvent, context.flags);
if (interactor->isActive())
unhandledButtons &= ~context.triggeringButtons;
}
else
interactor->setInactive();
}
}
bool Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QWheelEvent* event)
Palapeli::EventProcessingFlags Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QWheelEvent* event)
{
if (!trigger.isValid())
return false;
return trigger.modifiers() == event->modifiers()
&& trigger.wheelDirection() == event->orientation()
&& trigger.wheelDirection() != 0;
if (trigger.isValid())
{
const bool testModifiers = trigger.modifiers() == event->modifiers();
const bool checkDirection = trigger.wheelDirection() != 0;
const bool testDirection = trigger.wheelDirection() == event->orientation();
if (testModifiers && checkDirection && testDirection)
return Palapeli::EventMatches;
}
//if execution comes to this point, trigger does not match
return 0;
}
bool Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QMouseEvent* event)
Palapeli::EventProcessingFlags Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QMouseEvent* event)
{
if (!trigger.isValid())
return false;
if (trigger.wheelDirection() != 0 || trigger.modifiers() != event->modifiers())
return false;
if (trigger.button() == Qt::NoButton)
return true;
else if (event->type() == QEvent::MouseMove)
return event->buttons() & trigger.button();
else
return (event->button() | event->buttons()) & trigger.button();
if (trigger.isValid())
{
const bool testModifiers = trigger.modifiers() == event->modifiers();
const bool checkDirection = trigger.wheelDirection() == 0;
if (testModifiers && checkDirection)
{
if (trigger.button() == Qt::NoButton)
//trigger matches
return Palapeli::EventMatches;
const bool checkButtons = (event->button() | event->buttons()) & trigger.button();
if (checkButtons)
{
//trigger matches - construct result
Palapeli::EventProcessingFlags result = Palapeli::EventMatches;
if (event->button() == trigger.button())
{
if (event->type() == QEvent::MouseButtonPress)
result |= Palapeli::EventStartsInteraction;
if (event->type() == QEvent::MouseButtonRelease)
result |= Palapeli::EventConcludesInteraction;
}
return result;
}
}
}
//if execution comes to this point, trigger does not match
return 0;
}
bool Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QKeyEvent* event)
Palapeli::EventProcessingFlags Palapeli::InteractorManager::testTrigger(const Palapeli::InteractorTrigger& trigger, QKeyEvent* event)
{
if (!trigger.isValid())
return false;
//read modifiers
Qt::KeyboardModifiers modifiers = event->modifiers();
const Qt::Key key = (Qt::Key) event->key();
if (m_keyModifierMap.contains(key))
modifiers |= m_keyModifierMap[key];
//checking
return trigger.modifiers() == modifiers
&& trigger.button() == Qt::NoButton
&& trigger.wheelDirection() == 0;
if (trigger.isValid())
{
//read modifiers
const Qt::KeyboardModifier keyModifier = m_keyModifierMap.value((Qt::Key) event->key(), Qt::NoModifier);
const Qt::KeyboardModifiers modifiers = keyModifier | event->modifiers();
//checking
const bool testModifiers = trigger.modifiers() == modifiers;
const bool checkDirection = trigger.wheelDirection() == 0;
const bool checkButton = trigger.button() & m_buttons;
if (testModifiers && checkDirection && checkButton)
{
//trigger matches - construct result
Palapeli::EventProcessingFlags result = Palapeli::EventMatches;
if (keyModifier != Qt::NoModifier)
{
if (event->type() == QEvent::KeyPress)
result |= Palapeli::EventStartsInteraction;
if (event->type() == QEvent::KeyRelease)
result |= Palapeli::EventConcludesInteraction;
}
return result;
}
}
//if execution comes to this point, trigger does not match
return 0;
}
//BEGIN API to configuration UI
......@@ -247,7 +244,8 @@ const QList<Palapeli::AssociatedInteractorTrigger> Palapeli::InteractorManager::
void Palapeli::InteractorManager::setTriggers(const QList<Palapeli::AssociatedInteractorTrigger>& triggers)
{
m_activeTriggers.clear();
foreach (Palapeli::Interactor* interactor, m_interactors)
interactor->setInactive();
m_triggers = triggers;
//TODO: write triggers to config file
}
......
......@@ -43,18 +43,22 @@ namespace Palapeli
const QList<Palapeli::AssociatedInteractorTrigger> triggers() const;
void setTriggers(const QList<Palapeli::AssociatedInteractorTrigger>& triggers);
protected:
bool testTrigger(const Palapeli::InteractorTrigger& trigger, QWheelEvent* event);
bool testTrigger(const Palapeli::InteractorTrigger& trigger, QMouseEvent* event);
bool testTrigger(const Palapeli::InteractorTrigger& trigger, QKeyEvent* event);
Palapeli::EventProcessingFlags testTrigger(const Palapeli::InteractorTrigger& trigger, QWheelEvent* event);
Palapeli::EventProcessingFlags testTrigger(const Palapeli::InteractorTrigger& trigger, QMouseEvent* event);
Palapeli::EventProcessingFlags testTrigger(const Palapeli::InteractorTrigger& trigger, QKeyEvent* event);
void handleMouseEvent(const Palapeli::MouseEvent& pEvent, QList<Palapeli::AssociatedInteractorTrigger>& matchingTriggers, QMap<Qt::MouseButton, QEvent::Type>& unhandledButtons);
struct EventContext
{
Palapeli::EventProcessingFlags flags;
Qt::MouseButtons triggeringButtons;
};
void handleEventCommon(const Palapeli::MouseEvent& pEvent, QMap<Palapeli::Interactor*, EventContext>& interactorData, Qt::MouseButtons unhandledButtons);
private:
QGraphicsView* m_view;
QMap<QByteArray, Palapeli::Interactor*> m_interactors; //NOTE: The interactor list is always hard-coded, based on what is available. The keys are used for writing the trigger list to the config.
//configuration
QList<Palapeli::AssociatedInteractorTrigger> m_triggers;
//state
QList<Palapeli::AssociatedInteractorTrigger> m_activeTriggers;
Qt::MouseButtons m_buttons;
QPoint m_mousePos;
//quasi-static data
......
......@@ -35,33 +35,15 @@ Palapeli::MovePieceInteractor::MovePieceInteractor(QGraphicsView* view)
static QGraphicsItem* findSelectableItemAt(const QPointF& scenePos, QGraphicsScene* scene)
{