/*
 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
 *
 * This file is part of the KD Chart library.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#ifndef KCHARTMEASURE_H
#define KCHARTMEASURE_H

#include "KChartEnums.h"
#include "KChartGlobal.h"
#include <QDebug>
#include <QStack>
#include <Qt>

/** \file KChartMeasure.h
 *  \brief Declaring the class KChart::Measure.
 *
 *
 */

QT_BEGIN_NAMESPACE
class QObject;
class QPaintDevice;
QT_END_NAMESPACE

namespace KChart
{

/**
 * \class Measure KChartMeasure.h KChartMeasure
 * \brief Measure is used to specify relative and absolute sizes in KChart, e.g. font sizes.
 *
 */

class KCHART_EXPORT Measure
{
public:
    Measure();
    /*implicit*/ Measure(qreal value,
                         KChartEnums::MeasureCalculationMode mode = KChartEnums::MeasureCalculationModeAuto,
                         KChartEnums::MeasureOrientation orientation = KChartEnums::MeasureOrientationAuto);
    Measure(const Measure &);
    Measure &operator=(const Measure &);

    void setValue(qreal val)
    {
        mValue = val;
    }
    qreal value() const
    {
        return mValue;
    }

    void setCalculationMode(KChartEnums::MeasureCalculationMode mode)
    {
        mMode = mode;
    }
    KChartEnums::MeasureCalculationMode calculationMode() const
    {
        return mMode;
    }

    /**
     * The reference area must either be derived from AbstractArea
     * or from QWidget, so it can also be derived from AbstractAreaWidget.
     */
    void setRelativeMode(const QObject *area, KChartEnums::MeasureOrientation orientation)
    {
        mMode = KChartEnums::MeasureCalculationModeRelative;
        mArea = area;
        mOrientation = orientation;
    }

    /**
     * \brief This is a convenience method for specifying a value,
     *  implicitly setting the calculation mode to MeasureCalculationModeAbsolute.
     *
     * Calling setAbsoluteValue( value ) is the same as calling
\verbatim
    setValue( value );
    setCalculationMode( KChartEnums::MeasureCalculationModeAbsolute );
\endverbatim
     */
    void setAbsoluteValue(qreal val)
    {
        mMode = KChartEnums::MeasureCalculationModeAbsolute;
        mValue = val;
    }

    /**
     * The reference area must either be derived from AbstractArea
     * or from QWidget, so it can also be derived from AbstractAreaWidget.
     */
    void setReferenceArea(const QObject *area)
    {
        mArea = area;
    }
    /**
     * The returned reference area will be derived from AbstractArea
     * or QWidget or both.
     */
    const QObject *referenceArea() const
    {
        return mArea;
    }

    void setReferenceOrientation(KChartEnums::MeasureOrientation orientation)
    {
        mOrientation = orientation;
    }
    KChartEnums::MeasureOrientation referenceOrientation() const
    {
        return mOrientation;
    }

    /**
     * The reference area must either be derived from AbstractArea
     * or from QWidget, so it can also be derived from AbstractAreaWidget.
     */
    qreal calculatedValue(const QObject *autoArea, KChartEnums::MeasureOrientation autoOrientation) const;
    qreal calculatedValue(const QSizeF &autoSize, KChartEnums::MeasureOrientation autoOrientation) const;
    const QSizeF sizeOfArea(const QObject *area) const;

    bool operator==(const Measure &) const;
    bool operator!=(const Measure &other) const
    {
        return !operator==(other);
    }

private:
    qreal mValue;
    KChartEnums::MeasureCalculationMode mMode;
    const QObject *mArea;
    KChartEnums::MeasureOrientation mOrientation;
}; // End of class Measure

/**
 * Auxiliary class used by the KChart::Measure and KChart::Chart class.
 *
 * Normally there should be no need to call any of these methods yourself.
 *
 * They are used by KChart::Chart::paint( QPainter*, const QRect& )
 * to adjust all of the relative Measures according to the target
 * rectangle's size.
 *
 * Default factors are (1.0, 1.0)
 */
class GlobalMeasureScaling
{
public:
    static GlobalMeasureScaling *instance();

    GlobalMeasureScaling();
    virtual ~GlobalMeasureScaling();

public:
    /**
     * Set new factors to be used by all Measure objects from now on.
     * Previous values will be saved on a stack internally.
     */
    static void setFactors(qreal factorX, qreal factorY);

    /**
     * Restore factors to the values before the previous call to
     * setFactors. The current values are popped off a stack internally.
     */
    static void resetFactors();

    /**
     * Return the currently active factors.
     */
    static const QPair<qreal, qreal> currentFactors();

    /**
     * Set the paint device to use for calculating font metrics.
     */
    static void setPaintDevice(QPaintDevice *paintDevice);

    /**
     * Return the paint device to use for calculating font metrics.
     */
    static QPaintDevice *paintDevice();

private:
    QStack<QPair<qreal, qreal>> mFactors;
    QPaintDevice *m_paintDevice;
};

}

#if !defined(QT_NO_DEBUG_STREAM)
KCHART_EXPORT QDebug operator<<(QDebug, const KChart::Measure &);
#endif /* QT_NO_DEBUG_STREAM */

#endif // KCHARTMEASURE_H
