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