Solving issue 1444: " Better Vibrance tool's threshold handling"

This commit is contained in:
natureh
2012-07-03 23:49:45 +02:00
parent dba91ea39e
commit 02c12d5259
9 changed files with 446 additions and 148 deletions

View File

@@ -21,6 +21,21 @@
#include "guiutils.h"
#include "../rtengine/procparams.h"
#include <iomanip>
class ThresholdSelector;
/*
* This class let the instanciator to provide the background curve
*/
class ThresholdCurveProvider {
public:
/*
* The curve provider has to send back a list of point (at least 2 points) in the [0.0 ; 1.0] range
* for both X and Y axis; X and Y values are streamlined ( X1, Y1, X2, Y2, X3, Y3, ...)
*/
virtual std::vector<double> getCurvePoints(ThresholdSelector* tAdjuster) const = 0;
};
/*
* This widget will let you select a linearly variable threshold, creating a ramp up
@@ -36,6 +51,11 @@
*
* Please note that the values are related to the cursors, depending on their position
* on the graph. E.g. the "bottomLeft" value is related to the bottom left cursor.
*
* It is also possible to have a threshold with 2 totally independent cursors, each one having his own range,
* man/max/default values and precision. This let developers create their own threshold curve, that they will
* have to provide through the
*
*/
class ThresholdSelector : public Gtk::DrawingArea {
@@ -57,17 +77,24 @@ class ThresholdSelector : public Gtk::DrawingArea {
Glib::RefPtr<Gdk::GC> gc_;
Glib::RefPtr<Gdk::Pixmap> backBuffer;
std::vector<GradientMilestone> bgGradient;
ThresholdCurveProvider* bgCurveProvider;
Glib::ustring additionalTTip;
Glib::ustring separatedLabelBottom; // Label for the bottom cursor, displayed if separatedSliders==true only
Glib::ustring separatedLabelTop; // Label for the top cursor, displayed if separatedSliders==true only
bool separatedSliders; // If true, the Top and Bottom sliders are totally separate and can be drag through the full range; for simple threshold only!
bool doubleThresh; // If true: there curve is a double threshold (0 to 1 to 0, or 1 to 0 to 1).
bool initalEq1; // If true: the curve start at 1 (top); if false: the curve start at 0 (bottom)
unsigned int precision; // Decimal number if this object has to handle "double" values
unsigned int precisionTop; // Decimal number if this object has to handle "double" values, for the Top slider
unsigned int precisionBottom; // Decimal number if this object has to handle "double" values, for the Bottom slider
ThreshCursorId litCursor;
ThreshCursorId oldLitCursor;
double boundary1[2], boundary2[2];
double tmpX, tmpPos;
ThreshCursorId movedCursor, secondaryMovedCursor;
double minVal, maxVal;
double minValTop, maxValTop;
double minValBottom, maxValBottom;
double defPos[4];
double positions[4];
unsigned short wslider;
@@ -75,22 +102,24 @@ class ThresholdSelector : public Gtk::DrawingArea {
const static int hb = 3; // horizontal border
const static int vb = 2; // vertical border
void initValues (double minValue, double maxValue, bool startAtOne);
void initValues ();
void findLitCursor(int posX, int posY);
void findSecondaryMovedCursor(guint state);
void findBoundaries(double &min, double &max);
double to01(double value);
double to01(ThreshCursorId cursorId);
void updateTooltip();
public:
sigc::signal<void> signal_value_changed();
ThresholdSelector(double minValueBottom, double maxValueBottom, double defBottom, Glib::ustring labelBottom, unsigned int precisionBottom,
double minValueTop, double maxValueTop, double defTop, Glib::ustring labelTop, unsigned int precisionTop,
ThresholdCurveProvider* curveProvider);
ThresholdSelector(double minValue, double maxValue, double defBottom, double defTop, unsigned int precision, bool startAtOne);
ThresholdSelector(double minValue, double maxValue, double defBottomLeft, double defTopLeft, double defBottomRight, double defTopRight, unsigned int precision, bool startAtOne);
double shapeValue (double value) { return round(value*pow(double(10), precision)) / pow(double(10), precision); }
double shapePositionValue (ThreshCursorId cursorId);
template <typename T>
void setDefaults (const rtengine::procparams::Threshold<T> &t) {
defPos[TS_BOTTOMLEFT] = double(t.value[0]); // should we use shapeValue() ?
@@ -100,10 +129,8 @@ class ThresholdSelector : public Gtk::DrawingArea {
defPos[TS_TOPRIGHT] = double(t.value[3]);
}
}
void setDefaults (double bottom, double top);
void setDefaults (double bottomLeft, double topLeft, double bottomRight, double topRight);
template <typename T>
void setPositions (const rtengine::procparams::Threshold<T> &tValues) {
positions[TS_BOTTOMLEFT] = static_cast<double>(tValues.value[TS_BOTTOMLEFT]);
@@ -122,28 +149,42 @@ class ThresholdSelector : public Gtk::DrawingArea {
rtengine::procparams::Threshold<T> getPositions () {
if (doubleThresh) {
rtengine::procparams::Threshold<T> rThresh(
static_cast<T>(shapeValue(positions[TS_BOTTOMLEFT])),
static_cast<T>(shapeValue(positions[TS_TOPLEFT])),
static_cast<T>(shapeValue(positions[TS_BOTTOMRIGHT])),
static_cast<T>(shapeValue(positions[TS_TOPRIGHT])),
static_cast<T>(shapePositionValue(TS_BOTTOMLEFT)),
static_cast<T>(shapePositionValue(TS_TOPLEFT)),
static_cast<T>(shapePositionValue(TS_BOTTOMRIGHT)),
static_cast<T>(shapePositionValue(TS_TOPRIGHT)),
initalEq1
);
return rThresh;
}
else {
rtengine::procparams::Threshold<T> rThresh(
static_cast<T>(shapeValue(positions[TS_BOTTOMLEFT])),
static_cast<T>(shapeValue(positions[TS_TOPLEFT])),
static_cast<T>(shapePositionValue(TS_BOTTOMLEFT)),
static_cast<T>(shapePositionValue(TS_TOPLEFT)),
initalEq1
);
return rThresh;
}
}
void getPositions (Glib::ustring& bottom, Glib::ustring& top);
void getPositions (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight);
template <typename T>
void getPositions (T &bottom, T &top) {
bottom = static_cast<T>(shapePositionValue(TS_BOTTOMLEFT));
top = static_cast<T>(shapePositionValue(TS_TOPLEFT));
}
template <typename T>
void getPositions (T &bottomLeft, T &topLeft, T &bottomRight, T &topRight) {
bottomLeft = static_cast<T>(shapePositionValue(TS_BOTTOMLEFT));
topLeft = static_cast<T>(shapePositionValue(TS_TOPLEFT));
bottomRight = static_cast<T>(shapePositionValue(TS_BOTTOMRIGHT));
topRight = static_cast<T>(shapePositionValue(TS_TOPRIGHT));
}
void setSeparatedSliders(bool separated);
bool getSeparatedSliders();
void setBgGradient (const std::vector<GradientMilestone> &milestones);
void setBgCurveProvider (ThresholdCurveProvider* provider);
bool isStartAtOne() { return initalEq1; }
bool isDouble() { return doubleThresh; }
void on_realize ();
@@ -153,9 +194,27 @@ class ThresholdSelector : public Gtk::DrawingArea {
bool on_motion_notify_event (GdkEventMotion* event);
bool on_leave_notify_event (GdkEventCrossing* event);
void styleChanged (const Glib::RefPtr<Gtk::Style>& style);
unsigned int getPrecision () { return precision; }
unsigned int getPrecision () { return precisionTop; }
void reset ();
void set_tooltip_markup(const Glib::ustring& markup);
// this set_tooltip_text method is to set_tooltip_markup, and text can contain markups
void set_tooltip_text(const Glib::ustring& text);
};
template<>
inline void ThresholdSelector::getPositions<Glib::ustring> (Glib::ustring& bottom, Glib::ustring& top) {
bottom = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT));
top = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT));
}
template<>
inline void ThresholdSelector::getPositions<Glib::ustring> (Glib::ustring& bottomLeft, Glib::ustring& topLeft, Glib::ustring& bottomRight, Glib::ustring& topRight) {
bottomLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMLEFT));
topLeft = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPLEFT));
bottomRight = Glib::ustring::format(std::fixed, std::setprecision(precisionBottom), shapePositionValue(TS_BOTTOMRIGHT));
topRight = Glib::ustring::format(std::fixed, std::setprecision(precisionTop), shapePositionValue(TS_TOPRIGHT));
}
#endif