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