Show More
@@ -63,16 +63,47 b' define(["components/underscore/underscore-min",' | |||||
63 | } |
|
63 | } | |
64 | } |
|
64 | } | |
65 | }, |
|
65 | }, | |
|
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 | }, | |||
66 |
|
81 | |||
67 |
|
82 | |||
68 | on_view_displayed: function (callback) { |
|
83 | on_view_displayed: function (callback) { | |
69 | this._view_displayed_callback = callback; |
|
84 | this._view_displayed_callback = callback; | |
70 | } |
|
85 | }, | |
71 |
|
86 | |||
72 |
|
87 | |||
73 | on_close: function (callback) { |
|
88 | on_close: function (callback) { | |
74 | this._close_callback = callback; |
|
89 | this._close_callback = callback; | |
75 | } |
|
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); | |||
|
104 | } | |||
|
105 | } | |||
|
106 | }, | |||
76 |
|
107 | |||
77 |
|
108 | |||
78 | // Handle when a widget is closed. |
|
109 | // Handle when a widget is closed. | |
@@ -108,6 +139,9 b' define(["components/underscore/underscore-min",' | |||||
108 | case 'update': |
|
139 | case 'update': | |
109 | this._handle_update(msg.content.data.state); |
|
140 | this._handle_update(msg.content.data.state); | |
110 | break; |
|
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 | console.log("Exception in widget model view displayed callback", e, view, this); |
|
259 | console.log("Exception in widget model view displayed callback", e, view, this); | |
226 | } |
|
260 | } | |
227 | } |
|
261 | } | |
228 | } |
|
262 | }, | |
229 |
|
263 | |||
230 |
|
264 | |||
231 | // Create view that represents the model. |
|
265 | // Create view that represents the model. |
@@ -83,6 +83,7 b' class Widget(LoggingConfigurable):' | |||||
83 | self._add_class = [0] |
|
83 | self._add_class = [0] | |
84 | self._remove_class = [0] |
|
84 | self._remove_class = [0] | |
85 | self._display_callbacks = [] |
|
85 | self._display_callbacks = [] | |
|
86 | self._msg_callbacks = [] | |||
86 | super(Widget, self).__init__(**kwargs) |
|
87 | super(Widget, self).__init__(**kwargs) | |
87 |
|
88 | |||
88 | # Register after init to allow default values to be specified |
|
89 | # Register after init to allow default values to be specified | |
@@ -116,10 +117,38 b' class Widget(LoggingConfigurable):' | |||||
116 | # Event handlers |
|
117 | # Event handlers | |
117 | def _handle_msg(self, msg): |
|
118 | def _handle_msg(self, msg): | |
118 | """Called when a msg is recieved from the frontend""" |
|
119 | """Called when a msg is recieved from the frontend""" | |
|
120 | data = msg['content']['data'] | |||
|
121 | ||||
119 | # Handle backbone sync methods CREATE, PATCH, and UPDATE |
|
122 | # Handle backbone sync methods CREATE, PATCH, and UPDATE | |
120 | sync_method = msg['content']['data']['sync_method'] |
|
123 | if 'sync_method' in data and 'sync_data' in data: | |
121 | sync_data = msg['content']['data']['sync_data'] |
|
124 | sync_method = data['sync_method'] | |
122 | self._handle_recieve_state(sync_data) # handles all methods |
|
125 | sync_data = data['sync_data'] | |
|
126 | self._handle_recieve_state(sync_data) # handles all methods | |||
|
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) | |||
123 |
|
152 | |||
124 |
|
153 | |||
125 | def _handle_recieve_state(self, sync_data): |
|
154 | def _handle_recieve_state(self, sync_data): | |
@@ -146,6 +175,34 b' class Widget(LoggingConfigurable):' | |||||
146 | def _handle_close(self): |
|
175 | def _handle_close(self): | |
147 | """Called when the comm is closed by the frontend.""" |
|
176 | """Called when the comm is closed by the frontend.""" | |
148 | self._comm = None |
|
177 | self._comm = None | |
|
178 | ||||
|
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) | |||
149 |
|
206 | |||
150 |
|
207 | |||
151 | # Public methods |
|
208 | # Public methods | |
@@ -271,6 +328,36 b' class Widget(LoggingConfigurable):' | |||||
271 | self.send_state(key='_remove_class') |
|
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 | def on_displayed(self, callback, remove=False): |
|
361 | def on_displayed(self, callback, remove=False): | |
275 | """Register a callback to be called when the widget has been displayed |
|
362 | """Register a callback to be called when the widget has been displayed | |
276 |
|
363 | |||
@@ -283,40 +370,12 b' class Widget(LoggingConfigurable):' | |||||
283 | - callback(sender, view_name) |
|
370 | - callback(sender, view_name) | |
284 | remove: bool |
|
371 | remove: bool | |
285 | True if the callback should be unregistered.""" |
|
372 | True if the callback should be unregistered.""" | |
286 | if remove: |
|
373 | if remove and callback in self._display_callbacks: | |
287 | self._display_callbacks.remove(callback) |
|
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 | self._display_callbacks.append(callback) |
|
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 | # Support methods |
|
379 | # Support methods | |
321 | def _repr_widget_(self, view_name=None): |
|
380 | def _repr_widget_(self, view_name=None): | |
322 | """Function that is called when `IPython.display.display` is called on |
|
381 | """Function that is called when `IPython.display.display` is called on | |
@@ -347,7 +406,7 b' class Widget(LoggingConfigurable):' | |||||
347 | "view_name": view_name, |
|
406 | "view_name": view_name, | |
348 | "parent": self.parent._comm.comm_id}) |
|
407 | "parent": self.parent._comm.comm_id}) | |
349 | self._displayed = True |
|
408 | self._displayed = True | |
350 | self.handle_displayed(view_name) |
|
409 | self._handle_displayed(view_name) | |
351 |
|
410 | |||
352 | # Now display children if any. |
|
411 | # Now display children if any. | |
353 | for child in self._children: |
|
412 | for child in self._children: |
General Comments 0
You need to be logged in to leave comments.
Login now