Package Gnumed :: Package timelinelib :: Package wxgui :: Package frames :: Package mainframe :: Module guicreator
[frames] | no frames]

Source Code for Module Gnumed.timelinelib.wxgui.frames.mainframe.guicreator

  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  A base class for the mainframe window, responsible for creating the GUI. 
 20  """ 
 21   
 22   
 23  import collections 
 24  import wx 
 25   
 26  from timelinelib.db.utils import safe_locking 
 27  from timelinelib.meta.about import display_about_dialog 
 28  from timelinelib.plugin.factory import EVENTBOX_DRAWER 
 29  from timelinelib.plugin.factory import EXPORTER 
 30  from timelinelib.plugin import factory 
 31  from timelinelib.proxies.drawingarea import DrawingAreaProxy 
 32  from timelinelib.wxgui.components.mainpanel import MainPanel 
 33  from timelinelib.wxgui.components.statusbaradapter import StatusBarAdapter 
 34  from timelinelib.wxgui.dialogs.duplicateevent.view import open_duplicate_event_dialog_for_event 
 35  from timelinelib.wxgui.dialogs.editevent.view import open_create_event_editor 
 36  from timelinelib.wxgui.dialogs.feedback.view import show_feedback_dialog 
 37  from timelinelib.wxgui.dialogs.filenew.view import FileNewDialog 
 38  from timelinelib.wxgui.dialogs.importevents.view import ImportEventsDialog 
 39  from timelinelib.wxgui.dialogs.milestone.view import open_milestone_editor_for 
 40  from timelinelib.wxgui.dialogs.preferences.view import PreferencesDialog 
 41  from timelinelib.wxgui.dialogs.shortcutseditor.view import ShortcutsEditorDialog 
 42  from timelinelib.wxgui.dialogs.systeminfo.view import show_system_info_dialog 
 43   
 44   
 45  NONE = 0 
 46  CHECKBOX = 1 
 47  CHECKED_RB = 2 
 48  UNCHECKED_RB = 3 
 49  ID_SIDEBAR = wx.NewId() 
 50  ID_LEGEND = wx.NewId() 
 51  ID_BALLOONS = wx.NewId() 
 52  ID_ZOOMIN = wx.NewId() 
 53  ID_ZOOMOUT = wx.NewId() 
 54  ID_VERT_ZOOMIN = wx.NewId() 
 55  ID_VERT_ZOOMOUT = wx.NewId() 
 56  ID_CREATE_EVENT = wx.NewId() 
 57  ID_CREATE_MILESTONE = wx.NewId() 
 58  ID_PT_EVENT_TO_RIGHT = wx.NewId() 
 59  ID_EDIT_EVENT = wx.NewId() 
 60  ID_DUPLICATE_EVENT = wx.NewId() 
 61  ID_SET_CATEGORY_ON_SELECTED = wx.NewId() 
 62  ID_MEASURE_DISTANCE = wx.NewId() 
 63  ID_COMPRESS = wx.NewId() 
 64  ID_SET_CATEGORY_ON_WITHOUT = wx.NewId() 
 65  ID_EDIT_ERAS = wx.NewId() 
 66  ID_SET_READONLY = wx.NewId() 
 67  ID_FIND_FIRST = wx.NewId() 
 68  ID_FIND_LAST = wx.NewId() 
 69  ID_FIT_ALL = wx.NewId() 
 70  ID_EDIT_SHORTCUTS = wx.NewId() 
 71  ID_TUTORIAL = wx.NewId() 
 72  ID_NUMTUTORIAL = wx.NewId() 
 73  ID_FEEDBACK = wx.NewId() 
 74  ID_CONTACT = wx.NewId() 
 75  ID_SYSTEM_INFO = wx.NewId() 
 76  ID_IMPORT = wx.NewId() 
 77  ID_EXPORT = wx.NewId() 
 78  ID_EXPORT_ALL = wx.NewId() 
 79  ID_EXPORT_SVG = wx.NewId() 
 80  ID_FIND_CATEGORIES = wx.NewId() 
 81  ID_SELECT_ALL = wx.NewId() 
 82  ID_RESTORE_TIME_PERIOD = wx.NewId() 
 83  ID_NEW = wx.ID_NEW 
 84  ID_FIND = wx.ID_FIND 
 85  ID_UNDO = wx.NewId() 
 86  ID_REDO = wx.NewId() 
 87  ID_PREFERENCES = wx.ID_PREFERENCES 
 88  ID_HELP = wx.ID_HELP 
 89  ID_ABOUT = wx.ID_ABOUT 
 90  ID_SAVEAS = wx.ID_SAVEAS 
 91  ID_EXIT = wx.ID_EXIT 
 92  ID_MOVE_EVENT_UP = wx.NewId() 
 93  ID_MOVE_EVENT_DOWN = wx.NewId() 
 94  ID_PRESENTATION = wx.NewId() 
 95  ID_HIDE_DONE = wx.NewId() 
 96  ID_NAVIGATE = wx.NewId() + 100 
 97   
 98   
99 -class GuiCreator(object):
100
101 - def _create_gui(self):
102 self.shortcut_items = {} 103 self._create_status_bar() 104 self._create_main_panel() 105 self._create_main_menu_bar() 106 self._bind_frame_events()
107
108 - def _create_status_bar(self):
109 self.CreateStatusBar() 110 self.status_bar_adapter = StatusBarAdapter(self.GetStatusBar())
111
112 - def _create_main_panel(self):
113 self.main_panel = MainPanel(self, self.config, self)
114
115 - def _create_main_menu_bar(self):
116 main_menu_bar = wx.MenuBar() 117 main_menu_bar.Append(self._create_file_menu(), _("&File")) 118 main_menu_bar.Append(self._create_edit_menu(), _("&Edit")) 119 main_menu_bar.Append(self._create_view_menu(), _("&View")) 120 main_menu_bar.Append(self._create_timeline_menu(), _("&Timeline")) 121 main_menu_bar.Append(self._create_navigate_menu(), _("&Navigate")) 122 main_menu_bar.Append(self._create_help_menu(), _("&Help")) 123 self._set_shortcuts() 124 self.SetMenuBar(main_menu_bar) 125 self.update_navigation_menu_items() 126 self.enable_disable_menus()
127
128 - def _set_shortcuts(self):
129 from timelinelib.config.shortcut import ShortcutController 130 self.shortcut_controller = ShortcutController(self.config, self.shortcut_items) 131 self.shortcut_controller.load_config_settings()
132
133 - def _bind_frame_events(self):
134 self.Bind(wx.EVT_CLOSE, self._window_on_close)
135
136 - def _create_file_menu(self):
137 file_menu = wx.Menu() 138 self._create_file_new_menu_item(file_menu) 139 self._create_file_open_menu_item(file_menu) 140 self._create_file_open_recent_menu(file_menu) 141 file_menu.AppendSeparator() 142 self._create_file_save_as_menu(file_menu) 143 file_menu.AppendSeparator() 144 self._create_import_menu_item(file_menu) 145 file_menu.AppendSeparator() 146 self._create_export_menues(file_menu) 147 file_menu.AppendSeparator() 148 self._create_file_exit_menu_item(file_menu) 149 self._file_menu = file_menu 150 return file_menu
151
152 - def _create_export_menues(self, file_menu):
153 154 def create_click_handler(plugin, main_frame): 155 def event_handler(evt): 156 plugin.run(main_frame)
157 return event_handler
158 159 submenu = wx.Menu() 160 file_menu.Append(wx.ID_ANY, _("Export"), submenu) 161 for plugin in factory.get_plugins(EXPORTER): 162 mnu = submenu.Append(wx.ID_ANY, plugin.display_name(), plugin.display_name()) 163 self.menu_controller.add_menu_requiring_timeline(mnu) 164 handler = create_click_handler(plugin, self) 165 self.Bind(wx.EVT_MENU, handler, mnu) 166 method = getattr(plugin, "wxid", None) 167 if callable(method): 168 self.shortcut_items[method()] = mnu 169
170 - def _create_file_new_menu_item(self, file_menu):
171 accel = wx.GetStockLabel(wx.ID_NEW, wx.STOCK_WITH_ACCELERATOR | wx.STOCK_WITH_MNEMONIC) 172 accel = accel.split("\t", 1)[1] 173 file_menu.Append( 174 wx.ID_NEW, _("New...") + "\t" + accel, _("Create a new timeline")) 175 self.shortcut_items[wx.ID_NEW] = file_menu.FindItemById(wx.ID_NEW) 176 self.Bind(wx.EVT_MENU, self._mnu_file_new_on_click, id=wx.ID_NEW)
177
178 - def _create_file_open_menu_item(self, file_menu):
179 file_menu.Append( 180 wx.ID_OPEN, self._add_ellipses_to_menuitem(wx.ID_OPEN), 181 _("Open an existing timeline")) 182 self.Bind(wx.EVT_MENU, self._mnu_file_open_on_click, id=wx.ID_OPEN)
183
184 - def _create_file_open_recent_menu(self, file_menu):
185 self.mnu_file_open_recent_submenu = wx.Menu() 186 file_menu.Append(wx.ID_ANY, _("Open &Recent"), self.mnu_file_open_recent_submenu) 187 self.update_open_recent_submenu()
188
189 - def _create_file_save_as_menu(self, file_menu):
190 menu = file_menu.Append(wx.ID_SAVEAS, "", _("Save As...")) 191 self.shortcut_items[wx.ID_SAVEAS] = menu 192 self.Bind(wx.EVT_MENU, self.mnu_file_save_as_on_click, id=wx.ID_SAVEAS)
193
194 - def _create_import_menu_item(self, file_menu):
195 mnu_file_import = file_menu.Append( 196 ID_IMPORT, _("Import events..."), _("Import events...")) 197 self.shortcut_items[ID_IMPORT] = mnu_file_import 198 self.Bind(wx.EVT_MENU, self._mnu_file_import_on_click, mnu_file_import) 199 self.menu_controller.add_menu_requiring_writable_timeline(mnu_file_import)
200
201 - def _create_file_exit_menu_item(self, file_menu):
202 file_menu.Append(wx.ID_EXIT, "", _("Exit the program")) 203 self.shortcut_items[wx.ID_EXIT] = file_menu.FindItemById(wx.ID_EXIT) 204 self.Bind(wx.EVT_MENU, self._mnu_file_exit_on_click, id=wx.ID_EXIT)
205
206 - def _create_edit_menu(self):
207 from timelinelib.wxgui.dialogs.categoryfinder.view import CategoryFinderDialog 208 209 def create_category_find_dialog(): 210 return CategoryFinderDialog(self, self.timeline)
211 212 def find(evt): 213 self.main_panel.show_searchbar(True) 214 215 def find_categories(evt): 216 dialog = create_category_find_dialog() 217 dialog.ShowModal() 218 dialog.Destroy() 219 220 def select_all(evt): 221 self.controller.select_all() 222 223 def preferences(evt): 224 def edit_function(): 225 dialog = PreferencesDialog(self, self.config) 226 dialog.ShowModal() 227 dialog.Destroy() 228 safe_locking(self, edit_function) 229 230 def edit_shortcuts(evt): 231 232 def edit_function(): 233 dialog = ShortcutsEditorDialog(self, self.shortcut_controller) 234 dialog.ShowModal() 235 dialog.Destroy() 236 safe_locking(self, edit_function) 237 cbx = NONE 238 items_spec = ((wx.ID_FIND, find, None, cbx), 239 (ID_FIND_CATEGORIES, find_categories, _("Find Categories..."), cbx), 240 None, 241 (ID_SELECT_ALL, select_all, _("Select All Events"), cbx), 242 None, 243 (wx.ID_PREFERENCES, preferences, None, cbx), 244 (ID_EDIT_SHORTCUTS, edit_shortcuts, _("Shortcuts..."), cbx)) 245 self._edit_menu = self._create_menu(items_spec) 246 self._add_edit_menu_items_to_controller(self._edit_menu) 247 return self._edit_menu 248
249 - def _add_edit_menu_items_to_controller(self, edit_menu):
250 find_item = edit_menu.FindItemById(ID_FIND) 251 find_categories_item = edit_menu.FindItemById(ID_FIND_CATEGORIES) 252 self.menu_controller.add_menu_requiring_timeline(find_item) 253 self.menu_controller.add_menu_requiring_timeline(find_categories_item)
254
255 - def _create_view_menu(self):
256 257 def sidebar(evt): 258 self.config.show_sidebar = evt.IsChecked() 259 if evt.IsChecked(): 260 self.main_panel.show_sidebar() 261 else: 262 self.main_panel.hide_sidebar()
263 264 def legend(evt): 265 self.config.show_legend = evt.IsChecked() 266 267 def balloons(evt): 268 self.config.balloon_on_hover = evt.IsChecked() 269 270 def zoomin(evt): 271 DrawingAreaProxy(self).zoom_in() 272 273 def zoomout(evt): 274 DrawingAreaProxy(self).zoom_out() 275 276 def vert_zoomin(evt): 277 DrawingAreaProxy(self).vertical_zoom_in() 278 279 def vert_zoomout(evt): 280 DrawingAreaProxy(self).vertical_zoom_out() 281 282 def start_slide_show(evt): 283 canvas = self.main_panel.get_timeline_canvas() 284 self.controller.start_slide_show(canvas) 285 286 def hide_events_done(evt): 287 self.config.hide_events_done = evt.IsChecked() 288 289 items_spec = [self._create_view_toolbar_menu_item, 290 (ID_SIDEBAR, sidebar, _("&Sidebar") + "\tCtrl+I", CHECKBOX), 291 (ID_LEGEND, legend, _("&Legend"), CHECKBOX), 292 None, 293 (ID_BALLOONS, balloons, _("&Balloons on hover"), CHECKBOX), 294 None, 295 (ID_ZOOMIN, zoomin, _("Zoom &In") + "\tCtrl++", NONE), 296 (ID_ZOOMOUT, zoomout, _("Zoom &Out") + "\tCtrl+-", NONE), 297 (ID_VERT_ZOOMIN, vert_zoomin, _("Vertical Zoom &In") + "\tAlt++", NONE), 298 (ID_VERT_ZOOMOUT, vert_zoomout, _("Vertical Zoom &Out") + "\tAlt+-", NONE), 299 None, 300 self._create_view_point_event_alignment_menu, 301 None, 302 self._create_event_box_drawers_menu, 303 None, 304 (ID_PRESENTATION, start_slide_show, _("Start slide show") + "...", NONE), 305 None, 306 (ID_HIDE_DONE, hide_events_done, _("&Hide Events done"), CHECKBOX), 307 ] 308 self._view_menu = self._create_menu(items_spec) 309 self._check_view_menu_items(self._view_menu) 310 self._add_view_menu_items_to_controller(self._view_menu) 311 return self._view_menu 312
313 - def _create_view_toolbar_menu_item(self, view_menu):
314 item = view_menu.Append(wx.ID_ANY, _("Toolbar"), kind=wx.ITEM_CHECK) 315 316 def on_click(event): 317 self.config.show_toolbar = event.IsChecked()
318 319 def check_item_corresponding_to_config(): 320 item.Check(self.config.show_toolbar) 321 322 self.Bind(wx.EVT_MENU, on_click, item) 323 self.config.listen_for_any(check_item_corresponding_to_config) 324 check_item_corresponding_to_config() 325
326 - def _create_event_box_drawers_menu(self, view_menu):
327 328 def create_click_handler(plugin): 329 def event_handler(evt): 330 self.main_panel.get_timeline_canvas().SetEventBoxDrawer(plugin.run()) 331 self.config.set_selected_event_box_drawer(plugin.display_name())
332 return event_handler 333 334 items = [] 335 for plugin in factory.get_plugins(EVENTBOX_DRAWER): 336 if plugin.display_name() == self.config.get_selected_event_box_drawer(): 337 items.append((wx.ID_ANY, create_click_handler(plugin), plugin.display_name(), CHECKED_RB)) 338 else: 339 items.append((wx.ID_ANY, create_click_handler(plugin), plugin.display_name(), UNCHECKED_RB)) 340 sub_menu = self._create_menu(items) 341 view_menu.Append(wx.ID_ANY, _("Event appearance"), sub_menu) 342
343 - def _create_view_point_event_alignment_menu(self, view_menu):
344 sub_menu = wx.Menu() 345 left_item = sub_menu.Append(wx.ID_ANY, _("Left"), kind=wx.ITEM_RADIO) 346 center_item = sub_menu.Append(wx.ID_ANY, _("Center"), kind=wx.ITEM_RADIO) 347 view_menu.Append(wx.ID_ANY, _("Point event alignment"), sub_menu) 348 349 def on_first_tool_click(event): 350 self.config.draw_point_events_to_right = True
351 352 def on_second_tool_click(event): 353 self.config.draw_point_events_to_right = False 354 355 def check_item_corresponding_to_config(): 356 if self.config.draw_point_events_to_right: 357 left_item.Check() 358 else: 359 center_item.Check() 360 361 self.Bind(wx.EVT_MENU, on_first_tool_click, left_item) 362 self.Bind(wx.EVT_MENU, on_second_tool_click, center_item) 363 self.config.listen_for_any(check_item_corresponding_to_config) 364 check_item_corresponding_to_config() 365
366 - def _check_view_menu_items(self, view_menu):
367 368 def item(item_id): 369 return view_menu.FindItemById(item_id)
370 371 item(ID_SIDEBAR).Check(self.config.show_sidebar) 372 item(ID_LEGEND).Check(self.config.show_legend) 373 item(ID_BALLOONS).Check(self.config.balloon_on_hover) 374 item(ID_HIDE_DONE).Check(self.config.hide_events_done) 375
376 - def _add_view_menu_items_to_controller(self, view_menu):
377 sidebar_item = view_menu.FindItemById(ID_SIDEBAR) 378 legend_item = view_menu.FindItemById(ID_LEGEND) 379 balloons_item = view_menu.FindItemById(ID_BALLOONS) 380 self.menu_controller.add_menu_requiring_visible_timeline_view(sidebar_item) 381 self.menu_controller.add_menu_requiring_timeline(legend_item) 382 self.menu_controller.add_menu_requiring_timeline(balloons_item) 383 self.menu_controller.add_menu_requiring_timeline(view_menu.FindItemById(ID_ZOOMIN)) 384 self.menu_controller.add_menu_requiring_timeline(view_menu.FindItemById(ID_ZOOMOUT)) 385 self.menu_controller.add_menu_requiring_timeline(view_menu.FindItemById(ID_VERT_ZOOMIN)) 386 self.menu_controller.add_menu_requiring_timeline(view_menu.FindItemById(ID_VERT_ZOOMOUT))
387
388 - def set_category_on_selected(self):
389 390 def edit_function(): 391 self._set_category_to_selected_events()
392 393 safe_locking(self, edit_function) 394
395 - def _create_timeline_menu(self):
396 397 def create_event(evt): 398 open_create_event_editor(self, self, self.config, self.timeline)
399 400 def edit_event(evt): 401 try: 402 event_id = self.main_panel.get_id_of_first_selected_event() 403 event = self.timeline.find_event_with_id(event_id) 404 except IndexError: 405 # No event selected so do nothing! 406 return 407 self.main_panel.open_event_editor(event) 408 409 def duplicate_event(evt): 410 try: 411 event_id = self.main_panel.get_id_of_first_selected_event() 412 event = self.timeline.find_event_with_id(event_id) 413 except IndexError: 414 # No event selected so do nothing! 415 return 416 open_duplicate_event_dialog_for_event(self, self, self.timeline, event) 417 418 def create_milestone(evt): 419 open_milestone_editor_for(self, self, self.config, self.timeline) 420 421 def set_categoryon_selected(evt): 422 423 def edit_function(): 424 self._set_category_to_selected_events() 425 safe_locking(self, edit_function) 426 427 def measure_distance(evt): 428 self._measure_distance_between_events() 429 430 def set_category_on_without(evt): 431 def edit_function(): 432 self._set_category() 433 safe_locking(self, edit_function) 434 435 def edit_eras(evt): 436 def edit_function(): 437 self._edit_eras() 438 safe_locking(self, edit_function) 439 440 def set_readonly(evt): 441 self.controller.set_timeline_in_readonly_mode() 442 443 def undo(evt): 444 safe_locking(self, self.timeline.undo) 445 446 def redo(evt): 447 safe_locking(self, self.timeline.redo) 448 449 def compress(evt): 450 safe_locking(self, self.timeline.compress) 451 452 def move_up_handler(event): 453 self.main_panel.timeline_panel.move_selected_event_up() 454 455 def move_down_handler(event): 456 self.main_panel.timeline_panel.move_selected_event_down() 457 458 cbx = NONE 459 items_spec = ((ID_CREATE_EVENT, create_event, _("Create &Event..."), cbx), 460 (ID_EDIT_EVENT, edit_event, _("&Edit Selected Event..."), cbx), 461 (ID_DUPLICATE_EVENT, duplicate_event, _("&Duplicate Selected Event..."), cbx), 462 (ID_SET_CATEGORY_ON_SELECTED, set_categoryon_selected, _("Set Category on Selected Events..."), cbx), 463 (ID_MOVE_EVENT_UP, move_up_handler, _("Move event up") + "\tAlt+Up", cbx), 464 (ID_MOVE_EVENT_DOWN, move_down_handler, _("Move event down") + "\tAlt+Down", cbx), 465 None, 466 (ID_CREATE_MILESTONE, create_milestone, _("Create &Milestone..."), cbx), 467 None, 468 (ID_COMPRESS, compress, _("&Compress timeline Events"), cbx), 469 None, 470 (ID_MEASURE_DISTANCE, measure_distance, _("&Measure Distance between two Events..."), cbx), 471 None, 472 (ID_SET_CATEGORY_ON_WITHOUT, set_category_on_without, 473 _("Set Category on events &without category..."), cbx), 474 None, 475 (ID_EDIT_ERAS, edit_eras, _("Edit Era's..."), cbx), 476 None, 477 (ID_SET_READONLY, set_readonly, _("&Read Only"), cbx), 478 None, 479 (ID_UNDO, undo, _("&Undo") + "\tCtrl+Z", cbx), 480 (ID_REDO, redo, _("&Redo") + "\tAlt+Z", cbx)) 481 self._timeline_menu = self._create_menu(items_spec) 482 self._add_timeline_menu_items_to_controller(self._timeline_menu) 483 return self._timeline_menu 484
485 - def _add_timeline_menu_items_to_controller(self, menu):
486 self._add_to_controller_requiring_writeable_timeline(menu, ID_CREATE_EVENT) 487 self._add_to_controller_requiring_writeable_timeline(menu, ID_EDIT_EVENT) 488 self._add_to_controller_requiring_writeable_timeline(menu, ID_CREATE_MILESTONE) 489 self._add_to_controller_requiring_writeable_timeline(menu, ID_DUPLICATE_EVENT) 490 self._add_to_controller_requiring_writeable_timeline(menu, ID_SET_CATEGORY_ON_SELECTED) 491 self._add_to_controller_requiring_writeable_timeline(menu, ID_MEASURE_DISTANCE) 492 self._add_to_controller_requiring_writeable_timeline(menu, ID_SET_CATEGORY_ON_WITHOUT) 493 self._add_to_controller_requiring_writeable_timeline(menu, ID_SET_READONLY) 494 self._add_to_controller_requiring_writeable_timeline(menu, ID_EDIT_ERAS) 495 self._add_to_controller_requiring_writeable_timeline(menu, ID_COMPRESS)
496
497 - def _add_to_controller_requiring_writeable_timeline(self, menu, item_id):
498 mnu_item = menu.FindItemById(item_id) 499 self.menu_controller.add_menu_requiring_writable_timeline(mnu_item)
500
501 - def _create_navigate_menu(self):
502 503 def find_first(evt): 504 event = self.timeline.get_first_event() 505 if event: 506 start = event.get_start_time() 507 delta = self.main_panel.get_displayed_period_delta() 508 end = start + delta 509 margin_delta = delta / 24 510 self.main_panel.Navigate(lambda tp: tp.update(start, end, -margin_delta))
511 512 def find_last(evt): 513 event = self.timeline.get_last_event() 514 if event: 515 end = event.get_end_time() 516 delta = self.main_panel.get_displayed_period_delta() 517 try: 518 start = end - delta 519 except ValueError: 520 start = self.timeline.get_time_type().get_min_time() 521 margin_delta = delta / 24 522 self.main_panel.Navigate(lambda tp: tp.update(start, end, end_delta=margin_delta)) 523 524 def restore_time_period(evt): 525 if self.prev_time_period: 526 self.main_panel.Navigate(lambda tp: self.prev_time_period) 527 528 def fit_all(evt): 529 self._fit_all_events() 530 531 cbx = NONE 532 items_spec = (None, 533 (ID_FIND_FIRST, find_first, _("Find &First Event"), cbx), 534 (ID_FIND_LAST, find_last, _("Find &Last Event"), cbx), 535 (ID_FIT_ALL, fit_all, _("Fit &All Events"), cbx), 536 None, 537 (ID_RESTORE_TIME_PERIOD, restore_time_period, _("Go to previous time period"), cbx),) 538 self._navigation_menu_items = [] 539 self._navigation_functions_by_menu_item_id = {} 540 self.update_navigation_menu_items() 541 self._navigate_menu = self._create_menu(items_spec) 542 self._add_navigate_menu_items_to_controller(self._navigate_menu) 543 return self._navigate_menu 544
545 - def _add_navigate_menu_items_to_controller(self, menu):
546 self._add_to_controller_requiring_timeline(menu, ID_FIND_FIRST) 547 self._add_to_controller_requiring_timeline(menu, ID_FIND_LAST) 548 self._add_to_controller_requiring_timeline(menu, ID_FIT_ALL)
549
550 - def _add_to_controller_requiring_timeline(self, menu, item_id):
551 mnu_item = menu.FindItemById(item_id) 552 self.menu_controller.add_menu_requiring_timeline(mnu_item)
553
554 - def _create_help_menu(self):
555 556 def feedback(e): 557 show_feedback_dialog(parent=None, info="", subject=_("Feedback"), body="")
558 559 cbx = NONE 560 items_spec = [(wx.ID_HELP, self.help_browser.show_contents_page, _("&Contents") + "\tF1", cbx), 561 None, 562 (ID_TUTORIAL, self.controller.open_gregorian_tutorial_timeline, _("Getting started &tutorial"), cbx), 563 (ID_NUMTUTORIAL, self.controller.open_numeric_tutorial_timeline, _("Getting started numeric &tutorial"), cbx), 564 None, 565 (ID_FEEDBACK, feedback, _("Give &Feedback..."), cbx), 566 (ID_CONTACT, self.help_browser.show_contact_page, _("Co&ntact"), cbx), 567 None, 568 (ID_SYSTEM_INFO, show_system_info_dialog, _("System information"), cbx), 569 None, 570 (wx.ID_ABOUT, display_about_dialog, None, cbx)] 571 self._help_menu = self._create_menu(items_spec) 572 return self._help_menu 573
574 - def _create_menu(self, items_spec):
575 menu = wx.Menu() 576 for item in items_spec: 577 if item is not None: 578 self._create_menu_item(menu, item) 579 else: 580 menu.AppendSeparator() 581 return menu
582
583 - def _create_menu_item(self, menu, item_spec):
584 if isinstance(item_spec, collections.Callable): 585 item_spec(menu) 586 else: 587 item_id, handler, label, checkbox = item_spec 588 if label is not None: 589 if checkbox == CHECKBOX: 590 item = menu.Append(item_id, label, kind=wx.ITEM_CHECK) 591 elif checkbox == CHECKED_RB: 592 item = menu.Append(item_id, label, kind=wx.ITEM_RADIO) 593 item.Check(True) 594 elif checkbox == UNCHECKED_RB: 595 item = menu.Append(item_id, label, kind=wx.ITEM_RADIO) 596 else: 597 if label is not None: 598 item = menu.Append(item_id, label) 599 else: 600 item = menu.Append(item_id) 601 else: 602 item = menu.Append(item_id) 603 self.shortcut_items[item_id] = menu.FindItemById(item_id) 604 self.Bind(wx.EVT_MENU, handler, item)
605
606 - def _mnu_file_new_on_click(self, event):
607 items = [ 608 { 609 "text": _("Gregorian"), 610 "description": _("This creates a timeline using the standard calendar."), 611 "create_fn": self._create_new_timeline, 612 }, 613 { 614 "text": _("Numeric"), 615 "description": _("This creates a timeline that has numbers on the x-axis instead of dates."), 616 "create_fn": self._create_new_numeric_timeline, 617 }, 618 { 619 "text": _("Directory"), 620 "description": _("This creates a timeline where the modification date of files in a directory are shown as events."), 621 "create_fn": self._create_new_dir_timeline, 622 }, 623 { 624 "text": _("Bosparanian"), 625 "description": _("This creates a timeline using the fictuous Bosparanian calendar from the German pen-and-paper RPG \"The Dark Eye\" (\"Das schwarze Auge\", DSA)."), 626 "create_fn": self._create_new_bosparanian_timeline, 627 }, 628 { 629 "text": _("Pharaonic"), 630 "description": _("This creates a timeline using the ancient egypt pharaonic calendar"), 631 "create_fn": self._create_new_pharaonic_timeline, 632 }, 633 { 634 "text": _("Coptic"), 635 "description": _("This creates a timeline using the coptic calendar"), 636 "create_fn": self._create_new_coptic_timeline, 637 }, 638 ] 639 dialog = FileNewDialog(self, items) 640 if dialog.ShowModal() == wx.ID_OK: 641 dialog.GetSelection()["create_fn"]() 642 dialog.Destroy()
643
644 - def _mnu_file_open_on_click(self, event):
645 self._open_existing_timeline()
646
647 - def mnu_file_save_as_on_click(self, event):
648 if self.timeline is not None: 649 self._save_as()
650
651 - def _mnu_file_import_on_click(self, menu):
652 def open_import_dialog(): 653 dialog = ImportEventsDialog(self.timeline, self) 654 dialog.ShowModal() 655 dialog.Destroy()
656 safe_locking(self, open_import_dialog) 657
658 - def _mnu_file_exit_on_click(self, evt):
659 self.Close()
660
661 - def _add_ellipses_to_menuitem(self, wx_id):
662 plain = wx.GetStockLabel(wx_id, wx.STOCK_WITH_ACCELERATOR | wx.STOCK_WITH_MNEMONIC) 663 # format of plain 'xxx[\tyyy]', example '&New\tCtrl+N' 664 tab_index = plain.find("\t") 665 if tab_index != -1: 666 return plain[:tab_index] + "..." + plain[tab_index:] 667 return plain + "..."
668