Commit fa3c22de authored by Eoin O'Neill's avatar Eoin O'Neill 🍀

Gradient Stop Sorting by Value

Adds right click context menu to gradient editor widget with the ability
to sort gradients by value. 'Sort by Value' simply sorts the values onto
the gradient by the value of the color and thus is distributed
appropriately. 'Sort by Value (Even Distribution)' sorts the stops by
value but instead of placing them by color value onto the gradient, it
evenly distributes the colors across the entire gradient space. Both of
these values can be flipped using the 'reverse' button or the reverse
option in the right click menu.
parent 4271c956
......@@ -29,6 +29,13 @@
typedef QPair<qreal, KoColor> KoGradientStop;
struct KoGradientStopValueSort
{
inline bool operator() (const KoGradientStop& a, const KoGradientStop& b) {
return (a.second.toQColor().valueF() < b.second.toQColor().valueF());
}
};
/**
* Resource for colorstop based gradients like SVG gradients
*/
......
......@@ -21,6 +21,8 @@
#include <QPainter>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QPoint>
#include <QMenu>
#include <KoColorSpace.h>
#include <resources/KoStopGradient.h>
......@@ -56,6 +58,10 @@ KisStopGradientEditor::KisStopGradientEditor(QWidget *parent)
KisIconUtils::updateIcon(buttonReverseSecond);
connect(buttonReverseSecond, SIGNAL(clicked()), SLOT(reverse()));
this->setContextMenuPolicy(Qt::CustomContextMenu);
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showContextMenu(const QPoint &)));
setCompactMode(false);
setGradient(0);
......@@ -195,3 +201,57 @@ void KisStopGradientEditor::reverse()
emit sigGradientChanged();
}
void KisStopGradientEditor::sortByValue( SortFlags flags = SORT_ASCENDING )
{
if (!m_gradient) return;
bool ascending = (flags & SORT_ASCENDING) > 0;
bool evenDistribution = (flags & EVEN_DISTRIBUTION) > 0;
QList<KoGradientStop> stops = m_gradient->stops();
const int stopCount = stops.size();
QList<KoGradientStop> sortedStops;
std::sort(stops.begin(), stops.end(), KoGradientStopValueSort());
int stopIndex = 0;
for (const KoGradientStop& stop : stops) {
const float value = evenDistribution ? (float)stopIndex / (float)(stopCount - 1) : stop.second.toQColor().valueF();
const float position = ascending ? value : 1.f - value;
if (ascending) {
sortedStops.push_back(KoGradientStop(position, stop.second));
} else {
sortedStops.push_front(KoGradientStop(position, stop.second));
}
stopIndex++;
}
m_gradient->setStops(sortedStops);
gradientSlider->setSelectedStop(stopCount - 1);
gradientSlider->update();
emit sigGradientChanged();
}
void KisStopGradientEditor::showContextMenu(const QPoint &origin)
{
QMenu contextMenu(i18n("Options"), this);
QAction reverseValues(i18n("Reverse Values"), this);
connect(&reverseValues, &QAction::triggered, this, &KisStopGradientEditor::reverse);
QAction sortAscendingValues(i18n("Sort by Value"), this);
connect(&sortAscendingValues, &QAction::triggered, this, [this]{ this->sortByValue(SORT_ASCENDING); } );
QAction sortAscendingDistributed(i18n("Sort by Value (Even Distribution)"), this);
connect(&sortAscendingDistributed, &QAction::triggered, this, [this]{ this->sortByValue(SORT_ASCENDING | EVEN_DISTRIBUTION);} );
contextMenu.addAction(&reverseValues);
contextMenu.addSeparator();
contextMenu.addAction(&sortAscendingValues);
contextMenu.addAction(&sortAscendingDistributed);
contextMenu.exec(mapToGlobal(origin));
}
......@@ -31,6 +31,13 @@ class KRITAUI_EXPORT KisStopGradientEditor : public QWidget, public Ui::KisWdgSt
Q_OBJECT
public:
enum SortFlag {
SORT_ASCENDING = 1 << 0,
EVEN_DISTRIBUTION = 1 << 1
};
Q_DECLARE_FLAGS( SortFlags, SortFlag);
KisStopGradientEditor(QWidget *parent);
KisStopGradientEditor(KoStopGradient* gradient, QWidget *parent, const char* name, const QString& caption);
......@@ -53,6 +60,9 @@ private Q_SLOTS:
void opacityChanged(qreal value);
void nameChanged();
void reverse();
void sortByValue(SortFlags flags);
void showContextMenu( const class QPoint& origin );
};
Q_DECLARE_OPERATORS_FOR_FLAGS(KisStopGradientEditor::SortFlags);
#endif
......@@ -164,6 +164,11 @@ void KisStopGradientSliderWidget::mousePressEvent(QMouseEvent * e)
return;
}
if (e->buttons() != Qt::LeftButton ) {
QWidget::mousePressEvent(e);
return;
}
const QRect handlesRect = this->handlesStipeRect();
const qreal t = (qreal(e->x()) - handlesRect.x()) / handlesRect.width();
const QList<KoGradientStop> stops = m_gradient->stops();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment