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