#pragma once

#include "volumeshop.h"

#include <qdrawutil.h>
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QString>
#include <QSlider>
#include <QLabel>
#include <QColor>
#include <QToolButton>
#include <QPixmap>
#include <QColorDialog>
#include <QPaintEvent>
#include <QPolygon>
#include <QGridLayout>
#include <QEvent>
#include <QShowEvent>
#include <QMouseEvent>
#include <QPalette>

#include <map>
#include <set>
#include <vector>

#include "Color.h"
#include "Compositor.h"

class QGradientWidgetAlphaButtonDialog : public QDialog
{
	Q_OBJECT

public:

	enum Alignment
	{
		ALIGNMENT_LEFT,
		ALIGNMENT_RIGHT,
		ALIGNMENT_TOP,
		ALIGNMENT_BOTTOM
	};

	QGradientWidgetAlphaButtonDialog(const Alignment & eAlignment, const float fAlpha, QWidget *pParent = 0) : QDialog(pParent,Qt::ToolTip | Qt::MSWindowsFixedSizeDialogHint), m_eAlignment(eAlignment), m_fAlpha(fAlpha)
	{
		setAttribute(Qt::WA_DeleteOnClose);
		QGridLayout *pLayout = new QGridLayout(this);	

		if (m_eAlignment == ALIGNMENT_TOP || m_eAlignment == ALIGNMENT_BOTTOM)
			m_pSlider = new QSlider(Qt::Horizontal,this);
		else
			m_pSlider = new QSlider(Qt::Vertical,this);

		m_pSlider->setMinimum(0);
		m_pSlider->setMaximum(1000);
		m_pSlider->setFocusProxy(this);
		pLayout->addWidget(m_pSlider,0,0);	

		connect(m_pSlider,SIGNAL(valueChanged (int)),SLOT(OnSliderValueChanged(int)));
		SetAlpha(fAlpha);
	};

	virtual ~QGradientWidgetAlphaButtonDialog()
	{
	};

	void SetAlpha(const float fAlpha)
	{
		m_fAlpha = fAlpha;

		const float fMinimum = float(m_pSlider->minimum());
		const float fMaximum = float(m_pSlider->maximum());

		if (m_pSlider->orientation() == Qt::Horizontal)
			m_pSlider->setValue(std::min(m_pSlider->maximum(),std::max(m_pSlider->minimum(),int((m_fAlpha) * (fMaximum - fMinimum) + fMinimum))));
		else
			m_pSlider->setValue(std::min(m_pSlider->maximum(),std::max(m_pSlider->minimum(),int((1.0f-m_fAlpha) * (fMaximum - fMinimum) + fMinimum))));

		emit valueChanged(m_fAlpha);
	};

	const float GetAlpha() const
	{
		return m_fAlpha;
	};

signals:

	void valueChanged(const float fAlpha);

protected:

	virtual void showEvent ( QShowEvent *e )
	{
		if (parentWidget())
		{
			QPoint poiPosition;
			
			if (m_eAlignment == ALIGNMENT_LEFT)
				poiPosition = QPoint(- frameGeometry().width(),(parentWidget()->height() - frameGeometry().height()) /2 );
			else if (m_eAlignment == ALIGNMENT_RIGHT)
				poiPosition = QPoint(parentWidget()->width(),(parentWidget()->height() - frameGeometry().height()) /2 );
			else if (m_eAlignment == ALIGNMENT_TOP)
				poiPosition = QPoint((parentWidget()->width() - frameGeometry().width()) /2,-frameGeometry().height());
			else
				poiPosition = QPoint((parentWidget()->width() - frameGeometry().width()) /2,parentWidget()->height());

			move(parentWidget()->mapToGlobal(poiPosition));
		}
	};

	virtual void leaveEvent  ( QEvent  *e )
	{
		QDialog::leaveEvent(e);
		accept();
	};

protected slots:

	void OnSliderValueChanged(int iValue)
	{
		const float fMinimum = float(m_pSlider->minimum());
		const float fMaximum = float(m_pSlider->maximum());

		if (m_pSlider->orientation() == Qt::Horizontal)
			m_fAlpha = std::min(1.0f,std::max(0.0f,(float(iValue) - fMinimum) / (fMaximum - fMinimum)));
		else
			m_fAlpha = 1.0f - std::min(1.0f,std::max(0.0f,(float(iValue) - fMinimum) / (fMaximum - fMinimum)));

		emit valueChanged(m_fAlpha);
	};

private:

	Alignment m_eAlignment;
	QSlider *m_pSlider;
	float m_fAlpha;
	QWidget *m_pActive;
};

class QGradientWidgetButton : public QWidget
{
	friend class QGradientWidget;

	Q_OBJECT

public:

	enum Arrow
	{
		ARROW_LEFT,
		ARROW_RIGHT,
		ARROW_UP,
		ARROW_DOWN
	};

	QGradientWidgetButton(const Arrow &eArrow, const float fPosition, QWidget *pParent = NULL, Qt::WFlags wf = 0) : QWidget(pParent,wf), m_eArrow(eArrow), m_fPosition(fPosition), m_bSelected(false)
	{
	};

	virtual ~QGradientWidgetButton()
	{
	};

	virtual QSize sizeHint () const 
	{
		if (m_eArrow == ARROW_LEFT || m_eArrow == ARROW_RIGHT)
			return QSize(24,12);
		
		return QSize(12,24);
	};

	void SetPosition(const float fPosition)
	{
		m_fPosition = fPosition;
		repaint();
	};

	const float GetPosition() const
	{
		return m_fPosition;
	};


	void SetSelected(const bool bSelected)
	{
		m_bSelected = bSelected;
		repaint();
	};

	const bool IsSelected() const
	{
		return m_bSelected;
	};

protected:

	Arrow GetArrow() const
	{
		return m_eArrow;
	};

	virtual void paintEvent ( QPaintEvent *e)
	{
		QPainter p(this);

		QRect recButton;
		QRect recArrow;
		QPolygon polArrow(3);

		if (m_eArrow == ARROW_UP)
		{
			recButton.setCoords(0,(height()-1)/3,width()-1,height()-1);
			recArrow.setCoords(0,0,width()-1,(height()-1)/3);
			polArrow.setPoint(0,recArrow.bottomLeft());
			polArrow.setPoint(1,QPoint((recArrow.right()+recArrow.left())/2,recArrow.top()));
			polArrow.setPoint(2,recArrow.bottomRight());
		}
		else if (m_eArrow == ARROW_DOWN)
		{
			recButton.setCoords(0,0,width()-1,2*(height()-1)/3);
			recArrow.setCoords(0,2*(height()-1)/3,width()-1,height()-1);
			polArrow.setPoint(0,recArrow.topLeft());
			polArrow.setPoint(1,QPoint((recArrow.right()+recArrow.left())/2,recArrow.bottom()));
			polArrow.setPoint(2,recArrow.topRight());
		}
		else if (m_eArrow == ARROW_LEFT)
		{
			recButton.setCoords((width()-1)/3,0,width()-1,height()-1);
			recArrow.setCoords(0,0,(width()-1)/3,height()-1);
			polArrow.setPoint(0,recArrow.topRight());
			polArrow.setPoint(1,QPoint(recArrow.left(),(recArrow.top()+recArrow.bottom())/2));
			polArrow.setPoint(2,recArrow.bottomRight());
		}
		else
		{
			recButton.setCoords(0,0,2*(width()-1)/3,height()-1);
			recArrow.setCoords(2*(width()-1)/3,0,width()-1,height()-1);
			polArrow.setPoint(0,recArrow.topLeft());
			polArrow.setPoint(1,QPoint(recArrow.right(),(recArrow.top()+recArrow.bottom())/2));
			polArrow.setPoint(2,recArrow.bottomLeft());
		}

		QPen penArrow(palette().text().color());
		QBrush bruArrow(m_bSelected ? palette().text() : palette().background());

		p.setPen(penArrow);
		p.setBrush(bruArrow);

		p.drawConvexPolygon(polArrow);

		QBrush bruButton(GetButtonColor());
		qDrawShadePanel(&p,recButton.x()+1,recButton.y()+1,recButton.width()-2,recButton.height()-2,palette(),false,2,&bruButton);
		qDrawPlainRect(&p,recButton,palette().buttonText().color());
		
		p.end();
	};

	virtual void mousePressEvent ( QMouseEvent * e )
	{
		if (e->button()== Qt::LeftButton)
			emit highlighted(!(e->modifiers() & Qt::ShiftModifier));
		else if (e->button() == Qt::RightButton)
			emit activated();
	};

	virtual void mouseReleaseEvent ( QMouseEvent * e )
	{
		emit released();
	};

	virtual const QColor GetButtonColor() const = 0;

signals:

	void highlighted(bool bExclusive);
	void activated();
	void released();
	void valueChanged();

private:

	Arrow m_eArrow;
	float m_fPosition;
	bool m_bSelected;
};


class QGradientWidgetColorButton : public QGradientWidgetButton
{
	Q_OBJECT

public:

	QGradientWidgetColorButton(const Arrow &eArrow, const float fPosition, QWidget *pParent = NULL, Qt::WFlags wf = 0) : QGradientWidgetButton(eArrow,fPosition,pParent,wf), m_colColor(Qt::black)
	{
	};

	virtual ~QGradientWidgetColorButton()
	{
	};

	void SetColor(const QColor &colColor)
	{
		m_colColor = colColor;
		repaint();
		emit valueChanged();
	};

	const QColor & GetColor() const
	{
		return m_colColor;
	};

protected:

	virtual const QColor GetButtonColor() const
	{
		return m_colColor;
	};

	virtual void mouseDoubleClickEvent ( QMouseEvent * e )
	{
		if (e->button() == Qt::LeftButton)
		{
			QColor colColor = QColorDialog::getColor (m_colColor,this);

			if (colColor.isValid())
				SetColor(colColor);
		}
	};

private:

	QColor m_colColor;
};

class QGradientWidgetAlphaButton : public QGradientWidgetButton
{
	Q_OBJECT

public:

	QGradientWidgetAlphaButton(const Arrow &eArrow, const float fPosition, QWidget *pParent = NULL, Qt::WFlags wf = 0) : QGradientWidgetButton(eArrow,fPosition,pParent,wf), m_fAlpha(0.0f)
	{
	};

	virtual ~QGradientWidgetAlphaButton()
	{
	};

	void SetAlpha(const float fAlpha)
	{
		m_fAlpha = fAlpha;
		repaint();
		emit valueChanged();
	};

	const float GetAlpha() const
	{
		return m_fAlpha;
	};

protected:

	virtual const QColor GetButtonColor() const
	{
		return QColor(int((1.0f-m_fAlpha)*255.0f),int((1.0f-m_fAlpha)*255.0f),int((1.0f-m_fAlpha)*255.0f));
	};

	virtual void mouseDoubleClickEvent ( QMouseEvent * e )
	{
		if (e->button() == Qt::LeftButton)
		{
			QGradientWidgetAlphaButtonDialog::Alignment eAlignment;

			if (GetArrow() == ARROW_LEFT)
				eAlignment = QGradientWidgetAlphaButtonDialog::ALIGNMENT_RIGHT;
			else if (GetArrow() == ARROW_RIGHT)
				eAlignment = QGradientWidgetAlphaButtonDialog::ALIGNMENT_LEFT;
			else if (GetArrow() == ARROW_UP)
				eAlignment = QGradientWidgetAlphaButtonDialog::ALIGNMENT_BOTTOM;
			else
				eAlignment = QGradientWidgetAlphaButtonDialog::ALIGNMENT_TOP;

			QGradientWidgetAlphaButtonDialog *pDialog = new QGradientWidgetAlphaButtonDialog(eAlignment,m_fAlpha,this);

			connect(pDialog,SIGNAL(valueChanged(const float)),SLOT(OnDialogValueChanged(const float)));
			pDialog->show();
		}
	};

protected slots:

	void OnDialogValueChanged(const float fAlpha)
	{
		SetAlpha(fAlpha);
	};

private:

	float m_fAlpha;
};

class QWidgetGradient
{
public:
	QWidgetGradient()
	{
	};

	~QWidgetGradient()
	{
	};

	void addAlpha(const float fPosition, const float fAlpha)
	{
		m_mapAlpha.insert(std::pair<float,float>(fPosition,fAlpha));
	};

	void addColor(const float fPosition, const QColor & colColor)
	{
		m_mapColor.insert(std::pair<float,QColor>(fPosition,colColor));
	};

	void removeAlpha(const float fPosition)
	{
		std::map<float,float>::iterator i = m_mapAlpha.find(fPosition);

		if (i != m_mapAlpha.end())
			m_mapAlpha.erase(i);
	};

	void removeColor(const float fPosition)
	{
		std::map<float,QColor>::iterator i = m_mapColor.find(fPosition);

		if (i != m_mapColor.end())
			m_mapColor.erase(i);
	};

	const bool HasAlpha(const float fPosition) const
	{
		std::map<float,float>::const_iterator i = m_mapAlpha.find(fPosition);

		if (i != m_mapAlpha.end())
			return true;

		return false;
	};

	const bool HasColor(const float fPosition) const
	{
		std::map<float,QColor>::const_iterator i = m_mapColor.find(fPosition);

		if (i != m_mapColor.end())
			return true;

		return false;
	};

	const std::pair<float,float> GetLowerAlpha(const float fPosition) const
	{
		if (m_mapAlpha.size()==1)
			return *m_mapAlpha.begin();

		std::map<float,float>::const_iterator i = m_mapAlpha.lower_bound(fPosition);

		if (i != m_mapAlpha.end())
		{
			if (i != m_mapAlpha.begin())
				i--;

			return *i;
		}
		else
		{
			if (m_mapAlpha.size() > 0)
				return *(m_mapAlpha.rbegin());
		}

		return std::pair<float,float>(0.0f,0.0f);
	};

	const std::pair<float,QColor> GetLowerColor(const float fPosition) const
	{
		if (m_mapColor.size()==1)
			return *m_mapColor.begin();

		std::map<float,QColor>::const_iterator i = m_mapColor.lower_bound(fPosition);

		if (i != m_mapColor.end())
		{
			if (i != m_mapColor.begin())
				i--;

			return *i;
		}
		else
		{
			if (m_mapColor.size() > 0)
				return *(m_mapColor.rbegin());
		}

		return std::pair<float,QColor>(0.0f,QColor(0,0,0));
	};

	const std::pair<float,float> GetUpperAlpha(const float fPosition) const
	{
		if (m_mapAlpha.size()==1)
			return *m_mapAlpha.begin();

		std::map<float,float>::const_iterator i = m_mapAlpha.lower_bound(fPosition);

		if (i != m_mapAlpha.end())
			return *i;
		else
		{
			if (m_mapAlpha.size() > 0)
				return *(m_mapAlpha.rbegin());
		}

		return std::pair<float,float>(1.0f,0.0f);
	};

	const std::pair<float,QColor> GetUpperColor(const float fPosition) const
	{
		if (m_mapColor.size()==1)
			return *m_mapColor.begin();

		std::map<float,QColor>::const_iterator i = m_mapColor.lower_bound(fPosition);

		if (i != m_mapColor.end())
			return *i;
		else
		{
			if (m_mapColor.size() > 0)
				return *(m_mapColor.rbegin());
		}

		return std::pair<float,QColor>(1.0f,QColor(0,0,0));
	};

	const std::map<float,float> & GetAlpha() const
	{
		return m_mapAlpha;
	};

	const std::map<float,QColor> & GetColor() const
	{
		return m_mapColor;
	};

	const std::map<float,QRgb> Get() const
	{
		std::map<float,QRgb> mapValues;

		mapValues[0.0f] = qRgba(0,0,0,0);
		mapValues[1.0f] = qRgba(0,0,0,0);

		for (std::map<float,float>::const_iterator i = m_mapAlpha.begin(); i!= m_mapAlpha.end(); i++)
			mapValues[i->first] = qRgba(0,0,0,0);

		for (std::map<float,QColor>::const_iterator i = m_mapColor.begin(); i!= m_mapColor.end(); i++)
			mapValues[i->first] = qRgba(0,0,0,0);

		for (std::map<float,QRgb>::iterator i = mapValues.begin(); i!= mapValues.end(); i++)
		{
			const float fPosition = i->first;

			const std::pair<float,float> paiLowerAlpha = GetLowerAlpha(fPosition);
			const std::pair<float,float> paiUpperAlpha = GetUpperAlpha(fPosition);

			const std::pair<float,QColor> paiLowerColor = GetLowerColor(fPosition);
			const std::pair<float,QColor> paiUpperColor = GetUpperColor(fPosition);

			const float fAlphaFactor = (paiUpperAlpha.first-paiLowerAlpha.first) > 0.0f ? (fPosition - paiLowerAlpha.first) / (paiUpperAlpha.first-paiLowerAlpha.first) : 0.0f;
			const float fColorFactor = (paiUpperColor.first-paiLowerColor.first) > 0.0f ? (fPosition - paiLowerColor.first) / (paiUpperColor.first-paiLowerColor.first) : 0.0f;

			const float fAlpha = 255.0f*(paiLowerAlpha.second + (paiUpperAlpha.second - paiLowerAlpha.second) * fAlphaFactor);
			const float fRed = float(paiLowerColor.second.red()) + float(paiUpperColor.second.red() - paiLowerColor.second.red()) * fColorFactor;
			const float fGreen = float(paiLowerColor.second.green()) + float(paiUpperColor.second.green() - paiLowerColor.second.green()) * fColorFactor;
			const float fBlue = float(paiLowerColor.second.blue()) + float(paiUpperColor.second.blue() - paiLowerColor.second.blue()) * fColorFactor;
			const QRgb rgbValue = qRgba(std::min(255,std::max(0,int(fRed))),std::min(255,std::max(0,int(fGreen))),std::min(255,std::max(0,int(fBlue))),std::min(255,std::max(0,int(fAlpha))));
			i->second = rgbValue;
		}

		return mapValues;		
	};

	const std::vector<QRgb> Get(const unsigned int uSize) const
	{
		std::vector<QRgb> vecValues;
		vecValues.resize(uSize);

		for (int i=0; i < int(uSize); i++)
		{
			float fPosition = float(i) / float(uSize-1);

			const std::pair<float,float> paiLowerAlpha = GetLowerAlpha(fPosition);
			const std::pair<float,float> paiUpperAlpha = GetUpperAlpha(fPosition);

			const std::pair<float,QColor> paiLowerColor = GetLowerColor(fPosition);
			const std::pair<float,QColor> paiUpperColor = GetUpperColor(fPosition);

			const float fAlphaFactor = (paiUpperAlpha.first-paiLowerAlpha.first) > 0.0f ? (fPosition - paiLowerAlpha.first) / (paiUpperAlpha.first-paiLowerAlpha.first) : 0.0f;
			const float fColorFactor = (paiUpperColor.first-paiLowerColor.first) > 0.0f ? (fPosition - paiLowerColor.first) / (paiUpperColor.first-paiLowerColor.first) : 0.0f;

			const float fAlpha = 255.0f*(paiLowerAlpha.second + (paiUpperAlpha.second - paiLowerAlpha.second) * fAlphaFactor);
			const float fRed = float(paiLowerColor.second.red()) + float(paiUpperColor.second.red() - paiLowerColor.second.red()) * fColorFactor;
			const float fGreen = float(paiLowerColor.second.green()) + float(paiUpperColor.second.green() - paiLowerColor.second.green()) * fColorFactor;
			const float fBlue = float(paiLowerColor.second.blue()) + float(paiUpperColor.second.blue() - paiLowerColor.second.blue()) * fColorFactor;
			const QRgb rgbValue = qRgba(std::min(255,std::max(0,int(fRed))),std::min(255,std::max(0,int(fGreen))),std::min(255,std::max(0,int(fBlue))),std::min(255,std::max(0,int(fAlpha))));
			vecValues[i] = rgbValue;
		}

		return vecValues;

	};

	void drawHorizontal(QPainter &p, const QRect &recRect) const
	{
		static const float vfBackground[2] = {255.0f,192.0f};
		QImage image(recRect.width(),recRect.height(),QImage::Format_ARGB32);

		for (int i=0; i < image.width(); i++)
		{
			float fPosition = float(i) / float(image.width()-1);

			const std::pair<float,float> paiLowerAlpha = GetLowerAlpha(fPosition);
			const std::pair<float,float> paiUpperAlpha = GetUpperAlpha(fPosition);

			const std::pair<float,QColor> paiLowerColor = GetLowerColor(fPosition);
			const std::pair<float,QColor> paiUpperColor = GetUpperColor(fPosition);

			const float fAlphaFactor = (paiUpperAlpha.first-paiLowerAlpha.first) > 0.0f ? (fPosition - paiLowerAlpha.first) / (paiUpperAlpha.first-paiLowerAlpha.first) : 0.0f;
			const float fColorFactor = (paiUpperColor.first-paiLowerColor.first) > 0.0f ? (fPosition - paiLowerColor.first) / (paiUpperColor.first-paiLowerColor.first) : 0.0f;

			const float fAlpha = std::min(1.0f,std::max(0.0f,(paiLowerAlpha.second + (paiUpperAlpha.second - paiLowerAlpha.second) * fAlphaFactor)));
			const float fRed = float(paiLowerColor.second.red()) + float(paiUpperColor.second.red() - paiLowerColor.second.red()) * fColorFactor;
			const float fGreen = float(paiLowerColor.second.green()) + float(paiUpperColor.second.green() - paiLowerColor.second.green()) * fColorFactor;
			const float fBlue = float(paiLowerColor.second.blue()) + float(paiUpperColor.second.blue() - paiLowerColor.second.blue()) * fColorFactor;

			const int iBx = (i / 5) % 2;

			const float fBackgroundFirst = vfBackground[iBx] * (1.0f - fAlpha);
			const float fRedFirst = fAlpha*fRed + fBackgroundFirst;
			const float fGreenFirst = fAlpha*fGreen + fBackgroundFirst;
			const float fBlueFirst = fAlpha*fBlue + fBackgroundFirst;

			const float fBackgroundSecond = vfBackground[1-iBx] * (1.0f - fAlpha);
			const float fRedSecond = fAlpha*fRed + fBackgroundSecond;
			const float fGreenSecond = fAlpha*fGreen + fBackgroundSecond;
			const float fBlueSecond = fAlpha*fBlue + fBackgroundSecond;

			const QRgb rgbPixelFirst = qRgb(std::min(255,std::max(0,int(fRedFirst))),std::min(255,std::max(0,int(fGreenFirst))),std::min(255,std::max(0,int(fBlueFirst))));
			const QRgb rgbPixelSecond = qRgb(std::min(255,std::max(0,int(fRedSecond))),std::min(255,std::max(0,int(fGreenSecond))),std::min(255,std::max(0,int(fBlueSecond))));

			const QRgb vrgbBackground[] = {rgbPixelFirst,rgbPixelSecond};

			for (int j=0;j<image.height();j++)
			{
				const int iBy = (j / 5) % 2;
				image.setPixel(i,j,vrgbBackground[iBy]);
			}
		}

		p.drawImage(recRect,image);
	};	

	void drawVertical(QPainter &p, const QRect &recRect) const
	{
		static const float vfBackground[2] = {255.0f,192.0f};
		QImage image(recRect.width(),recRect.height(),QImage::Format_ARGB32);

		for (int i=0; i < image.height(); i++)
		{
			float fPosition = float(image.height()-1-i) / float(image.height()-1);

			const std::pair<float,float> paiLowerAlpha = GetLowerAlpha(fPosition);
			const std::pair<float,float> paiUpperAlpha = GetUpperAlpha(fPosition);

			const std::pair<float,QColor> paiLowerColor = GetLowerColor(fPosition);
			const std::pair<float,QColor> paiUpperColor = GetUpperColor(fPosition);

			const float fAlphaFactor = (paiUpperAlpha.first-paiLowerAlpha.first) > 0.0f ? (fPosition - paiLowerAlpha.first) / (paiUpperAlpha.first-paiLowerAlpha.first) : 0.0f;
			const float fColorFactor = (paiUpperColor.first-paiLowerColor.first) > 0.0f ? (fPosition - paiLowerColor.first) / (paiUpperColor.first-paiLowerColor.first) : 0.0f;

			const float fAlpha = std::min(1.0f,std::max(0.0f,(paiLowerAlpha.second + (paiUpperAlpha.second - paiLowerAlpha.second) * fAlphaFactor)));
			const float fRed = float(paiLowerColor.second.red()) + float(paiUpperColor.second.red() - paiLowerColor.second.red()) * fColorFactor;
			const float fGreen = float(paiLowerColor.second.green()) + float(paiUpperColor.second.green() - paiLowerColor.second.green()) * fColorFactor;
			const float fBlue = float(paiLowerColor.second.blue()) + float(paiUpperColor.second.blue() - paiLowerColor.second.blue()) * fColorFactor;

			const int iBx = (i / 5) % 2;

			const float fBackgroundFirst = vfBackground[iBx] * (1.0f - fAlpha);
			const float fRedFirst = fAlpha*fRed + fBackgroundFirst;
			const float fGreenFirst = fAlpha*fGreen + fBackgroundFirst;
			const float fBlueFirst = fAlpha*fBlue + fBackgroundFirst;

			const float fBackgroundSecond = vfBackground[1-iBx] * (1.0f - fAlpha);
			const float fRedSecond = fAlpha*fRed + fBackgroundSecond;
			const float fGreenSecond = fAlpha*fGreen + fBackgroundSecond;
			const float fBlueSecond = fAlpha*fBlue + fBackgroundSecond;

			const QRgb rgbPixelFirst = qRgb(std::min(255,std::max(0,int(fRedFirst))),std::min(255,std::max(0,int(fGreenFirst))),std::min(255,std::max(0,int(fBlueFirst))));
			const QRgb rgbPixelSecond = qRgb(std::min(255,std::max(0,int(fRedSecond))),std::min(255,std::max(0,int(fGreenSecond))),std::min(255,std::max(0,int(fBlueSecond))));

			const QRgb vrgbBackground[] = {rgbPixelFirst,rgbPixelSecond};

			for (int j=0;j<image.width();j++)
			{
				const int iBy = (j / 5) % 2;
				image.setPixel(j,i,vrgbBackground[iBy]);
			}
		}

		p.drawImage(recRect,image);
	};

	void draw(QPainter &p, const QRect &recRect, const QWidgetGradient & graOther, const Compositor::Operator & opeOperator) const
	{
		static const float vfBackground[2][2] = {{255.0f,192.0f},{192.0f,255.0f}};

		const std::vector<QRgb> & vecHorizontal = Get(unsigned int(recRect.width()));
		const std::vector<QRgb> & vecVertical = graOther.Get(unsigned int(recRect.height()));
		
		QImage image(recRect.width(),recRect.height(),QImage::Format_ARGB32);

		for (int j=0;j<image.height();j++)
		{
			const int iBy = (j / 5) % 2;
			const Color colB(qRed(vecVertical[j]),qGreen(vecVertical[j]),qBlue(vecVertical[j]),qAlpha(vecVertical[j]));

			for (int i=0;i<image.width();i++)
			{
				const int iBx = (i / 5) % 2;

				const Color colA(qRed(vecHorizontal[i]),qGreen(vecHorizontal[i]),qBlue(vecHorizontal[i]),qAlpha(vecHorizontal[i]));
				const Color colResult = Compositor(opeOperator,colA,colB);

				const float fRed = float(colResult.GetRed());
				const float fGreen = float(colResult.GetGreen());
				const float fBlue = float(colResult.GetBlue());
				const float fAlpha = colResult.GetNormalizedAlpha();

				const float fBackground = vfBackground[iBy][iBx] * (1.0f - fAlpha);
				const float fRedPixel = fAlpha*fRed + fBackground;
				const float fGreenPixel = fAlpha*fGreen + fBackground;
				const float fBluePixel = fAlpha*fBlue + fBackground;

				const QRgb rgbValue = qRgba(std::min(255,std::max(0,int(fRedPixel))),std::min(255,std::max(0,int(fGreenPixel))),std::min(255,std::max(0,int(fBluePixel))),255);
				image.setPixel(i,image.height()-1-j,rgbValue);
			}
		}
/*
		for (int j=0; j < image.height(); j++)
		{
			const float fDy = float(image.width()) / float(image.height()) * float(j);
			const int iDy = int(fDy);
			const int iBy = (j / 5) % 2;

			const float fRedVertical = float(qRed(vecVertical[j]));
			const float fGreenVertical = float(qGreen(vecVertical[j]));
			const float fBlueVertical = float(qBlue(vecVertical[j]));
			const float fAlphaVertical = float(qAlpha(vecVertical[j]));


			for (int i=0; i <= iDy; i++)
			{
				const int iBx = (i / 5) % 2;
				const float fX = (iDy != 0) ? float(i) / float(iDy) : 0.0f;

				Color colA(qRed(vecHorizontal[i]),qGreen(vecHorizontal[i]),qBlue(vecHorizontal[i]),qAlpha(vecHorizontal[i]));
				Color colB(qRed(vecVertical[j]),qGreen(vecVertical[j]),qBlue(vecVertical[j]),qAlpha(vecVertical[j]));

				Color colResult = Compositor(Compositor::OPERATOR_PLUS,colA,colB);

				const float fRedMixture = float(colResult.GetRed());
				const float fGreenMixture = float(colResult.GetGreen());
				const float fBlueMixture = float(colResult.GetBlue());
				const float fAlphaMixture = float(colResult.GetAlpha());

				const float fRed = fRedMixture * fX + fRedVertical * (1.0f - fX);
				const float fGreen = fGreenMixture * fX + fGreenVertical * (1.0f - fX);
				const float fBlue = fBlueMixture * fX + fBlueVertical * (1.0f - fX);
				const float fAlpha = (fAlphaMixture * fX + fAlphaVertical * (1.0f - fX)) / 255.0f;

				const float fBackground = vfBackground[iBy][iBx] * (1.0f - fAlpha);
				const float fRedPixel = fAlpha*fRed + fBackground;
				const float fGreenPixel = fAlpha*fGreen + fBackground;
				const float fBluePixel = fAlpha*fBlue + fBackground;

				const QRgb rgbValue = qRgba(std::min(255,std::max(0,int(fRedPixel))),std::min(255,std::max(0,int(fGreenPixel))),std::min(255,std::max(0,int(fBluePixel))),255);
				image.setPixel(i,image.height()-1-j,rgbValue);
			}
		}

		for (int j=0; j < image.width(); j++)
		{
			const float fDx = float(image.height()) / float(image.width()) * float(j);
			const int iDx = int(fDx);
			const int iBx = (j / 5) % 2;

			const float fRedHorizontal = float(qRed(vecHorizontal[j]));
			const float fGreenHorizontal = float(qGreen(vecHorizontal[j]));
			const float fBlueHorizontal = float(qBlue(vecHorizontal[j]));
			const float fAlphaHorizontal = float(qAlpha(vecHorizontal[j]));

			for (int i=0; i <= iDx; i++)
			{
				const int iBy = (i / 5) % 2;
				const float fY = (iDx != 0) ? float(i) / float(iDx) : 0.0f;

				Color colB(qRed(vecHorizontal[j]),qGreen(vecHorizontal[j]),qBlue(vecHorizontal[j]),qAlpha(vecHorizontal[j]));
				Color colA(qRed(vecVertical[i]),qGreen(vecVertical[i]),qBlue(vecVertical[i]),qAlpha(vecVertical[i]));

				Color colResult = Compositor(Compositor::OPERATOR_PLUS,colB,colA);

				const float fRedMixture = float(colResult.GetRed());
				const float fGreenMixture = float(colResult.GetGreen());
				const float fBlueMixture = float(colResult.GetBlue());
				const float fAlphaMixture = float(colResult.GetAlpha());

				const float fRed = fRedMixture * fY + fRedHorizontal * (1.0f - fY);
				const float fGreen = fGreenMixture * fY + fGreenHorizontal * (1.0f - fY);
				const float fBlue = fBlueMixture * fY + fBlueHorizontal * (1.0f - fY);
				const float fAlpha = (fAlphaMixture * fY + fAlphaHorizontal * (1.0f - fY)) / 255.0f;

				const float fBackground = vfBackground[iBy][iBx] * (1.0f - fAlpha);
				const float fRedPixel = fAlpha*fRed + fBackground;
				const float fGreenPixel = fAlpha*fGreen + fBackground;
				const float fBluePixel = fAlpha*fBlue + fBackground;

				const QRgb rgbValue = qRgba(std::min(255,std::max(0,int(fRedPixel))),std::min(255,std::max(0,int(fGreenPixel))),std::min(255,std::max(0,int(fBluePixel))),255);
				image.setPixel(j,image.height()-1-i,rgbValue);

			}
		}
*/
		p.drawImage(recRect,image);

	};

	void clear()
	{
		m_mapAlpha.clear();
		m_mapColor.clear();
	};

private:	

	std::map<float,float> m_mapAlpha;
	std::map<float,QColor> m_mapColor;

};

class QGradientArea : public QWidget
{
	Q_OBJECT

public:
	
	QGradientArea (const QWidgetGradient & graHorizontal, const QWidgetGradient & graVertical, QWidget *pParent = NULL, Qt::WFlags wf = 0) : QWidget(pParent,wf), m_graHorizontal(graHorizontal), m_graVertical(graVertical)
	{
	};

	void SetOperator(const Compositor::Operator & opeOperator)
	{
		m_opeOperator = opeOperator;
		repaint();
	};

	const Compositor::Operator & GetOperator() const
	{
		return m_opeOperator;
	};

	const QWidgetGradient & GetHorizontal() const
	{
		return m_graHorizontal;
	};

	const QWidgetGradient & GetVertical() const
	{
		return m_graVertical;
	};

	virtual QSize sizeHint () const 
	{
		const int iMaximum = std::max(width(),height());
		return QSize(iMaximum,iMaximum);
	};

	virtual QSizePolicy sizePolicy() const
	{
		return QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::MinimumExpanding);
	};

protected:

	virtual void paintEvent (QPaintEvent *e)
	{
		const int iGradientBorder = 2;

		QPainter p(this);

		//QRect recBorder = QRect(6,6,width()-13,height()-13);
		QRect recBorder = QRect(6,6,width()-14,height()-14);
		//QRect recGradient = QRect(recBorder.left()+iGradientBorder,recBorder.top()+iGradientBorder,recBorder.width()-2*iGradientBorder,recBorder.height()-2*iGradientBorder);
		QRect recGradient = QRect(recBorder.left()+iGradientBorder,recBorder.top()+iGradientBorder,recBorder.width()-2*iGradientBorder+1,recBorder.height()-2*iGradientBorder+1);

		p.setPen(palette().buttonText().color());
		p.drawRect(recBorder);

		if (recGradient.isValid())
			m_graHorizontal.draw(p,recGradient,m_graVertical,m_opeOperator);

		p.end();
	};

private:

	Compositor::Operator m_opeOperator;
	const QWidgetGradient & m_graHorizontal;
	const QWidgetGradient & m_graVertical;
};


class QGradientWidget : public QWidget
{
	Q_OBJECT

public:

	enum Orientation
	{
		ORIENTATION_HORIZONTAL,
		ORIENTATION_VERTICAL
	};

	QGradientWidget (const Orientation &eOrientation, QWidget *pParent = NULL, Qt::WFlags wf = 0) : QWidget(pParent,wf), m_eOrientation(eOrientation), m_bMoving(false)
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
		{
			m_iButtonWidth = 13;
			m_iButtonHeight = 19;
		}
		else
		{
			m_iButtonWidth = 19;
			m_iButtonHeight = 13;
		}

		m_iGradientBorder = 2;
		m_iGradientHeight = 20;

		addAlphaButton(0.5,1.0f);

		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			addColorButton(0.5f,Qt::red);
		else
			addColorButton(0.5f,Qt::green);
	};

	virtual ~QGradientWidget()
	{
	};

	const Orientation & GetOrientation() const
	{
		return m_eOrientation;
	};

	virtual QSize sizeHint () const 
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return QSize(2*m_iButtonHeight+2*m_iGradientBorder+m_iGradientHeight,2*m_iButtonHeight+2*m_iGradientBorder+m_iGradientHeight);
		else
			return QSize(2*m_iButtonWidth+2*m_iGradientBorder+m_iGradientHeight,2*m_iButtonWidth+2*m_iGradientBorder+m_iGradientHeight);
	};

	virtual QSize minimumSizeHint () const 
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return QSize(2*m_iButtonHeight+2*m_iGradientBorder+m_iGradientHeight,2*m_iButtonHeight+2*m_iGradientBorder+m_iGradientHeight);
		else
			return QSize(2*m_iButtonWidth+2*m_iGradientBorder+m_iGradientHeight,2*m_iButtonWidth+2*m_iGradientBorder+m_iGradientHeight);
	};

	virtual QSizePolicy sizePolicy() const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return QSizePolicy(QSizePolicy::MinimumExpanding,QSizePolicy::Fixed);
		else
			return QSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding);
	};

	const QWidgetGradient & GetGradient() const
	{
		return m_graGradient;
	};

	void addColorButton(const float fPosition, const QColor & colColor)
	{
		QGradientWidgetColorButton *pButton;

		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			pButton = new QGradientWidgetColorButton(QGradientWidgetButton::ARROW_UP,fPosition,this);
		else
			pButton = new QGradientWidgetColorButton(QGradientWidgetButton::ARROW_RIGHT,fPosition,this);

		pButton->SetColor(colColor);
		pButton->setFixedSize(m_iButtonWidth,m_iButtonHeight);
		connect(pButton,SIGNAL(highlighted(bool)),SLOT(OnButtonSelected(bool)));
		connect(pButton,SIGNAL(activated()),SLOT(OnButtonActivated()));
		connect(pButton,SIGNAL(released()),SLOT(OnButtonReleased()));
		connect(pButton,SIGNAL(valueChanged()),SLOT(OnButtonValueChanged()));

		m_lisColorButtons.push_back(pButton);
		pButton->show();

		updateToGradient();
		repaint();
		emit valueChanged();
	};

	void addAlphaButton(const float fPosition, const float fAlpha)
	{
		QGradientWidgetAlphaButton *pButton;

		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			pButton = new QGradientWidgetAlphaButton(QGradientWidgetButton::ARROW_DOWN,fPosition,this);
		else 
			pButton = new QGradientWidgetAlphaButton(QGradientWidgetButton::ARROW_LEFT,fPosition,this);

		pButton->SetAlpha(fAlpha);
		pButton->setFixedSize(m_iButtonWidth,m_iButtonHeight);
		connect(pButton,SIGNAL(highlighted(bool)),SLOT(OnButtonSelected(bool)));
		connect(pButton,SIGNAL(activated()),SLOT(OnButtonActivated()));
		connect(pButton,SIGNAL(released()),SLOT(OnButtonReleased()));
		connect(pButton,SIGNAL(valueChanged()),SLOT(OnButtonValueChanged()));

		m_lisAlphaButtons.push_back(pButton);
		pButton->show();

		updateToGradient();
		repaint();
		emit valueChanged();
	};

	void removeAllAlphaButtons()
	{
		for (std::list<QGradientWidgetAlphaButton*>::iterator i=m_lisAlphaButtons.begin();i!=m_lisAlphaButtons.end();i++)
		{
			QGradientWidgetAlphaButton *pButton = *i;		
			i = m_lisAlphaButtons.erase(i);

			std::set<QGradientWidgetButton*>::iterator j = m_setSelected.find(pButton);

			if (j != m_setSelected.end())
				m_setSelected.erase(j);

			if (pButton)
				delete pButton;
		}

		updateToGradient();
		repaint();
		emit valueChanged();
	};

	void removeAllColorButtons()
	{
		for (std::list<QGradientWidgetColorButton*>::iterator i=m_lisColorButtons.begin();i!=m_lisColorButtons.end();i++)
		{
			QGradientWidgetColorButton *pButton = *i;		
			i = m_lisColorButtons.erase(i);

			std::set<QGradientWidgetButton*>::iterator j = m_setSelected.find(pButton);

			if (j != m_setSelected.end())
				m_setSelected.erase(j);

			if (pButton)
				delete pButton;
		}

		updateToGradient();
		repaint();
		emit valueChanged();
	};

signals:

	void valueChanged();

protected:

	virtual void mousePressEvent ( QMouseEvent * e )
	{
		if (e->button() == Qt::RightButton)
		{
			if (IsAlphaButtonPoint(e->pos()))
				addAlphaButton(GetPositionFromPoint(e->pos()),1.0f);
			else
				addColorButton(GetPositionFromPoint(e->pos()),Qt::black);
		}
	};

	virtual void mouseMoveEvent ( QMouseEvent * e )
	{
		if (m_bMoving)
		{
			const float fCurrentPosition = GetPositionFromPoint(e->pos());

			const float fChange = fCurrentPosition - m_fStartPosition;
			moveSelectedButtons(fChange);

			if (fCurrentPosition >= 0.0f && fCurrentPosition <= 1.0f)
				m_fStartPosition = fCurrentPosition;
		}
	};

	virtual void paintEvent (QPaintEvent *e)
	{
		for (std::list<QGradientWidgetColorButton*>::iterator i=m_lisColorButtons.begin();i!=m_lisColorButtons.end();i++)
		{
			QPoint poiPosition = GetPointFromColorPosition((*i)->GetPosition());
			QSize sizSize(m_iButtonWidth,m_iButtonHeight);

			QRect recRect(poiPosition.x() - sizSize.width()/2,poiPosition.y() - sizSize.height()/2,sizSize.width(),sizSize.height());
			(*i)->setGeometry(recRect);
		};

		for (std::list<QGradientWidgetAlphaButton*>::iterator i=m_lisAlphaButtons.begin();i!=m_lisAlphaButtons.end();i++)
		{
			QPoint poiPosition = GetPointFromAlphaPosition((*i)->GetPosition());
			QSize sizSize(m_iButtonWidth,m_iButtonHeight);

			QRect recRect(poiPosition.x() - sizSize.width()/2,poiPosition.y() - sizSize.height()/2,sizSize.width(),sizSize.height());
			(*i)->setGeometry(recRect);
		};


		QRect recBorder;
		QRect recGradient;

		if (m_eOrientation == ORIENTATION_HORIZONTAL)
		{
			//recBorder = QRect(m_iButtonWidth/2,m_iButtonHeight,width()-m_iButtonWidth,height()-2*m_iButtonHeight);
			recBorder = QRect(m_iButtonWidth/2,m_iButtonHeight,width()-m_iButtonWidth-1,height()-2*m_iButtonHeight-1);
			recGradient = QRect(m_iButtonWidth/2+m_iGradientBorder,m_iButtonHeight+m_iGradientBorder,width()-m_iButtonWidth-2*m_iGradientBorder,height()-2*m_iButtonHeight-2*m_iGradientBorder);
		}
		else
		{
			//recBorder = QRect(m_iButtonWidth,m_iButtonHeight/2,width()-2*m_iButtonWidth,height()-m_iButtonHeight);
			recBorder = QRect(m_iButtonWidth,m_iButtonHeight/2,width()-2*m_iButtonWidth-1,height()-m_iButtonHeight-1);
			recGradient = QRect(m_iButtonWidth+m_iGradientBorder,m_iButtonHeight/2+m_iGradientBorder,width()-2*m_iButtonWidth-2*m_iGradientBorder,height()-m_iButtonHeight-2*m_iGradientBorder);
		}

		QPainter p(this);
		p.setPen(palette().buttonText().color());
		p.drawRect(recBorder);

		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			m_graGradient.drawHorizontal(p,recGradient);
		else
			m_graGradient.drawVertical(p,recGradient);

		p.end();
	};

	void removeButton(QGradientWidgetButton *pButton)
	{
		m_lisColorButtons.remove((QGradientWidgetColorButton*) pButton);
		m_lisAlphaButtons.remove((QGradientWidgetAlphaButton*) pButton);

		std::set<QGradientWidgetButton*>::iterator l = m_setSelected.find(pButton);

		if (l != m_setSelected.end())
			m_setSelected.erase(l);

		delete pButton;

		updateToGradient();
		repaint();
		emit valueChanged();
	};


	void removeAlphaButton(const float fPosition)
	{
		for (std::list<QGradientWidgetAlphaButton*>::iterator i=m_lisAlphaButtons.begin();i!=m_lisAlphaButtons.end();i++)
		{
			if ((*i)->GetPosition() == fPosition)
			{
				QGradientWidgetAlphaButton *pButton = *i;		
				m_lisAlphaButtons.erase(i);

				std::set<QGradientWidgetButton*>::iterator j = m_setSelected.find(pButton);

				if (j != m_setSelected.end())
					m_setSelected.erase(j);

				if (pButton)
					delete pButton;

				updateToGradient();
				repaint();
				emit valueChanged();
			}
		}
	};

	void removeColorButton(const float fPosition)
	{
		for (std::list<QGradientWidgetColorButton*>::iterator i=m_lisColorButtons.begin();i!=m_lisColorButtons.end();i++)
		{
			if ((*i)->GetPosition() == fPosition)
			{
				QGradientWidgetColorButton *pButton = *i;		
				m_lisColorButtons.erase(i);

				std::set<QGradientWidgetButton*>::iterator j = m_setSelected.find(pButton);

				if (j != m_setSelected.end())
					m_setSelected.erase(j);

				if (pButton)
					delete pButton;

				updateToGradient();
				repaint();
				emit valueChanged();
			}
		}
	};

	void moveSelectedButtons(const float fChange)
	{
		float fMaximumPosition = 0.0f;
		float fMinimumPosition = 1.0f;

		for (std::set<QGradientWidgetButton*>::iterator i = m_setSelected.begin();i != m_setSelected.end();i++)
		{
			const float fPosition = (*i)->GetPosition();
			fMaximumPosition = std::max(fMaximumPosition,fPosition);
			fMinimumPosition = std::min(fMinimumPosition,fPosition);
		}

		float fCorrectedChange = fChange;

		if (fMinimumPosition+fChange < 0.0f)
			fCorrectedChange = -fMinimumPosition;

		if (fMaximumPosition+fChange > 1.0f)
			fCorrectedChange = 1.0f - fMaximumPosition;

		for (std::set<QGradientWidgetButton*>::iterator i = m_setSelected.begin();i != m_setSelected.end();i++)
			(*i)->SetPosition((*i)->GetPosition()+fCorrectedChange);

		updateToGradient();
		repaint();
		emit valueChanged();
	};

	const QPoint GetPointFromAlphaPosition(const float fPosition) const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return QPoint(m_iButtonWidth/2+m_iGradientBorder+int(float(width()-1-m_iButtonWidth-2*m_iGradientBorder)*fPosition),m_iButtonHeight/2);
		else
			return QPoint(width()-m_iButtonWidth/2 - m_iButtonWidth%2,height()-2-(m_iButtonHeight/2+m_iGradientBorder+int(float(height()-1-m_iButtonHeight-2*m_iGradientBorder)*fPosition)));
	};

	const QPoint GetPointFromColorPosition(const float fPosition) const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return QPoint(m_iButtonWidth/2+m_iGradientBorder+int(float(width()-1-m_iButtonWidth-2*m_iGradientBorder)*fPosition),height()-m_iButtonHeight/2-m_iButtonHeight%2);
		else
			return QPoint(m_iButtonWidth/2,height()-2-(m_iButtonHeight/2+m_iGradientBorder+int(float(height()-1-m_iButtonHeight-2*m_iGradientBorder)*fPosition)));
	};

	const float GetPositionFromPoint(const QPoint & poiPoint) const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return float(poiPoint.x()-int(m_iButtonWidth/2)-m_iGradientBorder) / float(width()-1-m_iButtonWidth-2*m_iGradientBorder);
		else
			return float((height()-2-poiPoint.y())-int(m_iButtonHeight/2)-m_iGradientBorder) / float(height()-m_iButtonHeight-2*m_iGradientBorder);
	};

	const bool IsAlphaButtonPoint(const QPoint & poiPoint) const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return (poiPoint.y() >= 0 && poiPoint.y() < m_iButtonHeight);
		else
			return (poiPoint.x() >= width()-m_iButtonWidth-1 && poiPoint.x() < width());
	};

	const bool IsColorButtonPoint(const QPoint & poiPoint) const
	{
		if (m_eOrientation == ORIENTATION_HORIZONTAL)
			return (poiPoint.y() >= height()-m_iButtonHeight-1 && poiPoint.y() < height());
		else
			return (poiPoint.x() >= 0 && poiPoint.x() < m_iButtonWidth);
	};

	void updateToGradient()
	{
		m_graGradient.clear();

		for (std::list<QGradientWidgetColorButton*>::const_iterator i=m_lisColorButtons.begin();i!=m_lisColorButtons.end();i++)
			m_graGradient.addColor((*i)->GetPosition(),(*i)->GetColor());

		for (std::list<QGradientWidgetAlphaButton*>::const_iterator i=m_lisAlphaButtons.begin();i!=m_lisAlphaButtons.end();i++)
			m_graGradient.addAlpha((*i)->GetPosition(),(*i)->GetAlpha());
	};

protected slots:

	void OnButtonSelected(bool bExclusive)
	{
		QGradientWidgetButton *pButton = (QGradientWidgetButton*)sender();

		if (bExclusive)
		{
			m_setSelected.clear();
			m_setSelected.insert(pButton);
		}
		else
		{
			std::set<QGradientWidgetButton*>::iterator i = m_setSelected.find((QGradientWidgetButton*)sender());

			if (i == m_setSelected.end())
				m_setSelected.insert(pButton);
			else
				m_setSelected.erase(i);
		}
		
		for (std::list<QGradientWidgetColorButton*>::iterator i=m_lisColorButtons.begin();i!=m_lisColorButtons.end();i++)
			(*i)->SetSelected(m_setSelected.find(*i) != m_setSelected.end());

		for (std::list<QGradientWidgetAlphaButton*>::iterator i=m_lisAlphaButtons.begin();i!=m_lisAlphaButtons.end();i++)
			(*i)->SetSelected(m_setSelected.find(*i) != m_setSelected.end());

		m_bMoving = true;
		m_fStartPosition = pButton->GetPosition();
	};

	void OnButtonActivated()
	{
		removeButton((QGradientWidgetButton*)sender());
	};

	void OnButtonReleased()
	{
		m_bMoving = false;
	};

	void OnButtonValueChanged()
	{
		updateToGradient();
		repaint();
		emit valueChanged();
	};

private:

	int m_iButtonWidth;
	int m_iButtonHeight;
	int m_iGradientHeight;
	int m_iGradientBorder;

	Orientation m_eOrientation;
	QWidgetGradient m_graGradient;
	bool m_bMoving;

	std::list<QGradientWidgetColorButton*> m_lisColorButtons;
	std::list<QGradientWidgetAlphaButton*> m_lisAlphaButtons;
	std::set<QGradientWidgetButton*> m_setSelected;

	float m_fStartPosition;
};