Source code for timelinelib.wxgui.components.maincanvas.maincanvas

# Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018  Rickard Lindberg, Roger Lindberg
#
# This file is part of Timeline.
#
# Timeline is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Timeline is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Timeline.  If not, see <http://www.gnu.org/licenses/>.


import wx

from timelinelib.canvas.data import TimeOutOfRangeLeftError
from timelinelib.canvas.data import TimeOutOfRangeRightError
from timelinelib.canvas import TimelineCanvas
from timelinelib.utils import ex_msg
from timelinelib.wxgui.cursor import Cursor
from timelinelib.wxgui.keyboard import Keyboard
from timelinelib.wxgui.components.maincanvas.inputhandler import InputHandler
from timelinelib.general.methodcontainer import MethodContainer
from timelinelib.canvas.data import TimePeriod
from timelinelib.canvas.timelinecanvas import LEFT_RESIZE_HANDLE
from timelinelib.canvas.timelinecanvas import RIGHT_RESIZE_HANDLE
from timelinelib.canvas.timelinecanvas import MOVE_HANDLE


[docs]class MainCanvas(TimelineCanvas):
[docs] def __init__(self, parent, main_frame, config): TimelineCanvas.__init__(self, parent, config) self._main_frame = main_frame self.SetInputHandler(InputHandler(self)) self.dragscroll_timer = wx.Timer(self, -1) self.Bind(wx.EVT_LEFT_DOWN, self._on_left_down) self.Bind(wx.EVT_LEFT_DCLICK, self._on_left_dclick) self.Bind(wx.EVT_LEFT_UP, self._on_left_up) self.Bind(wx.EVT_MOTION, self._on_motion) self.Bind(wx.EVT_TIMER, self._on_dragscroll, self.dragscroll_timer) self.Bind(wx.EVT_MIDDLE_DOWN, self._on_middle_down) self.Bind(wx.EVT_MOUSEWHEEL, self._on_mousewheel)
[docs] def SetDb(self, db): db.display_in_canvas(self)
[docs] def Navigate(self, navigation_fn): try: TimelineCanvas.Navigate(self, navigation_fn) except TimeOutOfRangeLeftError as e: self._main_frame.DisplayStatus(_("Can't scroll more to the left")) except TimeOutOfRangeRightError as e: self._main_frame.DisplayStatus(_("Can't scroll more to the right")) except (ValueError, OverflowError) as e: self._main_frame.DisplayStatus(ex_msg(e)) else: self._main_frame.DisplayStatus("")
[docs] def SetInputHandler(self, input_handler): self._input_handler = input_handler
def _on_left_down(self, evt): self._main_frame.main_panel.save_time_period() self.SetFocus() self._input_handler.left_mouse_down(self._get_cursor(evt), self._get_keyboard(evt)) def _on_left_dclick(self, evt): """ Event handler used when the left mouse button has been double clicked. If the timeline is readonly, no action is taken. If the mouse hits an event, a dialog opens for editing this event. Otherwise a dialog for creating a new event is opened. """ if self.IsReadOnly(): return # Since the event sequence is, 1. EVT_LEFT_DOWN 2. EVT_LEFT_UP # 3. EVT_LEFT_DCLICK we must compensate for the toggle_event_selection # that occurs in the handling of EVT_LEFT_DOWN, since we still want # the event(s) selected or deselected after a left doubleclick # It doesn't look too god but I havent found any other way to do it. self.ToggleEventSelection(evt) def _get_cursor(self, evt): return Cursor(evt.GetX(), evt.GetY()) def _get_keyboard(self, evt): return Keyboard(evt.ControlDown(), evt.ShiftDown(), evt.AltDown()) def _on_left_up(self, event): self._input_handler.left_mouse_up() def _on_motion(self, evt): self.DisplayBalloons(evt) self._main_frame.DisplayStatus(self.GetTimelineInfoText(evt)) self.SetCursorShape(evt) self._input_handler.mouse_moved(self._get_cursor(evt), self._get_keyboard(evt)) def _on_dragscroll(self, event): self._input_handler.dragscroll_timer_fired() def _on_middle_down(self, evt): self.CenterAtCursor(evt) def _on_mousewheel(self, evt): self._main_frame.main_panel.save_time_period() keyboard = self._get_keyboard(evt) methods = MethodContainer( [ (Keyboard.CTRL, self.ZoomHorizontallyOnMouseWheel), (Keyboard.SHIFT + Keyboard.CTRL, self.SpecialScrollVerticallyOnMouseWheel), (Keyboard.SHIFT, self.ScrollVerticallyOnMouseWheel), (Keyboard.ALT, self.ZoomVerticallyOnMouseWheel), ], default_method=self.ScrollHorizontallyOnMouseWheel ) methods.select(keyboard.keys_combination)(evt)
[docs] def start_dragscroll_timer(self, milliseconds=-1, oneShot=False): self.dragscroll_timer.Start(milliseconds, oneShot)
[docs] def stop_dragscroll_timer(self): self.dragscroll_timer.Stop()
[docs] def toggle_event_selection(self, cursor, keyboard): def toggle_event_selection_when_event_is_hit(event): selected = not self.IsEventSelected(event) if keyboard.ctrl: self.SetEventSelected(event, selected) else: self.ClearSelectedEvents() self.SetEventSelected(event, selected) event = self.GetEventAt(cursor, keyboard.alt) if event: toggle_event_selection_when_event_is_hit(event) else: self.ClearSelectedEvents()
[docs] def format_current_pos_time_string(self, x): tm = self.GetTimeAt(x) return self.GetTimeType().format_period(TimePeriod(tm, tm))
[docs] def toggle_balloon_stickyness(self, event_with_balloon): stick = not self.EventHasStickyBalloon(event_with_balloon) self.SetEventStickyBalloon(event_with_balloon, stick) if stick: self.Redraw() else: if self.GetAppearance().get_balloons_visible(): self.SetHoveredEvent(event_with_balloon) else: self.SetHoveredEvent(None)
[docs] def hit_resize_handle(self, cursor, keyboard): try: event, hit_info = self.GetEventWithHitInfoAt(cursor) if event.get_locked(): return None if event.is_milestone(): return None if not self.IsEventSelected(event): return None if hit_info == LEFT_RESIZE_HANDLE: return wx.LEFT if hit_info == RIGHT_RESIZE_HANDLE: return wx.RIGHT return None except: return None
[docs] def hit_move_handle(self, cursor): event_and_hit_info = self.GetEventWithHitInfoAt(cursor) if event_and_hit_info is None: return False (event, hit_info) = event_and_hit_info if event.get_locked(): return False if not self.IsEventSelected(event): return False return hit_info == MOVE_HANDLE
[docs]def step_function(x_value): y_value = 0 if x_value < 0: y_value = -1 elif x_value > 0: y_value = 1 return y_value