/*
  quickdecorationsdrawer.h

  This file is part of GammaRay, the Qt application inspection and manipulation tool.

  SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
  Author: Filipe Azevedo <filipe.azevedo@kdab.com>

  SPDX-License-Identifier: GPL-2.0-or-later

  Contact KDAB at <info@kdab.com> for commercial licensing options.
*/

#ifndef GAMMARAY_QUICKINSPECTOR_QUICKDECORATIONSDRAWER_H
#define GAMMARAY_QUICKINSPECTOR_QUICKDECORATIONSDRAWER_H

#include <QPen>

#include "quickitemgeometry.h"

namespace GammaRay {

struct QuickDecorationsSettings
{
    QuickDecorationsSettings()
        : boundingRectColor(QColor(232, 87, 82, 170))
        , boundingRectBrush(QBrush(QColor(232, 87, 82, 95)))
        , geometryRectColor(QColor(Qt::gray))
        , geometryRectBrush(QBrush(QColor(Qt::gray), Qt::BDiagPattern))
        , childrenRectColor(QColor(0, 99, 193, 170))
        , childrenRectBrush(QBrush(QColor(0, 99, 193, 95)))
        , transformOriginColor(QColor(156, 15, 86, 170))
        , coordinatesColor(QColor(136, 136, 136))
        , marginsColor(QColor(139, 179, 0))
        , paddingColor(QColor(Qt::darkBlue))
        , gridOffset(QPointF(0, 0))
        , gridCellSize(QSizeF(0, 0))
        , gridColor(QColor(Qt::red))
        , componentsTraces(false)
        , gridEnabled(false)
    {
    }

    bool operator==(const QuickDecorationsSettings &other) const
    {
        return boundingRectColor == other.boundingRectColor && boundingRectBrush == other.boundingRectBrush && geometryRectColor == other.geometryRectColor && geometryRectBrush == other.geometryRectBrush && childrenRectColor == other.childrenRectColor && childrenRectBrush == other.childrenRectBrush && transformOriginColor == other.transformOriginColor && coordinatesColor == other.coordinatesColor && marginsColor == other.marginsColor && paddingColor == other.paddingColor && gridOffset == other.gridOffset && gridCellSize == other.gridCellSize && gridColor == other.gridColor && componentsTraces == other.componentsTraces && gridEnabled == other.gridEnabled;
    }

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

    QColor boundingRectColor;
    QBrush boundingRectBrush;
    QColor geometryRectColor;
    QBrush geometryRectBrush;
    QColor childrenRectColor;
    QBrush childrenRectBrush;
    QColor transformOriginColor;
    QColor coordinatesColor;
    QColor marginsColor;
    QColor paddingColor;
    QPointF gridOffset;
    QSizeF gridCellSize;
    QColor gridColor;
    bool componentsTraces;
    bool gridEnabled;
};

QDataStream &operator<<(QDataStream &stream, const GammaRay::QuickDecorationsSettings &settings);
QDataStream &operator>>(QDataStream &stream, GammaRay::QuickDecorationsSettings &settings);

struct QuickDecorationsBaseRenderInfo
{
    QuickDecorationsBaseRenderInfo(const QuickDecorationsSettings &settings = QuickDecorationsSettings(),
                                   const QRectF &viewRect = QRectF(),
                                   qreal zoom = 1.0)
        : settings(settings)
        , viewRect(viewRect)
        , zoom(zoom)
    {
    }

    const QuickDecorationsSettings settings;
    const QRectF viewRect;
    const qreal zoom;
};

struct QuickDecorationsRenderInfo : QuickDecorationsBaseRenderInfo
{
    QuickDecorationsRenderInfo(const QuickDecorationsSettings &settings = QuickDecorationsSettings(),
                               const QuickItemGeometry &itemGeometry = QuickItemGeometry(),
                               const QRectF &viewRect = QRectF(),
                               qreal zoom = 1.0)
        : QuickDecorationsBaseRenderInfo(settings, viewRect, zoom)
        , itemGeometry(itemGeometry)
    {
    }

    const QuickItemGeometry itemGeometry;
};

struct QuickDecorationsTracesInfo : QuickDecorationsBaseRenderInfo
{
    QuickDecorationsTracesInfo(const QuickDecorationsSettings &settings = QuickDecorationsSettings(),
                               const QVector<QuickItemGeometry> &itemsGeometry = QVector<QuickItemGeometry>(),
                               const QRectF &viewRect = QRectF(),
                               qreal zoom = 1.0)
        : QuickDecorationsBaseRenderInfo(settings, viewRect, zoom)
        , itemsGeometry(itemsGeometry)
    {
    }

    const QVector<QuickItemGeometry> itemsGeometry;
};

class QuickDecorationsDrawer
{
public:
    enum Type
    {
        Decorations,
        Traces
    };

    QuickDecorationsDrawer(QuickDecorationsDrawer::Type type, QPainter &painter,
                           const QuickDecorationsBaseRenderInfo &renderInfo);

    void render();

private:
    struct DrawTextInfo
    {
        DrawTextInfo(const QPen &pen = QPen(), const QRectF &rect = QRectF(),
                     const QString &label = QString(),
                     int align = Qt::AlignCenter | Qt::TextDontClip)
            : pen(pen)
            , rect(rect)
            , label(label)
            , align(align)
        {
        }

        QPen pen;
        QRectF rect;
        QString label;
        int align;
    };

    typedef QVector<DrawTextInfo> DrawTextInfoList;

    QuickItemGeometry itemGeometry() const;
    QVector<QuickItemGeometry> itemsGeometry() const;

    void drawDecorations();
    void drawTraces();
    void drawGrid();
    void drawArrow(const QPointF &first, const QPointF &second);
    void drawAnchor(const QuickItemGeometry &itemGeometry, Qt::Orientation orientation,
                    qreal ownAnchorLine, qreal offset);
    void drawVerticalAnchor(const QuickItemGeometry &itemGeometry, qreal ownAnchorLine,
                            qreal offset);
    void drawHorizontalAnchor(const QuickItemGeometry &itemGeometry, qreal ownAnchorLine,
                              qreal offset);
    DrawTextInfo drawAnchorLabel(const QuickItemGeometry &itemGeometry, Qt::Orientation orientation,
                                 qreal ownAnchorLine, qreal offset, const QString &label,
                                 Qt::Alignment align);
    DrawTextInfo drawHorizontalAnchorLabel(const QuickItemGeometry &itemGeometry, qreal ownAnchorLine,
                                           qreal offset, const QString &label, Qt::Alignment align);
    DrawTextInfo drawVerticalAnchorLabel(const QuickItemGeometry &itemGeometry, qreal ownAnchorLine,
                                         qreal offset, const QString &label, Qt::Alignment align);

    const QuickDecorationsDrawer::Type m_type;
    const QuickDecorationsBaseRenderInfo *const m_renderInfo;
    QPainter *const m_painter;
};
}

Q_DECLARE_METATYPE(GammaRay::QuickDecorationsSettings)

#endif
