Gnumed.timelinelib.wxgui.components.maincanvas.maincanvas

Package Gnumed :: Package timelinelib :: Package wxgui :: Package components :: Package maincanvas :: Module maincanvas |
[frames] | no frames]

# Source Code for Module Gnumed.timelinelib.wxgui.components.maincanvas.maincanvas

      1  # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
      2  #
      3  # This file is part of Timeline.
      4  #
      5  # Timeline is free software: you can redistribute it and/or modify
      6  # it under the terms of the GNU General Public License as published by
      7  # the Free Software Foundation, either version 3 of the License, or
      8  # (at your option) any later version.
      9  #
     10  # Timeline is distributed in the hope that it will be useful,
     11  # but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  # GNU General Public License for more details.
     14  #
     15  # You should have received a copy of the GNU General Public License
     16  # along with Timeline.  If not, see <http://www.gnu.org/licenses/>.
     17
     18
     19  import wx
     20
     21  from timelinelib.canvas.data import TimeOutOfRangeLeftError
     22  from timelinelib.canvas.data import TimeOutOfRangeRightError
     23  from timelinelib.canvas import TimelineCanvas
     24  from timelinelib.utils import ex_msg
     25  from timelinelib.wxgui.cursor import Cursor
     26  from timelinelib.wxgui.keyboard import Keyboard
     27  from timelinelib.wxgui.components.maincanvas.inputhandler import InputHandler
     28  from timelinelib.general.methodcontainer import MethodContainer
     29  from timelinelib.canvas.data import TimePeriod
     30  from timelinelib.canvas.timelinecanvas import LEFT_RESIZE_HANDLE
     31  from timelinelib.canvas.timelinecanvas import RIGHT_RESIZE_HANDLE
     32  from timelinelib.canvas.timelinecanvas import MOVE_HANDLE
     33
     34
     35 -class MainCanvas(TimelineCanvas):
     36
     37 -    def __init__(self, parent, edit_controller, status_bar):
     38          TimelineCanvas.__init__(self, parent)
     39          self._edit_controller = edit_controller
     40          self._status_bar = status_bar
     41          self.SetInputHandler(InputHandler(self))
     42          self.dragscroll_timer = wx.Timer(self, -1)
     43          self.Bind(wx.EVT_LEFT_DOWN, self._on_left_down)
     44          self.Bind(wx.EVT_LEFT_DCLICK, self._on_left_dclick)
     45          self.Bind(wx.EVT_LEFT_UP, self._on_left_up)
     46          self.Bind(wx.EVT_MOTION, self._on_motion)
     47          self.Bind(wx.EVT_TIMER, self._on_dragscroll, self.dragscroll_timer)
     48          self.Bind(wx.EVT_MIDDLE_DOWN, self._on_middle_down)
     49          self.Bind(wx.EVT_MOUSEWHEEL, self._on_mousewheel)
     50
     51 -    def SetDb(self, db):
     52          db.display_in_canvas(self)
     53
     54 -    def Navigate(self, navigation_fn):
     55          try:
     56              TimelineCanvas.Navigate(self, navigation_fn)
     57          except (TimeOutOfRangeLeftError) as e:
     58              self._status_bar.set_text(_("Can't scroll more to the left"))
     59          except (TimeOutOfRangeRightError) as e:
     60              self._status_bar.set_text(_("Can't scroll more to the right"))
     61          except (ValueError, OverflowError) as e:
     62              self._status_bar.set_text(ex_msg(e))
     63          else:
     64              self._status_bar.set_text("")
     65
     66 -    def SetInputHandler(self, input_handler):
     67          self._input_handler = input_handler
     68
     69 -    def _on_left_down(self, evt):
     70          self._edit_controller.save_time_period()
     71          self.SetFocus()
     72          self._input_handler.left_mouse_down(self._get_cursor(evt),
     73                                              self._get_keyboard(evt))
     74
     75 -    def _on_left_dclick(self, evt):
     76          """
     77          Event handler used when the left mouse button has been double clicked.
     78
     79          If the timeline is readonly, no action is taken.
     80          If the mouse hits an event, a dialog opens for editing this event.
     81          Otherwise a dialog for creating a new event is opened.
     82          """
     83          if self.IsReadOnly():
     84              return
     85          # Since the event sequence is, 1. EVT_LEFT_DOWN  2. EVT_LEFT_UP
     86          # 3. EVT_LEFT_DCLICK we must compensate for the toggle_event_selection
     87          # that occurs in the handling of EVT_LEFT_DOWN, since we still want
     88          # the event(s) selected or deselected after a left doubleclick
     89          # It doesn't look too god but I havent found any other way to do it.
     90          self.ToggleEventSelection(evt)
     91
     92 -    def _get_cursor(self, evt):
     93          return Cursor(evt.GetX(), evt.GetY())
     94
     95 -    def _get_keyboard(self, evt):
     96          return Keyboard(evt.ControlDown(), evt.ShiftDown(), evt.AltDown())
     97
     98 -    def _on_left_up(self, event):
     99          self._input_handler.left_mouse_up()
    100
    101 -    def _on_motion(self, evt):
    102          self.DisplayBalloons(evt)
    103          self._status_bar.set_text(self.GetTimelineInfoText(evt))
    104          self.SetCursorShape(evt)
    105          self._input_handler.mouse_moved(self._get_cursor(evt),
    106                                          self._get_keyboard(evt))
    107
    108 -    def _on_dragscroll(self, event):
    109          self._input_handler.dragscroll_timer_fired()
    110
    111 -    def _on_middle_down(self, evt):
    112          self.CenterAtCursor(evt)
    113
    114 -    def _on_mousewheel(self, evt):
    115          self._edit_controller.save_time_period()
    116
    117          keyboard = self._get_keyboard(evt)
    118          methods = MethodContainer(
    119              [
    120                  (Keyboard.CTRL, self.ZoomHorizontallyOnMouseWheel),
    121                  (Keyboard.SHIFT + Keyboard.CTRL, self.SpecialScrollVerticallyOnMouseWheel),
    122                  (Keyboard.SHIFT, self.ScrollVerticallyOnMouseWheel),
    123                  (Keyboard.ALT, self.ZoomVerticallyOnMouseWheel),
    124              ], default_method=self.ScrollHorizontallyOnMouseWheel
    125          )
    126          methods.select(keyboard.keys_combination)(evt)
    127
    128 -    def start_dragscroll_timer(self, milliseconds=-1, oneShot=False):
    129          self.dragscroll_timer.Start(milliseconds, oneShot)
    130
    131 -    def stop_dragscroll_timer(self):
    132          self.dragscroll_timer.Stop()
    133
    134 -    def toggle_event_selection(self, cursor, keyboard):
    135
    136          def toggle_event_selection_when_event_is_hit(event):
    137              selected = not self.IsEventSelected(event)
    138              if keyboard.ctrl:
    139                  self.SetEventSelected(event, selected)
    140              else:
    141                  self.ClearSelectedEvents()
    142                  self.SetEventSelected(event, selected)
    143
    144          event = self.GetEventAt(cursor, keyboard.alt)
    145          if event:
    146              toggle_event_selection_when_event_is_hit(event)
    147          else:
    148              self.ClearSelectedEvents()
    149
    150 -    def format_current_pos_time_string(self, x):
    151          tm = self.GetTimeAt(x)
    152          return self.GetTimeType().format_period(TimePeriod(tm, tm))
    153
    154 -    def toggle_balloon_stickyness(self, event_with_balloon):
    155          stick = not self.EventHasStickyBalloon(event_with_balloon)
    156          self.SetEventStickyBalloon(event_with_balloon, stick)
    157          if stick:
    158              self.Redraw()
    159          else:
    160              if self.GetAppearance().get_balloons_visible():
    161                  self.SetHoveredEvent(event_with_balloon)
    162              else:
    163                  self.SetHoveredEvent(None)
    164
    165 -    def hit_resize_handle(self, cursor, keyboard):
    166          try:
    167              event, hit_info = self.GetEventWithHitInfoAt(cursor, keyboard)
    168              if event.get_locked():
    169                  return None
    170              if event.is_milestone():
    171                  return None
    172              if not self.IsEventSelected(event):
    173                  return None
    174              if hit_info == LEFT_RESIZE_HANDLE:
    175                  return wx.LEFT
    176              if hit_info == RIGHT_RESIZE_HANDLE:
    177                  return wx.RIGHT
    178              return None
    179          except:
    180              return None
    181
    182 -    def hit_move_handle(self, cursor, keyboard):
    183          event_and_hit_info = self.GetEventWithHitInfoAt(cursor, keyboard)
    184          if event_and_hit_info is None:
    185              return False
    186          (event, hit_info) = event_and_hit_info
    187          if event.get_locked():
    188              return False
    189          if not self.IsEventSelected(event):
    190              return False
    191          return hit_info == MOVE_HANDLE
    192
    193
    194 -def step_function(x_value):
    195      y_value = 0
    196      if x_value < 0:
    197          y_value = -1
    198      elif x_value > 0:
    199          y_value = 1
    200      return y_value
    201