Show More
@@ -21,7 +21,7 import os | |||
|
21 | 21 | import IPython |
|
22 | 22 | from IPython.kernel.comm import Comm |
|
23 | 23 | from IPython.config import LoggingConfigurable |
|
24 | from IPython.utils.traitlets import Unicode, Dict, List | |
|
24 | from IPython.utils.traitlets import Unicode, Dict, List, Instance | |
|
25 | 25 | from IPython.display import Javascript, display |
|
26 | 26 | from IPython.utils.py3compat import string_types |
|
27 | 27 | |
@@ -49,17 +49,30 class Widget(LoggingConfigurable): | |||
|
49 | 49 | registered in the frontend to create and sync this widget with.""") |
|
50 | 50 | default_view_name = Unicode(help="""Default view registered in the frontend |
|
51 | 51 | to use to represent the widget.""") |
|
52 | ||
|
52 | parent = Instance('IPython.html.widgets.widget.Widget') | |
|
53 | ||
|
54 | def _parent_changed(self, name, old, new): | |
|
55 | if self._displayed: | |
|
56 | raise Exception('Parent cannot be set because widget has been displayed.') | |
|
57 | elif new == self: | |
|
58 | raise Exception('Parent cannot be set to self.') | |
|
59 | else: | |
|
60 | ||
|
61 | # Parent/child association | |
|
62 | if new is not None and not self in new._children: | |
|
63 | new._children.append(self) | |
|
64 | if old is not None and self in old._children: | |
|
65 | old._children.remove(self) | |
|
53 | 66 | |
|
54 | 67 | # Private/protected declarations |
|
55 | 68 | _keys = [] |
|
56 | 69 | _property_lock = False |
|
57 | _parent = None | |
|
58 | _children = [] | |
|
59 | 70 | _css = Dict() |
|
71 | _displayed = False | |
|
72 | _comm = None | |
|
60 | 73 | |
|
61 | 74 | |
|
62 |
def __init__(self, |
|
|
75 | def __init__(self, **kwargs): | |
|
63 | 76 | """Public constructor |
|
64 | 77 | |
|
65 | 78 | Parameters |
@@ -72,15 +85,9 class Widget(LoggingConfigurable): | |||
|
72 | 85 | widget's default view as it's child. The default view can be set |
|
73 | 86 | via the default_view_name property. |
|
74 | 87 | """ |
|
75 | super(Widget, self).__init__(**kwargs) | |
|
76 | ||
|
77 | # Parent/child association | |
|
78 | 88 | self._children = [] |
|
79 | if parent is not None: | |
|
80 | parent._children.append(self) | |
|
81 | self._parent = parent | |
|
82 | self.comm = None | |
|
83 | ||
|
89 | super(Widget, self).__init__(**kwargs) | |
|
90 | ||
|
84 | 91 | # Register after init to allow default values to be specified |
|
85 | 92 | self.on_trait_change(self._handle_property_changed, self.keys) |
|
86 | 93 | |
@@ -94,21 +101,11 class Widget(LoggingConfigurable): | |||
|
94 | 101 | """Close method. Closes the widget which closes the underlying comm. |
|
95 | 102 | When the comm is closed, all of the widget views are automatically |
|
96 | 103 | removed from the frontend.""" |
|
97 | self.comm.close() | |
|
98 | del self.comm | |
|
99 | ||
|
100 | ||
|
101 | # Properties | |
|
102 | def _get_parent(self): | |
|
103 | return self._parent | |
|
104 | parent = property(_get_parent) | |
|
105 | ||
|
106 | ||
|
107 | def _get_children(self): | |
|
108 | return copy(self._children) | |
|
109 | children = property(_get_children) | |
|
104 | self._comm.close() | |
|
105 | del self._comm | |
|
110 | 106 | |
|
111 | 107 | |
|
108 | # Properties | |
|
112 | 109 | def _get_keys(self): |
|
113 | 110 | keys = ['_css'] |
|
114 | 111 | keys.extend(self._keys) |
@@ -140,7 +137,7 class Widget(LoggingConfigurable): | |||
|
140 | 137 | |
|
141 | 138 | def _handle_property_changed(self, name, old, new): |
|
142 | 139 | """Called when a proeprty has been changed.""" |
|
143 | if not self._property_lock and self.comm is not None: | |
|
140 | if not self._property_lock and self._comm is not None: | |
|
144 | 141 | # TODO: Validate properties. |
|
145 | 142 | # Send new state to frontend |
|
146 | 143 | self.send_state(key=name) |
@@ -148,7 +145,7 class Widget(LoggingConfigurable): | |||
|
148 | 145 | |
|
149 | 146 | def _handle_close(self): |
|
150 | 147 | """Called when the comm is closed by the frontend.""" |
|
151 | self.comm = None | |
|
148 | self._comm = None | |
|
152 | 149 | |
|
153 | 150 | |
|
154 | 151 | # Public methods |
@@ -160,7 +157,7 class Widget(LoggingConfigurable): | |||
|
160 | 157 | key : unicode (optional) |
|
161 | 158 | A single property's name to sync with the frontend. |
|
162 | 159 | """ |
|
163 | if self.comm is not None: | |
|
160 | if self._comm is not None: | |
|
164 | 161 | state = {} |
|
165 | 162 | |
|
166 | 163 | # If a key is provided, just send the state of that key. |
@@ -174,7 +171,7 class Widget(LoggingConfigurable): | |||
|
174 | 171 | state[key] = getattr(self, key) |
|
175 | 172 | except Exception as e: |
|
176 | 173 | pass # Eat errors, nom nom nom |
|
177 | self.comm.send({"method": "update", | |
|
174 | self._comm.send({"method": "update", | |
|
178 | 175 | "state": state}) |
|
179 | 176 | |
|
180 | 177 | |
@@ -226,27 +223,30 class Widget(LoggingConfigurable): | |||
|
226 | 223 | ---------- |
|
227 | 224 | view_name: unicode (optional) |
|
228 | 225 | View to display in the frontend. Overrides default_view_name.""" |
|
226 | ||
|
229 | 227 | if not view_name: |
|
230 | 228 | view_name = self.default_view_name |
|
231 | 229 | |
|
232 | 230 | # Create a comm. |
|
233 | if self.comm is None: | |
|
234 | self.comm = Comm(target_name=self.target_name) | |
|
235 | self.comm.on_msg(self._handle_msg) | |
|
236 | self.comm.on_close(self._handle_close) | |
|
231 | if self._comm is None: | |
|
232 | self._comm = Comm(target_name=self.target_name) | |
|
233 | self._comm.on_msg(self._handle_msg) | |
|
234 | self._comm.on_close(self._handle_close) | |
|
237 | 235 | |
|
238 | 236 | # Make sure model is syncronized |
|
239 | 237 | self.send_state() |
|
240 | 238 | |
|
241 | 239 | # Show view. |
|
242 | if self.parent is None: | |
|
243 | self.comm.send({"method": "display", "view_name": view_name}) | |
|
240 | if self.parent is None or self.parent._comm is None: | |
|
241 | self._comm.send({"method": "display", "view_name": view_name}) | |
|
244 | 242 | else: |
|
245 | self.comm.send({"method": "display", | |
|
243 | self._comm.send({"method": "display", | |
|
246 | 244 | "view_name": view_name, |
|
247 | "parent": self.parent.comm.comm_id}) | |
|
248 | ||
|
245 | "parent": self.parent._comm.comm_id}) | |
|
246 | self._displayed = True | |
|
247 | ||
|
249 | 248 | # Now display children if any. |
|
250 | for child in self.children: | |
|
251 | child._repr_widget_() | |
|
249 | for child in self._children: | |
|
250 | if child != self: | |
|
251 | child._repr_widget_() | |
|
252 | 252 | return None |
General Comments 0
You need to be logged in to leave comments.
Login now