##// END OF EJS Templates
Cleaned up Python widget code.
Jonathan Frederic -
Show More
@@ -1,3 +1,17 b''
1 """Base Widget class. Allows user to create widgets in the backend that render
2 in the IPython notebook frontend.
3 """
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2013, the IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
1 15 from copy import copy
2 16 from glob import glob
3 17 import uuid
@@ -11,6 +25,9 b' from IPython.utils.traitlets import Unicode, Dict, List'
11 25 from IPython.display import Javascript, display
12 26 from IPython.utils.py3compat import string_types
13 27
28 #-----------------------------------------------------------------------------
29 # Shared
30 #-----------------------------------------------------------------------------
14 31 def init_widget_js():
15 32 path = os.path.split(os.path.abspath( __file__ ))[0]
16 33 for filepath in glob(os.path.join(path, "*.py")):
@@ -22,14 +39,19 b' def init_widget_js():'
22 39 display(Javascript(data='$.getScript("%s");' % js_path))
23 40
24 41
42 #-----------------------------------------------------------------------------
43 # Classes
44 #-----------------------------------------------------------------------------
25 45 class Widget(LoggingConfigurable):
26 46
27 ### Public declarations
28 target_name = Unicode('widget')
29 default_view_name = Unicode()
47 # Public declarations
48 target_name = Unicode('widget', help="""Name of the backbone model
49 registered in the frontend to create and sync this widget with.""")
50 default_view_name = Unicode(help="""Default view registered in the frontend
51 to use to represent the widget.""")
30 52
31 53
32 ### Private/protected declarations
54 # Private/protected declarations
33 55 _keys = []
34 56 _property_lock = False
35 57 _parent = None
@@ -37,10 +59,22 b' class Widget(LoggingConfigurable):'
37 59 _css = Dict()
38 60
39 61
40 ### Public constructor
41 62 def __init__(self, parent=None, **kwargs):
63 """Public constructor
64
65 Parameters
66 ----------
67 parent : Widget instance (optional)
68 Widget that this widget instance is child of. When the widget is
69 displayed in the frontend, it's corresponding view will be made
70 child of the parent's view if the parent's view exists already. If
71 the parent's view is displayed, it will automatically display this
72 widget's default view as it's child. The default view can be set
73 via the default_view_name property.
74 """
42 75 super(Widget, self).__init__(**kwargs)
43 76
77 # Parent/child association
44 78 self._children = []
45 79 if parent is not None:
46 80 parent._children.append(self)
@@ -52,14 +86,19 b' class Widget(LoggingConfigurable):'
52 86
53 87
54 88 def __del__(self):
89 """Object disposal"""
55 90 self.close()
56 91
92
57 93 def close(self):
94 """Close method. Closes the widget which closes the underlying comm.
95 When the comm is closed, all of the widget views are automatically
96 removed from the frontend."""
58 97 self.comm.close()
59 98 del self.comm
60 99
61 100
62 ### Properties
101 # Properties
63 102 def _get_parent(self):
64 103 return self._parent
65 104 parent = property(_get_parent)
@@ -76,26 +115,10 b' class Widget(LoggingConfigurable):'
76 115 return keys
77 116 keys = property(_get_keys)
78 117
79 def _get_css(self, key, selector=""):
80 if selector in self._css and key in self._css[selector]:
81 return self._css[selector][key]
82 else:
83 return None
84 def _set_css(self, value, key, selector=""):
85 if selector not in self._css:
86 self._css[selector] = {}
87
88 # Only update the property if it has changed.
89 if not (key in self._css[selector] and value in self._css[selector][key]):
90 self._css[selector][key] = value
91 self.send_state() # Send new state to client.
92
93 css = property(_get_css, _set_css)
94
95 118
96 ### Event handlers
119 # Event handlers
97 120 def _handle_msg(self, msg):
98
121 """Called when a msg is recieved from the frontend"""
99 122 # Handle backbone sync methods CREATE, PATCH, and UPDATE
100 123 sync_method = msg['content']['data']['sync_method']
101 124 sync_data = msg['content']['data']['sync_data']
@@ -103,6 +126,7 b' class Widget(LoggingConfigurable):'
103 126
104 127
105 128 def _handle_recieve_state(self, sync_data):
129 """Called when a state is recieved from the frontend."""
106 130 self._property_lock = True
107 131 try:
108 132
@@ -115,6 +139,7 b' class Widget(LoggingConfigurable):'
115 139
116 140
117 141 def _handle_property_changed(self, name, old, new):
142 """Called when a proeprty has been changed."""
118 143 if not self._property_lock and self.comm is not None:
119 144 # TODO: Validate properties.
120 145 # Send new state to frontend
@@ -122,11 +147,84 b' class Widget(LoggingConfigurable):'
122 147
123 148
124 149 def _handle_close(self):
150 """Called when the comm is closed by the frontend."""
125 151 self.comm = None
126 152
127 153
128 ### Public methods
154 # Public methods
155 def send_state(self, key=None):
156 """Sends the widget state, or a piece of it, to the frontend.
157
158 Parameters
159 ----------
160 key : unicode (optional)
161 A single property's name to sync with the frontend.
162 """
163 state = {}
164
165 # If a key is provided, just send the state of that key.
166 keys = []
167 if key is None:
168 keys.extend(self.keys)
169 else:
170 keys.append(key)
171 for key in self.keys:
172 try:
173 state[key] = getattr(self, key)
174 except Exception as e:
175 pass # Eat errors, nom nom nom
176 self.comm.send({"method": "update",
177 "state": state})
178
179
180 def get_css(self, key, selector=""):
181 """Get a CSS property of the widget views (shared among all of the
182 views)
183
184 Parameters
185 ----------
186 key: unicode
187 CSS key
188 selector: unicode (optional)
189 JQuery selector used when the CSS key/value was set.
190 """
191 if selector in self._css and key in self._css[selector]:
192 return self._css[selector][key]
193 else:
194 return None
195
196
197 def set_css(self, key, value, selector=""):
198 """Set a CSS property of the widget views (shared among all of the
199 views)
200
201 Parameters
202 ----------
203 key: unicode
204 CSS key
205 value
206 CSS value
207 selector: unicode (optional)
208 JQuery selector to use to apply the CSS key/value.
209 """
210 if selector not in self._css:
211 self._css[selector] = {}
212
213 # Only update the property if it has changed.
214 if not (key in self._css[selector] and value in self._css[selector][key]):
215 self._css[selector][key] = value
216 self.send_state() # Send new state to client.
217
218
219 # Support methods
129 220 def _repr_widget_(self, view_name=None):
221 """Function that is called when `IPython.display.display` is called on
222 the widget.
223
224 Parameters
225 ----------
226 view_name: unicode (optional)
227 View to display in the frontend. Overrides default_view_name."""
130 228 if not view_name:
131 229 view_name = self.default_view_name
132 230
@@ -151,21 +249,3 b' class Widget(LoggingConfigurable):'
151 249 for child in self.children:
152 250 child._repr_widget_()
153 251 return None
154
155
156 def send_state(self, key=None):
157 state = {}
158
159 # If a key is provided, just send the state of that key.
160 keys = []
161 if key is None:
162 keys.extend(self.keys)
163 else:
164 keys.append(key)
165 for key in self.keys:
166 try:
167 state[key] = getattr(self, key)
168 except Exception as e:
169 pass # Eat errors, nom nom nom
170 self.comm.send({"method": "update",
171 "state": state})
@@ -1,12 +1,31 b''
1 """BoolWidget class.
2
3 Represents a boolean using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class BoolWidget(Widget):
5 23 target_name = Unicode('BoolWidgetModel')
6 24 default_view_name = Unicode('CheckboxView')
25
26 # Model Keys
7 27 _keys = ['value', 'description', 'disabled']
8
9 value = Bool(False)
10 description = Unicode('') # Description of the boolean (label).
11 disabled = Bool(False) # Enable or disable user changes
28 value = Bool(False, help="Bool value")
29 description = Unicode('', help="Description of the boolean (label).")
30 disabled = Bool(False, help="Enable or disable user changes.")
12 31 No newline at end of file
@@ -1,22 +1,48 b''
1 """ButtonWidget class.
2
3 Represents a button in the frontend using a widget. Allows user to listen for
4 click events on the button and trigger backend code when the clicks are fired.
5 """
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2013, the IPython Development Team.
8 #
9 # Distributed under the terms of the Modified BSD License.
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
13
14 #-----------------------------------------------------------------------------
15 # Imports
16 #-----------------------------------------------------------------------------
1 17 import inspect
2 18 import types
3 19
4 20 from widget import Widget
5 21 from IPython.utils.traitlets import Unicode, Bool, Int
6 22
23 #-----------------------------------------------------------------------------
24 # Classes
25 #-----------------------------------------------------------------------------
7 26 class ButtonWidget(Widget):
8 27 target_name = Unicode('ButtonWidgetModel')
9 28 default_view_name = Unicode('ButtonView')
29
30 # Keys
10 31 _keys = ['clicks', 'description', 'disabled']
11
12 clicks = Int(0)
13 description = Unicode('') # Description of the button (label).
14 disabled = Bool(False) # Enable or disable user changes
32 clicks = Int(0, help="Number of times the button has been clicked.")
33 description = Unicode('', help="Description of the button (label).")
34 disabled = Bool(False, help="Enable or disable user changes.")
15 35
16 36 _click_handlers = []
17 37
18 38
19 39 def on_click(self, callback, remove=False):
40 """Register a callback to execute when the button is clicked.
41
42 Parameters
43 ----------
44 remove : bool (optional)
45 Set to tru to remove the callback from the list of callbacks."""
20 46 if remove:
21 47 self._click_handlers.remove(callback)
22 48 else:
@@ -24,6 +50,8 b' class ButtonWidget(Widget):'
24 50
25 51
26 52 def _clicks_changed(self, name, old, new):
53 """Handles when the clicks property has been changed. Fires on_click
54 callbacks when appropriate."""
27 55 if new > old:
28 56 for handler in self._click_handlers:
29 57 if callable(handler):
@@ -42,4 +70,3 b' class ButtonWidget(Widget):'
42 70 else:
43 71 raise TypeError('ButtonWidget click callback must ' \
44 72 'accept 0 or 1 arguments.')
45
@@ -1,12 +1,31 b''
1 """ContainerWidget class.
2
3 Represents a container that can be used to group other widgets.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Bool
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class ContainerWidget(Widget):
5 23 target_name = Unicode('ContainerWidgetModel')
6 24 default_view_name = Unicode('ContainerView')
7 _keys = ['_vbox', '_hbox', '_start', '_end', '_center']
8 _trait_changing = False
9 25
26 # Keys, all private and managed by helper methods. Flexible box model
27 # classes...
28 _keys = ['_vbox', '_hbox', '_start', '_end', '_center']
10 29 _hbox = Bool(False)
11 30 _vbox = Bool(False)
12 31 _start = Bool(False)
@@ -14,28 +33,68 b' class ContainerWidget(Widget):'
14 33 _center = Bool(False)
15 34
16 35 def hbox(self, enabled=True):
36 """Make this container an hbox. Automatically disables conflicting
37 features.
38
39 Parameters
40 ----------
41 enabled: bool (optional)
42 Enabled or disable the hbox feature of the container, defaults to
43 True."""
17 44 self._hbox = enabled
18 45 if enabled:
19 46 self._vbox = False
20 47
21 48 def vbox(self, enabled=True):
49 """Make this container an vbox. Automatically disables conflicting
50 features.
51
52 Parameters
53 ----------
54 enabled: bool (optional)
55 Enabled or disable the vbox feature of the container, defaults to
56 True."""
22 57 self._vbox = enabled
23 58 if enabled:
24 59 self._hbox = False
25 60
26 61 def start(self, enabled=True):
62 """Make the contents of this container align to the start of the axis.
63 Automatically disables conflicting alignments.
64
65 Parameters
66 ----------
67 enabled: bool (optional)
68 Enabled or disable the start alignment of the container, defaults to
69 True."""
27 70 self._start = enabled
28 71 if enabled:
29 72 self._end = False
30 73 self._center = False
31 74
32 75 def end(self, enabled=True):
76 """Make the contents of this container align to the end of the axis.
77 Automatically disables conflicting alignments.
78
79 Parameters
80 ----------
81 enabled: bool (optional)
82 Enabled or disable the end alignment of the container, defaults to
83 True."""
33 84 self._end = enabled
34 85 if enabled:
35 86 self._start = False
36 87 self._center = False
37 88
38 89 def center(self, enabled=True):
90 """Make the contents of this container align to the center of the axis.
91 Automatically disables conflicting alignments.
92
93 Parameters
94 ----------
95 enabled: bool (optional)
96 Enabled or disable the center alignment of the container, defaults to
97 True."""
39 98 self._center = enabled
40 99 if enabled:
41 100 self._start = False
@@ -1,10 +1,29 b''
1 """FloatWidget class.
2
3 Represents an unbounded float using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Float, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class FloatWidget(Widget):
5 23 target_name = Unicode('FloatWidgetModel')
6 24 default_view_name = Unicode('FloatTextView')
25
26 # Keys
7 27 _keys = ['value', 'disabled']
8
9 value = Float(0.0)
10 disabled = Bool(False) # Enable or disable user changes
28 value = Float(0.0, help="Float value")
29 disabled = Bool(False, help="Enable or disable user changes")
@@ -1,14 +1,33 b''
1 """FloatRangeWidget class.
2
3 Represents a bounded float using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Float, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class FloatRangeWidget(Widget):
5 23 target_name = Unicode('FloatRangeWidgetModel')
6 24 default_view_name = Unicode('FloatSliderView')
25
26 # Keys
7 27 _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation']
8
9 value = Float(0.0)
10 max = Float(100.0) # Max value
11 min = Float(0.0) # Min value
12 disabled = Bool(False) # Enable or disable user changes
13 step = Float(0.1) # Minimum step that the value can take (ignored by some views)
14 orientation = Unicode(u'horizontal') # Vertical or horizontal (ignored by some views)
28 value = Float(0.0, help="Flaot value")
29 max = Float(100.0, help="Max value")
30 min = Float(0.0, help="Min value")
31 disabled = Bool(False, help="Enable or disable user changes")
32 step = Float(0.1, help="Minimum step that the value can take (ignored by some views)")
33 orientation = Unicode(u'horizontal', help="Vertical or horizontal (ignored by some views)")
@@ -1,10 +1,29 b''
1 """IntWidget class.
2
3 Represents an unbounded int using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Int, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class IntWidget(Widget):
5 23 target_name = Unicode('IntWidgetModel')
6 24 default_view_name = Unicode('IntTextView')
7 _keys = ['value', 'disabled']
8 25
9 value = Int(0)
10 disabled = Bool(False) # Enable or disable user changes
26 # Keys
27 _keys = ['value', 'disabled']
28 value = Int(0, help="Int value")
29 disabled = Bool(False, help="Enable or disable user changes")
@@ -1,14 +1,33 b''
1 """IntRangeWidget class.
2
3 Represents a bounded int using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Int, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class IntRangeWidget(Widget):
5 23 target_name = Unicode('IntRangeWidgetModel')
6 24 default_view_name = Unicode('IntSliderView')
7 _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation']
8 25
9 value = Int(0)
10 max = Int(100) # Max value
11 min = Int(0) # Min value
12 disabled = Bool(False) # Enable or disable user changes
13 step = Int(1) # Minimum step that the value can take (ignored by some views)
14 orientation = Unicode(u'horizontal') # Vertical or horizontal (ignored by some views)
26 # Keys
27 _keys = ['value', 'step', 'max', 'min', 'disabled', 'orientation']
28 value = Int(0, help="Int value")
29 max = Int(100, help="Max value")
30 min = Int(0, help="Min value")
31 disabled = Bool(False, help="Enable or disable user changes")
32 step = Int(1, help="Minimum step that the value can take (ignored by some views)")
33 orientation = Unicode(u'horizontal', help="Vertical or horizontal (ignored by some views)")
@@ -1,12 +1,31 b''
1 """SelectionWidget class.
2
3 Represents an enumeration using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, List, Bool
3 18
19 #-----------------------------------------------------------------------------
20 # SelectionWidget
21 #-----------------------------------------------------------------------------
4 22 class SelectionWidget(Widget):
5 23 target_name = Unicode('SelectionWidgetModel')
6 24 default_view_name = Unicode('DropdownView')
7 _keys = ['value', 'values', 'disabled']
8 25
9 value = Unicode()
10 values = List() # List of values the user can select
11 disabled = Bool(False) # Enable or disable user changes
26 # Keys
27 _keys = ['value', 'values', 'disabled']
28 value = Unicode(help="Selected value")
29 values = List(help="List of values the user can select")
30 disabled = Bool(False, help="Enable or disable user changes")
12 31 No newline at end of file
@@ -1,11 +1,29 b''
1 """StringWidget class.
2
3 Represents a unicode string using a widget.
4 """
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
7 #
8 # Distributed under the terms of the Modified BSD License.
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
12
13 #-----------------------------------------------------------------------------
14 # Imports
15 #-----------------------------------------------------------------------------
1 16 from widget import Widget
2 17 from IPython.utils.traitlets import Unicode, Bool, List
3 18
19 #-----------------------------------------------------------------------------
20 # Classes
21 #-----------------------------------------------------------------------------
4 22 class StringWidget(Widget):
5 23 target_name = Unicode('StringWidgetModel')
6 24 default_view_name = Unicode('TextboxView')
25
26 # Keys
7 27 _keys = ['value', 'disabled']
8
9 value = Unicode()
10 disabled = Bool(False) # Enable or disable user changes
11 No newline at end of file
28 value = Unicode(help="String value")
29 disabled = Bool(False, help="Enable or disable user changes")
General Comments 0
You need to be logged in to leave comments. Login now