Show More
@@ -14,18 +14,33 b' define([' | |||||
14 | "widgets/js/widget_selection", |
|
14 | "widgets/js/widget_selection", | |
15 | "widgets/js/widget_selectioncontainer", |
|
15 | "widgets/js/widget_selectioncontainer", | |
16 | "widgets/js/widget_string", |
|
16 | "widgets/js/widget_string", | |
17 |
], function(widgetmanager |
|
17 | ], function(widgetmanager) { | |
18 | for (var target_name in linkModels) { |
|
18 | ||
19 | if (linkModels.hasOwnProperty(target_name)) { |
|
19 | ||
20 | widgetmanager.WidgetManager.register_widget_model(target_name, linkModels[target_name]); |
|
20 | /** | |
|
21 | * From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith | |||
|
22 | * Can be removed with the string endsWith function is implemented in major browsers | |||
|
23 | */ | |||
|
24 | var endsWith = function(target, searchString, position) { | |||
|
25 | var subjectString = target.toString(); | |||
|
26 | if (position === undefined || position > subjectString.length) { | |||
|
27 | position = subjectString.length; | |||
21 | } |
|
28 | } | |
22 | } |
|
29 | position -= searchString.length; | |
|
30 | var lastIndex = subjectString.indexOf(searchString, position); | |||
|
31 | return lastIndex !== -1 && lastIndex === position; | |||
|
32 | }; | |||
23 |
|
33 | |||
24 | // Register all of the loaded views with the widget manager. |
|
34 | // Register all of the loaded models and views with the widget manager. | |
25 |
for (var i = |
|
35 | for (var i = 1; i < arguments.length; i++) { | |
26 |
|
|
36 | var module = arguments[i]; | |
27 | if (arguments[i].hasOwnProperty(target_name)) { |
|
37 | for (var target_name in module) { | |
28 | widgetmanager.WidgetManager.register_widget_view(target_name, arguments[i][target_name]); |
|
38 | if (module.hasOwnProperty(target_name)) { | |
|
39 | if (endsWith(target_name, "View")) { | |||
|
40 | widgetmanager.WidgetManager.register_widget_view(target_name, module[target_name]); | |||
|
41 | } else if (endsWith(target_name, "Model")) { | |||
|
42 | widgetmanager.WidgetManager.register_widget_model(target_name, module[target_name]); | |||
|
43 | } | |||
29 | } |
|
44 | } | |
30 | } |
|
45 | } | |
31 | } |
|
46 | } |
@@ -32,7 +32,6 b' define(["widgets/js/manager",' | |||||
32 | this.state_lock = null; |
|
32 | this.state_lock = null; | |
33 | this.id = model_id; |
|
33 | this.id = model_id; | |
34 | this.views = {}; |
|
34 | this.views = {}; | |
35 | this.serializers = {}; |
|
|||
36 | this._resolve_received_state = {}; |
|
35 | this._resolve_received_state = {}; | |
37 |
|
36 | |||
38 | if (comm !== undefined) { |
|
37 | if (comm !== undefined) { | |
@@ -146,23 +145,17 b' define(["widgets/js/manager",' | |||||
146 | var state = msg.content.data.state || {}; |
|
145 | var state = msg.content.data.state || {}; | |
147 | var buffer_keys = msg.content.data.buffers || []; |
|
146 | var buffer_keys = msg.content.data.buffers || []; | |
148 | var buffers = msg.buffers || []; |
|
147 | var buffers = msg.buffers || []; | |
149 | var metadata = msg.content.data.metadata || {}; |
|
|||
150 | var i,k; |
|
|||
151 | for (var i=0; i<buffer_keys.length; i++) { |
|
148 | for (var i=0; i<buffer_keys.length; i++) { | |
152 |
k = buffer |
|
149 | state[buffer_keys[i]] = buffers[i]; | |
153 | state[k] = buffers[i]; |
|
|||
154 | } |
|
150 | } | |
155 |
|
151 | |||
156 |
// |
|
152 | // deserialize fields that have custom deserializers | |
157 | // state to a promise that resolves to the deserialized version |
|
153 | var serializers = that.constructor.serializers; | |
158 | // also, store the serialization function for the attribute |
|
154 | if (serializers) { | |
159 |
var k |
|
155 | for (var k in state) { | |
160 | for (var i=0; i<keys.length; i++) { |
|
156 | if (serializers[k] && serializers[k].deserialize) { | |
161 |
k = |
|
157 | state[k] = (serializers[k].deserialize)(state[k], that); | |
162 |
|
|
158 | } | |
163 | that.serializers[k] = utils.load_class.apply(that, |
|
|||
164 | metadata[k].serialization); |
|
|||
165 | state[k] = that.deserialize(that.serializers[k], state[k]); |
|
|||
166 | } |
|
159 | } | |
167 | } |
|
160 | } | |
168 | return utils.resolve_promises_dict(state); |
|
161 | return utils.resolve_promises_dict(state); | |
@@ -188,19 +181,6 b' define(["widgets/js/manager",' | |||||
188 | } |
|
181 | } | |
189 | }, |
|
182 | }, | |
190 |
|
183 | |||
191 | deserialize: function(serializer, value) { |
|
|||
192 | // given a serializer dict and a value, |
|
|||
193 | // return a promise for the deserialized value |
|
|||
194 | var that = this; |
|
|||
195 | return serializer.then(function(s) { |
|
|||
196 | if (s.deserialize) { |
|
|||
197 | return s.deserialize(value, that); |
|
|||
198 | } else { |
|
|||
199 | return value; |
|
|||
200 | } |
|
|||
201 | }); |
|
|||
202 | }, |
|
|||
203 |
|
||||
204 | set_state: function (state) { |
|
184 | set_state: function (state) { | |
205 | var that = this; |
|
185 | var that = this; | |
206 | // Handle when a widget is updated via the python side. |
|
186 | // Handle when a widget is updated via the python side. | |
@@ -362,25 +342,15 b' define(["widgets/js/manager",' | |||||
362 | var that = this; |
|
342 | var that = this; | |
363 | // first, build a state dictionary with key=the attribute and the value |
|
343 | // first, build a state dictionary with key=the attribute and the value | |
364 | // being the value or the promise of the serialized value |
|
344 | // being the value or the promise of the serialized value | |
365 | var state_promise_dict = {}; |
|
345 | var serializers = this.constructor.serializers; | |
366 | var keys = Object.keys(attrs); |
|
346 | if (serializers) { | |
367 | for (var i=0; i<keys.length; i++) { |
|
347 | for (k in attrs) { | |
368 | // bind k and v locally; needed since we have an inner async function using v |
|
348 | if (serializers[k] && serializers[k].serialize) { | |
369 | (function(k,v) { |
|
349 | attrs[k] = (serializers[k].serialize)(attrs[k], this); | |
370 | if (that.serializers[k]) { |
|
|||
371 | state_promise_dict[k] = that.serializers[k].then(function(f) { |
|
|||
372 | if (f.serialize) { |
|
|||
373 | return f.serialize(v, that); |
|
|||
374 | } else { |
|
|||
375 | return v; |
|
|||
376 | } |
|
|||
377 | }) |
|
|||
378 | } else { |
|
|||
379 | state_promise_dict[k] = v; |
|
|||
380 | } |
|
350 | } | |
381 | })(keys[i], attrs[keys[i]]) |
|
351 | } | |
382 | } |
|
352 | } | |
383 |
utils.resolve_promises_dict( |
|
353 | utils.resolve_promises_dict(attrs).then(function(state) { | |
384 | // get binary values, then send |
|
354 | // get binary values, then send | |
385 | var keys = Object.keys(state); |
|
355 | var keys = Object.keys(state); | |
386 | var buffers = []; |
|
356 | var buffers = []; | |
@@ -402,20 +372,6 b' define(["widgets/js/manager",' | |||||
402 | }); |
|
372 | }); | |
403 | }, |
|
373 | }, | |
404 |
|
374 | |||
405 | serialize: function(model, attrs) { |
|
|||
406 | // Serialize the attributes into a sync message |
|
|||
407 | var keys = Object.keys(attrs); |
|
|||
408 | var key, value; |
|
|||
409 | var buffers, metadata, buffer_keys, serialize; |
|
|||
410 | for (var i=0; i<keys.length; i++) { |
|
|||
411 | key = keys[i]; |
|
|||
412 | serialize = model.serializers[key]; |
|
|||
413 | if (serialize && serialize.serialize) { |
|
|||
414 | attrs[key] = serialize.serialize(attrs[key]); |
|
|||
415 | } |
|
|||
416 | } |
|
|||
417 | }, |
|
|||
418 |
|
||||
419 | save_changes: function(callbacks) { |
|
375 | save_changes: function(callbacks) { | |
420 | /** |
|
376 | /** | |
421 | * Push this model's state to the back-end |
|
377 | * Push this model's state to the back-end |
@@ -4,10 +4,41 b'' | |||||
4 | define([ |
|
4 | define([ | |
5 | "widgets/js/widget", |
|
5 | "widgets/js/widget", | |
6 | "jqueryui", |
|
6 | "jqueryui", | |
|
7 | "underscore", | |||
7 | "base/js/utils", |
|
8 | "base/js/utils", | |
8 | "bootstrap", |
|
9 | "bootstrap", | |
9 | ], function(widget, $, utils){ |
|
10 | ], function(widget, $, _, utils){ | |
10 | "use strict"; |
|
11 | "use strict"; | |
|
12 | var unpack_models = function unpack_models(value, model) { | |||
|
13 | /** | |||
|
14 | * Replace model ids with models recursively. | |||
|
15 | */ | |||
|
16 | var unpacked; | |||
|
17 | if ($.isArray(value)) { | |||
|
18 | unpacked = []; | |||
|
19 | _.each(value, function(sub_value, key) { | |||
|
20 | unpacked.push(unpack_models(sub_value, model)); | |||
|
21 | }); | |||
|
22 | return Promise.all(unpacked); | |||
|
23 | } else if (value instanceof Object) { | |||
|
24 | unpacked = {}; | |||
|
25 | _.each(value, function(sub_value, key) { | |||
|
26 | unpacked[key] = unpack_models(sub_value, model); | |||
|
27 | }); | |||
|
28 | return utils.resolve_promises_dict(unpacked); | |||
|
29 | } else if (typeof value === 'string' && value.slice(0,10) === "IPY_MODEL_") { | |||
|
30 | // get_model returns a promise already | |||
|
31 | return model.widget_manager.get_model(value.slice(10, value.length)); | |||
|
32 | } else { | |||
|
33 | return Promise.resolve(value); | |||
|
34 | } | |||
|
35 | }; | |||
|
36 | ||||
|
37 | var BoxModel = widget.WidgetModel.extend({}, { | |||
|
38 | serializers: _.extend({ | |||
|
39 | children: {deserialize: unpack_models} | |||
|
40 | }, widget.WidgetModel.serializers) | |||
|
41 | }); | |||
11 |
|
42 | |||
12 | var BoxView = widget.DOMWidgetView.extend({ |
|
43 | var BoxView = widget.DOMWidgetView.extend({ | |
13 | initialize: function(){ |
|
44 | initialize: function(){ | |
@@ -148,6 +179,7 b' define([' | |||||
148 | }); |
|
179 | }); | |
149 |
|
180 | |||
150 | return { |
|
181 | return { | |
|
182 | 'BoxModel': BoxModel, | |||
151 | 'BoxView': BoxView, |
|
183 | 'BoxView': BoxView, | |
152 | 'FlexBoxView': FlexBoxView, |
|
184 | 'FlexBoxView': FlexBoxView, | |
153 | }; |
|
185 | }; |
@@ -89,31 +89,6 b' def register(key=None):' | |||||
89 | return wrap |
|
89 | return wrap | |
90 |
|
90 | |||
91 |
|
91 | |||
92 | def _widget_to_json(x): |
|
|||
93 | if isinstance(x, dict): |
|
|||
94 | return {k: _widget_to_json(v) for k, v in x.items()} |
|
|||
95 | elif isinstance(x, (list, tuple)): |
|
|||
96 | return [_widget_to_json(v) for v in x] |
|
|||
97 | elif isinstance(x, Widget): |
|
|||
98 | return "IPY_MODEL_" + x.model_id |
|
|||
99 | else: |
|
|||
100 | return x |
|
|||
101 |
|
||||
102 | def _json_to_widget(x): |
|
|||
103 | if isinstance(x, dict): |
|
|||
104 | return {k: _json_to_widget(v) for k, v in x.items()} |
|
|||
105 | elif isinstance(x, (list, tuple)): |
|
|||
106 | return [_json_to_widget(v) for v in x] |
|
|||
107 | elif isinstance(x, string_types) and x.startswith('IPY_MODEL_') and x[10:] in Widget.widgets: |
|
|||
108 | return Widget.widgets[x[10:]] |
|
|||
109 | else: |
|
|||
110 | return x |
|
|||
111 |
|
||||
112 | widget_serialization = { |
|
|||
113 | 'from_json': _json_to_widget, |
|
|||
114 | 'to_json': lambda x: (_widget_to_json(x), {'serialization': ('models', 'widgets/js/types')}) |
|
|||
115 | } |
|
|||
116 |
|
||||
117 | class Widget(LoggingConfigurable): |
|
92 | class Widget(LoggingConfigurable): | |
118 | #------------------------------------------------------------------------- |
|
93 | #------------------------------------------------------------------------- | |
119 | # Class attributes |
|
94 | # Class attributes | |
@@ -241,12 +216,10 b' class Widget(LoggingConfigurable):' | |||||
241 | key : unicode, or iterable (optional) |
|
216 | key : unicode, or iterable (optional) | |
242 | A single property's name or iterable of property names to sync with the front-end. |
|
217 | A single property's name or iterable of property names to sync with the front-end. | |
243 | """ |
|
218 | """ | |
244 |
state, buffer_keys, buffers |
|
219 | state, buffer_keys, buffers = self.get_state(key=key) | |
245 | msg = {"method": "update", "state": state} |
|
220 | msg = {"method": "update", "state": state} | |
246 | if buffer_keys: |
|
221 | if buffer_keys: | |
247 | msg['buffers'] = buffer_keys |
|
222 | msg['buffers'] = buffer_keys | |
248 | if metadata: |
|
|||
249 | msg['metadata'] = metadata |
|
|||
250 | self._send(msg, buffers=buffers) |
|
223 | self._send(msg, buffers=buffers) | |
251 |
|
224 | |||
252 | def get_state(self, key=None): |
|
225 | def get_state(self, key=None): | |
@@ -278,19 +251,16 b' class Widget(LoggingConfigurable):' | |||||
278 | state = {} |
|
251 | state = {} | |
279 | buffers = [] |
|
252 | buffers = [] | |
280 | buffer_keys = [] |
|
253 | buffer_keys = [] | |
281 | metadata = {} |
|
|||
282 | for k in keys: |
|
254 | for k in keys: | |
283 | f = self.trait_metadata(k, 'to_json', self._trait_to_json) |
|
255 | f = self.trait_metadata(k, 'to_json', self._trait_to_json) | |
284 | value = getattr(self, k) |
|
256 | value = getattr(self, k) | |
285 |
serialized |
|
257 | serialized = f(value) | |
286 | if isinstance(serialized, memoryview): |
|
258 | if isinstance(serialized, memoryview): | |
287 | buffers.append(serialized) |
|
259 | buffers.append(serialized) | |
288 | buffer_keys.append(k) |
|
260 | buffer_keys.append(k) | |
289 | else: |
|
261 | else: | |
290 | state[k] = serialized |
|
262 | state[k] = serialized | |
291 | if md is not None: |
|
263 | return state, buffer_keys, buffers | |
292 | metadata[k] = md |
|
|||
293 | return state, buffer_keys, buffers, metadata |
|
|||
294 |
|
264 | |||
295 | def set_state(self, sync_data): |
|
265 | def set_state(self, sync_data): | |
296 | """Called when a state is received from the front-end.""" |
|
266 | """Called when a state is received from the front-end.""" | |
@@ -439,11 +409,8 b' class Widget(LoggingConfigurable):' | |||||
439 | self._display_callbacks(self, **kwargs) |
|
409 | self._display_callbacks(self, **kwargs) | |
440 |
|
410 | |||
441 | def _trait_to_json(self, x): |
|
411 | def _trait_to_json(self, x): | |
442 | """Convert a trait value to json. |
|
412 | """Convert a trait value to json.""" | |
443 |
|
413 | return x | ||
444 | Metadata (the second return value) is not sent |
|
|||
445 | """ |
|
|||
446 | return x, None |
|
|||
447 |
|
414 | |||
448 | def _trait_from_json(self, x): |
|
415 | def _trait_from_json(self, x): | |
449 | """Convert json values to objects.""" |
|
416 | """Convert json values to objects.""" |
@@ -6,13 +6,40 b' Represents a container that can be used to group other widgets.' | |||||
6 | # Copyright (c) IPython Development Team. |
|
6 | # Copyright (c) IPython Development Team. | |
7 | # Distributed under the terms of the Modified BSD License. |
|
7 | # Distributed under the terms of the Modified BSD License. | |
8 |
|
8 | |||
9 |
from .widget import DOMWidget, |
|
9 | from .widget import DOMWidget, Widget, register | |
10 | from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum |
|
10 | from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum | |
11 | from IPython.utils.warn import DeprecatedClass |
|
11 | from IPython.utils.warn import DeprecatedClass | |
12 |
|
12 | |||
|
13 | def _widget_to_json(x): | |||
|
14 | if isinstance(x, dict): | |||
|
15 | return {k: _widget_to_json(v) for k, v in x.items()} | |||
|
16 | elif isinstance(x, (list, tuple)): | |||
|
17 | return [_widget_to_json(v) for v in x] | |||
|
18 | elif isinstance(x, Widget): | |||
|
19 | return "IPY_MODEL_" + x.model_id | |||
|
20 | else: | |||
|
21 | return x | |||
|
22 | ||||
|
23 | def _json_to_widget(x): | |||
|
24 | if isinstance(x, dict): | |||
|
25 | return {k: _json_to_widget(v) for k, v in x.items()} | |||
|
26 | elif isinstance(x, (list, tuple)): | |||
|
27 | return [_json_to_widget(v) for v in x] | |||
|
28 | elif isinstance(x, string_types) and x.startswith('IPY_MODEL_') and x[10:] in Widget.widgets: | |||
|
29 | return Widget.widgets[x[10:]] | |||
|
30 | else: | |||
|
31 | return x | |||
|
32 | ||||
|
33 | widget_serialization = { | |||
|
34 | 'from_json': _json_to_widget, | |||
|
35 | 'to_json': _widget_to_json | |||
|
36 | } | |||
|
37 | ||||
|
38 | ||||
13 | @register('IPython.Box') |
|
39 | @register('IPython.Box') | |
14 | class Box(DOMWidget): |
|
40 | class Box(DOMWidget): | |
15 | """Displays multiple widgets in a group.""" |
|
41 | """Displays multiple widgets in a group.""" | |
|
42 | _model_name = Unicode('BoxModel', sync=True) | |||
16 | _view_name = Unicode('BoxView', sync=True) |
|
43 | _view_name = Unicode('BoxView', sync=True) | |
17 |
|
44 | |||
18 | # Child widgets in the container. |
|
45 | # Child widgets in the container. |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now