##// END OF EJS Templates
Decoupled Python Widget from Comm...
Jonathan Frederic -
Show More
@@ -74,8 +74,7 b' class Widget(LoggingConfigurable):'
74 _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
74 _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
75 _css = Dict() # Internal CSS property dict
75 _css = Dict() # Internal CSS property dict
76 _displayed = False
76 _displayed = False
77 _comm = None
77
78
79
78
80 def __init__(self, **kwargs):
79 def __init__(self, **kwargs):
81 """Public constructor
80 """Public constructor
@@ -110,11 +109,7 b' class Widget(LoggingConfigurable):'
110 """Close method. Closes the widget which closes the underlying comm.
109 """Close method. Closes the widget which closes the underlying comm.
111 When the comm is closed, all of the widget views are automatically
110 When the comm is closed, all of the widget views are automatically
112 removed from the frontend."""
111 removed from the frontend."""
113 try:
112 self._close_communication()
114 self._comm.close()
115 del self._comm
116 except:
117 pass # Comm doesn't exist and/or is already closed.
118
113
119
114
120 # Properties
115 # Properties
@@ -180,18 +175,11 b' class Widget(LoggingConfigurable):'
180 def _handle_property_changed(self, name, old, new):
175 def _handle_property_changed(self, name, old, new):
181 """Called when a proeprty has been changed."""
176 """Called when a proeprty has been changed."""
182 # Make sure this isn't information that the front-end just sent us.
177 # Make sure this isn't information that the front-end just sent us.
183 if self._property_lock[0] != name and self._property_lock[1] != new \
178 if self._property_lock[0] != name and self._property_lock[1] != new:
184 and self._comm is not None:
185 # TODO: Validate properties.
186 # Send new state to frontend
179 # Send new state to frontend
187 self.send_state(key=name)
180 self.send_state(key=name)
188
181
189
182
190 def _handle_close(self):
191 """Called when the comm is closed by the frontend."""
192 self._comm = None
193
194
195 def _handle_displayed(self, view_name, parent=None):
183 def _handle_displayed(self, view_name, parent=None):
196 """Called when a view has been displayed for this widget instance
184 """Called when a view has been displayed for this widget instance
197
185
@@ -233,22 +221,21 b' class Widget(LoggingConfigurable):'
233 key : unicode (optional)
221 key : unicode (optional)
234 A single property's name to sync with the frontend.
222 A single property's name to sync with the frontend.
235 """
223 """
236 if self._comm is not None:
224 state = {}
237 state = {}
238
225
239 # If a key is provided, just send the state of that key.
226 # If a key is provided, just send the state of that key.
240 keys = []
227 keys = []
241 if key is None:
228 if key is None:
242 keys.extend(self.keys)
229 keys.extend(self.keys)
243 else:
230 else:
244 keys.append(key)
231 keys.append(key)
245 for key in self.keys:
232 for key in self.keys:
246 try:
233 try:
247 state[key] = getattr(self, key)
234 state[key] = getattr(self, key)
248 except Exception as e:
235 except Exception as e:
249 pass # Eat errors, nom nom nom
236 pass # Eat errors, nom nom nom
250 self._comm.send({"method": "update",
237 self._send({"method": "update",
251 "state": state})
238 "state": state})
252
239
253
240
254 def get_css(self, key, selector=""):
241 def get_css(self, key, selector=""):
@@ -327,10 +314,9 b' class Widget(LoggingConfigurable):'
327 JQuery selector to select the DOM element(s) that the class(es) will
314 JQuery selector to select the DOM element(s) that the class(es) will
328 be added to.
315 be added to.
329 """
316 """
330 if self._comm is not None:
317 self._send({"method": "add_class",
331 self._comm.send({"method": "add_class",
318 "class_list": class_name,
332 "class_list": class_name,
319 "selector": selector})
333 "selector": selector})
334
320
335
321
336 def remove_class(self, class_name, selector=""):
322 def remove_class(self, class_name, selector=""):
@@ -345,10 +331,9 b' class Widget(LoggingConfigurable):'
345 JQuery selector to select the DOM element(s) that the class(es) will
331 JQuery selector to select the DOM element(s) that the class(es) will
346 be removed from.
332 be removed from.
347 """
333 """
348 if self._comm is not None:
334 self._send({"method": "remove_class",
349 self._comm.send({"method": "remove_class",
335 "class_list": class_name,
350 "class_list": class_name,
336 "selector": selector})
351 "selector": selector})
352
337
353
338
354 def send(self, content):
339 def send(self, content):
@@ -359,9 +344,8 b' class Widget(LoggingConfigurable):'
359 content : dict
344 content : dict
360 Content of the message to send.
345 Content of the message to send.
361 """
346 """
362 if self._comm is not None:
347 self._send({"method": "custom",
363 self._comm.send({"method": "custom",
348 "custom_content": content})
364 "custom_content": content})
365
349
366
350
367 def on_msg(self, callback, remove=False):
351 def on_msg(self, callback, remove=False):
@@ -412,21 +396,18 b' class Widget(LoggingConfigurable):'
412 if not view_name:
396 if not view_name:
413 view_name = self.default_view_name
397 view_name = self.default_view_name
414
398
415 # Create a comm.
399 # Create a communication.
416 if self._comm is None:
400 self._open_communication()
417 self._comm = Comm(target_name=self.target_name)
418 self._comm.on_msg(self._handle_msg)
419 self._comm.on_close(self._handle_close)
420
401
421 # Make sure model is syncronized
402 # Make sure model is syncronized
422 self.send_state()
403 self.send_state()
423
404
424 # Show view.
405 # Show view.
425 if self.parent is None or self.parent._comm is None:
406 if self.parent is None or self.parent._comm is None:
426 self._comm.send({"method": "display", "view_name": view_name})
407 self._send({"method": "display", "view_name": view_name})
427 self._handle_displayed(view_name)
408 self._handle_displayed(view_name)
428 else:
409 else:
429 self._comm.send({"method": "display",
410 self._send({"method": "display",
430 "view_name": view_name,
411 "view_name": view_name,
431 "parent": self.parent._comm.comm_id})
412 "parent": self.parent._comm.comm_id})
432 self._handle_displayed(view_name, self.parent)
413 self._handle_displayed(view_name, self.parent)
@@ -437,3 +418,32 b' class Widget(LoggingConfigurable):'
437 if child != self:
418 if child != self:
438 child._repr_widget_()
419 child._repr_widget_()
439 return None
420 return None
421
422
423 def _open_communication(self):
424 """Opens a communication with the front-end."""
425 # Create a comm.
426 if not hasattr(self, '_comm') or self._comm is None:
427 self._comm = Comm(target_name=self.target_name)
428 self._comm.on_msg(self._handle_msg)
429 self._comm.on_close(self._handle_close)
430
431
432 def _handle_close(self):
433 """Called when the comm is closed by the front-end."""
434 self._close_communication()
435
436
437 def _close_communication(self):
438 """Closes a communication with the front-end."""
439 if hasattr(self, '_comm') and self._comm is not None:
440 self._comm.close()
441
442
443 def _send(self, msg):
444 """Sends a message to the model in the front-end"""
445 if hasattr(self, '_comm') and self._comm is not None:
446 self._comm.send(msg)
447 return True
448 else:
449 return False
General Comments 0
You need to be logged in to leave comments. Login now