#include <qlayout.h>
#include <qvalidator.h>
#include <qspinbox.h>
#include <qslider.h>
#include <qlineedit.h>
#include <qlabel.h>
#include <qcolor.h>

#include "CColorWidget.h"


CColorWidget::CColorWidget( QWidget *parent, const char *name)
  : QWidget(parent, name)
{
  m_layout = new QGridLayout(this, 4, 4, 11, 6, name);
  m_doublevalidator = new QDoubleValidator(0.0, 1.0, 3, this);

  for (int i = 0; i < 4; ++i)
  {
    m_sliders[i]   = new QSlider(0, 255, 1, 0, Qt::Horizontal, this);
    m_spinboxes[i] = new QSpinBox(0, 255, 1, this);
    m_floatedit[i] = new QLineEdit("0", this);
    m_floatedit[i]->setValidator(m_doublevalidator);

    m_layout->addWidget(m_sliders[i]  , i, 0);
    m_layout->addWidget(m_spinboxes[i], i, 1);
    m_layout->addWidget(m_floatedit[i], i, 2);
  }

  m_labels[0] = new QLabel("Red"  , this);
  m_layout->addWidget(m_labels[0], 0, 3);
  m_labels[1] = new QLabel("Green", this);
  m_layout->addWidget(m_labels[1], 1, 3);
  m_labels[2] = new QLabel("Blue" , this);
  m_layout->addWidget(m_labels[2], 2, 3);
  m_labels[3] = new QLabel("Alpha", this);
  m_layout->addWidget(m_labels[3], 3, 3);

  connect( m_sliders[0] , SIGNAL(valueChanged(int)),
           this,          SLOT(UpdateLine0())       );
  connect( m_sliders[1] , SIGNAL(valueChanged(int)),
           this,          SLOT(UpdateLine1())       );
  connect( m_sliders[2] , SIGNAL(valueChanged(int)),
           this,          SLOT(UpdateLine2())       );
  connect( m_sliders[3] , SIGNAL(valueChanged(int)),
           this,          SLOT(UpdateLine3())       );

  connect( m_spinboxes[0] , SIGNAL(valueChanged(int)),
           this,            SLOT(UpdateLine0())       );
  connect( m_spinboxes[1] , SIGNAL(valueChanged(int)),
           this,            SLOT(UpdateLine1())       );
  connect( m_spinboxes[2] , SIGNAL(valueChanged(int)),
           this,            SLOT(UpdateLine2())       );
  connect( m_spinboxes[3] , SIGNAL(valueChanged(int)),
           this,            SLOT(UpdateLine3())       );

  connect( m_floatedit[0] , SIGNAL(textChanged(const QString &)),
           this,            SLOT(UpdateLine0())                  );
  connect( m_floatedit[1] , SIGNAL(textChanged(const QString &)),
           this,            SLOT(UpdateLine1())                  );
  connect( m_floatedit[2] , SIGNAL(textChanged(const QString &)),
           this,            SLOT(UpdateLine2())                  );
  connect( m_floatedit[3] , SIGNAL(textChanged(const QString &)),
           this,            SLOT(UpdateLine3())                  );

  for (int a = 0; a < 4; ++a)
    {
      m_ValueSpinbox[a] = 0;
      m_ValueSlider[a]  = 0;
      m_ValueFloat[a]   = "0";
    }

  adjustSize();
  setMaximumSize(size());
  setMinimumSize(size());
}


CColorWidget::~CColorWidget()
{
  for (int i = 0; i < 4; ++i)
  {
    delete m_labels[i];
    delete m_floatedit[i];
    delete m_spinboxes[i];
    delete m_sliders[i];
  }

  delete m_doublevalidator;
  delete m_layout;
}



QColor CColorWidget::getQtColor() const
{
  return (QColor(m_ValueSlider[0],
                 m_ValueSlider[1],
                 m_ValueSlider[2]) );
}


void CColorWidget::getFloatColor(float color[4]) const
{
  for (int i = 0; i < 4; ++i)
    color[i] = QString(m_ValueFloat[i]).toFloat();
}


void CColorWidget::setColor(const float color[4])
{
  for (int i = 0; i < 4; ++i)
    {
      m_spinboxes[i]->setValue((int) (color[i] * 255));
      m_ValueSpinbox[i] = m_spinboxes[i]->value();

      m_sliders[i]->setValue((int) (color[i] * 255));
      m_ValueSlider[i] = m_sliders[i]->value();

      m_floatedit[i]->setText(QString::number(color[i]));
      m_ValueFloat[i] = m_floatedit[i]->text();
    }
}


#define UPDATELINEINT(index)                                                \
void CColorWidget::UpdateLine##index ()                                     \
{                                                                           \
  if (m_ValueSpinbox[index] != m_spinboxes[index]->value())                 \
    {                                                                       \
      m_ValueSpinbox[index] = m_spinboxes[index]->value();                  \
                                                                            \
      m_ValueSlider[index]  = m_spinboxes[index]->value();                  \
      m_sliders[index]->setValue(m_spinboxes[index]->value());              \
                                                                            \
      m_ValueFloat[index]                                                   \
        = QString::number((float) m_spinboxes[index]->value()/255.0f);      \
      m_floatedit[index]->setText(m_ValueFloat[index]);                     \
    }                                                                       \
  else if (m_ValueSlider[index] != m_sliders[index]->value())               \
    {                                                                       \
      m_ValueSlider[index]  = m_sliders[index]->value();                    \
                                                                            \
      m_ValueSpinbox[index] = m_sliders[index]->value();                    \
      m_spinboxes[index]->setValue(m_sliders[index]->value());              \
                                                                            \
      m_ValueFloat[index]                                                   \
        = QString::number((float) m_sliders[index]->value() / 255.0f);      \
      m_floatedit[index]->setText(m_ValueFloat[index]);                     \
    }                                                                       \
  else if (m_ValueFloat[index] != m_floatedit[index]->text())               \
    {                                                                       \
      m_ValueFloat[index] = m_floatedit[index]->text();                     \
                                                                            \
      m_ValueSpinbox[index] = (int) (m_ValueFloat[index].toFloat()*255.0f); \
      m_spinboxes[index]->setValue(m_ValueSpinbox[index]);                  \
                                                                            \
      m_ValueSlider[index]  = m_spinboxes[index]->value();                  \
      m_sliders[index]->setValue(m_spinboxes[index]->value());              \
    }                                                                       \
                                                                            \
  emit Changed();                                                           \
}

UPDATELINEINT(0)
UPDATELINEINT(1)
UPDATELINEINT(2)
UPDATELINEINT(3)
