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