Show More
@@ -64,15 +64,46 b' define(["components/underscore/underscore-min",' | |||
|
64 | 64 | } |
|
65 | 65 | }, |
|
66 | 66 | |
|
67 | send = function (content) { | |
|
68 | ||
|
69 | // Used the last modified view as the sender of the message. This | |
|
70 | // will insure that any python code triggered by the sent message | |
|
71 | // can create and display widgets and output. | |
|
72 | var cell = null; | |
|
73 | if (this.last_modified_view != undefined && | |
|
74 | this.last_modified_view.cell != undefined) { | |
|
75 | cell = this.last_modified_view.cell; | |
|
76 | } | |
|
77 | var callbacks = this._make_callbacks(cell); | |
|
78 | var data = {custom_content: content}; | |
|
79 | this.comm.send(data, callbacks); | |
|
80 | }, | |
|
81 | ||
|
67 | 82 | |
|
68 | 83 | on_view_displayed: function (callback) { |
|
69 | 84 | this._view_displayed_callback = callback; |
|
70 | } | |
|
85 | }, | |
|
71 | 86 | |
|
72 | 87 | |
|
73 | 88 | on_close: function (callback) { |
|
74 | 89 | this._close_callback = callback; |
|
90 | }, | |
|
91 | ||
|
92 | ||
|
93 | on_msg: function (callback) { | |
|
94 | this._msg_callback = callback; | |
|
95 | }, | |
|
96 | ||
|
97 | ||
|
98 | _handle_custom_msg: function (content) { | |
|
99 | if (this._msg_callback) { | |
|
100 | try { | |
|
101 | this._msg_callback(content); | |
|
102 | } catch (e) { | |
|
103 | console.log("Exception in widget model msg callback", e, content); | |
|
75 | 104 | } |
|
105 | } | |
|
106 | }, | |
|
76 | 107 | |
|
77 | 108 | |
|
78 | 109 | // Handle when a widget is closed. |
@@ -108,6 +139,9 b' define(["components/underscore/underscore-min",' | |||
|
108 | 139 | case 'update': |
|
109 | 140 | this._handle_update(msg.content.data.state); |
|
110 | 141 | break; |
|
142 | case 'custom': | |
|
143 | this._handle_custom_msg(msg.content.data.custom_content); | |
|
144 | break; | |
|
111 | 145 | } |
|
112 | 146 | }, |
|
113 | 147 | |
@@ -225,7 +259,7 b' define(["components/underscore/underscore-min",' | |||
|
225 | 259 | console.log("Exception in widget model view displayed callback", e, view, this); |
|
226 | 260 | } |
|
227 | 261 | } |
|
228 | } | |
|
262 | }, | |
|
229 | 263 | |
|
230 | 264 | |
|
231 | 265 | // Create view that represents the model. |
@@ -83,6 +83,7 b' class Widget(LoggingConfigurable):' | |||
|
83 | 83 | self._add_class = [0] |
|
84 | 84 | self._remove_class = [0] |
|
85 | 85 | self._display_callbacks = [] |
|
86 | self._msg_callbacks = [] | |
|
86 | 87 | super(Widget, self).__init__(**kwargs) |
|
87 | 88 | |
|
88 | 89 | # Register after init to allow default values to be specified |
@@ -116,11 +117,39 b' class Widget(LoggingConfigurable):' | |||
|
116 | 117 | # Event handlers |
|
117 | 118 | def _handle_msg(self, msg): |
|
118 | 119 | """Called when a msg is recieved from the frontend""" |
|
120 | data = msg['content']['data'] | |
|
121 | ||
|
119 | 122 | # Handle backbone sync methods CREATE, PATCH, and UPDATE |
|
120 | sync_method = msg['content']['data']['sync_method'] | |
|
121 | sync_data = msg['content']['data']['sync_data'] | |
|
123 | if 'sync_method' in data and 'sync_data' in data: | |
|
124 | sync_method = data['sync_method'] | |
|
125 | sync_data = data['sync_data'] | |
|
122 | 126 | self._handle_recieve_state(sync_data) # handles all methods |
|
123 | 127 | |
|
128 | # Handle a custom msg from the front-end | |
|
129 | if 'custom_content' in data: | |
|
130 | self._handle_custom_msg(data['custom_content']) | |
|
131 | ||
|
132 | ||
|
133 | def _handle_custom_msg(self, content): | |
|
134 | """Called when a custom msg is recieved.""" | |
|
135 | for handler in self._msg_callbacks: | |
|
136 | if callable(handler): | |
|
137 | argspec = inspect.getargspec(handler) | |
|
138 | nargs = len(argspec[0]) | |
|
139 | ||
|
140 | # Bound methods have an additional 'self' argument | |
|
141 | if isinstance(handler, types.MethodType): | |
|
142 | nargs -= 1 | |
|
143 | ||
|
144 | # Call the callback | |
|
145 | if nargs == 1: | |
|
146 | handler(content) | |
|
147 | elif nargs == 2: | |
|
148 | handler(self, content) | |
|
149 | else: | |
|
150 | raise TypeError('Widget msg callback must ' \ | |
|
151 | 'accept 1 or 2 arguments, not %d.' % nargs) | |
|
152 | ||
|
124 | 153 | |
|
125 | 154 | def _handle_recieve_state(self, sync_data): |
|
126 | 155 | """Called when a state is recieved from the frontend.""" |
@@ -148,6 +177,34 b' class Widget(LoggingConfigurable):' | |||
|
148 | 177 | self._comm = None |
|
149 | 178 | |
|
150 | 179 | |
|
180 | def _handle_displayed(self, view_name): | |
|
181 | """Called when a view has been displayed for this widget instance | |
|
182 | ||
|
183 | Parameters | |
|
184 | ---------- | |
|
185 | view_name: unicode | |
|
186 | Name of the view that was displayed.""" | |
|
187 | for handler in self._display_callbacks: | |
|
188 | if callable(handler): | |
|
189 | argspec = inspect.getargspec(handler) | |
|
190 | nargs = len(argspec[0]) | |
|
191 | ||
|
192 | # Bound methods have an additional 'self' argument | |
|
193 | if isinstance(handler, types.MethodType): | |
|
194 | nargs -= 1 | |
|
195 | ||
|
196 | # Call the callback | |
|
197 | if nargs == 0: | |
|
198 | handler() | |
|
199 | elif nargs == 1: | |
|
200 | handler(self) | |
|
201 | elif nargs == 2: | |
|
202 | handler(self, view_name) | |
|
203 | else: | |
|
204 | raise TypeError('Widget display callback must ' \ | |
|
205 | 'accept 0-2 arguments, not %d.' % nargs) | |
|
206 | ||
|
207 | ||
|
151 | 208 | # Public methods |
|
152 | 209 | def send_state(self, key=None): |
|
153 | 210 | """Sends the widget state, or a piece of it, to the frontend. |
@@ -271,6 +328,36 b' class Widget(LoggingConfigurable):' | |||
|
271 | 328 | self.send_state(key='_remove_class') |
|
272 | 329 | |
|
273 | 330 | |
|
331 | def send(self, content): | |
|
332 | """Sends a custom msg to the widget model in the front-end. | |
|
333 | ||
|
334 | Parameters | |
|
335 | ---------- | |
|
336 | content : dict | |
|
337 | Content of the message to send. | |
|
338 | """ | |
|
339 | if self._comm is not None: | |
|
340 | self._comm.send({"method": "custom", | |
|
341 | "custom_content": content}) | |
|
342 | ||
|
343 | ||
|
344 | def on_msg(self, callback, remove=False): | |
|
345 | """Register a callback for when a custom msg is recieved from the front-end | |
|
346 | ||
|
347 | Parameters | |
|
348 | ---------- | |
|
349 | callback: method handler | |
|
350 | Can have a signature of: | |
|
351 | - callback(content) | |
|
352 | - callback(sender, content) | |
|
353 | remove: bool | |
|
354 | True if the callback should be unregistered.""" | |
|
355 | if remove and callback in self._msg_callbacks: | |
|
356 | self._msg_callbacks.remove(callback) | |
|
357 | elif not remove and not callback in self._msg_callbacks: | |
|
358 | self._msg_callbacks.append(callback) | |
|
359 | ||
|
360 | ||
|
274 | 361 | def on_displayed(self, callback, remove=False): |
|
275 | 362 | """Register a callback to be called when the widget has been displayed |
|
276 | 363 | |
@@ -283,40 +370,12 b' class Widget(LoggingConfigurable):' | |||
|
283 | 370 | - callback(sender, view_name) |
|
284 | 371 | remove: bool |
|
285 | 372 | True if the callback should be unregistered.""" |
|
286 | if remove: | |
|
373 | if remove and callback in self._display_callbacks: | |
|
287 | 374 | self._display_callbacks.remove(callback) |
|
288 | elif not callback in self._display_callbacks: | |
|
375 | elif not remove and not callback in self._display_callbacks: | |
|
289 | 376 | self._display_callbacks.append(callback) |
|
290 | 377 | |
|
291 | 378 | |
|
292 | def handle_displayed(self, view_name): | |
|
293 | """Called when a view has been displayed for this widget instance | |
|
294 | ||
|
295 | Parameters | |
|
296 | ---------- | |
|
297 | view_name: unicode | |
|
298 | Name of the view that was displayed.""" | |
|
299 | for handler in self._display_callbacks: | |
|
300 | if callable(handler): | |
|
301 | argspec = inspect.getargspec(handler) | |
|
302 | nargs = len(argspec[0]) | |
|
303 | ||
|
304 | # Bound methods have an additional 'self' argument | |
|
305 | if isinstance(handler, types.MethodType): | |
|
306 | nargs -= 1 | |
|
307 | ||
|
308 | # Call the callback | |
|
309 | if nargs == 0: | |
|
310 | handler() | |
|
311 | elif nargs == 1: | |
|
312 | handler(self) | |
|
313 | elif nargs == 2: | |
|
314 | handler(self, view_name) | |
|
315 | else: | |
|
316 | raise TypeError('Widget display callback must ' \ | |
|
317 | 'accept 0-2 arguments, not %d.' % nargs) | |
|
318 | ||
|
319 | ||
|
320 | 379 | # Support methods |
|
321 | 380 | def _repr_widget_(self, view_name=None): |
|
322 | 381 | """Function that is called when `IPython.display.display` is called on |
@@ -347,7 +406,7 b' class Widget(LoggingConfigurable):' | |||
|
347 | 406 | "view_name": view_name, |
|
348 | 407 | "parent": self.parent._comm.comm_id}) |
|
349 | 408 | self._displayed = True |
|
350 | self.handle_displayed(view_name) | |
|
409 | self._handle_displayed(view_name) | |
|
351 | 410 | |
|
352 | 411 | # Now display children if any. |
|
353 | 412 | for child in self._children: |
General Comments 0
You need to be logged in to leave comments.
Login now