from . import statusbar as statusbar\r
\r
\r
-class HookeFrame (wx.Frame):\r
+class HookeFrame (PerspectiveHooks, wx.Frame):\r
"""The main Hooke-interface window.\r
\r
\r
\r
name = self.gui.config['active perspective']\r
return # TODO: cleanup\r
- menu_item = self.GetPerspectiveMenuItem(name)\r
- if menu_item is not None:\r
- self._on_restore_perspective(menu_item)\r
- #TODO: config setting to remember playlists from last session\r
self.playlists = self._c['playlists'].Playlists\r
self._displayed_plot = None\r
#load default list, if possible\r
self.do_loadlist(self.GetStringFromConfig('core', 'preferences', 'playlist'))\r
\r
+\r
+ # GUI maintenance\r
+\r
def _setup_panels(self):\r
client_size = self.GetClientSize()\r
for label,p,style in [\r
#results panel\r
self.panelResults.results_list.OnCheckItem = self.OnResultsCheck\r
\r
+ def _on_about(self, *args):\r
+ dialog = wx.MessageDialog(\r
+ parent=self,\r
+ message=self.gui._splash_text(),\r
+ caption='About Hooke',\r
+ style=wx.OK|wx.ICON_INFORMATION)\r
+ dialog.ShowModal()\r
+ dialog.Destroy()\r
+\r
+ def _on_close(self, *args):\r
+ # apply changes\r
+ self.gui.config['main height'] = str(self.GetSize().GetHeight())\r
+ self.gui.config['main left'] = str(self.GetPosition()[0])\r
+ self.gui.config['main top'] = str(self.GetPosition()[1])\r
+ self.gui.config['main width'] = str(self.GetSize().GetWidth())\r
+ # push changes back to Hooke.config?\r
+ self._c['manager'].UnInit()\r
+ del self._c['manager']\r
+ self.Destroy()\r
+\r
+\r
+ # Command handling\r
+\r
def _command_by_name(self, name):\r
cs = [c for c in self.commands if c.name == name]\r
if len(cs) == 0:\r
self.inqueue.put(response)\r
\r
\r
+\r
+ # Command-specific postprocessing\r
+\r
+ def _postprocess_get_curve(self, command, results):\r
+ """Update `self` to show the curve.\r
+ """\r
+ if not isinstance(results[-1], Success):\r
+ return # error executing 'get curve'\r
+ assert len(results) == 2, results\r
+ curve = results[0]\r
+ print curve\r
+\r
+ selected_item = self._c['playlists']._c['tree'].GetSelection()\r
+ if self._c['playlists']._c['tree'].ItemHasChildren(selected_item):\r
+ #GetFirstChild returns a tuple\r
+ #we only need the first element\r
+ next_item = self._c['playlists']._c['tree'].GetFirstChild(selected_item)[0]\r
+ else:\r
+ next_item = self._c['playlists']._c['tree'].GetNextSibling(selected_item)\r
+ if not next_item.IsOk():\r
+ parent_item = self._c['playlists']._c['tree'].GetItemParent(selected_item)\r
+ #GetFirstChild returns a tuple\r
+ #we only need the first element\r
+ next_item = self._c['playlists']._c['tree'].GetFirstChild(parent_item)[0]\r
+ self._c['playlists']._c['tree'].SelectItem(next_item, True)\r
+ if not self._c['playlists']._c['tree'].ItemHasChildren(selected_item):\r
+ playlist = self.GetActivePlaylist()\r
+ if playlist.count > 1:\r
+ playlist.next()\r
+ self._c['status bar'].set_playlist(playlist)\r
+ self.UpdateNote()\r
+ self.UpdatePlot()\r
+\r
+\r
+\r
+ # TODO: cruft\r
+\r
def _GetActiveFileIndex(self):\r
lib.playlist.Playlist = self.GetActivePlaylist()\r
#get the selected item from the tree\r
for option in config[section]:\r
properties.append([option, config[section][option]])\r
\r
- def select_command(self, _class, method, command):\r
- self.select_plugin(plugin=command.plugin)\r
- plugin = self.GetItemText(selected_item)\r
- if plugin != 'core':\r
- doc_string = eval('plugins.' + plugin + '.' + plugin + 'Commands.__doc__')\r
- else:\r
- doc_string = 'The module "core" contains Hooke core functionality'\r
- if doc_string is not None:\r
- self.panelAssistant.ChangeValue(doc_string)\r
- else:\r
- self.panelAssistant.ChangeValue('')\r
- panel.propertyeditor.PropertyEditor.Initialize(self.panelProperties, properties)\r
- self.gui.config['selected command'] = command\r
-\r
def AddPlaylistFromFiles(self, files=[], name='Untitled'):\r
if files:\r
playlist = lib.playlist.Playlist(self, self.drivers)\r
return plotmanipulator\r
return None\r
\r
- def GetPerspectiveMenuItem(self, name):\r
- if self._perspectives.has_key(name):\r
- perspectives_list = [key for key, value in self._perspectives.iteritems()]\r
- perspectives_list.sort()\r
- index = perspectives_list.index(name)\r
- perspective_Id = ID_FirstPerspective + index\r
- menu_item = self._c['menu bar'].FindItemById(perspective_Id)\r
- return menu_item\r
- else:\r
- return None\r
-\r
def HasPlotmanipulator(self, name):\r
'''\r
returns True if the plotmanipulator 'name' is loaded, False otherwise\r
return True\r
return False\r
\r
- def _on_about(self, *args):\r
- dialog = wx.MessageDialog(\r
- parent=self,\r
- message=self.gui._splash_text(),\r
- caption='About Hooke',\r
- style=wx.OK|wx.ICON_INFORMATION)\r
- dialog.ShowModal()\r
- dialog.Destroy()\r
-\r
- def _on_close(self, *args):\r
- # apply changes\r
- self.gui.config['main height'] = str(self.GetSize().GetHeight())\r
- self.gui.config['main left'] = str(self.GetPosition()[0])\r
- self.gui.config['main top'] = str(self.GetPosition()[1])\r
- self.gui.config['main width'] = str(self.GetSize().GetWidth())\r
- # push changes back to Hooke.config?\r
- self._c['manager'].UnInit()\r
- del self._c['manager']\r
- self.Destroy()\r
-\r
- def _setup_perspectives(self):\r
- """Add perspectives to menubar and _perspectives.\r
- """\r
- self._perspectives = {\r
- 'Default': self._c['manager'].SavePerspective(),\r
- }\r
- path = self.gui.config['perspective path']\r
- if os.path.isdir(path):\r
- files = sorted(os.listdir(path))\r
- for fname in files:\r
- name, extension = os.path.splitext(fname)\r
- if extension != self.gui.config['perspective extension']:\r
- continue\r
- fpath = os.path.join(path, fname)\r
- if not os.path.isfile(fpath):\r
- continue\r
- perspective = None\r
- with open(fpath, 'rU') as f:\r
- perspective = f.readline()\r
- if perspective:\r
- self._perspectives[name] = perspective\r
-\r
- selected_perspective = self.gui.config['active perspective']\r
- if not self._perspectives.has_key(selected_perspective):\r
- self.gui.config['active perspective'] = 'Default' # TODO: push to engine's Hooke\r
-\r
- self._restore_perspective(selected_perspective)\r
- self._update_perspective_menu()\r
-\r
- def _update_perspective_menu(self):\r
- self._c['menu bar']._c['perspective'].update(\r
- sorted(self._perspectives.keys()),\r
- self.gui.config['active perspective'])\r
-\r
- def _save_perspective(self, perspective, perspective_dir, name,\r
- extension=None):\r
- path = os.path.join(perspective_dir, name)\r
- if extension != None:\r
- path += extension\r
- if not os.path.isdir(perspective_dir):\r
- os.makedirs(perspective_dir)\r
- with open(path, 'w') as f:\r
- f.write(perspective)\r
- self._perspectives[name] = perspective\r
- self._restore_perspective(name)\r
- self._update_perspective_menu()\r
-\r
- def _delete_perspectives(self, perspective_dir, names,\r
- extension=None):\r
- print 'pop', names\r
- for name in names:\r
- path = os.path.join(perspective_dir, name)\r
- if extension != None:\r
- path += extension\r
- os.remove(path)\r
- del(self._perspectives[name])\r
- self._update_perspective_menu()\r
- if self.gui.config['active perspective'] in names:\r
- self._restore_perspective('Default')\r
- # TODO: does this bug still apply?\r
- # Unfortunately, there is a bug in wxWidgets for win32 (Ticket #3258\r
- # http://trac.wxwidgets.org/ticket/3258 \r
- # ) that makes the radio item indicator in the menu disappear.\r
- # The code should be fine once this issue is fixed.\r
-\r
- def _restore_perspective(self, name):\r
- if name != self.gui.config['active perspective']:\r
- print 'restoring perspective:', name\r
- self.gui.config['active perspective'] = name # TODO: push to engine's Hooke\r
- self._c['manager'].LoadPerspective(self._perspectives[name])\r
- self._c['manager'].Update()\r
- for pane in self._c['manager'].GetAllPanes():\r
- if pane.name in self._c['menu bar']._c['view']._c.keys():\r
- pane.Check(pane.window.IsShown())\r
-\r
- def _on_save_perspective(self, *args):\r
- perspective = self._c['manager'].SavePerspective()\r
- name = self.gui.config['active perspective']\r
- if name == 'Default':\r
- name = 'New perspective'\r
- name = select_save_file(\r
- directory=self.gui.config['perspective path'],\r
- name=name,\r
- extension=self.gui.config['perspective extension'],\r
- parent=self,\r
- message='Enter a name for the new perspective:',\r
- caption='Save perspective')\r
- if name == None:\r
- return\r
- self._save_perspective(\r
- perspective, self.gui.config['perspective path'], name=name,\r
- extension=self.gui.config['perspective extension'])\r
-\r
- def _on_delete_perspective(self, *args, **kwargs):\r
- options = sorted([p for p in self._perspectives.keys()\r
- if p != 'Default'])\r
- dialog = SelectionDialog(\r
- options=options,\r
- message="\nPlease check the perspectives\n\nyou want to delete and click 'Delete'.\n",\r
- button_id=wx.ID_DELETE,\r
- selection_style='multiple',\r
- parent=self,\r
- title='Delete perspective(s)',\r
- style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)\r
- dialog.CenterOnScreen()\r
- dialog.ShowModal()\r
- names = [options[i] for i in dialog.selected]\r
- dialog.Destroy()\r
- self._delete_perspectives(\r
- self.gui.config['perspective path'], names=names,\r
- extension=self.gui.config['perspective extension'])\r
-\r
- def _on_select_perspective(self, _class, method, name):\r
- self._restore_perspective(name)\r
\r
def _on_dir_ctrl_left_double_click(self, event):\r
file_path = self.panelFolders.GetPath()\r
def _on_erase_background(self, event):\r
event.Skip()\r
\r
- def _next_curve(self, *args):\r
- """Call the `next curve` command.\r
- """\r
- results = self.execute_command(\r
- command=self._command_by_name('next curve'))\r
- if isinstance(results[-1], Success):\r
- self.execute_command(\r
- command=self._command_by_name('get curve'))\r
-\r
- def _previous_curve(self, *args):\r
- """Call the `previous curve` command.\r
- """\r
- self.execute_command(\r
- command=self._command_by_name('previous curve'))\r
- if isinstance(results[-1], Success):\r
- self.execute_command(\r
- command=self._command_by_name('get curve'))\r
-\r
- def _postprocess_get_curve(self, command, results):\r
- """Update `self` to show the curve.\r
- """\r
- if not isinstance(results[-1], Success):\r
- return # error executing 'get curve'\r
- assert len(results) == 2, results\r
- curve = results[0]\r
- print curve\r
-\r
- selected_item = self._c['playlists']._c['tree'].GetSelection()\r
- if self._c['playlists']._c['tree'].ItemHasChildren(selected_item):\r
- #GetFirstChild returns a tuple\r
- #we only need the first element\r
- next_item = self._c['playlists']._c['tree'].GetFirstChild(selected_item)[0]\r
- else:\r
- next_item = self._c['playlists']._c['tree'].GetNextSibling(selected_item)\r
- if not next_item.IsOk():\r
- parent_item = self._c['playlists']._c['tree'].GetItemParent(selected_item)\r
- #GetFirstChild returns a tuple\r
- #we only need the first element\r
- next_item = self._c['playlists']._c['tree'].GetFirstChild(parent_item)[0]\r
- self._c['playlists']._c['tree'].SelectItem(next_item, True)\r
- if not self._c['playlists']._c['tree'].ItemHasChildren(selected_item):\r
- playlist = self.GetActivePlaylist()\r
- if playlist.count > 1:\r
- playlist.next()\r
- self._c['status bar'].set_playlist(playlist)\r
- self.UpdateNote()\r
- self.UpdatePlot()\r
-\r
def _on_notebook_page_close(self, event):\r
ctrl = event.GetEventObject()\r
playlist_name = ctrl.GetPageText(ctrl._curpage)\r
active_file = self.GetActiveFile()\r
active_file.note = self.panelNote.Editor.GetValue()\r
\r
- def _on_panel_visibility(self, _class, method, panel_name, visible):\r
- pane = self._c['manager'].GetPane(panel_name)\r
- print visible\r
- pane.Show(visible)\r
- #if we don't do the following, the Folders pane does not resize properly on hide/show\r
- if pane.caption == 'Folders' and pane.IsShown() and pane.IsDocked():\r
- #folders_size = pane.GetSize()\r
- self.panelFolders.Fit()\r
- self._c['manager'].Update()\r
-\r
- def _clickize(self, xvector, yvector, index):\r
- '''\r
- Returns a ClickedPoint() object from an index and vectors of x, y coordinates\r
- '''\r
- point = lib.clickedpoint.ClickedPoint()\r
- point.index = index\r
- point.absolute_coords = xvector[index], yvector[index]\r
- point.find_graph_coords(xvector, yvector)\r
- return point\r
-\r
- def _delta(self, message='Click 2 points', block=0):\r
- '''\r
- Calculates the difference between two clicked points\r
- '''\r
- clicked_points = self._measure_N_points(N=2, message=message, block=block)\r
-\r
- plot = self.GetDisplayedPlotCorrected()\r
- curve = plot.curves[block]\r
-\r
- delta = lib.delta.Delta()\r
- delta.point1.x = clicked_points[0].graph_coords[0]\r
- delta.point1.y = clicked_points[0].graph_coords[1]\r
- delta.point2.x = clicked_points[1].graph_coords[0]\r
- delta.point2.y = clicked_points[1].graph_coords[1]\r
- delta.units.x = curve.units.x\r
- delta.units.y = curve.units.y\r
-\r
- return delta\r
-\r
- def _measure_N_points(self, N, message='', block=0):\r
- '''\r
- General helper function for N-points measurements\r
- By default, measurements are done on the retraction\r
- '''\r
- if message:\r
- dialog = wx.MessageDialog(None, message, 'Info', wx.OK)\r
- dialog.ShowModal()\r
-\r
- figure = self.GetActiveFigure()\r
-\r
- xvector = self.displayed_plot.curves[block].x\r
- yvector = self.displayed_plot.curves[block].y\r
-\r
- clicked_points = figure.ginput(N, timeout=-1, show_clicks=True)\r
-\r
- points = []\r
- for clicked_point in clicked_points:\r
- point = lib.clickedpoint.ClickedPoint()\r
- point.absolute_coords = clicked_point[0], clicked_point[1]\r
- point.dest = 0\r
- #TODO: make this optional?\r
- #so far, the clicked point is taken, not the corresponding data point\r
- point.find_graph_coords(xvector, yvector)\r
- point.is_line_edge = True\r
- point.is_marker = True\r
- points.append(point)\r
- return points\r
-\r
- def do_copylog(self):\r
- '''\r
- Copies all files in the current playlist that have a note to the destination folder.\r
- destination: select folder where you want the files to be copied\r
- use_LVDT_folder: when checked, the files will be copied to a folder called 'LVDT' in the destination folder (for MFP-1D files only)\r
- '''\r
- playlist = self.GetActivePlaylist()\r
- if playlist is not None:\r
- destination = self.GetStringFromConfig('core', 'copylog', 'destination')\r
- if not os.path.isdir(destination):\r
- os.makedirs(destination)\r
- for current_file in playlist.files:\r
- if current_file.note:\r
- shutil.copy(current_file.filename, destination)\r
- if current_file.driver.filetype == 'mfp1d':\r
- filename = current_file.filename.replace('deflection', 'LVDT', 1)\r
- path, name = os.path.split(filename)\r
- filename = os.path.join(path, 'lvdt', name)\r
- use_LVDT_folder = self.GetBoolFromConfig('core', 'copylog', 'use_LVDT_folder')\r
- if use_LVDT_folder:\r
- destination = os.path.join(destination, 'LVDT')\r
- shutil.copy(filename, destination)\r
-\r
- def do_plotmanipulators(self):\r
- '''\r
- Please select the plotmanipulators you would like to use\r
- and define the order in which they will be applied to the data.\r
-\r
- Click 'Execute' to apply your changes.\r
- '''\r
- self.UpdatePlot()\r
-\r
- def do_preferences(self):\r
- '''\r
- Please set general preferences for Hooke here.\r
- hide_curve_extension: hides the extension of the force curve files.\r
- not recommended for 'picoforce' files\r
- '''\r
- pass\r
-\r
- def do_test(self):\r
- '''\r
- Use this command for testing purposes. You find do_test in hooke.py.\r
- '''\r
- pass\r
-\r
- def do_version(self):\r
- '''\r
- VERSION\r
- ------\r
- Prints the current version and codename, plus library version. Useful for debugging.\r
- '''\r
- self.AppendToOutput('Hooke ' + __version__ + ' (' + __codename__ + ')')\r
- self.AppendToOutput('Released on: ' + __releasedate__)\r
- self.AppendToOutput('---')\r
- self.AppendToOutput('Python version: ' + python_version)\r
- self.AppendToOutput('WxPython version: ' + wx_version)\r
- self.AppendToOutput('Matplotlib version: ' + mpl_version)\r
- self.AppendToOutput('SciPy version: ' + scipy_version)\r
- self.AppendToOutput('NumPy version: ' + numpy_version)\r
- self.AppendToOutput('ConfigObj version: ' + configobj_version)\r
- self.AppendToOutput('wxPropertyGrid version: ' + '.'.join([str(PROPGRID_MAJOR), str(PROPGRID_MINOR), str(PROPGRID_RELEASE)]))\r
- self.AppendToOutput('---')\r
- self.AppendToOutput('Platform: ' + str(platform.uname()))\r
- self.AppendToOutput('******************************')\r
- self.AppendToOutput('Loaded plugins')\r
- self.AppendToOutput('---')\r
-\r
- #sort the plugins into alphabetical order\r
- plugins_list = [key for key, value in self.plugins.iteritems()]\r
- plugins_list.sort()\r
- for plugin in plugins_list:\r
- self.AppendToOutput(plugin)\r
-\r
def UpdateNote(self):\r
#update the note for the active file\r
active_file = self.GetActiveFile()\r
self.Parent.DeleteFromPlaylists(playlist_name)\r
\r
\r
+\r
+ # Command panel interface\r
+\r
+ def select_command(self, _class, method, command):\r
+ self.select_plugin(plugin=command.plugin)\r
+ plugin = self.GetItemText(selected_item)\r
+ if plugin != 'core':\r
+ doc_string = eval('plugins.' + plugin + '.' + plugin + 'Commands.__doc__')\r
+ else:\r
+ doc_string = 'The module "core" contains Hooke core functionality'\r
+ if doc_string is not None:\r
+ self.panelAssistant.ChangeValue(doc_string)\r
+ else:\r
+ self.panelAssistant.ChangeValue('')\r
+ panel.propertyeditor.PropertyEditor.Initialize(self.panelProperties, properties)\r
+ self.gui.config['selected command'] = command\r
+\r
+\r
+\r
+ # Navbar interface\r
+\r
+ def _next_curve(self, *args):\r
+ """Call the `next curve` command.\r
+ """\r
+ results = self.execute_command(\r
+ command=self._command_by_name('next curve'))\r
+ if isinstance(results[-1], Success):\r
+ self.execute_command(\r
+ command=self._command_by_name('get curve'))\r
+\r
+ def _previous_curve(self, *args):\r
+ """Call the `previous curve` command.\r
+ """\r
+ self.execute_command(\r
+ command=self._command_by_name('previous curve'))\r
+ if isinstance(results[-1], Success):\r
+ self.execute_command(\r
+ command=self._command_by_name('get curve'))\r
+\r
+\r
+\r
+ # Panel display handling\r
+\r
+ def _on_panel_visibility(self, _class, method, panel_name, visible):\r
+ pane = self._c['manager'].GetPane(panel_name)\r
+ print visible\r
+ pane.Show(visible)\r
+ #if we don't do the following, the Folders pane does not resize properly on hide/show\r
+ if pane.caption == 'Folders' and pane.IsShown() and pane.IsDocked():\r
+ #folders_size = pane.GetSize()\r
+ self.panelFolders.Fit()\r
+ self._c['manager'].Update()\r
+\r
+ def _setup_perspectives(self):\r
+ """Add perspectives to menubar and _perspectives.\r
+ """\r
+ self._perspectives = {\r
+ 'Default': self._c['manager'].SavePerspective(),\r
+ }\r
+ path = self.gui.config['perspective path']\r
+ if os.path.isdir(path):\r
+ files = sorted(os.listdir(path))\r
+ for fname in files:\r
+ name, extension = os.path.splitext(fname)\r
+ if extension != self.gui.config['perspective extension']:\r
+ continue\r
+ fpath = os.path.join(path, fname)\r
+ if not os.path.isfile(fpath):\r
+ continue\r
+ perspective = None\r
+ with open(fpath, 'rU') as f:\r
+ perspective = f.readline()\r
+ if perspective:\r
+ self._perspectives[name] = perspective\r
+\r
+ selected_perspective = self.gui.config['active perspective']\r
+ if not self._perspectives.has_key(selected_perspective):\r
+ self.gui.config['active perspective'] = 'Default' # TODO: push to engine's Hooke\r
+\r
+ self._restore_perspective(selected_perspective)\r
+ self._update_perspective_menu()\r
+\r
+ def _update_perspective_menu(self):\r
+ self._c['menu bar']._c['perspective'].update(\r
+ sorted(self._perspectives.keys()),\r
+ self.gui.config['active perspective'])\r
+\r
+ def _save_perspective(self, perspective, perspective_dir, name,\r
+ extension=None):\r
+ path = os.path.join(perspective_dir, name)\r
+ if extension != None:\r
+ path += extension\r
+ if not os.path.isdir(perspective_dir):\r
+ os.makedirs(perspective_dir)\r
+ with open(path, 'w') as f:\r
+ f.write(perspective)\r
+ self._perspectives[name] = perspective\r
+ self._restore_perspective(name)\r
+ self._update_perspective_menu()\r
+\r
+ def _delete_perspectives(self, perspective_dir, names,\r
+ extension=None):\r
+ print 'pop', names\r
+ for name in names:\r
+ path = os.path.join(perspective_dir, name)\r
+ if extension != None:\r
+ path += extension\r
+ os.remove(path)\r
+ del(self._perspectives[name])\r
+ self._update_perspective_menu()\r
+ if self.gui.config['active perspective'] in names:\r
+ self._restore_perspective('Default')\r
+ # TODO: does this bug still apply?\r
+ # Unfortunately, there is a bug in wxWidgets for win32 (Ticket #3258\r
+ # http://trac.wxwidgets.org/ticket/3258 \r
+ # ) that makes the radio item indicator in the menu disappear.\r
+ # The code should be fine once this issue is fixed.\r
+\r
+ def _restore_perspective(self, name):\r
+ if name != self.gui.config['active perspective']:\r
+ print 'restoring perspective:', name\r
+ self.gui.config['active perspective'] = name # TODO: push to engine's Hooke\r
+ self._c['manager'].LoadPerspective(self._perspectives[name])\r
+ self._c['manager'].Update()\r
+ for pane in self._c['manager'].GetAllPanes():\r
+ if pane.name in self._c['menu bar']._c['view']._c.keys():\r
+ pane.Check(pane.window.IsShown())\r
+\r
+ def _on_save_perspective(self, *args):\r
+ perspective = self._c['manager'].SavePerspective()\r
+ name = self.gui.config['active perspective']\r
+ if name == 'Default':\r
+ name = 'New perspective'\r
+ name = select_save_file(\r
+ directory=self.gui.config['perspective path'],\r
+ name=name,\r
+ extension=self.gui.config['perspective extension'],\r
+ parent=self,\r
+ message='Enter a name for the new perspective:',\r
+ caption='Save perspective')\r
+ if name == None:\r
+ return\r
+ self._save_perspective(\r
+ perspective, self.gui.config['perspective path'], name=name,\r
+ extension=self.gui.config['perspective extension'])\r
+\r
+ def _on_delete_perspective(self, *args, **kwargs):\r
+ options = sorted([p for p in self._perspectives.keys()\r
+ if p != 'Default'])\r
+ dialog = SelectionDialog(\r
+ options=options,\r
+ message="\nPlease check the perspectives\n\nyou want to delete and click 'Delete'.\n",\r
+ button_id=wx.ID_DELETE,\r
+ selection_style='multiple',\r
+ parent=self,\r
+ title='Delete perspective(s)',\r
+ style=wx.DEFAULT_DIALOG_STYLE | wx.RESIZE_BORDER)\r
+ dialog.CenterOnScreen()\r
+ dialog.ShowModal()\r
+ names = [options[i] for i in dialog.selected]\r
+ dialog.Destroy()\r
+ self._delete_perspectives(\r
+ self.gui.config['perspective path'], names=names,\r
+ extension=self.gui.config['perspective extension'])\r
+\r
+ def _on_select_perspective(self, _class, method, name):\r
+ self._restore_perspective(name)\r
+\r
+\r
+\r
class HookeApp (wx.App):\r
"""A :class:`wx.App` wrapper around :class:`HookeFrame`.\r
\r