class PlotWindow(Window):
    """Subclass of Window that displays an interactive GLFigure"""

    double_click_time = datetime.timedelta(seconds=0.3)
    cursor_names = {None:Window.CURSOR_DEFAULT,
                    'pan':Window.CURSOR_HAND,
                    'zoom':Window.CURSOR_CROSSHAIR}

    def __init__(self, *args, **kwargs):
        # Initialise self
        kwargs['resizable'] = kwargs.get('resizable', True)
        interactive = kwargs.pop('interactive', False)
        super(PlotWindow, self).__init__(*args, **kwargs)
        self._init = False
        self.last_press = datetime.datetime.now()
        # Create figure object
        width, height = self.get_size()
        self.figure = GLFigure()
        self.figure.set_rect([0, 0, width, height])
        # Create cursors used for interactivity
        self._cursors = {}
        for k, v in self.cursor_names.iteritems():
            self._cursors[k] = self.get_system_mouse_cursor(v)
        # Create interactivity data
        self.set_interactive(interactive)

    def run(self):
        pyglet.app.run()

    def on_draw(self):
        if not self._init:
            self.figure._initgl()
            self._init = True
        self.figure._draw()

    def on_resize(self, width, height):
        self.figure._resize(width, height)

    def set_interactive(self, interactive):
        self._interactive = InteractiveState(interactive, self)

    def _set_cursor(self, mode):
        self.set_mouse_cursor(self._cursors[mode])

    # Manually detect double-clicks
    def on_mouse_press(self, x, y, button, modifiers):
        self.on_mouse_down(x, y, button, modifiers)
        penultimate_press = self.last_press
        self.last_press = datetime.datetime.now()
        delta = self.last_press - penultimate_press
        if button == mouse.LEFT and delta < self.double_click_time:
            self.on_double_click(x, y, button, modifiers)

    def _point(self, x, y):
        width, height = self.get_size()
        return float(x) / float(width), float(y) / float(height)

    def on_mouse_down(self, x, y, button, modifiers):
        if button == mouse.LEFT:
            self._interactive.on_left_down(self._point(x, y))

    def on_mouse_release(self, x, y, button, modifiers):
        if button == mouse.LEFT:
            self._interactive.on_left_up(self._point(x, y))

    def on_double_click(self, x, y, button, modifiers):
        if button == mouse.LEFT:
            self._interactive.on_left_double_click(self._point(x, y))

    def on_mouse_drag(self, x, y, dx, dy, buttons, modifiers):
        if buttons & mouse.LEFT:
            self._interactive.on_mouse_drag(self._point(x, y))

    def on_mouse_motion(self, x, y, dx, dy):
        self._interactive.on_mouse_move(self._point(x, y))
 def set_interactive(self, interactive):
     self._interactive = InteractiveState(interactive, self)
Example #3
0
class _FigurePanelWx(wx.Panel):
    """Specialise InteractiveState for wx gui toolkit"""
    def __init__(self, *args, **kwargs):
        interactive = kwargs.pop('interactive', False)
        super(_FigurePanelWx, self).__init__(*args, **kwargs)
        # Create figure and canvas
        self.figure = self.FigureCls()
        self.canvas = self.CanvasCls(self, wx.ID_ANY, self.figure)
        # Standard sizing
        self.Bind(wx.EVT_SIZE, self.OnSize)
        # Cursors used by InteractiveState
        self._cursors = {None: wx.StockCursor(wx.CURSOR_DEFAULT),
                        'pan':wx.StockCursor(wx.CURSOR_HAND),
                        'zoom':wx.StockCursor(wx.CURSOR_CROSS)}
        # These will call through to self.interactive
        self._left_down = False
        self.canvas.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDoubleClick)
        self.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.canvas.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
        self.canvas.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        #Prepare interactivity
        self.set_interactive(interactive)

    def OnSize(self, event):
        self.canvas.SetSize(self.GetSize())

    def set_interactive(self, interactive):
        self._interactive = InteractiveState(interactive, self)

    def _set_cursor(self, mode):
        self.canvas.SetCursor(self._cursors[mode])

    def _point(self, event):
        x, y = event.GetPosition()
        w, h = self.canvas.GetSize()
        return float(x) / float(w), float(h - y) / float(h)

    def OnLeftDown(self, event):
        self._left_down = True
        self._interactive.on_left_down(self._point(event))

    def OnLeftUp(self, event):
        self._left_down = False
        self._interactive.on_left_up(self._point(event))

    def OnLeftDoubleClick(self, event):
        self._interactive.on_left_double_click(self._point(event))

    def OnRightDown(self, event):
        self._interactive.on_right_down(self._point(event))

    def OnMotion(self, event):
        if self._left_down and not wx.GetMouseState().LeftDown():
            self.OnLeftUp(event)
        elif self._left_down:
            self._interactive.on_mouse_drag(self._point(event))
        else:
            self._interactive.on_mouse_move(self._point(event))