Broke menu, navbar, statusbar, panel.notebook, and panel.welcome out of gui
authorW. Trevor King <wking@drexel.edu>
Mon, 26 Jul 2010 20:43:07 +0000 (16:43 -0400)
committerW. Trevor King <wking@drexel.edu>
Mon, 26 Jul 2010 20:43:07 +0000 (16:43 -0400)
hooke/ui/gui/__init__.py
hooke/ui/gui/menu.py [new file with mode: 0644]
hooke/ui/gui/navbar.py [new file with mode: 0644]
hooke/ui/gui/panel/__init__.py
hooke/ui/gui/panel/note.py
hooke/ui/gui/panel/notebook.py [new file with mode: 0644]
hooke/ui/gui/panel/welcome.py [new file with mode: 0644]
hooke/ui/gui/playlist.py
hooke/ui/gui/statusbar.py [new file with mode: 0644]

index 720c364befaee1ef2c5d464cebe3b77f4ef138af..69f5a61588a7c698ba9bdbbb45f3a43942b722ae 100644 (file)
@@ -31,145 +31,24 @@ from ...command import CommandExit, Exit, Command, Argument, StoreValue
 from ...config import Setting\r
 from ...interaction import Request, BooleanRequest, ReloadUserInterfaceConfig\r
 from ...ui import UserInterface, CommandMessage\r
+from . import menu as menu\r
+from . import navbar as navbar\r
 from . import panel as panel\r
 from . import prettyformat as prettyformat\r
-\r
-\r
-class Notebook (aui.AuiNotebook):\r
-    def __init__(self, *args, **kwargs):\r
-        super(Notebook, self).__init__(*args, **kwargs)\r
-        self.SetArtProvider(aui.AuiDefaultTabArt())\r
-        #uncomment if we find a nice icon\r
-        #page_bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))\r
-        self.AddPage(self._welcome_window(), 'Welcome')\r
-\r
-    def _welcome_window(self):\r
-        #TODO: move into panel.welcome\r
-        ctrl = wx.html.HtmlWindow(parent=self, size=wx.Size(400, 300))\r
-        lines = [\r
-            '<h1>Welcome to Hooke</h1>',\r
-            '<h3>Features</h3>',\r
-            '<ul>',\r
-            '<li>View, annotate, measure force files</li>',\r
-            '<li>Worm-like chain fit of force peaks</li>',\r
-            '<li>Automatic convolution-based filtering of empty files</li>',\r
-            '<li>Automatic fit and measurement of multiple force peaks</li>',\r
-            '<li>Handles force-clamp force experiments (experimental)</li>',\r
-            '<li>It is extensible through plugins and drivers</li>',\r
-            '</ul>',\r
-            '<p>See the <a href="%s">DocumentationIndex</a>'\r
-            % 'http://code.google.com/p/hooke/wiki/DocumentationIndex',\r
-            'for more information</p>',\r
-            ]\r
-        ctrl.SetPage('\n'.join(lines))\r
-        return ctrl\r
-\r
-\r
-class NavBar (wx.ToolBar):\r
-    def __init__(self, *args, **kwargs):\r
-        super(NavBar, self).__init__(*args, **kwargs)\r
-        self.SetToolBitmapSize(wx.Size(16,16))\r
-        self._c = {\r
-            'previous': self.AddLabelTool(\r
-                id=wx.ID_PREVIEW_PREVIOUS,\r
-                label='Previous',\r
-                bitmap=wx.ArtProvider_GetBitmap(\r
-                    wx.ART_GO_BACK, wx.ART_OTHER, wx.Size(16, 16)),\r
-                shortHelp='Previous curve'),\r
-            'next': self.AddLabelTool(\r
-                id=wx.ID_PREVIEW_NEXT,\r
-                label='Next',\r
-                bitmap=wx.ArtProvider_GetBitmap(\r
-                    wx.ART_GO_FORWARD, wx.ART_OTHER, wx.Size(16, 16)),\r
-                shortHelp='Next curve'),\r
-            }\r
-        self.Realize()\r
-\r
-\r
-class FileMenu (wx.Menu):\r
-    def __init__(self, *args, **kwargs):\r
-        super(FileMenu, self).__init__(*args, **kwargs)\r
-        self._c = {'exit': self.Append(wx.ID_EXIT)}\r
-\r
-\r
-class ViewMenu (wx.Menu):\r
-    def __init__(self, *args, **kwargs):\r
-        super(ViewMenu, self).__init__(*args, **kwargs)\r
-        self._c = {\r
-            'folders': self.AppendCheckItem(id=wx.ID_ANY, text='Folders\tF5'),\r
-            'playlist': self.AppendCheckItem(\r
-                id=wx.ID_ANY, text='Playlists\tF6'),\r
-            'commands': self.AppendCheckItem(\r
-                id=wx.ID_ANY, text='Commands\tF7'),\r
-            'assistant': self.AppendCheckItem(\r
-                id=wx.ID_ANY, text='Assistant\tF9'),\r
-            'properties': self.AppendCheckItem(\r
-                id=wx.ID_ANY, text='Properties\tF8'),\r
-            'results': self.AppendCheckItem(id=wx.ID_ANY, text='Results\tF10'),\r
-            'output': self.AppendCheckItem(id=wx.ID_ANY, text='Output\tF11'),\r
-            'note': self.AppendCheckItem(id=wx.ID_ANY, text='Note\tF12'),\r
-            }\r
-        for item in self._c.values():\r
-            item.Check()\r
-\r
-\r
-class PerspectiveMenu (wx.Menu):\r
-    def __init__(self, *args, **kwargs):\r
-        super(PerspectiveMenu, self).__init__(*args, **kwargs)\r
-        self._c = {}\r
-\r
-    def update(self, perspectives, selected, callback):\r
-        """Rebuild the perspectives menu.\r
-        """\r
-        for item in self.GetMenuItems():\r
-            self.UnBind(item)\r
-            self.DeleteItem(item)\r
-        self._c = {\r
-            'save': self.Append(id=wx.ID_ANY, text='Save Perspective'),\r
-            'delete': self.Append(id=wx.ID_ANY, text='Delete Perspective'),\r
-            }\r
-        self.AppendSeparator()\r
-        for label in perspectives:\r
-            self._c[label] = self.AppendRadioItem(id=wx.ID_ANY, text=label)\r
-            self.Bind(wx.EVT_MENU, callback, self._c[label])\r
-            if label == selected:\r
-                self._c[label].Check(True)\r
-            \r
-\r
-class HelpMenu (wx.Menu):\r
-    def __init__(self, *args, **kwargs):\r
-        super(HelpMenu, self).__init__(*args, **kwargs)\r
-        self._c = {'about':self.Append(id=wx.ID_ABOUT)}\r
-\r
-\r
-class MenuBar (wx.MenuBar):\r
-    def __init__(self, *args, **kwargs):\r
-        super(MenuBar, self).__init__(*args, **kwargs)\r
-        self._c = {\r
-            'file': FileMenu(),\r
-            'view': ViewMenu(),\r
-            'perspective': PerspectiveMenu(),\r
-            'help': HelpMenu(),\r
-            }\r
-        self.Append(self._c['file'], 'File')\r
-        self.Append(self._c['view'], 'View')\r
-        self.Append(self._c['perspective'], 'Perspective')\r
-        self.Append(self._c['help'], 'Help')\r
-\r
-\r
-class StatusBar (wx.StatusBar):\r
-    def __init__(self, *args, **kwargs):\r
-        super(StatusBar, self).__init__(*args, **kwargs)\r
-        self.SetStatusWidths([-2, -3])\r
-        self.SetStatusText('Ready', 0)\r
-        self.SetStatusText(u'Welcome to Hooke (version %s)' % version(), 1)\r
+from . import statusbar as statusbar\r
 \r
 \r
 class HookeFrame (wx.Frame):\r
-    def __init__(self, gui, commands, *args, **kwargs):\r
+    """The main Hooke-interface window.\r
+\r
+    \r
+    """\r
+    def __init__(self, gui, commands, inqueue, outqueue, *args, **kwargs):\r
         super(HookeFrame, self).__init__(*args, **kwargs)\r
         self.gui = gui\r
         self.commands = commands\r
+        self.inqueue = inqueue\r
+        self.outqueue = outqueue\r
         self._perspectives = {}  # {name: perspective_str}\r
         self._c = {}\r
 \r
@@ -196,11 +75,14 @@ class HookeFrame (wx.Frame):
 \r
         # Create the menubar after the panes so that the default\r
         # perspective is created with all panes open\r
-        self._c['menu bar'] = MenuBar(\r
+        self._c['menu bar'] = menu.MenuBar(\r
+            callbacks={},\r
             )\r
         self.SetMenuBar(self._c['menu bar'])\r
 \r
-        self._c['status bar'] = StatusBar(self, style=wx.ST_SIZEGRIP)\r
+        self._c['status bar'] = statubar.StatusBar(\r
+            parent=self,\r
+            style=wx.ST_SIZEGRIP)\r
 \r
         self._update_perspectives()\r
         self._bind_events()\r
@@ -285,7 +167,13 @@ class HookeFrame (wx.Frame):
         self._c['manager'].AddPane(panel, info)\r
 \r
     def _setup_toolbars(self):\r
-        self._c['navbar'] = NavBar(self, style=wx.TB_FLAT | wx.TB_NODIVIDER)\r
+        self._c['navbar'] = navbar.NavBar(\r
+            callbacks={\r
+                'next': self._next_curve,\r
+                'previous': self._previous_curve,\r
+                },\r
+            parent=self,\r
+            style=wx.TB_FLAT | wx.TB_NODIVIDER)\r
 \r
         self._c['manager'].AddPane(\r
             self._c['navbar'],\r
@@ -313,9 +201,6 @@ class HookeFrame (wx.Frame):
         self.Bind(wx.EVT_MENU, self._on_delete_perspective,\r
                   self._c['menu bar']._c['perspective']._c['delete'])\r
 \r
-        self.Bind(wx.EVT_TOOL, self._on_next, self._c['navbar']._c['next'])\r
-        self.Bind(wx.EVT_TOOL, self._on_previous,self._c['navbar']._c['previous'])\r
-\r
         treeCtrl = self._c['folders'].GetTreeCtrl()\r
         treeCtrl.Bind(wx.EVT_LEFT_DCLICK, self._on_dir_ctrl_left_double_click)\r
         \r
@@ -660,10 +545,7 @@ class HookeFrame (wx.Frame):
     def _on_erase_background(self, event):\r
         event.Skip()\r
 \r
-    def OnExit(self, event):\r
-        self.Close()\r
-\r
-    def _on_next(self, event):\r
+    def _next_curve(self, *args):\r
         '''\r
         NEXT\r
         Go to the next curve in the playlist.\r
@@ -688,19 +570,11 @@ class HookeFrame (wx.Frame):
             playlist = self.GetActivePlaylist()\r
             if playlist.count > 1:\r
                 playlist.next()\r
-                self.statusbar.SetStatusText(playlist.get_status_string(), 0)\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
-        self.DeleteFromPlaylists(playlist_name)\r
-\r
-    def OnPaneClose(self, event):\r
-        event.Skip()\r
-\r
-    def _on_previous(self, event):\r
+    def _previous_curve(self, *args):\r
         '''\r
         PREVIOUS\r
         Go to the previous curve in the playlist.\r
@@ -723,10 +597,18 @@ class HookeFrame (wx.Frame):
         playlist = self.GetActivePlaylist()\r
         if playlist.count > 1:\r
             playlist.previous()\r
-            self.statusbar.SetStatusText(playlist.get_status_string(), 0)\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
+        self.DeleteFromPlaylists(playlist_name)\r
+\r
+    def OnPaneClose(self, event):\r
+        event.Skip()\r
+\r
     def OnPropGridChanged (self, event):\r
         prop = event.GetProperty()\r
         if prop:\r
@@ -913,7 +795,7 @@ class HookeFrame (wx.Frame):
         playlist = self.GetActivePlaylist()\r
         if playlist is not None:\r
             if playlist.index >= 0:\r
-                self.statusbar.SetStatusText(playlist.get_status_string(), 0)\r
+                self._c['status bar'].set_playlist(playlist)\r
                 self.UpdateNote()\r
                 self.UpdatePlot()\r
 \r
@@ -1011,7 +893,7 @@ class HookeFrame (wx.Frame):
         playlist.figure = plotPanel.get_figure()\r
         self.playlists[playlist.name] = playlist\r
         #self.playlists[playlist.name] = [playlist, figure]\r
-        self.statusbar.SetStatusText(playlist.get_status_string(), 0)\r
+        self._c['status bar'].set_playlist(playlist)\r
         self.UpdateNote()\r
         self.UpdatePlot()\r
 \r
@@ -1022,7 +904,7 @@ class HookeFrame (wx.Frame):
         if current_playlist != playlist_name:\r
             index = self._GetPlaylistTab(playlist_name)\r
             self._c['notebook'].SetSelection(index)\r
-        self.statusbar.SetStatusText(playlist.get_status_string(), 0)\r
+        self._c['status bar'].set_playlist(playlist)\r
         self.UpdateNote()\r
         self.UpdatePlot()\r
 \r
@@ -1035,6 +917,11 @@ class HookeFrame (wx.Frame):
         \r
 \r
 class HookeApp (wx.App):\r
+    """A :class:`wx.App` wrapper around :class:`HookeFrame`.\r
+\r
+    Tosses up a splash screen and then loads :class:`HookeFrame` in\r
+    its own window.\r
+    """\r
     def __init__(self, gui, commands, inqueue, outqueue, *args, **kwargs):\r
         self.gui = gui\r
         self.commands = commands\r
@@ -1063,7 +950,8 @@ class HookeApp (wx.App):
 \r
         self._c = {\r
             'frame': HookeFrame(\r
-                self.gui, self.commands, parent=None, title='Hooke',\r
+                self.gui, self.commands, self.inqueue, self.outqueue,\r
+                parent=None, title='Hooke',\r
                 pos=(left, top), size=(width, height),\r
                 style=wx.DEFAULT_FRAME_STYLE|wx.SUNKEN_BORDER|wx.CLIP_CHILDREN),\r
             }\r
@@ -1090,9 +978,6 @@ class HookeApp (wx.App):
                 sleepFactor = 1.2\r
                 time.sleep(sleepFactor * duration / 1000)\r
 \r
-    def OnExit(self):\r
-        return True\r
-\r
 \r
 class GUI (UserInterface):\r
     """wxWindows graphical user interface.\r
diff --git a/hooke/ui/gui/menu.py b/hooke/ui/gui/menu.py
new file mode 100644 (file)
index 0000000..184e66d
--- /dev/null
@@ -0,0 +1,77 @@
+# Copyright
+
+"""Menu bar for Hooke.
+"""
+
+import wx
+
+
+class FileMenu (wx.Menu):
+    def __init__(self, *args, **kwargs):
+        super(FileMenu, self).__init__(*args, **kwargs)
+        self._c = {'exit': self.Append(wx.ID_EXIT)}
+
+
+class ViewMenu (wx.Menu):
+    def __init__(self, *args, **kwargs):
+        super(ViewMenu, self).__init__(*args, **kwargs)
+        self._c = {
+            'folders': self.AppendCheckItem(id=wx.ID_ANY, text='Folders\tF5'),
+            'playlist': self.AppendCheckItem(
+                id=wx.ID_ANY, text='Playlists\tF6'),
+            'commands': self.AppendCheckItem(
+                id=wx.ID_ANY, text='Commands\tF7'),
+            'assistant': self.AppendCheckItem(
+                id=wx.ID_ANY, text='Assistant\tF9'),
+            'properties': self.AppendCheckItem(
+                id=wx.ID_ANY, text='Properties\tF8'),
+            'results': self.AppendCheckItem(id=wx.ID_ANY, text='Results\tF10'),
+            '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 PerspectiveMenu (wx.Menu):
+    def __init__(self, *args, **kwargs):
+        super(PerspectiveMenu, self).__init__(*args, **kwargs)
+        self._c = {}
+
+    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(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] = 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_ABOUT)}
+
+
+class MenuBar (wx.MenuBar):
+    def __init__(self, *args, **kwargs):
+        super(MenuBar, self).__init__(*args, **kwargs)
+        self._c = {
+            'file': FileMenu(),
+            'view': ViewMenu(),
+            'perspective': PerspectiveMenu(),
+            'help': HelpMenu(),
+            }
+        self.Append(self._c['file'], 'File')
+        self.Append(self._c['view'], 'View')
+        self.Append(self._c['perspective'], 'Perspective')
+        self.Append(self._c['help'], 'Help')
diff --git a/hooke/ui/gui/navbar.py b/hooke/ui/gui/navbar.py
new file mode 100644 (file)
index 0000000..c10f6a1
--- /dev/null
@@ -0,0 +1,47 @@
+# Copyright
+
+"""Navigation bar for Hooke.
+"""
+
+import wx
+
+
+class NavBar (wx.ToolBar):
+    def __init__(self, callbacks, *args, **kwargs):
+        super(NavBar, self).__init__(*args, **kwargs)
+        self.SetToolBitmapSize(wx.Size(16,16))
+        self._c = {
+            'previous': self.AddLabelTool(
+                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_PREVIEW_NEXT,
+                label='Next',
+                bitmap=wx.ArtProvider_GetBitmap(
+                    wx.ART_GO_FORWARD, wx.ART_OTHER, wx.Size(16, 16)),
+                shortHelp='Next curve'),
+            }
+        self.Realize()
+        self._callbacks = callbacks
+        self.Bind(wx.EVT_TOOL, self._on_next, self._c['next'])
+        self.Bind(wx.EVT_TOOL, self._on_previous, self._c['previous'])
+
+    def _on_next(self, event):
+        self.next()
+
+    def _on_previous(self, event):
+        self.previous()
+
+    @callback
+    def next(self):
+        pass
+
+    @callback
+    def previous(self):
+        pass
+
+
+    
index c5a77e655c59a8d094f7638a8b8a1923937834d1..f5427765a02202ca65853abab96a57a2163621f2 100644 (file)
@@ -2,11 +2,13 @@
 \r
 from . import commands as commands\r
 from . import note as note\r
+from . import notebook as notebook\r
 from . import playlist as playlist\r
 from . import plot as plot\r
 #from . import propertyeditor as propertyeditor\r
 from . import results as results\r
 from . import selection as selection\r
+from . import welcome as welcome\r
 \r
-__all__ = [commands, note, playlist, plot, #propertyeditor,\r
-           results, selection]\r
+__all__ = [commands, note, notebook, playlist, plot, #propertyeditor,\r
+           results, selection, welcome]\r
index ff92cfe336e11dd2684ac5ed4899aa98f777f3a7..4df7db827f057ff9cb3277e13cff5a46fd449f80 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python\r
+# Copyright\r
 \r
 """Note panel for Hooke.\r
 """\r
diff --git a/hooke/ui/gui/panel/notebook.py b/hooke/ui/gui/panel/notebook.py
new file mode 100644 (file)
index 0000000..4534f42
--- /dev/null
@@ -0,0 +1,21 @@
+# Copyright
+
+"""Notebook panel for Hooke.
+"""
+
+import wx.aui as aui
+
+from .welcome import Welcome
+
+
+class Notebook (aui.AuiNotebook):
+    def __init__(self, *args, **kwargs):
+        super(Notebook, self).__init__(*args, **kwargs)
+        self.SetArtProvider(aui.AuiDefaultTabArt())
+        #uncomment if we find a nice icon
+        #page_bmp = wx.ArtProvider.GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, wx.Size(16, 16))
+        self.AddPage(
+            Welcome(
+                parent=self,
+                size=wx.Size(400, 300)),
+            'Welcome')
diff --git a/hooke/ui/gui/panel/welcome.py b/hooke/ui/gui/panel/welcome.py
new file mode 100644 (file)
index 0000000..a9f8527
--- /dev/null
@@ -0,0 +1,27 @@
+# Copyright
+
+"""Welcome panel for Hooke.
+"""
+
+import wx
+
+
+class Welcome (wx.html.HtmlWindow):
+    def __init__(self, *args, **kwargs):
+        super(Welcome, self).__init__(self, *args, **kwargs)
+        lines = [
+            '<h1>Welcome to Hooke</h1>',
+            '<h3>Features</h3>',
+            '<ul>',
+            '<li>View, annotate, measure force files</li>',
+            '<li>Worm-like chain fit of force peaks</li>',
+            '<li>Automatic convolution-based filtering of empty files</li>',
+            '<li>Automatic fit and measurement of multiple force peaks</li>',
+            '<li>Handles force-clamp force experiments (experimental)</li>',
+            '<li>It is extensible through plugins and drivers</li>',
+            '</ul>',
+            '<p>See the <a href="%s">DocumentationIndex</a>'
+            % 'http://code.google.com/p/hooke/wiki/DocumentationIndex',
+            'for more information</p>',
+            ]
+        ctrl.SetPage('\n'.join(lines))
index 90a730fec687ab575c583ca1f718612cf713af2a..9b7af3f9fa9773e0a422b68b99ab09bdcdcb17ba 100644 (file)
@@ -66,13 +66,6 @@ class Playlist(object):
         ##TODO: is this the only active (or default?) plot?\r
         #return self.files[self.index].plots[0]\r
 \r
-    def get_status_string(self):\r
-        if self.count > 0:\r
-            activeFileStr = ''.join([' (%s/%s)' %(self.index + 1, self.count)])\r
-            return ''.join([self.name, activeFileStr])\r
-        else:\r
-            return ''.join(['The file ', self.name, ' does not contain any valid force curve data.\n'])\r
-\r
     def load(self, filename):\r
         '''\r
         Loads a playlist file\r
diff --git a/hooke/ui/gui/statusbar.py b/hooke/ui/gui/statusbar.py
new file mode 100644 (file)
index 0000000..59e5859
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright
+
+"""Status bar for Hooke.
+"""
+
+import wx
+
+
+class StatusBar (wx.StatusBar):
+    def __init__(self, *args, **kwargs):
+        super(StatusBar, self).__init__(*args, **kwargs)
+        self.SetStatusWidths([-2, -3])
+        self.SetStatusText('Ready', 0)
+        self.SetStatusText(u'Welcome to Hooke (version %s)' % version(), 1)
+
+    def set_playlist(self, playlist):
+        self.SetStatusText(self._playlist_status(playlist), 0)
+
+    def set_curve(self, curve):
+        pass
+
+    def _playlist_status(self, playlist):
+        fields = [
+            playlist.name,
+            '(%d/%d)' % (playlist._index, len(playlist)),
+            ]
+        curve = playlist.current():
+        if curve != None:
+            fields.append(curve.name)
+        return ' '.join(fields)