##// END OF EJS Templates
Support multiple types in selection widget.
Jonathan Frederic -
Show More
@@ -57,14 +57,14 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
57 57 // changed by another view or by a state update from the back-end.
58 58
59 59 if (options === undefined || options.updated_view != this) {
60 var selected_item_text = this.model.get('value');
60 var selected_item_text = this.model.get('_value');
61 61 if (selected_item_text.length === 0) {
62 62 this.$droplabel.text(' ');
63 63 } else {
64 64 this.$droplabel.text(selected_item_text);
65 65 }
66 66
67 var items = this.model.get('values');
67 var items = this.model.get('_values');
68 68 var $replace_droplist = $('<ul />')
69 69 .addClass('dropdown-menu');
70 70 var that = this;
@@ -107,7 +107,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
107 107
108 108 // Calling model.set will trigger all of the other views of the
109 109 // model to update.
110 this.model.set('value', $(e.target).text(), {updated_view: this});
110 this.model.set('_value', $(e.target).text(), {updated_view: this});
111 111 this.touch();
112 112 },
113 113
@@ -139,7 +139,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
139 139 // changed by another view or by a state update from the back-end.
140 140 if (options === undefined || options.updated_view != this) {
141 141 // Add missing items to the DOM.
142 var items = this.model.get('values');
142 var items = this.model.get('_values');
143 143 var disabled = this.model.get('disabled');
144 144 var that = this;
145 145 _.each(items, function(item, index) {
@@ -159,7 +159,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
159 159 }
160 160
161 161 var $item_element = that.$container.find(item_query);
162 if (that.model.get('value') == item) {
162 if (that.model.get('_value') == item) {
163 163 $item_element.prop('checked', true);
164 164 } else {
165 165 $item_element.prop('checked', false);
@@ -199,7 +199,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
199 199
200 200 // Calling model.set will trigger all of the other views of the
201 201 // model to update.
202 this.model.set('value', $(e.target).val(), {updated_view: this});
202 this.model.set('_value', $(e.target).val(), {updated_view: this});
203 203 this.touch();
204 204 },
205 205 });
@@ -230,7 +230,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
230 230 // changed by another view or by a state update from the back-end.
231 231 if (options === undefined || options.updated_view != this) {
232 232 // Add missing items to the DOM.
233 var items = this.model.get('values');
233 var items = this.model.get('_values');
234 234 var disabled = this.model.get('disabled');
235 235 var that = this;
236 236 _.each(items, function(item, index) {
@@ -245,7 +245,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
245 245 }
246 246
247 247 var $item_element = that.$buttongroup.find(item_query);
248 if (that.model.get('value') == item) {
248 if (that.model.get('_value') == item) {
249 249 $item_element.addClass('active');
250 250 } else {
251 251 $item_element.removeClass('active');
@@ -285,7 +285,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
285 285
286 286 // Calling model.set will trigger all of the other views of the
287 287 // model to update.
288 this.model.set('value', $(e.target).text(), {updated_view: this});
288 this.model.set('_value', $(e.target).text(), {updated_view: this});
289 289 this.touch();
290 290 },
291 291 });
@@ -316,21 +316,21 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
316 316 // changed by another view or by a state update from the back-end.
317 317 if (options === undefined || options.updated_view != this) {
318 318 // Add missing items to the DOM.
319 var items = this.model.get('values');
319 var items = this.model.get('_values');
320 320 var that = this;
321 321 _.each(items, function(item, index) {
322 322 var item_query = ' :contains("' + item + '")';
323 323 if (that.$listbox.find(item_query).length === 0) {
324 324 $('<option />')
325 325 .text(item)
326 .attr('value', item)
326 .attr('_value', item)
327 327 .appendTo(that.$listbox)
328 328 .on('click', $.proxy(that.handle_click, that));
329 329 }
330 330 });
331 331
332 332 // Select the correct element
333 this.$listbox.val(this.model.get('value'));
333 this.$listbox.val(this.model.get('_value'));
334 334
335 335 // Disable listbox if needed
336 336 var disabled = this.model.get('disabled');
@@ -368,7 +368,7 b' define(["notebook/js/widgets/widget"], function(WidgetManager){'
368 368
369 369 // Calling model.set will trigger all of the other views of the
370 370 // model to update.
371 this.model.set('value', $(e.target).text(), {updated_view: this});
371 this.model.set('_value', $(e.target).text(), {updated_view: this});
372 372 this.touch();
373 373 },
374 374 });
@@ -13,18 +13,76 b' Represents an enumeration using a widget.'
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 from threading import Lock
17
16 18 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, List, Bool
19 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict
18 20
19 21 #-----------------------------------------------------------------------------
20 22 # SelectionWidget
21 23 #-----------------------------------------------------------------------------
22 24 class _SelectionWidget(DOMWidget):
23 value = Unicode(help="Selected value", sync=True) # TODO: Any support
24 values = List(help="List of values the user can select", sync=True)
25 value = Any(help="Selected value")
26 values = List(help="List of values the user can select")
27 value_names = Dict(help="""List of string representations for each value.
28 These string representations are used to display the values in the
29 front-end.""")
25 30 disabled = Bool(False, help="Enable or disable user changes", sync=True)
26 31 description = Unicode(help="Description of the value this widget represents", sync=True)
27 32
33 _value = Unicode(sync=True) # Bi-directionally synced.
34 _values = List(sync=True) # Only back-end to front-end synced.
35 _reverse_value_names = Dict()
36
37 def __init__(self, *pargs, **kwargs):
38 """Constructor"""
39 DOMWidget.__init__(self, *pargs, **kwargs)
40 self.value_lock = Lock()
41 self.on_trait_change(self._string_value_set, ['_value'])
42
43 def _value_names_changed(self, name=None, old=None, new=None):
44 """Handles when the value_names Dict has been changed.
45
46 This method sets the _reverse_value_names Dict to the inverse of the new
47 value for the value_names Dict."""
48 self._reverse_value_names = {v:k for k, v in self.value_names.items()}
49 self._values_changed()
50
51 def _values_changed(self, name=None, old=None, new=None):
52 """Called when values has been changed"""
53 self._values = [self._get_string_repr(v) for v in self.values]
54
55 def _value_changed(self, name, old, new):
56 """Called when value has been changed"""
57 if self.value_lock.acquire(False):
58 try:
59 # Make sure the value is in the list of values.
60 if new in self.values:
61 # Set the string version of the value.
62 self._value = self._get_string_repr(new)
63 else:
64 raise TypeError('Value must be a value in the values list.')
65 finally:
66 self.value_lock.release()
67
68 def _get_string_repr(self, value):
69 """Get the string repr of a value"""
70 if value not in self.value_names:
71 self.value_names[value] = str(value)
72 self._value_names_changed()
73 return self.value_names[value]
74
75 def _string_value_set(self, name, old, new):
76 """Called when _value has been changed."""
77 if self.value_lock.acquire(False):
78 try:
79 if new in self._reverse_value_names:
80 self.value = self._reverse_value_names[new]
81 else:
82 self.value = None
83 finally:
84 self.value_lock.release()
85
28 86
29 87 class ToggleButtonsWidget(_SelectionWidget):
30 88 view_name = Unicode('ToggleButtonsView', sync=True)
General Comments 0
You need to be logged in to leave comments. Login now