Show More
@@ -25,35 +25,35 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
25 | .appendTo(this.$el) |
|
25 | .appendTo(this.$el) | |
26 | .addClass('widget-hlabel') |
|
26 | .addClass('widget-hlabel') | |
27 | .hide(); |
|
27 | .hide(); | |
28 |
|
28 | |||
29 | this.$slider = $('<div />') |
|
29 | this.$slider = $('<div />') | |
30 | .slider({}) |
|
30 | .slider({}) | |
31 | .addClass('slider'); |
|
31 | .addClass('slider'); | |
32 |
// Put the slider in a container |
|
32 | // Put the slider in a container | |
33 | this.$slider_container = $('<div />') |
|
33 | this.$slider_container = $('<div />') | |
34 | .addClass('widget-hslider') |
|
34 | .addClass('widget-hslider') | |
35 | .append(this.$slider); |
|
35 | .append(this.$slider); | |
36 | this.$el_to_style = this.$slider_container; // Set default element to style |
|
36 | this.$el_to_style = this.$slider_container; // Set default element to style | |
37 | this.$el.append(this.$slider_container); |
|
37 | this.$el.append(this.$slider_container); | |
38 |
|
38 | |||
39 | this.$readout = $('<div/>') |
|
39 | this.$readout = $('<div/>') | |
40 | .appendTo(this.$el) |
|
40 | .appendTo(this.$el) | |
41 | .addClass('widget-hreadout') |
|
41 | .addClass('widget-hreadout') | |
42 | .hide(); |
|
42 | .hide(); | |
43 |
|
43 | |||
44 | // Set defaults. |
|
44 | // Set defaults. | |
45 | this.update(); |
|
45 | this.update(); | |
46 | }, |
|
46 | }, | |
47 |
|
47 | |||
48 | update : function(options){ |
|
48 | update : function(options){ | |
49 | // Update the contents of this view |
|
49 | // Update the contents of this view | |
50 | // |
|
50 | // | |
51 |
// Called when the model is changed. The model may have been |
|
51 | // Called when the model is changed. The model may have been | |
52 | // changed by another view or by a state update from the back-end. |
|
52 | // changed by another view or by a state update from the back-end. | |
53 | if (options === undefined || options.updated_view != this) { |
|
53 | if (options === undefined || options.updated_view != this) { | |
54 | // JQuery slider option keys. These keys happen to have a |
|
54 | // JQuery slider option keys. These keys happen to have a | |
55 | // one-to-one mapping with the corrosponding keys of the model. |
|
55 | // one-to-one mapping with the corrosponding keys of the model. | |
56 | var jquery_slider_keys = ['step', 'max', 'min', 'disabled']; |
|
56 | var jquery_slider_keys = ['step', 'max', 'min', 'disabled', 'range']; | |
57 | var that = this; |
|
57 | var that = this; | |
58 | _.each(jquery_slider_keys, function(key, i) { |
|
58 | _.each(jquery_slider_keys, function(key, i) { | |
59 | var model_value = that.model.get(key); |
|
59 | var model_value = that.model.get(key); | |
@@ -68,15 +68,25 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
68 | // of orientation change. Before applying the new |
|
68 | // of orientation change. Before applying the new | |
69 | // workaround, we set the value to the minimum to |
|
69 | // workaround, we set the value to the minimum to | |
70 | // make sure that the horizontal placement of the |
|
70 | // make sure that the horizontal placement of the | |
71 |
// handle in the vertical slider is always |
|
71 | // handle in the vertical slider is always | |
72 | // consistent. |
|
72 | // consistent. | |
73 | var orientation = this.model.get('orientation'); |
|
73 | var orientation = this.model.get('orientation'); | |
74 | var value = this.model.get('min'); |
|
74 | var value = this.model.get('min'); | |
75 | this.$slider.slider('option', 'value', value); |
|
75 | if (this.model.get('range')) { | |
|
76 | this.$slider.slider('option', 'values', [value, value]); | |||
|
77 | } else { | |||
|
78 | this.$slider.slider('option', 'value', value); | |||
|
79 | } | |||
76 | this.$slider.slider('option', 'orientation', orientation); |
|
80 | this.$slider.slider('option', 'orientation', orientation); | |
77 | value = this.model.get('value'); |
|
81 | value = this.model.get('value'); | |
78 | this.$slider.slider('option', 'value', value); |
|
82 | if (this.model.get('range')) { | |
79 |
this.$ |
|
83 | this.$slider.slider('option', 'values', value); | |
|
84 | this.$readout.text(value.join("-")); | |||
|
85 | } else { | |||
|
86 | this.$slider.slider('option', 'value', value); | |||
|
87 | this.$readout.text(value); | |||
|
88 | } | |||
|
89 | ||||
80 |
|
90 | |||
81 | // Use the right CSS classes for vertical & horizontal sliders |
|
91 | // Use the right CSS classes for vertical & horizontal sliders | |
82 | if (orientation=='vertical') { |
|
92 | if (orientation=='vertical') { | |
@@ -116,7 +126,7 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
116 | MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]); |
|
126 | MathJax.Hub.Queue(["Typeset",MathJax.Hub,this.$label.get(0)]); | |
117 | this.$label.show(); |
|
127 | this.$label.show(); | |
118 | } |
|
128 | } | |
119 |
|
129 | |||
120 | var readout = this.model.get('readout'); |
|
130 | var readout = this.model.get('readout'); | |
121 | if (readout) { |
|
131 | if (readout) { | |
122 | this.$readout.show(); |
|
132 | this.$readout.show(); | |
@@ -126,21 +136,27 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
126 | } |
|
136 | } | |
127 | return IntSliderView.__super__.update.apply(this); |
|
137 | return IntSliderView.__super__.update.apply(this); | |
128 | }, |
|
138 | }, | |
129 |
|
139 | |||
130 | events: { |
|
140 | events: { | |
131 | // Dictionary of events and their handlers. |
|
141 | // Dictionary of events and their handlers. | |
132 | "slide" : "handleSliderChange" |
|
142 | "slide" : "handleSliderChange" | |
133 |
}, |
|
143 | }, | |
134 |
|
144 | |||
135 |
handleSliderChange: function(e, ui) { |
|
145 | handleSliderChange: function(e, ui) { | |
136 | // Called when the slider value is changed. |
|
146 | // Called when the slider value is changed. | |
137 |
|
147 | |||
138 |
// Calling model.set will trigger all of the other views of the |
|
148 | // Calling model.set will trigger all of the other views of the | |
139 | // model to update. |
|
149 | // model to update. | |
140 | var actual_value = this._validate_slide_value(ui.value); |
|
150 | if (this.model.get("range")) { | |
|
151 | var actual_value = ui.values.map(this._validate_slide_value); | |||
|
152 | this.$readout.text(actual_value.join("-")); | |||
|
153 | } else { | |||
|
154 | var actual_value = this._validate_slide_value(ui.value); | |||
|
155 | this.$readout.text(actual_value); | |||
|
156 | } | |||
141 | this.model.set('value', actual_value, {updated_view: this}); |
|
157 | this.model.set('value', actual_value, {updated_view: this}); | |
142 | this.$readout.text(actual_value); |
|
|||
143 | this.touch(); |
|
158 | this.touch(); | |
|
159 | ||||
144 | }, |
|
160 | }, | |
145 |
|
161 | |||
146 | _validate_slide_value: function(x) { |
|
162 | _validate_slide_value: function(x) { | |
@@ -154,7 +170,7 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
154 | WidgetManager.register_widget_view('IntSliderView', IntSliderView); |
|
170 | WidgetManager.register_widget_view('IntSliderView', IntSliderView); | |
155 |
|
171 | |||
156 |
|
172 | |||
157 |
var IntTextView = IPython.DOMWidgetView.extend({ |
|
173 | var IntTextView = IPython.DOMWidgetView.extend({ | |
158 | render : function(){ |
|
174 | render : function(){ | |
159 | // Called when view is rendered. |
|
175 | // Called when view is rendered. | |
160 | this.$el |
|
176 | this.$el | |
@@ -170,18 +186,18 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
170 | this.$el_to_style = this.$textbox; // Set default element to style |
|
186 | this.$el_to_style = this.$textbox; // Set default element to style | |
171 | this.update(); // Set defaults. |
|
187 | this.update(); // Set defaults. | |
172 | }, |
|
188 | }, | |
173 |
|
189 | |||
174 | update : function(options){ |
|
190 | update : function(options){ | |
175 | // Update the contents of this view |
|
191 | // Update the contents of this view | |
176 | // |
|
192 | // | |
177 |
// Called when the model is changed. The model may have been |
|
193 | // Called when the model is changed. The model may have been | |
178 | // changed by another view or by a state update from the back-end. |
|
194 | // changed by another view or by a state update from the back-end. | |
179 | if (options === undefined || options.updated_view != this) { |
|
195 | if (options === undefined || options.updated_view != this) { | |
180 | var value = this.model.get('value'); |
|
196 | var value = this.model.get('value'); | |
181 | if (this._parse_value(this.$textbox.val()) != value) { |
|
197 | if (this._parse_value(this.$textbox.val()) != value) { | |
182 | this.$textbox.val(value); |
|
198 | this.$textbox.val(value); | |
183 | } |
|
199 | } | |
184 |
|
200 | |||
185 | if (this.model.get('disabled')) { |
|
201 | if (this.model.get('disabled')) { | |
186 | this.$textbox.attr('disabled','disabled'); |
|
202 | this.$textbox.attr('disabled','disabled'); | |
187 | } else { |
|
203 | } else { | |
@@ -208,20 +224,20 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
208 |
|
224 | |||
209 | // Fires only when control is validated or looses focus. |
|
225 | // Fires only when control is validated or looses focus. | |
210 | "change input" : "handleChanged" |
|
226 | "change input" : "handleChanged" | |
211 |
}, |
|
227 | }, | |
212 |
|
228 | |||
213 |
handleChanging: function(e) { |
|
229 | handleChanging: function(e) { | |
214 | // Handles and validates user input. |
|
230 | // Handles and validates user input. | |
215 |
|
231 | |||
216 | // Try to parse value as a int. |
|
232 | // Try to parse value as a int. | |
217 | var numericalValue = 0; |
|
233 | var numericalValue = 0; | |
218 | if (e.target.value !== '') { |
|
234 | if (e.target.value !== '') { | |
219 | var trimmed = e.target.value.trim(); |
|
235 | var trimmed = e.target.value.trim(); | |
220 | if (!(['-', '-.', '.', '+.', '+'].indexOf(trimmed) >= 0)) { |
|
236 | if (!(['-', '-.', '.', '+.', '+'].indexOf(trimmed) >= 0)) { | |
221 |
numericalValue = this._parse_value(e.target.value); |
|
237 | numericalValue = this._parse_value(e.target.value); | |
222 |
} |
|
238 | } | |
223 | } |
|
239 | } | |
224 |
|
240 | |||
225 | // If parse failed, reset value to value stored in model. |
|
241 | // If parse failed, reset value to value stored in model. | |
226 | if (isNaN(numericalValue)) { |
|
242 | if (isNaN(numericalValue)) { | |
227 | e.target.value = this.model.get('value'); |
|
243 | e.target.value = this.model.get('value'); | |
@@ -232,18 +248,18 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
232 | if (this.model.get('min') !== undefined) { |
|
248 | if (this.model.get('min') !== undefined) { | |
233 | numericalValue = Math.max(this.model.get('min'), numericalValue); |
|
249 | numericalValue = Math.max(this.model.get('min'), numericalValue); | |
234 | } |
|
250 | } | |
235 |
|
251 | |||
236 | // Apply the value if it has changed. |
|
252 | // Apply the value if it has changed. | |
237 | if (numericalValue != this.model.get('value')) { |
|
253 | if (numericalValue != this.model.get('value')) { | |
238 |
|
254 | |||
239 |
// Calling model.set will trigger all of the other views of the |
|
255 | // Calling model.set will trigger all of the other views of the | |
240 | // model to update. |
|
256 | // model to update. | |
241 | this.model.set('value', numericalValue, {updated_view: this}); |
|
257 | this.model.set('value', numericalValue, {updated_view: this}); | |
242 | this.touch(); |
|
258 | this.touch(); | |
243 | } |
|
259 | } | |
244 | } |
|
260 | } | |
245 | }, |
|
261 | }, | |
246 |
|
262 | |||
247 | handleChanged: function(e) { |
|
263 | handleChanged: function(e) { | |
248 | // Applies validated input. |
|
264 | // Applies validated input. | |
249 | if (this.model.get('value') != e.target.value) { |
|
265 | if (this.model.get('value') != e.target.value) { | |
@@ -279,18 +295,18 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
279 | .appendTo(this.$progress); |
|
295 | .appendTo(this.$progress); | |
280 | this.update(); // Set defaults. |
|
296 | this.update(); // Set defaults. | |
281 | }, |
|
297 | }, | |
282 |
|
298 | |||
283 | update : function(){ |
|
299 | update : function(){ | |
284 | // Update the contents of this view |
|
300 | // Update the contents of this view | |
285 | // |
|
301 | // | |
286 |
// Called when the model is changed. The model may have been |
|
302 | // Called when the model is changed. The model may have been | |
287 | // changed by another view or by a state update from the back-end. |
|
303 | // changed by another view or by a state update from the back-end. | |
288 | var value = this.model.get('value'); |
|
304 | var value = this.model.get('value'); | |
289 | var max = this.model.get('max'); |
|
305 | var max = this.model.get('max'); | |
290 | var min = this.model.get('min'); |
|
306 | var min = this.model.get('min'); | |
291 | var percent = 100.0 * (value - min) / (max - min); |
|
307 | var percent = 100.0 * (value - min) / (max - min); | |
292 | this.$bar.css('width', percent + '%'); |
|
308 | this.$bar.css('width', percent + '%'); | |
293 |
|
309 | |||
294 | var description = this.model.get('description'); |
|
310 | var description = this.model.get('description'); | |
295 | if (description.length === 0) { |
|
311 | if (description.length === 0) { | |
296 | this.$label.hide(); |
|
312 | this.$label.hide(); | |
@@ -300,7 +316,7 b' define(["widgets/js/widget"], function(WidgetManager){' | |||||
300 | this.$label.show(); |
|
316 | this.$label.show(); | |
301 | } |
|
317 | } | |
302 | return ProgressView.__super__.update.apply(this); |
|
318 | return ProgressView.__super__.update.apply(this); | |
303 |
}, |
|
319 | }, | |
304 | }); |
|
320 | }); | |
305 | WidgetManager.register_widget_view('ProgressView', ProgressView); |
|
321 | WidgetManager.register_widget_view('ProgressView', ProgressView); | |
306 |
|
322 |
@@ -5,7 +5,7 b' from .widget_button import ButtonWidget' | |||||
5 | from .widget_container import ContainerWidget, PopupWidget |
|
5 | from .widget_container import ContainerWidget, PopupWidget | |
6 | from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget |
|
6 | from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget | |
7 | from .widget_image import ImageWidget |
|
7 | from .widget_image import ImageWidget | |
8 | from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget |
|
8 | from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget, IntRangeSliderWidget | |
9 | from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget |
|
9 | from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget | |
10 | from .widget_selectioncontainer import TabWidget, AccordionWidget |
|
10 | from .widget_selectioncontainer import TabWidget, AccordionWidget | |
11 | from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget |
|
11 | from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget |
@@ -23,7 +23,7 b' from inspect import getcallargs' | |||||
23 | from IPython.core.getipython import get_ipython |
|
23 | from IPython.core.getipython import get_ipython | |
24 | from IPython.html.widgets import (Widget, TextWidget, |
|
24 | from IPython.html.widgets import (Widget, TextWidget, | |
25 | FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget, |
|
25 | FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget, | |
26 | ContainerWidget, DOMWidget) |
|
26 | ContainerWidget, DOMWidget, IntRangeSliderWidget) | |
27 | from IPython.display import display, clear_output |
|
27 | from IPython.display import display, clear_output | |
28 | from IPython.utils.py3compat import string_types, unicode_type |
|
28 | from IPython.utils.py3compat import string_types, unicode_type | |
29 | from IPython.utils.traitlets import HasTraits, Any, Unicode |
|
29 | from IPython.utils.traitlets import HasTraits, Any, Unicode | |
@@ -107,6 +107,15 b' def _widget_abbrev(o):' | |||||
107 | else: |
|
107 | else: | |
108 | cls = FloatSliderWidget |
|
108 | cls = FloatSliderWidget | |
109 | return cls(value=value, min=min, max=max, step=step) |
|
109 | return cls(value=value, min=min, max=max, step=step) | |
|
110 | elif _matches(o, [float_or_int]*4): | |||
|
111 | min, low, high, max = o | |||
|
112 | if not min <= low <= high <= max: | |||
|
113 | raise ValueError("Range input expects min <= low <= high <= max, got %r" % o) | |||
|
114 | if all(isinstance(_, int) for _ in o): | |||
|
115 | cls = IntRangeSliderWidget | |||
|
116 | else: | |||
|
117 | cls = FloatRangeSliderWidget | |||
|
118 | return cls(value=(low, high), min=min, max=max) | |||
110 | else: |
|
119 | else: | |
111 | return _widget_abbrev_single_value(o) |
|
120 | return _widget_abbrev_single_value(o) | |
112 |
|
121 |
@@ -1,4 +1,4 b'' | |||||
1 |
"""IntWidget class. |
|
1 | """IntWidget class. | |
2 |
|
2 | |||
3 | Represents an unbounded int using a widget. |
|
3 | Represents an unbounded int using a widget. | |
4 | """ |
|
4 | """ | |
@@ -14,13 +14,13 b' Represents an unbounded int using a widget.' | |||||
14 | # Imports |
|
14 | # Imports | |
15 | #----------------------------------------------------------------------------- |
|
15 | #----------------------------------------------------------------------------- | |
16 | from .widget import DOMWidget |
|
16 | from .widget import DOMWidget | |
17 | from IPython.utils.traitlets import Unicode, CInt, Bool, Enum |
|
17 | from IPython.utils.traitlets import Unicode, CInt, Bool, Enum, Tuple | |
18 |
|
18 | |||
19 | #----------------------------------------------------------------------------- |
|
19 | #----------------------------------------------------------------------------- | |
20 | # Classes |
|
20 | # Classes | |
21 | #----------------------------------------------------------------------------- |
|
21 | #----------------------------------------------------------------------------- | |
22 | class _IntWidget(DOMWidget): |
|
22 | class _IntWidget(DOMWidget): | |
23 |
value = CInt(0, help="Int value", sync=True) |
|
23 | value = CInt(0, help="Int value", sync=True) | |
24 | disabled = Bool(False, help="Enable or disable user changes", sync=True) |
|
24 | disabled = Bool(False, help="Enable or disable user changes", sync=True) | |
25 | description = Unicode(help="Description of the value this widget represents", sync=True) |
|
25 | description = Unicode(help="Description of the value this widget represents", sync=True) | |
26 |
|
26 | |||
@@ -51,10 +51,40 b' class BoundedIntTextWidget(_BoundedIntWidget):' | |||||
51 |
|
51 | |||
52 | class IntSliderWidget(_BoundedIntWidget): |
|
52 | class IntSliderWidget(_BoundedIntWidget): | |
53 | _view_name = Unicode('IntSliderView', sync=True) |
|
53 | _view_name = Unicode('IntSliderView', sync=True) | |
54 |
orientation = Enum([u'horizontal', u'vertical'], u'horizontal', |
|
54 | orientation = Enum([u'horizontal', u'vertical'], u'horizontal', | |
55 | help="Vertical or horizontal.", sync=True) |
|
55 | help="Vertical or horizontal.", sync=True) | |
|
56 | range = Bool(False, help="Display a range selector", sync=True) | |||
56 | readout = Bool(True, help="Display the current value of the slider next to it.", sync=True) |
|
57 | readout = Bool(True, help="Display the current value of the slider next to it.", sync=True) | |
57 |
|
58 | |||
58 |
|
59 | |||
59 | class IntProgressWidget(_BoundedIntWidget): |
|
60 | class IntProgressWidget(_BoundedIntWidget): | |
60 | _view_name = Unicode('ProgressView', sync=True) |
|
61 | _view_name = Unicode('ProgressView', sync=True) | |
|
62 | ||||
|
63 | class _IntRangeWidget(_IntWidget): | |||
|
64 | value = Tuple(CInt, CInt, default_value=(0, 1), help="Low and high int values", sync=True) | |||
|
65 | ||||
|
66 | class _BoundedIntRangeWidget(_IntRangeWidget): | |||
|
67 | step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True) | |||
|
68 | max = CInt(100, help="Max value", sync=True) | |||
|
69 | min = CInt(0, help="Min value", sync=True) | |||
|
70 | ||||
|
71 | def __init__(self, *pargs, **kwargs): | |||
|
72 | """Constructor""" | |||
|
73 | DOMWidget.__init__(self, *pargs, **kwargs) | |||
|
74 | self.on_trait_change(self._validate, ['value', 'min', 'max']) | |||
|
75 | ||||
|
76 | def _validate(self, name, old, new): | |||
|
77 | """Validate min <= low <= high <= max""" | |||
|
78 | if name == "value": | |||
|
79 | low, high = new | |||
|
80 | low = max(low, self.min) | |||
|
81 | high = min(high, self.max) | |||
|
82 | self.value = (min(low, high), max(low, high)) | |||
|
83 | ||||
|
84 | ||||
|
85 | class IntRangeSliderWidget(_BoundedIntRangeWidget): | |||
|
86 | _view_name = Unicode('IntSliderView', sync=True) | |||
|
87 | orientation = Enum([u'horizontal', u'vertical'], u'horizontal', | |||
|
88 | help="Vertical or horizontal.", sync=True) | |||
|
89 | range = Bool(True, help="Display a range selector", sync=True) | |||
|
90 | readout = Bool(True, help="Display the current value of the slider next to it.", sync=True) |
General Comments 0
You need to be logged in to leave comments.
Login now