/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
/***************************************************************************
                          gradienteditor  -  description
                             -------------------
    begin                : Mit Mai 26 2004
    copyright            : (C) 2004 by Franz Schmid
    email                : Franz.Schmid@altmuehlnet.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "gradienteditor.h"
#include "gradienteditor.moc"
#include <qpainter.h>
#include <qpixmap.h>
#include <qcursor.h>
#include "scpainter.h"
#include "fpoint.h"
extern QPixmap loadIcon(QString nam);

GradientPreview::GradientPreview(QWidget *pa) : QLabel(pa)
{
	setFrameShape( QFrame::Panel );
	setFrameShadow( QFrame::Sunken );
	setLineWidth( 2 );
	setEraseColor(QColor(255,255,255));
	setMinimumSize(QSize(200, 80));
	setMaximumSize(QSize(3000, 80));
	setMouseTracking(true);
	Mpressed = false;
	outside = true;
	onlyselect = true;
	fill_gradient = VGradient(VGradient::linear);
	fill_gradient.clearStops();

	QColor color;
	color = QColor(255,255,255);
	fill_gradient.addStop( color, 0.0, 0.5, 1.0 );
	color = QColor(0,0,0);
	fill_gradient.addStop( color, 1.0, 0.5, 1.0 );

	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	StopM.clear();
	ActStop = 0;
	for (uint a = 0; a < fill_gradient.Stops(); ++a)
	{
		int center = qRound(cstops.at(a)->rampPoint * (width()-20))+10;
		StopM.append(center);
	}
} 

void GradientPreview::paintEvent(QPaintEvent *e)
{
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	StopM.clear();
	for (uint a = 0; a < fill_gradient.Stops(); ++a)
	{
		int center = qRound(cstops.at(a)->rampPoint * (width()-20))+10;
		StopM.append(center);
	}
	QPixmap pixm(width()-20, 37);
	ScPainter *p = new ScPainter(&pixm, width()-20, 37);
	p->setPen(black);
	p->setLineWidth(1);
	p->setFillMode(2);
	p->fill_gradient = fill_gradient;
	p->setGradient(VGradient::linear, FPoint(0,20), FPoint(width()-20,20));
	p->drawRect(0, 0, width()-20, 37);
	p->end();
	delete p;
	QPainter pw;
	pw.begin(this);
	pw.drawPixmap(10, 5, pixm);
	for (uint a = 0; a < fill_gradient.Stops(); ++a)
	{
		int center = qRound(cstops.at(a)->rampPoint * (width()-20))+10;
		pw.setPen(QPen(black, 1, SolidLine, FlatCap, MiterJoin));
		if (StopM[QMAX(ActStop,0)] == center)
			pw.setBrush(red);
		else
			pw.setBrush(blue);
		QPointArray cr;
		cr.setPoints(3, qRound(center), 43, qRound(center-4), 56, qRound(center+4), 56);
		pw.drawPolygon(cr);
	}
	pw.end();
	QLabel::paintEvent(e);
}

void GradientPreview::mousePressEvent(QMouseEvent *m)
{
	QRect fpo;
	Mpressed = true;
	ActStop = -1;
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
	{
		fpo = QRect(static_cast<int>(StopM[yg])-4, 43, 8, 13);
		if (fpo.contains(m->pos()))
		{
			ActStop = yg;
			emit selectedColor(cstops.at(ActStop)->name, cstops.at(ActStop)->shade);
			emit currTrans(cstops.at(ActStop)->opacity);
			emit currStep(cstops.at(ActStop)->rampPoint);
			repaint();
			onlyselect = true;
			return;
		}
	}
}

void GradientPreview::mouseReleaseEvent(QMouseEvent *m)
{
	QRect fpo;
	if ((Mpressed) && (ActStop != 0) && (ActStop != static_cast<int>(StopM.count()-1)) && (ActStop != -1) && (outside || m->y() > 60))
	{
		onlyselect = false;
		fill_gradient.removeStop(ActStop);
		ActStop = 0;
		repaint();
		QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
		emit selectedColor(cstops.at(ActStop)->name, cstops.at(ActStop)->shade);
		emit currTrans(cstops.at(ActStop)->opacity);
		emit currStep(cstops.at(ActStop)->rampPoint);
	}
	if ((m->y() < 60) && (m->y() > 43) && (m->x() > 0) && (m->x() < width()) && (ActStop == -1))
	{
		QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
		double newStop = static_cast<double>((m->x() - 10)) / (static_cast<double>(width())-20);
		fill_gradient.addStop(cstops.at(0)->color, newStop, 0.5, 1.0, cstops.at(0)->name, cstops.at(0)->shade);
		repaint();
		onlyselect = false;
		cstops = fill_gradient.colorStops();
		for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
		{
			fpo = QRect(static_cast<int>(StopM[yg])-4, 43, 8, 13);
			if (fpo.contains(m->pos()))
			{
				ActStop = yg;
				emit selectedColor(cstops.at(ActStop)->name, cstops.at(ActStop)->shade);
				emit currTrans(cstops.at(ActStop)->opacity);
				emit currStep(cstops.at(ActStop)->rampPoint);
				repaint();
				break;
			}
		}
	}
	Mpressed = false;
	if (!onlyselect)
		emit gradientChanged();
}

void GradientPreview::mouseMoveEvent(QMouseEvent *m)
{
	QRect fpo;
	qApp->setOverrideCursor(QCursor(ArrowCursor), true);
	if ((!Mpressed) && (m->y() < 60) && (m->y() > 43) && (m->x() > 9) && (m->x() < width()-9))
	{
		qApp->setOverrideCursor(QCursor(loadIcon("AddPoint.png"), 1, 1), true);
		for (int yg = 0; yg < static_cast<int>(StopM.count()); ++yg)
		{
			fpo = QRect(static_cast<int>(StopM[yg])-4, 43, 8, 13);
			if (fpo.contains(m->pos()))
			{
				qApp->setOverrideCursor(QCursor(SizeHorCursor), true);
				return;
			}
		}
	}
	if ((Mpressed) && (m->y() < 60) && (m->y() > 43) && (m->x() > 9) && (m->x() < width()-9) && (ActStop != -1))
	{
		qApp->setOverrideCursor(QCursor(SizeHorCursor), true);
		double newStop = static_cast<double>((m->x() - 10)) / (static_cast<double>(width())-20);
		if (ActStop > 1)
		{
			if (StopM[ActStop-1]+2 >= m->x())
				return;
		}
		if (ActStop < static_cast<int>(StopM.count()-2))
		{
			if (StopM[ActStop+1]-2 < m->x())
				return;
		}
		StopM[ActStop] = m->x();
		QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
		cstops.at(ActStop)->rampPoint = newStop;
		emit currStep(cstops.at(ActStop)->rampPoint);
		cstops.sort();
		onlyselect = false;
		repaint();
	}
	if ((Mpressed) && (outside || m->y() > 60) && (ActStop != 0) && (ActStop != static_cast<int>(StopM.count()-1)) && (ActStop != -1))
		qApp->setOverrideCursor(QCursor(loadIcon("DelPoint.png"), 1, 1), true);
}

void GradientPreview::leaveEvent(QEvent*)
{
	if ((Mpressed) && (ActStop != 0) && (ActStop != static_cast<int>(StopM.count()-1)) && (ActStop != -1))
		qApp->setOverrideCursor(QCursor(loadIcon("DelPoint.png"), 1, 1), true);
	else
		qApp->setOverrideCursor(QCursor(ArrowCursor), true);
	outside = true;
}

void GradientPreview::enterEvent(QEvent*)
{
	outside = false;
}

void GradientPreview::updateDisplay()
{
	repaint();
	ActStop = 0;
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	emit selectedColor(cstops.at(ActStop)->name, cstops.at(ActStop)->shade);
	emit currTrans(cstops.at(ActStop)->opacity);
	emit currStep(cstops.at(ActStop)->rampPoint);
}

void GradientPreview::setActColor(QColor c, QString n, int s)
{
	if (ActStop == -1)
		return;
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	cstops.at(ActStop)->color = c;
	cstops.at(ActStop)->name = n;
	cstops.at(ActStop)->shade = s;
	repaint();
}

void GradientPreview::setActTrans(double t)
{
	if (ActStop == -1)
		return;
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	cstops.at(ActStop)->opacity = t;
	repaint();
}

void GradientPreview::setActStep(double t)
{
	if (ActStop == -1)
		return;
	QPtrVector<VColorStop> cstops = fill_gradient.colorStops();
	cstops.at(ActStop)->rampPoint = t;
	repaint();
}

GradientEditor::GradientEditor(QWidget *pa) : QLabel(pa)
{
	Form1Layout = new QVBoxLayout( this, 0, 0, "Form1Layout");
	Preview = new GradientPreview(this);
	Form1Layout->addWidget(Preview);
	Layout1 = new QHBoxLayout(0,0,0,"Layout1");
	Layout1->setSpacing( 4 );
	Layout1->setMargin( 0 );
	Position = new QSpinBox( this, "shspin" );
	Position->setMinValue(0);
	Position->setMaxValue(100);
	Position->setLineStep(1);
	Position->setValue(0);
	Desc = new QLabel( this, "Desc" );
	languageChange();
	Layout1->addWidget( Desc );
	Layout1->addWidget(Position);
	Form1Layout->addLayout(Layout1);
	connect(Position, SIGNAL(valueChanged(int)), this, SLOT(changePos(int)));
	connect(Preview, SIGNAL(currStep(double)), this, SLOT(setPos(double)));
	resize(minimumSizeHint());
}

void GradientEditor::setPos(double p)
{
	disconnect(Position, SIGNAL(valueChanged(int)), this, SLOT(changePos(int)));
	Position->setValue(qRound(p * 100));
	connect(Position, SIGNAL(valueChanged(int)), this, SLOT(changePos(int)));
}

void GradientEditor::changePos(int v)
{
	Preview->setActStep(static_cast<double>(v) / 100.0);
	emit gradientChanged();
}

void GradientEditor::languageChange()
{
	QToolTip::remove(Preview);
	QToolTip::add(Preview, QRect(10,43, Preview->width()-20, 13), tr( "Add, change or remove color stops here" ) );
	Desc->setText( tr( "Position:" ) );
	Position->setSuffix( tr(" %") );
}
