/***************************************************************************
    File                 : ColorButton.cpp
    Project              : SciDAVis
    --------------------------------------------------------------------
    Copyright            : (C) 2006 by Ion Vasilief, Tilman Benkert
    Email (use @ for *)  : ion_vasilief*yahoo.fr, thzs*gmx.net
    Description          : A button used for color selection

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/
#include "ColorButton.h"

#include <QColorDialog>
#include <QPalette>
#include <QPushButton>
#include <QHBoxLayout>
#include <QFrame>

const QColor ColorButton::colors[] = {
    QColor(Qt::black),
    QColor(Qt::red),
    QColor(Qt::green),
    QColor(Qt::blue),
    QColor(Qt::cyan),
    QColor(Qt::magenta),
    QColor(Qt::yellow),
    QColor(Qt::darkYellow),
    QColor(Qt::darkBlue),
    QColor(Qt::darkMagenta),
    QColor(Qt::darkRed),
    QColor(Qt::darkGreen),
    QColor(Qt::darkCyan),
    QColor("#0000A0"),
    QColor("#FF8000"),
    QColor("#8000FF"),
    QColor("#FF0080"),
    QColor(Qt::white),
    QColor(Qt::lightGray),
    QColor(Qt::gray),
    QColor("#FFFF80"),
    QColor("#80FFFF"),
    QColor("#FF80FF"),
    QColor(Qt::darkGray),
    // additional colors from figure 6 in doi:10.1016/j.csda.2008.11.033
    QColor("#023fa5"),
    QColor("#4a6fe3"),
    QColor("#11c638"),
    QColor("#0fcfc0"),
    QColor("#8e063b"),
    QColor("#d33f6a"),
    QColor("#ef9708"),
    QColor("#f79cd4"),
    QColor("#7d87b9"),
    QColor("#8595e1"),
    QColor("#8dd593"),
    QColor("#9cded6"),
    QColor("#bb7784"),
    QColor("#e07b91"),
    QColor("#f0b98d"),
    QColor("#f6c4e1"),
    QColor("#bec1d4"),
    QColor("#b5bbe3"),
    QColor("#c6dec7"),
    QColor("#d5eae7"),
    QColor("#d6bcc0"),
    QColor("#e6afb9"),
    QColor("#ead3c6"),
    QColor("#f3e1eb"),
};

const unsigned int ColorButton::colors_count = sizeof(colors) / sizeof(colors[0]);

ColorButton::ColorButton(QWidget *parent) : QWidget(parent)
{
    init();
}

void ColorButton::init()
{
    // transpose colors in the 6x8 basic colour grid.
    constexpr int rows = 8, cols = 6;
    static_assert(rows * cols <= sizeof(colors) / sizeof(colors[0]), "");
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            QColorDialog::setStandardColor(j + cols * i, colors[i + rows * j].rgb());
        }
    }
    const int btn_size = 28;
    selectButton = new QPushButton(QPixmap(":/palette.xpm"), QString(), this);
    selectButton->setMinimumWidth(btn_size);
    selectButton->setMinimumHeight(btn_size);

    display = new QFrame(this);
    display->setLineWidth(2);
    display->setFrameStyle(QFrame::Panel | QFrame::Sunken);
    display->setMinimumHeight(btn_size);
    display->setMinimumWidth(2 * btn_size);
    display->setAutoFillBackground(true);
    setColor(QColor(Qt::white));

    QHBoxLayout *l = new QHBoxLayout(this);
    l->setMargin(0);
    l->addWidget(display);
    l->addWidget(selectButton);

    setMaximumWidth(3 * btn_size);
    setMaximumHeight(btn_size);

    connect(selectButton, SIGNAL(clicked()), this, SLOT(pickColor()));
}

void ColorButton::setColor(const QColor &c)
{
    QPalette pal;
    pal.setColor(QPalette::Window, c);
    display->setPalette(pal);
    emit changed(c);
}

QColor ColorButton::color() const
{
    return display->palette().color(QPalette::Window);
}

unsigned int ColorButton::colorIndex(const QColor &c)
{
    const QColor *ite = std::find(std::begin(colors), std::end(colors), c);
    if (ite != std::end(colors) && ite->isValid())
        return (ite - colors);
    else
        return c.rgba();
}

QColor ColorButton::color(unsigned int colorIndex)
{
    if (colorIndex < colors_count)
        return colors[colorIndex];
    else {
        QColor qc = QColor::fromRgba(colorIndex);
        if (qc.isValid())
            return qc;
        else
            return QColor(Qt::black); // default color is black.
    }
}

bool ColorButton::isValidColor(const QColor &c)
{
    const QColor *ite = std::find(std::begin(colors), std::end(colors), c);
    return (ite != std::end(colors) && ite->isValid());
}

QSize ColorButton::sizeHint() const
{
    return QSize(4 * btn_size, btn_size);
}

void ColorButton::pickColor()
{
    QColor c = QColorDialog::getColor(color(), this, "Select color",
                                      QColorDialog::DontUseNativeDialog
                                              | QColorDialog::ShowAlphaChannel);
    if (!c.isValid() || c == color())
        return;
    setColor(c);
}
