summaryrefslogtreecommitdiff
path: root/silx/gui/plot/Interaction.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/Interaction.py')
-rw-r--r--silx/gui/plot/Interaction.py120
1 files changed, 85 insertions, 35 deletions
diff --git a/silx/gui/plot/Interaction.py b/silx/gui/plot/Interaction.py
index 358af74..6213889 100644
--- a/silx/gui/plot/Interaction.py
+++ b/silx/gui/plot/Interaction.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2014-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2014-2020 European Synchrotron Radiation Facility
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -137,6 +137,11 @@ class State(object):
"""
pass
+ def validate(self):
+ """Called externally to validate the current interaction in case of a
+ creation.
+ """
+ pass
class StateMachine(object):
"""State machine controller.
@@ -191,6 +196,12 @@ class StateMachine(object):
if handler is not None:
return handler(*args, **kwargs)
+ def validate(self):
+ """Called externally to validate the current interaction in case of a
+ creation.
+ """
+ self.state.validate()
+
# clickOrDrag #################################################################
@@ -209,92 +220,131 @@ class ClickOrDrag(StateMachine):
It is intended to be used through subclassing by overriding
:meth:`click`, :meth:`beginDrag`, :meth:`drag` and :meth:`endDrag`.
+
+ :param Set[str] clickButtons: Set of buttons that provides click interaction
+ :param Set[str] dragButtons: Set of buttons that provides drag interaction
"""
DRAG_THRESHOLD_SQUARE_DIST = 5 ** 2
class Idle(State):
def onPress(self, x, y, btn):
- if btn == LEFT_BTN:
- self.goto('clickOrDrag', x, y)
+ if btn in self.machine.dragButtons:
+ self.goto('clickOrDrag', x, y, btn)
return True
- elif btn == RIGHT_BTN:
- self.goto('rightClick', x, y)
+ elif btn in self.machine.clickButtons:
+ self.goto('click', x, y, btn)
return True
- class RightClick(State):
+ class Click(State):
+ def enterState(self, x, y, btn):
+ self.initPos = x, y
+ self.button = btn
+
def onMove(self, x, y):
- self.goto('idle')
+ dx2 = (x - self.initPos[0]) ** 2
+ dy2 = (y - self.initPos[1]) ** 2
+ if (dx2 + dy2) >= self.machine.DRAG_THRESHOLD_SQUARE_DIST:
+ self.goto('idle')
def onRelease(self, x, y, btn):
- if btn == RIGHT_BTN:
+ if btn == self.button:
self.machine.click(x, y, btn)
self.goto('idle')
class ClickOrDrag(State):
- def enterState(self, x, y):
+ def enterState(self, x, y, btn):
self.initPos = x, y
+ self.button = btn
def onMove(self, x, y):
dx2 = (x - self.initPos[0]) ** 2
dy2 = (y - self.initPos[1]) ** 2
if (dx2 + dy2) >= self.machine.DRAG_THRESHOLD_SQUARE_DIST:
- self.goto('drag', self.initPos, (x, y))
+ self.goto('drag', self.initPos, (x, y), self.button)
def onRelease(self, x, y, btn):
- if btn == LEFT_BTN:
- self.machine.click(x, y, btn)
+ if btn == self.button:
+ if btn in self.machine.clickButtons:
+ self.machine.click(x, y, btn)
self.goto('idle')
class Drag(State):
- def enterState(self, initPos, curPos):
+ def enterState(self, initPos, curPos, btn):
self.initPos = initPos
- self.machine.beginDrag(*initPos)
- self.machine.drag(*curPos)
+ self.button = btn
+ self.machine.beginDrag(*initPos, btn)
+ self.machine.drag(*curPos, btn)
def onMove(self, x, y):
- self.machine.drag(x, y)
+ self.machine.drag(x, y, self.button)
def onRelease(self, x, y, btn):
- if btn == LEFT_BTN:
- self.machine.endDrag(self.initPos, (x, y))
+ if btn == self.button:
+ self.machine.endDrag(self.initPos, (x, y), btn)
self.goto('idle')
- def __init__(self):
+ def __init__(self,
+ clickButtons=(LEFT_BTN, RIGHT_BTN),
+ dragButtons=(LEFT_BTN,)):
states = {
- 'idle': ClickOrDrag.Idle,
- 'rightClick': ClickOrDrag.RightClick,
- 'clickOrDrag': ClickOrDrag.ClickOrDrag,
- 'drag': ClickOrDrag.Drag
+ 'idle': self.Idle,
+ 'click': self.Click,
+ 'clickOrDrag': self.ClickOrDrag,
+ 'drag': self.Drag
}
+ self.__clickButtons = set(clickButtons)
+ self.__dragButtons = set(dragButtons)
super(ClickOrDrag, self).__init__(states, 'idle')
+ clickButtons = property(lambda self: self.__clickButtons,
+ doc="Buttons with click interaction (Set[int])")
+
+ dragButtons = property(lambda self: self.__dragButtons,
+ doc="Buttons with drag interaction (Set[int])")
+
def click(self, x, y, btn):
- """Called upon a left or right button click.
+ """Called upon a button supporting click.
- To override in a subclass.
+ Override in subclass.
+
+ :param int x: X mouse position in pixels.
+ :param int y: Y mouse position in pixels.
+ :param str btn: The mouse button which was clicked.
"""
pass
- def beginDrag(self, x, y):
- """Called at the beginning of a drag gesture with left button
- pressed.
+ def beginDrag(self, x, y, btn):
+ """Called at the beginning of a drag gesture with mouse button pressed.
+
+ Override in subclass.
- To override in a subclass.
+ :param int x: X mouse position in pixels.
+ :param int y: Y mouse position in pixels.
+ :param str btn: The mouse button for which a drag is starting.
"""
pass
- def drag(self, x, y):
+ def drag(self, x, y, btn):
"""Called on mouse moved during a drag gesture.
- To override in a subclass.
+ Override in subclass.
+
+ :param int x: X mouse position in pixels.
+ :param int y: Y mouse position in pixels.
+ :param str btn: The mouse button for which a drag is in progress.
"""
pass
- def endDrag(self, startPoint, endPoint):
- """Called at the end of a drag gesture when the left button is
- released.
+ def endDrag(self, startPoint, endPoint, btn):
+ """Called at the end of a drag gesture when the mouse button is released.
+
+ Override in subclass.
- To override in a subclass.
+ :param List[int] startPoint:
+ (x, y) mouse position in pixels at the beginning of the drag.
+ :param List[int] endPoint:
+ (x, y) mouse position in pixels at the end of the drag.
+ :param str btn: The mouse button for which a drag is done.
"""
pass