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