# Copyright\r
\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, notebook, playlist, plot, #propertyeditor,\r
- results, selection, welcome]\r
+from ....util.pluggable import IsSubclass, construct_odict\r
+\r
+\r
+PANEL_MODULES = [\r
+ 'commands',\r
+# 'note',\r
+# 'notebook',\r
+# 'playlist',\r
+# 'plot',\r
+# 'propertyeditor',\r
+# 'results',\r
+# 'selection',\r
+# 'welcome',\r
+ ]\r
+"""List of panel modules. TODO: autodiscovery\r
+"""\r
+\r
+class Panel (object):\r
+ """Base class for Hooke GUI panels.\r
+ \r
+ :attr:`name` identifies the request type and should match the\r
+ module name.\r
+ """\r
+ def __init__(self, name=None, callbacks=None, **kwargs):\r
+ super(Panel, self).__init__(**kwargs)\r
+ self.name = name\r
+ if callbacks == None:\r
+ callbacks = {}\r
+ self._callbacks = callbacks\r
+\r
+\r
+PANELS = construct_odict(\r
+ this_modname=__name__,\r
+ submodnames=PANEL_MODULES,\r
+ class_selector=IsSubclass(Panel, blacklist=[Panel]),\r
+ instantiate=False)\r
+""":class:`hooke.compat.odict.odict` of :class:`Panel`\r
+instances keyed by `.name`.\r
+"""\r