diff --git a/rtdata/images/curveType-NURBS.png b/rtdata/images/curveType-NURBS.png
new file mode 100644
index 000000000..81d78b517
Binary files /dev/null and b/rtdata/images/curveType-NURBS.png differ
diff --git a/rtdata/images/curveType-linear.png b/rtdata/images/curveType-linear.png
new file mode 100644
index 000000000..3b0ef7946
Binary files /dev/null and b/rtdata/images/curveType-linear.png differ
diff --git a/rtdata/images/curveType-parametric.png b/rtdata/images/curveType-parametric.png
new file mode 100644
index 000000000..4d2d0a7d3
Binary files /dev/null and b/rtdata/images/curveType-parametric.png differ
diff --git a/rtdata/images/curveType-spline.png b/rtdata/images/curveType-spline.png
new file mode 100644
index 000000000..794f6142c
Binary files /dev/null and b/rtdata/images/curveType-spline.png differ
diff --git a/rtdata/images/curveType-unchanged.png b/rtdata/images/curveType-unchanged.png
new file mode 100644
index 000000000..e89930a77
Binary files /dev/null and b/rtdata/images/curveType-unchanged.png differ
diff --git a/rtdata/languages/English b/rtdata/languages/English
index 21d94637c..23596a21d 100644
--- a/rtdata/languages/English
+++ b/rtdata/languages/English
@@ -10,6 +10,8 @@
!ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing
+!CURVEEDITOR_CURVE;Curve
+!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files
@@ -230,6 +232,8 @@
!HISTORY_MSG_90;Directional pyramid luminance
!HISTORY_MSG_91;Directional pyramid chominance
!HISTORY_MSG_92;Directional pyramid gamma
+!HISTORY_MSG_93;Contrast by detail levels parameter
+!HISTORY_MSG_94;Contrast by detail levels
!HISTORY_MSG_9;Highlight Compression
!HISTORY_NEWSNAPSHOT;Add
!HISTORY_NEWSNAPSHOTAS;As...
diff --git a/rtdata/languages/English (UK) b/rtdata/languages/English (UK)
index a98b3f047..7db4afff3 100644
--- a/rtdata/languages/English (UK)
+++ b/rtdata/languages/English (UK)
@@ -39,6 +39,8 @@ TP_HLREC_COLOR;Colour Propagation
!ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing
+!CURVEEDITOR_CURVE;Curve
+!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files
diff --git a/rtdata/languages/English (US) b/rtdata/languages/English (US)
index 97c9487c3..616903a98 100644
--- a/rtdata/languages/English (US)
+++ b/rtdata/languages/English (US)
@@ -10,6 +10,8 @@
!ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing
+!CURVEEDITOR_CURVE;Curve
+!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files
diff --git a/rtdata/languages/Francais b/rtdata/languages/Francais
index 880cde336..8f5ff5fd9 100644
--- a/rtdata/languages/Francais
+++ b/rtdata/languages/Francais
@@ -7,6 +7,8 @@
ADJUSTER_RESET_TO_DEFAULT;Réglages par défaut
BATCHQUEUE_AUTOSTART;Démarrage auto
BATCH_PROCESSING;Traitement par lot
+CURVEEDITOR_CURVE;Courbe
+CURVEEDITOR_CURVES;Courbes
CURVEEDITOR_CUSTOM;Personnalisé
CURVEEDITOR_DARKS;Zones sombres
CURVEEDITOR_FILEDLGFILTERANY;Tous les fichiers
@@ -224,6 +226,8 @@ HISTORY_MSG_8;Compensation d'exposition
HISTORY_MSG_90;Réd. de bruit Luminance
HISTORY_MSG_91;Réd. de bruit Chominance
HISTORY_MSG_92;Réd. de bruit Gamma
+HISTORY_MSG_93;Param. de contraste
+HISTORY_MSG_94;Contraste par niveau de détail
HISTORY_MSG_9;Compression des hautes lumières
HISTORY_NEWSNAPSHOT;Ajouter
HISTORY_NEWSNAPSHOTAS;Sous...
diff --git a/rtdata/languages/default b/rtdata/languages/default
index dbb0fbe87..3a65d7e42 100644
--- a/rtdata/languages/default
+++ b/rtdata/languages/default
@@ -3,6 +3,8 @@
ADJUSTER_RESET_TO_DEFAULT;Reset to default
BATCHQUEUE_AUTOSTART;Auto start
BATCH_PROCESSING;Batch processing
+CURVEEDITOR_CURVE;Curve
+CURVEEDITOR_CURVES;Curves
CURVEEDITOR_CUSTOM;Custom
CURVEEDITOR_DARKS;Darks
CURVEEDITOR_FILEDLGFILTERANY;Any files
@@ -223,6 +225,8 @@ HISTORY_MSG_8;Exposure Compensation
HISTORY_MSG_90;Directional pyramid luminance
HISTORY_MSG_91;Directional pyramid chominance
HISTORY_MSG_92;Directional pyramid gamma
+HISTORY_MSG_93;Contrast by detail levels parameter
+HISTORY_MSG_94;Contrast by detail levels
HISTORY_MSG_9;Highlight Compression
HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOTAS;As...
diff --git a/rtgui/CMakeLists.txt b/rtgui/CMakeLists.txt
index 4cba0b926..06f751323 100644
--- a/rtgui/CMakeLists.txt
+++ b/rtgui/CMakeLists.txt
@@ -12,7 +12,7 @@ set (BASESOURCEFILES
exifpanel.cc
sharpening.cc
whitebalance.cc vignetting.cc rotate.cc distortion.cc
- crophandler.cc curveeditor.cc dirbrowser.cc
+ crophandler.cc curveeditorgroup.cc curveeditor.cc dirbrowser.cc
filecatalog.cc
previewloader.cc
histogrampanel.cc history.cc imagearea.cc
@@ -26,7 +26,8 @@ set (BASESOURCEFILES
batchqueue.cc lwbutton.cc lwbuttonset.cc
batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc
profilestore.cc partialpastedlg.cc rawprocess.cc preprocess.cc
- equalizer.cc dirpyrequalizer.cc)
+ equalizer.cc dirpyrequalizer.cc
+ popupcommon.cc popupbutton.cc popuptogglebutton.cc)
if (WIN32)
set (EXTRA_SRC windirmonitor.cc myicon.o)
diff --git a/rtgui/curveeditor.cc b/rtgui/curveeditor.cc
index d156aaf98..6d2b6b11b 100644
--- a/rtgui/curveeditor.cc
+++ b/rtgui/curveeditor.cc
@@ -17,6 +17,7 @@
* along with RawTherapee. If not, see .
*/
#include
+#include
#include
#include
#include
@@ -24,495 +25,96 @@
extern Glib::ustring argv0;
-CurveEditor::CurveEditor () : cl(NULL), realized(false), curveTypeIx(Linear), activeParamControl(-1) {
+/*
+ * CurveEditor (CurveEditorGroup* ceGroup, Glib::ustring text)
+ *
+ * parameters:
+ * 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) {
- Gtk::HBox* tsbox = Gtk::manage (new Gtk::HBox ());
- Gtk::Label* tslab = Gtk::manage (new Gtk::Label (M("CURVEEDITOR_TYPE")));
- curveType = Gtk::manage (new Gtk::ComboBoxText ());
- curve_reset = Gtk::manage (new Gtk::Button ());
- curve_reset->add (*Gtk::manage (new Gtk::Image (argv0+"/images/undo.png")));
- curve_reset->set_relief (Gtk::RELIEF_NONE);
- curve_reset->set_border_width (0);
- curve_reset->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR"));
+ bgHistValid = false;
+ selected = Linear;
- tsbox->pack_start (*tslab, Gtk::PACK_SHRINK, 8);
- tsbox->pack_start (*curveType);
- tsbox->pack_start (*curve_reset, Gtk::PACK_SHRINK, 0);
-
- pack_start (*tsbox);
+ group = ceGroup;
+ if (group && text.size())
+ curveType = Gtk::manage (new PopUpToggleButton(text + ":", true));
+ else
+ curveType = Gtk::manage (new PopUpToggleButton());
+
+ curveType->set_image_position(Gtk::POS_RIGHT);
// Order set in the same order than "enum CurveType". Shouldn't change, for compatibility reason
- curveType->append_text (M("CURVEEDITOR_LINEAR")); // 0 Linear
- curveType->append_text (M("CURVEEDITOR_CUSTOM")); // 1 Spline
- curveType->append_text (M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric
- curveType->append_text (M("CURVEEDITOR_NURBS")); // 3 NURBS
- curveType->set_active (Linear);
+ 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) );
- curve_reset->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::curveResetPressed) );
-
- // custom curve
- customCurveBox = new Gtk::VBox ();
- 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::HBox* custombbox = Gtk::manage (new Gtk::HBox ());
- 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_EXPAND_WIDGET, 4);
- custombbox->pack_end (*loadCustom, Gtk::PACK_EXPAND_WIDGET, 4);
-
- customCurveBox->pack_end (*custombbox, Gtk::PACK_SHRINK, 2);
- customCurveBox->show_all ();
-
- saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) );
- loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::loadPressed) );
- saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
- loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
-
- // NURBS curve
- NURBSCurveBox = new Gtk::VBox ();
- 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::HBox* NURBSbbox = Gtk::manage (new Gtk::HBox ());
- 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_EXPAND_WIDGET, 4);
- NURBSbbox->pack_end (*loadNURBS, Gtk::PACK_EXPAND_WIDGET, 4);
-
- NURBSCurveBox->pack_end (*NURBSbbox, Gtk::PACK_SHRINK, 2);
- NURBSCurveBox->show_all ();
-
- saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::savePressed) );
- loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditor::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);
- typeconn = curveType->signal_changed().connect (sigc::mem_fun(*this, &CurveEditor::typeSelectionChanged) );
- evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 4));
- evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 5));
- evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 6));
- evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterEntered), 7));
- evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 4));
- evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 5));
- evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 6));
- evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &CurveEditor::adjusterLeft), 7));
-
- show_all ();
+ curveType->show();
}
+/*
CurveEditor::~CurveEditor () {
- delete customCurveBox;
- delete paramCurveBox;
}
+*/
-void CurveEditor::savePressed () {
-
- Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
-// if (options.multiUser)
-// dialog.set_current_folder (Options::rtdir + "/" + options.profilePath);
-// else
-// dialog.set_current_folder (argv0 + "/" + options.profilePath);
-
- dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
- dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK);
-
- Gtk::FileFilter filter_pp;
- filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE"));
- filter_pp.add_pattern("*.rtc");
- dialog.add_filter(filter_pp);
-
- Gtk::FileFilter filter_any;
- filter_any.set_name(M("CURVEEDITOR_FILEDLGFILTERANY"));
- filter_any.add_pattern("*");
- dialog.add_filter(filter_any);
-
- dialog.set_do_overwrite_confirmation (true);
-
- int result = dialog.run();
-
- if (result==Gtk::RESPONSE_OK) {
-
- std::string fname = dialog.get_filename();
-
- if (getExtension (fname)!="rtc")
- fname = fname + ".rtc";
-
- if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
- Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "";
- Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
- int response = msgd.run ();
- if (response==Gtk::RESPONSE_NO)
- return;
- }
-
- std::ofstream f (fname.c_str());
- std::vector p = customCurve->getPoints ();
-
- switch (curveType->get_active_row_number()) {
- 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;
- 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 ();
- }
- }
- }
-}
-
-void CurveEditor::on_realize () {
-
- Gtk::VBox::on_realize();
- realized = true;
- setCurve (tmpCurve);
-}
-
-void CurveEditor::setCurve (const std::vector& c) {
-
- tmpCurve = c;
-
- if (realized && curveType->get_active_row_number()<=Unchanged) { // if it is not realized or "unchanged" is selected, just store the curve (prev line) and do not change gui
-
- typeconn.block(true);
- if (c.size()==0 || c[0]==(double)(Linear)) {
- curveType->set_active (Linear); // Change the combo selection
- curveTypeIx = Linear;
- }
- else if (c[0]==(double)(Spline)) {
- curveType->set_active (Spline);
- curveTypeIx = Spline;
- customCurve->setPoints (c);
- }
- else if (c[0]==(double)(Parametric)) {
- curveType->set_active (Parametric);
- curveTypeIx = Parametric;
- paramCurve->setPoints (c);
- shcSelector->setPositions (c[1], c[2], c[3]);
- highlights->setValue (c[4]);
- lights->setValue (c[5]);
- darks->setValue (c[6]);
- shadows->setValue (c[7]);
- }
- else if (c[0]==(double)(NURBS)) {
- curveType->set_active (NURBS);
- curveTypeIx = NURBS;
- NURBSCurve->setPoints (c);
- }
- removeIfThere (this, customCurveBox, false);
- removeIfThere (this, paramCurveBox, false);
- removeIfThere (this, NURBSCurveBox, false);
-
- if (curveType->get_active_row_number()==Spline)
- pack_start (*customCurveBox);
- else if (curveType->get_active_row_number()==Parametric)
- pack_start (*paramCurveBox);
- else if (curveType->get_active_row_number()==NURBS)
- pack_start (*NURBSCurveBox);
-
- typeconn.block(false);
- }
+void CurveEditor::setCurve (const std::vector& p) {
+ tempCurve = p;
+ group->setCurveExternal(this, p);
}
std::vector CurveEditor::getCurve () {
+ std::vector curve;
- if (!realized || curveType->get_active_row_number()==Unchanged)
- return tmpCurve;
-
- // linear
- if (curveTypeIx<=Linear) {
- std::vector lcurve (1);
- lcurve[0] = (double)(Linear);
- return lcurve;
- }
- // parametric
- else if (curveTypeIx==Parametric) {
- std::vector 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;
- }
- // spline (custom)
- else if (curveTypeIx==Spline)
- return customCurve->getPoints ();
- // NURBS (control cage)
- else // Default solution, we return the NURBS curve (curveTypeIx==NURBS)
- return NURBSCurve->getPoints ();
-}
-
-void CurveEditor::typeSelectionChanged () {
-
- removeIfThere (this, customCurveBox, false);
- removeIfThere (this, paramCurveBox, false);
- removeIfThere (this, NURBSCurveBox, false);
-
- if (curveType->get_active_row_number()==Spline) {
- pack_start (*customCurveBox);
- }
- else if (curveType->get_active_row_number()==Parametric) {
- pack_start (*paramCurveBox);
- }
- else if (curveType->get_active_row_number()==NURBS) {
- pack_start (*NURBSCurveBox);
- }
-
- if (curveType->get_active_row_number() < Unchanged)
- curveTypeIx = (CurveType)curveType->get_active_row_number();
-
- curveChanged ();
-}
-
-void CurveEditor::curveChanged () {
-
- if (cl) {
- if (cl->isMulti())
- cl->curveChanged (this);
- else
- cl->curveChanged ();
- }
-}
-
-void CurveEditor::curveResetPressed () {
- switch (curveTypeIx) {
- case NURBS : // = Control cage
- NURBSCurve->reset ();
- break;
- case Spline : // = Custom
- customCurve->reset ();
- break;
- case Parametric :
- highlights->resetPressed();
- lights->resetPressed();
- darks->resetPressed();
- shadows->resetPressed();
- shcSelector->reset();
- paramCurve->reset ();
- break;
+ switch (selected) {
+ case (Spline):
+ return curve = customCurveEd;
+ case (Parametric):
+ return curve = paramCurveEd;
+ case (NURBS):
+ return curve = NURBSCurveEd;
default:
- break;
+ // returning Linear or Unchanged
+ curve.push_back((double)(selected));
+ return curve;
}
- curveChanged ();
}
-void CurveEditor::shcChanged () {
-
- paramCurve->setPoints (getCurve());
- if (cl) {
- if (cl->isMulti())
- cl->curveChanged (this);
- else
- cl->curveChanged ();
- }
+void CurveEditor::typeSelectionChanged (int n) {
+ group->typeSelectionChanged(this, n);
}
-void CurveEditor::adjusterChanged (Adjuster* a, double newval) {
-
- paramCurve->setPoints (getCurve());
- if (cl) {
- if (cl->isMulti())
- cl->curveChanged (this);
- else
- cl->curveChanged ();
- }
-}
-
-bool CurveEditor::adjusterEntered (GdkEventCrossing* ev, int ac) {
-
- if (ev->detail != GDK_NOTIFY_INFERIOR) {
- activeParamControl = ac;
- paramCurve->setActiveParam (activeParamControl);
- }
- return true;
-}
-
-bool CurveEditor::adjusterLeft (GdkEventCrossing* ev, int ac) {
-
- if (ev->detail != GDK_NOTIFY_INFERIOR) {
- activeParamControl = -1;
- paramCurve->setActiveParam (activeParamControl);
- }
- return true;
-}
-
-void CurveEditor::setBatchMode (bool batchMode) {
-
- curveType->append_text (M("GENERAL_UNCHANGED"));
+void CurveEditor::curveTypeToggled() {
+ group->curveTypeToggled(this);
}
bool CurveEditor::isUnChanged () {
-
- return curveType->get_active_row_number()==Unchanged;
+ return curveType->getSelected()==Unchanged;
}
void CurveEditor::setUnChanged (bool uc) {
-
- if (uc) {
- typeconn.block(true);
- removeIfThere (this, customCurveBox, false);
- removeIfThere (this, paramCurveBox, false);
- removeIfThere (this, NURBSCurveBox, false);
- curveType->set_active (Unchanged);
- typeconn.block(false);
- }
- else {
- typeconn.block(true);
- curveType->set_active (-1); // hack: if it remains 3 (unchanged), then setcurve does not switch selection in the combo
- setCurve (getCurve ());
- typeconn.block(false);
- }
+ group->setUnChanged(uc, this);
}
+/*
+ * Update the backgrounds histograms
+ */
void CurveEditor::updateBackgroundHistogram (unsigned int* hist) {
+ // Copy the histogram in the curve editor cache
+ if (hist!=NULL) {
+ memcpy (histogram, hist, 256*sizeof(unsigned int));
+ bgHistValid = true;
+ }
+ else
+ bgHistValid = false;
- paramCurve->updateBackgroundHistogram (hist);
- customCurve->updateBackgroundHistogram (hist);
- NURBSCurve->updateBackgroundHistogram (hist);
+ // Then call the curve editor group to eventually update the histogram
+ group->updateBackgroundHistogram (this);
}
diff --git a/rtgui/curveeditor.h b/rtgui/curveeditor.h
index bb9cd3638..fe8944912 100644
--- a/rtgui/curveeditor.h
+++ b/rtgui/curveeditor.h
@@ -1,85 +1,71 @@
-/*
- * This file is part of RawTherapee.
- *
- * Copyright (c) 2004-2010 Gabor Horvath
- *
- * 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 .
- */
-#ifndef _CURVEEDITOR_
-#define _CURVEEDITOR_
-
-#include
-#include
-#include
-#include
-
-class CurveEditor : public Gtk::VBox, public CurveListener, public SHCListener, public AdjusterListener {
-
- Gtk::ComboBoxText* curveType;
- Gtk::Button* curve_reset;
- Gtk::VBox* paramCurveBox;
- Gtk::VBox* customCurveBox;
- Gtk::VBox* NURBSCurveBox;
-
- MyCurve* customCurve;
- MyCurve* NURBSCurve;
- MyCurve* paramCurve;
- SHCSelector* shcSelector;
-
- Adjuster* highlights;
- Adjuster* lights;
- Adjuster* darks;
- Adjuster* shadows;
-
- Gtk::Button* saveCustom;
- Gtk::Button* loadCustom;
- Gtk::Button* saveNURBS;
- Gtk::Button* loadNURBS;
-
- CurveListener* cl;
-
- bool realized;
- std::vector tmpCurve;
- CurveType curveTypeIx;
-
- int activeParamControl;
-
- sigc::connection typeconn;
-
- public:
-
- CurveEditor ();
- virtual ~CurveEditor ();
- void setBatchMode (bool batchMode);
- bool isUnChanged ();
- void setUnChanged (bool uc);
-
- void on_realize ();
- void setCurveListener (CurveListener* l) { cl = l; }
- void savePressed ();
- void loadPressed ();
- void typeSelectionChanged ();
- void setCurve (const std::vector& c);
- std::vector getCurve ();
- void curveChanged ();
- void curveResetPressed ();
- void shcChanged ();
- void adjusterChanged (Adjuster* a, double newval);
- bool adjusterEntered (GdkEventCrossing* ev, int ac);
- bool adjusterLeft (GdkEventCrossing* ev, int ac);
- void updateBackgroundHistogram (unsigned int* hist);
-};
-
-
-#endif
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ */
+#ifndef _CURVEEDITOR_
+#define _CURVEEDITOR_
+
+#include
+#include
+#include
+#include
+
+class CurveEditorGroup;
+
+/*
+ * This class is an interface between RT and the curve editor group ; it handles the methods
+ * related to a specific curve. It is created by CurveEditorGroup::addCurve
+ */
+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[256]; // histogram values
+ bool bgHistValid;
+
+ CurveEditorGroup* group;
+ std::vector tempCurve;
+ std::vector customCurveEd;
+ std::vector paramCurveEd;
+ std::vector 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& p);
+ std::vector getCurve ();
+ bool isUnChanged ();
+ void setUnChanged (bool uc);
+ void updateBackgroundHistogram (unsigned int* hist);
+};
+
+
+#endif
diff --git a/rtgui/curveeditorgroup.cc b/rtgui/curveeditorgroup.cc
new file mode 100644
index 000000000..e85debb7f
--- /dev/null
+++ b/rtgui/curveeditorgroup.cc
@@ -0,0 +1,733 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+#include
+#include
+
+extern Glib::ustring argv0;
+
+CurveEditorGroup::CurveEditorGroup (Glib::ustring groupLabel) : cl(NULL), activeParamControl(-1) {
+ curveEditors.clear();
+ displayedCurve = 0;
+ numberOfPackedCurve = 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() {
+ for (std::vector::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i)
+ {
+ delete *i;
+ }
+ delete customCurveBox;
+ delete paramCurveBox;
+ delete NURBSCurveBox;
+}
+
+void CurveEditorGroup::hideCurrentCurve() {
+ // Setting the curve type to 'Unchanged' hide the CurveEditor
+ if (displayedCurve)
+ displayedCurve->curveType->set_active(false);
+}
+
+/*
+ * 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;
+}
+
+/*
+ * Use this method to start a new line of button
+ */
+void CurveEditorGroup::newLine() {
+ Gtk::HBox* headerBox;
+
+ if (curveEditors.size() > numberOfPackedCurve) {
+ headerBox = Gtk::manage (new Gtk::HBox ());
+
+ if (!numberOfPackedCurve) {
+ headerBox->pack_start(*curveGroupLabel, Gtk::PACK_SHRINK, 2);
+
+ curve_reset = Gtk::manage (new Gtk::Button ());
+ curve_reset->add (*Gtk::manage (new Gtk::Image (argv0+"/images/undo.png")));
+ curve_reset->set_relief (Gtk::RELIEF_NONE);
+ curve_reset->set_border_width (0);
+ curve_reset->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLINEAR"));
+ curve_reset->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::curveResetPressed) );
+
+ headerBox->pack_end (*curve_reset, Gtk::PACK_SHRINK, 0);
+ curve_reset->signal_clicked().connect( sigc::mem_fun(*this, &CurveEditorGroup::curveResetPressed) );
+ }
+
+ int j = numberOfPackedCurve;
+ for (int i = (int)(curveEditors.size())-1; i >= j; i--)
+ {
+ headerBox->pack_end (*curveEditors[i]->curveType, Gtk::PACK_EXPAND_WIDGET, 2);
+ numberOfPackedCurve++;
+ }
+
+ pack_start (*headerBox, Gtk::PACK_SHRINK, 2);
+ }
+
+
+}
+
+/*
+ * Create all the widgets now that the curve list is complete
+ * This method should handle all curve number correctly, i.e. eventually display the curve type buttons
+ * in a grid (or table)
+ */
+void CurveEditorGroup::curveListComplete() {
+ newLine();
+
+ // 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") + ":");
+
+ if (curveEditors.size() > 1)
+ cl->setMulti(true);
+}
+
+/*
+ * Callback method used when a curve type button has changed ;
+ * it will activate the button, and so emit 'signal_toggled' (-> curveTypeToggled here under)
+ */
+void CurveEditorGroup::typeSelectionChanged (CurveEditor* ce, int n) {
+ // Same type : do nothing
+ if (ce==displayedCurve && (CurveType)n==ce->selected)
+ return;
+
+ if ((CurveType)(n)selected = (CurveType)n;
+
+ // The user selected a new type from a toggled off button
+ if (ce!=displayedCurve)
+ // We toggle off the other curve: it will emit the toggle off signal
+ hideCurrentCurve();
+
+ // If the button was not pressed before
+ if (!ce->curveType->get_active()) {
+ storeDisplayedCurve();
+ // We set it pressed : it will emit the toggle on signal and update the GUI
+ ce->curveType->set_active( n>Linear && nisMulti())
+ cl->curveChanged (ce);
+ else
+ cl->curveChanged ();
+ }
+ }
+ else
+ curveChanged ();
+ }
+ else {
+ // The button is already pressed so we switch the GUI ourselves
+ switchGUI();
+ curveChanged ();
+ }
+}
+
+/*
+ * Callback method used when a button has been toggled on/off
+ * It then hide any other displayed curve and display it's curve
+ */
+void CurveEditorGroup::curveTypeToggled(CurveEditor* ce) {
+ bool curveRestored = false;
+
+ // Looking for the button state
+ if (ce->curveType->get_active()) {
+ // The button is now pressed, so we have to first hide all other CurveEditor
+ hideCurrentCurve();
+
+ displayedCurve = ce;
+
+ if (ce->curveType->getSelected()==Unchanged) {
+ curveRestored = true;
+ ce->curveType->setSelected(ce->selected);
+ }
+
+ // then show this CurveEditor
+ int ct = ce->curveType->getSelected();
+ if (ct < Unchanged)
+ restoreDisplayedHistogram();
+ }
+ else {
+ // The button is now released, so we have to hide this CurveEditor
+ displayedCurve = 0;
+ }
+ switchGUI();
+
+ if (curveRestored)
+ curveChanged ();
+
+}
+
+/*
+ * Switch the editor widgets to the currently edited curve
+ */
+void CurveEditorGroup::switchGUI() {
+
+ removeEditor();
+
+ 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;
+ }
+
+ //displayedCurve->typeconn.block(false);
+ }
+}
+
+void CurveEditorGroup::savePressed () {
+
+ Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE);
+// if (options.multiUser)
+// dialog.set_current_folder (Options::rtdir + "/" + options.profilePath);
+// else
+// dialog.set_current_folder (argv0 + "/" + options.profilePath);
+
+ dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
+ dialog.add_button(Gtk::StockID("gtk-save"), Gtk::RESPONSE_OK);
+
+ Gtk::FileFilter filter_pp;
+ filter_pp.set_name(M("CURVEEDITOR_FILEDLGFILTERCURVE"));
+ filter_pp.add_pattern("*.rtc");
+ dialog.add_filter(filter_pp);
+
+ Gtk::FileFilter filter_any;
+ filter_any.set_name(M("CURVEEDITOR_FILEDLGFILTERANY"));
+ filter_any.add_pattern("*");
+ dialog.add_filter(filter_any);
+
+ dialog.set_do_overwrite_confirmation (true);
+
+ int result = dialog.run();
+
+ if (result==Gtk::RESPONSE_OK) {
+
+ std::string fname = dialog.get_filename();
+
+ if (getExtension (fname)!="rtc")
+ fname = fname + ".rtc";
+
+ if (Glib::file_test (fname, Glib::FILE_TEST_EXISTS)) {
+ Glib::ustring msg_ = Glib::ustring("") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "";
+ Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
+ int response = msgd.run ();
+ if (response==Gtk::RESPONSE_NO)
+ return;
+ }
+
+ std::ofstream f (fname.c_str());
+ std::vector 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;
+ 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 ();
+ }
+ }
+ }
+}
+
+/*
+ * 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& 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()curveType->setSelected(ce->selected);
+
+ // if not displayed or "unchanged" is selected, do not change gui
+ if (ce==displayedCurve && ce->curveType->getSelected()& 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 CurveEditorGroup::getCurveFromGUI (CurveType type) {
+ switch (type) {
+ case (Parametric): {
+ std::vector 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 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::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);
+ printf(" - fait! (ce==displayedCurve)");
+ }
+}
diff --git a/rtgui/curveeditorgroup.h b/rtgui/curveeditorgroup.h
new file mode 100644
index 000000000..19a361932
--- /dev/null
+++ b/rtgui/curveeditorgroup.h
@@ -0,0 +1,108 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ */
+#ifndef _CURVEEDITORGROUP_
+#define _CURVEEDITORGROUP_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * This class handle the curve widgets, shared between any number curve
+ * - to add a curve to the list, use the 'addCurve' method
+ * - 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 {
+
+private:
+ 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 curveEditors;
+ CurveEditor* displayedCurve;
+
+ int activeParamControl;
+
+ 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& 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 getCurveFromGUI (CurveType type);
+ void updateBackgroundHistogram (CurveEditor* ce);
+
+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& c);
+ //void on_realize ();
+ void setCurveListener (CurveListener* l) { cl = l; }
+};
+
+#endif
diff --git a/rtgui/labcurve.cc b/rtgui/labcurve.cc
index e8a38f6a3..be30e66df 100644
--- a/rtgui/labcurve.cc
+++ b/rtgui/labcurve.cc
@@ -23,28 +23,6 @@ using namespace rtengine;
using namespace rtengine::procparams;
LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) {
-
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-/*
- Gtk::HBox* hb = Gtk::manage (new Gtk::HBox ());
- hb->set_border_width (4);
- hb->show ();
- Gtk::Label* labchan = Gtk::manage (new Gtk::Label (M("TP_LABCURVE_CHANNEL")+":"));
- labchan->show ();
- channel = Gtk::manage (new Gtk::ComboBoxText ());
- channel->append_text (M("TP_LCURVE"));
- channel->append_text (M("TP_ACURVE"));
- channel->append_text (M("TP_BCURVE"));
- channel->show ();
- hb->pack_start(*labchan, Gtk::PACK_SHRINK, 4);
- hb->pack_start(*channel);
- pack_start (*hb);
-*/
- //%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-
- Gtk::HBox* abox = Gtk::manage (new Gtk::HBox ());
- abox->set_border_width (2);
brightness = Gtk::manage (new Adjuster (M("TP_LABCURVE_BRIGHTNESS"), -100, 100, 0.01, 0));
contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100, 100, 1, 0));
@@ -55,7 +33,7 @@ LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) {
pack_start (*contrast);
contrast->show ();
-
+
pack_start (*saturation);
saturation->show ();
@@ -63,25 +41,19 @@ LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) {
hsep3->show ();
pack_start (*hsep3);
- lshape = Gtk::manage (new CurveEditor ());
- lshape->show ();
- lshape->setCurveListener (this);
- CurveListener::setMulti(true);
-
- ashape = Gtk::manage (new CurveEditor ());
- ashape->show ();
- ashape->setCurveListener (this);
- CurveListener::setMulti(true);
-
- bshape = Gtk::manage (new CurveEditor ());
- bshape->show ();
- bshape->setCurveListener (this);
- CurveListener::setMulti(true);
+ curveEditorG = new CurveEditorGroup ();
+ curveEditorG->setCurveListener (this);
- pack_start (*lshape, Gtk::PACK_SHRINK, 4);
- pack_start (*ashape, Gtk::PACK_SHRINK, 4);
- pack_start (*bshape, Gtk::PACK_SHRINK, 4);
+ lshape = curveEditorG->addCurve("L");
+ ashape = curveEditorG->addCurve("a");
+ bshape = curveEditorG->addCurve("b");
+ // This will add the reset button at the end of the curveType buttons
+ curveEditorG->curveListComplete();
+
+ pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4);
+
+ //curveEditorG->show();
brightness->setAdjusterListener (this);
contrast->setAdjusterListener (this);
@@ -92,6 +64,10 @@ LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) {
}
+LCurve::~LCurve () {
+ delete curveEditorG;
+}
+
void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener ();
@@ -159,6 +135,12 @@ void LCurve::setDefaults (const ProcParams* defParams, const ParamsEdited* pedit
}
}
+/*
+ * 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 LCurve::curveChanged (CurveEditor* ce) {
if (listener) {
@@ -217,9 +199,7 @@ void LCurve::setBatchMode (bool batchMode) {
contrast->showEditedCB ();
saturation->showEditedCB ();
- lshape->setBatchMode (batchMode);
- ashape->setBatchMode (batchMode);
- bshape->setBatchMode (batchMode);
+ curveEditorG->setBatchMode (batchMode);
}
void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) {
diff --git a/rtgui/labcurve.h b/rtgui/labcurve.h
index 14dc531f2..ce404f959 100644
--- a/rtgui/labcurve.h
+++ b/rtgui/labcurve.h
@@ -30,6 +30,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, publ
protected:
Gtk::ComboBoxText* channel;
+ CurveEditorGroup* curveEditorG;
Adjuster* brightness;
Adjuster* contrast;
Adjuster* saturation;
@@ -42,6 +43,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, publ
public:
LCurve ();
+ ~LCurve ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);
diff --git a/rtgui/mycurve.cc b/rtgui/mycurve.cc
index 4430fabba..6805a9230 100644
--- a/rtgui/mycurve.cc
+++ b/rtgui/mycurve.cc
@@ -36,10 +36,10 @@ MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
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.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;
@@ -54,8 +54,8 @@ MyCurve::~MyCurve () {
mcih->destroyed = true;
else
delete mcih;
- curve.x.empty();
- curve.y.empty();
+ //curve.x.clear();
+ //curve.y.clear();
}
std::vector MyCurve::get_vector (int veclen) {
@@ -563,12 +563,12 @@ void MyCurve::findClosestPoint() {
}
std::vector MyCurve::getPoints () {
-
std::vector result;
if (curve.type==Parametric) {
result.push_back ((double)(Parametric));
- for (int i=0; i<(int)curve.x.size(); i++)
+ 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
@@ -579,17 +579,17 @@ std::vector MyCurve::getPoints () {
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++)
+ 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& p) {
-
int ix = 0;
CurveType t = (CurveType)p[ix++];
curve.type = t;
diff --git a/rtgui/options.cc b/rtgui/options.cc
index 23c9aa8e9..fbb4065e6 100644
--- a/rtgui/options.cc
+++ b/rtgui/options.cc
@@ -105,7 +105,7 @@ void Options::setDefaults () {
editorToSendTo = 1;
liveThumbnails = true;
tpOpen.clear ();
- crvOpen.clear ();
+ //crvOpen.clear ();
parseExtensions.clear ();
parseExtensionsEnabled.clear ();
renameUseTemplates = false;
@@ -266,7 +266,7 @@ if (keyFile.has_group ("GUI")) {
if (keyFile.has_key ("GUI", "FrameColor")) bgcolor = keyFile.get_integer ("GUI", "FrameColor");
if (keyFile.has_key ("GUI", "ProcessingQueueEnbled"))procQueueEnabled = keyFile.get_boolean ("GUI", "ProcessingQueueEnbled");
if (keyFile.has_key ("GUI", "ToolPanelsExpanded")) tpOpen = keyFile.get_integer_list ("GUI", "ToolPanelsExpanded");
- if (keyFile.has_key ("GUI", "CurvePanelsExpanded")) crvOpen = keyFile.get_integer_list ("GUI", "CurvePanelsExpanded");
+ //if (keyFile.has_key ("GUI", "CurvePanelsExpanded")) crvOpen = keyFile.get_integer_list ("GUI", "CurvePanelsExpanded");
}
@@ -395,8 +395,8 @@ int Options::saveToFile (Glib::ustring fname) {
keyFile.set_boolean ("GUI", "ProcessingQueueEnbled", procQueueEnabled);
Glib::ArrayHandle tpopen = tpOpen;
keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen);
- Glib::ArrayHandle crvopen = crvOpen;
- keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen);
+ //Glib::ArrayHandle crvopen = crvOpen;
+ //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen);
keyFile.set_integer ("Crop Settings", "DPI", cropDPI);
diff --git a/rtgui/options.h b/rtgui/options.h
index c56475948..da848cd50 100644
--- a/rtgui/options.h
+++ b/rtgui/options.h
@@ -116,7 +116,7 @@ class Options {
std::vector parseExtensions;
std::vector parseExtensionsEnabled;
std::vector tpOpen;
- std::vector crvOpen;
+ //std::vector crvOpen;
std::vector baBehav;
rtengine::Settings rtSettings;
diff --git a/rtgui/popupbutton.cc b/rtgui/popupbutton.cc
new file mode 100644
index 000000000..bc201ce77
--- /dev/null
+++ b/rtgui/popupbutton.cc
@@ -0,0 +1,41 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+
+#include
+
+/*
+ * PopUpButton::PopUpButton (const Glib::ustring& label, bool imgRight)
+ *
+ * Creates a button with a contextual menu where you can select an item that the button content will reflect
+ *
+ * Parameters:
+ * label = label displayed in the button
+ * imRight = 0: the image is displayed at the left of the label (default)
+ * 1: the image is displayed at the right of the label
+ */
+PopUpButton::PopUpButton (const Glib::ustring& label, bool imgRight) : Gtk::Button(), PopUpCommon(this, label, imgRight) { }
+
+void PopUpButton::show() {
+ PopUpCommon::show();
+}
+void PopUpButton::set_tooltip_text (const Glib::ustring &text) {
+ PopUpCommon::set_tooltip_text (text);
+}
diff --git a/rtgui/popupbutton.h b/rtgui/popupbutton.h
new file mode 100644
index 000000000..3cf981a16
--- /dev/null
+++ b/rtgui/popupbutton.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+#ifndef _POPUPBUTTON_
+#define _POPUPBUTTON_
+
+#include
+#include
+
+class PopUpButton : public Gtk::Button, public PopUpCommon {
+
+public:
+ PopUpButton (const Glib::ustring& label = "", bool imgRight=false);
+ void show ();
+ void set_tooltip_text (const Glib::ustring &text);
+};
+
+#endif
diff --git a/rtgui/popupcommon.cc b/rtgui/popupcommon.cc
new file mode 100644
index 000000000..31e8ce674
--- /dev/null
+++ b/rtgui/popupcommon.cc
@@ -0,0 +1,141 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+
+#include
+#include
+
+PopUpCommon::PopUpCommon (Gtk::Button* thisButton, const Glib::ustring& label, bool imgRight) {
+ button = thisButton;
+ if (label.size()) {
+ hasText = true;
+ button->set_label(label + " ");
+ }
+ else
+ hasText = false;
+ // Create the list entry
+ imagePaths.clear();
+ images.clear();
+ sItems.clear();
+ items.clear();
+ selected = -1; // -1 : means that the button is invalid
+ menu = 0;
+ buttonImage = 0;
+ buttonHint = "";
+ imageRight = imgRight; // By default, image is on the left in the menu
+}
+
+PopUpCommon::~PopUpCommon () {
+ for (std::vector::iterator i = images.begin(); i != images.end(); ++i)
+ {
+ delete *i;
+ }
+ for (std::vector::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ delete *i;
+ }
+ if (menu) delete menu;
+ if (buttonImage) delete buttonImage;
+}
+
+PopUpCommon::type_signal_changed PopUpCommon::signal_changed() {
+ return message;
+}
+
+bool PopUpCommon::addEntry (Glib::ustring imagePath, Glib::ustring label) {
+ bool added = false;
+ if ( Glib::file_test(safe_locale_from_utf8(imagePath), Glib::FILE_TEST_EXISTS) && label.size() ) {
+ imagePaths.push_back(imagePath);
+ sItems.push_back(label);
+ // Create the image
+ Gtk::Image* newImage = new Gtk::Image(imagePath);
+ images.push_back(newImage);
+ int currPos = (int)images.size();
+ // Create the menu item
+ Gtk::ImageMenuItem* newItem = new Gtk::ImageMenuItem (*newImage, label);
+ items.push_back(newItem);
+ if (selected == -1) {
+ // Create the menu on the first item
+ menu = new Gtk::Menu ();
+ // Create the image for the button
+ buttonImage = new Gtk::Image(imagePath);
+ // Use the first image by default
+ if (hasText) {
+ button->set_image_position(imageRight ? Gtk::POS_RIGHT : Gtk::POS_LEFT);
+ button->set_image(*buttonImage);
+ }
+ else {
+ button->add(*buttonImage);
+ }
+ selected = 0;
+ }
+ newItem->signal_activate().connect (sigc::bind(sigc::mem_fun(*this, &PopUpCommon::entrySelected), currPos-1));
+ menu->attach (*newItem, 0, 1, currPos-1, currPos);
+ // When there is at least 2 choice, we add the RMB connector
+ if (images.size() == 2) {
+ button->signal_button_release_event().connect_notify( sigc::mem_fun(*this, &PopUpCommon::showMenu) );
+ }
+ // The item has been created
+ added = true;
+ }
+ return added;
+}
+
+// TODO: 'PopUpCommon::removeEntry' method to be created...
+
+void PopUpCommon::entrySelected (int i) {
+ if (setSelected((unsigned int)i))
+ // Emit a a signal if the selected item has changed
+ message.emit(selected);
+}
+
+/*
+ * Set the button image with the selected item
+ */
+bool PopUpCommon::setSelected (int entryNum) {
+ if (entryNum < 0 || entryNum > (int)images.size()-1 || (int)entryNum == selected)
+ return false;
+ else {
+ // Maybe we could do something better than loading the image file each time the selection is changed !?
+ buttonImage->set(imagePaths.at(entryNum));
+ selected = entryNum;
+ setButtonHint();
+ return true;
+ }
+}
+
+void PopUpCommon::show() {
+ menu->reposition();
+ setButtonHint();
+ menu->show_all();
+ button->show();
+}
+
+void PopUpCommon::setButtonHint() {
+ button->set_tooltip_text(buttonHint.size() ? buttonHint + " : " + sItems.at(selected) : sItems.at(selected));
+}
+
+void PopUpCommon::showMenu(GdkEventButton* event) {
+ if (event->button == 3) menu->popup(event->button, event->time);
+}
+
+void PopUpCommon::set_tooltip_text (const Glib::ustring &text) {
+ buttonHint = text;
+}
diff --git a/rtgui/popupcommon.h b/rtgui/popupcommon.h
new file mode 100644
index 000000000..22def0799
--- /dev/null
+++ b/rtgui/popupcommon.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+#ifndef _POPUPCOMMON_
+#define _POPUPCOMMON_
+
+
+#include
+#include
+
+
+class PopUpCommon {
+
+public:
+ typedef sigc::signal type_signal_changed;
+ type_signal_changed signal_changed();
+
+ PopUpCommon (Gtk::Button* button, const Glib::ustring& label = "", bool imgRight=false);
+ ~PopUpCommon ();
+ bool addEntry (Glib::ustring imagePath, Glib::ustring label);
+ bool setSelected (int entryNum);
+ int getSelected () { return selected; }
+ void setButtonHint();
+ void show ();
+ void set_tooltip_text (const Glib::ustring &text);
+
+private:
+ type_signal_changed message;
+
+ /*
+ TODO: MenuItem::get_label() seems to be buggy : it doesn't return any string, or an empty string !?
+ That's why we store entries strings in sItems, but it would be nice to get ride of it...
+ */
+ std::vector sItems;
+ std::vector imagePaths;
+ std::vector images;
+ std::vector items;
+ Glib::ustring buttonHint;
+ Gtk::Image* buttonImage;
+ Gtk::Menu* menu;
+ Gtk::Button* button;
+ int selected;
+ bool hasText;
+ bool imageRight;
+
+ void showMenu(GdkEventButton* event);
+ void entrySelected (int i);
+
+};
+
+#endif
diff --git a/rtgui/popuptogglebutton.cc b/rtgui/popuptogglebutton.cc
new file mode 100644
index 000000000..27e0bff30
--- /dev/null
+++ b/rtgui/popuptogglebutton.cc
@@ -0,0 +1,41 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+
+#include
+
+/*
+ * PopUpToggleButton::PopUpToggleButton (const Glib::ustring& label, bool imgRight)
+ *
+ * Creates a toggle button with a contextual menu where you can select an item that the button content will reflect
+ *
+ * Parameters:
+ * label = label displayed in the button
+ * imRight = 0: the image is displayed at the left of the label (default)
+ * 1: the image is displayed at the right of the label
+ */
+PopUpToggleButton::PopUpToggleButton (const Glib::ustring& label, bool imgRight) : Gtk::ToggleButton(), PopUpCommon(this, label, imgRight) { }
+
+void PopUpToggleButton::show() {
+ PopUpCommon::show();
+}
+void PopUpToggleButton::set_tooltip_text (const Glib::ustring &text) {
+ PopUpCommon::set_tooltip_text (text);
+}
diff --git a/rtgui/popuptogglebutton.h b/rtgui/popuptogglebutton.h
new file mode 100644
index 000000000..bc18a888f
--- /dev/null
+++ b/rtgui/popuptogglebutton.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of RawTherapee.
+ *
+ * Copyright (c) 2004-2010 Gabor Horvath
+ *
+ * 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 .
+ *
+ * Class created by Jean-Christophe FRISCH, aka 'Hombre'
+ */
+#ifndef _POPUPTOGGLEBUTTON_
+#define _POPUPTOGGLEBUTTON_
+
+#include
+#include
+
+class PopUpToggleButton : public Gtk::ToggleButton, public PopUpCommon {
+
+public:
+ PopUpToggleButton (const Glib::ustring& label = "", bool imgRight=false);
+ void show ();
+ void set_tooltip_text (const Glib::ustring &text);
+};
+
+#endif
diff --git a/rtgui/tonecurve.cc b/rtgui/tonecurve.cc
index 5f6c07547..01359dde3 100644
--- a/rtgui/tonecurve.cc
+++ b/rtgui/tonecurve.cc
@@ -72,12 +72,17 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
//----------- Curve ------------------------------
pack_start (*Gtk::manage (new Gtk::HSeparator()));
- shape = Gtk::manage (new CurveEditor ());
- shape->setCurveListener (this);
- curvexp = Gtk::manage (new Gtk::Expander (M("TP_EXPOSURE_CURVEEDITOR")));
- curvexp->add (*shape);
+ curveEditorG = new CurveEditorGroup (M("TP_EXPOSURE_CURVEEDITOR"));
+ curveEditorG->setCurveListener (this);
- pack_start (*curvexp, Gtk::PACK_SHRINK, 4);
+ shape = curveEditorG->addCurve();
+
+ // This will add the reset button at the end of the curveType buttons
+ curveEditorG->curveListComplete();
+
+ pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4);
+
+ //curveEditorG->show();
// --------- Set Up Listeners -------------
expcomp->setAdjusterListener (this);
@@ -267,7 +272,7 @@ void ToneCurve::waitForAutoExp () {
hlcompr->setEnabled (false);
shcompr->setEnabled (false);
contrast->setEnabled (false);
- shape->set_sensitive (false);
+ curveEditorG->set_sensitive (false);
}
int aexpcomputed (void* data) {
@@ -296,7 +301,7 @@ void ToneCurve::enableAll () {
hlcompr->setEnabled (true);
shcompr->setEnabled (true);
contrast->setEnabled (true);
- shape->set_sensitive (true);
+ curveEditorG->set_sensitive (true);
}
bool ToneCurve::autoExpComputed_ () {
@@ -310,17 +315,6 @@ bool ToneCurve::autoExpComputed_ () {
return false;
}
-void ToneCurve::expandCurve (bool isExpanded) {
-
- curvexp->set_expanded (isExpanded);
-}
-
-bool ToneCurve::isCurveExpanded () {
-
- return curvexp->get_expanded ();
-}
-
-
void ToneCurve::setBatchMode (bool batchMode) {
removeIfThere (abox, autolevels, false);
@@ -336,7 +330,7 @@ void ToneCurve::setBatchMode (bool batchMode) {
brightness->showEditedCB ();
contrast->showEditedCB ();
- shape->setBatchMode (batchMode);
+ curveEditorG->setBatchMode (batchMode);
}
void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) {
diff --git a/rtgui/tonecurve.h b/rtgui/tonecurve.h
index 900e6f34e..6af309cc1 100644
--- a/rtgui/tonecurve.h
+++ b/rtgui/tonecurve.h
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, public rtengine::AutoExpListener, public CurveListener {
@@ -39,8 +40,8 @@ class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, p
Adjuster* contrast;
bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto;
sigc::connection autoconn;
+ CurveEditorGroup* curveEditorG;
CurveEditor* shape;
- Gtk::Expander* curvexp;
double nextBr;
int nextBl;
diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc
index ef52ca239..9a8a200af 100644
--- a/rtgui/toolpanelcoord.cc
+++ b/rtgui/toolpanelcoord.cc
@@ -275,8 +275,8 @@ void ToolPanelCoordinator::readOptions () {
if (iset_expanded (options.tpOpen[i]);
- if (options.crvOpen.size()>1)
- curve->expandCurve (options.crvOpen[0]);
+ //if (options.crvOpen.size()>1)
+ // curve->expandCurve (options.crvOpen[0]);
}
void ToolPanelCoordinator::writeOptions () {
@@ -286,8 +286,8 @@ void ToolPanelCoordinator::writeOptions () {
for (int i=0; iget_expanded ());
- options.crvOpen.clear ();
- options.crvOpen.push_back (curve->isCurveExpanded());
+ //options.crvOpen.clear ();
+ //options.crvOpen.push_back (curve->isCurveExpanded());
}
diff --git a/tools/CurveType.svg b/tools/CurveType.svg
new file mode 100644
index 000000000..fde437f65
--- /dev/null
+++ b/tools/CurveType.svg
@@ -0,0 +1,205 @@
+
+
+