##// END OF EJS Templates
Added widget.py
Jonathan Frederic -
Show More
@@ -0,0 +1,1 b''
1 from widget import Widget No newline at end of file
@@ -0,0 +1,148 b''
1 from IPython.kernel.comm import Comm
2 from IPython.config import LoggingConfigurable
3 from IPython.utils.traitlets import Unicode, Float, Bool, Dict
4 from IPython.display import clear_output
5
6 from copy import copy
7 import uuid
8 import sys
9
10
11 class Widget(Comm):
12
13 ### Public declarations
14 target_name = Unicode('widget')
15 default_view_name = Unicode()
16
17
18 ### Private/protected declarations
19 _keys = []
20 _property_lock = False
21 _parent = None
22 _children = []
23 _css = Dict()
24
25
26 ### Public constructor
27 def __init__(self, parent=None, **kwargs):
28 super(Widget, self).__init__(**kwargs)
29
30 self._children = []
31 if parent is not None:
32 parent._children.append(self)
33 self._parent = parent
34
35 self.comm = Comm(target_name=self.target_name)
36 self.comm.on_msg(self._handle_msg)
37
38 # Register after init to allow default values to be specified
39 self.on_trait_change(self._handle_property_changed, self.keys)
40
41 # Set initial properties on client model.
42 self.send_state()
43
44
45 def __del__(self):
46 self.close()
47
48 def close(self):
49 self.comm.close()
50 del self.comm
51
52
53 ### Properties
54 def _get_parent(self):
55 return self._parent
56 parent = property(_get_parent)
57
58
59 def _get_children(self):
60 return copy(self._children)
61 children = property(_get_children)
62
63
64 def _get_keys(self):
65 keys = ['_css']
66 keys.extend(self._keys)
67 return keys
68 keys = property(_get_keys)
69
70 def _get_css(self, key, selector=""):
71 if selector in self._css and key in self._css[selector]:
72 return self._css[selector][key]
73 else:
74 return None
75 def _set_css(self, value, key, selector=""):
76 if selector not in self._css:
77 self._css[selector] = {}
78
79 # Only update the property if it has changed.
80 if not (key in self._css[selector] and value in self._css[selector][key]):
81 self._css[selector][key] = value
82 self.send_state() # Send new state to client.
83
84 css = property(_get_css, _set_css)
85
86
87 ### Event handlers
88 def _handle_msg(self, msg):
89
90 # Handle backbone sync methods
91 sync_method = msg['content']['data']['sync_method']
92 sync_data = msg['content']['data']['sync_data']
93 if sync_method.lower() in ['create', 'update']:
94 self._handle_recieve_state(sync_data)
95
96
97 def _handle_recieve_state(self, sync_data):
98 self._property_lock = True
99 try:
100
101 # Use _keys instead of keys - Don't get retrieve the css from the client side.
102 for name in self._keys:
103 if name in sync_data:
104 setattr(self, name, sync_data[name])
105 finally:
106 self._property_lock = False
107
108
109 def _handle_property_changed(self, name, old, new):
110 if not self._property_lock:
111 # TODO: Validate properties.
112 # Send new state to frontend
113 self.send_state()
114
115
116 ### Public methods
117 def show(self, view_name=None):
118 if not view_name:
119 view_name = self.default_view_name
120 if not view_name:
121 view_name = self.target_name
122
123 # Make sure model is syncronized
124 self.send_state()
125
126 # Show view.
127 if self.parent is None:
128 self.comm.send({"method": "show", "view_name": view_name})
129 else:
130 self.comm.send({"method": "show",
131 "view_name": view_name,
132 "parent": self.parent.comm.comm_id})
133
134 # Now show children if any.
135 for child in self.children:
136 child.show()
137
138
139 def send_state(self):
140 state = {}
141 for key in self.keys:
142 try:
143 state[key] = getattr(self, key)
144 except Exception as e:
145 pass # Eat errors, nom nom nom
146 self.comm.send({"method": "update",
147 "state": state})
148 No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now