##// END OF EJS Templates
Changed selection widget API to use labels list...
Jonathan Frederic -
Show More
@@ -1,376 +1,376 b''
1 //----------------------------------------------------------------------------
1 //----------------------------------------------------------------------------
2 // Copyright (C) 2013 The IPython Development Team
2 // Copyright (C) 2013 The IPython Development Team
3 //
3 //
4 // Distributed under the terms of the BSD License. The full license is in
4 // Distributed under the terms of the BSD License. The full license is in
5 // the file COPYING, distributed as part of this software.
5 // the file COPYING, distributed as part of this software.
6 //----------------------------------------------------------------------------
6 //----------------------------------------------------------------------------
7
7
8 //============================================================================
8 //============================================================================
9 // SelectionWidget
9 // SelectionWidget
10 //============================================================================
10 //============================================================================
11
11
12 /**
12 /**
13 * @module IPython
13 * @module IPython
14 * @namespace IPython
14 * @namespace IPython
15 **/
15 **/
16
16
17 define(["notebook/js/widgets/widget"], function(WidgetManager){
17 define(["notebook/js/widgets/widget"], function(WidgetManager){
18
18
19 var DropdownView = IPython.DOMWidgetView.extend({
19 var DropdownView = IPython.DOMWidgetView.extend({
20 render : function(){
20 render : function(){
21 // Called when view is rendered.
21 // Called when view is rendered.
22 this.$el
22 this.$el
23 .addClass('widget-hbox-single');
23 .addClass('widget-hbox-single');
24 this.$label = $('<div />')
24 this.$label = $('<div />')
25 .appendTo(this.$el)
25 .appendTo(this.$el)
26 .addClass('widget-hlabel')
26 .addClass('widget-hlabel')
27 .hide();
27 .hide();
28 this.$buttongroup = $('<div />')
28 this.$buttongroup = $('<div />')
29 .addClass('widget_item')
29 .addClass('widget_item')
30 .addClass('btn-group')
30 .addClass('btn-group')
31 .appendTo(this.$el);
31 .appendTo(this.$el);
32 this.$el_to_style = this.$buttongroup; // Set default element to style
32 this.$el_to_style = this.$buttongroup; // Set default element to style
33 this.$droplabel = $('<button />')
33 this.$droplabel = $('<button />')
34 .addClass('btn')
34 .addClass('btn')
35 .addClass('widget-combo-btn')
35 .addClass('widget-combo-btn')
36 .text(' ')
36 .text(' ')
37 .appendTo(this.$buttongroup);
37 .appendTo(this.$buttongroup);
38 this.$dropbutton = $('<button />')
38 this.$dropbutton = $('<button />')
39 .addClass('btn')
39 .addClass('btn')
40 .addClass('dropdown-toggle')
40 .addClass('dropdown-toggle')
41 .addClass('widget-combo-carrot-btn')
41 .addClass('widget-combo-carrot-btn')
42 .attr('data-toggle', 'dropdown')
42 .attr('data-toggle', 'dropdown')
43 .append($('<span />').addClass("caret"))
43 .append($('<span />').addClass("caret"))
44 .appendTo(this.$buttongroup);
44 .appendTo(this.$buttongroup);
45 this.$droplist = $('<ul />')
45 this.$droplist = $('<ul />')
46 .addClass('dropdown-menu')
46 .addClass('dropdown-menu')
47 .appendTo(this.$buttongroup);
47 .appendTo(this.$buttongroup);
48
48
49 // Set defaults.
49 // Set defaults.
50 this.update();
50 this.update();
51 },
51 },
52
52
53 update : function(options){
53 update : function(options){
54 // Update the contents of this view
54 // Update the contents of this view
55 //
55 //
56 // Called when the model is changed. The model may have been
56 // Called when the model is changed. The model may have been
57 // changed by another view or by a state update from the back-end.
57 // changed by another view or by a state update from the back-end.
58
58
59 if (options === undefined || options.updated_view != this) {
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 if (selected_item_text.length === 0) {
61 if (selected_item_text.length === 0) {
62 this.$droplabel.text(' ');
62 this.$droplabel.text(' ');
63 } else {
63 } else {
64 this.$droplabel.text(selected_item_text);
64 this.$droplabel.text(selected_item_text);
65 }
65 }
66
66
67 var items = this.model.get('_values');
67 var items = this.model.get('labels');
68 var $replace_droplist = $('<ul />')
68 var $replace_droplist = $('<ul />')
69 .addClass('dropdown-menu');
69 .addClass('dropdown-menu');
70 var that = this;
70 var that = this;
71 _.each(items, function(item, i) {
71 _.each(items, function(item, i) {
72 var item_button = $('<a href="#"/>')
72 var item_button = $('<a href="#"/>')
73 .text(item)
73 .text(item)
74 .on('click', $.proxy(that.handle_click, that));
74 .on('click', $.proxy(that.handle_click, that));
75 $replace_droplist.append($('<li />').append(item_button));
75 $replace_droplist.append($('<li />').append(item_button));
76 });
76 });
77
77
78 this.$droplist.replaceWith($replace_droplist);
78 this.$droplist.replaceWith($replace_droplist);
79 this.$droplist.remove();
79 this.$droplist.remove();
80 this.$droplist = $replace_droplist;
80 this.$droplist = $replace_droplist;
81
81
82 if (this.model.get('disabled')) {
82 if (this.model.get('disabled')) {
83 this.$buttongroup.attr('disabled','disabled');
83 this.$buttongroup.attr('disabled','disabled');
84 this.$droplabel.attr('disabled','disabled');
84 this.$droplabel.attr('disabled','disabled');
85 this.$dropbutton.attr('disabled','disabled');
85 this.$dropbutton.attr('disabled','disabled');
86 this.$droplist.attr('disabled','disabled');
86 this.$droplist.attr('disabled','disabled');
87 } else {
87 } else {
88 this.$buttongroup.removeAttr('disabled');
88 this.$buttongroup.removeAttr('disabled');
89 this.$droplabel.removeAttr('disabled');
89 this.$droplabel.removeAttr('disabled');
90 this.$dropbutton.removeAttr('disabled');
90 this.$dropbutton.removeAttr('disabled');
91 this.$droplist.removeAttr('disabled');
91 this.$droplist.removeAttr('disabled');
92 }
92 }
93
93
94 var description = this.model.get('description');
94 var description = this.model.get('description');
95 if (description.length === 0) {
95 if (description.length === 0) {
96 this.$label.hide();
96 this.$label.hide();
97 } else {
97 } else {
98 this.$label.text(description);
98 this.$label.text(description);
99 this.$label.show();
99 this.$label.show();
100 }
100 }
101 }
101 }
102 return DropdownView.__super__.update.apply(this);
102 return DropdownView.__super__.update.apply(this);
103 },
103 },
104
104
105 handle_click: function (e) {
105 handle_click: function (e) {
106 // Handle when a value is clicked.
106 // Handle when a value is clicked.
107
107
108 // Calling model.set will trigger all of the other views of the
108 // Calling model.set will trigger all of the other views of the
109 // model to update.
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 this.touch();
111 this.touch();
112 },
112 },
113
113
114 });
114 });
115 WidgetManager.register_widget_view('DropdownView', DropdownView);
115 WidgetManager.register_widget_view('DropdownView', DropdownView);
116
116
117
117
118 var RadioButtonsView = IPython.DOMWidgetView.extend({
118 var RadioButtonsView = IPython.DOMWidgetView.extend({
119 render : function(){
119 render : function(){
120 // Called when view is rendered.
120 // Called when view is rendered.
121 this.$el
121 this.$el
122 .addClass('widget-hbox');
122 .addClass('widget-hbox');
123 this.$label = $('<div />')
123 this.$label = $('<div />')
124 .appendTo(this.$el)
124 .appendTo(this.$el)
125 .addClass('widget-hlabel')
125 .addClass('widget-hlabel')
126 .hide();
126 .hide();
127 this.$container = $('<div />')
127 this.$container = $('<div />')
128 .appendTo(this.$el)
128 .appendTo(this.$el)
129 .addClass('widget-container')
129 .addClass('widget-container')
130 .addClass('vbox');
130 .addClass('vbox');
131 this.$el_to_style = this.$container; // Set default element to style
131 this.$el_to_style = this.$container; // Set default element to style
132 this.update();
132 this.update();
133 },
133 },
134
134
135 update : function(options){
135 update : function(options){
136 // Update the contents of this view
136 // Update the contents of this view
137 //
137 //
138 // Called when the model is changed. The model may have been
138 // Called when the model is changed. The model may have been
139 // changed by another view or by a state update from the back-end.
139 // changed by another view or by a state update from the back-end.
140 if (options === undefined || options.updated_view != this) {
140 if (options === undefined || options.updated_view != this) {
141 // Add missing items to the DOM.
141 // Add missing items to the DOM.
142 var items = this.model.get('_values');
142 var items = this.model.get('labels');
143 var disabled = this.model.get('disabled');
143 var disabled = this.model.get('disabled');
144 var that = this;
144 var that = this;
145 _.each(items, function(item, index) {
145 _.each(items, function(item, index) {
146 var item_query = ' :input[value="' + item + '"]';
146 var item_query = ' :input[value="' + item + '"]';
147 if (that.$el.find(item_query).length === 0) {
147 if (that.$el.find(item_query).length === 0) {
148 var $label = $('<label />')
148 var $label = $('<label />')
149 .addClass('radio')
149 .addClass('radio')
150 .text(item)
150 .text(item)
151 .appendTo(that.$container);
151 .appendTo(that.$container);
152
152
153 $('<input />')
153 $('<input />')
154 .attr('type', 'radio')
154 .attr('type', 'radio')
155 .addClass(that.model)
155 .addClass(that.model)
156 .val(item)
156 .val(item)
157 .prependTo($label)
157 .prependTo($label)
158 .on('click', $.proxy(that.handle_click, that));
158 .on('click', $.proxy(that.handle_click, that));
159 }
159 }
160
160
161 var $item_element = that.$container.find(item_query);
161 var $item_element = that.$container.find(item_query);
162 if (that.model.get('_value') == item) {
162 if (that.model.get('_value') == item) {
163 $item_element.prop('checked', true);
163 $item_element.prop('checked', true);
164 } else {
164 } else {
165 $item_element.prop('checked', false);
165 $item_element.prop('checked', false);
166 }
166 }
167 $item_element.prop('disabled', disabled);
167 $item_element.prop('disabled', disabled);
168 });
168 });
169
169
170 // Remove items that no longer exist.
170 // Remove items that no longer exist.
171 this.$container.find('input').each(function(i, obj) {
171 this.$container.find('input').each(function(i, obj) {
172 var value = $(obj).val();
172 var value = $(obj).val();
173 var found = false;
173 var found = false;
174 _.each(items, function(item, index) {
174 _.each(items, function(item, index) {
175 if (item == value) {
175 if (item == value) {
176 found = true;
176 found = true;
177 return false;
177 return false;
178 }
178 }
179 });
179 });
180
180
181 if (!found) {
181 if (!found) {
182 $(obj).parent().remove();
182 $(obj).parent().remove();
183 }
183 }
184 });
184 });
185
185
186 var description = this.model.get('description');
186 var description = this.model.get('description');
187 if (description.length === 0) {
187 if (description.length === 0) {
188 this.$label.hide();
188 this.$label.hide();
189 } else {
189 } else {
190 this.$label.text(description);
190 this.$label.text(description);
191 this.$label.show();
191 this.$label.show();
192 }
192 }
193 }
193 }
194 return RadioButtonsView.__super__.update.apply(this);
194 return RadioButtonsView.__super__.update.apply(this);
195 },
195 },
196
196
197 handle_click: function (e) {
197 handle_click: function (e) {
198 // Handle when a value is clicked.
198 // Handle when a value is clicked.
199
199
200 // Calling model.set will trigger all of the other views of the
200 // Calling model.set will trigger all of the other views of the
201 // model to update.
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 this.touch();
203 this.touch();
204 },
204 },
205 });
205 });
206 WidgetManager.register_widget_view('RadioButtonsView', RadioButtonsView);
206 WidgetManager.register_widget_view('RadioButtonsView', RadioButtonsView);
207
207
208
208
209 var ToggleButtonsView = IPython.DOMWidgetView.extend({
209 var ToggleButtonsView = IPython.DOMWidgetView.extend({
210 render : function(){
210 render : function(){
211 // Called when view is rendered.
211 // Called when view is rendered.
212 this.$el
212 this.$el
213 .addClass('widget-hbox-single');
213 .addClass('widget-hbox-single');
214 this.$label = $('<div />')
214 this.$label = $('<div />')
215 .appendTo(this.$el)
215 .appendTo(this.$el)
216 .addClass('widget-hlabel')
216 .addClass('widget-hlabel')
217 .hide();
217 .hide();
218 this.$buttongroup = $('<div />')
218 this.$buttongroup = $('<div />')
219 .addClass('btn-group')
219 .addClass('btn-group')
220 .attr('data-toggle', 'buttons-radio')
220 .attr('data-toggle', 'buttons-radio')
221 .appendTo(this.$el);
221 .appendTo(this.$el);
222 this.$el_to_style = this.$buttongroup; // Set default element to style
222 this.$el_to_style = this.$buttongroup; // Set default element to style
223 this.update();
223 this.update();
224 },
224 },
225
225
226 update : function(options){
226 update : function(options){
227 // Update the contents of this view
227 // Update the contents of this view
228 //
228 //
229 // Called when the model is changed. The model may have been
229 // Called when the model is changed. The model may have been
230 // changed by another view or by a state update from the back-end.
230 // changed by another view or by a state update from the back-end.
231 if (options === undefined || options.updated_view != this) {
231 if (options === undefined || options.updated_view != this) {
232 // Add missing items to the DOM.
232 // Add missing items to the DOM.
233 var items = this.model.get('_values');
233 var items = this.model.get('labels');
234 var disabled = this.model.get('disabled');
234 var disabled = this.model.get('disabled');
235 var that = this;
235 var that = this;
236 _.each(items, function(item, index) {
236 _.each(items, function(item, index) {
237 var item_query = ' :contains("' + item + '")';
237 var item_query = ' :contains("' + item + '")';
238 if (that.$buttongroup.find(item_query).length === 0) {
238 if (that.$buttongroup.find(item_query).length === 0) {
239 $('<button />')
239 $('<button />')
240 .attr('type', 'button')
240 .attr('type', 'button')
241 .addClass('btn')
241 .addClass('btn')
242 .text(item)
242 .text(item)
243 .appendTo(that.$buttongroup)
243 .appendTo(that.$buttongroup)
244 .on('click', $.proxy(that.handle_click, that));
244 .on('click', $.proxy(that.handle_click, that));
245 }
245 }
246
246
247 var $item_element = that.$buttongroup.find(item_query);
247 var $item_element = that.$buttongroup.find(item_query);
248 if (that.model.get('_value') == item) {
248 if (that.model.get('_value') == item) {
249 $item_element.addClass('active');
249 $item_element.addClass('active');
250 } else {
250 } else {
251 $item_element.removeClass('active');
251 $item_element.removeClass('active');
252 }
252 }
253 $item_element.prop('disabled', disabled);
253 $item_element.prop('disabled', disabled);
254 });
254 });
255
255
256 // Remove items that no longer exist.
256 // Remove items that no longer exist.
257 this.$buttongroup.find('button').each(function(i, obj) {
257 this.$buttongroup.find('button').each(function(i, obj) {
258 var value = $(obj).text();
258 var value = $(obj).text();
259 var found = false;
259 var found = false;
260 _.each(items, function(item, index) {
260 _.each(items, function(item, index) {
261 if (item == value) {
261 if (item == value) {
262 found = true;
262 found = true;
263 return false;
263 return false;
264 }
264 }
265 });
265 });
266
266
267 if (!found) {
267 if (!found) {
268 $(obj).remove();
268 $(obj).remove();
269 }
269 }
270 });
270 });
271
271
272 var description = this.model.get('description');
272 var description = this.model.get('description');
273 if (description.length === 0) {
273 if (description.length === 0) {
274 this.$label.hide();
274 this.$label.hide();
275 } else {
275 } else {
276 this.$label.text(description);
276 this.$label.text(description);
277 this.$label.show();
277 this.$label.show();
278 }
278 }
279 }
279 }
280 return ToggleButtonsView.__super__.update.apply(this);
280 return ToggleButtonsView.__super__.update.apply(this);
281 },
281 },
282
282
283 handle_click: function (e) {
283 handle_click: function (e) {
284 // Handle when a value is clicked.
284 // Handle when a value is clicked.
285
285
286 // Calling model.set will trigger all of the other views of the
286 // Calling model.set will trigger all of the other views of the
287 // model to update.
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 this.touch();
289 this.touch();
290 },
290 },
291 });
291 });
292 WidgetManager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
292 WidgetManager.register_widget_view('ToggleButtonsView', ToggleButtonsView);
293
293
294
294
295 var ListBoxView = IPython.DOMWidgetView.extend({
295 var ListBoxView = IPython.DOMWidgetView.extend({
296 render : function(){
296 render : function(){
297 // Called when view is rendered.
297 // Called when view is rendered.
298 this.$el
298 this.$el
299 .addClass('widget-hbox');
299 .addClass('widget-hbox');
300 this.$label = $('<div />')
300 this.$label = $('<div />')
301 .appendTo(this.$el)
301 .appendTo(this.$el)
302 .addClass('widget-hlabel')
302 .addClass('widget-hlabel')
303 .hide();
303 .hide();
304 this.$listbox = $('<select />')
304 this.$listbox = $('<select />')
305 .addClass('widget-listbox')
305 .addClass('widget-listbox')
306 .attr('size', 6)
306 .attr('size', 6)
307 .appendTo(this.$el);
307 .appendTo(this.$el);
308 this.$el_to_style = this.$listbox; // Set default element to style
308 this.$el_to_style = this.$listbox; // Set default element to style
309 this.update();
309 this.update();
310 },
310 },
311
311
312 update : function(options){
312 update : function(options){
313 // Update the contents of this view
313 // Update the contents of this view
314 //
314 //
315 // Called when the model is changed. The model may have been
315 // Called when the model is changed. The model may have been
316 // changed by another view or by a state update from the back-end.
316 // changed by another view or by a state update from the back-end.
317 if (options === undefined || options.updated_view != this) {
317 if (options === undefined || options.updated_view != this) {
318 // Add missing items to the DOM.
318 // Add missing items to the DOM.
319 var items = this.model.get('_values');
319 var items = this.model.get('labels');
320 var that = this;
320 var that = this;
321 _.each(items, function(item, index) {
321 _.each(items, function(item, index) {
322 var item_query = ' :contains("' + item + '")';
322 var item_query = ' :contains("' + item + '")';
323 if (that.$listbox.find(item_query).length === 0) {
323 if (that.$listbox.find(item_query).length === 0) {
324 $('<option />')
324 $('<option />')
325 .text(item)
325 .text(item)
326 .attr('_value', item)
326 .attr('_value', item)
327 .appendTo(that.$listbox)
327 .appendTo(that.$listbox)
328 .on('click', $.proxy(that.handle_click, that));
328 .on('click', $.proxy(that.handle_click, that));
329 }
329 }
330 });
330 });
331
331
332 // Select the correct element
332 // Select the correct element
333 this.$listbox.val(this.model.get('_value'));
333 this.$listbox.val(this.model.get('_value'));
334
334
335 // Disable listbox if needed
335 // Disable listbox if needed
336 var disabled = this.model.get('disabled');
336 var disabled = this.model.get('disabled');
337 this.$listbox.prop('disabled', disabled);
337 this.$listbox.prop('disabled', disabled);
338
338
339 // Remove items that no longer exist.
339 // Remove items that no longer exist.
340 this.$listbox.find('option').each(function(i, obj) {
340 this.$listbox.find('option').each(function(i, obj) {
341 var value = $(obj).text();
341 var value = $(obj).text();
342 var found = false;
342 var found = false;
343 _.each(items, function(item, index) {
343 _.each(items, function(item, index) {
344 if (item == value) {
344 if (item == value) {
345 found = true;
345 found = true;
346 return false;
346 return false;
347 }
347 }
348 });
348 });
349
349
350 if (!found) {
350 if (!found) {
351 $(obj).remove();
351 $(obj).remove();
352 }
352 }
353 });
353 });
354
354
355 var description = this.model.get('description');
355 var description = this.model.get('description');
356 if (description.length === 0) {
356 if (description.length === 0) {
357 this.$label.hide();
357 this.$label.hide();
358 } else {
358 } else {
359 this.$label.text(description);
359 this.$label.text(description);
360 this.$label.show();
360 this.$label.show();
361 }
361 }
362 }
362 }
363 return ListBoxView.__super__.update.apply(this);
363 return ListBoxView.__super__.update.apply(this);
364 },
364 },
365
365
366 handle_click: function (e) {
366 handle_click: function (e) {
367 // Handle when a value is clicked.
367 // Handle when a value is clicked.
368
368
369 // Calling model.set will trigger all of the other views of the
369 // Calling model.set will trigger all of the other views of the
370 // model to update.
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 this.touch();
372 this.touch();
373 },
373 },
374 });
374 });
375 WidgetManager.register_widget_view('ListBoxView', ListBoxView);
375 WidgetManager.register_widget_view('ListBoxView', ListBoxView);
376 });
376 });
@@ -1,100 +1,95 b''
1 """SelectionWidget class.
1 """SelectionWidget class.
2
2
3 Represents an enumeration using a widget.
3 Represents an enumeration using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from threading import Lock
16 from threading import Lock
17
17
18 from .widget import DOMWidget
18 from .widget import DOMWidget
19 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict
19 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict
20
20
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 # SelectionWidget
22 # SelectionWidget
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 class _SelectionWidget(DOMWidget):
24 class _SelectionWidget(DOMWidget):
25 value = Any(help="Selected value")
25 value = Any(help="Selected value")
26 values = List(help="List of values the user can select")
26 values = List(help="List of values the user can select")
27 value_names = Dict(help="""List of string representations for each value.
27 labels = List(help="""List of string representations for each value.
28 These string representations are used to display the values in the
28 These string representations are used to display the values in the
29 front-end.""")
29 front-end.""", sync=True) # Only synced to the back-end.
30 disabled = Bool(False, help="Enable or disable user changes", sync=True)
30 disabled = Bool(False, help="Enable or disable user changes", sync=True)
31 description = Unicode(help="Description of the value this widget represents", sync=True)
31 description = Unicode(help="Description of the value this widget represents", sync=True)
32
32
33 _value = Unicode(sync=True) # Bi-directionally synced.
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
34
37 def __init__(self, *pargs, **kwargs):
35 def __init__(self, *pargs, **kwargs):
38 """Constructor"""
36 """Constructor"""
39 DOMWidget.__init__(self, *pargs, **kwargs)
40 self.value_lock = Lock()
37 self.value_lock = Lock()
41 self.on_trait_change(self._string_value_set, ['_value'])
38 self.on_trait_change(self._string_value_set, ['_value'])
39 DOMWidget.__init__(self, *pargs, **kwargs)
42
40
43 def _value_names_changed(self, name=None, old=None, new=None):
41 def _labels_changed(self, name=None, old=None, new=None):
44 """Handles when the value_names Dict has been changed.
42 """Handles when the value_names Dict has been changed.
45
43
46 This method sets the _reverse_value_names Dict to the inverse of the new
44 This method sets the _reverse_value_names Dict to the inverse of the new
47 value for the value_names Dict."""
45 value for the value_names Dict."""
48 self._reverse_value_names = {v:k for k, v in self.value_names.items()}
46 if len(new) != len(self.values):
49 self._values_changed()
47 raise TypeError('Labels list must be the same size as the values list.')
50
48
51 def _values_changed(self, name=None, old=None, new=None):
49 def _values_changed(self, name=None, old=None, new=None):
52 """Called when values has been changed"""
50 """Handles when the value_names Dict has been changed.
53 self._values = [self._get_string_repr(v) for v in self.values]
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)]
54
56
55 def _value_changed(self, name, old, new):
57 def _value_changed(self, name, old, new):
56 """Called when value has been changed"""
58 """Called when value has been changed"""
57 if self.value_lock.acquire(False):
59 if self.value_lock.acquire(False):
58 try:
60 try:
59 # Make sure the value is in the list of values.
61 # Make sure the value is in the list of values.
60 if new in self.values:
62 if new in self.values:
61 # Set the string version of the value.
63 # Set the string version of the value.
62 self._value = self._get_string_repr(new)
64 self._value = self.labels[self.values.index(new)]
63 else:
65 else:
64 raise TypeError('Value must be a value in the values list.')
66 raise TypeError('Value must be a value in the values list.')
65 finally:
67 finally:
66 self.value_lock.release()
68 self.value_lock.release()
67
69
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):
70 def _string_value_set(self, name, old, new):
76 """Called when _value has been changed."""
71 """Called when _value has been changed."""
77 if self.value_lock.acquire(False):
72 if self.value_lock.acquire(False):
78 try:
73 try:
79 if new in self._reverse_value_names:
74 if new in self.labels:
80 self.value = self._reverse_value_names[new]
75 self.value = self.values[self.labels.index(new)]
81 else:
76 else:
82 self.value = None
77 self.value = None
83 finally:
78 finally:
84 self.value_lock.release()
79 self.value_lock.release()
85
80
86
81
87 class ToggleButtonsWidget(_SelectionWidget):
82 class ToggleButtonsWidget(_SelectionWidget):
88 _view_name = Unicode('ToggleButtonsView', sync=True)
83 _view_name = Unicode('ToggleButtonsView', sync=True)
89
84
90
85
91 class DropdownWidget(_SelectionWidget):
86 class DropdownWidget(_SelectionWidget):
92 _view_name = Unicode('DropdownView', sync=True)
87 _view_name = Unicode('DropdownView', sync=True)
93
88
94
89
95 class RadioButtonsWidget(_SelectionWidget):
90 class RadioButtonsWidget(_SelectionWidget):
96 _view_name = Unicode('RadioButtonsView', sync=True)
91 _view_name = Unicode('RadioButtonsView', sync=True)
97
92
98
93
99 class ListBoxWidget(_SelectionWidget):
94 class ListBoxWidget(_SelectionWidget):
100 _view_name = Unicode('ListBoxView', sync=True)
95 _view_name = Unicode('ListBoxView', sync=True)
General Comments 0
You need to be logged in to leave comments. Login now