Merge pull request #8142 from SylvainCorlay/slider_validation

Using the early validation hook for IntSlider and FloatSlider
This commit is contained in:
Min RK 2015-03-29 14:07:51 -07:00
commit b1d70df578
2 changed files with 50 additions and 52 deletions

View File

@ -1,4 +1,4 @@
"""Float class. """Float class.
Represents an unbounded float using a widget. Represents an unbounded float using a widget.
""" """
@ -15,7 +15,8 @@ Represents an unbounded float using a widget.
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
from .widget import DOMWidget, register from .widget import DOMWidget, register
from .trait_types import Color from .trait_types import Color
from IPython.utils.traitlets import Unicode, CFloat, Bool, CaselessStrEnum, Tuple from IPython.utils.traitlets import (Unicode, CFloat, Bool, CaselessStrEnum,
Tuple, TraitError)
from IPython.utils.warn import DeprecatedClass from IPython.utils.warn import DeprecatedClass
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@ -31,39 +32,37 @@ class _Float(DOMWidget):
kwargs['value'] = value kwargs['value'] = value
super(_Float, self).__init__(**kwargs) super(_Float, self).__init__(**kwargs)
class _BoundedFloat(_Float): class _BoundedFloat(_Float):
max = CFloat(100.0, help="Max value", sync=True) max = CFloat(100.0, help="Max value", sync=True)
min = CFloat(0.0, help="Min value", sync=True) min = CFloat(0.0, help="Min value", sync=True)
step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True) step = CFloat(0.1, help="Minimum step to increment the value (ignored by some views)", sync=True)
def __init__(self, *pargs, **kwargs): def __init__(self, *pargs, **kwargs):
"""Constructor""" """Constructor"""
super(_BoundedFloat, self).__init__(*pargs, **kwargs) super(_BoundedFloat, self).__init__(*pargs, **kwargs)
self._handle_value_changed('value', None, self.value)
self._handle_max_changed('max', None, self.max)
self._handle_min_changed('min', None, self.min)
self.on_trait_change(self._handle_value_changed, 'value')
self.on_trait_change(self._handle_max_changed, 'max')
self.on_trait_change(self._handle_min_changed, 'min')
def _handle_value_changed(self, name, old, new): def _value_validate(self, value, trait):
"""Validate value.""" """Cap and floor value"""
if self.min > new or new > self.max: if self.min > value or self.max < value:
self.value = min(max(new, self.min), self.max) value = min(max(value, self.min), self.max)
return value
def _handle_max_changed(self, name, old, new): def _min_validate(self, min, trait):
"""Make sure the min is always <= the max.""" """Enforce min <= value <= max"""
if new < self.min: if min > self.max:
raise ValueError("setting max < min") raise TraitError("Setting min > max")
if new < self.value: if min > self.value:
self.value = new self.value = min
return min
def _handle_min_changed(self, name, old, new): def _max_validate(self, max, trait):
"""Make sure the max is always >= the min.""" """Enforce min <= value <= max"""
if new > self.max: if max < self.min:
raise ValueError("setting min > max") raise TraitError("setting max < min")
if new > self.value: if max < self.value:
self.value = new self.value = max
return max
@register('IPython.FloatText') @register('IPython.FloatText')
@ -76,9 +75,9 @@ class FloatText(_Float):
value : float value : float
value displayed value displayed
description : str description : str
description displayed next to the textbox description displayed next to the text box
color : str Unicode color code (eg. '#C13535'), optional color : str Unicode color code (eg. '#C13535'), optional
color of the value displayed color of the value displayed
""" """
_view_name = Unicode('FloatTextView', sync=True) _view_name = Unicode('FloatTextView', sync=True)

View File

@ -1,4 +1,4 @@
"""Int class. """Int class.
Represents an unbounded int using a widget. Represents an unbounded int using a widget.
""" """
@ -15,7 +15,8 @@ Represents an unbounded int using a widget.
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
from .widget import DOMWidget, register from .widget import DOMWidget, register
from .trait_types import Color from .trait_types import Color
from IPython.utils.traitlets import Unicode, CInt, Bool, CaselessStrEnum, Tuple from IPython.utils.traitlets import (Unicode, CInt, Bool, CaselessStrEnum,
Tuple, TraitError)
from IPython.utils.warn import DeprecatedClass from IPython.utils.warn import DeprecatedClass
#----------------------------------------------------------------------------- #-----------------------------------------------------------------------------
@ -32,41 +33,39 @@ class _Int(DOMWidget):
kwargs['value'] = value kwargs['value'] = value
super(_Int, self).__init__(**kwargs) super(_Int, self).__init__(**kwargs)
class _BoundedInt(_Int): class _BoundedInt(_Int):
"""Base class used to create widgets that represent a int that is bounded """Base class used to create widgets that represent a int that is bounded
by a minium and maximum.""" by a minium and maximum."""
step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True) step = CInt(1, help="Minimum step to increment the value (ignored by some views)", sync=True)
max = CInt(100, help="Max value", sync=True) max = CInt(100, help="Max value", sync=True)
min = CInt(0, help="Min value", sync=True) min = CInt(0, help="Min value", sync=True)
def __init__(self, *pargs, **kwargs): def __init__(self, *pargs, **kwargs):
"""Constructor""" """Constructor"""
super(_BoundedInt, self).__init__(*pargs, **kwargs) super(_BoundedInt, self).__init__(*pargs, **kwargs)
self._handle_value_changed('value', None, self.value)
self._handle_max_changed('max', None, self.max)
self._handle_min_changed('min', None, self.min)
self.on_trait_change(self._handle_value_changed, 'value')
self.on_trait_change(self._handle_max_changed, 'max')
self.on_trait_change(self._handle_min_changed, 'min')
def _handle_value_changed(self, name, old, new): def _value_validate(self, value, trait):
"""Validate value.""" """Cap and floor value"""
if self.min > new or new > self.max: if self.min > value or self.max < value:
self.value = min(max(new, self.min), self.max) value = min(max(value, self.min), self.max)
return value
def _handle_max_changed(self, name, old, new): def _min_validate(self, min, trait):
"""Make sure the min is always <= the max.""" """Enforce min <= value <= max"""
if new < self.min: if min > self.max:
raise ValueError("setting max < min") raise TraitError("Setting min > max")
if new < self.value: if min > self.value:
self.value = new self.value = min
return min
def _handle_min_changed(self, name, old, new): def _max_validate(self, max, trait):
"""Make sure the max is always >= the min.""" """Enforce min <= value <= max"""
if new > self.max: if max < self.min:
raise ValueError("setting min > max") raise TraitError("setting max < min")
if new > self.value: if max < self.value:
self.value = new self.value = max
return max
@register('IPython.IntText') @register('IPython.IntText')
class IntText(_Int): class IntText(_Int):