Source code for enaml.widgets.dual_slider

#------------------------------------------------------------------------------
# Copyright (c) 2013-2023, Nucleic Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file LICENSE, distributed with this software.
#------------------------------------------------------------------------------
from atom.api import Bool, Enum, Int, Range, Typed, ForwardTyped

from enaml.core.declarative import d_, observe

from .control import Control, ProxyControl


#: The base tick position enum definition.
TickPosition = Enum('no_ticks', 'left', 'right', 'top', 'bottom', 'both')


class ProxyDualSlider(ProxyControl):
    """ The abstract definition of a proxy Slider object.

    """
    #: A reference to the Slider declaration.
    declaration = ForwardTyped(lambda: DualSlider)

    def set_minimum(self, minimum):
        raise NotImplementedError

    def set_maximum(self, maximum):
        raise NotImplementedError

    def set_low_value(self, value):
        raise NotImplementedError

    def set_high_value(self, value):
        raise NotImplementedError

    def set_tick_position(self, position):
        raise NotImplementedError

    def set_tick_interval(self, interval):
        raise NotImplementedError

    def set_orientation(self, orientation):
        raise NotImplementedError

    # def set_tracking(self, tracking):
    #     raise NotImplementedError


[docs] class DualSlider(Control): """ A simple dual slider widget. A dual slider can be used to select a range within a larger range of integral values. """ #: The minimum slider value. If the minimum value is changed such #: that it becomes greater than the current value or the maximum #: value, then those values will be adjusted. The default is 0. minimum = d_(Int(0)) #: The maximum slider value. If the maximum value is changed such #: that it becomes smaller than the current value or the minimum #: value, then those values will be adjusted. The default is 100. maximum = d_(Int(100)) #: The low position value of the DualSlider. The value will be #: clipped to always fall between the minimum and maximum and be #: smaller than the high value. low_value = d_(Int()) #: The high position value of the DualSlider. The value will be #: clipped to always fall between the minimum and maximum and be #: larger than the low value. high_value = d_(Int()) #: A TickPosition enum value indicating how to display the tick #: marks. Note that the orientation takes precedence over the tick #: mark position and an incompatible tick position will be adapted #: according to the current orientation. The default tick position #: is 'bottom'. tick_position = d_(TickPosition('bottom')) #: The interval to place between slider tick marks in value units #: (as opposed to pixels). The minimum value is 0, which indicates #: that the choice is left up to the client. tick_interval = d_(Range(low=0)) #: The orientation of the slider. The default is 'horizontal'. When #: the orientation is flipped the tick positions (if set) also adapt #: to reflect the changes (e.g. the LEFT becomes TOP when the #: orientation becomes horizontal). orientation = d_(Enum('horizontal', 'vertical')) #: Whether or not to automatically adjust the 'hug_width' and #: 'hug_height' values based on the value of 'orientation'. auto_hug = Bool(True) #: A reference to the ProxyDualSlider object. proxy = Typed(ProxyDualSlider) #-------------------------------------------------------------------------- # Observers #-------------------------------------------------------------------------- @observe('minimum', 'maximum', 'low_value', 'high_value', 'tick_position', 'tick_interval', 'orientation') def _update_proxy(self, change): """ An observer which sends state change to the proxy. """ # The superclass handler implementation is sufficient. super(DualSlider, self)._update_proxy(change) #-------------------------------------------------------------------------- # DefaultValue Handlers #-------------------------------------------------------------------------- def _default_hug_width(self): """ Get the default hug width for the slider. The default hug width is computed based on the orientation. """ if self.orientation == 'horizontal': return 'ignore' return 'strong' def _default_hug_height(self): """ Get the default hug height for the slider. The default hug height is computed based on the orientation. """ if self.orientation == 'vertical': return 'ignore' return 'strong' def _default_low_value(self): """ Get the default low value for the slider The default low value is the minimum of the slider. """ return self.minimum def _default_high_value(self): """ Get the default high value for the slider The default high value is the maximum of the slider. """ return self.maximum #-------------------------------------------------------------------------- # PostSetAttr Handlers #-------------------------------------------------------------------------- def _post_setattr_orientation(self, old, new): """ Post setattr the orientation for the slider. If auto hug is enabled, the hug values will be updated. """ if self.auto_hug: if new == 'vertical': self.hug_width = 'strong' self.hug_height = 'ignore' else: self.hug_width = 'ignore' self.hug_height = 'strong' def _post_setattr_minimum(self, old, new): """ Post setattr the minimum value for the slider. If the new minimum is greater than the current value or maximum, those values are adjusted up. """ if new > self.maximum: self.maximum = new if new > self.high_value: self.high_value = new if new > self.low_value: self.low_value = new def _post_setattr_maximum(self, old, new): """ Post setattr the maximum value for the slider. If the new maximum is less than the current value or the minimum, those values are adjusted down. """ if new < self.minimum: self.minimum = new if new < self.low_value: self.low_value = new if new < self.high_value: self.high_value = new #-------------------------------------------------------------------------- # Post Validation Handlers #-------------------------------------------------------------------------- def _post_validate_low_value(self, old, new): """ Post validate the low_value for the slider. The low_value is clipped to minimum and high_value bounds. """ return max(self.minimum, min(new, self.maximum)) def _post_validate_high_value(self, old, new): """ Post validate the high_value for the slider. The high_value is clipped to low_value and maximum bounds. """ return max(self.minimum, min(new, self.maximum))