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(' |
|
|
60 | var selected_item_text = this.model.get('value_name'); | |
|
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(' |
|
|
67 | var items = this.model.get('value_names'); | |
|
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(' |
|
|
110 | this.model.set('value_name', $(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(' |
|
|
142 | var items = this.model.get('value_names'); | |
|
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(' |
|
|
162 | if (that.model.get('value_name') == item) { | |
|
163 | 163 | $item_element.prop('checked', true); |
|
164 | 164 | } else { |
|
165 | 165 | $item_element.prop('checked', false); |
@@ -199,14 +199,14 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(' |
|
|
202 | this.model.set('value_name', $(e.target).val(), {updated_view: this}); | |
|
203 | 203 | this.touch(); |
|
204 | 204 | }, |
|
205 | 205 | }); |
|
206 | 206 | WidgetManager.register_widget_view('RadioButtonsView', RadioButtonsView); |
|
207 | 207 | |
|
208 | 208 | |
|
209 |
var ToggleButtonsView = IPython.DOMWidgetView.extend({ |
|
|
209 | var ToggleButtonsView = IPython.DOMWidgetView.extend({ | |
|
210 | 210 | render : function(){ |
|
211 | 211 | // Called when view is rendered. |
|
212 | 212 | this.$el |
@@ -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(' |
|
|
233 | var items = this.model.get('value_names'); | |
|
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(' |
|
|
248 | if (that.model.get('value_name') == 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(' |
|
|
288 | this.model.set('value_name', $(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(' |
|
|
319 | var items = this.model.get('value_names'); | |
|
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(' |
|
|
326 | .attr('value_name', 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(' |
|
|
333 | this.$listbox.val(this.model.get('value_name')); | |
|
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(' |
|
|
371 | this.model.set('value_name', $(e.target).text(), {updated_view: this}); | |
|
372 | 372 | this.touch(); |
|
373 | 373 | }, |
|
374 | 374 | }); |
@@ -123,7 +123,9 b' casper.notebook_test(function () {' | |||
|
123 | 123 | |
|
124 | 124 | index = this.append_cell( |
|
125 | 125 | 'for widget in selection:\n' + |
|
126 |
' |
|
|
126 | ' d = widget.values.copy()\n' + | |
|
127 | ' d["z"] = "z"\n' + | |
|
128 | ' widget.values = d\n' + | |
|
127 | 129 | 'selection[0].value = "z"'); |
|
128 | 130 | this.execute_cell_then(index, function(index){ |
|
129 | 131 |
@@ -1,4 +1,4 b'' | |||
|
1 |
"""SelectionWidget class. |
|
|
1 | """SelectionWidget classes. | |
|
2 | 2 | |
|
3 | 3 | Represents an enumeration using a widget. |
|
4 | 4 | """ |
@@ -13,66 +13,84 b' Represents an enumeration using a widget.' | |||
|
13 | 13 | #----------------------------------------------------------------------------- |
|
14 | 14 | # Imports |
|
15 | 15 | #----------------------------------------------------------------------------- |
|
16 | ||
|
17 | from collections import OrderedDict | |
|
16 | 18 | from threading import Lock |
|
17 | 19 | |
|
18 | 20 | from .widget import DOMWidget |
|
19 | from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict | |
|
21 | from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError | |
|
22 | from IPython.utils.py3compat import unicode_type | |
|
20 | 23 | |
|
21 | 24 | #----------------------------------------------------------------------------- |
|
22 | 25 | # SelectionWidget |
|
23 | 26 | #----------------------------------------------------------------------------- |
|
24 | 27 | class _SelectionWidget(DOMWidget): |
|
25 | value = Any(help="Selected value") | |
|
26 | values = List(help="List of values the user can select") | |
|
27 | labels = List(help="""List of string representations for each value. | |
|
28 | These string representations are used to display the values in the | |
|
29 | front-end.""", sync=True) # Only synced to the back-end. | |
|
28 | """Base class for Selection widgets | |
|
29 | ||
|
30 | ``values`` can be specified as a list or dict. If given as a list, | |
|
31 | it will be transformed to a dict of the form ``{str(value):value}``. | |
|
32 | """ | |
|
33 | ||
|
34 | value = Any(help="Selected value") | |
|
35 | values = Dict(help="""Dictionary of {name: value} the user can select. | |
|
36 | ||
|
37 | The keys of this dictionary are the strings that will be displayed in the UI, | |
|
38 | representing the actual Python choices. | |
|
39 | ||
|
40 | The keys of this dictionary are also available as value_names. | |
|
41 | """) | |
|
42 | value_name = Unicode(help="The name of the selected value", sync=True) | |
|
43 | value_names = List(Unicode, help="""List of names for each value. | |
|
44 | ||
|
45 | If values is specified as a list, this is the string representation of each element. | |
|
46 | Otherwise, it is the keys of the values dictionary. | |
|
47 | ||
|
48 | These strings are used to display the choices in the front-end.""", sync=True) | |
|
30 | 49 | disabled = Bool(False, help="Enable or disable user changes", sync=True) |
|
31 | 50 | description = Unicode(help="Description of the value this widget represents", sync=True) |
|
51 | ||
|
32 | 52 | |
|
33 | _value = Unicode(sync=True) # Bi-directionally synced. | |
|
34 | ||
|
35 | def __init__(self, *pargs, **kwargs): | |
|
36 | """Constructor""" | |
|
53 | def __init__(self, *args, **kwargs): | |
|
37 | 54 | self.value_lock = Lock() |
|
38 | self.on_trait_change(self._string_value_set, ['_value']) | |
|
39 | DOMWidget.__init__(self, *pargs, **kwargs) | |
|
40 | ||
|
41 | def _labels_changed(self, name=None, old=None, new=None): | |
|
42 | """Handles when the value_names Dict has been changed. | |
|
55 | if 'values' in kwargs: | |
|
56 | values = kwargs['values'] | |
|
57 | # convert list values to an dict of {str(v):v} | |
|
58 | if isinstance(values, list): | |
|
59 | # preserve list order with an OrderedDict | |
|
60 | kwargs['values'] = OrderedDict((unicode_type(v), v) for v in values) | |
|
61 | DOMWidget.__init__(self, *args, **kwargs) | |
|
62 | ||
|
63 | def _values_changed(self, name, old, new): | |
|
64 | """Handles when the values dict has been changed. | |
|
43 | 65 | |
|
44 | This method sets the _reverse_value_names Dict to the inverse of the new | |
|
45 | value for the value_names Dict.""" | |
|
66 | Setting values implies setting value names from the keys of the dict. | |
|
67 | """ | |
|
68 | self.value_names = list(new.keys()) | |
|
69 | ||
|
70 | def _value_names_changed(self, name, old, new): | |
|
46 | 71 | if len(new) != len(self.values): |
|
47 | raise TypeError('Labels list must be the same size as the values list.') | |
|
48 | ||
|
49 | def _values_changed(self, name=None, old=None, new=None): | |
|
50 | """Handles when the value_names Dict has been changed. | |
|
51 | ||
|
52 | This method sets the _reverse_value_names Dict to the inverse of the new | |
|
53 | value for the value_names Dict.""" | |
|
54 | if len(new) != len(self.labels): | |
|
55 | self.labels = [(self.labels[i] if i < len(self.labels) else str(v)) for i, v in enumerate(new)] | |
|
72 | raise TraitError("Expected %i value names, got %i." % (len(self.values), len(new))) | |
|
56 | 73 | |
|
57 | 74 | def _value_changed(self, name, old, new): |
|
58 | 75 | """Called when value has been changed""" |
|
59 | 76 | if self.value_lock.acquire(False): |
|
60 | 77 | try: |
|
61 |
# Make sure the value is |
|
|
62 |
|
|
|
63 | # Set the string version of the value. | |
|
64 | self._value = self.labels[self.values.index(new)] | |
|
65 | else: | |
|
66 | raise TypeError('Value must be a value in the values list.') | |
|
78 | # Make sure the value is one of the options | |
|
79 | for k,v in self.values.items(): | |
|
80 | if new == v: | |
|
81 | # set the selected value name | |
|
82 | self.value_name = k | |
|
83 | return | |
|
84 | raise TraitError('Value not found: %r' % new) | |
|
67 | 85 | finally: |
|
68 | 86 | self.value_lock.release() |
|
69 | 87 | |
|
70 |
def |
|
|
71 |
"""Called when |
|
|
88 | def _value_name_changed(self, name, old, new): | |
|
89 | """Called when the value name has been changed (typically by the frontend).""" | |
|
72 | 90 | if self.value_lock.acquire(False): |
|
73 | 91 | try: |
|
74 |
if new in self. |
|
|
75 |
self.value = self.values[ |
|
|
92 | if new in self.values: | |
|
93 | self.value = self.values[new] | |
|
76 | 94 | else: |
|
77 | 95 | self.value = None |
|
78 | 96 | finally: |
General Comments 0
You need to be logged in to leave comments.
Login now