# Source code for qwt.plot_grid

    # -*- 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)

    """
    QwtPlotGrid
    -----------

    .. autoclass:: QwtPlotGrid
       :members:
    """

    from qwt.scale_div import QwtScaleDiv
    from qwt.plot import QwtPlotItem
    from qwt.text import QwtText
    from qwt.painter import QwtPainter
    from qwt.math import qwtFuzzyGreaterOrEqual, qwtFuzzyLessOrEqual

    from qwt.qt.QtGui import QPen
    from qwt.qt.QtCore import Qt

    class QwtPlotGrid_PrivateData(object):
        def __init__(self):
            self.xEnabled = True
            self.yEnabled = True
            self.xMinEnabled = False
            self.yMinEnabled = False
            self.xScaleDiv = QwtScaleDiv()
            self.yScaleDiv = QwtScaleDiv()
            self.majorPen = QPen()
            self.minorPen = QPen()

    class QwtPlotGrid(QwtPlotItem):
        """
        A class which draws a coordinate grid

        The `QwtPlotGrid` class can be used to draw a coordinate grid.
        A coordinate grid consists of major and minor vertical
        and horizontal grid lines. The locations of the grid lines
        are determined by the X and Y scale divisions which can
        be assigned with `setXDiv()` and `setYDiv()`.
        The `draw()` member draws the grid within a bounding
        rectangle.
        """

        def __init__(self):
            QwtPlotItem.__init__(self, QwtText("Grid"))
            self.__data = QwtPlotGrid_PrivateData()
            self.setItemInterest(QwtPlotItem.ScaleInterest, True)
            self.setZ(10.)

        def rtti(self):
            """
            :return: Return `QwtPlotItem.Rtti_PlotGrid`
            """
            return QwtPlotItem.Rtti_PlotGrid

        def enableX(self, on):
            """
            Enable or disable vertical grid lines

            :param bool on: Enable (true) or disable

            .. seealso::

                :py:meth:`enableXMin()`
            """
            if self.__data.xEnabled != on:
                self.__data.xEnabled = on
                self.legendChanged()
                self.itemChanged()

        def enableY(self, on):
            """
            Enable or disable horizontal grid lines

            :param bool on: Enable (true) or disable

            .. seealso::

                :py:meth:`enableYMin()`
            """
            if self.__data.yEnabled != on:
                self.__data.yEnabled = on
                self.legendChanged()
                self.itemChanged()

        def enableXMin(self, on):
            """
            Enable or disable  minor vertical grid lines.

            :param bool on: Enable (true) or disable

            .. seealso::

                :py:meth:`enableX()`
            """
            if self.__data.xMinEnabled != on:
                self.__data.xMinEnabled = on
                self.legendChanged()
                self.itemChanged()

        def enableYMin(self, on):
            """
            Enable or disable  minor horizontal grid lines.

            :param bool on: Enable (true) or disable

            .. seealso::

                :py:meth:`enableY()`
            """
            if self.__data.yMinEnabled != on:
                self.__data.yMinEnabled = on
                self.legendChanged()
                self.itemChanged()

        def setXDiv(self, scaleDiv):
            """
            Assign an x axis scale division

            :param qwt.scale_div.QwtScaleDiv scaleDiv: Scale division
            """
            if self.__data.xScaleDiv != scaleDiv:
                self.__data.xScaleDiv = scaleDiv
                self.itemChanged()

        def setYDiv(self, scaleDiv):
            """
            Assign an y axis scale division

            :param qwt.scale_div.QwtScaleDiv scaleDiv: Scale division
            """
            if self.__data.yScaleDiv != scaleDiv:
                self.__data.yScaleDiv = scaleDiv
                self.itemChanged()

        def setPen(self, *args):
            """
            Build and/or assign a pen for both major and minor grid lines

            .. py:method:: setPen(color, width, style)

                Build and assign a pen for both major and minor grid lines

                In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
                non cosmetic (see `QPen.isCosmetic()`). This method signature has
                been introduced to hide this incompatibility.

                :param QColor color: Pen color
                :param float width: Pen width
                :param Qt.PenStyle style: Pen style

            .. py:method:: setPen(pen)

                Assign a pen for both major and minor grid lines

                :param QPen pen: New pen

            .. seealso::

                :py:meth:`pen()`, :py:meth:`brush()`
            """
            if len(args) == 3:
                color, width, style = args
                self.setPen(QPen(color, width, style))
            elif len(args) == 1:
                pen, = args
                if self.__data.majorPen != pen or self.__data.minorPen != pen:
                    self.__data.majorPen = pen
                    self.__data.minorPen = pen
                    self.legendChanged()
                    self.itemChanged()
            else:
                raise TypeError("%s().setPen() takes 1 or 3 argument(s) (%s given)"\
                                % (self.__class__.__name__, len(args)))

        def setMajorPen(self, *args):
            """
            Build and/or assign a pen for both major grid lines

            .. py:method:: setMajorPen(color, width, style)

                Build and assign a pen for both major grid lines

                In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
                non cosmetic (see `QPen.isCosmetic()`). This method signature has
                been introduced to hide this incompatibility.

                :param QColor color: Pen color
                :param float width: Pen width
                :param Qt.PenStyle style: Pen style

            .. py:method:: setMajorPen(pen)

                Assign a pen for the major grid lines

                :param QPen pen: New pen

            .. seealso::

                :py:meth:`majorPen()`, :py:meth:`setMinorPen()`,
                :py:meth:`setPen()`, :py:meth:`pen()`, :py:meth:`brush()`
            """
            if len(args) == 3:
                color, width, style = args
                self.setMajorPen(QPen(color, width, style))
            elif len(args) == 1:
                pen, = args
                if self.__data.majorPen != pen:
                    self.__data.majorPen = pen
                    self.legendChanged()
                    self.itemChanged()
            else:
                raise TypeError("%s().setMajorPen() takes 1 or 3 argument(s) (%s "\
                                "given)" % (self.__class__.__name__, len(args)))

        def setMinorPen(self, *args):
            """
            Build and/or assign a pen for both minor grid lines

            .. py:method:: setMinorPen(color, width, style)

                Build and assign a pen for both minor grid lines

                In Qt5 the default pen width is 1.0 ( 0.0 in Qt4 ) what makes it
                non cosmetic (see `QPen.isCosmetic()`). This method signature has
                been introduced to hide this incompatibility.

                :param QColor color: Pen color
                :param float width: Pen width
                :param Qt.PenStyle style: Pen style

            .. py:method:: setMinorPen(pen)

                Assign a pen for the minor grid lines

                :param QPen pen: New pen

            .. seealso::

                :py:meth:`minorPen()`, :py:meth:`setMajorPen()`,
                :py:meth:`setPen()`, :py:meth:`pen()`, :py:meth:`brush()`
            """
            if len(args) == 3:
                color, width, style = args
                self.setMinorPen(QPen(color, width, style))
            elif len(args) == 1:
                pen, = args
                if self.__data.minorPen != pen:
                    self.__data.minorPen = pen
                    self.legendChanged()
                    self.itemChanged()
            else:
                raise TypeError("%s().setMinorPen() takes 1 or 3 argument(s) (%s "\
                                "given)" % (self.__class__.__name__, len(args)))

        def draw(self, painter, xMap, yMap, canvasRect):
            """
            Draw the grid

            The grid is drawn into the bounding rectangle such that
            grid lines begin and end at the rectangle's borders. The X and Y
            maps are used to map the scale divisions into the drawing region
            screen.

            :param QPainter painter: Painter
            :param qwt.scale_map.QwtScaleMap xMap: X axis map
            :param qwt.scale_map.QwtScaleMap yMap: Y axis
            :param QRectF canvasRect: Contents rectangle of the plot canvas
            """
            minorPen = QPen(self.__data.minorPen)
            minorPen.setCapStyle(Qt.FlatCap)
            painter.setPen(minorPen)
            if self.__data.xEnabled and self.__data.xMinEnabled:
                self.drawLines(painter, canvasRect, Qt.Vertical, xMap,
                               self.__data.xScaleDiv.ticks(QwtScaleDiv.MinorTick))
                self.drawLines(painter, canvasRect, Qt.Vertical, xMap,
                               self.__data.xScaleDiv.ticks(QwtScaleDiv.MediumTick))
            if self.__data.yEnabled and self.__data.yMinEnabled:
                self.drawLines(painter, canvasRect, Qt.Horizontal, yMap,
                               self.__data.yScaleDiv.ticks(QwtScaleDiv.MinorTick))
                self.drawLines(painter, canvasRect, Qt.Horizontal, yMap,
                               self.__data.yScaleDiv.ticks(QwtScaleDiv.MediumTick))
            majorPen = QPen(self.__data.majorPen)
            majorPen.setCapStyle(Qt.FlatCap)
            painter.setPen(majorPen)
            if self.__data.xEnabled:
                self.drawLines(painter, canvasRect, Qt.Vertical, xMap,
                               self.__data.xScaleDiv.ticks(QwtScaleDiv.MajorTick))
            if self.__data.yEnabled:
                self.drawLines(painter, canvasRect, Qt.Horizontal, yMap,
                               self.__data.yScaleDiv.ticks(QwtScaleDiv.MajorTick))

        def drawLines(self, painter, canvasRect, orientation, scaleMap, values):
            x1 = canvasRect.left()
            x2 = canvasRect.right()-1.
            y1 = canvasRect.top()
            y2 = canvasRect.bottom()-1.
            for val in values:
                value = scaleMap.transform(val)
                if orientation == Qt.Horizontal:
                    if qwtFuzzyGreaterOrEqual(value, y1) and\
                       qwtFuzzyLessOrEqual(value, y2):
                        painter.drawLine(x1, value, x2, value)
                else:
                    if qwtFuzzyGreaterOrEqual(value, x1) and\
                       qwtFuzzyLessOrEqual(value, x2):
                        painter.drawLine(value, y1, value, y2)

        def majorPen(self):
            """
            :return: the pen for the major grid lines

            .. seealso::

                :py:meth:`setMajorPen()`, :py:meth:`setMinorPen()`,
                :py:meth:`setPen()`
            """
            return self.__data.majorPen

        def minorPen(self):
            """
            :return: the pen for the minor grid lines

            .. seealso::

                :py:meth:`setMinorPen()`, :py:meth:`setMajorPen()`,
                :py:meth:`setPen()`
            """
            return self.__data.minorPen

        def xEnabled(self):
            """
            :return: True if vertical grid lines are enabled

            .. seealso::

                :py:meth:`enableX()`
            """
            return self.__data.xEnabled

        def yEnabled(self):
            """
            :return: True if horizontal grid lines are enabled

            .. seealso::

                :py:meth:`enableY()`
            """
            return self.__data.yEnabled

        def xMinEnabled(self):
            """
            :return: True if minor vertical grid lines are enabled

            .. seealso::

                :py:meth:`enableXMin()`
            """
            return self.__data.xMinEnabled

        def yMinEnabled(self):
            """
            :return: True if minor horizontal grid lines are enabled

            .. seealso::

                :py:meth:`enableYMin()`
            """
            return self.__data.yMinEnabled

        def xScaleDiv(self):
            """
            :return: the scale division of the x axis
            """
            return self.__data.xScaleDiv

        def yScaleDiv(self):
            """
            :return: the scale division of the y axis
            """
            return self.__data.yScaleDiv

        def updateScaleDiv(self, xScaleDiv, yScaleDiv):
            """
            Update the grid to changes of the axes scale division

            :param qwt.scale_map.QwtScaleMap xMap: Scale division of the x-axis
            :param qwt.scale_map.QwtScaleMap yMap: Scale division of the y-axis

            .. seealso::

                :py:meth:`updateAxes()`
            """
            self.setXDiv(xScaleDiv)
            self.setYDiv(yScaleDiv)