Flat curve editor widget, HSV tool modified to use it.
Usage : - click & drag a control point to move it in X&Y direction - click & drag a vertical line to move it in horizontal or vertical direction (the very first move will be used to determine the motion direction) - click & drag the yellow or blue square handle to modify the tangent of the same color
This commit is contained in:
@@ -12,12 +12,13 @@ set (BASESOURCEFILES
|
||||
exifpanel.cc toolpanel.cc
|
||||
sharpening.cc
|
||||
whitebalance.cc vignetting.cc rotate.cc distortion.cc
|
||||
crophandler.cc curveeditorgroup.cc curveeditor.cc dirbrowser.cc
|
||||
crophandler.cc dirbrowser.cc
|
||||
curveeditor.cc curveeditorgroup.cc diagonalcurveeditorsubgroup.cc flatcurveeditorsubgroup.cc
|
||||
filecatalog.cc
|
||||
previewloader.cc
|
||||
histogrampanel.cc history.cc imagearea.cc
|
||||
imageareapanel.cc iptcpanel.cc labcurve.cc lumadenoise.cc main.cc
|
||||
multilangmgr.cc mycurve.cc options.cc
|
||||
multilangmgr.cc mycurve.cc myflatcurve.cc mydiagonalcurve.cc options.cc
|
||||
preferences.cc profilepanel.cc safegtk.cc saveasdlg.cc
|
||||
saveformatpanel.cc splash.cc
|
||||
thumbnail.cc tonecurve.cc toolbar.cc
|
||||
|
||||
33
rtgui/colorprovider.h
Normal file
33
rtgui/colorprovider.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _COLORPROVIDER_
|
||||
#define _COLORPROVIDER_
|
||||
|
||||
class ColorProvider {
|
||||
|
||||
public:
|
||||
double red;
|
||||
double green;
|
||||
double blue;
|
||||
|
||||
virtual void colorForValue (double valX, double valY) {}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -30,6 +30,8 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin) {
|
||||
cCropMove = new Gdk::Cursor (Gdk::FLEUR);
|
||||
cCropMoving = new Gdk::Cursor (Gdk::HAND2);
|
||||
cCropSelection = new Gdk::Cursor (Gdk::CROSSHAIR);
|
||||
cLeftTanMove = new Gdk::Cursor (Gdk::SB_LEFT_ARROW);
|
||||
cRightTanMove = new Gdk::Cursor (Gdk::SB_RIGHT_ARROW);
|
||||
cAdd = new Gdk::Cursor (Gdk::PLUS);
|
||||
|
||||
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
||||
@@ -50,7 +52,7 @@ void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape sha
|
||||
|
||||
if (shape==CSArrow)
|
||||
// set_cursor without any arguments to select system default
|
||||
window->set_cursor ();
|
||||
window->set_cursor ();
|
||||
else if (shape==CSOpenHand)
|
||||
window->set_cursor (*cHand);
|
||||
else if (shape==CSClosedHand)
|
||||
@@ -67,6 +69,10 @@ void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape sha
|
||||
window->set_cursor (*cWB);
|
||||
else if (shape==CSCropSelect)
|
||||
window->set_cursor (*cCropSelection);
|
||||
else if (shape==CSMoveLeft)
|
||||
window->set_cursor (*cLeftTanMove);
|
||||
else if (shape==CSMoveRight)
|
||||
window->set_cursor (*cRightTanMove);
|
||||
else if (shape==CSStraighten)
|
||||
window->set_cursor (*cCropSelection);
|
||||
else if (shape==CSPlus)
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
#include <gtkmm.h>
|
||||
|
||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSEmpty};
|
||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSMoveLeft, CSMoveRight, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSEmpty};
|
||||
|
||||
class CursorManager {
|
||||
|
||||
@@ -31,6 +31,8 @@ class CursorManager {
|
||||
Gdk::Cursor* cResizeDiag;
|
||||
Gdk::Cursor* cCropMove;
|
||||
Gdk::Cursor* cCropMoving;
|
||||
Gdk::Cursor* cLeftTanMove;
|
||||
Gdk::Cursor* cRightTanMove;
|
||||
Gdk::Cursor* cNormal;
|
||||
Gdk::Cursor* cCropSelection;
|
||||
Gdk::Cursor* cAdd;
|
||||
|
||||
@@ -25,6 +25,58 @@
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
DiagonalCurveEditor::DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, (CurveEditorGroup*) ceGroup, ceSubGroup) {
|
||||
|
||||
// Order set in the same order than "enum DiagonalCurveType". Shouldn't change, for compatibility reason
|
||||
curveType->addEntry(argv0+"/images/curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
||||
curveType->addEntry(argv0+"/images/curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline
|
||||
curveType->addEntry(argv0+"/images/curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric
|
||||
curveType->addEntry(argv0+"/images/curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS
|
||||
curveType->setSelected(DCT_Linear);
|
||||
curveType->show();
|
||||
}
|
||||
|
||||
std::vector<double> DiagonalCurveEditor::getCurve () {
|
||||
std::vector<double> curve;
|
||||
|
||||
switch (selected) {
|
||||
case (DCT_Spline):
|
||||
return curve = customCurveEd;
|
||||
case (DCT_Parametric):
|
||||
return curve = paramCurveEd;
|
||||
case (DCT_NURBS):
|
||||
return curve = NURBSCurveEd;
|
||||
default:
|
||||
// returning Linear or Unchanged
|
||||
curve.push_back((double)(selected));
|
||||
return curve;
|
||||
}
|
||||
}
|
||||
|
||||
FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, (CurveEditorGroup*) ceGroup, ceSubGroup) {
|
||||
|
||||
// Order set in the same order than "enum FlatCurveType". Shouldn't change, for compatibility reason
|
||||
curveType->addEntry(argv0+"/images/curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
||||
curveType->addEntry(argv0+"/images/curveType-controlPoints.png", M("CURVEEDITOR_MINMAXCPOINTS")); // 1 Min/Max ControlPoints
|
||||
curveType->setSelected(FCT_Linear);
|
||||
curveType->show();
|
||||
}
|
||||
|
||||
std::vector<double> FlatCurveEditor::getCurve () {
|
||||
std::vector<double> curve;
|
||||
|
||||
switch (selected) {
|
||||
//case (Parametric):
|
||||
// return curve = paramCurveEd;
|
||||
case (FCT_MinMaxCPoints):
|
||||
return curve = controlPointsCurveEd;
|
||||
default:
|
||||
// returning Linear or Unchanged
|
||||
curve.push_back((double)(selected));
|
||||
return curve;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* CurveEditor (CurveEditorGroup* ceGroup, Glib::ustring text)
|
||||
*
|
||||
@@ -32,32 +84,25 @@ extern Glib::ustring argv0;
|
||||
* ceGroup = NULL or the address of the Widget that will receive the CurveTypeToggleButton
|
||||
* text = (optional) label of the curve, displayed in the CurveTypeToggleButton, next to the image
|
||||
*/
|
||||
CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup) {
|
||||
CurveEditor::CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) {
|
||||
|
||||
bgHistValid = false;
|
||||
selected = Linear;
|
||||
selected = DCT_Linear;
|
||||
|
||||
histogram = new unsigned int[256]; // histogram values
|
||||
|
||||
group = ceGroup;
|
||||
subGroup = ceSubGroup;
|
||||
|
||||
if (group && text.size())
|
||||
curveType = Gtk::manage (new PopUpToggleButton(text + ":"));
|
||||
else
|
||||
curveType = Gtk::manage (new PopUpToggleButton());
|
||||
|
||||
// Order set in the same order than "enum CurveType". Shouldn't change, for compatibility reason
|
||||
curveType->addEntry(argv0+"/images/curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
|
||||
curveType->addEntry(argv0+"/images/curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline
|
||||
curveType->addEntry(argv0+"/images/curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric
|
||||
curveType->addEntry(argv0+"/images/curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS
|
||||
curveType->setSelected(Linear);
|
||||
curveType->set_tooltip_text(M("CURVEEDITOR_TYPE"));
|
||||
// TODO: Does this signal have to be blocked when on curve type change ?
|
||||
curveType->signal_toggled().connect ( sigc::mem_fun(*this, &CurveEditor::curveTypeToggled) );
|
||||
typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) );
|
||||
|
||||
curveType->show();
|
||||
}
|
||||
|
||||
CurveEditor::~CurveEditor () {
|
||||
@@ -65,29 +110,11 @@ CurveEditor::~CurveEditor () {
|
||||
delete [] histogram;
|
||||
}
|
||||
|
||||
|
||||
void CurveEditor::setCurve (const std::vector<double>& p) {
|
||||
tempCurve = p;
|
||||
group->setCurveExternal(this, p);
|
||||
}
|
||||
|
||||
std::vector<double> CurveEditor::getCurve () {
|
||||
std::vector<double> curve;
|
||||
|
||||
switch (selected) {
|
||||
case (Spline):
|
||||
return curve = customCurveEd;
|
||||
case (Parametric):
|
||||
return curve = paramCurveEd;
|
||||
case (NURBS):
|
||||
return curve = NURBSCurveEd;
|
||||
default:
|
||||
// returning Linear or Unchanged
|
||||
curve.push_back((double)(selected));
|
||||
return curve;
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditor::typeSelectionChanged (int n) {
|
||||
group->typeSelectionChanged(this, n);
|
||||
}
|
||||
@@ -97,7 +124,7 @@ void CurveEditor::curveTypeToggled() {
|
||||
}
|
||||
|
||||
bool CurveEditor::isUnChanged () {
|
||||
return curveType->getSelected()==Unchanged;
|
||||
return curveType->getSelected()==subGroup->getValUnchanged();
|
||||
}
|
||||
|
||||
void CurveEditor::setUnChanged (bool uc) {
|
||||
@@ -117,5 +144,5 @@ void CurveEditor::updateBackgroundHistogram (unsigned int* hist) {
|
||||
bgHistValid = false;
|
||||
|
||||
// Then call the curve editor group to eventually update the histogram
|
||||
group->updateBackgroundHistogram (this);
|
||||
subGroup->updateBackgroundHistogram (this);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,16 @@
|
||||
#ifndef _CURVEEDITOR_
|
||||
#define _CURVEEDITOR_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <popuptogglebutton.h>
|
||||
#include <curveeditorgroup.h>
|
||||
#include <mycurve.h>
|
||||
|
||||
class CurveEditorGroup;
|
||||
class CurveEditorSubGroup;
|
||||
|
||||
|
||||
/*
|
||||
*********************** Curve Editor ***********************
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This class is an interface between RT and the curve editor group ; it handles the methods
|
||||
@@ -32,40 +36,83 @@ class CurveEditorGroup;
|
||||
*/
|
||||
class CurveEditor {
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* The curve editor contains only one widget (the curve type button) to receive the signals
|
||||
* but it's co-handled by the CurveEditorGroup too
|
||||
*/
|
||||
|
||||
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
||||
CurveType selected;
|
||||
|
||||
PopUpToggleButton* curveType;
|
||||
unsigned int* histogram; // histogram values
|
||||
bool bgHistValid;
|
||||
|
||||
CurveEditorGroup* group;
|
||||
std::vector<double> tempCurve;
|
||||
std::vector<double> customCurveEd;
|
||||
std::vector<double> paramCurveEd;
|
||||
std::vector<double> NURBSCurveEd;
|
||||
sigc::connection typeconn;
|
||||
|
||||
public:
|
||||
|
||||
friend class CurveEditorGroup;
|
||||
CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup);
|
||||
~CurveEditor ();
|
||||
void typeSelectionChanged (int n);
|
||||
void curveTypeToggled();
|
||||
void setCurve (const std::vector<double>& p);
|
||||
std::vector<double> getCurve ();
|
||||
bool isUnChanged ();
|
||||
void setUnChanged (bool uc);
|
||||
void updateBackgroundHistogram (unsigned int* hist);
|
||||
friend class CurveEditorSubGroup;
|
||||
friend class DiagonalCurveEditorSubGroup;
|
||||
friend class FlatCurveEditorSubGroup;
|
||||
friend class DiagonalCurveEditor;
|
||||
friend class FlatCurveEditor;
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
* The curve editor contains only one widget (the curve type button) to receive the signals
|
||||
* but it's co-handled by the CurveEditorGroup too
|
||||
*/
|
||||
|
||||
PopUpToggleButton* curveType;
|
||||
unsigned int* histogram; // histogram values
|
||||
bool bgHistValid;
|
||||
|
||||
int selected;
|
||||
|
||||
CurveEditorGroup* group;
|
||||
CurveEditorSubGroup* subGroup;
|
||||
|
||||
std::vector<double> tempCurve;
|
||||
sigc::connection typeconn;
|
||||
|
||||
public:
|
||||
|
||||
CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup);
|
||||
~CurveEditor ();
|
||||
void typeSelectionChanged (int n);
|
||||
void curveTypeToggled();
|
||||
bool isUnChanged ();
|
||||
void setUnChanged (bool uc);
|
||||
void updateBackgroundHistogram (unsigned int* hist);
|
||||
void setCurve (const std::vector<double>& p);
|
||||
virtual std::vector<double> getCurve () = 0;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
******************** Diagonal Curve Editor ********************
|
||||
*/
|
||||
|
||||
|
||||
class DiagonalCurveEditor : public CurveEditor {
|
||||
|
||||
friend class DiagonalCurveEditorSubGroup;
|
||||
|
||||
protected:
|
||||
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
||||
std::vector<double> customCurveEd;
|
||||
std::vector<double> paramCurveEd;
|
||||
std::vector<double> NURBSCurveEd;
|
||||
|
||||
public:
|
||||
DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup);
|
||||
std::vector<double> getCurve ();
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
********************** Flat Curve Editor **********************
|
||||
*/
|
||||
|
||||
|
||||
class FlatCurveEditor : public CurveEditor {
|
||||
|
||||
friend class FlatCurveEditorSubGroup;
|
||||
|
||||
protected:
|
||||
// reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
|
||||
std::vector<double> controlPointsCurveEd;
|
||||
|
||||
public:
|
||||
FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup);
|
||||
std::vector<double> getCurve ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,144 +18,24 @@
|
||||
*
|
||||
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
|
||||
*/
|
||||
|
||||
#include <curveeditor.h>
|
||||
#include <curveeditorgroup.h>
|
||||
#include <diagonalcurveeditorsubgroup.h>
|
||||
#include <flatcurveeditorsubgroup.h>
|
||||
#include <multilangmgr.h>
|
||||
|
||||
extern Glib::ustring argv0;
|
||||
|
||||
CurveEditorGroup::CurveEditorGroup (Glib::ustring groupLabel) : cl(NULL), activeParamControl(-1) {
|
||||
CurveEditorGroup::CurveEditorGroup (Glib::ustring groupLabel) : cl(NULL), cp(NULL) {
|
||||
curveEditors.clear();
|
||||
displayedCurve = 0;
|
||||
numberOfPackedCurve = 0;
|
||||
flatSubGroup = 0;
|
||||
diagonalSubGroup = 0;
|
||||
|
||||
// We set the label to the one provided as parameter, even if it's an empty string
|
||||
curveGroupLabel = Gtk::manage (new Gtk::Label (groupLabel+":", Gtk::ALIGN_LEFT));
|
||||
|
||||
// custom curve
|
||||
customCurveBox = new Gtk::HBox ();
|
||||
Gtk::HBox* tmpa = Gtk::manage (new Gtk::HBox ());
|
||||
customCurve = Gtk::manage (new MyCurve ());
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//af->add (*customCurve);
|
||||
customCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
customCurve->setType (Spline);
|
||||
//customCurve->set_tooltip_text (M("CURVEEDITOR_TOOLTIPMOVESPEED"));
|
||||
tmpa->pack_start (*customCurve, true, false, 4);
|
||||
customCurveBox->pack_start (*tmpa, true, true,4);
|
||||
|
||||
Gtk::VBox* custombbox = Gtk::manage (new Gtk::VBox ());
|
||||
saveCustom = Gtk::manage (new Gtk::Button ());
|
||||
saveCustom->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
loadCustom = Gtk::manage (new Gtk::Button ());
|
||||
loadCustom->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
custombbox->pack_end (*saveCustom, Gtk::PACK_SHRINK, 4);
|
||||
custombbox->pack_end (*loadCustom, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
customCurveBox->pack_end (*custombbox, Gtk::PACK_SHRINK, 0);
|
||||
customCurveBox->show_all ();
|
||||
|
||||
saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::savePressed) );
|
||||
loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::loadPressed) );
|
||||
saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
// NURBS curve
|
||||
NURBSCurveBox = new Gtk::HBox ();
|
||||
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||
NURBSCurve = Gtk::manage (new MyCurve ());
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//af->add (*customCurve);
|
||||
NURBSCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
NURBSCurve->setType (NURBS);
|
||||
//customCurve->set_tooltip_text (M("CURVEEDITOR_TOOLTIPMOVESPEED"));
|
||||
tmpb->pack_start (*NURBSCurve, true, false, 4);
|
||||
NURBSCurveBox->pack_start (*tmpb, true, true,4);
|
||||
|
||||
Gtk::VBox* NURBSbbox = Gtk::manage (new Gtk::VBox ());
|
||||
saveNURBS = Gtk::manage (new Gtk::Button ());
|
||||
saveNURBS->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
loadNURBS = Gtk::manage (new Gtk::Button ());
|
||||
loadNURBS->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
NURBSbbox->pack_end (*saveNURBS, Gtk::PACK_SHRINK, 4);
|
||||
NURBSbbox->pack_end (*loadNURBS, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
NURBSCurveBox->pack_end (*NURBSbbox, Gtk::PACK_SHRINK, 0);
|
||||
NURBSCurveBox->show_all ();
|
||||
|
||||
saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::savePressed) );
|
||||
loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::loadPressed) );
|
||||
saveNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
// parametric curve
|
||||
paramCurveBox = new Gtk::VBox ();
|
||||
paramCurve = Gtk::manage (new MyCurve ());
|
||||
Gtk::Table* paramctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
//Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//afp->add (*paramCurve);
|
||||
paramCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
paramCurve->setType (Parametric);
|
||||
shcSelector = Gtk::manage (new SHCSelector ());
|
||||
shcSelector->set_size_request (GRAPH_SIZE, 20);
|
||||
|
||||
paramctab->attach (*paramCurve, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 4, 4);
|
||||
paramctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, RADIUS+4, 0);
|
||||
|
||||
Gtk::HBox* tmpc = Gtk::manage (new Gtk::HBox ());
|
||||
tmpc->pack_start (*paramctab, true, false);
|
||||
|
||||
paramCurveBox->pack_start (*tmpc, true, true);
|
||||
|
||||
highlights = Gtk::manage (new Adjuster (M("CURVEEDITOR_HIGHLIGHTS"), -100, 100, 1, 0));
|
||||
lights = Gtk::manage (new Adjuster (M("CURVEEDITOR_LIGHTS"), -100, 100, 1, 0));
|
||||
darks = Gtk::manage (new Adjuster (M("CURVEEDITOR_DARKS"), -100, 100, 1, 0));
|
||||
shadows = Gtk::manage (new Adjuster (M("CURVEEDITOR_SHADOWS"), -100, 100, 1, 0));
|
||||
|
||||
Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ());
|
||||
|
||||
evhighlights->add (*highlights);
|
||||
evlights->add (*lights);
|
||||
evdarks->add (*darks);
|
||||
evshadows->add (*shadows);
|
||||
|
||||
paramCurveBox->pack_start (*Gtk::manage (new Gtk::HSeparator ()));
|
||||
paramCurveBox->pack_start (*evhighlights);
|
||||
paramCurveBox->pack_start (*evlights);
|
||||
paramCurveBox->pack_start (*evdarks);
|
||||
paramCurveBox->pack_start (*evshadows);
|
||||
paramCurveBox->show_all ();
|
||||
|
||||
customCurveBox->reference ();
|
||||
paramCurveBox->reference ();
|
||||
|
||||
customCurve->setCurveListener (this);
|
||||
NURBSCurve->setCurveListener (this);
|
||||
paramCurve->setCurveListener (this);
|
||||
shcSelector->setSHCListener (this);
|
||||
|
||||
highlights->setAdjusterListener (this);
|
||||
lights->setAdjusterListener (this);
|
||||
darks->setAdjusterListener (this);
|
||||
shadows->setAdjusterListener (this);
|
||||
|
||||
evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterEntered), 4));
|
||||
evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterEntered), 5));
|
||||
evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterEntered), 6));
|
||||
evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterEntered), 7));
|
||||
evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterLeft), 4));
|
||||
evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterLeft), 5));
|
||||
evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterLeft), 6));
|
||||
evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditorGroup::adjusterLeft), 7));
|
||||
|
||||
}
|
||||
|
||||
CurveEditorGroup::~CurveEditorGroup() {
|
||||
@@ -163,9 +43,8 @@ CurveEditorGroup::~CurveEditorGroup() {
|
||||
{
|
||||
delete *i;
|
||||
}
|
||||
delete customCurveBox;
|
||||
delete paramCurveBox;
|
||||
delete NURBSCurveBox;
|
||||
delete flatSubGroup;
|
||||
delete diagonalSubGroup;
|
||||
}
|
||||
|
||||
void CurveEditorGroup::hideCurrentCurve() {
|
||||
@@ -177,17 +56,22 @@ void CurveEditorGroup::hideCurrentCurve() {
|
||||
/*
|
||||
* Add a new curve to the curves list
|
||||
*/
|
||||
CurveEditor* CurveEditorGroup::addCurve(Glib::ustring curveLabel) {
|
||||
CurveEditor* newCE = new CurveEditor(curveLabel, this);
|
||||
|
||||
// Initialization of the new curve
|
||||
storeCurveValues(newCE, getCurveFromGUI(Spline));
|
||||
storeCurveValues(newCE, getCurveFromGUI(Parametric));
|
||||
storeCurveValues(newCE, getCurveFromGUI(NURBS));
|
||||
|
||||
// We add it to the curve editor list
|
||||
curveEditors.push_back(newCE);
|
||||
return newCE;
|
||||
CurveEditor* CurveEditorGroup::addCurve(CurveType cType, Glib::ustring curveLabel) {
|
||||
switch (cType) {
|
||||
case (CT_Diagonal):
|
||||
if (!diagonalSubGroup) {
|
||||
diagonalSubGroup = new DiagonalCurveEditorSubGroup(this);
|
||||
}
|
||||
return (CurveEditor*)diagonalSubGroup->addCurve(curveLabel);
|
||||
case (CT_Flat):
|
||||
if (!flatSubGroup) {
|
||||
flatSubGroup = new FlatCurveEditorSubGroup(this);
|
||||
}
|
||||
return (CurveEditor*)flatSubGroup->addCurve(curveLabel);
|
||||
default:
|
||||
return (CurveEditor*)NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -233,6 +117,12 @@ void CurveEditorGroup::newLine() {
|
||||
void CurveEditorGroup::curveListComplete() {
|
||||
newLine();
|
||||
|
||||
// Set the color provider
|
||||
if (cp) {
|
||||
if (flatSubGroup) flatSubGroup->setColorProvider(cp);
|
||||
if (diagonalSubGroup) diagonalSubGroup->setColorProvider(cp);
|
||||
}
|
||||
|
||||
// We check the length of the label ; if it contains only one char (':'), we set it to the right default string
|
||||
if (curveGroupLabel->get_label().size()==1)
|
||||
curveGroupLabel->set_label(M(curveEditors.size() > 1 ? "CURVEEDITOR_CURVES" : "CURVEEDITOR_CURVE") + ":");
|
||||
@@ -247,11 +137,11 @@ void CurveEditorGroup::curveListComplete() {
|
||||
*/
|
||||
void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) {
|
||||
// Same type : do nothing
|
||||
if (ce==displayedCurve && (CurveType)n==ce->selected)
|
||||
if (ce==displayedCurve && n==(int)ce->selected)
|
||||
return;
|
||||
|
||||
if ((CurveType)(n)<Unchanged)
|
||||
ce->selected = (CurveType)n;
|
||||
if (n<ce->subGroup->valUnchanged)
|
||||
ce->selected = n;
|
||||
|
||||
// The user selected a new type from a toggled off button
|
||||
if (ce!=displayedCurve)
|
||||
@@ -260,11 +150,11 @@ void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) {
|
||||
|
||||
// If the button was not pressed before
|
||||
if (!ce->curveType->get_active()) {
|
||||
storeDisplayedCurve();
|
||||
ce->subGroup->storeDisplayedCurve();
|
||||
// We set it pressed : it will emit the toggle on signal and update the GUI
|
||||
ce->curveType->set_active( n>Linear && n<Unchanged );
|
||||
if (n==Linear || n==Unchanged) {
|
||||
// Since we do not activate the curve when the user switch the a toggled off button to 'Linear', we have to
|
||||
ce->curveType->set_active( n>ce->subGroup->valLinear && n<ce->subGroup->valUnchanged );
|
||||
if (n==ce->subGroup->valLinear || n==ce->subGroup->valUnchanged) {
|
||||
// Since we do not activate the curve when the user switch the toggled off button to 'Linear', we have to
|
||||
// to call the curve listener manually, because 'curveChanged' uses displayedCurve...
|
||||
if (cl) {
|
||||
if (cl->isMulti())
|
||||
@@ -278,7 +168,7 @@ void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) {
|
||||
}
|
||||
else {
|
||||
// The button is already pressed so we switch the GUI ourselves
|
||||
switchGUI();
|
||||
ce->subGroup->switchGUI();
|
||||
curveChanged ();
|
||||
}
|
||||
}
|
||||
@@ -297,21 +187,21 @@ void CurveEditorGroup::curveTypeToggled(CurveEditor* ce) {
|
||||
|
||||
displayedCurve = ce;
|
||||
|
||||
if (ce->curveType->getSelected()==Unchanged) {
|
||||
if (ce->curveType->getSelected()==ce->subGroup->valUnchanged) {
|
||||
curveRestored = true;
|
||||
ce->curveType->setSelected(ce->selected);
|
||||
}
|
||||
|
||||
// then show this CurveEditor
|
||||
int ct = ce->curveType->getSelected();
|
||||
if (ct < Unchanged)
|
||||
restoreDisplayedHistogram();
|
||||
if (ct < ce->subGroup->valUnchanged)
|
||||
ce->subGroup->restoreDisplayedHistogram();
|
||||
}
|
||||
else {
|
||||
// The button is now released, so we have to hide this CurveEditor
|
||||
displayedCurve = 0;
|
||||
}
|
||||
switchGUI();
|
||||
ce->subGroup->switchGUI();
|
||||
|
||||
if (curveRestored)
|
||||
curveChanged ();
|
||||
@@ -319,49 +209,88 @@ void CurveEditorGroup::curveTypeToggled(CurveEditor* ce) {
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the editor widgets to the currently edited curve
|
||||
* Update the GUI if the given curveEditor is currently displayed
|
||||
*/
|
||||
void CurveEditorGroup::switchGUI() {
|
||||
void CurveEditorGroup::updateGUI (CurveEditor* ce) {
|
||||
if (!ce) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeEditor();
|
||||
// we update the curve type button to the corresponding curve type, only if it is not currently set to 'Unchanged'
|
||||
if (ce->curveType->getSelected()<ce->subGroup->valUnchanged)
|
||||
ce->curveType->setSelected(ce->selected);
|
||||
|
||||
// if not displayed or "unchanged" is selected, do not change gui
|
||||
if (ce==displayedCurve && ce->curveType->getSelected()<ce->subGroup->valUnchanged) {
|
||||
ce->subGroup->switchGUI();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from the outside to set the curve type & values
|
||||
*/
|
||||
void CurveEditorGroup::setCurveExternal (CurveEditor* ce, const std::vector<double>& c) {
|
||||
if (c.size()) {
|
||||
ce->subGroup->storeCurveValues(ce, c); // The new curve is saved in the CurveEditor
|
||||
(ce)->selected = c[0]; // We set the selected curve type in the CurveEditor to the one of the specified curve
|
||||
}
|
||||
updateGUI((CurveEditor*)ce); // And we update the GUI if necessary
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the user has modified the curve
|
||||
*/
|
||||
void CurveEditorGroup::curveChanged () {
|
||||
|
||||
displayedCurve->subGroup->storeDisplayedCurve();
|
||||
if (cl) {
|
||||
if (cl->isMulti())
|
||||
cl->curveChanged (displayedCurve);
|
||||
else
|
||||
cl->curveChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back method when the reset button is pressed :
|
||||
* reset the currently toggled on curve editor
|
||||
*/
|
||||
void CurveEditorGroup::curveResetPressed () {
|
||||
if (displayedCurve) {
|
||||
|
||||
// Initializing GUI values + repacking the appropriated widget
|
||||
//displayedCurve->typeconn.block(true);
|
||||
|
||||
switch((CurveType)(displayedCurve->curveType->getSelected())) {
|
||||
case (Spline):
|
||||
customCurve->setPoints (displayedCurve->customCurveEd);
|
||||
pack_start (*customCurveBox);
|
||||
break;
|
||||
case (Parametric):
|
||||
paramCurve->setPoints (displayedCurve->paramCurveEd);
|
||||
shcSelector->setPositions (
|
||||
displayedCurve->paramCurveEd.at(1),
|
||||
displayedCurve->paramCurveEd.at(2),
|
||||
displayedCurve->paramCurveEd.at(3)
|
||||
);
|
||||
highlights->setValue (displayedCurve->paramCurveEd.at(4));
|
||||
lights->setValue (displayedCurve->paramCurveEd.at(5));
|
||||
darks->setValue (displayedCurve->paramCurveEd.at(6));
|
||||
shadows->setValue (displayedCurve->paramCurveEd.at(7));
|
||||
pack_start (*paramCurveBox);
|
||||
break;
|
||||
case (NURBS):
|
||||
NURBSCurve->setPoints (displayedCurve->NURBSCurveEd);
|
||||
pack_start (*NURBSCurveBox);
|
||||
break;
|
||||
default: // (Linear, Unchanged)
|
||||
// ... do nothing
|
||||
break;
|
||||
if (displayedCurve->subGroup->curveReset(displayedCurve->selected)) {
|
||||
curveChanged();
|
||||
}
|
||||
|
||||
//displayedCurve->typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditorGroup::savePressed () {
|
||||
void CurveEditorGroup::setBatchMode (bool batchMode) {
|
||||
for (std::vector<CurveEditor*>::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) {
|
||||
(*i)->curveType->addEntry(argv0+"/images/curveType-unchanged.png", M("GENERAL_UNCHANGED"));
|
||||
(*i)->curveType->show();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) {
|
||||
if (uc) {
|
||||
// the user selected several thumbnails, so we hide the editors and set the curveEditor selection to 'Unchanged'
|
||||
//ce->typeconn.block(true);
|
||||
// we hide the editor widgets
|
||||
hideCurrentCurve();
|
||||
// the curve type selected option is set to unchanged
|
||||
ce->curveType->setSelected(ce->subGroup->valUnchanged);
|
||||
//ce->typeconn.block(false);
|
||||
}
|
||||
else {
|
||||
// we want it to use back the 'CurveEditor::setCurve' memorized in CurveEditor::tempCurve
|
||||
//ce->typeconn.block(true);
|
||||
// we switch back the curve type selected option to the one of the used curve
|
||||
ce->curveType->setSelected(ce->selected);
|
||||
updateGUI (ce);
|
||||
//ce->typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
Glib::ustring CurveEditorSubGroup::outputFile () {
|
||||
|
||||
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
|
||||
// if (options.multiUser)
|
||||
@@ -384,52 +313,37 @@ void CurveEditorGroup::savePressed () {
|
||||
|
||||
dialog.set_do_overwrite_confirmation (true);
|
||||
|
||||
int result = dialog.run();
|
||||
Glib::ustring fname;
|
||||
do {
|
||||
int result = dialog.run();
|
||||
|
||||
if (result==Gtk::RESPONSE_OK) {
|
||||
fname = dialog.get_filename();
|
||||
|
||||
std::string fname = dialog.get_filename();
|
||||
if (result==Gtk::RESPONSE_OK) {
|
||||
|
||||
if (getExtension (fname)!="rtc")
|
||||
fname = fname + ".rtc";
|
||||
if (getExtension (fname)!="rtc")
|
||||
fname = fname + ".rtc";
|
||||
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
|
||||
Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
|
||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
|
||||
int response = msgd.run ();
|
||||
if (response==Gtk::RESPONSE_NO)
|
||||
return;
|
||||
}
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
|
||||
Glib::ustring msg_ = Glib::ustring("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
|
||||
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
|
||||
int response = msgd.run ();
|
||||
if (response==Gtk::RESPONSE_YES)
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else {
|
||||
fname = "";
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
std::ofstream f (fname.c_str());
|
||||
std::vector<double> p = customCurve->getPoints ();
|
||||
|
||||
switch (displayedCurve->selected) {
|
||||
case Spline: // custom
|
||||
p = customCurve->getPoints ();
|
||||
break;
|
||||
case NURBS: // NURBS
|
||||
p = NURBSCurve->getPoints ();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int ix = 0;
|
||||
if (p[ix]==(double)(Linear))
|
||||
f << "Linear\n";
|
||||
else if (p[ix]==(double)(Spline))
|
||||
f << "Spline\n";
|
||||
else if (p[ix]==(double)(NURBS))
|
||||
f << "NURBS\n";
|
||||
ix++;
|
||||
for (unsigned int i=0; i<p.size()/2; i++, ix+=2)
|
||||
f << p[ix] << ' ' << p[ix+1] << std::endl;
|
||||
f.close ();
|
||||
}
|
||||
return fname;
|
||||
}
|
||||
|
||||
void CurveEditorGroup::loadPressed () {
|
||||
Glib::ustring CurveEditorSubGroup::inputFile () {
|
||||
|
||||
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN);
|
||||
|
||||
@@ -448,284 +362,12 @@ void CurveEditorGroup::loadPressed () {
|
||||
|
||||
int result = dialog.run();
|
||||
|
||||
Glib::ustring fname;
|
||||
if (result==Gtk::RESPONSE_OK) {
|
||||
std::ifstream f (dialog.get_filename().c_str());
|
||||
if (f) {
|
||||
std::vector<double> p;
|
||||
std::string s;
|
||||
f >> s;
|
||||
if (s=="Linear")
|
||||
p.push_back ((double)(Linear));
|
||||
else if (s=="Spline")
|
||||
p.push_back ((double)(Spline));
|
||||
else if (s=="NURBS")
|
||||
p.push_back ((double)(NURBS));
|
||||
else return;
|
||||
double x;
|
||||
while (f) {
|
||||
f >> x;
|
||||
if (f)
|
||||
p.push_back (x);
|
||||
}
|
||||
if (p[0] == (double)(Spline)) {
|
||||
customCurve->setPoints (p);
|
||||
customCurve->queue_draw ();
|
||||
customCurve->notifyListener ();
|
||||
}
|
||||
else if (p[0] == (double)(NURBS)) {
|
||||
NURBSCurve->setPoints (p);
|
||||
NURBSCurve->queue_draw ();
|
||||
NURBSCurve->notifyListener ();
|
||||
}
|
||||
}
|
||||
fname = dialog.get_filename();
|
||||
if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS))
|
||||
return fname;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the curves of the currently displayed type from the widgets to the CurveEditor object
|
||||
*/
|
||||
void CurveEditorGroup::storeDisplayedCurve() {
|
||||
if (displayedCurve) {
|
||||
switch (displayedCurve->selected) {
|
||||
case (Spline):
|
||||
storeCurveValues(displayedCurve, getCurveFromGUI(Spline));
|
||||
break;
|
||||
case (Parametric):
|
||||
storeCurveValues(displayedCurve, getCurveFromGUI(Parametric));
|
||||
break;
|
||||
case (NURBS):
|
||||
storeCurveValues(displayedCurve, getCurveFromGUI(NURBS));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the histogram to all types from the CurveEditor object to the widgets
|
||||
*/
|
||||
void CurveEditorGroup::restoreDisplayedHistogram() {
|
||||
if (displayedCurve) {
|
||||
paramCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
|
||||
customCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
|
||||
NURBSCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CurveEditorGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p) {
|
||||
if (p.size()) {
|
||||
CurveType t = (CurveType)p[0];
|
||||
for (int i=0; i<(int)p.size(); i++)
|
||||
|
||||
switch (t) {
|
||||
case (Spline):
|
||||
ce->customCurveEd = p;
|
||||
break;
|
||||
case (Parametric):
|
||||
ce->paramCurveEd = p;
|
||||
break;
|
||||
case (NURBS):
|
||||
ce->NURBSCurveEd = p;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the GUI if the given curveEditor is currently displayed
|
||||
*/
|
||||
void CurveEditorGroup::updateGUI (CurveEditor* ce) {
|
||||
if (!ce) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we update the curve type button to the corresponding curve type, only if it is not currently set to 'Unchanged'
|
||||
if (ce->curveType->getSelected()<Unchanged)
|
||||
ce->curveType->setSelected(ce->selected);
|
||||
|
||||
// if not displayed or "unchanged" is selected, do not change gui
|
||||
if (ce==displayedCurve && ce->curveType->getSelected()<Unchanged) {
|
||||
switchGUI();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from the outside to set the curve type & values
|
||||
*/
|
||||
void CurveEditorGroup::setCurveExternal (CurveEditor* ce, const std::vector<double>& c) {
|
||||
if (c.size()) {
|
||||
storeCurveValues(ce, c); // The new curve is saved in the CurveEditor
|
||||
ce->selected = (CurveType)(c[0]); // We set the selected curve type in the CurveEditor to the one of the specified curve
|
||||
}
|
||||
updateGUI(ce); // And we update the GUI if necessary
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to update the parametric curve graph with new slider values
|
||||
*/
|
||||
const std::vector<double> CurveEditorGroup::getCurveFromGUI (CurveType type) {
|
||||
switch (type) {
|
||||
case (Parametric): {
|
||||
std::vector<double> lcurve (8);
|
||||
lcurve[0] = (double)(Parametric);
|
||||
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
|
||||
lcurve[4] = highlights->getValue ();
|
||||
lcurve[5] = lights->getValue ();
|
||||
lcurve[6] = darks->getValue ();
|
||||
lcurve[7] = shadows->getValue ();
|
||||
return lcurve;
|
||||
}
|
||||
case (Spline):
|
||||
return customCurve->getPoints ();
|
||||
case (NURBS):
|
||||
return NURBSCurve->getPoints ();
|
||||
default: {
|
||||
// linear and other solutions
|
||||
std::vector<double> lcurve (1);
|
||||
lcurve[0] = (double)(Linear);
|
||||
return lcurve;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink the tree editor widgets from their parent box to hide them
|
||||
*/
|
||||
void CurveEditorGroup::removeEditor () {
|
||||
removeIfThere (this, customCurveBox, false);
|
||||
removeIfThere (this, paramCurveBox, false);
|
||||
removeIfThere (this, NURBSCurveBox, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the user has modified the curve
|
||||
*/
|
||||
void CurveEditorGroup::curveChanged () {
|
||||
|
||||
storeDisplayedCurve();
|
||||
if (cl) {
|
||||
if (cl->isMulti())
|
||||
cl->curveChanged (displayedCurve);
|
||||
else
|
||||
cl->curveChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener
|
||||
*/
|
||||
void CurveEditorGroup::shcChanged () {
|
||||
|
||||
paramCurve->setPoints (getCurveFromGUI(Parametric));
|
||||
storeDisplayedCurve();
|
||||
if (cl->isMulti())
|
||||
cl->curveChanged (displayedCurve);
|
||||
else
|
||||
cl->curveChanged ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener
|
||||
*/
|
||||
void CurveEditorGroup::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
paramCurve->setPoints (getCurveFromGUI(Parametric));
|
||||
storeDisplayedCurve();
|
||||
if (cl->isMulti())
|
||||
cl->curveChanged (displayedCurve);
|
||||
else
|
||||
cl->curveChanged ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the mouse is over a parametric curve's slider
|
||||
*/
|
||||
bool CurveEditorGroup::adjusterEntered (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = ac;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the mouse left the parametric curve's slider
|
||||
*/
|
||||
bool CurveEditorGroup::adjusterLeft (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = -1;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call back method when the reset button is pressed :
|
||||
* reset the currently toggled on curve editor
|
||||
*/
|
||||
void CurveEditorGroup::curveResetPressed() {
|
||||
if (displayedCurve) {
|
||||
switch (displayedCurve->selected) {
|
||||
case (NURBS) : // = Control cage
|
||||
NURBSCurve->reset ();
|
||||
curveChanged ();
|
||||
break;
|
||||
case (Spline) : // = Custom
|
||||
customCurve->reset ();
|
||||
curveChanged ();
|
||||
break;
|
||||
case (Parametric) :
|
||||
highlights->resetPressed();
|
||||
lights->resetPressed();
|
||||
darks->resetPressed();
|
||||
shadows->resetPressed();
|
||||
shcSelector->reset();
|
||||
paramCurve->reset ();
|
||||
curveChanged ();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditorGroup::setBatchMode (bool batchMode) {
|
||||
for (std::vector<CurveEditor*>::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) {
|
||||
(*i)->curveType->addEntry(argv0+"/images/curveType-unchanged.png", M("GENERAL_UNCHANGED"));
|
||||
(*i)->curveType->show();
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) {
|
||||
if (uc) {
|
||||
// the user selected several thumbnails, so we hide the editors and set the curveEditor selection to 'Unchanged'
|
||||
//ce->typeconn.block(true);
|
||||
// we hide the editor widgets
|
||||
hideCurrentCurve();
|
||||
// the curve type selected option is set to unchanged
|
||||
ce->curveType->setSelected(Unchanged);
|
||||
//ce->typeconn.block(false);
|
||||
}
|
||||
else {
|
||||
// we want it to use back the 'CurveEditor::setCurve' memorized in CurveEditor::tempCurve
|
||||
//ce->typeconn.block(true);
|
||||
// we switch back the curve type selected option to the one of the used curve
|
||||
ce->curveType->setSelected(ce->selected);
|
||||
updateGUI (ce);
|
||||
//ce->typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveEditorGroup::updateBackgroundHistogram (CurveEditor* ce) {
|
||||
if (ce==displayedCurve) {
|
||||
paramCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
customCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
NURBSCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
}
|
||||
fname = "";
|
||||
return fname;
|
||||
}
|
||||
|
||||
@@ -24,9 +24,14 @@
|
||||
#include <string>
|
||||
#include <guiutils.h>
|
||||
#include <mycurve.h>
|
||||
#include <myflatcurve.h>
|
||||
#include <mydiagonalcurve.h>
|
||||
#include <shcselector.h>
|
||||
#include <adjuster.h>
|
||||
#include <curveeditor.h>
|
||||
|
||||
class CurveEditor;
|
||||
class DiagonalCurveEditorSubGroup;
|
||||
class FlatCurveEditorSubGroup;
|
||||
|
||||
/*
|
||||
* This class handle the curve widgets, shared between any number curve
|
||||
@@ -34,75 +39,76 @@
|
||||
* - to start a new line of curve button, use the 'newLine' method
|
||||
* - if you add more than one curve, you must add a "CurveEditor* ce" parameter to your listener
|
||||
*/
|
||||
class CurveEditorGroup : public Gtk::VBox, public CurveListener, public SHCListener, public AdjusterListener {
|
||||
class CurveEditorGroup : public Gtk::VBox, public CurveListener {
|
||||
|
||||
private:
|
||||
friend class CurveEditor;
|
||||
friend class CurveEditorSubGroup;
|
||||
friend class DiagonalCurveEditorSubGroup;
|
||||
friend class FlatCurveEditorSubGroup;
|
||||
|
||||
protected:
|
||||
Gtk::Label* curveGroupLabel;
|
||||
|
||||
Gtk::Button* curve_reset;
|
||||
Gtk::HBox* customCurveBox;
|
||||
Gtk::VBox* paramCurveBox;
|
||||
Gtk::HBox* NURBSCurveBox;
|
||||
|
||||
MyCurve* customCurve;
|
||||
MyCurve* paramCurve;
|
||||
MyCurve* NURBSCurve;
|
||||
|
||||
SHCSelector* shcSelector;
|
||||
Adjuster* highlights;
|
||||
Adjuster* lights;
|
||||
Adjuster* darks;
|
||||
Adjuster* shadows;
|
||||
|
||||
Gtk::Button* saveCustom;
|
||||
Gtk::Button* loadCustom;
|
||||
Gtk::Button* saveNURBS;
|
||||
Gtk::Button* loadNURBS;
|
||||
|
||||
CurveListener* cl;
|
||||
|
||||
CurveType curveTypeIx;
|
||||
unsigned int numberOfPackedCurve;
|
||||
|
||||
std::vector<CurveEditor*> curveEditors;
|
||||
CurveEditor* displayedCurve;
|
||||
FlatCurveEditorSubGroup* flatSubGroup;
|
||||
DiagonalCurveEditorSubGroup* diagonalSubGroup;
|
||||
|
||||
int activeParamControl;
|
||||
CurveListener* cl;
|
||||
ColorProvider* cp;
|
||||
|
||||
void curveResetPressed ();
|
||||
void curveTypeToggled ();
|
||||
void typeSelectionChanged (CurveEditor* ce, int n);
|
||||
void curveTypeToggled (CurveEditor* ce);
|
||||
void savePressed ();
|
||||
void loadPressed ();
|
||||
void hideCurrentCurve ();
|
||||
void setUnChanged (bool uc, CurveEditor* ce);
|
||||
void storeDisplayedCurve ();
|
||||
void restoreDisplayedHistogram();
|
||||
void storeCurveValues (CurveEditor* ce, const std::vector<double>& p);
|
||||
void typeSelectionChanged (int n);
|
||||
void switchGUI();
|
||||
void updateGUI (CurveEditor* ce);
|
||||
void removeEditor ();
|
||||
void curveChanged ();
|
||||
void shcChanged ();
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
bool adjusterEntered (GdkEventCrossing* ev, int ac);
|
||||
bool adjusterLeft (GdkEventCrossing* ev, int ac);
|
||||
const std::vector<double> getCurveFromGUI (CurveType type);
|
||||
void updateBackgroundHistogram (CurveEditor* ce);
|
||||
unsigned int numberOfPackedCurve;
|
||||
|
||||
public:
|
||||
friend class CurveEditor;
|
||||
CurveEditorGroup(Glib::ustring groupLabel = "");
|
||||
~CurveEditorGroup();
|
||||
CurveEditor* addCurve(Glib::ustring curveLabel = "");
|
||||
void newLine();
|
||||
void curveListComplete();
|
||||
void setBatchMode (bool batchMode);
|
||||
void setCurveExternal (CurveEditor* ce, const std::vector<double>& c);
|
||||
//void on_realize ();
|
||||
void setCurveListener (CurveListener* l) { cl = l; }
|
||||
void setColorProvider (ColorProvider* p) { cp = p; }
|
||||
CurveEditor* getDisplayedCurve () { return displayedCurve; }
|
||||
//void on_realize ();
|
||||
CurveEditor* addCurve(CurveType cType, Glib::ustring curveLabel);
|
||||
|
||||
protected:
|
||||
//void curveTypeToggled ();
|
||||
void curveTypeToggled (CurveEditor* ce);
|
||||
//void typeSelectionChanged (int n);
|
||||
void typeSelectionChanged (CurveEditor* ce, int n);
|
||||
void hideCurrentCurve ();
|
||||
void updateGUI (CurveEditor* ce);
|
||||
void curveResetPressed ();
|
||||
void curveChanged ();
|
||||
void setUnChanged (bool uc, CurveEditor* ce);
|
||||
};
|
||||
|
||||
class CurveEditorSubGroup {
|
||||
|
||||
friend class CurveEditorGroup;
|
||||
|
||||
protected:
|
||||
int valLinear;
|
||||
int valUnchanged;
|
||||
CurveEditorGroup *parent;
|
||||
|
||||
public:
|
||||
int getValUnchanged() { return valUnchanged; }
|
||||
virtual void updateBackgroundHistogram (CurveEditor* ce) {}
|
||||
virtual void setColorProvider (ColorProvider* p) = 0;
|
||||
|
||||
protected:
|
||||
Glib::ustring outputFile ();
|
||||
Glib::ustring inputFile ();
|
||||
|
||||
virtual bool curveReset (int cType) = 0; // Reset a curve editor, return TRUE if successful (curve changed)
|
||||
virtual void storeCurveValues (CurveEditor* ce, const std::vector<double>& p) = 0;
|
||||
virtual void storeDisplayedCurve () = 0;
|
||||
virtual void restoreDisplayedHistogram() {};
|
||||
virtual void switchGUI() = 0;
|
||||
virtual void removeEditor () = 0;
|
||||
virtual const std::vector<double> getCurveFromGUI (int type) = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
474
rtgui/diagonalcurveeditorsubgroup.cc
Normal file
474
rtgui/diagonalcurveeditorsubgroup.cc
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <guiutils.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <guiutils.h>
|
||||
#include <mycurve.h>
|
||||
#include <shcselector.h>
|
||||
#include <adjuster.h>
|
||||
#include <mycurve.h>
|
||||
#include <curveeditor.h>
|
||||
#include <diagonalcurveeditorsubgroup.h>
|
||||
|
||||
DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt) {
|
||||
|
||||
valLinear = (int)DCT_Linear;
|
||||
valUnchanged = (int)DCT_Unchanged;
|
||||
parent = prt;
|
||||
|
||||
activeParamControl = -1;
|
||||
|
||||
// custom curve
|
||||
customCurveBox = new Gtk::HBox ();
|
||||
Gtk::HBox* tmpa = Gtk::manage (new Gtk::HBox ());
|
||||
customCurve = Gtk::manage (new MyDiagonalCurve ());
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
customCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
customCurve->setType (DCT_Spline);
|
||||
//customCurve->set_tooltip_text (M("CURVEEDITOR_TOOLTIPMOVESPEED"));
|
||||
tmpa->pack_start (*customCurve, true, false, 4);
|
||||
customCurveBox->pack_start (*tmpa, true, true,4);
|
||||
|
||||
Gtk::VBox* custombbox = Gtk::manage (new Gtk::VBox ());
|
||||
saveCustom = Gtk::manage (new Gtk::Button ());
|
||||
saveCustom->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
loadCustom = Gtk::manage (new Gtk::Button ());
|
||||
loadCustom->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
custombbox->pack_end (*saveCustom, Gtk::PACK_SHRINK, 4);
|
||||
custombbox->pack_end (*loadCustom, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
customCurveBox->pack_end (*custombbox, Gtk::PACK_SHRINK, 0);
|
||||
customCurveBox->show_all ();
|
||||
|
||||
saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) );
|
||||
loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
|
||||
saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
// NURBS curve
|
||||
NURBSCurveBox = new Gtk::HBox ();
|
||||
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||
NURBSCurve = Gtk::manage (new MyDiagonalCurve ());
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//af->add (*customCurve);
|
||||
NURBSCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
NURBSCurve->setType (DCT_NURBS);
|
||||
//customCurve->set_tooltip_text (M("CURVEEDITOR_TOOLTIPMOVESPEED"));
|
||||
tmpb->pack_start (*NURBSCurve, true, false, 4);
|
||||
NURBSCurveBox->pack_start (*tmpb, true, true,4);
|
||||
|
||||
Gtk::VBox* NURBSbbox = Gtk::manage (new Gtk::VBox ());
|
||||
saveNURBS = Gtk::manage (new Gtk::Button ());
|
||||
saveNURBS->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
loadNURBS = Gtk::manage (new Gtk::Button ());
|
||||
loadNURBS->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
NURBSbbox->pack_end (*saveNURBS, Gtk::PACK_SHRINK, 4);
|
||||
NURBSbbox->pack_end (*loadNURBS, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
NURBSCurveBox->pack_end (*NURBSbbox, Gtk::PACK_SHRINK, 0);
|
||||
NURBSCurveBox->show_all ();
|
||||
|
||||
saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) );
|
||||
loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
|
||||
saveNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
// parametric curve
|
||||
paramCurveBox = new Gtk::VBox ();
|
||||
paramCurve = Gtk::manage (new MyDiagonalCurve ());
|
||||
Gtk::Table* paramctab = Gtk::manage (new Gtk::Table (2,1));
|
||||
//Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
paramCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||
paramCurve->setType (DCT_Parametric);
|
||||
shcSelector = Gtk::manage (new SHCSelector ());
|
||||
shcSelector->set_size_request (GRAPH_SIZE, 20);
|
||||
|
||||
paramctab->attach (*paramCurve, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 4, 4);
|
||||
paramctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, RADIUS+4, 0);
|
||||
|
||||
Gtk::HBox* tmpc = Gtk::manage (new Gtk::HBox ());
|
||||
tmpc->pack_start (*paramctab, true, false);
|
||||
|
||||
paramCurveBox->pack_start (*tmpc, true, true);
|
||||
|
||||
highlights = Gtk::manage (new Adjuster (M("CURVEEDITOR_HIGHLIGHTS"), -100, 100, 1, 0));
|
||||
lights = Gtk::manage (new Adjuster (M("CURVEEDITOR_LIGHTS"), -100, 100, 1, 0));
|
||||
darks = Gtk::manage (new Adjuster (M("CURVEEDITOR_DARKS"), -100, 100, 1, 0));
|
||||
shadows = Gtk::manage (new Adjuster (M("CURVEEDITOR_SHADOWS"), -100, 100, 1, 0));
|
||||
|
||||
Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ());
|
||||
Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ());
|
||||
|
||||
evhighlights->add (*highlights);
|
||||
evlights->add (*lights);
|
||||
evdarks->add (*darks);
|
||||
evshadows->add (*shadows);
|
||||
|
||||
paramCurveBox->pack_start (*Gtk::manage (new Gtk::HSeparator ()));
|
||||
paramCurveBox->pack_start (*evhighlights);
|
||||
paramCurveBox->pack_start (*evlights);
|
||||
paramCurveBox->pack_start (*evdarks);
|
||||
paramCurveBox->pack_start (*evshadows);
|
||||
paramCurveBox->show_all ();
|
||||
|
||||
customCurveBox->reference ();
|
||||
paramCurveBox->reference ();
|
||||
|
||||
customCurve->setCurveListener (parent); // Send the message directly to the parent
|
||||
NURBSCurve->setCurveListener (parent);
|
||||
paramCurve->setCurveListener (parent);
|
||||
shcSelector->setSHCListener (this);
|
||||
|
||||
highlights->setAdjusterListener (this);
|
||||
lights->setAdjusterListener (this);
|
||||
darks->setAdjusterListener (this);
|
||||
shadows->setAdjusterListener (this);
|
||||
|
||||
evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
|
||||
evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 4));
|
||||
evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 5));
|
||||
evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 6));
|
||||
evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 7));
|
||||
evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 4));
|
||||
evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 5));
|
||||
evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 6));
|
||||
evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 7));
|
||||
}
|
||||
|
||||
DiagonalCurveEditorSubGroup::~DiagonalCurveEditorSubGroup() {
|
||||
delete customCurveBox;
|
||||
delete paramCurveBox;
|
||||
delete NURBSCurveBox;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new curve to the curves list
|
||||
*/
|
||||
DiagonalCurveEditor* DiagonalCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) {
|
||||
DiagonalCurveEditor* newCE = new DiagonalCurveEditor(curveLabel, parent, this);
|
||||
|
||||
// Initialization of the new curve
|
||||
storeCurveValues(newCE, getCurveFromGUI(DCT_Spline));
|
||||
storeCurveValues(newCE, getCurveFromGUI(DCT_Parametric));
|
||||
storeCurveValues(newCE, getCurveFromGUI(DCT_NURBS));
|
||||
|
||||
// We add it to the curve editor list
|
||||
parent->curveEditors.push_back(newCE);
|
||||
return newCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the editor widgets to the currently edited curve
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::switchGUI() {
|
||||
|
||||
removeEditor();
|
||||
|
||||
DiagonalCurveEditor* dCurve = (DiagonalCurveEditor*)(parent->displayedCurve);
|
||||
|
||||
if (dCurve) {
|
||||
|
||||
// Initializing GUI values + repacking the appropriated widget
|
||||
//dCurve->typeconn.block(true);
|
||||
|
||||
|
||||
switch((DiagonalCurveType)(dCurve->curveType->getSelected())) {
|
||||
case (DCT_Spline):
|
||||
customCurve->setPoints (dCurve->customCurveEd);
|
||||
parent->pack_start (*customCurveBox);
|
||||
break;
|
||||
case (DCT_Parametric):
|
||||
paramCurve->setPoints (dCurve->paramCurveEd);
|
||||
shcSelector->setPositions (
|
||||
dCurve->paramCurveEd.at(1),
|
||||
dCurve->paramCurveEd.at(2),
|
||||
dCurve->paramCurveEd.at(3)
|
||||
);
|
||||
highlights->setValue (dCurve->paramCurveEd.at(4));
|
||||
lights->setValue (dCurve->paramCurveEd.at(5));
|
||||
darks->setValue (dCurve->paramCurveEd.at(6));
|
||||
shadows->setValue (dCurve->paramCurveEd.at(7));
|
||||
parent->pack_start (*paramCurveBox);
|
||||
break;
|
||||
case (DCT_NURBS):
|
||||
NURBSCurve->setPoints (dCurve->NURBSCurveEd);
|
||||
parent->pack_start (*NURBSCurveBox);
|
||||
break;
|
||||
default: // (DCT_Linear, DCT_Unchanged)
|
||||
// ... do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
//dCurve->typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
void DiagonalCurveEditorSubGroup::savePressed () {
|
||||
|
||||
Glib::ustring fname = outputFile();
|
||||
if (fname.size()) {
|
||||
std::ofstream f (fname.c_str());
|
||||
std::vector<double> p;
|
||||
//std::vector<double> p = customCurve->getPoints ();
|
||||
|
||||
switch (parent->displayedCurve->selected) {
|
||||
case DCT_Spline: // custom
|
||||
p = customCurve->getPoints ();
|
||||
break;
|
||||
case DCT_NURBS: // NURBS
|
||||
p = NURBSCurve->getPoints ();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int ix = 0;
|
||||
if (p[ix]==(double)(DCT_Linear))
|
||||
f << "Linear\n";
|
||||
else if (p[ix]==(double)(DCT_Spline))
|
||||
f << "Spline\n";
|
||||
else if (p[ix]==(double)(DCT_NURBS))
|
||||
f << "NURBS\n";
|
||||
ix++;
|
||||
for (unsigned int i=0; i<p.size()/2; i++, ix+=2)
|
||||
f << p[ix] << ' ' << p[ix+1] << std::endl;
|
||||
f.close ();
|
||||
}
|
||||
}
|
||||
|
||||
void DiagonalCurveEditorSubGroup::loadPressed () {
|
||||
|
||||
Glib::ustring fname = inputFile();
|
||||
if (fname.size()) {
|
||||
std::ifstream f (fname.c_str());
|
||||
if (f) {
|
||||
std::vector<double> p;
|
||||
std::string s;
|
||||
f >> s;
|
||||
if (s=="Linear")
|
||||
p.push_back ((double)(DCT_Linear));
|
||||
else if (s=="Spline")
|
||||
p.push_back ((double)(DCT_Spline));
|
||||
else if (s=="NURBS")
|
||||
p.push_back ((double)(DCT_NURBS));
|
||||
else return;
|
||||
double x;
|
||||
while (f) {
|
||||
f >> x;
|
||||
if (f)
|
||||
p.push_back (x);
|
||||
}
|
||||
if (p[0] == (double)(DCT_Spline)) {
|
||||
customCurve->setPoints (p);
|
||||
customCurve->queue_draw ();
|
||||
customCurve->notifyListener ();
|
||||
}
|
||||
else if (p[0] == (double)(DCT_NURBS)) {
|
||||
NURBSCurve->setPoints (p);
|
||||
NURBSCurve->queue_draw ();
|
||||
NURBSCurve->notifyListener ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the curves of the currently displayed type from the widgets to the CurveEditor object
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::storeDisplayedCurve() {
|
||||
if (parent->displayedCurve) {
|
||||
switch (parent->displayedCurve->selected) {
|
||||
case (DCT_Spline):
|
||||
storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Spline));
|
||||
break;
|
||||
case (DCT_Parametric):
|
||||
storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Parametric));
|
||||
break;
|
||||
case (DCT_NURBS):
|
||||
storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_NURBS));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the histogram to all types from the CurveEditor object to the widgets
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::restoreDisplayedHistogram() {
|
||||
if (parent->displayedCurve) {
|
||||
paramCurve->updateBackgroundHistogram (parent->displayedCurve->bgHistValid ? parent->displayedCurve->histogram : NULL);
|
||||
customCurve->updateBackgroundHistogram (parent->displayedCurve->bgHistValid ? parent->displayedCurve->histogram : NULL);
|
||||
NURBSCurve->updateBackgroundHistogram (parent->displayedCurve->bgHistValid ? parent->displayedCurve->histogram : NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DiagonalCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p) {
|
||||
if (p.size()) {
|
||||
DiagonalCurveType t = (DiagonalCurveType)p[0];
|
||||
for (int i=0; i<(int)p.size(); i++)
|
||||
|
||||
switch (t) {
|
||||
case (DCT_Spline):
|
||||
((DiagonalCurveEditor*)ce)->customCurveEd = p;
|
||||
break;
|
||||
case (DCT_Parametric):
|
||||
((DiagonalCurveEditor*)ce)->paramCurveEd = p;
|
||||
break;
|
||||
case (DCT_NURBS):
|
||||
((DiagonalCurveEditor*)ce)->NURBSCurveEd = p;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to update the parametric curve graph with new slider values
|
||||
*/
|
||||
const std::vector<double> DiagonalCurveEditorSubGroup::getCurveFromGUI (int type) {
|
||||
switch ((DiagonalCurveType)type) {
|
||||
case (DCT_Parametric): {
|
||||
std::vector<double> lcurve (8);
|
||||
lcurve[0] = (double)(DCT_Parametric);
|
||||
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
|
||||
lcurve[4] = highlights->getValue ();
|
||||
lcurve[5] = lights->getValue ();
|
||||
lcurve[6] = darks->getValue ();
|
||||
lcurve[7] = shadows->getValue ();
|
||||
return lcurve;
|
||||
}
|
||||
case (DCT_Spline):
|
||||
return customCurve->getPoints ();
|
||||
case (DCT_NURBS):
|
||||
return NURBSCurve->getPoints ();
|
||||
default: {
|
||||
// linear and other solutions
|
||||
std::vector<double> lcurve (1);
|
||||
lcurve[0] = (double)(DCT_Linear);
|
||||
return lcurve;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink the tree editor widgets from their parent box to hide them
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::removeEditor () {
|
||||
removeIfThere (parent, customCurveBox, false);
|
||||
removeIfThere (parent, paramCurveBox, false);
|
||||
removeIfThere (parent, NURBSCurveBox, false);
|
||||
}
|
||||
|
||||
bool DiagonalCurveEditorSubGroup::curveReset(int cType) {
|
||||
switch ((DiagonalCurveType) cType) {
|
||||
case (DCT_NURBS) : // = Control cage
|
||||
NURBSCurve->reset ();
|
||||
return true;
|
||||
break;
|
||||
case (DCT_Spline) : // = Custom
|
||||
customCurve->reset ();
|
||||
return true;
|
||||
break;
|
||||
case (DCT_Parametric) :
|
||||
highlights->resetPressed();
|
||||
lights->resetPressed();
|
||||
darks->resetPressed();
|
||||
shadows->resetPressed();
|
||||
shcSelector->reset();
|
||||
paramCurve->reset ();
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void DiagonalCurveEditorSubGroup::setColorProvider (ColorProvider* p) {
|
||||
customCurve->setColorProvider(p);
|
||||
paramCurve->setColorProvider(p);
|
||||
NURBSCurve->setColorProvider(p);
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::shcChanged () {
|
||||
|
||||
paramCurve->setPoints (getCurveFromGUI(DCT_Parametric));
|
||||
storeDisplayedCurve();
|
||||
parent->curveChanged ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener
|
||||
*/
|
||||
void DiagonalCurveEditorSubGroup::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
paramCurve->setPoints (getCurveFromGUI(DCT_Parametric));
|
||||
storeDisplayedCurve();
|
||||
parent->curveChanged ();
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the mouse is over a parametric curve's slider
|
||||
*/
|
||||
bool DiagonalCurveEditorSubGroup::adjusterEntered (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = ac;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Listener called when the mouse left the parametric curve's slider
|
||||
*/
|
||||
bool DiagonalCurveEditorSubGroup::adjusterLeft (GdkEventCrossing* ev, int ac) {
|
||||
|
||||
if (ev->detail != GDK_NOTIFY_INFERIOR) {
|
||||
activeParamControl = -1;
|
||||
paramCurve->setActiveParam (activeParamControl);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DiagonalCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce) {
|
||||
if (ce==parent->displayedCurve) {
|
||||
paramCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
customCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
NURBSCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
|
||||
}
|
||||
}
|
||||
77
rtgui/diagonalcurveeditorsubgroup.h
Normal file
77
rtgui/diagonalcurveeditorsubgroup.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _DIAGONALCURVEEDITORSUBGROUP_
|
||||
#define _DIAGONALCURVEEDITORSUBGROUP_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <curveeditorgroup.h>
|
||||
|
||||
class DiagonalCurveEditor;
|
||||
|
||||
class DiagonalCurveEditorSubGroup : public CurveEditorSubGroup, public SHCListener, public AdjusterListener {
|
||||
|
||||
friend class DiagonalCurveEditor;
|
||||
|
||||
private:
|
||||
Gtk::HBox* customCurveBox;
|
||||
Gtk::VBox* paramCurveBox;
|
||||
Gtk::HBox* NURBSCurveBox;
|
||||
|
||||
MyDiagonalCurve* customCurve;
|
||||
MyDiagonalCurve* paramCurve;
|
||||
MyDiagonalCurve* NURBSCurve;
|
||||
|
||||
SHCSelector* shcSelector;
|
||||
Adjuster* highlights;
|
||||
Adjuster* lights;
|
||||
Adjuster* darks;
|
||||
Adjuster* shadows;
|
||||
|
||||
Gtk::Button* saveCustom;
|
||||
Gtk::Button* loadCustom;
|
||||
Gtk::Button* saveNURBS;
|
||||
Gtk::Button* loadNURBS;
|
||||
|
||||
int activeParamControl;
|
||||
|
||||
public:
|
||||
DiagonalCurveEditorSubGroup(CurveEditorGroup* prt);
|
||||
~DiagonalCurveEditorSubGroup();
|
||||
|
||||
DiagonalCurveEditor* addCurve(Glib::ustring curveLabel = "");
|
||||
virtual void updateBackgroundHistogram (CurveEditor* ce);
|
||||
virtual void setColorProvider (ColorProvider* p);
|
||||
|
||||
private:
|
||||
void storeCurveValues (CurveEditor* ce, const std::vector<double>& p);
|
||||
void storeDisplayedCurve ();
|
||||
void restoreDisplayedHistogram ();
|
||||
void savePressed ();
|
||||
void loadPressed ();
|
||||
void switchGUI();
|
||||
bool curveReset (int cType);
|
||||
void removeEditor ();
|
||||
const std::vector<double> getCurveFromGUI (int type);
|
||||
void shcChanged ();
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
bool adjusterEntered (GdkEventCrossing* ev, int ac);
|
||||
bool adjusterLeft (GdkEventCrossing* ev, int ac);
|
||||
};
|
||||
|
||||
#endif
|
||||
272
rtgui/flatcurveeditorsubgroup.cc
Normal file
272
rtgui/flatcurveeditorsubgroup.cc
Normal file
@@ -0,0 +1,272 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <guiutils.h>
|
||||
#include <multilangmgr.h>
|
||||
#include <guiutils.h>
|
||||
#include <mycurve.h>
|
||||
#include <shcselector.h>
|
||||
#include <adjuster.h>
|
||||
#include <mycurve.h>
|
||||
#include <curveeditor.h>
|
||||
#include <flatcurveeditorsubgroup.h>
|
||||
|
||||
FlatCurveEditorSubGroup::FlatCurveEditorSubGroup (CurveEditorGroup* prt) {
|
||||
|
||||
valLinear = (int)FCT_Linear;
|
||||
valUnchanged = (int)FCT_Unchanged;
|
||||
parent = prt;
|
||||
|
||||
// ControlPoints curve
|
||||
CPointsCurveBox = new Gtk::HBox ();
|
||||
//Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||
CPointsCurve = Gtk::manage (new MyFlatCurve ());
|
||||
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||
//CPointsCurve->set_size_request (GRAPH_SIZE+2*RADIUS+1, GRAPH_SIZE+2*RADIUS+1);
|
||||
CPointsCurve->setType (FCT_MinMaxCPoints);
|
||||
//tmpb->pack_start (*CPointsCurve, Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
CPointsCurveBox->pack_start (*CPointsCurve, Gtk::PACK_EXPAND_WIDGET,4);
|
||||
//CPointsCurveBox->pack_start (*tmpb, Gtk::PACK_EXPAND_WIDGET,4);
|
||||
|
||||
Gtk::VBox* CPointsbbox = Gtk::manage (new Gtk::VBox ());
|
||||
saveCPoints = Gtk::manage (new Gtk::Button ());
|
||||
saveCPoints->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-save"), Gtk::ICON_SIZE_BUTTON)));
|
||||
loadCPoints = Gtk::manage (new Gtk::Button ());
|
||||
loadCPoints->add (*Gtk::manage (new Gtk::Image (Gtk::StockID("gtk-open"), Gtk::ICON_SIZE_BUTTON)));
|
||||
|
||||
CPointsbbox->pack_end (*saveCPoints, Gtk::PACK_SHRINK, 4);
|
||||
CPointsbbox->pack_end (*loadCPoints, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
CPointsCurveBox->pack_end (*CPointsbbox, Gtk::PACK_SHRINK, 0);
|
||||
CPointsCurveBox->show_all ();
|
||||
|
||||
saveCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::savePressed) );
|
||||
loadCPoints->signal_clicked().connect( sigc::mem_fun(*this, &FlatCurveEditorSubGroup::loadPressed) );
|
||||
saveCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
|
||||
loadCPoints->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
|
||||
|
||||
CPointsCurve->setCurveListener (parent); // Send the message directly to the parent
|
||||
}
|
||||
|
||||
FlatCurveEditorSubGroup::~FlatCurveEditorSubGroup() {
|
||||
delete CPointsCurveBox;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new curve to the curves list
|
||||
*/
|
||||
FlatCurveEditor* FlatCurveEditorSubGroup::addCurve(Glib::ustring curveLabel) {
|
||||
FlatCurveEditor* newCE = new FlatCurveEditor(curveLabel, parent, this);
|
||||
|
||||
// Initialization of the new curve
|
||||
storeCurveValues(newCE, getCurveFromGUI(FCT_MinMaxCPoints));
|
||||
|
||||
// We add it to the curve editor list
|
||||
parent->curveEditors.push_back(newCE);
|
||||
return newCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch the editor widgets to the currently edited curve
|
||||
*/
|
||||
void FlatCurveEditorSubGroup::switchGUI() {
|
||||
|
||||
removeEditor();
|
||||
|
||||
FlatCurveEditor* dCurve = (FlatCurveEditor*)(parent->displayedCurve);
|
||||
|
||||
if (dCurve) {
|
||||
|
||||
// Initializing GUI values + repacking the appropriated widget
|
||||
//dCurve->typeconn.block(true);
|
||||
|
||||
switch((FlatCurveType)(dCurve->curveType->getSelected())) {
|
||||
case (FCT_MinMaxCPoints):
|
||||
CPointsCurve->setPoints (dCurve->controlPointsCurveEd);
|
||||
parent->pack_start (*CPointsCurveBox);
|
||||
break;
|
||||
default: // (DCT_Linear, DCT_Unchanged)
|
||||
// ... do nothing
|
||||
break;
|
||||
}
|
||||
|
||||
//dCurve->typeconn.block(false);
|
||||
}
|
||||
}
|
||||
|
||||
void FlatCurveEditorSubGroup::savePressed () {
|
||||
|
||||
Glib::ustring fname = outputFile();
|
||||
if (fname.size()) {
|
||||
std::ofstream f (fname.c_str());
|
||||
std::vector<double> p;
|
||||
//std::vector<double> p = customCurve->getPoints ();
|
||||
|
||||
switch (parent->displayedCurve->selected) {
|
||||
case FCT_MinMaxCPoints: // Control points
|
||||
p = CPointsCurve->getPoints ();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
int ix = 0;
|
||||
if (p[ix]==(double)(FCT_Linear))
|
||||
f << "Linear\n";
|
||||
else if (p[ix]==(double)(FCT_MinMaxCPoints))
|
||||
f << "ControlPoints\n";
|
||||
ix++;
|
||||
for (unsigned int i=0; i<p.size()/2; i++, ix+=2)
|
||||
f << p[ix] << ' ' << p[ix+1] << std::endl;
|
||||
f.close ();
|
||||
}
|
||||
}
|
||||
|
||||
void FlatCurveEditorSubGroup::loadPressed () {
|
||||
|
||||
Glib::ustring fname = inputFile();
|
||||
if (fname.size()) {
|
||||
std::ifstream f (fname.c_str());
|
||||
if (f) {
|
||||
std::vector<double> p;
|
||||
std::string s;
|
||||
f >> s;
|
||||
if (s=="Linear")
|
||||
p.push_back ((double)(FCT_Linear));
|
||||
else if (s=="ControlPoints")
|
||||
p.push_back ((double)(FCT_MinMaxCPoints));
|
||||
else return;
|
||||
double x;
|
||||
while (f) {
|
||||
f >> x;
|
||||
if (f)
|
||||
p.push_back (x);
|
||||
}
|
||||
if (p[0] == (double)(FCT_MinMaxCPoints)) {
|
||||
CPointsCurve->setPoints (p);
|
||||
CPointsCurve->queue_draw ();
|
||||
CPointsCurve->notifyListener ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the curves of the currently displayed type from the widgets to the CurveEditor object
|
||||
*/
|
||||
void FlatCurveEditorSubGroup::storeDisplayedCurve() {
|
||||
if (parent->displayedCurve) {
|
||||
switch (parent->displayedCurve->selected) {
|
||||
/*case (FCT_Parametric):
|
||||
storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_Parametric));
|
||||
break;*/
|
||||
case (FCT_MinMaxCPoints):
|
||||
storeCurveValues(parent->displayedCurve, getCurveFromGUI(FCT_MinMaxCPoints));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Restore the histogram to all types from the CurveEditor object to the widgets
|
||||
*/
|
||||
void FlatCurveEditorSubGroup::restoreDisplayedHistogram() {
|
||||
if (parent->displayedCurve) {
|
||||
//paramCurve->updateBackgroundHistogram (parent->displayedCurve->bgHistValid ? parent->displayedCurve->histogram : NULL);
|
||||
CPointsCurve->updateBackgroundHistogram (parent->displayedCurve->bgHistValid ? parent->displayedCurve->histogram : NULL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FlatCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p) {
|
||||
if (p.size()) {
|
||||
FlatCurveType t = (FlatCurveType)p[0];
|
||||
for (int i=0; i<(int)p.size(); i++)
|
||||
|
||||
switch (t) {
|
||||
case (FCT_MinMaxCPoints):
|
||||
((FlatCurveEditor*)ce)->controlPointsCurveEd = p;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to update the parametric curve graph with new slider values
|
||||
*/
|
||||
const std::vector<double> FlatCurveEditorSubGroup::getCurveFromGUI (int type) {
|
||||
switch ((FlatCurveType)type) {
|
||||
case (FCT_MinMaxCPoints):
|
||||
return CPointsCurve->getPoints ();
|
||||
default: {
|
||||
// linear and other solutions
|
||||
std::vector<double> lcurve (1);
|
||||
lcurve[0] = (double)(FCT_Linear);
|
||||
return lcurve;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Unlink the tree editor widgets from their parent box to hide them
|
||||
*/
|
||||
void FlatCurveEditorSubGroup::removeEditor () {
|
||||
removeIfThere (parent, CPointsCurveBox, false);
|
||||
}
|
||||
|
||||
bool FlatCurveEditorSubGroup::curveReset(int cType) {
|
||||
switch ((FlatCurveType) cType) {
|
||||
case (FCT_MinMaxCPoints) : // = Control cage
|
||||
CPointsCurve->reset ();
|
||||
return true;
|
||||
break;
|
||||
/*case (FCT_Parametric) :
|
||||
highlights->resetPressed();
|
||||
lights->resetPressed();
|
||||
darks->resetPressed();
|
||||
shadows->resetPressed();
|
||||
shcSelector->reset();
|
||||
paramCurve->reset ();
|
||||
return true;
|
||||
break;*/
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FlatCurveEditorSubGroup::setColorProvider (ColorProvider* p) {
|
||||
CPointsCurve->setColorProvider(p);
|
||||
}
|
||||
|
||||
/*void FlatCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce) {
|
||||
CurveEditor* fce = (CurveEditor*)ce;
|
||||
if (fce==displayedCurve) {
|
||||
paramCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL);
|
||||
customCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL);
|
||||
NURBSCurve->updateBackgroundHistogram (fce->bgHistValid ? fce->histogram : NULL);
|
||||
}
|
||||
}*/
|
||||
59
rtgui/flatcurveeditorsubgroup.h
Normal file
59
rtgui/flatcurveeditorsubgroup.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _FLATCURVEEDITORSUBGROUP_
|
||||
#define _FLATCURVEEDITORSUBGROUP_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <curveeditorgroup.h>
|
||||
|
||||
class FlatCurveEditor;
|
||||
|
||||
class FlatCurveEditorSubGroup: public CurveEditorSubGroup {
|
||||
|
||||
friend class FlatCurveEditor;
|
||||
|
||||
private:
|
||||
Gtk::HBox* CPointsCurveBox;
|
||||
|
||||
MyFlatCurve* CPointsCurve;
|
||||
|
||||
Gtk::Button* saveCPoints;
|
||||
Gtk::Button* loadCPoints;
|
||||
|
||||
public:
|
||||
FlatCurveEditorSubGroup(CurveEditorGroup* prt);
|
||||
~FlatCurveEditorSubGroup();
|
||||
|
||||
FlatCurveEditor* addCurve(Glib::ustring curveLabel = "");
|
||||
//virtual void updateBackgroundHistogram (CurveEditor* ce);
|
||||
virtual void setColorProvider (ColorProvider* p);
|
||||
|
||||
private:
|
||||
void storeCurveValues (CurveEditor* ce, const std::vector<double>& p);
|
||||
void storeDisplayedCurve ();
|
||||
void restoreDisplayedHistogram ();
|
||||
void savePressed ();
|
||||
void loadPressed ();
|
||||
void switchGUI();
|
||||
bool curveReset (int cType);
|
||||
void removeEditor ();
|
||||
const std::vector<double> getCurveFromGUI (int type);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include <hsvequalizer.h>
|
||||
#include <utils.h>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
@@ -26,196 +27,61 @@ using namespace rtengine::procparams;
|
||||
|
||||
HSVEqualizer::HSVEqualizer () : Gtk::VBox(), FoldableToolPanel(this) {
|
||||
|
||||
enabled = Gtk::manage (new Gtk::CheckButton (M("GENERAL_ENABLED")));
|
||||
enabled->set_active (true);
|
||||
pack_start(*enabled);
|
||||
enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &HSVEqualizer::enabledToggled) );
|
||||
|
||||
Gtk::HSeparator *hsvsepa = Gtk::manage (new Gtk::HSeparator());
|
||||
pack_start(*hsvsepa, Gtk::PACK_SHRINK, 2);
|
||||
hsvsepa->show ();
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ());
|
||||
hb->set_border_width (4);
|
||||
hb->show ();
|
||||
Gtk::Label* hsvselect = Gtk::manage (new Gtk::Label (M("TP_HSVEQUALIZER_CHANNEL")+":"));
|
||||
hsvselect->show ();
|
||||
hsvchannel = Gtk::manage (new Gtk::ComboBoxText ());
|
||||
hsvchannel->append_text (M("TP_HSVEQUALIZER_SAT"));
|
||||
hsvchannel->append_text (M("TP_HSVEQUALIZER_VAL"));
|
||||
hsvchannel->append_text (M("TP_HSVEQUALIZER_HUE"));
|
||||
hsvchannel->show ();
|
||||
hb->pack_start(*hsvselect, Gtk::PACK_SHRINK, 4);
|
||||
hb->pack_start(*hsvchannel);
|
||||
|
||||
Gtk::Button * neutralButton = Gtk::manage (new Gtk::Button(M("TP_HSVEQUALIZER_NEUTRAL")));
|
||||
hb->pack_start(*neutralButton, Gtk::PACK_SHRINK, 2);
|
||||
neutralPressedConn = neutralButton->signal_pressed().connect( sigc::mem_fun(*this, &HSVEqualizer::neutralPressed));
|
||||
|
||||
|
||||
pack_start (*hb);
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
/*
|
||||
Gtk::HBox * buttonBox17 = Gtk::manage (new Gtk::HBox());
|
||||
pack_start(*buttonBox17, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
Gtk::Button * neutralButton = Gtk::manage (new Gtk::Button(M("TP_HSVEQUALIZER_NEUTRAL")));
|
||||
buttonBox17->pack_start(*neutralButton, Gtk::PACK_SHRINK, 2);
|
||||
neutralPressedConn = neutralButton->signal_pressed().connect( sigc::mem_fun(*this, &HSVEqualizer::neutralPressed));
|
||||
|
||||
buttonBox17->show();
|
||||
*/
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
Gtk::HSeparator *hsvsepb = Gtk::manage (new Gtk::HSeparator());
|
||||
pack_start(*hsvsepb, Gtk::PACK_SHRINK, 2);
|
||||
hsvsepb->show ();
|
||||
|
||||
satbox = new Gtk::VBox ();
|
||||
sat[0] = new Adjuster (M("TP_HSVEQUALIZER1"), -100, 100, 1, 0);
|
||||
sat[1] = new Adjuster (M("TP_HSVEQUALIZER2"), -100, 100, 1, 0);
|
||||
sat[2] = new Adjuster (M("TP_HSVEQUALIZER3"), -100, 100, 1, 0);
|
||||
sat[3] = new Adjuster (M("TP_HSVEQUALIZER4"), -100, 100, 1, 0);
|
||||
sat[4] = new Adjuster (M("TP_HSVEQUALIZER5"), -100, 100, 1, 0);
|
||||
sat[5] = new Adjuster (M("TP_HSVEQUALIZER6"), -100, 100, 1, 0);
|
||||
sat[6] = new Adjuster (M("TP_HSVEQUALIZER7"), -100, 100, 1, 0);
|
||||
sat[7] = new Adjuster (M("TP_HSVEQUALIZER8"), -100, 100, 1, 0);
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
sat[i]->setAdjusterListener(this);
|
||||
satbox->pack_start(*sat[i]);
|
||||
}
|
||||
|
||||
//show_all_children ();
|
||||
satbox->show ();
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
valbox = new Gtk::VBox ();
|
||||
val[0] = new Adjuster (M("TP_HSVEQUALIZER1"), -100, 100, 1, 0);
|
||||
val[1] = new Adjuster (M("TP_HSVEQUALIZER2"), -100, 100, 1, 0);
|
||||
val[2] = new Adjuster (M("TP_HSVEQUALIZER3"), -100, 100, 1, 0);
|
||||
val[3] = new Adjuster (M("TP_HSVEQUALIZER4"), -100, 100, 1, 0);
|
||||
val[4] = new Adjuster (M("TP_HSVEQUALIZER5"), -100, 100, 1, 0);
|
||||
val[5] = new Adjuster (M("TP_HSVEQUALIZER6"), -100, 100, 1, 0);
|
||||
val[6] = new Adjuster (M("TP_HSVEQUALIZER7"), -100, 100, 1, 0);
|
||||
val[7] = new Adjuster (M("TP_HSVEQUALIZER8"), -100, 100, 1, 0);
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
val[i]->setAdjusterListener(this);
|
||||
valbox->pack_start(*val[i]);
|
||||
}
|
||||
|
||||
//show_all_children ();
|
||||
valbox->show ();
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
huebox = new Gtk::VBox ();
|
||||
|
||||
|
||||
hue[0] = new Adjuster (M("TP_HSVEQUALIZER1"), -100, 100, 1, 0);
|
||||
hue[1] = new Adjuster (M("TP_HSVEQUALIZER2"), -100, 100, 1, 0);
|
||||
hue[2] = new Adjuster (M("TP_HSVEQUALIZER3"), -100, 100, 1, 0);
|
||||
hue[3] = new Adjuster (M("TP_HSVEQUALIZER4"), -100, 100, 1, 0);
|
||||
hue[4] = new Adjuster (M("TP_HSVEQUALIZER5"), -100, 100, 1, 0);
|
||||
hue[5] = new Adjuster (M("TP_HSVEQUALIZER6"), -100, 100, 1, 0);
|
||||
hue[6] = new Adjuster (M("TP_HSVEQUALIZER7"), -100, 100, 1, 0);
|
||||
hue[7] = new Adjuster (M("TP_HSVEQUALIZER8"), -100, 100, 1, 0);
|
||||
for(int i = 0; i < 8; i++)
|
||||
{
|
||||
hue[i]->setAdjusterListener(this);
|
||||
huebox->pack_start(*hue[i]);
|
||||
}
|
||||
|
||||
//huebox->show_all_children ();
|
||||
huebox->show ();
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
huebox->reference ();
|
||||
valbox->reference ();
|
||||
satbox->reference ();
|
||||
|
||||
//enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &HSVEqualizer::enabled_toggled) );
|
||||
hsvchannel->signal_changed().connect( sigc::mem_fun(*this, &HSVEqualizer::hsvchannelChanged) );
|
||||
curveEditorG = new CurveEditorGroup (M("TP_HSVEQUALIZER_CHANNEL"));
|
||||
curveEditorG->setCurveListener (this);
|
||||
curveEditorG->setColorProvider (this);
|
||||
|
||||
hshape = (FlatCurveEditor*)curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_HUE"));
|
||||
sshape = (FlatCurveEditor*)curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_SAT"));
|
||||
vshape = (FlatCurveEditor*)curveEditorG->addCurve(CT_Flat, M("TP_HSVEQUALIZER_VAL"));
|
||||
|
||||
// This will add the reset button at the end of the curveType buttons
|
||||
curveEditorG->curveListComplete();
|
||||
|
||||
pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
//curveEditorG->show();
|
||||
}
|
||||
|
||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
HSVEqualizer::~HSVEqualizer () {
|
||||
for (int i=0;i<8;i++)
|
||||
{
|
||||
delete hue[i];
|
||||
delete val[i];
|
||||
delete sat[i];
|
||||
}
|
||||
delete curveEditorG;
|
||||
}
|
||||
|
||||
|
||||
void HSVEqualizer::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
|
||||
|
||||
disableListener ();
|
||||
|
||||
|
||||
if (pedited) {
|
||||
for (int i=0; i<8; i++) {
|
||||
sat[i]->setEditedState (pedited->hsvequalizer.sat[i] ? Edited : UnEdited);
|
||||
val[i]->setEditedState (pedited->hsvequalizer.val[i] ? Edited : UnEdited);
|
||||
hue[i]->setEditedState (pedited->hsvequalizer.hue[i] ? Edited : UnEdited);
|
||||
}
|
||||
enabled->set_inconsistent (!pedited->hsvequalizer.enabled);
|
||||
hshape->setUnChanged (!pedited->hsvequalizer.hcurve);
|
||||
sshape->setUnChanged (!pedited->hsvequalizer.scurve);
|
||||
vshape->setUnChanged (!pedited->hsvequalizer.vcurve);
|
||||
}
|
||||
|
||||
enaConn.block (true);
|
||||
enabled->set_active (pp->hsvequalizer.enabled);
|
||||
enaConn.block (false);
|
||||
lastEnabled = pp->hsvequalizer.enabled;
|
||||
|
||||
for (int i=0; i<8; i++) {
|
||||
sat[i]->setValue (pp->hsvequalizer.sat[i]);
|
||||
val[i]->setValue (pp->hsvequalizer.val[i]);
|
||||
hue[i]->setValue (pp->hsvequalizer.hue[i]);
|
||||
}
|
||||
|
||||
if (pedited && !pedited->hsvequalizer.hsvchannel)
|
||||
hsvchannel->set_active (3);
|
||||
else if (pp->hsvequalizer.hsvchannel=="sat")
|
||||
hsvchannel->set_active (0);
|
||||
else if (pp->hsvequalizer.hsvchannel=="val")
|
||||
hsvchannel->set_active (1);
|
||||
else if (pp->hsvequalizer.hsvchannel=="hue")
|
||||
hsvchannel->set_active (2);
|
||||
|
||||
hshape->setCurve (pp->hsvequalizer.hcurve);
|
||||
sshape->setCurve (pp->hsvequalizer.scurve);
|
||||
vshape->setCurve (pp->hsvequalizer.vcurve);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void HSVEqualizer::write (ProcParams* pp, ParamsEdited* pedited) {
|
||||
|
||||
pp->hsvequalizer.enabled = enabled->get_active ();
|
||||
for (int i=0; i<8; i++) {
|
||||
pp->hsvequalizer.sat[i] = sat[i]->getValue();
|
||||
pp->hsvequalizer.val[i] = val[i]->getValue();
|
||||
pp->hsvequalizer.hue[i] = hue[i]->getValue();
|
||||
}
|
||||
|
||||
if (hsvchannel->get_active_row_number()==0)
|
||||
pp->hsvequalizer.hsvchannel = "sat";
|
||||
else if (hsvchannel->get_active_row_number()==1)
|
||||
pp->hsvequalizer.hsvchannel = "val";
|
||||
else if (hsvchannel->get_active_row_number()==2)
|
||||
pp->hsvequalizer.hsvchannel = "hue";
|
||||
|
||||
pp->hsvequalizer.hcurve = hshape->getCurve ();
|
||||
pp->hsvequalizer.scurve = sshape->getCurve ();
|
||||
pp->hsvequalizer.vcurve = vshape->getCurve ();
|
||||
|
||||
if (pedited) {
|
||||
pedited->hsvequalizer.enabled = !enabled->get_inconsistent();//from dirpyreq
|
||||
for (int i=0; i<8; i++) {
|
||||
pedited->hsvequalizer.sat[i] = sat[i]->getEditedState ();
|
||||
pedited->hsvequalizer.val[i] = val[i]->getEditedState ();
|
||||
pedited->hsvequalizer.hue[i] = hue[i]->getEditedState ();
|
||||
}
|
||||
|
||||
pedited->hsvequalizer.hcurve = !hshape->isUnChanged ();
|
||||
pedited->hsvequalizer.scurve = !sshape->isUnChanged ();
|
||||
pedited->hsvequalizer.vcurve = !vshape->isUnChanged ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void HSVEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited* pedited) {
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
@@ -239,7 +105,27 @@ void HSVEqualizer::setDefaults (const ProcParams* defParams, const ParamsEdited*
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* Curve listener
|
||||
*
|
||||
* If more than one curve has been added, the curve listener is automatically
|
||||
* set to 'multi=true', and send a pointer of the modified curve in a parameter
|
||||
*/
|
||||
void HSVEqualizer::curveChanged (CurveEditor* ce) {
|
||||
|
||||
if (listener) {
|
||||
if (ce == hshape)
|
||||
listener->panelChanged (EvHSVEqualizerH, M("HISTORY_CUSTOMCURVE"));
|
||||
if (ce == sshape)
|
||||
listener->panelChanged (EvHSVEqualizerS, M("HISTORY_CUSTOMCURVE"));
|
||||
if (ce == vshape)
|
||||
listener->panelChanged (EvHSVEqualizerV, M("HISTORY_CUSTOMCURVE"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void HSVEqualizer::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener && enabled->get_active()) {
|
||||
@@ -289,75 +175,47 @@ void HSVEqualizer::adjusterChanged (Adjuster* a, double newval) {
|
||||
//listener->panelChanged (EvHSVEqualizer, ss.str());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void HSVEqualizer::enabledToggled () {
|
||||
|
||||
if (batchMode) {
|
||||
if (enabled->get_inconsistent()) {
|
||||
enabled->set_inconsistent (false);
|
||||
enaConn.block (true);
|
||||
enabled->set_active (false);
|
||||
enaConn.block (false);
|
||||
}
|
||||
else if (lastEnabled)
|
||||
enabled->set_inconsistent (true);
|
||||
|
||||
lastEnabled = enabled->get_active ();
|
||||
void HSVEqualizer::colorForValue (double valX, double valY) {
|
||||
|
||||
float r, g, b;
|
||||
|
||||
CurveEditor* ce = curveEditorG->getDisplayedCurve();
|
||||
|
||||
if (ce == hshape) { // Hue = f(Hue)
|
||||
|
||||
float h = (float)((valY - 0.5) * 2. + valX);
|
||||
if (h > 1.0)
|
||||
h -= 1.0;
|
||||
else if (h < 0.0)
|
||||
h += 1.0;
|
||||
hsv2rgb(h, (float)0.5, (float)0.5, r, g, b);
|
||||
red = (double)r;
|
||||
green = (double)g;
|
||||
blue = (double)b;
|
||||
}
|
||||
|
||||
if (listener) {
|
||||
if (enabled->get_active ())
|
||||
listener->panelChanged (EvHSVEqEnabled, M("GENERAL_ENABLED"));
|
||||
else
|
||||
listener->panelChanged (EvHSVEqEnabled, M("GENERAL_DISABLED"));
|
||||
else if (ce == sshape) { // Saturation = f(Hue)
|
||||
hsv2rgb((float)valX, (float)valY, (float)0.5, r, g, b);
|
||||
red = (double)r;
|
||||
green = (double)g;
|
||||
blue = (double)b;
|
||||
}
|
||||
else if (ce == vshape) { // Value = f(Hue)
|
||||
hsv2rgb((float)valX, (float)0.5, (float)valY, r, g, b);
|
||||
red = (double)r;
|
||||
green = (double)g;
|
||||
blue = (double)b;
|
||||
}
|
||||
else {
|
||||
printf("Error: no curve displayed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void HSVEqualizer::hsvchannelChanged () {
|
||||
|
||||
removeIfThere (this, satbox, false);
|
||||
removeIfThere (this, valbox, false);
|
||||
removeIfThere (this, huebox, false);
|
||||
|
||||
if (hsvchannel->get_active_row_number()==0)
|
||||
pack_start (*satbox);
|
||||
else if (hsvchannel->get_active_row_number()==1)
|
||||
pack_start (*valbox);
|
||||
else if (hsvchannel->get_active_row_number()==2)
|
||||
pack_start (*huebox);
|
||||
|
||||
}
|
||||
|
||||
void HSVEqualizer::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
sat[i]->showEditedCB();
|
||||
val[i]->showEditedCB();
|
||||
hue[i]->showEditedCB();
|
||||
}
|
||||
|
||||
hsvchannel->append_text (M("GENERAL_UNCHANGED"));
|
||||
}
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
|
||||
void HSVEqualizer::neutralPressed () {
|
||||
if (hsvchannel->get_active_row_number()==0)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
sat[i]->setValue(0);
|
||||
adjusterChanged(sat[i], 0);
|
||||
}
|
||||
else if (hsvchannel->get_active_row_number()==1)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
val[i]->setValue(0);
|
||||
adjusterChanged(val[i], 0);
|
||||
}
|
||||
else if (hsvchannel->get_active_row_number()==2)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
hue[i]->setValue(0);
|
||||
adjusterChanged(hue[i], 0);
|
||||
}
|
||||
|
||||
|
||||
curveEditorG->setBatchMode (batchMode);
|
||||
}
|
||||
|
||||
@@ -24,28 +24,23 @@
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
#include <guiutils.h>
|
||||
#include <curveeditor.h>
|
||||
#include <curveeditorgroup.h>
|
||||
#include <colorprovider.h>
|
||||
|
||||
|
||||
class HSVEqualizer : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel
|
||||
class HSVEqualizer : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
Gtk::CheckButton * enabled;
|
||||
Gtk::ComboBoxText* hsvchannel;
|
||||
|
||||
Gtk::VBox* satbox;
|
||||
Gtk::VBox* valbox;
|
||||
Gtk::VBox* huebox;
|
||||
|
||||
Adjuster* sat[8];
|
||||
Adjuster* val[8];
|
||||
Adjuster* hue[8];
|
||||
|
||||
sigc::connection enaConn;
|
||||
sigc::connection neutralPressedConn;
|
||||
|
||||
bool lastEnabled;
|
||||
CurveEditorGroup* curveEditorG;
|
||||
FlatCurveEditor* hshape;
|
||||
FlatCurveEditor* sshape;
|
||||
FlatCurveEditor* vshape;
|
||||
|
||||
public:
|
||||
|
||||
@@ -54,15 +49,12 @@ public:
|
||||
|
||||
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
|
||||
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
|
||||
void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void curveChanged (CurveEditor* ce);
|
||||
//void setDefaults (const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited=NULL);
|
||||
void setBatchMode (bool batchMode);
|
||||
virtual void colorForValue (double valX, double valY);
|
||||
|
||||
void adjusterChanged (Adjuster* a, double newval);
|
||||
void enabledToggled ();
|
||||
void hsvchannelChanged ();
|
||||
|
||||
void neutralPressed ();
|
||||
|
||||
//void adjusterChanged (Adjuster* a, double newval);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,10 +69,11 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this), brAdd(false), contrAdd
|
||||
|
||||
curveEditorG = new CurveEditorGroup ();
|
||||
curveEditorG->setCurveListener (this);
|
||||
curveEditorG->setColorProvider (this);
|
||||
|
||||
lshape = curveEditorG->addCurve("L");
|
||||
ashape = curveEditorG->addCurve("a");
|
||||
bshape = curveEditorG->addCurve("b");
|
||||
lshape = (DiagonalCurveEditor*)curveEditorG->addCurve(CT_Diagonal, "L");
|
||||
ashape = (DiagonalCurveEditor*)curveEditorG->addCurve(CT_Diagonal, "a");
|
||||
bshape = (DiagonalCurveEditor*)curveEditorG->addCurve(CT_Diagonal, "b");
|
||||
|
||||
// This will add the reset button at the end of the curveType buttons
|
||||
curveEditorG->curveListComplete();
|
||||
@@ -305,6 +306,32 @@ void LCurve::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
}*/
|
||||
|
||||
void LCurve::colorForValue (double valX, double valY) {
|
||||
|
||||
CurveEditor* ce = curveEditorG->getDisplayedCurve();
|
||||
|
||||
if (ce == lshape) { // L = f(L)
|
||||
red = (double)valY;
|
||||
green = (double)valY;
|
||||
blue = (double)valY;
|
||||
}
|
||||
else if (ce == ashape) { // a = f(a)
|
||||
// TODO: To be implemented
|
||||
red = (double)valY;
|
||||
green = (double)valY;
|
||||
blue = (double)valY;
|
||||
}
|
||||
else if (ce == bshape) { // b = f(b)
|
||||
red = (double)valY;
|
||||
green = (double)valY;
|
||||
blue = (double)valY;
|
||||
}
|
||||
else {
|
||||
printf("Error: no curve displayed!\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void LCurve::setBatchMode (bool batchMode) {
|
||||
|
||||
ToolPanel::setBatchMode (batchMode);
|
||||
|
||||
@@ -23,9 +23,10 @@
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
#include <curveeditor.h>
|
||||
#include <mycurve.h>
|
||||
#include <curveeditorgroup.h>
|
||||
#include <colorprovider.h>
|
||||
|
||||
class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener {
|
||||
class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener, public ColorProvider {
|
||||
|
||||
protected:
|
||||
Gtk::ComboBoxText* channel;
|
||||
@@ -34,9 +35,9 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPan
|
||||
Adjuster* brightness;
|
||||
Adjuster* contrast;
|
||||
Adjuster* saturation;
|
||||
CurveEditor* lshape;
|
||||
CurveEditor* ashape;
|
||||
CurveEditor* bshape;
|
||||
DiagonalCurveEditor* lshape;
|
||||
DiagonalCurveEditor* ashape;
|
||||
DiagonalCurveEditor* bshape;
|
||||
|
||||
//%%%%%%%%%%%%%%%%
|
||||
Gtk::CheckButton* avoidclip;
|
||||
@@ -65,6 +66,8 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPan
|
||||
void avoidclip_toggled ();
|
||||
void enablelimiter_toggled ();
|
||||
void updateCurveBackgroundHistogram (unsigned* hist);
|
||||
|
||||
virtual void colorForValue (double valX, double valY);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -40,7 +40,7 @@ LCurve::LCurve () : Gtk::VBox(), FoldableToolPanel(this), brAdd(false), contrAdd
|
||||
hsep3->show ();
|
||||
pack_start (*hsep3);
|
||||
|
||||
shape = Gtk::manage (new CurveEditor ());
|
||||
shape = Gtk::manage (new DiagonalCurveEditor ());
|
||||
shape->show ();
|
||||
shape->setCurveListener (this);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <adjuster.h>
|
||||
#include <toolpanel.h>
|
||||
#include <curveeditor.h>
|
||||
#include <curveeditorgroup.h>
|
||||
#include <mycurve.h>
|
||||
|
||||
class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPanel, public CurveListener {
|
||||
@@ -30,7 +31,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public FoldableToolPan
|
||||
protected:
|
||||
Adjuster* brightness;
|
||||
Adjuster* contrast;
|
||||
CurveEditor* shape;
|
||||
DiagonalCurveEditor* shape;
|
||||
bool brAdd, contrAdd;
|
||||
|
||||
public:
|
||||
|
||||
751
rtgui/mycurve.cc
751
rtgui/mycurve.cc
@@ -1,695 +1,56 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mycurve.h>
|
||||
#include <curves.h>
|
||||
#include <string.h>
|
||||
#include <gdkmm/types.h>
|
||||
|
||||
MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
|
||||
|
||||
cursor_type = CSArrow;
|
||||
curve.type = Spline;
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
prevInnerHeight = innerHeight;
|
||||
grab_point = -1;
|
||||
lit_point = -1;
|
||||
buttonPressed = false;
|
||||
|
||||
bghist = new unsigned int[256];
|
||||
|
||||
set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||
signal_event().connect( sigc::mem_fun(*this, &MyCurve::handleEvents) );
|
||||
|
||||
curve.x.push_back(0.);
|
||||
curve.y.push_back(0.);
|
||||
curve.x.push_back(1.);
|
||||
curve.y.push_back(1.);
|
||||
curve.type = Spline;
|
||||
|
||||
mcih = new MyCurveIdleHelper;
|
||||
mcih->myCurve = this;
|
||||
mcih->destroyed = false;
|
||||
mcih->pending = 0;
|
||||
}
|
||||
|
||||
MyCurve::~MyCurve () {
|
||||
|
||||
if (mcih->pending)
|
||||
mcih->destroyed = true;
|
||||
else
|
||||
delete mcih;
|
||||
|
||||
delete [] bghist;
|
||||
}
|
||||
|
||||
std::vector<double> MyCurve::get_vector (int veclen) {
|
||||
|
||||
std::vector<double> vector;
|
||||
vector.resize (veclen);
|
||||
|
||||
if (curve.type != Parametric) {
|
||||
// count active points:
|
||||
double prev =- 1.0;
|
||||
int active = 0;
|
||||
int firstact = -1;
|
||||
for (int i = 0; i < (int)curve.x.size(); ++i)
|
||||
if (curve.x[i] > prev) {
|
||||
if (firstact < 0)
|
||||
firstact = i;
|
||||
prev = curve.x[i];
|
||||
++active;
|
||||
}
|
||||
// handle degenerate case:
|
||||
if (active < 2) {
|
||||
double ry;
|
||||
if (active > 0)
|
||||
ry = curve.y[firstact];
|
||||
else
|
||||
ry = 0.0;
|
||||
if (ry < 0.0) ry = 0.0;
|
||||
if (ry > 1.0) ry = 1.0;
|
||||
for (int x = 0; x < veclen; ++x)
|
||||
vector[x] = ry;
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate remaining points
|
||||
std::vector<double> curveDescr = getPoints ();
|
||||
rtengine::Curve* rtcurve = new rtengine::Curve (curveDescr, veclen*1.5);
|
||||
std::vector<double> t;
|
||||
t.resize (veclen);
|
||||
for (int i = 0; i < veclen; i++)
|
||||
t[i] = (double) i / (veclen - 1.0);
|
||||
rtcurve->getVal (t, vector);
|
||||
delete rtcurve;
|
||||
return vector;
|
||||
}
|
||||
|
||||
void MyCurve::interpolate () {
|
||||
|
||||
prevInnerHeight = innerHeight;
|
||||
point.resize (innerWidth);
|
||||
std::vector<double> vector = get_vector (innerWidth);
|
||||
prevInnerHeight = innerHeight;
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
point[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
upoint.clear ();
|
||||
lpoint.clear ();
|
||||
|
||||
if (curve.type==Parametric && activeParam>0) {
|
||||
double tmp = curve.x[activeParam-1];
|
||||
if (activeParam>=4) {
|
||||
upoint.resize(innerWidth);
|
||||
lpoint.resize(innerWidth);
|
||||
curve.x[activeParam-1] = 100;
|
||||
vector = get_vector (innerWidth);
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
upoint[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
curve.x[activeParam-1] = -100;
|
||||
vector = get_vector (innerWidth);
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
lpoint[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
curve.x[activeParam-1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyCurve::draw (int handle) {
|
||||
if (!pixmap)
|
||||
return;
|
||||
|
||||
// re-calculate curve if dimensions changed
|
||||
if (prevInnerHeight != innerHeight || (int)point.size() != innerWidth)
|
||||
interpolate ();
|
||||
|
||||
Gtk::StateType state = Gtk::STATE_NORMAL;
|
||||
if (!is_sensitive())
|
||||
state = Gtk::STATE_INSENSITIVE;
|
||||
|
||||
Glib::RefPtr<Gtk::Style> style = get_style ();
|
||||
Cairo::RefPtr<Cairo::Context> cr = pixmap->create_cairo_context();
|
||||
|
||||
// bounding rectangle
|
||||
Gdk::Color c = style->get_bg (state);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->rectangle (0, 0, innerWidth + RADIUS*2, innerHeight + RADIUS*2);
|
||||
cr->fill ();
|
||||
|
||||
// histogram in the background
|
||||
if (bghistvalid) {
|
||||
// find highest bin
|
||||
unsigned int histheight = 0;
|
||||
for (int i=0; i<256; i++)
|
||||
if (bghist[i]>histheight)
|
||||
histheight = bghist[i];
|
||||
// draw histogram
|
||||
cr->set_line_width (1.0);
|
||||
double stepSize = (innerWidth-1) / 256.0;
|
||||
cr->move_to (RADIUS, innerHeight-1+RADIUS);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = bghist[i] * (double)(innerHeight-2) / (double)histheight;
|
||||
if (val>innerHeight-1)
|
||||
val = innerHeight-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize+RADIUS, innerHeight-1+RADIUS-val);
|
||||
}
|
||||
cr->line_to (innerWidth-1+RADIUS, innerHeight-1+RADIUS);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
// draw the grid lines:
|
||||
cr->set_line_width (1.0);
|
||||
c = style->get_dark (state);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
for (int i = 0; i < 5; i++) { // + 0.5 to align well with f(x)=x so it will cut through the center
|
||||
cr->move_to (RADIUS, MAX(0,i * (innerHeight + 0.5) / 4) + RADIUS);
|
||||
cr->line_to (innerWidth + RADIUS, MAX(0,i * (innerHeight + 0.5) / 4) + RADIUS);
|
||||
cr->move_to (MAX(0,i * innerWidth / 4) + RADIUS, RADIUS);
|
||||
cr->line_to (MAX(0,i * innerWidth / 4) + RADIUS, innerHeight + RADIUS);
|
||||
}
|
||||
cr->stroke ();
|
||||
|
||||
// draw f(x)=x line
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (RADIUS, innerHeight + RADIUS);
|
||||
cr->line_to (innerWidth + RADIUS, RADIUS);
|
||||
cr->stroke ();
|
||||
cr->unset_dash ();
|
||||
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
// draw upper and lower bounds
|
||||
if (curve.type==Parametric && activeParam>0 && lpoint.size()>1 && upoint.size()>1) {
|
||||
cr->set_source_rgba (0.0, 0.0, 0.0, 0.15);
|
||||
cr->move_to (upoint[0].get_x(), upoint[0].get_y());
|
||||
for (int i=1; i<(int)upoint.size(); i++)
|
||||
cr->line_to (upoint[i].get_x(), upoint[i].get_y());
|
||||
cr->line_to (lpoint[lpoint.size()-1].get_x(), lpoint[lpoint.size()-1].get_y());
|
||||
for (int i=(int)lpoint.size()-2; i>=0; i--)
|
||||
cr->line_to (lpoint[i].get_x(), lpoint[i].get_y());
|
||||
cr->line_to (upoint[0].get_x(), upoint[0].get_y());
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
// draw the cage of the NURBS curve
|
||||
if (curve.type==NURBS) {
|
||||
std::valarray<double> ch_ds (1);
|
||||
ch_ds[0] = 2;
|
||||
cr->set_dash (ch_ds, 0);
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::vector<double> points = getPoints();
|
||||
for (int i = 1; i < (int)points.size(); ) {
|
||||
double x = ((innerWidth-1) * points[i++] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||
double y = innerHeight - ((innerHeight-1) * points[i++] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||
if (i==3)
|
||||
cr->move_to (x, y);
|
||||
else
|
||||
cr->line_to (x, y);
|
||||
}
|
||||
cr->stroke ();
|
||||
cr->unset_dash ();
|
||||
}
|
||||
|
||||
// draw curve
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
cr->move_to (point[0].get_x(), point[0].get_y());
|
||||
for (int i=1; i<(int)point.size(); i++)
|
||||
cr->line_to (point[i].get_x(), point[i].get_y());
|
||||
cr->stroke ();
|
||||
|
||||
// draw bullets
|
||||
if (curve.type!=Parametric)
|
||||
for (int i = 0; i < (int)curve.x.size(); ++i) {
|
||||
cr->set_source_rgb ((i == handle ? 1.0 : 0.0), 0.0, 0.0);
|
||||
double x = ((innerWidth-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||
double y = innerHeight - ((innerHeight-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||
|
||||
cr->arc (x, y, RADIUS+0.5, 0, 2*M_PI);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
get_window()->draw_drawable (style->get_fg_gc (state), pixmap, 0, 0, 0, 0, innerWidth + RADIUS * 2, innerHeight + RADIUS * 2);
|
||||
}
|
||||
|
||||
bool MyCurve::handleEvents (GdkEvent* event) {
|
||||
|
||||
CursorShape new_type = cursor_type;
|
||||
int src, dst;
|
||||
std::vector<double>::iterator itx, ity;
|
||||
|
||||
bool retval = false;
|
||||
int num = (int)curve.x.size();
|
||||
|
||||
/* innerWidth and innerHeight are the size of the graph */
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
|
||||
double minDistanceX = (double)(MIN_DISTANCE) / (double)(innerWidth-1);
|
||||
double minDistanceY = (double)(MIN_DISTANCE) / (double)(innerHeight-1);
|
||||
|
||||
if ((innerWidth < 0) || (innerHeight < 0))
|
||||
return false;
|
||||
|
||||
switch (event->type) {
|
||||
case Gdk::CONFIGURE:
|
||||
if (pixmap)
|
||||
pixmap.clear ();
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::EXPOSE:
|
||||
if (!pixmap) {
|
||||
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
|
||||
interpolate ();
|
||||
}
|
||||
draw (lit_point);
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_PRESS:
|
||||
if (curve.type!=Parametric) {
|
||||
if (event->button.button == 1) {
|
||||
buttonPressed = true;
|
||||
add_modal_grab ();
|
||||
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
findClosestPoint();
|
||||
|
||||
new_type = CSMove;
|
||||
if (distanceX > minDistanceX) {
|
||||
/* insert a new control point */
|
||||
if (num > 0) {
|
||||
if (clampedX > curve.x[closest_point])
|
||||
++closest_point;
|
||||
}
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
for (int i=0; i<closest_point; i++) { itx++; ity++; }
|
||||
curve.x.insert (itx, 0);
|
||||
curve.y.insert (ity, 0);
|
||||
num++;
|
||||
|
||||
// the graph is refreshed only if a new point is created (snaped to a pixel)
|
||||
curve.x[closest_point] = clampedX;
|
||||
curve.y[closest_point] = clampedY;
|
||||
|
||||
interpolate ();
|
||||
draw (closest_point);
|
||||
notifyListener ();
|
||||
}
|
||||
grab_point = closest_point;
|
||||
lit_point = closest_point;
|
||||
ugpX = curve.x[closest_point];
|
||||
ugpY = curve.y[closest_point];
|
||||
}
|
||||
if (buttonPressed) retval = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_RELEASE:
|
||||
if (curve.type!=Parametric) {
|
||||
if (buttonPressed && event->button.button == 1) {
|
||||
buttonPressed = false;
|
||||
/* get the pointer position */
|
||||
getCursorPosition(event);
|
||||
findClosestPoint();
|
||||
|
||||
remove_modal_grab ();
|
||||
int previous_lit_point = lit_point;
|
||||
/* delete inactive points: */
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
for (src = dst = 0; src < num; ++src)
|
||||
if (curve.x[src] >= 0.0) {
|
||||
curve.x[dst] = curve.x[src];
|
||||
curve.y[dst] = curve.y[src];
|
||||
++dst;
|
||||
++itx;
|
||||
++ity;
|
||||
}
|
||||
if (dst < src) {
|
||||
curve.x.erase (itx, curve.x.end());
|
||||
curve.y.erase (ity, curve.y.end());
|
||||
if (!curve.x.size()) {
|
||||
curve.x.push_back (0);
|
||||
curve.y.push_back (0);
|
||||
interpolate ();
|
||||
draw (lit_point);
|
||||
}
|
||||
}
|
||||
if (distanceX <= minDistanceX) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if (lit_point != previous_lit_point)
|
||||
draw (lit_point);
|
||||
grab_point = -1;
|
||||
retval = true;
|
||||
notifyListener ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Gdk::LEAVE_NOTIFY:
|
||||
// Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case
|
||||
// The cursor will have to LEAVE another time after the drag...
|
||||
if (!buttonPressed)
|
||||
if (grab_point == -1) {
|
||||
new_type = CSArrow;
|
||||
lit_point = -1;
|
||||
draw (lit_point);
|
||||
}
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::MOTION_NOTIFY:
|
||||
if (curve.type == Linear || curve.type == Spline || curve.type == NURBS) {
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
|
||||
if (grab_point == -1) {
|
||||
// there's no point currently being moved
|
||||
int previous_lit_point = lit_point;
|
||||
findClosestPoint();
|
||||
if (distanceX <= minDistanceX) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if (lit_point != previous_lit_point)
|
||||
draw (lit_point);
|
||||
}
|
||||
else {
|
||||
// a point is being moved
|
||||
|
||||
// bounds of the grabbed point
|
||||
double leftBound = (grab_point == 0 ) ? 0. : curve.x[grab_point-1];
|
||||
double rightBound = (grab_point == num-1) ? 1. : curve.x[grab_point+1];
|
||||
double const bottomBound = 0.;
|
||||
double const topBound = 1.;
|
||||
|
||||
double leftDeletionBound = leftBound - minDistanceX;
|
||||
double rightDeletionBound = rightBound + minDistanceX;
|
||||
double bottomDeletionBound = bottomBound - minDistanceY;
|
||||
double topDeletionBound = topBound + minDistanceY;
|
||||
|
||||
// we memorize the previous position of the point, for optimization purpose
|
||||
double prevPosX = curve.x[grab_point];
|
||||
double prevPosY = curve.y[grab_point];
|
||||
|
||||
// we memorize the previous position of the point, for optimization purpose
|
||||
ugpX += deltaX;
|
||||
ugpY += deltaY;
|
||||
|
||||
// handling limitations along X axis
|
||||
if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else if (ugpX <= leftDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else
|
||||
// nextPosX is in bounds
|
||||
curve.x[grab_point] = CLAMP(ugpX, leftBound, rightBound);
|
||||
|
||||
// Handling limitations along Y axis
|
||||
if (ugpY >= topDeletionBound && grab_point != 0 && grab_point != num-1) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num-1) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else
|
||||
// nextPosY is in the bounds
|
||||
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||
|
||||
if (curve.x[grab_point] != prevPosX || curve.y[grab_point] != prevPosY) {
|
||||
// we recalculate the curve only if we have to
|
||||
interpolate ();
|
||||
draw (lit_point);
|
||||
notifyListener ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (new_type != cursor_type) {
|
||||
cursor_type = new_type;
|
||||
cursorManager.setCursor(cursor_type);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void MyCurve::getCursorPosition(GdkEvent* event) {
|
||||
int tx, ty;
|
||||
int prevCursorX, prevCursorY;
|
||||
double incrementX = 1. / (double)(innerWidth-1);
|
||||
double incrementY = 1. / (double)(innerHeight-1);
|
||||
|
||||
// getting the cursor position
|
||||
switch (event->type) {
|
||||
case (Gdk::MOTION_NOTIFY) :
|
||||
if (event->motion.is_hint) {
|
||||
get_window()->get_pointer (tx, ty, mod_type);
|
||||
}
|
||||
else {
|
||||
tx = (int)event->button.x;
|
||||
ty = (int)event->button.y;
|
||||
mod_type = (Gdk::ModifierType)event->button.state;
|
||||
}
|
||||
break;
|
||||
case (Gdk::BUTTON_PRESS) :
|
||||
case (Gdk::BUTTON_RELEASE) :
|
||||
tx = (int)event->button.x;
|
||||
ty = (int)event->button.y;
|
||||
mod_type = (Gdk::ModifierType)event->button.state;
|
||||
break;
|
||||
default :
|
||||
// The cursor position is not available
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (grab_point != -1) {
|
||||
prevCursorX = cursorX;
|
||||
prevCursorY = cursorY;
|
||||
}
|
||||
cursorX = tx - RADIUS;
|
||||
cursorY = (innerHeight-1) - (ty - RADIUS);
|
||||
|
||||
// update deltaX/Y if the user drags a point
|
||||
if (grab_point != -1) {
|
||||
// set the dragging factor
|
||||
int control_key = mod_type & GDK_CONTROL_MASK;
|
||||
int shift_key = mod_type & GDK_SHIFT_MASK;
|
||||
|
||||
// the increment get smaller if modifier key are used
|
||||
if (control_key && shift_key) { incrementX *= 0.01; incrementY *= 0.01; }
|
||||
else if (shift_key) { incrementX *= 0.07; incrementY *= 0.07; }
|
||||
else if (control_key) { incrementX *= 0.25; incrementY *= 0.25; }
|
||||
|
||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||
}
|
||||
// otherwise set the position of the new point (modifier keys has no effect here)
|
||||
else {
|
||||
double tempCursorX = cursorX * incrementX;
|
||||
double tempCursorY = cursorY * incrementY;
|
||||
clampedX = CLAMP (tempCursorX, 0., 1.); // X position of the pointer from the origin of the graph
|
||||
clampedY = CLAMP (tempCursorY, 0., 1.); // Y position of the pointer from the origin of the graph
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MyCurve::findClosestPoint() {
|
||||
distanceX = 10.0; distanceY = 10.0;
|
||||
closest_point = -1;
|
||||
|
||||
if (curve.type!=Parametric) {
|
||||
for (int i = 0; i < (int)curve.x.size(); i++) {
|
||||
double dX = curve.x[i] - clampedX;
|
||||
double dY = curve.y[i] - clampedY;
|
||||
double currDistX = dX < 0. ? -dX : dX; //abs (dX);
|
||||
double currDistY = dY < 0. ? -dY : dY; //abs (dY);
|
||||
if (currDistX < distanceX) {
|
||||
distanceX = currDistX;
|
||||
distanceY = currDistY;
|
||||
closest_point = i;
|
||||
}
|
||||
else if (currDistX == distanceX && currDistY < distanceY) {
|
||||
// there is more than 1 point for that X coordinate, we select the closest point to the cursor
|
||||
distanceY = currDistY;
|
||||
closest_point = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> MyCurve::getPoints () {
|
||||
std::vector<double> result;
|
||||
if (curve.type==Parametric) {
|
||||
result.push_back ((double)(Parametric));
|
||||
for (int i=0; i<(int)curve.x.size(); i++) {
|
||||
result.push_back (curve.x[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the first value gives the type of the curve
|
||||
if (curve.type==Linear)
|
||||
result.push_back ((double)(Linear));
|
||||
else if (curve.type==Spline)
|
||||
result.push_back ((double)(Spline));
|
||||
else if (curve.type==NURBS)
|
||||
result.push_back ((double)(NURBS));
|
||||
// then we push all the points coordinate
|
||||
for (int i=0; i<(int)curve.x.size(); i++) {
|
||||
if (curve.x[i]>=0) {
|
||||
result.push_back (curve.x[i]);
|
||||
result.push_back (curve.y[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MyCurve::setPoints (const std::vector<double>& p) {
|
||||
int ix = 0;
|
||||
CurveType t = (CurveType)p[ix++];
|
||||
curve.type = t;
|
||||
if (t==Parametric) {
|
||||
curve.x.clear ();
|
||||
curve.y.clear ();
|
||||
for (int i=1; i<(int)p.size(); i++)
|
||||
curve.x.push_back (p[ix++]);
|
||||
}
|
||||
else {
|
||||
curve.x.clear ();
|
||||
curve.y.clear ();
|
||||
for (int i=0; i<(int)p.size()/2; i++) {
|
||||
curve.x.push_back (p[ix++]);
|
||||
curve.y.push_back (p[ix++]);
|
||||
}
|
||||
activeParam = -1;
|
||||
}
|
||||
pixmap.clear ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void MyCurve::setType (CurveType t) {
|
||||
|
||||
curve.type = t;
|
||||
pixmap.clear ();
|
||||
}
|
||||
|
||||
void MyCurve::notifyListener () {
|
||||
|
||||
if (listener)
|
||||
listener->curveChanged ();
|
||||
}
|
||||
|
||||
void MyCurve::setActiveParam (int ac) {
|
||||
|
||||
activeParam = ac;
|
||||
pixmap.clear ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
int mchistupdate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
|
||||
MyCurveIdleHelper* mcih = (MyCurveIdleHelper*)data;
|
||||
|
||||
if (mcih->destroyed) {
|
||||
if (mcih->pending == 1)
|
||||
delete mcih;
|
||||
else
|
||||
mcih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
mcih->myCurve->pixmap.clear ();
|
||||
mcih->myCurve->queue_draw ();
|
||||
|
||||
mcih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MyCurve::updateBackgroundHistogram (unsigned int* hist) {
|
||||
|
||||
if (hist!=NULL) {
|
||||
memcpy (bghist, hist, 256*sizeof(unsigned int));
|
||||
bghistvalid = true;
|
||||
}
|
||||
else
|
||||
bghistvalid = false;
|
||||
|
||||
mcih->pending++;
|
||||
g_idle_add (mchistupdate, mcih);
|
||||
|
||||
}
|
||||
|
||||
void MyCurve::reset() {
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
|
||||
switch (curve.type) {
|
||||
case Spline :
|
||||
case NURBS :
|
||||
curve.x.clear();
|
||||
curve.y.clear();
|
||||
curve.x.push_back(0.);
|
||||
curve.y.push_back(0.);
|
||||
curve.x.push_back(1.);
|
||||
curve.y.push_back(1.);
|
||||
grab_point = -1;
|
||||
lit_point = -1;
|
||||
interpolate ();
|
||||
break;
|
||||
case Parametric :
|
||||
// Nothing to do (?)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
draw(-1);
|
||||
}
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mycurve.h>
|
||||
#include <curves.h>
|
||||
#include <string.h>
|
||||
#include <gdkmm/types.h>
|
||||
|
||||
MyCurve::MyCurve () : listener(NULL) {
|
||||
|
||||
cursor_type = CSArrow;
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
prevInnerHeight = innerHeight;
|
||||
buttonPressed = false;
|
||||
snapTo = ST_None;
|
||||
colorProvider = NULL;
|
||||
sized = false;
|
||||
|
||||
set_extension_events(Gdk::EXTENSION_EVENTS_ALL);
|
||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||
|
||||
mcih = new MyCurveIdleHelper;
|
||||
mcih->myCurve = this;
|
||||
mcih->destroyed = false;
|
||||
mcih->pending = 0;
|
||||
}
|
||||
|
||||
MyCurve::~MyCurve () {
|
||||
|
||||
if (mcih->pending)
|
||||
mcih->destroyed = true;
|
||||
else
|
||||
delete mcih;
|
||||
}
|
||||
|
||||
void MyCurve::notifyListener () {
|
||||
|
||||
if (listener)
|
||||
listener->curveChanged ();
|
||||
}
|
||||
|
||||
122
rtgui/mycurve.h
122
rtgui/mycurve.h
@@ -23,91 +23,73 @@
|
||||
#include <vector>
|
||||
#include <curvelistener.h>
|
||||
#include <cursormanager.h>
|
||||
#include <colorprovider.h>
|
||||
|
||||
#define RADIUS 3 /* radius of the control points. Assuming that the center of the spot is in the center of the pixel, the real RADIUS will be this value +0.5 */
|
||||
#define MIN_DISTANCE 8 /* min distance between control points */
|
||||
#define RADIUS 3 /* radius of the control points */
|
||||
#define SQUARE 2 /* half length of the square shape of the tangent handles */
|
||||
#define MIN_DISTANCE 5 /* min distance between control points */
|
||||
#define GRAPH_SIZE 200 /* size of the curve editor graphic */
|
||||
|
||||
// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget
|
||||
enum CurveType {
|
||||
Empty = -1,
|
||||
Linear, // 0
|
||||
Spline, // 1
|
||||
Parametric, // 2
|
||||
NURBS, // 3
|
||||
// Insert new curve type above this line
|
||||
Unchanged // Must remain the last of the enum
|
||||
CT_Flat,
|
||||
CT_Diagonal
|
||||
};
|
||||
|
||||
class CurveDescr {
|
||||
|
||||
public:
|
||||
CurveType type;
|
||||
std::vector<double> x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets.
|
||||
};
|
||||
|
||||
class MyCurve;
|
||||
struct MyCurveIdleHelper {
|
||||
MyCurve* myCurve;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
enum SnapToType {
|
||||
ST_None,
|
||||
ST_Identity, // Point snapped to the identity curve
|
||||
ST_Neighbors // Point snapped to the neighbor points
|
||||
};
|
||||
class MyCurveIdleHelper;
|
||||
|
||||
class MyCurve : public Gtk::DrawingArea {
|
||||
|
||||
friend int mchistupdate (void* data);
|
||||
friend class MyCurveIdleHelper;
|
||||
|
||||
protected:
|
||||
CurveListener* listener;
|
||||
CurveDescr curve;
|
||||
CursorShape cursor_type;
|
||||
Glib::RefPtr<Gdk::Pixmap> pixmap;
|
||||
int innerWidth; // inner width of the editor, allocated by the system
|
||||
int innerHeight; // inner height of the editor, allocated by the system
|
||||
int prevInnerHeight;// previous inner height of the editor
|
||||
int grab_point; // the point that the user is moving
|
||||
int closest_point; // the point that is the closest from the cursor
|
||||
int lit_point; // the point that is lit when the cursor is near it
|
||||
//int last;
|
||||
protected:
|
||||
CurveListener* listener;
|
||||
ColorProvider* colorProvider;
|
||||
CursorShape cursor_type;
|
||||
Glib::RefPtr<Gdk::Pixmap> pixmap;
|
||||
int innerWidth; // inner width of the editor, allocated by the system
|
||||
int innerHeight; // inner height of the editor, allocated by the system
|
||||
int prevInnerHeight;// previous inner height of the editor
|
||||
Gdk::ModifierType mod_type;
|
||||
int cursorX; // X coordinate in the graph of the cursor
|
||||
int cursorY; // Y coordinate in the graph of the cursor
|
||||
double clampedX; // clamped grabbed point X coordinates in the [0;1] range
|
||||
double clampedY; // clamped grabbed point Y coordinates in the [0;1] range
|
||||
double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double distanceX; // X distance from the cursor to the closest point
|
||||
double distanceY; // Y distance from the cursor to the closest point
|
||||
double ugpX; // unclamped grabbed point X coordinate in the graph
|
||||
double ugpY; // unclamped grabbed point Y coordinate in the graph
|
||||
std::vector<Gdk::Point> point;
|
||||
std::vector<Gdk::Point> upoint;
|
||||
std::vector<Gdk::Point> lpoint;
|
||||
int activeParam;
|
||||
unsigned int* bghist; // histogram values
|
||||
bool bghistvalid;
|
||||
bool buttonPressed;
|
||||
MyCurveIdleHelper* mcih;
|
||||
int cursorX; // X coordinate in the graph of the cursor
|
||||
int cursorY; // Y coordinate in the graph of the cursor
|
||||
std::vector<Gdk::Point> point;
|
||||
std::vector<Gdk::Point> upoint;
|
||||
std::vector<Gdk::Point> lpoint;
|
||||
bool buttonPressed;
|
||||
enum SnapToType snapTo;
|
||||
MyCurveIdleHelper* mcih;
|
||||
bool sized;
|
||||
|
||||
void draw (int handle);
|
||||
void interpolate ();
|
||||
void getCursorPosition(GdkEvent* event);
|
||||
void findClosestPoint();
|
||||
std::vector<double> get_vector (int veclen);
|
||||
public:
|
||||
MyCurve ();
|
||||
~MyCurve ();
|
||||
|
||||
void setCurveListener (CurveListener* cl) { listener = cl; }
|
||||
void setColorProvider (ColorProvider* cp) { colorProvider = cp; }
|
||||
void notifyListener ();
|
||||
void updateBackgroundHistogram (unsigned int* hist) {return;} ;
|
||||
virtual std::vector<double> getPoints () = 0;
|
||||
virtual void setPoints (const std::vector<double>& p) = 0;
|
||||
virtual bool handleEvents (GdkEvent* event) = 0;
|
||||
virtual void reset () = 0;
|
||||
protected:
|
||||
virtual std::vector<double> get_vector (int veclen) = 0;
|
||||
};
|
||||
|
||||
class MyCurveIdleHelper {
|
||||
public:
|
||||
MyCurve* myCurve;
|
||||
bool destroyed;
|
||||
int pending;
|
||||
|
||||
void clearPixmap () { myCurve->pixmap.clear (); }
|
||||
|
||||
public:
|
||||
MyCurve ();
|
||||
~MyCurve ();
|
||||
|
||||
void setCurveListener (CurveListener* cl) { listener = cl; }
|
||||
std::vector<double> getPoints ();
|
||||
void setPoints (const std::vector<double>& p);
|
||||
void setType (CurveType t);
|
||||
bool handleEvents (GdkEvent* event);
|
||||
void notifyListener ();
|
||||
void setActiveParam (int ac);
|
||||
void updateBackgroundHistogram (unsigned int* hist);
|
||||
void reset ();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
678
rtgui/mydiagonalcurve.cc
Normal file
678
rtgui/mydiagonalcurve.cc
Normal file
@@ -0,0 +1,678 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <mydiagonalcurve.h>
|
||||
#include <curves.h>
|
||||
#include <string.h>
|
||||
#include <gdkmm/types.h>
|
||||
|
||||
MyDiagonalCurve::MyDiagonalCurve () : activeParam(-1), bghistvalid(false) {
|
||||
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
prevInnerHeight = innerHeight;
|
||||
grab_point = -1;
|
||||
lit_point = -1;
|
||||
buttonPressed = false;
|
||||
|
||||
bghist = new unsigned int[256];
|
||||
|
||||
signal_event().connect( sigc::mem_fun(*this, &MyDiagonalCurve::handleEvents) );
|
||||
|
||||
curve.type = DCT_Spline;
|
||||
|
||||
curve.x.push_back(0.);
|
||||
curve.y.push_back(0.);
|
||||
curve.x.push_back(1.);
|
||||
curve.y.push_back(1.);
|
||||
}
|
||||
|
||||
MyDiagonalCurve::~MyDiagonalCurve () {
|
||||
|
||||
delete [] bghist;
|
||||
}
|
||||
|
||||
std::vector<double> MyDiagonalCurve::get_vector (int veclen) {
|
||||
|
||||
std::vector<double> vector;
|
||||
vector.resize (veclen);
|
||||
|
||||
if (curve.type != DCT_Parametric) {
|
||||
// count active points:
|
||||
double prev =- 1.0;
|
||||
int active = 0;
|
||||
int firstact = -1;
|
||||
for (int i = 0; i < (int)curve.x.size(); ++i)
|
||||
if (curve.x[i] > prev) {
|
||||
if (firstact < 0)
|
||||
firstact = i;
|
||||
prev = curve.x[i];
|
||||
++active;
|
||||
}
|
||||
// handle degenerate case:
|
||||
if (active < 2) {
|
||||
double ry;
|
||||
if (active > 0)
|
||||
ry = curve.y[firstact];
|
||||
else
|
||||
ry = 0.0;
|
||||
if (ry < 0.0) ry = 0.0;
|
||||
if (ry > 1.0) ry = 1.0;
|
||||
for (int x = 0; x < veclen; ++x)
|
||||
vector[x] = ry;
|
||||
return vector;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate remaining points
|
||||
std::vector<double> curveDescr = getPoints ();
|
||||
rtengine::DiagonalCurve* rtcurve = new rtengine::DiagonalCurve (curveDescr, veclen*1.5);
|
||||
std::vector<double> t;
|
||||
t.resize (veclen);
|
||||
for (int i = 0; i < veclen; i++)
|
||||
t[i] = (double) i / (veclen - 1.0);
|
||||
rtcurve->getVal (t, vector);
|
||||
delete rtcurve;
|
||||
return vector;
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::interpolate () {
|
||||
|
||||
prevInnerHeight = innerHeight;
|
||||
point.resize (innerWidth);
|
||||
std::vector<double> vector = get_vector (innerWidth);
|
||||
prevInnerHeight = innerHeight;
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
point[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
upoint.clear ();
|
||||
lpoint.clear ();
|
||||
|
||||
if (curve.type==DCT_Parametric && activeParam>0) {
|
||||
double tmp = curve.x[activeParam-1];
|
||||
if (activeParam>=4) {
|
||||
upoint.resize(innerWidth);
|
||||
lpoint.resize(innerWidth);
|
||||
curve.x[activeParam-1] = 100;
|
||||
vector = get_vector (innerWidth);
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
upoint[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
curve.x[activeParam-1] = -100;
|
||||
vector = get_vector (innerWidth);
|
||||
for (int i = 0; i < innerWidth; ++i)
|
||||
lpoint[i] = Gdk::Point (RADIUS + i, RADIUS + innerHeight - (int)((innerHeight-1) * vector[i] + 0.5));
|
||||
curve.x[activeParam-1] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::draw (int handle) {
|
||||
if (!pixmap)
|
||||
return;
|
||||
|
||||
// re-calculate curve if dimensions changed
|
||||
if (prevInnerHeight != innerHeight || (int)point.size() != innerWidth)
|
||||
interpolate ();
|
||||
|
||||
Gtk::StateType state = Gtk::STATE_NORMAL;
|
||||
if (!is_sensitive())
|
||||
state = Gtk::STATE_INSENSITIVE;
|
||||
|
||||
Glib::RefPtr<Gtk::Style> style = get_style ();
|
||||
Cairo::RefPtr<Cairo::Context> cr = pixmap->create_cairo_context();
|
||||
|
||||
// bounding rectangle
|
||||
Gdk::Color c = style->get_bg (state);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->rectangle (0, 0, innerWidth + RADIUS*2, innerHeight + RADIUS*2);
|
||||
cr->fill ();
|
||||
|
||||
// histogram in the background
|
||||
if (bghistvalid) {
|
||||
// find highest bin
|
||||
unsigned int histheight = 0;
|
||||
for (int i=0; i<256; i++)
|
||||
if (bghist[i]>histheight)
|
||||
histheight = bghist[i];
|
||||
// draw histogram
|
||||
cr->set_line_width (1.0);
|
||||
double stepSize = (innerWidth-1) / 256.0;
|
||||
cr->move_to (RADIUS, innerHeight-1+RADIUS);
|
||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||
for (int i=0; i<256; i++) {
|
||||
double val = bghist[i] * (double)(innerHeight-2) / (double)histheight;
|
||||
if (val>innerHeight-1)
|
||||
val = innerHeight-1;
|
||||
if (i>0)
|
||||
cr->line_to (i*stepSize+RADIUS, innerHeight-1+RADIUS-val);
|
||||
}
|
||||
cr->line_to (innerWidth-1+RADIUS, innerHeight-1+RADIUS);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
// draw the grid lines:
|
||||
cr->set_line_width (1.0);
|
||||
c = style->get_dark (state);
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
cr->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||
for (int i = 0; i < 5; i++) { // + 0.5 to align well with f(x)=x so it will cut through the center
|
||||
cr->move_to (RADIUS, MAX(0,i * (innerHeight + 0.5) / 4) + RADIUS);
|
||||
cr->line_to (innerWidth + RADIUS, MAX(0,i * (innerHeight + 0.5) / 4) + RADIUS);
|
||||
cr->move_to (MAX(0,i * innerWidth / 4) + RADIUS, RADIUS);
|
||||
cr->line_to (MAX(0,i * innerWidth / 4) + RADIUS, innerHeight + RADIUS);
|
||||
}
|
||||
cr->stroke ();
|
||||
|
||||
// draw f(x)=x line
|
||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||
std::valarray<double> ds (1);
|
||||
ds[0] = 4;
|
||||
cr->set_dash (ds, 0);
|
||||
cr->move_to (RADIUS, innerHeight + RADIUS);
|
||||
cr->line_to (innerWidth + RADIUS, RADIUS);
|
||||
cr->stroke ();
|
||||
cr->unset_dash ();
|
||||
|
||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||
cr->set_line_width (1.0);
|
||||
|
||||
// draw upper and lower bounds
|
||||
if (curve.type==DCT_Parametric && activeParam>0 && lpoint.size()>1 && upoint.size()>1) {
|
||||
cr->set_source_rgba (0.0, 0.0, 0.0, 0.15);
|
||||
cr->move_to (upoint[0].get_x(), upoint[0].get_y());
|
||||
for (int i=1; i<(int)upoint.size(); i++)
|
||||
cr->line_to (upoint[i].get_x(), upoint[i].get_y());
|
||||
cr->line_to (lpoint[lpoint.size()-1].get_x(), lpoint[lpoint.size()-1].get_y());
|
||||
for (int i=(int)lpoint.size()-2; i>=0; i--)
|
||||
cr->line_to (lpoint[i].get_x(), lpoint[i].get_y());
|
||||
cr->line_to (upoint[0].get_x(), upoint[0].get_y());
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
// draw the cage of the NURBS curve
|
||||
if (curve.type==DCT_NURBS) {
|
||||
std::valarray<double> ch_ds (1);
|
||||
ch_ds[0] = 2;
|
||||
cr->set_dash (ch_ds, 0);
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
std::vector<double> points = getPoints();
|
||||
for (int i = 1; i < (int)points.size(); ) {
|
||||
double x = ((innerWidth-1) * points[i++] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||
double y = innerHeight - ((innerHeight-1) * points[i++] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||
if (i==3)
|
||||
cr->move_to (x, y);
|
||||
else
|
||||
cr->line_to (x, y);
|
||||
}
|
||||
cr->stroke ();
|
||||
cr->unset_dash ();
|
||||
}
|
||||
|
||||
// draw curve
|
||||
cr->set_source_rgb (0.0, 0.0, 0.0);
|
||||
cr->move_to (point[0].get_x(), point[0].get_y());
|
||||
for (int i=1; i<(int)point.size(); i++)
|
||||
cr->line_to (point[i].get_x(), point[i].get_y());
|
||||
cr->stroke ();
|
||||
|
||||
// draw bullets
|
||||
if (curve.type!=DCT_Parametric)
|
||||
for (int i = 0; i < (int)curve.x.size(); ++i) {
|
||||
cr->set_source_rgb ((i == handle ? 1.0 : 0.0), 0.0, 0.0);
|
||||
double x = ((innerWidth-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, innerWidth);
|
||||
double y = innerHeight - ((innerHeight-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, innerHeight);
|
||||
|
||||
cr->arc (x, y, RADIUS+0.5, 0, 2*M_PI);
|
||||
cr->fill ();
|
||||
}
|
||||
|
||||
get_window()->draw_drawable (style->get_fg_gc (state), pixmap, 0, 0, 0, 0, innerWidth + RADIUS * 2, innerHeight + RADIUS * 2);
|
||||
}
|
||||
|
||||
bool MyDiagonalCurve::handleEvents (GdkEvent* event) {
|
||||
|
||||
CursorShape new_type = cursor_type;
|
||||
int src, dst;
|
||||
std::vector<double>::iterator itx, ity;
|
||||
|
||||
bool retval = false;
|
||||
int num = (int)curve.x.size();
|
||||
|
||||
/* innerWidth and innerHeight are the size of the graph */
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
|
||||
double minDistanceX = (double)(MIN_DISTANCE) / (double)(innerWidth-1);
|
||||
double minDistanceY = (double)(MIN_DISTANCE) / (double)(innerHeight-1);
|
||||
|
||||
if ((innerWidth < 0) || (innerHeight < 0))
|
||||
return false;
|
||||
|
||||
switch (event->type) {
|
||||
case Gdk::CONFIGURE:
|
||||
if (pixmap)
|
||||
pixmap.clear ();
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::EXPOSE:
|
||||
if (!pixmap) {
|
||||
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
|
||||
interpolate ();
|
||||
}
|
||||
draw (lit_point);
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_PRESS:
|
||||
if (curve.type!=DCT_Parametric) {
|
||||
if (event->button.button == 1) {
|
||||
buttonPressed = true;
|
||||
add_modal_grab ();
|
||||
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
findClosestPoint();
|
||||
|
||||
new_type = CSMove;
|
||||
if (distanceX > minDistanceX) {
|
||||
/* insert a new control point */
|
||||
if (num > 0) {
|
||||
if (clampedX > curve.x[closest_point])
|
||||
++closest_point;
|
||||
}
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
for (int i=0; i<closest_point; i++) { itx++; ity++; }
|
||||
curve.x.insert (itx, 0);
|
||||
curve.y.insert (ity, 0);
|
||||
num++;
|
||||
|
||||
// the graph is refreshed only if a new point is created (snaped to a pixel)
|
||||
curve.x[closest_point] = clampedX;
|
||||
curve.y[closest_point] = clampedY;
|
||||
|
||||
interpolate ();
|
||||
draw (closest_point);
|
||||
notifyListener ();
|
||||
}
|
||||
grab_point = closest_point;
|
||||
lit_point = closest_point;
|
||||
ugpX = curve.x[closest_point];
|
||||
ugpY = curve.y[closest_point];
|
||||
}
|
||||
if (buttonPressed) retval = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gdk::BUTTON_RELEASE:
|
||||
if (curve.type!=DCT_Parametric) {
|
||||
if (buttonPressed && event->button.button == 1) {
|
||||
buttonPressed = false;
|
||||
/* get the pointer position */
|
||||
getCursorPosition(event);
|
||||
findClosestPoint();
|
||||
|
||||
remove_modal_grab ();
|
||||
int previous_lit_point = lit_point;
|
||||
/* delete inactive points: */
|
||||
itx = curve.x.begin();
|
||||
ity = curve.y.begin();
|
||||
for (src = dst = 0; src < num; ++src)
|
||||
if (curve.x[src] >= 0.0) {
|
||||
curve.x[dst] = curve.x[src];
|
||||
curve.y[dst] = curve.y[src];
|
||||
++dst;
|
||||
++itx;
|
||||
++ity;
|
||||
}
|
||||
if (dst < src) {
|
||||
curve.x.erase (itx, curve.x.end());
|
||||
curve.y.erase (ity, curve.y.end());
|
||||
if (!curve.x.size()) {
|
||||
curve.x.push_back (0);
|
||||
curve.y.push_back (0);
|
||||
interpolate ();
|
||||
draw (lit_point);
|
||||
}
|
||||
}
|
||||
if (distanceX <= minDistanceX) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if (lit_point != previous_lit_point)
|
||||
draw (lit_point);
|
||||
grab_point = -1;
|
||||
retval = true;
|
||||
notifyListener ();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Gdk::LEAVE_NOTIFY:
|
||||
// Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case
|
||||
// The cursor will have to LEAVE another time after the drag...
|
||||
if (!buttonPressed)
|
||||
if (grab_point == -1) {
|
||||
new_type = CSArrow;
|
||||
lit_point = -1;
|
||||
draw (lit_point);
|
||||
}
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
case Gdk::MOTION_NOTIFY:
|
||||
if (curve.type == DCT_Linear || curve.type == DCT_Spline || curve.type == DCT_NURBS) {
|
||||
// get the pointer position
|
||||
getCursorPosition(event);
|
||||
|
||||
if (grab_point == -1) {
|
||||
// there's no point currently being moved
|
||||
int previous_lit_point = lit_point;
|
||||
findClosestPoint();
|
||||
if (distanceX <= minDistanceX) {
|
||||
new_type = CSMove;
|
||||
lit_point = closest_point;
|
||||
}
|
||||
else {
|
||||
new_type = CSPlus;
|
||||
lit_point = -1;
|
||||
}
|
||||
if (lit_point != previous_lit_point)
|
||||
draw (lit_point);
|
||||
}
|
||||
else {
|
||||
// a point is being moved
|
||||
|
||||
// bounds of the grabbed point
|
||||
double leftBound = (grab_point == 0 ) ? 0. : curve.x[grab_point-1];
|
||||
double rightBound = (grab_point == num-1) ? 1. : curve.x[grab_point+1];
|
||||
double const bottomBound = 0.;
|
||||
double const topBound = 1.;
|
||||
|
||||
double leftDeletionBound = leftBound - minDistanceX;
|
||||
double rightDeletionBound = rightBound + minDistanceX;
|
||||
double bottomDeletionBound = bottomBound - minDistanceY;
|
||||
double topDeletionBound = topBound + minDistanceY;
|
||||
|
||||
// we memorize the previous position of the point, for optimization purpose
|
||||
double prevPosX = curve.x[grab_point];
|
||||
double prevPosY = curve.y[grab_point];
|
||||
|
||||
// we memorize the previous position of the point, for optimization purpose
|
||||
ugpX += deltaX;
|
||||
ugpY += deltaY;
|
||||
|
||||
// handling limitations along X axis
|
||||
if (ugpX >= rightDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else if (ugpX <= leftDeletionBound && (grab_point > 0 && grab_point < (num-1))) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else
|
||||
// nextPosX is in bounds
|
||||
curve.x[grab_point] = CLAMP(ugpX, leftBound, rightBound);
|
||||
|
||||
// Handling limitations along Y axis
|
||||
if (ugpY >= topDeletionBound && grab_point != 0 && grab_point != num-1) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else if (ugpY <= bottomDeletionBound && grab_point != 0 && grab_point != num-1) {
|
||||
curve.x[grab_point] = -1.;
|
||||
}
|
||||
else
|
||||
// nextPosY is in the bounds
|
||||
curve.y[grab_point] = CLAMP(ugpY, 0.0, 1.0);
|
||||
|
||||
if (curve.x[grab_point] != prevPosX || curve.y[grab_point] != prevPosY) {
|
||||
// we recalculate the curve only if we have to
|
||||
interpolate ();
|
||||
draw (lit_point);
|
||||
notifyListener ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retval = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (new_type != cursor_type) {
|
||||
cursor_type = new_type;
|
||||
cursorManager.setCursor(cursor_type);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::getCursorPosition(GdkEvent* event) {
|
||||
int tx, ty;
|
||||
int prevCursorX, prevCursorY;
|
||||
double incrementX = 1. / (double)(innerWidth-1);
|
||||
double incrementY = 1. / (double)(innerHeight-1);
|
||||
|
||||
// getting the cursor position
|
||||
switch (event->type) {
|
||||
case (Gdk::MOTION_NOTIFY) :
|
||||
if (event->motion.is_hint) {
|
||||
get_window()->get_pointer (tx, ty, mod_type);
|
||||
}
|
||||
else {
|
||||
tx = (int)event->button.x;
|
||||
ty = (int)event->button.y;
|
||||
mod_type = (Gdk::ModifierType)event->button.state;
|
||||
}
|
||||
break;
|
||||
case (Gdk::BUTTON_PRESS) :
|
||||
case (Gdk::BUTTON_RELEASE) :
|
||||
tx = (int)event->button.x;
|
||||
ty = (int)event->button.y;
|
||||
mod_type = (Gdk::ModifierType)event->button.state;
|
||||
break;
|
||||
default :
|
||||
// The cursor position is not available
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (grab_point != -1) {
|
||||
prevCursorX = cursorX;
|
||||
prevCursorY = cursorY;
|
||||
}
|
||||
cursorX = tx - RADIUS;
|
||||
cursorY = (innerHeight-1) - (ty - RADIUS);
|
||||
|
||||
snapTo = ST_None;
|
||||
|
||||
// update deltaX/Y if the user drags a point
|
||||
if (grab_point != -1) {
|
||||
// set the dragging factor
|
||||
int control_key = mod_type & GDK_CONTROL_MASK;
|
||||
int shift_key = mod_type & GDK_SHIFT_MASK;
|
||||
|
||||
// the increment get smaller if modifier key are used, and "snap to" may be enabled
|
||||
if (control_key && shift_key) { snapTo = ST_Neighbors; }
|
||||
else if (control_key) { snapTo = ST_Identity; }
|
||||
else if (shift_key) { incrementX *= 0.04; incrementY *= 0.04; }
|
||||
|
||||
deltaX = (double)(cursorX - prevCursorX) * incrementX;
|
||||
deltaY = (double)(cursorY - prevCursorY) * incrementY;
|
||||
}
|
||||
// otherwise set the position of the new point (modifier keys has no effect here)
|
||||
else {
|
||||
double tempCursorX = cursorX * incrementX;
|
||||
double tempCursorY = cursorY * incrementY;
|
||||
clampedX = CLAMP (tempCursorX, 0., 1.); // X position of the pointer from the origin of the graph
|
||||
clampedY = CLAMP (tempCursorY, 0., 1.); // Y position of the pointer from the origin of the graph
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::findClosestPoint() {
|
||||
distanceX = 10.0; distanceY = 10.0;
|
||||
closest_point = -1;
|
||||
|
||||
if (curve.type!=DCT_Parametric) {
|
||||
for (int i = 0; i < (int)curve.x.size(); i++) {
|
||||
double dX = curve.x[i] - clampedX;
|
||||
double dY = curve.y[i] - clampedY;
|
||||
double currDistX = dX < 0. ? -dX : dX; //abs (dX);
|
||||
double currDistY = dY < 0. ? -dY : dY; //abs (dY);
|
||||
if (currDistX < distanceX) {
|
||||
distanceX = currDistX;
|
||||
distanceY = currDistY;
|
||||
closest_point = i;
|
||||
}
|
||||
else if (currDistX == distanceX && currDistY < distanceY) {
|
||||
// there is more than 1 point for that X coordinate, we select the closest point to the cursor
|
||||
distanceY = currDistY;
|
||||
closest_point = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<double> MyDiagonalCurve::getPoints () {
|
||||
std::vector<double> result;
|
||||
if (curve.type==DCT_Parametric) {
|
||||
result.push_back ((double)(DCT_Parametric));
|
||||
for (int i=0; i<(int)curve.x.size(); i++) {
|
||||
result.push_back (curve.x[i]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// the first value gives the type of the curve
|
||||
if (curve.type==DCT_Linear)
|
||||
result.push_back ((double)(DCT_Linear));
|
||||
else if (curve.type==DCT_Spline)
|
||||
result.push_back ((double)(DCT_Spline));
|
||||
else if (curve.type==DCT_NURBS)
|
||||
result.push_back ((double)(DCT_NURBS));
|
||||
// then we push all the points coordinate
|
||||
for (int i=0; i<(int)curve.x.size(); i++) {
|
||||
if (curve.x[i]>=0) {
|
||||
result.push_back (curve.x[i]);
|
||||
result.push_back (curve.y[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::setPoints (const std::vector<double>& p) {
|
||||
int ix = 0;
|
||||
DiagonalCurveType t = (DiagonalCurveType)p[ix++];
|
||||
curve.type = t;
|
||||
if (t==DCT_Parametric) {
|
||||
curve.x.clear ();
|
||||
curve.y.clear ();
|
||||
for (int i=1; i<(int)p.size(); i++)
|
||||
curve.x.push_back (p[ix++]);
|
||||
}
|
||||
else {
|
||||
curve.x.clear ();
|
||||
curve.y.clear ();
|
||||
for (int i=0; i<(int)p.size()/2; i++) {
|
||||
curve.x.push_back (p[ix++]);
|
||||
curve.y.push_back (p[ix++]);
|
||||
}
|
||||
activeParam = -1;
|
||||
}
|
||||
pixmap.clear ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::setType (DiagonalCurveType t) {
|
||||
|
||||
curve.type = t;
|
||||
pixmap.clear ();
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::setActiveParam (int ac) {
|
||||
|
||||
activeParam = ac;
|
||||
pixmap.clear ();
|
||||
queue_draw ();
|
||||
}
|
||||
|
||||
int diagonalmchistupdate (void* data) {
|
||||
|
||||
gdk_threads_enter ();
|
||||
|
||||
MyCurveIdleHelper* mcih = (MyCurveIdleHelper*)data;
|
||||
|
||||
if (mcih->destroyed) {
|
||||
if (mcih->pending == 1)
|
||||
delete mcih;
|
||||
else
|
||||
mcih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
mcih->clearPixmap ();
|
||||
mcih->myCurve->queue_draw ();
|
||||
|
||||
mcih->pending--;
|
||||
gdk_threads_leave ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::updateBackgroundHistogram (unsigned int* hist) {
|
||||
|
||||
if (hist!=NULL) {
|
||||
memcpy (bghist, hist, 256*sizeof(unsigned int));
|
||||
bghistvalid = true;
|
||||
}
|
||||
else
|
||||
bghistvalid = false;
|
||||
|
||||
mcih->pending++;
|
||||
g_idle_add (diagonalmchistupdate, mcih);
|
||||
|
||||
}
|
||||
|
||||
void MyDiagonalCurve::reset() {
|
||||
innerWidth = get_allocation().get_width() - RADIUS * 2;
|
||||
innerHeight = get_allocation().get_height() - RADIUS * 2;
|
||||
|
||||
switch (curve.type) {
|
||||
case DCT_Spline :
|
||||
case DCT_NURBS :
|
||||
curve.x.clear();
|
||||
curve.y.clear();
|
||||
curve.x.push_back(0.);
|
||||
curve.y.push_back(0.);
|
||||
curve.x.push_back(1.);
|
||||
curve.y.push_back(1.);
|
||||
grab_point = -1;
|
||||
lit_point = -1;
|
||||
interpolate ();
|
||||
break;
|
||||
case DCT_Parametric :
|
||||
// Nothing to do (?)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
draw(-1);
|
||||
}
|
||||
83
rtgui/mydiagonalcurve.h
Normal file
83
rtgui/mydiagonalcurve.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _MYDIAGONALCURVE_
|
||||
#define _MYDIAGONALCURVE_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <vector>
|
||||
#include <curvelistener.h>
|
||||
#include <cursormanager.h>
|
||||
#include <mycurve.h>
|
||||
|
||||
// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget
|
||||
enum DiagonalCurveType {
|
||||
DCT_Empty = -1,
|
||||
DCT_Linear, // 0
|
||||
DCT_Spline, // 1
|
||||
DCT_Parametric, // 2
|
||||
DCT_NURBS, // 3
|
||||
// Insert new curve type above this line
|
||||
DCT_Unchanged // Must remain the last of the enum
|
||||
};
|
||||
|
||||
class DiagonalCurveDescr {
|
||||
|
||||
public:
|
||||
DiagonalCurveType type;
|
||||
std::vector<double> x, y; // in case of parametric curves the curve parameters are stored in vector x. In other cases these vectors store the coordinates of the bullets.
|
||||
};
|
||||
|
||||
class MyDiagonalCurve : public MyCurve {
|
||||
|
||||
protected:
|
||||
DiagonalCurveDescr curve;
|
||||
int grab_point; // the point that the user is moving
|
||||
int closest_point; // the point that is the closest from the cursor
|
||||
int lit_point; // the point that is lit when the cursor is near it
|
||||
double clampedX; // clamped grabbed point X coordinates in the [0;1] range
|
||||
double clampedY; // clamped grabbed point Y coordinates in the [0;1] range
|
||||
double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double distanceX; // X distance from the cursor to the closest point
|
||||
double distanceY; // Y distance from the cursor to the closest point
|
||||
double ugpX; // unclamped grabbed point X coordinate in the graph
|
||||
double ugpY; // unclamped grabbed point Y coordinate in the graph
|
||||
int activeParam;
|
||||
unsigned int* bghist; // histogram values
|
||||
bool bghistvalid;
|
||||
void draw (int handle);
|
||||
void interpolate ();
|
||||
void getCursorPosition(GdkEvent* event);
|
||||
void findClosestPoint();
|
||||
std::vector<double> get_vector (int veclen);
|
||||
|
||||
public:
|
||||
MyDiagonalCurve ();
|
||||
~MyDiagonalCurve ();
|
||||
std::vector<double> getPoints ();
|
||||
void setPoints (const std::vector<double>& p);
|
||||
void setType (DiagonalCurveType t);
|
||||
bool handleEvents (GdkEvent* event);
|
||||
void setActiveParam (int ac);
|
||||
void reset ();
|
||||
void updateBackgroundHistogram (unsigned int* hist);
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
1296
rtgui/myflatcurve.cc
Normal file
1296
rtgui/myflatcurve.cc
Normal file
File diff suppressed because it is too large
Load Diff
135
rtgui/myflatcurve.h
Normal file
135
rtgui/myflatcurve.h
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee 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 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee 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 RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef _MYFLATCURVE_
|
||||
#define _MYFLATCURVE_
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <vector>
|
||||
#include <curvelistener.h>
|
||||
#include <cursormanager.h>
|
||||
#include <mycurve.h>
|
||||
|
||||
// For compatibility and simplicity reason, order shouldn't change, and must be identical to the order specified in the curveType widget
|
||||
enum FlatCurveType {
|
||||
FCT_Empty = -1,
|
||||
FCT_Linear, // 0
|
||||
FCT_MinMaxCPoints, // 1
|
||||
//FCT_Parametric, // 2
|
||||
// Insert new curve type above this line
|
||||
FCT_Unchanged // Must remain the last of the enum
|
||||
};
|
||||
|
||||
enum MouseOverAreas {
|
||||
FCT_Area_None = 1<<0, // over a zone that don't have any
|
||||
FCT_Area_Insertion = 1<<1, // where the user can insert a new point
|
||||
FCT_Area_Point = 1<<2, // over an existing point
|
||||
FCT_Area_H = 1<<3, // cursor is on the horizontal line going through the edited control point
|
||||
FCT_Area_V = 1<<4, // cursor is on the vertical line going through the edited control point
|
||||
FCT_Area_LeftTan = 1<<5, // in the left tangent edition area
|
||||
FCT_Area_RightTan = 1<<6 // in the right tangent edition area
|
||||
};
|
||||
|
||||
enum EditedHandle {
|
||||
FCT_EditedHandle_None = 1<<0,
|
||||
FCT_EditedHandle_CPointUD = 1<<1, // UD stands for Unknown Direction
|
||||
FCT_EditedHandle_CPoint = 1<<2,
|
||||
FCT_EditedHandle_CPointX = 1<<3,
|
||||
FCT_EditedHandle_CPointY = 1<<4,
|
||||
FCT_EditedHandle_LeftTan = 1<<5,
|
||||
FCT_EditedHandle_RightTan = 1<<6
|
||||
};
|
||||
|
||||
class FlatCurveDescr {
|
||||
|
||||
public:
|
||||
FlatCurveType type;
|
||||
std::vector<double> x, // Range: [0.0 - 1.0]
|
||||
y, // Range: [0.0 - 1.0], default value = 0.5
|
||||
leftTangent, // Range: [0.0 - 1.0], where 1.0 = distance from previous to this point
|
||||
rightTangent; // Range: [0.0 - 1.0], where 1.0 = distance from this to next point
|
||||
};
|
||||
|
||||
class RectArea {
|
||||
|
||||
public:
|
||||
double top;
|
||||
double left;
|
||||
double bottom;
|
||||
double right;
|
||||
};
|
||||
|
||||
class HandlePosition {
|
||||
|
||||
public:
|
||||
double centerX;
|
||||
double centerY;
|
||||
};
|
||||
|
||||
class MyFlatCurve : public MyCurve {
|
||||
|
||||
protected:
|
||||
FlatCurveDescr curve;
|
||||
int closest_point; // the point that is the closest from the cursor
|
||||
int lit_point; // the point that is lit when the cursor is near it
|
||||
double clampedX; // clamped grabbed point X coordinates in the [0;1] range
|
||||
double clampedY; // clamped grabbed point Y coordinates in the [0;1] range
|
||||
double deltaX; // signed X distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double deltaY; // signed Y distance of the cursor between two consecutive MOTION_NOTIFY
|
||||
double distanceX; // X distance from the cursor to the closest point
|
||||
double distanceY; // Y distance from the cursor to the closest point
|
||||
double ugpX; // unclamped grabbed point X coordinate in the graph
|
||||
double ugpY; // unclamped grabbed point Y coordinate in the graph
|
||||
double leftTanX; // X position of the left tangent handle
|
||||
double rightTanX; // X position of the right tangent handle
|
||||
double preciseCursorX; // X coordinate in the graph of the cursor, as a double value
|
||||
double preciseCursorY; // Y coordinate in the graph of the cursor, as a double value
|
||||
double minDistanceX; // X minimal distance before point suppression
|
||||
double minDistanceY; // Y minimal distance before point suppression
|
||||
double deletedPointX; // Backup of the X value of the edited point, when deleted while being dragged
|
||||
//RectArea leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle
|
||||
//RectArea rightTanHandle; // XY coordinate if the upper left and bottom right corner of the right tangent handle
|
||||
HandlePosition leftTanHandle; // XY coordinate if the upper left and bottom right corner of the left tangent handle
|
||||
HandlePosition rightTanHandle; // XY coordinate if the upper left and bottom right corner of the right tangent handle
|
||||
bool tanHandlesDisplayed; // True if the tangent handles are displayed
|
||||
bool periodic; // Flat curves are periodic by default
|
||||
enum EditedHandle editedHandle;
|
||||
bool draggingElement;
|
||||
enum MouseOverAreas area;
|
||||
|
||||
void draw ();
|
||||
void movePoint(bool moveX, bool moveY);
|
||||
void defaultCurve ();
|
||||
void interpolate ();
|
||||
void getCursorPosition(GdkEvent* event);
|
||||
void getMouseOverArea ();
|
||||
bool getHandles(int n);
|
||||
std::vector<double> get_vector (int veclen);
|
||||
|
||||
public:
|
||||
MyFlatCurve ();
|
||||
//~MyFlatCurve ();
|
||||
std::vector<double> getPoints ();
|
||||
void setPoints (const std::vector<double>& p);
|
||||
void setType (FlatCurveType t);
|
||||
bool handleEvents (GdkEvent* event);
|
||||
void reset ();
|
||||
//void updateBackgroundHistogram (unsigned int* hist);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -157,18 +157,15 @@ void ParamsEdited::set (bool v) {
|
||||
raw.linenoise = v;
|
||||
equalizer.enabled = v;
|
||||
dirpyrequalizer.enabled = v;
|
||||
hsvequalizer.enabled = v;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
equalizer.c[i] = v;
|
||||
}
|
||||
for(int i = 0; i < 5; i++) {
|
||||
dirpyrequalizer.mult[i] = v;
|
||||
}
|
||||
for(int i = 0; i < 8; i++) {
|
||||
hsvequalizer.sat[i] = v;
|
||||
hsvequalizer.val[i] = v;
|
||||
hsvequalizer.hue[i] = v;
|
||||
}
|
||||
hsvequalizer.hcurve = v;
|
||||
hsvequalizer.scurve = v;
|
||||
hsvequalizer.vcurve = v;
|
||||
exif.clear ();
|
||||
iptc.clear ();
|
||||
}
|
||||
@@ -323,12 +320,9 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
|
||||
for(int i = 0; i < 8; i++) {
|
||||
dirpyrequalizer.mult[i] = dirpyrequalizer.mult[i] && p.dirpyrequalizer.mult[i] == other.dirpyrequalizer.mult[i];
|
||||
}
|
||||
hsvequalizer.enabled = hsvequalizer.enabled && p.hsvequalizer.enabled == other.hsvequalizer.enabled;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
hsvequalizer.sat[i] = hsvequalizer.sat[i] && p.hsvequalizer.sat[i] == other.hsvequalizer.sat[i];
|
||||
hsvequalizer.val[i] = hsvequalizer.val[i] && p.hsvequalizer.val[i] == other.hsvequalizer.val[i];
|
||||
hsvequalizer.hue[i] = hsvequalizer.hue[i] && p.hsvequalizer.hue[i] == other.hsvequalizer.hue[i];
|
||||
}
|
||||
hsvequalizer.hcurve = hsvequalizer.hcurve && p.hsvequalizer.hcurve == other.hsvequalizer.hcurve;
|
||||
hsvequalizer.scurve = hsvequalizer.scurve && p.hsvequalizer.scurve == other.hsvequalizer.scurve;
|
||||
hsvequalizer.vcurve = hsvequalizer.vcurve && p.hsvequalizer.vcurve == other.hsvequalizer.vcurve;
|
||||
// exif = exif && p.exif==other.exif
|
||||
// iptc = other.iptc;
|
||||
}
|
||||
@@ -474,12 +468,10 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
|
||||
for(int i = 0; i < 5; i++) {
|
||||
if(dirpyrequalizer.mult[i]) toEdit.dirpyrequalizer.mult[i] = mods.dirpyrequalizer.mult[i];
|
||||
}
|
||||
if (hsvequalizer.enabled) toEdit.hsvequalizer.enabled = mods.hsvequalizer.enabled;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(hsvequalizer.sat[i]) toEdit.hsvequalizer.sat[i] = mods.hsvequalizer.sat[i];
|
||||
if(hsvequalizer.val[i]) toEdit.hsvequalizer.val[i] = mods.hsvequalizer.val[i];
|
||||
if(hsvequalizer.hue[i]) toEdit.hsvequalizer.hue[i] = mods.hsvequalizer.hue[i];
|
||||
}
|
||||
if (hsvequalizer.hcurve) toEdit.hsvequalizer.hcurve = mods.hsvequalizer.hcurve;
|
||||
if (hsvequalizer.scurve) toEdit.hsvequalizer.scurve = mods.hsvequalizer.scurve;
|
||||
if (hsvequalizer.vcurve) toEdit.hsvequalizer.vcurve = mods.hsvequalizer.vcurve;
|
||||
|
||||
// if (exif) toEdit.exif==mo.exif = mods.exif==other.exif;
|
||||
// if (iptc;) toEdit.iptc==other.iptc; = mods.iptc==other.iptc;;
|
||||
}
|
||||
|
||||
@@ -269,11 +269,9 @@ public:
|
||||
class HSVEqualizerParamsEdited {
|
||||
|
||||
public:
|
||||
bool enabled;
|
||||
bool sat[8];
|
||||
bool val[8];
|
||||
bool hue[8];
|
||||
int hsvchannel;
|
||||
bool hcurve;
|
||||
bool scurve;
|
||||
bool vcurve;
|
||||
};
|
||||
|
||||
class RAWParamsEdited {
|
||||
@@ -321,11 +319,9 @@ class ParamsEdited {
|
||||
ColorShiftParamsEdited colorShift;
|
||||
LumaDenoiseParamsEdited lumaDenoise;
|
||||
ColorDenoiseParamsEdited colorDenoise;
|
||||
|
||||
DefringeParamsEdited defringe;
|
||||
DirPyrDenoiseParamsEdited dirpyrDenoise;
|
||||
ImpulseDenoiseParamsEdited impulseDenoise;
|
||||
|
||||
SHParamsEdited sh;
|
||||
CropParamsEdited crop;
|
||||
CoarseTransformParamsEdited coarse;
|
||||
|
||||
@@ -78,7 +78,7 @@ ToneCurve::ToneCurve () : Gtk::VBox(), FoldableToolPanel(this), expAdd(false),hl
|
||||
curveEditorG = new CurveEditorGroup (M("TP_EXPOSURE_CURVEEDITOR"));
|
||||
curveEditorG->setCurveListener (this);
|
||||
|
||||
shape = curveEditorG->addCurve();
|
||||
shape = (DiagonalCurveEditor*)curveEditorG->addCurve(CT_Diagonal, "");
|
||||
|
||||
// This will add the reset button at the end of the curveType buttons
|
||||
curveEditorG->curveListComplete();
|
||||
@@ -95,7 +95,7 @@ ToneCurve::ToneCurve () : Gtk::VBox(), FoldableToolPanel(this), expAdd(false),hl
|
||||
hlcomprthresh->setAdjusterListener (this);
|
||||
shcompr->setAdjusterListener (this);
|
||||
contrast->setAdjusterListener (this);
|
||||
saturation->setAdjusterListener (this);
|
||||
saturation->setAdjusterListener (this);
|
||||
}
|
||||
|
||||
void ToneCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
|
||||
@@ -394,6 +394,6 @@ void ToneCurve::setAdjusterBehavior (bool expadd, bool hlcompadd, bool hlcompthr
|
||||
}
|
||||
|
||||
void ToneCurve::updateCurveBackgroundHistogram (unsigned* hist) {
|
||||
|
||||
|
||||
shape->updateBackgroundHistogram (hist);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public FoldableTool
|
||||
bool expAdd,hlcompAdd,hlcompthreshAdd, blackAdd, shcompAdd, brAdd, contrAdd, satAdd, clipDirty, lastAuto;
|
||||
sigc::connection autoconn;
|
||||
CurveEditorGroup* curveEditorG;
|
||||
CurveEditor* shape;
|
||||
DiagonalCurveEditor* shape;
|
||||
double nextBr;
|
||||
int nextBl;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user