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))
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))