# Source code for qwt.scale_div

    # -*- coding: utf-8 -*-
    #
    # Licensed under the terms of the Qwt License
    # Copyright (c) 2002 Uwe Rathmann, for the original C++ code
    # Copyright (c) 2015 Pierre Raybaut, for the Python translation/optimization
    # (see LICENSE file for more details)

    """
    QwtScaleDiv
    -----------

    .. autoclass:: QwtScaleDiv
       :members:
    """

    import copy

    from qwt.interval import QwtInterval

    class QwtScaleDiv(object):
        """
        A class representing a scale division

        A Qwt scale is defined by its boundaries and 3 list
        for the positions of the major, medium and minor ticks.

        The `upperLimit()` might be smaller than the `lowerLimit()`
        to indicate inverted scales.

        Scale divisions can be calculated from a `QwtScaleEngine`.

        .. seealso::

            :py:meth:`qwt.scale_engine.QwtScaleEngine.divideScale()`,
            :py:meth:`qwt.plot.QwtPlot.setAxisScaleDiv()`

        Scale tick types:

          * `QwtScaleDiv.NoTick`: No ticks
          * `QwtScaleDiv.MinorTick`: Minor ticks
          * `QwtScaleDiv.MediumTick`: Medium ticks
          * `QwtScaleDiv.MajorTick`: Major ticks
          * `QwtScaleDiv.NTickTypes`: Number of valid tick types

        .. py:class:: QwtScaleDiv()

            Basic constructor. Lower bound = Upper bound = 0.

        .. py:class:: QwtScaleDiv(interval, ticks)
            :noindex:

            :param qwt.interval.QwtInterval interval: Interval
            :param list ticks: list of major, medium and minor ticks

        .. py:class:: QwtScaleDiv(lowerBound, upperBound)
            :noindex:

            :param float lowerBound: First boundary
            :param float upperBound: Second boundary

        .. py:class:: QwtScaleDiv(lowerBound, upperBound, ticks)
            :noindex:

            :param float lowerBound: First boundary
            :param float upperBound: Second boundary
            :param list ticks: list of major, medium and minor ticks

        .. py:class:: QwtScaleDiv(lowerBound, upperBound, minorTicks, mediumTicks, majorTicks)
            :noindex:

            :param float lowerBound: First boundary
            :param float upperBound: Second boundary
            :param list minorTicks: list of minor ticks
            :param list mediumTicks: list of medium ticks
            :param list majorTicks: list of major ticks

        .. note::

            lowerBound might be greater than upperBound for inverted scales
        """

        # enum TickType
        NoTick = -1
        MinorTick, MediumTick, MajorTick, NTickTypes = list(range(4))

        def __init__(self, *args):
            self.__ticks = None
            if len(args) == 2 and isinstance(args[1], (tuple, list)):
                interval, ticks = args
                self.__lowerBound = interval.minValue()
                self.__upperBound = interval.maxValue()
                self.__ticks = ticks[:]
            elif len(args) == 2:
                self.__lowerBound, self.__upperBound = args
            elif len(args) == 3:
                self.__lowerBound, self.__upperBound, ticks = args
                self.__ticks = ticks[:]
            elif len(args) == 5:
                (
                    self.__lowerBound,
                    self.__upperBound,
                    minorTicks,
                    mediumTicks,
                    majorTicks,
                ) = args
                self.__ticks = [0] * self.NTickTypes
                self.__ticks[self.MinorTick] = minorTicks
                self.__ticks[self.MediumTick] = mediumTicks
                self.__ticks[self.MajorTick] = majorTicks
            elif len(args) == 0:
                self.__lowerBound, self.__upperBound = 0.0, 0.0
            else:
                raise TypeError(
                    "%s() takes 0, 2, 3 or 5 argument(s) (%s given)"
                    % (self.__class__.__name__, len(args))
                )

        def setInterval(self, *args):
            """
            Change the interval

            .. py:method:: setInterval(lowerBound, upperBound)
                :noindex:

                :param float lowerBound: First boundary
                :param float upperBound: Second boundary

            .. py:method:: setInterval(interval)
                :noindex:

                :param qwt.interval.QwtInterval interval: Interval

            .. note::

                lowerBound might be greater than upperBound for inverted scales
            """
            if len(args) == 2:
                self.__lowerBound, self.__upperBound = args
            elif len(args) == 1:
                (interval,) = args
                self.__lowerBound = interval.minValue()
                self.__upperBound = interval.maxValue()
            else:
                raise TypeError(
                    "%s().setInterval() takes 1 or 2 argument(s) (%s "
                    "given)" % (self.__class__.__name__, len(args))
                )

        def interval(self):
            """
            :return: Interval
            """
            return QwtInterval(self.__lowerBound, self.__upperBound)

        def setLowerBound(self, lowerBound):
            """
            Set the first boundary

            :param float lowerBound: First boundary

            .. seealso::

                :py:meth:`lowerBound()`, :py:meth:`setUpperBound()`
            """
            self.__lowerBound = lowerBound

        def lowerBound(self):
            """
            :return: the first boundary

            .. seealso::

                :py:meth:`upperBound()`
            """
            return self.__lowerBound

        def setUpperBound(self, upperBound):
            """
            Set the second boundary

            :param float lowerBound: Second boundary

            .. seealso::

                :py:meth:`upperBound()`, :py:meth:`setLowerBound()`
            """
            self.__upperBound = upperBound

        def upperBound(self):
            """
            :return: the second boundary

            .. seealso::

                :py:meth:`lowerBound()`
            """
            return self.__upperBound

        def range(self):
            """
            :return: upperBound() - lowerBound()
            """
            return self.__upperBound - self.__lowerBound

        def __eq__(self, other):
            if self.__ticks is None:
                return False
            if (
                self.__lowerBound != other.__lowerBound
                or self.__upperBound != other.__upperBound
            ):
                return False
            return self.__ticks == other.__ticks

        def __ne__(self, other):
            return not self.__eq__(other)

        def isEmpty(self):
            """
            Check if the scale division is empty( lowerBound() == upperBound() )
            """
            return self.__lowerBound == self.__upperBound

        def isIncreasing(self):
            """
            Check if the scale division is increasing( lowerBound() <= upperBound() )
            """
            return self.__lowerBound <= self.__upperBound

        def contains(self, value):
            """
            Return if a value is between lowerBound() and upperBound()

            :param float value: Value
            :return: True/False
            """
            min_ = min([self.__lowerBound, self.__upperBound])
            max_ = max([self.__lowerBound, self.__upperBound])
            return value >= min_ and value <= max_

        def invert(self):
            """
            Invert the scale division

            .. seealso::

                :py:meth:`inverted()`
            """
            (self.__lowerBound, self.__upperBound) = self.__upperBound, self.__lowerBound
            for index in range(self.NTickTypes):
                self.__ticks[index].reverse()

        def inverted(self):
            """
            :return: A scale division with inverted boundaries and ticks

            .. seealso::

                :py:meth:`invert()`
            """
            other = copy.deepcopy(self)
            other.invert()
            return other

        def bounded(self, lowerBound, upperBound):
            """
            Return a scale division with an interval [lowerBound, upperBound]
            where all ticks outside this interval are removed

            :param float lowerBound: First boundary
            :param float lowerBound: Second boundary
            :return: Scale division with all ticks inside of the given interval

            .. note::

                lowerBound might be greater than upperBound for inverted scales
            """
            min_ = min([self.__lowerBound, self.__upperBound])
            max_ = max([self.__lowerBound, self.__upperBound])
            sd = QwtScaleDiv()
            sd.setInterval(lowerBound, upperBound)
            for tickType in range(self.NTickTypes):
                sd.setTicks(
                    tickType,
                    [
                        tick
                        for tick in self.__ticks[tickType]
                        if tick >= min_ and tick <= max_
                    ],
                )
            return sd

        def setTicks(self, tickType, ticks):
            """
            Assign ticks

            :param int type: MinorTick, MediumTick or MajorTick
            :param list ticks: Values of the tick positions
            """
            if tickType in range(self.NTickTypes):
                self.__ticks[tickType] = ticks

        def ticks(self, tickType):
            """
            Return a list of ticks

            :param int type: MinorTick, MediumTick or MajorTick
            :return: Tick list
            """
            if self.__ticks is not None and tickType in range(self.NTickTypes):
                return self.__ticks[tickType]
            else:
                return []