Decoupled Python Widget from Comm

Fixed conflicts:
	IPython/html/widgets/widget.py
This commit is contained in:
Jonathan Frederic 2013-12-20 17:05:48 -08:00 committed by Jonathan Frederic
parent f2fefe20ff
commit 857ae831fb

View File

@ -74,7 +74,6 @@ class Widget(LoggingConfigurable):
_property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo. _property_lock = (None, None) # Last updated (key, value) from the front-end. Prevents echo.
_css = Dict() # Internal CSS property dict _css = Dict() # Internal CSS property dict
_displayed = False _displayed = False
_comm = None
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -110,11 +109,7 @@ class Widget(LoggingConfigurable):
"""Close method. Closes the widget which closes the underlying comm. """Close method. Closes the widget which closes the underlying comm.
When the comm is closed, all of the widget views are automatically When the comm is closed, all of the widget views are automatically
removed from the frontend.""" removed from the frontend."""
try: self._close_communication()
self._comm.close()
del self._comm
except:
pass # Comm doesn't exist and/or is already closed.
# Properties # Properties
@ -180,18 +175,11 @@ class Widget(LoggingConfigurable):
def _handle_property_changed(self, name, old, new): def _handle_property_changed(self, name, old, new):
"""Called when a proeprty has been changed.""" """Called when a proeprty has been changed."""
# Make sure this isn't information that the front-end just sent us. # Make sure this isn't information that the front-end just sent us.
if self._property_lock[0] != name and self._property_lock[1] != new \ if self._property_lock[0] != name and self._property_lock[1] != new:
and self._comm is not None:
# TODO: Validate properties.
# Send new state to frontend # Send new state to frontend
self.send_state(key=name) self.send_state(key=name)
def _handle_close(self):
"""Called when the comm is closed by the frontend."""
self._comm = None
def _handle_displayed(self, view_name, parent=None): def _handle_displayed(self, view_name, parent=None):
"""Called when a view has been displayed for this widget instance """Called when a view has been displayed for this widget instance
@ -233,7 +221,6 @@ class Widget(LoggingConfigurable):
key : unicode (optional) key : unicode (optional)
A single property's name to sync with the frontend. A single property's name to sync with the frontend.
""" """
if self._comm is not None:
state = {} state = {}
# If a key is provided, just send the state of that key. # If a key is provided, just send the state of that key.
@ -247,7 +234,7 @@ class Widget(LoggingConfigurable):
state[key] = getattr(self, key) state[key] = getattr(self, key)
except Exception as e: except Exception as e:
pass # Eat errors, nom nom nom pass # Eat errors, nom nom nom
self._comm.send({"method": "update", self._send({"method": "update",
"state": state}) "state": state})
@ -327,8 +314,7 @@ class Widget(LoggingConfigurable):
JQuery selector to select the DOM element(s) that the class(es) will JQuery selector to select the DOM element(s) that the class(es) will
be added to. be added to.
""" """
if self._comm is not None: self._send({"method": "add_class",
self._comm.send({"method": "add_class",
"class_list": class_name, "class_list": class_name,
"selector": selector}) "selector": selector})
@ -345,8 +331,7 @@ class Widget(LoggingConfigurable):
JQuery selector to select the DOM element(s) that the class(es) will JQuery selector to select the DOM element(s) that the class(es) will
be removed from. be removed from.
""" """
if self._comm is not None: self._send({"method": "remove_class",
self._comm.send({"method": "remove_class",
"class_list": class_name, "class_list": class_name,
"selector": selector}) "selector": selector})
@ -359,8 +344,7 @@ class Widget(LoggingConfigurable):
content : dict content : dict
Content of the message to send. Content of the message to send.
""" """
if self._comm is not None: self._send({"method": "custom",
self._comm.send({"method": "custom",
"custom_content": content}) "custom_content": content})
@ -412,21 +396,18 @@ class Widget(LoggingConfigurable):
if not view_name: if not view_name:
view_name = self.default_view_name view_name = self.default_view_name
# Create a comm. # Create a communication.
if self._comm is None: self._open_communication()
self._comm = Comm(target_name=self.target_name)
self._comm.on_msg(self._handle_msg)
self._comm.on_close(self._handle_close)
# Make sure model is syncronized # Make sure model is syncronized
self.send_state() self.send_state()
# Show view. # Show view.
if self.parent is None or self.parent._comm is None: if self.parent is None or self.parent._comm is None:
self._comm.send({"method": "display", "view_name": view_name}) self._send({"method": "display", "view_name": view_name})
self._handle_displayed(view_name) self._handle_displayed(view_name)
else: else:
self._comm.send({"method": "display", self._send({"method": "display",
"view_name": view_name, "view_name": view_name,
"parent": self.parent._comm.comm_id}) "parent": self.parent._comm.comm_id})
self._handle_displayed(view_name, self.parent) self._handle_displayed(view_name, self.parent)
@ -437,3 +418,32 @@ class Widget(LoggingConfigurable):
if child != self: if child != self:
child._repr_widget_() child._repr_widget_()
return None return None
def _open_communication(self):
"""Opens a communication with the front-end."""
# Create a comm.
if not hasattr(self, '_comm') or self._comm is None:
self._comm = Comm(target_name=self.target_name)
self._comm.on_msg(self._handle_msg)
self._comm.on_close(self._handle_close)
def _handle_close(self):
"""Called when the comm is closed by the front-end."""
self._close_communication()
def _close_communication(self):
"""Closes a communication with the front-end."""
if hasattr(self, '_comm') and self._comm is not None:
self._comm.close()
def _send(self, msg):
"""Sends a message to the model in the front-end"""
if hasattr(self, '_comm') and self._comm is not None:
self._comm.send(msg)
return True
else:
return False