Source code for traitsui.editors.range_editor

# (C) Copyright 2004-2023 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

""" Defines the range editor factory for all traits user interface toolkits.
"""
import warnings

from types import CodeType

from traits.api import (
    Any,
    Bool,
    CTrait,
    Enum,
    Int,
    Property,
    Range,
    Str,
    Undefined,
)


from traitsui.editor_factory import EditorFactory
from traitsui.toolkit import toolkit_object
from traitsui.view import View


[docs]class RangeEditor(EditorFactory): """Editor factory for range editors.""" # ------------------------------------------------------------------------- # Trait definitions: # ------------------------------------------------------------------------- #: Number of columns when displayed as an enumeration cols = Range(1, 20) #: Is user input set on every keystroke? auto_set = Bool(True) #: Is user input set when the Enter key is pressed? enter_set = Bool(False) #: Label for the low end of the range low_label = Str() #: Label for the high end of the range high_label = Str() #: FIXME: This is supported only in the wx backend so far. #: The width of the low and high labels label_width = Int() #: The name of an [object.]trait that defines the low value for the range low_name = Str() #: The name of an [object.]trait that defines the high value for the range high_name = Str() #: Formatting string used to format value and labels format_str = Str("%s") #: Is the range for floating pointer numbers (vs. integers)? is_float = Bool(Undefined) #: Function to evaluate floats/ints when they are assigned to an object #: trait evaluate = Any() #: The object trait containing the function used to evaluate floats/ints evaluate_name = Str() #: Low end of range low = Property() #: High end of range high = Property() #: Display mode to use mode = Enum( "auto", "slider", "xslider", "spinner", "enum", "text", "logslider" ) # ------------------------------------------------------------------------- # Traits view definition: # ------------------------------------------------------------------------- traits_view = View( [ ["low", "high", "|[Range]"], ["low_label{Low}", "high_label{High}", "|[Range Labels]"], [ "auto_set{Set automatically}", "enter_set{Set on enter key pressed}", "is_float{Is floating point range}", "-[Options]>", ], ["cols", "|[Number of columns for integer custom style]<>"], ] )
[docs] def init(self, handler=None): """Performs any initialization needed after all constructor traits have been set. """ if handler is not None: if isinstance(handler, CTrait): handler = handler.handler if self.low_name == "": if isinstance(handler._low, CodeType): self.low = eval(handler._low) else: self.low = handler._low if self.high_name == "": if isinstance(handler._low, CodeType): self.high = eval(handler._high) else: self.high = handler._high else: if (self.low is None) and (self.low_name == ""): self.low = 0.0 if (self.high is None) and (self.high_name == ""): self.high = 1.0
def _get_low(self): return self._low def _set_low(self, low): old_low = self._low self._low = low = self._cast(low) if self.is_float is Undefined: self.is_float = isinstance(low, float) if (self.low_label == "") or (self.low_label == str(old_low)): self.low_label = str(low) def _get_high(self): return self._high def _set_high(self, high): old_high = self._high self._high = high = self._cast(high) if self.is_float is Undefined: self.is_float = isinstance(high, float) if (self.high_label == "") or (self.high_label == str(old_high)): self.high_label = str(high) def _cast(self, value): if not isinstance(value, str): return value try: return int(value) except ValueError: return float(value) # -- Private Methods ------------------------------------------------------ def _get_low_high(self, ui): """Returns the low and high values used to determine the initial range.""" low, high = self.low, self.high if (low is None) and (self.low_name != ""): low = self.named_value(self.low_name, ui) if self.is_float is Undefined: self.is_float = isinstance(low, float) if (high is None) and (self.high_name != ""): high = self.named_value(self.high_name, ui) if self.is_float is Undefined: self.is_float = isinstance(high, float) if self.is_float is Undefined: self.is_float = True return (low, high, self.is_float) # ------------------------------------------------------------------------- # Property getters. # ------------------------------------------------------------------------- def _get_format(self): warnings.warn( "Use of format trait is deprecated. Use format_str instead.", DeprecationWarning, stacklevel=2, ) return self.format_str def _set_format(self, format_string): warnings.warn( "Use of format trait is deprecated. Use format_str instead.", DeprecationWarning, stacklevel=2, ) self.format_str = format_string def _get_simple_editor_class(self): """Returns the editor class to use for a simple style. The type of editor depends on the type and extent of the range being edited: * One end of range is unspecified: RangeTextEditor * **mode** is specified and not 'auto': editor corresponding to **mode** * Floating point range with extent > 100: LargeRangeSliderEditor * Integer range or floating point range with extent <= 100: SimpleSliderEditor * All other cases: SimpleSpinEditor """ low, high, is_float = self._low_value, self._high_value, self.is_float if (low is None) or (high is None): return toolkit_object("range_editor:RangeTextEditor") if (not is_float) and (abs(high - low) > 1000000000): return toolkit_object("range_editor:RangeTextEditor") if self.mode != "auto": return toolkit_object("range_editor:SimpleEditorMap")[self.mode] if is_float and (abs(high - low) > 100): return toolkit_object("range_editor:LargeRangeSliderEditor") if is_float or (abs(high - low) <= 100): return toolkit_object("range_editor:SimpleSliderEditor") return toolkit_object("range_editor:SimpleSpinEditor") def _get_custom_editor_class(self): """Creates a custom style of range editor The type of editor depends on the type and extent of the range being edited: * One end of range is unspecified: RangeTextEditor * **mode** is specified and not 'auto': editor corresponding to **mode** * Floating point range: Same as "simple" style * Integer range with extent > 15: Same as "simple" style * Integer range with extent <= 15: CustomEnumEditor """ low, high, is_float = self._low_value, self._high_value, self.is_float if (low is None) or (high is None): return toolkit_object("range_editor:RangeTextEditor") if self.mode != "auto": return toolkit_object("range_editor:CustomEditorMap")[self.mode] if is_float or (abs(high - low) > 15): return self.simple_editor_class return toolkit_object("range_editor:CustomEnumEditor") def _get_text_editor_class(self): """Returns the editor class to use for a text style.""" return toolkit_object("range_editor:RangeTextEditor") # ------------------------------------------------------------------------- # 'Editor' factory methods: # -------------------------------------------------------------------------
[docs] def simple_editor(self, ui, object, name, description, parent): """Generates an editor using the "simple" style. Overridden to set the values of the _low_value, _high_value and is_float traits. """ self._low_value, self._high_value, self.is_float = self._get_low_high( ui ) return super().simple_editor(ui, object, name, description, parent)
[docs] def custom_editor(self, ui, object, name, description, parent): """Generates an editor using the "custom" style. Overridden to set the values of the _low_value, _high_value and is_float traits. """ self._low_value, self._high_value, self.is_float = self._get_low_high( ui ) return super().custom_editor(ui, object, name, description, parent)
# This alias is deprecated and will be removed in TraitsUI 8. ToolkitEditorFactory = RangeEditor