Commit e820d52d authored by Sven Langkamp's avatar Sven Langkamp

make loaded gradients editable

merges KisAutogradientResource into KoSegmentGradient
parent f4612cc5
......@@ -68,7 +68,6 @@ set(kritaui_LIB_SRCS
flake/kis_shape_selection_model.cpp
flake/kis_take_all_shapes_command.cpp
kis_autogradient.cc
kis_autogradient_resource.cc
kis_bookmarked_configurations_editor.cc
kis_bookmarked_configurations_model.cc
kis_bookmarked_filter_configurations_model.cc
......
......@@ -27,14 +27,13 @@
#include <KoColorSpace.h>
#include <KoSegmentGradient.h>
#include "kis_autogradient_resource.h"
#include "kis_debug.h"
#include "widgets/kis_gradient_slider_widget.h"
/****************************** KisAutogradient ******************************/
KisAutogradient::KisAutogradient(KisAutogradientResource* gradient, QWidget *parent, const char* name, const QString& caption)
KisAutogradient::KisAutogradient(KoSegmentGradient* gradient, QWidget *parent, const char* name, const QString& caption)
: QWidget(parent), m_autogradientResource(gradient)
{
setObjectName(name);
......
......@@ -24,19 +24,19 @@
class KoResource;
class KoGradientSegment;
class KisAutogradientResource;
class KoSegmentGradient;
class KisAutogradient : public QWidget, public Ui::KisWdgAutogradient
{
Q_OBJECT
public:
KisAutogradient(KisAutogradientResource* gradient, QWidget *parent, const char* name, const QString& caption);
KisAutogradient(KoSegmentGradient* gradient, QWidget *parent, const char* name, const QString& caption);
void activate();
signals:
void activatedResource(KoResource *r);
private:
KisAutogradientResource* m_autogradientResource;
KoSegmentGradient* m_autogradientResource;
private slots:
void slotSelectedSegment(KoGradientSegment* segment);
void slotChangedSegment(KoGradientSegment* segment);
......
/*
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
* 2004 Sven Langkamp <sven.langkamp@gmail.com>
*
* 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 "kis_autogradient_resource.h"
#include "KoColorSpace.h"
// XXX: use the same #define as in kis_gradient.cc, probably best customizable?
#define PREVIEW_WIDTH 64
#define PREVIEW_HEIGHT 64
void KisAutogradientResource::createSegment(int interpolation, int colorInterpolation, double startOffset, double endOffset, double middleOffset, const QColor & left, const QColor & right)
{
pushSegment(new KoGradientSegment(interpolation, colorInterpolation, startOffset, middleOffset, endOffset, KoColor(left, colorSpace()), KoColor(right, colorSpace())));
}
const QList<double> KisAutogradientResource::getHandlePositions() const
{
QList<double> handlePositions;
handlePositions.push_back(m_segments[0]->startOffset());
for (int i = 0; i < m_segments.count(); i++) {
handlePositions.push_back(m_segments[i]->endOffset());
}
return handlePositions;
}
const QList<double> KisAutogradientResource::getMiddleHandlePositions() const
{
QList<double> middleHandlePositions;
for (int i = 0; i < m_segments.count(); i++) {
middleHandlePositions.push_back(m_segments[i]->middleOffset());
}
return middleHandlePositions;
}
void KisAutogradientResource::moveSegmentStartOffset(KoGradientSegment* segment, double t)
{
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
if (it == m_segments.begin()) {
segment->setStartOffset(0.0);
return;
}
KoGradientSegment* previousSegment = (*(it - 1));
if (t > segment->startOffset()) {
if (t > segment->middleOffset())
t = segment->middleOffset();
} else {
if (t < previousSegment->middleOffset())
t = previousSegment->middleOffset();
}
previousSegment->setEndOffset(t);
segment->setStartOffset(t);
}
}
void KisAutogradientResource::moveSegmentEndOffset(KoGradientSegment* segment, double t)
{
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
if (it + 1 == m_segments.end()) {
segment->setEndOffset(1.0);
return;
}
KoGradientSegment* followingSegment = (*(it + 1));
if (t < segment->endOffset()) {
if (t < segment->middleOffset())
t = segment->middleOffset();
} else {
if (t > followingSegment->middleOffset())
t = followingSegment->middleOffset();
}
followingSegment->setStartOffset(t);
segment->setEndOffset(t);
}
}
void KisAutogradientResource::moveSegmentMiddleOffset(KoGradientSegment* segment, double t)
{
if (segment) {
if (t > segment->endOffset())
segment->setMiddleOffset(segment->endOffset());
else if (t < segment->startOffset())
segment->setMiddleOffset(segment->startOffset());
else
segment->setMiddleOffset(t);
}
}
void KisAutogradientResource::splitSegment(KoGradientSegment* segment)
{
Q_ASSERT(segment != 0);
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
KoColor midleoffsetColor(segment->endColor().colorSpace());
segment->colorAt(midleoffsetColor, segment->middleOffset());
KoGradientSegment* newSegment = new KoGradientSegment(
segment->interpolation(), segment->colorInterpolation(),
segment ->startOffset(),
(segment->middleOffset() - segment->startOffset()) / 2 + segment->startOffset(),
segment->middleOffset(),
segment->startColor(),
midleoffsetColor);
m_segments.insert(it, newSegment);
segment->setStartColor(midleoffsetColor);
segment->setStartOffset(segment->middleOffset());
segment->setMiddleOffset((segment->endOffset() - segment->startOffset()) / 2 + segment->startOffset());
}
}
void KisAutogradientResource::duplicateSegment(KoGradientSegment* segment)
{
Q_ASSERT(segment != 0);
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
double middlePostionPercentage = (segment->middleOffset() - segment->startOffset()) / segment->length();
double center = segment->startOffset() + segment->length() / 2;
KoGradientSegment* newSegment = new KoGradientSegment(
segment->interpolation(), segment->colorInterpolation(),
segment ->startOffset(),
segment->length() / 2 * middlePostionPercentage + segment->startOffset(),
center, segment->startColor(),
segment->endColor());
m_segments.insert(it, newSegment);
segment->setStartOffset(center);
segment->setMiddleOffset(segment->length() * middlePostionPercentage + segment->startOffset());
}
}
void KisAutogradientResource::mirrorSegment(KoGradientSegment* segment)
{
Q_ASSERT(segment != 0);
KoColor tmpColor = segment->startColor();
segment->setStartColor(segment->endColor());
segment->setEndColor(tmpColor);
segment->setMiddleOffset(segment->endOffset() - (segment->middleOffset() - segment->startOffset()));
if (segment->interpolation() == INTERP_SPHERE_INCREASING)
segment->setInterpolation(INTERP_SPHERE_DECREASING);
else if (segment->interpolation() == INTERP_SPHERE_DECREASING)
segment->setInterpolation(INTERP_SPHERE_INCREASING);
if (segment->colorInterpolation() == COLOR_INTERP_HSV_CW)
segment->setColorInterpolation(COLOR_INTERP_HSV_CCW);
else if (segment->colorInterpolation() == COLOR_INTERP_HSV_CCW)
segment->setColorInterpolation(COLOR_INTERP_HSV_CW);
}
KoGradientSegment* KisAutogradientResource::removeSegment(KoGradientSegment* segment)
{
Q_ASSERT(segment != 0);
if (m_segments.count() < 2)
return 0;
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
double middlePostionPercentage;
KoGradientSegment* nextSegment;
if (it == m_segments.begin()) {
nextSegment = (*(it + 1));
middlePostionPercentage = (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length();
nextSegment->setStartOffset(segment->startOffset());
nextSegment->setMiddleOffset(middlePostionPercentage * nextSegment->length() + nextSegment->startOffset());
} else {
nextSegment = (*(it - 1));
middlePostionPercentage = (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length();
nextSegment->setEndOffset(segment->endOffset());
nextSegment->setMiddleOffset(middlePostionPercentage * nextSegment->length() + nextSegment->startOffset());
}
delete segment;
m_segments.erase(it);
return nextSegment;
}
return 0;
}
bool KisAutogradientResource::removeSegmentPossible() const
{
if (m_segments.count() < 2)
return false;
return true;
}
/*
* Copyright (c) 2004 Cyrille Berger <cberger@cberger.net>
* 2004 Sven Langkamp <sven.langkamp@gmail.com>
*
* 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.
*/
/**
* @file this file is part of the Krita application in calligra.
* Handles the gradient colour picker segments and their positions.
* @author Cyrille Berger
* @author Sven Langkamp
* @author documentation by hscott
* @since 1.4
*/
#ifndef _KIS_AUTOGRADIENT_RESOURCE_H_
#define _KIS_AUTOGRADIENT_RESOURCE_H_
#include <QList>
#include <KoSegmentGradient.h>
#include <krita_export.h>
class QColor;
/**
* @class KisAutogradientResource
* Is for creating custom gradient colour pickers. A gradient is
* a field which shifts from one colour to one or more other
* colours. The gradient colour picker defines what colours are
* used in the image's gradient field. This class only handles
* the gradient colour picker, _not_ the image's gradient field.
*/
class KRITAUI_EXPORT KisAutogradientResource : public KoSegmentGradient
{
public:
KisAutogradientResource()
: KoSegmentGradient("")
{
}
public:
/**
* a gradient colour picker can consist of one or more segments.
* A segment has two end points - each colour in the gradient
* colour picker represents a segment end point.
* @param interpolation
* @param colorInterpolation
* @param startOffset
* @param endOffset
* @param middleOffset
* @param left
* @param right
* @return void
*/
void createSegment(int interpolation, int colorInterpolation, double startOffset, double endOffset, double middleOffset, const QColor & left, const QColor & right);
/**
* gets a list of end points of the segments in the gradient
* colour picker. If two colours, one segment then two end
* points, and if three colours, then two segments with four
* endpoints.
* @return a list of double values
*/
const QList<double> getHandlePositions() const;
/**
* gets a list of middle points of the segments in the gradient
* colour picker.
* @return a list of double values
*/
const QList<double> getMiddleHandlePositions() const;
/**
* Moves the StartOffset of the specified segment to the
* specified value and corrects the endoffset of the previous
* segment. If the segment is the first Segment the startoffset
* will be set to 0.0 . The offset will maximally be moved till
* the middle of the current or the previous segment. This is
* useful if someone clicks to move the handler for a segment,
* to set the half the segment to the right and half the segment
* to the left of the handler.
* @param segment the segment for which to move the relative
* offset within the gradient colour picker.
* @param t the new startoff position for the segment
* @return void
*/
void moveSegmentStartOffset(KoGradientSegment* segment, double t);
/**
* Moves the endoffset of the specified segment to the specified
* value and corrects the startoffset of the following segment.
* If the segment is the last segment the endoffset will be set
* to 1.0 . The offset will maximally be moved till the middle
* of the current or the following segment. This is useful if
* someone moves the segment handler in the gradient colour
* picker, and needs the segment to move with it. Sets the end
* position of the segment to the correct new position.
* @param segment the segment for which to move the relative
* end position within the gradient colour picker.
* @param t the new end position for the segment
* @return void
*/
void moveSegmentEndOffset(KoGradientSegment* segment, double t);
/**
* moves the Middle of the specified segment to the specified
* value. The offset will maximally be moved till the endoffset
* or startoffset of the segment. This sets the middle of the
* segment to the same position as the handler of the gradient
* colour picker.
* @param segment the segment for which to move the relative
* middle position within the gradient colour picker.
* @param t the new middle position for the segment
* @return void
*/
void moveSegmentMiddleOffset(KoGradientSegment* segment, double t);
/**
* splits the specified segment into two equal parts
* @param segment the segment to split
* @return void
*/
void splitSegment(KoGradientSegment* segment);
/**
* duplicate the specified segment
* @param segment the segment to duplicate
* @return void
*/
void duplicateSegment(KoGradientSegment* segment);
/**
* create a segment horizontally reversed to the specified one.
* @param segment the segment to reverse
* @return void
*/
void mirrorSegment(KoGradientSegment* segment);
/**
* removes the specific segment from the gradient colour picker.
* @param segment the segment to remove
* @return the segment which will be at the place of the old
* segment. 0 if the segment is not in the gradient or it is
* not possible to remove the segment.
*/
KoGradientSegment* removeSegment(KoGradientSegment* segment);
/**
* checks if it's possible to remove a segment (at least two
* segments in the gradient)
* @return true if it's possible to remove an segment
*/
bool removeSegmentPossible() const;
public:
virtual bool load() {
return false;
}
};
#endif // _KIS_AUTOGRADIENT_RESOURCE_H_
......@@ -64,12 +64,6 @@ target_link_libraries(KisShapeSelectionTest ${KDE4_KDEUI_LIBS} kritaimage krita
########### next target ###############
set(kis_autogradient_resource_test_SRCS kis_autogradient_resource_test.cpp )
kde4_add_unit_test(KisAutogradientResourceTest TESTNAME krita-ui-KisAutogradientResourceTest ${kis_autogradient_resource_test_SRCS})
target_link_libraries(KisAutogradientResourceTest ${KDE4_KDEUI_LIBS} kritaimage kritaui ${QT_QTTEST_LIBRARY})
########### next target ###############
set(kis_exiv2_test_SRCS kis_exiv2_test.cpp )
kde4_add_unit_test(KisExiv2Test TESTNAME krita-ui-KisExiv2Test ${kis_exiv2_test_SRCS})
target_link_libraries(KisExiv2Test ${KDE4_KDEUI_LIBS} kritaimage kritaui ${QT_QTTEST_LIBRARY})
......
/*
* Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org
*
* 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 "kis_autogradient_resource_test.h"
#include <qtest_kde.h>
#include "kis_autogradient_resource.h"
void KisAutogradientResourceTest::testCreation()
{
KisAutogradientResource test;
}
QTEST_KDEMAIN(KisAutogradientResourceTest, GUI)
#include "kis_autogradient_resource_test.moc"
/*
* Copyright (c) 2007 Boudewijn Rempt boud@valdyas.org
*
* 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.
*/
#ifndef KIS_AUTOGRADIENT_RESOURCE_TEST_H
#define KIS_AUTOGRADIENT_RESOURCE_TEST_H
#include <QtTest>
class KisAutogradientResourceTest : public QObject
{
Q_OBJECT
private slots:
void testCreation();
};
#endif
......@@ -38,9 +38,8 @@
#include "kis_global.h"
#include "kis_autogradient.h"
#include "kis_canvas_resource_provider.h"
#include <kis_autogradient_resource.h>
KisCustomGradientDialog::KisCustomGradientDialog(KisAutogradientResource* gradient, QWidget * parent, const char *name)
KisCustomGradientDialog::KisCustomGradientDialog(KoSegmentGradient* gradient, QWidget * parent, const char *name)
: KDialog(parent)
{
setCaption(i18n("Custom Gradient"));
......@@ -81,9 +80,10 @@ KisGradientChooser::KisGradientChooser(KisView2 * view, QWidget *parent, const c
connect(addGradient, SIGNAL(clicked()), this, SLOT(addGradient()));
buttonLayout->addWidget(addGradient);
QPushButton* editGradient = new QPushButton(koIcon("configure"), i18n("Edit..."));
connect(editGradient, SIGNAL(clicked()), this, SLOT(editGradient()));
buttonLayout->addWidget(editGradient);
m_editGradient = new QPushButton(koIcon("configure"), i18n("Edit..."));
m_editGradient->setEnabled(false);
connect(m_editGradient, SIGNAL(clicked()), this, SLOT(editGradient()));
buttonLayout->addWidget(m_editGradient);
QVBoxLayout *mainLayout = new QVBoxLayout(this);
mainLayout->setObjectName("main layout");
......@@ -115,6 +115,9 @@ void KisGradientChooser::update(KoResource * resource)
{
KoAbstractGradient *gradient = static_cast<KoAbstractGradient *>(resource);
m_lbName->setText(i18n(gradient->name().toUtf8().data()));
KoSegmentGradient *segmentGradient = dynamic_cast<KoSegmentGradient*>(gradient);
m_editGradient->setEnabled(segmentGradient && segmentGradient->removable());
}
void KisGradientChooser::addGradient()
......@@ -122,7 +125,7 @@ void KisGradientChooser::addGradient()
KoResourceServer<KoAbstractGradient> * rserver = KoResourceServerProvider::instance()->gradientServer();
QString saveLocation = rserver->saveLocation();
KisAutogradientResource* gradient = new KisAutogradientResource();
KoSegmentGradient* gradient = new KoSegmentGradient("");
gradient->createSegment(INTERP_LINEAR, COLOR_INTERP_RGB, 0.0, 1.0, 0.5, Qt::black, Qt::white);
gradient->setName(i18n("unnamed"));
......@@ -137,7 +140,7 @@ void KisGradientChooser::addGradient()
void KisGradientChooser::editGradient()
{
KisAutogradientResource* gradient = dynamic_cast<KisAutogradientResource*>(currentResource());
KoSegmentGradient* gradient = dynamic_cast<KoSegmentGradient*>(currentResource());
if (gradient) {
KisCustomGradientDialog dialog(gradient, this, "autogradient");
dialog.exec();
......
......@@ -22,6 +22,7 @@
#include <QFrame>
class KoSegmentGradient;
class KisAutogradientResource;
class KisView2;
class QLabel;
......@@ -38,7 +39,7 @@ class KisCustomGradientDialog : public KDialog
public:
KisCustomGradientDialog(KisAutogradientResource* gradient, QWidget * parent, const char *name);
KisCustomGradientDialog(KoSegmentGradient* gradient, QWidget * parent, const char *name);
private:
......@@ -74,6 +75,7 @@ private slots:
private:
QLabel *m_lbName;
KoResourceItemChooser * m_itemChooser;
QPushButton* m_editGradient;
};
#endif // KIS_GRADIENT_CHOOSER_H_
......
......@@ -30,7 +30,7 @@
#include <klocale.h>
#include <kaction.h>
#include "kis_autogradient_resource.h"
#include <KoSegmentGradient.h>
#define MARGIN 5
#define HANDLE_SIZE 10
......@@ -55,7 +55,7 @@ KisGradientSliderWidget::KisGradientSliderWidget(QWidget *parent, const char* na
m_segmentMenu->addAction(m_removeSegmentAction);
}
void KisGradientSliderWidget::setGradientResource(KisAutogradientResource* agr)
void KisGradientSliderWidget::setGradientResource(KoSegmentGradient* agr)
{
m_autogradientResource = agr;
m_selectedSegment = m_autogradientResource->segmentAt(0.0);
......
......@@ -28,6 +28,7 @@ class KAction;
class KMenu;
class KisAutogradientResource;
class KoGradientSegment;
class KoSegmentGradient;
class KisGradientSliderWidget : public QWidget
{
......@@ -38,7 +39,7 @@ public:
public:
virtual void paintEvent(QPaintEvent *);
void setGradientResource(KisAutogradientResource* agr);
void setGradientResource(KoSegmentGradient* agr);
KoGradientSegment* selectedSegment() {
return m_selectedSegment;
}
......@@ -75,7 +76,7 @@ private:
REMOVE_SEGMENT
};
KisAutogradientResource* m_autogradientResource;
KoSegmentGradient* m_autogradientResource;
KoGradientSegment* m_currentSegment;
KoGradientSegment* m_selectedSegment;
KMenu* m_segmentMenu;
......
......@@ -720,3 +720,178 @@ qreal KoGradientSegment::SphereDecreasingInterpolationStrategy::valueAt(qreal t,
return value;
}
void KoSegmentGradient::createSegment(int interpolation, int colorInterpolation, double startOffset, double endOffset, double middleOffset, const QColor & left, const QColor & right)
{
pushSegment(new KoGradientSegment(interpolation, colorInterpolation, startOffset, middleOffset, endOffset, KoColor(left, colorSpace()), KoColor(right, colorSpace())));
}
const QList<double> KoSegmentGradient::getHandlePositions() const
{
QList<double> handlePositions;
handlePositions.push_back(m_segments[0]->startOffset());
for (int i = 0; i < m_segments.count(); i++) {
handlePositions.push_back(m_segments[i]->endOffset());
}
return handlePositions;
}
const QList<double> KoSegmentGradient::getMiddleHandlePositions() const
{
QList<double> middleHandlePositions;
for (int i = 0; i < m_segments.count(); i++) {
middleHandlePositions.push_back(m_segments[i]->middleOffset());
}
return middleHandlePositions;
}
void KoSegmentGradient::moveSegmentStartOffset(KoGradientSegment* segment, double t)
{
QList<KoGradientSegment*>::iterator it = qFind(m_segments.begin(), m_segments.end(), segment);
if (it != m_segments.end()) {
if (it == m_segments.begin()) {
segment->setStartOffset(0.0);
return;
}
KoGradientSegment* previousSegment = (*(it - 1));
if (t > segment->startOffset()) {
if (t > segment->middleOffset())
t = segment->middleOffset();
} else {