Run update-copyright.py.
[hooke.git] / hooke / interaction.py
1 # Copyright (C) 2010-2012 W. Trevor King <wking@drexel.edu>
2 #
3 # This file is part of Hooke.
4 #
5 # Hooke is free software: you can redistribute it and/or modify it under the
6 # terms of the GNU Lesser General Public License as published by the Free
7 # Software Foundation, either version 3 of the License, or (at your option) any
8 # later version.
9 #
10 # Hooke is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with Hooke.  If not, see <http://www.gnu.org/licenses/>.
17
18 """The `interaction` module provides :class:`Request`,
19 :class:`Response`, an related classes for handling user interaction
20 through the
21 :class:`hooke.engine.CommandEngine`/:class:`hooke.ui.UserInterface`
22 connection.
23 """
24
25
26 class InList (list):
27     """:class:`Request` validator class.
28
29     Examples
30     --------
31
32     >>> i = InList(['abc', 'def', 5, True])
33     >>> i('abc')
34     >>> i(5)
35     >>> i(False)
36     Traceback (most recent call last):
37       ...
38     ValueError: False
39     """
40     def __init__(self, *args, **kwargs):
41         list.__init__(self, *args, **kwargs)
42
43     def __call__(self, value):
44         """Raises ValueError if a given `value` is not in our internal
45         list.
46         """
47         if value not in self:
48             raise ValueError(value)
49
50 class Interaction (object):
51     """Mid-command inter-process interaction.
52
53     Stores :attr:`type`, a string representing the interaction type
54     ('boolean', 'string', ...).
55     """
56     def __init__(self, type):
57         self.type = type
58
59 class Request (Interaction):
60     """Command engine requests for information from the UI.
61
62     >>> r = Request('test', 'Does response_class work?')
63     >>> r.response_class()    
64     <class 'hooke.interaction.Response'>
65     """
66     def __init__(self, type, msg, default=None, validator=None):
67         super(Request, self).__init__(type)
68         self.msg = msg
69         self.default = default
70         self.validator = validator
71
72     def response_class(self):
73         class_name = self.__class__.__name__.replace('Request', 'Response')
74         return globals()[class_name]
75
76     def response(self, value):
77         if self.validator != None:
78             self.validator(value)
79         return self.response_class()(value)
80
81 class Response (Interaction):
82     """UI response to a :class:`Request`.
83     """
84     def __init__(self, type, value):
85         super(Response, self).__init__(type)
86         self.value = value
87
88 class EOFResponse (Response):
89     """End of user input.
90
91     After this point, no more user interaction is possible.
92     """
93     def __init__(self):
94         super(EOFResponse, self).__init__('EOF', None)
95
96 class BooleanRequest (Request):
97     def __init__(self, msg, default=None):
98         super(BooleanRequest, self).__init__(
99             'boolean', msg, default,
100             validator = InList([True, False, default]))
101
102 class BooleanResponse (Response):
103     def __init__(self, value):
104         super(BooleanResponse, self).__init__('boolean', value)
105
106 class StringRequest (Request):
107     def __init__(self, msg, default=None):
108         super(StringRequest, self).__init__('string', msg, default)
109
110 class StringResponse (Response):
111     def __init__(self, value):
112         super(StringResponse, self).__init__('string', value)
113
114 class FloatRequest (Request):
115     def __init__(self, msg, default=None):
116         super(FloatRequest, self).__init__('float', msg, default)
117
118 class FloatResponse (Response):
119     def __init__(self, value):
120         super(FloatResponse, self).__init__('float', value)
121
122 class SelectionRequest (Request):
123     def __init__(self, msg, default=None, options=[]):
124         super(SelectionRequest, self).__init__('selection', msg, default)
125         self.options = options
126
127 class SelectionResponse (Response):
128     def __init__(self, value):
129         super(SelectionResponse, self).__init__('selection', value)
130
131 class PointRequest (Request):
132     def __init__(self, msg, curve, block=0, default=None):
133         super(PointRequest, self).__init__('point', msg, default)
134         self.curve = curve
135         self.block = block
136
137 class PointResponse (Response):
138     def __init__(self, value):
139         super(PointResponse, self).__init__('point', value)
140
141
142 class Notification (object):
143     def __init__(self, type):
144         self.type = type
145
146 class ReloadUserInterfaceConfig (Notification):
147     def __init__(self, config):
148         super(ReloadUserInterfaceConfig, self).__init__(
149             'reload user interface config')
150         self.config = config