1 # Copyright (C) 2010 W. Trevor King <wking@drexel.edu>
3 # This file is part of Hooke.
5 # Hooke is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as
7 # published by the Free Software Foundation, either version 3 of the
8 # License, or (at your option) any later version.
10 # Hooke is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
13 # Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with Hooke. If not, see
17 # <http://www.gnu.org/licenses/>.
19 """The `ui` module provides :class:`UserInterface` and various subclasses.
22 import ConfigParser as configparser
24 from .. import version
25 from ..config import Setting
26 from ..engine import CloseEngine, CommandMessage
27 from ..util.pluggable import IsSubclass, construct_odict
30 from ..license import short_license
31 except ImportError, e:
33 logging.warn('Could not load short_license from hooke.license')
34 from .. import __license__
35 def short_license(extra_info, **kwargs):
39 USER_INTERFACE_MODULES = [
43 """List of user interface modules. TODO: autodiscovery
46 USER_INTERFACE_SETTING_SECTION = 'user interfaces'
47 """Name of the config section which controls UI selection.
51 class UserInterface (object):
52 """A user interface to drive the :class:`hooke.engine.CommandEngine`.
54 def __init__(self, name):
56 self.setting_section = '%s user interface' % (self.name)
59 def default_settings(self):
60 """Return a list of :class:`hooke.config.Setting`\s for any
61 configurable UI settings.
63 The suggested section setting is::
65 Setting(section=self.setting_section, help=self.__doc__)
69 def reload_config(self, config):
70 """Update the user interface for new config settings.
72 Should be called with the new `config` upon recipt of
73 `ReloadUserInterfaceConfig` from the `CommandEngine` or when
74 loading the initial configuration.
77 self.config = dict(config.items(self.setting_section))
78 except configparser.NoSectionError:
81 def run(self, commands, ui_to_command_queue, command_to_ui_queue):
84 # Assorted useful tidbits for subclasses
86 def _splash_text(self, extra_info, **kwargs):
92 """ % (version(), short_license(extra_info, **kwargs))).strip()
94 def _playlist_status(self, playlist):
96 return '%s (%s/%s)' % (playlist.name, playlist.index() + 1,
98 return 'The playlist %s does not contain any valid force curve data.' \
102 USER_INTERFACES = construct_odict(
103 this_modname=__name__,
104 submodnames=USER_INTERFACE_MODULES,
105 class_selector=IsSubclass(UserInterface, blacklist=[UserInterface]))
106 """:class:`hooke.compat.odict.odict` of :class:`UserInterface`
107 instances keyed by `.name`.
110 def default_settings():
111 settings = [Setting(USER_INTERFACE_SETTING_SECTION,
112 help='Select the user interface (only one).')]
113 for i,ui in enumerate(USER_INTERFACES.values()):
114 help = ui.__doc__.split('\n', 1)[0]
115 settings.append(Setting(USER_INTERFACE_SETTING_SECTION,
116 ui.name, str(i==0), help=help))
117 # i==0 to enable the first by default
118 for ui in USER_INTERFACES.values():
119 settings.extend(ui.default_settings())
122 def load_ui(config, name=None):
124 uis = [c for c,v in config.items(USER_INTERFACE_SETTING_SECTION) if v == 'True']
125 assert len(uis) == 1, 'Can only select one UI, not %d: %s' % (len(uis),uis)
127 ui = USER_INTERFACES[name]
128 ui.reload_config(config)