1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 import os
20 import webbrowser
21
22 import wx
23
24 from timelinelib.canvas import EVT_DIVIDER_POSITION_CHANGED
25 from timelinelib.canvas import EVT_TIMELINE_REDRAWN
26 from timelinelib.db.utils import safe_locking
27 from timelinelib.general.observer import Listener
28 from timelinelib.wxgui.components.maincanvas.createperiodeventbydrag import CreatePeriodEventByDragInputHandler
29 from timelinelib.wxgui.components.maincanvas.maincanvas import MainCanvas
30 from timelinelib.wxgui.components.maincanvas.movebydrag import MoveByDragInputHandler
31 from timelinelib.wxgui.components.maincanvas.noop import NoOpInputHandler
32 from timelinelib.wxgui.components.maincanvas.resizebydrag import ResizeByDragInputHandler
33 from timelinelib.wxgui.components.maincanvas.scrollbydrag import ScrollByDragInputHandler
34 from timelinelib.wxgui.components.maincanvas.zoombydrag import ZoomByDragInputHandler
35 from timelinelib.wxgui.components.maincanvas.selectevents import SelectEventsInputHandler
36 from timelinelib.wxgui.components.messagebar import MessageBar
37 from timelinelib.wxgui.components.sidebar import Sidebar
38 from timelinelib.wxgui.dialogs.duplicateevent.view import open_duplicate_event_dialog_for_event
39 from timelinelib.wxgui.dialogs.editevent.view import open_create_event_editor
40 from timelinelib.wxgui.dialogs.editevent.view import open_event_editor_for
41 from timelinelib.wxgui.dialogs.milestone.view import open_milestone_editor_for
42 from timelinelib.wxgui.frames.mainframe.toolbar import ToolbarCreator
43 from timelinelib.wxgui.utils import _ask_question
44 from timelinelib.config.paths import ICONS_DIR
45 from timelinelib.wxgui.cursor import Cursor
46
47
48 LEFT_RIGHT_SCROLL_FACTOR = 1 / 200.0
49
50
52
57
60
63
65 self._create_toolbar()
66 self._create_warning_bar()
67 self._create_divider_line_slider()
68 self._create_splitter()
69 self._layout_components()
70
73
76
78
79 def on_slider(evt):
80 self.config.divider_line_slider_pos = evt.GetPosition()
81
82 style = wx.SL_LEFT | wx.SL_VERTICAL
83 self.divider_line_slider = wx.Slider(self, style=style)
84 self.Bind(wx.EVT_SCROLL, on_slider, self.divider_line_slider)
85
86 self.divider_line_slider.Bind(wx.EVT_SLIDER, self._slider_on_slider)
87 self.divider_line_slider.Bind(wx.EVT_CONTEXT_MENU, self._slider_on_context_menu)
88
91
93 menu = wx.Menu()
94 menu_item = wx.MenuItem(menu, wx.NewId(), _("Center"))
95 self.Bind(wx.EVT_MENU, self._context_menu_on_menu_center, id=menu_item.GetId())
96 menu.Append(menu_item)
97 self.PopupMenu(menu)
98 menu.Destroy()
99
101 self.timeline_canvas.SetDividerPosition(50)
102
104 self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE)
105 self.splitter.SetMinimumPaneSize(50)
106 self.Bind(
107 wx.EVT_SPLITTER_SASH_POS_CHANGED,
108 self._splitter_on_splitter_sash_pos_changed, self.splitter)
109 self._create_sidebar()
110 self._create_timeline_canvas()
111 self.splitter.Initialize(self.timeline_canvas)
112
114 if self.IsShown():
115 self.sidebar_width = self.splitter.GetSashPosition()
116
119
121 self.timeline_canvas = MainCanvas(
122 self.splitter, self._edit_controller, self.status_bar_adapter)
123 self.timeline_canvas.Bind(
124 wx.EVT_LEFT_DCLICK,
125 self._timeline_canvas_on_double_clicked
126 )
127 self.timeline_canvas.Bind(
128 wx.EVT_RIGHT_DOWN,
129 self._timeline_canvas_on_right_down
130 )
131 self.timeline_canvas.Bind(
132 wx.EVT_KEY_DOWN,
133 self._timeline_canvas_on_key_down
134 )
135 self.timeline_canvas.Bind(
136 EVT_DIVIDER_POSITION_CHANGED,
137 self._timeline_canvas_on_divider_position_changed
138 )
139 self.timeline_canvas.Bind(
140 EVT_TIMELINE_REDRAWN,
141 self._timeline_canvas_on_timeline_redrawn
142 )
143 self.timeline_canvas.SetDividerPosition(self.config.divider_line_slider_pos)
144 self.timeline_canvas.SetEventBoxDrawer(self._get_saved_event_box_drawer())
145 self.timeline_canvas.SetInputHandler(NoOpInputHandler(
146 InputHandlerState(
147 self.timeline_canvas, self.status_bar_adapter,
148 self._edit_controller, self.config),
149 self.timeline_canvas))
150
151 def update_appearance():
152 appearance = self.timeline_canvas.GetAppearance()
153 appearance.set_legend_visible(self.config.show_legend)
154 appearance.set_balloons_visible(self.config.balloon_on_hover)
155 appearance.set_hide_events_done(self.config.hide_events_done)
156 appearance.set_minor_strip_divider_line_colour(self.config.minor_strip_divider_line_colour)
157 appearance.set_major_strip_divider_line_colour(self.config.major_strip_divider_line_colour)
158 appearance.set_now_line_colour(self.config.now_line_colour)
159 appearance.set_weekend_colour(self.config.weekend_colour)
160 appearance.set_bg_colour(self.config.bg_colour)
161 appearance.set_colorize_weekends(self.config.colorize_weekends)
162 appearance.set_draw_period_events_to_right(self.config.draw_point_events_to_right)
163 appearance.set_text_below_icon(self.config.text_below_icon)
164 appearance.set_minor_strip_font(self.config.minor_strip_font)
165 appearance.set_major_strip_font(self.config.major_strip_font)
166 appearance.set_balloon_font(self.config.balloon_font)
167 appearance.set_legend_font(self.config.legend_font)
168 appearance.set_center_event_texts(self.config.center_event_texts)
169 appearance.set_never_show_period_events_as_point_events(self.config.never_show_period_events_as_point_events)
170 appearance.set_week_start(self.config.get_week_start())
171 appearance.set_use_inertial_scrolling(self.config.use_inertial_scrolling)
172 appearance.set_fuzzy_icon(self.config.fuzzy_icon)
173 appearance.set_locked_icon(self.config.locked_icon)
174 appearance.set_hyperlink_icon(self.config.hyperlink_icon)
175 appearance.set_vertical_space_between_events(self.config.vertical_space_between_events)
176 appearance.set_skip_s_in_decade_text(self.config.skip_s_in_decade_text)
177 appearance.set_display_checkmark_on_events_done(self.config.display_checkmark_on_events_done)
178 appearance.set_never_use_time(self.config.never_use_time)
179 appearance.set_legend_pos(self.config.legend_pos)
180 appearance.set_time_scale_pos(self.config.time_scale_pos)
181 appearance.set_use_bold_nowline(self.config.use_bold_nowline)
182 self.config.listen_for_any(update_appearance)
183 update_appearance()
184
191
212
220
234
236 self._try_move_event_vertically(True)
237
239 self._try_move_event_vertically(False)
240
245
268 safe_locking(self._edit_controller, edit_function)
269
271 menu_definitions = [
272 (_("Delete"), self._context_menu_on_delete_event, None),
273 ]
274 nbr_of_selected_events = len(self.timeline_canvas.GetSelectedEvents())
275 if nbr_of_selected_events == 1:
276 menu_definitions.insert(0, (_("Edit"), self._context_menu_on_edit_event, None))
277 menu_definitions.insert(1, (_("Duplicate..."), self._context_menu_on_duplicate_event, None))
278 menu_definitions.append((_("Mark Event as Done"), self._context_menu_on_done_event, None))
279 menu_definitions.append((_("Select Category..."), self._context_menu_on_select_category, None))
280 if nbr_of_selected_events == 1 and self.timeline_canvas.GetSelectedEvent().has_data():
281 menu_definitions.append((_("Sticky Balloon"), self._context_menu_on_sticky_balloon_event, None))
282 if nbr_of_selected_events == 1:
283 hyperlinks = self.timeline_canvas.GetSelectedEvent().get_data("hyperlink")
284 if hyperlinks is not None:
285 imp = wx.Menu()
286 menuid = 0
287 for hyperlink in hyperlinks.split(";"):
288 imp.Append(menuid, hyperlink)
289 menuid += 1
290 menu_definitions.append((_("Goto URL"), self._context_menu_on_goto_hyperlink_event, imp))
291 menu = wx.Menu()
292 mid = 0
293 for menu_definition in menu_definitions:
294 text, method, imp = menu_definition
295 menu_item = wx.MenuItem(menu, mid, text)
296 if imp is not None:
297 for menu_item in imp.GetMenuItems():
298 self.Bind(wx.EVT_MENU, method, id=menu_item.GetId())
299 menu.AppendMenu(wx.ID_ANY, text, imp)
300 else:
301 self.Bind(wx.EVT_MENU, method, id=menu_item.GetId())
302 menu.Append(menu_item)
303 mid += 1
304 self.PopupMenu(menu)
305 menu.Destroy()
306
308 self._delete_selected_events()
309
320
321 def user_ack():
322 if number_of_selected_events > 1:
323 text = _("Are you sure you want to delete %d events?" %
324 number_of_selected_events)
325 else:
326 text = _("Are you sure you want to delete this event?")
327 return _ask_question(text) == wx.YES
328 safe_locking(self._edit_controller, edit_function)
329
331 self.open_event_editor(self.timeline_canvas.GetSelectedEvent())
332
334 open_duplicate_event_dialog_for_event(
335 self._edit_controller,
336 self,
337 self.timeline_canvas.GetDb(),
338 self.timeline_canvas.GetSelectedEvent())
339
340
342 def edit_function():
343 with self.timeline_canvas.GetDb().transaction("Mark events done"):
344 for event in self.timeline_canvas.GetSelectedEvents():
345 if not event.is_container():
346 event.set_progress(100)
347 event.save()
348 self.timeline_canvas.ClearSelectedEvents()
349 safe_locking(self._edit_controller, edit_function)
350
352
353
354 set_category_on_selected = getattr(self.main_frame, 'set_category_on_selected', None)
355 if callable(set_category_on_selected):
356 set_category_on_selected()
357
359 self.timeline_canvas.SetEventStickyBalloon(self.timeline_canvas.GetSelectedEvent(), True)
360
362 hyperlinks = self.timeline_canvas.GetSelectedEvent().get_data("hyperlink")
363 hyperlink = hyperlinks.split(";")[evt.Id]
364 webbrowser.open(hyperlink)
365
369
376
378 hsizer = wx.BoxSizer(wx.HORIZONTAL)
379 hsizer.Add(self.splitter, proportion=1, flag=wx.EXPAND)
380 hsizer.Add(self.divider_line_slider, proportion=0, flag=wx.EXPAND)
381 vsizer = wx.BoxSizer(wx.VERTICAL)
382 vsizer.Add(self.tool_bar, proportion=0, flag=wx.EXPAND)
383 vsizer.Add(self.message_bar, proportion=0, flag=wx.EXPAND)
384 vsizer.Add(hsizer, proportion=1, flag=wx.EXPAND)
385 self.SetSizer(vsizer)
386
387
389
390 - def __init__(self, parent, config, status_bar_adapter, main_frame):
397
401
403 return self.timeline_canvas
404
407
418
426
428 self.timeline_canvas.Redraw()
429
431 return self.timeline_canvas.Navigate(navigation_fn)
432
435
438
443
446
450
462
463
512