##// END OF EJS Templates
Added support for custom widget msgs
Jonathan Frederic -
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