From 6e7f0c7fd0aa9ff34c6e35297d9dac0fdfca12d8 Mon Sep 17 00:00:00 2001 From: "W. Trevor King" Date: Sat, 24 Jul 2010 15:58:01 -0400 Subject: [PATCH] Bound events down through folders. To go: commands, propgrid, results --- hooke/ui/gui/__init__.py | 357 ++++++++++++++++++--------------------- 1 file changed, 165 insertions(+), 192 deletions(-) diff --git a/hooke/ui/gui/__init__.py b/hooke/ui/gui/__init__.py index 5fcfb14..e4c966b 100644 --- a/hooke/ui/gui/__init__.py +++ b/hooke/ui/gui/__init__.py @@ -18,6 +18,7 @@ import wx.html import wx.aui as aui import wx.lib.evtmgr as evtmgr + # wxPropertyGrid included in wxPython >= 2.9.1, until then, see # http://wxpropgrid.sourceforge.net/cgi-bin/index?page=download # until then, we'll avoid it because of the *nix build problems. @@ -70,13 +71,13 @@ class NavBar (wx.ToolBar): self.SetToolBitmapSize(wx.Size(16,16)) self._c = { 'previous': self.AddLabelTool( - id=wx.ID_ANY, + id=wx.ID_PREVIEW_PREVIOUS, label='Previous', bitmap=wx.ArtProvider_GetBitmap( wx.ART_GO_BACK, wx.ART_OTHER, wx.Size(16, 16)), shortHelp='Previous curve'), 'next': self.AddLabelTool( - id=wx.ID_ANY, + id=wx.ID_PREVIEW_NEXT, label='Next', bitmap=wx.ArtProvider_GetBitmap( wx.ART_GO_FORWARD, wx.ART_OTHER, wx.Size(16, 16)), @@ -88,7 +89,7 @@ class NavBar (wx.ToolBar): class FileMenu (wx.Menu): def __init__(self, *args, **kwargs): super(FileMenu, self).__init__(*args, **kwargs) - self._c = {'exit': self.Append(wx.ID_EXIT, 'Exit\tCtrl-Q')} + self._c = {'exit': self.Append(wx.ID_EXIT)} class ViewMenu (wx.Menu): @@ -108,33 +109,37 @@ class ViewMenu (wx.Menu): 'output': self.AppendCheckItem(id=wx.ID_ANY, text='Output\tF11'), 'note': self.AppendCheckItem(id=wx.ID_ANY, text='Note\tF12'), } + for item in self._c.values(): + item.Check() -class PerspectivesMenu (wx.Menu): +class PerspectiveMenu (wx.Menu): def __init__(self, *args, **kwargs): - super(PerspectivesMenu, self).__init__(*args, **kwargs) + super(PerspectiveMenu, self).__init__(*args, **kwargs) self._c = {} - def update(self, perspectives, selected): + def update(self, perspectives, selected, callback): """Rebuild the perspectives menu. """ for item in self.GetMenuItems(): + self.UnBind(item) self.DeleteItem(item) self._c = { - 'save': self.Append(item='Save Perspective'), - 'delete': self.Append(item='Delete Perspective'), + 'save': self.Append(id=wx.ID_ANY, text='Save Perspective'), + 'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'), } self.AppendSeparator() for label in perspectives: - self._c[label] = menu.AppendRadioItem(item=label) - if label == selected_perspective: + self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label) + self.Bind(wx.EVT_MENU, callback, self._c[label]) + if label == selected: self._c[label].Check(True) - + class HelpMenu (wx.Menu): def __init__(self, *args, **kwargs): super(HelpMenu, self).__init__(*args, **kwargs) - self._c = {'about':self.Append(id=wx.ID_ANY, text='About Hooke')} + self._c = {'about':self.Append(id=wx.ID_ABOUT)} class MenuBar (wx.MenuBar): @@ -143,12 +148,12 @@ class MenuBar (wx.MenuBar): self._c = { 'file': FileMenu(), 'view': ViewMenu(), - 'perspectives': PerspectivesMenu(), + 'perspective': PerspectiveMenu(), 'help': HelpMenu(), } self.Append(self._c['file'], 'File') self.Append(self._c['view'], 'View') - self.Append(self._c['perspectives'], 'Perspectives') + self.Append(self._c['perspective'], 'Perspective') self.Append(self._c['help'], 'Help') @@ -191,19 +196,20 @@ class HookeFrame (wx.Frame): # Create the menubar after the panes so that the default # perspective is created with all panes open - self._c['menu bar'] = MenuBar() + self._c['menu bar'] = MenuBar( + ) self.SetMenuBar(self._c['menu bar']) self._c['status bar'] = StatusBar(self, style=wx.ST_SIZEGRIP) + self._update_perspectives() self._bind_events() - self._update_perspectives() name = self.gui.config['active perspective'] return # TODO: cleanup menu_item = self.GetPerspectiveMenuItem(name) if menu_item is not None: - self.OnRestorePerspective(menu_item) + self._on_restore_perspective(menu_item) #TODO: config setting to remember playlists from last session self.playlists = self._c['playlists'].Playlists self._displayed_plot = None @@ -279,32 +285,29 @@ class HookeFrame (wx.Frame): # TODO: figure out if we can use the eventManager for menu # ranges and events of 'self' without raising an assertion # fail error. - self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground) - self.Bind(wx.EVT_SIZE, self.OnSize) - self.Bind(wx.EVT_CLOSE, self.OnClose) - return # TODO: cleanup - # Show How To Use The Closing Panes Event + self.Bind(wx.EVT_ERASE_BACKGROUND, self._on_erase_background) + self.Bind(wx.EVT_SIZE, self._on_size) + self.Bind(wx.EVT_CLOSE, self._on_close) + self.Bind(wx.EVT_MENU, self._on_close, id=wx.ID_EXIT) + self.Bind(wx.EVT_MENU, self._on_about, id=wx.ID_ABOUT) self.Bind(aui.EVT_AUI_PANE_CLOSE, self.OnPaneClose) - self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.OnNotebookPageClose) - #menu - evtmgr.eventManager.Register(self.OnAbout, wx.EVT_MENU, win=self, id=wx.ID_ABOUT) - evtmgr.eventManager.Register(self.OnClose, wx.EVT_MENU, win=self, id=wx.ID_EXIT) - #view - self.Bind(wx.EVT_MENU_RANGE, self.OnView, id=ID_ViewAssistant, id2=ID_ViewResults) - #perspectives - self.Bind(wx.EVT_MENU, self.OnDeletePerspective, id=ID_DeletePerspective) - self.Bind(wx.EVT_MENU, self.OnSavePerspective, id=ID_SavePerspective) - self.Bind(wx.EVT_MENU_RANGE, self.OnRestorePerspective, id=ID_FirstPerspective, id2=ID_FirstPerspective+1000) - #toolbar - evtmgr.eventManager.Register(self.OnNext, wx.EVT_TOOL, win=self, id=ID_Next) - evtmgr.eventManager.Register(self.OnPrevious, wx.EVT_TOOL, win=self, id=ID_Previous) - #self.Bind(.EVT_AUITOOLBAR_TOOL_DROPDOWN, self.OnDropDownToolbarItem, id=ID_DropDownToolbarItem) - #dir control - treeCtrl = self.panelFolders.GetTreeCtrl() - #tree.Bind(wx.EVT_LEFT_UP, self.OnDirCtrl1LeftUp) - #tree.Bind(wx.EVT_LEFT_DOWN, self.OnGenericDirCtrl1LeftDown) - treeCtrl.Bind(wx.EVT_LEFT_DCLICK, self.OnDirCtrlLeftDclick) - #playlist tree + self.Bind(aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self._on_notebook_page_close) + + for value in self._c['menu bar']._c['view']._c.values(): + self.Bind(wx.EVT_MENU_RANGE, self._on_view, value) + + self.Bind(wx.EVT_MENU, self._on_save_perspective, + self._c['menu bar']._c['perspective']._c['save']) + self.Bind(wx.EVT_MENU, self._on_delete_perspective, + self._c['menu bar']._c['perspective']._c['delete']) + + self.Bind(wx.EVT_TOOL, self._on_next, self._c['navbar']._c['next']) + self.Bind(wx.EVT_TOOL, self._on_previous,self._c['navbar']._c['previous']) + + treeCtrl = self._c['folders'].GetTreeCtrl() + treeCtrl.Bind(wx.EVT_LEFT_DCLICK, self._on_dir_ctrl_left_double_click) + + return # TODO: cleanup self._c['playlists'].PlaylistsTree.Bind(wx.EVT_LEFT_DOWN, self.OnPlaylistsLeftDown) self._c['playlists'].PlaylistsTree.Bind(wx.EVT_LEFT_DCLICK, self.OnPlaylistsLeftDclick) #commands tree @@ -346,50 +349,22 @@ class HookeFrame (wx.Frame): count += 1 return playlist_name - def _RestorePerspective(self, name): + def _restore_perspective(self, name): + # TODO: cleanup + self.gui.config['active perspective'] = name # TODO: push to engine's Hooke self._c['manager'].LoadPerspective(self._perspectives[name]) - self.gui.config['active perspective'] = name self._c['manager'].Update() - all_panes = self._c['manager'].GetAllPanes() - for pane in all_panes: - if not pane.name.startswith('toolbar'): - if pane.name == 'Assistant': - self.MenuBar.FindItemById(ID_ViewAssistant).Check(pane.window.IsShown()) - if pane.name == 'Folders': - self.MenuBar.FindItemById(ID_ViewFolders).Check(pane.window.IsShown()) - if pane.name == 'Playlists': - self.MenuBar.FindItemById(ID_ViewPlaylists).Check(pane.window.IsShown()) - if pane.name == 'Commands': - self.MenuBar.FindItemById(ID_ViewCommands).Check(pane.window.IsShown()) - if pane.name == 'Note': - self.MenuBar.FindItemById(ID_ViewNote).Check(pane.window.IsShown()) - if pane.name == 'Properties': - self.MenuBar.FindItemById(ID_ViewProperties).Check(pane.window.IsShown()) - if pane.name == 'Output': - self.MenuBar.FindItemById(ID_ViewOutput).Check(pane.window.IsShown()) - if pane.name == 'Results': - self.MenuBar.FindItemById(ID_ViewResults).Check(pane.window.IsShown()) + for pane in self._c['manager'].GetAllPanes(): + if pane.name in self._c['menu bar']._c['view']._c.keys(): + pane.Check(pane.window.IsShown()) def _SavePerspectiveToFile(self, name, perspective): filename = ''.join([name, '.txt']) - filename = lh.get_file_path(filename, ['perspectives']) + filename = lh.get_file_path(filename, ['perspective']) perspectivesFile = open(filename, 'w') perspectivesFile.write(perspective) perspectivesFile.close() - def _UnbindEvents(self): - #menu - evtmgr.eventManager.DeregisterListener(self.OnAbout) - evtmgr.eventManager.DeregisterListener(self.OnClose) - #toolbar - evtmgr.eventManager.DeregisterListener(self.OnNext) - evtmgr.eventManager.DeregisterListener(self.OnPrevious) - #commands tree - evtmgr.eventManager.DeregisterListener(self.OnExecute) - evtmgr.eventManager.DeregisterListener(self.OnTreeCtrlCommandsSelectionChanged) - evtmgr.eventManager.DeregisterListener(self.OnTreeCtrlItemActivated) - evtmgr.eventManager.DeregisterListener(self.OnUpdateNote) - def AddPlaylist(self, playlist=None, name='Untitled'): if playlist and playlist.count > 0: playlist.name = self._GetUniquePlaylistName(name) @@ -556,7 +531,7 @@ class HookeFrame (wx.Frame): return True return False - def OnAbout(self, event): + def _on_about(self, event): message = 'Hooke\n\n'+\ 'A free, open source data analysis platform\n\n'+\ 'Copyright 2006-2008 by Massimo Sandal\n'+\ @@ -566,21 +541,117 @@ class HookeFrame (wx.Frame): dialog.ShowModal() dialog.Destroy() - def OnClose(self, event): + def _on_close(self, event): # apply changes self.gui.config['main height'] = str(self.GetSize().GetHeight()) self.gui.config['main left'] = str(self.GetPosition()[0]) self.gui.config['main top'] = str(self.GetPosition()[1]) self.gui.config['main width'] = str(self.GetSize().GetWidth()) # push changes back to Hooke.config? - self._UnbindEvents() self._c['manager'].UnInit() del self._c['manager'] self.Destroy() - def OnDeletePerspective(self, event): + def _update_perspectives(self): + """Add perspectives to menubar and _perspectives. + """ + self._perspectives = { + 'Default': self._c['manager'].SavePerspective(), + } + path = self.gui.config['perspective path'] + if os.path.isdir(path): + files = sorted(os.listdir(path)) + for fname in files: + name, extension = os.path.splitext(fname) + if extension != '.txt': + continue + fpath = os.path.join(path, fpath) + if not os.path.isfile(fpath): + continue + perspective = None + with open(fpath, 'rU') as f: + perspective = f.readline() + if perspective: + self._perspectives[name] = perspective + + selected_perspective = self.gui.config['active perspective'] + if not self._perspectives.has_key(selected_perspective): + self.gui.config['active perspective'] = 'Default' # TODO: push to engine's Hooke + + self._update_perspective_menu() + self._restore_perspective(selected_perspective) + + def _update_perspective_menu(self): + self._c['menu bar']._c['perspective'].update( + sorted(self._perspectives.keys()), + self.gui.config['active perspective'], + self._on_restore_perspective) + + def _on_restore_perspective(self, event): + name = self.MenuBar.FindItemById(event.GetId()).GetLabel() + self._restore_perspective(name) + + def _on_save_perspective(self, event): + def nameExists(name): + menu_position = self.MenuBar.FindMenu('Perspective') + menu = self.MenuBar.GetMenu(menu_position) + for item in menu.GetMenuItems(): + if item.GetText() == name: + return True + return False + + done = False + while not done: + dialog = wx.TextEntryDialog(self, 'Enter a name for the new perspective:', 'Save perspective') + dialog.SetValue('New perspective') + if dialog.ShowModal() != wx.ID_OK: + return + else: + name = dialog.GetValue() + + if nameExists(name): + dialogConfirm = wx.MessageDialog(self, 'A file with this name already exists.\n\nDo you want to replace it?', 'Confirm', wx.YES_NO|wx.ICON_QUESTION|wx.CENTER) + if dialogConfirm.ShowModal() == wx.ID_YES: + done = True + else: + done = True + + perspective = self._c['manager'].SavePerspective() + self._SavePerspectiveToFile(name, perspective) + self.gui.config['active perspectives'] = name + self._update_perspective_menu() +# if nameExists(name): +# #check the corresponding menu item +# menu_item = self.GetPerspectiveMenuItem(name) +# #replace the perspectiveStr in _pespectives +# self._perspectives[name] = perspective +# else: +# #because we deal with radio items, we need to do some extra work +# #delete all menu items from the perspectives menu +# for item in self._perspectives_menu.GetMenuItems(): +# self._perspectives_menu.DeleteItem(item) +# #recreate the perspectives menu +# self._perspectives_menu.Append(ID_SavePerspective, 'Save Perspective') +# self._perspectives_menu.Append(ID_DeletePerspective, 'Delete Perspective') +# self._perspectives_menu.AppendSeparator() +# #convert the perspectives dictionary into a list +# # the list contains: +# #[0]: name of the perspective +# #[1]: perspective +# perspectives_list = [key for key, value in self._perspectives.iteritems()] +# perspectives_list.append(name) +# perspectives_list.sort() +# #add all previous perspectives +# for index, item in enumerate(perspectives_list): +# menu_item = self._perspectives_menu.AppendRadioItem(ID_FirstPerspective + index, item) +# if item == name: +# menu_item.Check() +# #add the new perspective to _perspectives +# self._perspectives[name] = perspective + + def _on_delete_perspective(self, event): dialog = panel.selection.Selection( - options=sorted(os.listdir(self.gui.config['perspective-path'])), + options=sorted(os.listdir(self.gui.config['perspective path'])), message="\nPlease check the perspectives\n\nyou want to delete and click 'Delete'.\n", button_id=wx.ID_DELETE, button_callback=self._on_delete_perspective, @@ -590,9 +661,7 @@ class HookeFrame (wx.Frame): dialog.CenterOnScreen() dialog.ShowModal() dialog.Destroy() - self._c['menu bar']['perspectives'].update( - sorted(self._perspectives.keys), - self.gui.config['active perspective']) + self._update_perspective_menu() # Unfortunately, there is a bug in wxWidgets for win32 (Ticket #3258 # http://trac.wxwidgets.org/ticket/3258 # ) that makes the radio item indicator in the menu disappear. @@ -603,18 +672,19 @@ class HookeFrame (wx.Frame): self._perspectives.remove(item) if item == self.gui.config['active perspective']: self.gui.config['active perspective'] = 'Default' - path = os.path.join(self.gui.config['perspective-path'], + path = os.path.join(self.gui.config['perspective path'], item+'.txt') remove(path) + self._update_perspective_menu() - def OnDirCtrlLeftDclick(self, event): + def _on_dir_ctrl_left_double_click(self, event): file_path = self.panelFolders.GetPath() if os.path.isfile(file_path): if file_path.endswith('.hkp'): self.do_loadlist(file_path) event.Skip() - def OnEraseBackground(self, event): + def _on_erase_background(self, event): event.Skip() def OnExecute(self, event): @@ -629,7 +699,7 @@ class HookeFrame (wx.Frame): def OnExit(self, event): self.Close() - def OnNext(self, event): + def _on_next(self, event): ''' NEXT Go to the next curve in the playlist. @@ -658,7 +728,7 @@ class HookeFrame (wx.Frame): self.UpdateNote() self.UpdatePlot() - def OnNotebookPageClose(self, event): + def _on_notebook_page_close(self, event): ctrl = event.GetEventObject() playlist_name = ctrl.GetPageText(ctrl._curpage) self.DeleteFromPlaylists(playlist_name) @@ -708,7 +778,7 @@ class HookeFrame (wx.Frame): self.playlists[playlist_name] = playlist event.Skip() - def OnPrevious(self, event): + def _on_previous(self, event): ''' PREVIOUS Go to the previous curve in the playlist. @@ -748,10 +818,6 @@ class HookeFrame (wx.Frame): config[property_section][property_key]['value'] = property_value - def OnRestorePerspective(self, event): - name = self.MenuBar.FindItemById(event.GetId()).GetLabel() - self._RestorePerspective(name) - def OnResultsCheck(self, index, flag): results = self.GetActivePlot().results if results.has_key(self.results_str): @@ -759,67 +825,8 @@ class HookeFrame (wx.Frame): results[self.results_str].update() self.UpdatePlot() - def OnSavePerspective(self, event): - - def nameExists(name): - menu_position = self.MenuBar.FindMenu('Perspectives') - menu = self.MenuBar.GetMenu(menu_position) - for item in menu.GetMenuItems(): - if item.GetText() == name: - return True - return False - - done = False - while not done: - dialog = wx.TextEntryDialog(self, 'Enter a name for the new perspective:', 'Save perspective') - dialog.SetValue('New perspective') - if dialog.ShowModal() != wx.ID_OK: - return - else: - name = dialog.GetValue() - - if nameExists(name): - dialogConfirm = wx.MessageDialog(self, 'A file with this name already exists.\n\nDo you want to replace it?', 'Confirm', wx.YES_NO|wx.ICON_QUESTION|wx.CENTER) - if dialogConfirm.ShowModal() == wx.ID_YES: - done = True - else: - done = True - - perspective = self._c['manager'].SavePerspective() - self._SavePerspectiveToFile(name, perspective) - self.gui.config['active perspectives'] = name - self._c['menu bar']['perspectives'].update( - sorted(self._perspectives.keys), name) -# if nameExists(name): -# #check the corresponding menu item -# menu_item = self.GetPerspectiveMenuItem(name) -# #replace the perspectiveStr in _pespectives -# self._perspectives[name] = perspective -# else: -# #because we deal with radio items, we need to do some extra work -# #delete all menu items from the perspectives menu -# for item in self._perspectives_menu.GetMenuItems(): -# self._perspectives_menu.DeleteItem(item) -# #recreate the perspectives menu -# self._perspectives_menu.Append(ID_SavePerspective, 'Save Perspective') -# self._perspectives_menu.Append(ID_DeletePerspective, 'Delete Perspective') -# self._perspectives_menu.AppendSeparator() -# #convert the perspectives dictionary into a list -# # the list contains: -# #[0]: name of the perspective -# #[1]: perspective -# perspectives_list = [key for key, value in self._perspectives.iteritems()] -# perspectives_list.append(name) -# perspectives_list.sort() -# #add all previous perspectives -# for index, item in enumerate(perspectives_list): -# menu_item = self._perspectives_menu.AppendRadioItem(ID_FirstPerspective + index, item) -# if item == name: -# menu_item.Check() -# #add the new perspective to _perspectives -# self._perspectives[name] = perspective - def OnSize(self, event): + def _on_size(self, event): event.Skip() def OnTreeCtrlCommandsSelectionChanged(self, event): @@ -871,7 +878,7 @@ class HookeFrame (wx.Frame): active_file = self.GetActiveFile() active_file.note = self.panelNote.Editor.GetValue() - def OnView(self, event): + def _on_view(self, event): menu_id = event.GetId() menu_item = self.MenuBar.FindItemById(menu_id) menu_label = menu_item.GetLabel() @@ -1022,40 +1029,6 @@ class HookeFrame (wx.Frame): if active_file is not None: self.panelNote.Editor.SetValue(active_file.note) - def _update_perspectives(self): - # add perspectives to menubar and _perspectives - self._perspectives = {} - return # TODO: cleanup - if os.path.isdir(perspectivesDirectory): - perspectiveFileNames = os.listdir(perspectivesDirectory) - for perspectiveFilename in perspectiveFileNames: - filename = lh.get_file_path(perspectiveFilename, ['perspectives']) - if os.path.isfile(filename): - perspectiveFile = open(filename, 'rU') - perspective = perspectiveFile.readline() - perspectiveFile.close() - if perspective: - name, extension = os.path.splitext(perspectiveFilename) - if extension == '.txt': - self._perspectives[name] = perspective - - #in case there are no perspectives - if not self._perspectives: - perspective = self._c['manager'].SavePerspective() - self._perspectives['Default'] = perspective - self._SavePerspectiveToFile('Default', perspective) - - selected_perspective = self.gui.config['active perspective'] - if not self._perspectives.has_key(selected_perspective): - self.gui.config['active perspective'] = 'Default' - selected_perspective = 'Default' - - self._c['menu']._c['perspectives'].update( - sorted(self._perspectives.keys()), selected_perspective) - - self._RestorePerspective(selected_perspective) - - def UpdatePlaylistsTreeSelection(self): playlist = self.GetActivePlaylist() if playlist is not None: @@ -1240,8 +1213,8 @@ class GUI (UserInterface): Setting(section=self.setting_section, option='splash screen duration', value=1000, help='Duration of the splash screen in milliseconds.'), - Setting(section=self.setting_section, option='perspective-path', - value=os.path.join('resources', 'gui', 'perspectives'), + Setting(section=self.setting_section, option='perspective path', + value=os.path.join('resources', 'gui', 'perspective'), help='Directory containing perspective files.'), # TODO: allow colon separated list, like $PATH. Setting(section=self.setting_section, option='folders-workdir', value='.', -- 2.26.2