1 /*
2  *  This file is part of RawTherapee.
3  *
4  *  Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
5  *
6  *  RawTherapee is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  RawTherapee is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with RawTherapee.  If not, see <https://www.gnu.org/licenses/>.
18  */
19 
20 #include "clipboard.h"
21 #include <gtkmm.h>
22 #include <fstream>
23 #include <string>
24 #include "guiutils.h"
25 #include "multilangmgr.h"
26 #include "mycurve.h"
27 #include "shcselector.h"
28 #include "adjuster.h"
29 #include "mycurve.h"
30 #include "mydiagonalcurve.h"
31 #include "curveeditor.h"
32 #include "diagonalcurveeditorsubgroup.h"
33 #include "rtimage.h"
34 #include "options.h"
35 #include "popuptogglebutton.h"
36 
37 #include "../rtengine/curves.h"
38 
DiagonalCurveEditorSubGroup(CurveEditorGroup * prt,Glib::ustring & curveDir)39 DiagonalCurveEditorSubGroup::DiagonalCurveEditorSubGroup (CurveEditorGroup* prt, Glib::ustring& curveDir) : CurveEditorSubGroup(curveDir)
40 {
41 
42     editedAdjuster = nullptr;
43     editedAdjusterValue = 0;
44 
45     Gtk::PositionType sideStart = options.curvebboxpos == 0 || options.curvebboxpos == 2 ? Gtk::POS_LEFT : Gtk::POS_TOP;
46     Gtk::PositionType sideEnd = options.curvebboxpos == 0 || options.curvebboxpos == 2 ? Gtk::POS_RIGHT : Gtk::POS_BOTTOM;
47 
48     valLinear = (int)DCT_Linear;
49     valUnchanged = (int)DCT_Unchanged;
50     parent = prt;
51 
52     activeParamControl = -1;
53 
54     // custom curve
55     customCurveGrid = new Gtk::Grid ();
56     customCurveGrid->set_orientation(Gtk::ORIENTATION_VERTICAL);
57     customCurveGrid->get_style_context()->add_class("curve-mainbox");
58 
59     customCurve = Gtk::manage (new MyDiagonalCurve ());
60     customCurve->setType (DCT_Spline);
61 
62     Gtk::Grid* customCurveBox= Gtk::manage (new Gtk::Grid ());
63     customCurveBox->get_style_context()->add_class("curve-curvebox");
64     customCurveBox->add(*customCurve);
65 
66     Gtk::Grid* custombbox = Gtk::manage (new Gtk::Grid ()); // curvebboxpos 0=above, 1=right, 2=below, 3=left
67     custombbox->get_style_context()->add_class("curve-buttonbox");
68 
69     if (options.curvebboxpos == 0) {
70         custombbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
71         setExpandAlignProperties(custombbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
72         customCurveGrid->get_style_context()->add_class("top");
73     } else if (options.curvebboxpos == 2) {
74         custombbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
75         setExpandAlignProperties(custombbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
76         customCurveGrid->get_style_context()->add_class("bottom");
77     } else if (options.curvebboxpos == 1) {
78         custombbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
79         setExpandAlignProperties(custombbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
80         customCurveGrid->get_style_context()->add_class("right");
81     } else if (options.curvebboxpos == 3){
82         custombbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
83         setExpandAlignProperties(custombbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
84         customCurveGrid->get_style_context()->add_class("left");
85     }
86 
87     editPointCustom = Gtk::manage (new Gtk::ToggleButton ());
88     initButton(*editPointCustom, Glib::ustring("edit-point.png"), Gtk::ALIGN_START, false, "CURVEEDITOR_EDITPOINT_HINT");
89     editCustom = Gtk::manage (new Gtk::ToggleButton());
90     initButton(*editCustom, Glib::ustring("crosshair-node-curve.png"), Gtk::ALIGN_START, false, "EDIT_PIPETTE_TOOLTIP");
91     editCustom->hide();
92     copyCustom = Gtk::manage (new Gtk::Button ());
93     initButton(*copyCustom, Glib::ustring("copy.png"), Gtk::ALIGN_END, true);
94     pasteCustom = Gtk::manage (new Gtk::Button ());
95     initButton(*pasteCustom, Glib::ustring("paste.png"), Gtk::ALIGN_END, false);
96     loadCustom = Gtk::manage (new Gtk::Button ());
97     initButton(*loadCustom, Glib::ustring("folder-open.png"), Gtk::ALIGN_END, false);
98     saveCustom = Gtk::manage (new Gtk::Button ());
99     initButton(*saveCustom, Glib::ustring("save.png"), Gtk::ALIGN_END, false);
100 
101     custombbox->attach_next_to(*editPointCustom, sideStart, 1, 1);
102     custombbox->attach_next_to(*editCustom,      sideStart, 1, 1);
103     custombbox->attach_next_to(*copyCustom,      sideEnd, 1, 1);
104     custombbox->attach_next_to(*pasteCustom,     sideEnd, 1, 1);
105     custombbox->attach_next_to(*loadCustom,      sideEnd, 1, 1);
106     custombbox->attach_next_to(*saveCustom,      sideEnd, 1, 1);
107 
108     customCoordAdjuster = Gtk::manage (new CoordinateAdjuster(customCurve, this));
109     customCoordAdjuster->get_style_context()->add_class("curve-spinbuttonbox");
110 
111     // Button box position: 0=above, 1=right, 2=below, 3=left
112     customCurveGrid->add(*customCurveBox);
113     customCurve->set_hexpand(true);
114 
115     if (options.curvebboxpos == 0) {
116         customCurveGrid->attach_next_to(*custombbox, *customCurveBox, Gtk::POS_TOP, 1, 1);
117         customCurveGrid->attach_next_to(*customCoordAdjuster, *customCurveBox, Gtk::POS_BOTTOM, 1, 1);
118     } else if (options.curvebboxpos == 1) {
119         customCurveGrid->attach_next_to(*custombbox, *customCurveBox, Gtk::POS_RIGHT, 1, 1);
120         customCurveGrid->attach_next_to(*customCoordAdjuster, *customCurveBox, Gtk::POS_BOTTOM, 2, 1);
121     } else if (options.curvebboxpos == 2) {
122         customCurveGrid->attach_next_to(*customCoordAdjuster, *customCurveBox, Gtk::POS_BOTTOM, 1, 1);
123         customCurveGrid->attach_next_to(*custombbox, *customCoordAdjuster, Gtk::POS_BOTTOM, 1, 1);
124     } else if (options.curvebboxpos == 3) {
125         customCurveGrid->attach_next_to(*custombbox, *customCurveBox, Gtk::POS_LEFT, 1, 1);
126         customCurveGrid->attach_next_to(*customCoordAdjuster, *custombbox, Gtk::POS_BOTTOM, 2, 1);
127     }
128 
129     customCurveGrid->show_all ();
130     customCoordAdjuster->hide();
131 
132     saveCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) );
133     loadCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
134     copyCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) );
135     pasteCustom->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) );
136     editPointCustomConn = editPointCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointCustom) );
137     editCustomConn = editCustom->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editCustom) );
138 
139     saveCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
140     loadCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
141     copyCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY"));
142     pasteCustom->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE"));
143     // Custom curve end
144 
145 
146     // NURBS curve
147     NURBSCurveGrid = new Gtk::Grid ();
148     NURBSCurveGrid->set_orientation(Gtk::ORIENTATION_VERTICAL);
149     NURBSCurveGrid->get_style_context()->add_class("curve-mainbox");
150 
151     NURBSCurve = Gtk::manage (new MyDiagonalCurve ());
152     NURBSCurve->setType (DCT_NURBS);
153 
154     Gtk::Grid* NURBSCurveBox= Gtk::manage (new Gtk::Grid ());
155     NURBSCurveBox->get_style_context()->add_class("curve-curvebox");
156     NURBSCurveBox->add(*NURBSCurve);
157 
158     Gtk::Grid* NURBSbbox = Gtk::manage (new Gtk::Grid ());
159     NURBSbbox->get_style_context()->add_class("curve-buttonbox");
160 
161     if (options.curvebboxpos == 0) {
162         NURBSbbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
163         setExpandAlignProperties(NURBSbbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
164         NURBSCurveGrid->get_style_context()->add_class("top");
165     } else if (options.curvebboxpos == 2) {
166         NURBSbbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
167         setExpandAlignProperties(NURBSbbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
168         NURBSCurveGrid->get_style_context()->add_class("bottom");
169     } else if (options.curvebboxpos == 1) {
170         NURBSbbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
171         setExpandAlignProperties(NURBSbbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
172         NURBSCurveGrid->get_style_context()->add_class("right");
173     } else if (options.curvebboxpos == 3){
174         NURBSbbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
175         setExpandAlignProperties(NURBSbbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
176         NURBSCurveGrid->get_style_context()->add_class("left");
177     }
178 
179     editPointNURBS = Gtk::manage (new Gtk::ToggleButton ());
180     initButton(*editPointNURBS, Glib::ustring("edit-point.png"), Gtk::ALIGN_START, false, "CURVEEDITOR_EDITPOINT_HINT");
181     editNURBS = Gtk::manage (new Gtk::ToggleButton());
182     initButton(*editNURBS, Glib::ustring("crosshair-node-curve.png"), Gtk::ALIGN_START, false, "EDIT_PIPETTE_TOOLTIP");
183     editNURBS->hide();
184     copyNURBS = Gtk::manage (new Gtk::Button ());
185     initButton(*copyNURBS, Glib::ustring("copy.png"), Gtk::ALIGN_END, true);
186     pasteNURBS = Gtk::manage (new Gtk::Button ());
187     initButton(*pasteNURBS, Glib::ustring("paste.png"), Gtk::ALIGN_END, false);
188     loadNURBS = Gtk::manage (new Gtk::Button ());
189     initButton(*loadNURBS, Glib::ustring("folder-open.png"), Gtk::ALIGN_END, false);
190     saveNURBS = Gtk::manage (new Gtk::Button ());
191     initButton(*saveNURBS, Glib::ustring("save.png"), Gtk::ALIGN_END, false);
192 
193     NURBSbbox->attach_next_to(*editPointNURBS, sideStart, 1, 1);
194     NURBSbbox->attach_next_to(*editNURBS,      sideStart, 1, 1);
195     NURBSbbox->attach_next_to(*copyNURBS,      sideEnd,   1, 1);
196     NURBSbbox->attach_next_to(*pasteNURBS,     sideEnd,   1, 1);
197     NURBSbbox->attach_next_to(*loadNURBS,      sideEnd,   1, 1);
198     NURBSbbox->attach_next_to(*saveNURBS,      sideEnd,   1, 1);
199 
200     NURBSCoordAdjuster = Gtk::manage (new CoordinateAdjuster(NURBSCurve, this));
201     NURBSCoordAdjuster->get_style_context()->add_class("curve-spinbuttonbox");
202 
203     // Button box position: 0=above, 1=right, 2=below, 3=left
204     NURBSCurveGrid->add(*NURBSCurveBox);
205     NURBSCurve->set_hexpand(true);
206 
207     if (options.curvebboxpos == 0) {
208         NURBSCurveGrid->attach_next_to(*NURBSbbox, *NURBSCurveBox, Gtk::POS_TOP, 1, 1);
209         NURBSCurveGrid->attach_next_to(*NURBSCoordAdjuster, *NURBSCurveBox, Gtk::POS_BOTTOM, 1, 1);
210     } else if (options.curvebboxpos == 1) {
211         NURBSCurveGrid->attach_next_to(*NURBSbbox, *NURBSCurveBox, Gtk::POS_RIGHT, 1, 1);
212         NURBSCurveGrid->attach_next_to(*NURBSCoordAdjuster, *NURBSCurveBox, Gtk::POS_BOTTOM, 2, 1);
213     } else if (options.curvebboxpos == 2) {
214         NURBSCurveGrid->attach_next_to(*NURBSCoordAdjuster, *NURBSCurveBox, Gtk::POS_BOTTOM, 1, 1);
215         NURBSCurveGrid->attach_next_to(*NURBSbbox, *NURBSCoordAdjuster, Gtk::POS_BOTTOM, 1, 1);
216     } else if (options.curvebboxpos == 3) {
217         NURBSCurveGrid->attach_next_to(*NURBSbbox, *NURBSCurveBox, Gtk::POS_LEFT, 1, 1);
218         NURBSCurveGrid->attach_next_to(*NURBSCoordAdjuster, *NURBSbbox, Gtk::POS_BOTTOM, 2, 1);
219     }
220 
221     NURBSCurveGrid->show_all ();
222     NURBSCoordAdjuster->hide();
223 
224     saveNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) );
225     loadNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
226     pasteNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) );
227     copyNURBS->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) );
228     editPointNURBSConn = editPointNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editPointToggled), editPointNURBS) );
229     editNURBSConn = editNURBS->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editNURBS) );
230 
231     saveNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
232     loadNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
233     pasteNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE"));
234     copyNURBS->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY"));
235     // NURBS curve end
236 
237 
238     // parametric curve
239     paramCurveGrid = new Gtk::Grid ();
240     paramCurveGrid->set_orientation(Gtk::ORIENTATION_VERTICAL);
241     paramCurveGrid->get_style_context()->add_class("curve-mainbox");
242 
243     paramCurve = Gtk::manage (new MyDiagonalCurve ());
244     paramCurve->setType (DCT_Parametric);
245 
246     Gtk::Grid* paramCurveBox= Gtk::manage (new Gtk::Grid ());
247     paramCurveBox->get_style_context()->add_class("curve-curvebox");
248     paramCurveBox->add(*paramCurve);
249 
250     Gtk::Grid* parambbox = Gtk::manage (new Gtk::Grid ());
251     parambbox->get_style_context()->add_class("curve-buttonbox");
252 
253     if (options.curvebboxpos == 0) {
254         parambbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
255         setExpandAlignProperties(parambbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
256         paramCurveGrid->get_style_context()->add_class("top");
257     } else if (options.curvebboxpos == 2) {
258         parambbox->set_orientation(Gtk::ORIENTATION_HORIZONTAL);
259         setExpandAlignProperties(parambbox, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
260         paramCurveGrid->get_style_context()->add_class("bottom");
261     } else if (options.curvebboxpos == 1) {
262         parambbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
263         setExpandAlignProperties(parambbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
264         paramCurveGrid->get_style_context()->add_class("right");
265     } else if (options.curvebboxpos == 3){
266         parambbox->set_orientation(Gtk::ORIENTATION_VERTICAL);
267         setExpandAlignProperties(parambbox, false, true, Gtk::ALIGN_CENTER, Gtk::ALIGN_FILL);
268         paramCurveGrid->get_style_context()->add_class("left");
269     }
270 
271     shcSelector = Gtk::manage (new SHCSelector ());
272     shcSelector->set_name("CurveSHCSelector");
273     paramCurveBox->attach_next_to(*shcSelector, *paramCurve, Gtk::POS_BOTTOM, 1, 1);
274 
275     editParam = Gtk::manage (new Gtk::ToggleButton());
276     initButton(*editParam, Glib::ustring("crosshair-node-curve.png"), Gtk::ALIGN_START, false, "EDIT_PIPETTE_TOOLTIP");
277     editParam->hide();
278     copyParam = Gtk::manage (new Gtk::Button ());
279     initButton(*copyParam, Glib::ustring("copy.png"), Gtk::ALIGN_END, true);
280     pasteParam = Gtk::manage (new Gtk::Button ());
281     initButton(*pasteParam, Glib::ustring("paste.png"), Gtk::ALIGN_END, false);
282     loadParam = Gtk::manage (new Gtk::Button ());
283     initButton(*loadParam, Glib::ustring("folder-open.png"), Gtk::ALIGN_END, false);
284     saveParam = Gtk::manage (new Gtk::Button ());
285     initButton(*saveParam, Glib::ustring("save.png"), Gtk::ALIGN_END, false);
286 
287     parambbox->attach_next_to(*editParam,  sideStart, 1, 1);
288     parambbox->attach_next_to(*copyParam,  sideEnd,   1, 1);
289     parambbox->attach_next_to(*pasteParam, sideEnd,   1, 1);
290     parambbox->attach_next_to(*loadParam,  sideEnd,   1, 1);
291     parambbox->attach_next_to(*saveParam,  sideEnd,   1, 1);
292 
293     saveParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::savePressed) );
294     loadParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::loadPressed) );
295     pasteParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::pastePressed) );
296     copyParam->signal_clicked().connect( sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::copyPressed) );
297     editParamConn = editParam->signal_toggled().connect( sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::editToggled), editParam) );
298 
299     saveParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPSAVE"));
300     loadParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPLOAD"));
301     pasteParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPPASTE"));
302     copyParam->set_tooltip_text (M("CURVEEDITOR_TOOLTIPCOPY"));
303 
304     highlights = Gtk::manage (new Adjuster (M("CURVEEDITOR_HIGHLIGHTS"), -100, 100, 1, 0));
305     lights     = Gtk::manage (new Adjuster (M("CURVEEDITOR_LIGHTS"), -100, 100, 1, 0));
306     darks      = Gtk::manage (new Adjuster (M("CURVEEDITOR_DARKS"), -100, 100, 1, 0));
307     shadows    = Gtk::manage (new Adjuster (M("CURVEEDITOR_SHADOWS"), -100, 100, 1, 0));
308 
309     Gtk::EventBox* evhighlights = Gtk::manage (new Gtk::EventBox ());
310     Gtk::EventBox* evlights = Gtk::manage (new Gtk::EventBox ());
311     Gtk::EventBox* evdarks = Gtk::manage (new Gtk::EventBox ());
312     Gtk::EventBox* evshadows = Gtk::manage (new Gtk::EventBox ());
313 
314     evhighlights->add (*highlights);
315     evlights->add (*lights);
316     evdarks->add (*darks);
317     evshadows->add (*shadows);
318 
319     // paramCurveSliderBox needed to set vspacing(4) between curve+shc and sliders without vspacing between each slider
320     Gtk::Grid* paramCurveSliderBox = Gtk::manage (new Gtk::Grid());
321     paramCurveSliderBox->set_orientation(Gtk::ORIENTATION_VERTICAL);
322     paramCurveSliderBox->get_style_context()->add_class("curve-sliderbox");
323 
324     paramCurveSliderBox->attach_next_to(*evhighlights, Gtk::POS_TOP, 1, 1);
325     paramCurveSliderBox->attach_next_to(*evlights, Gtk::POS_TOP, 1, 1);
326     paramCurveSliderBox->attach_next_to(*evdarks, Gtk::POS_TOP, 1, 1);
327     paramCurveSliderBox->attach_next_to(*evshadows, Gtk::POS_TOP, 1, 1);
328 
329     paramCurveGrid->show_all ();
330 
331     // Button box position: 0=above, 1=right, 2=below, 3=left
332     paramCurveGrid->add(*paramCurveBox);
333     paramCurve->set_hexpand(true);
334 
335     if (options.curvebboxpos == 0) {
336         paramCurveGrid->attach_next_to(*parambbox, *paramCurveBox, Gtk::POS_TOP, 1, 1);
337         paramCurveGrid->attach_next_to(*paramCurveSliderBox, *paramCurveBox, Gtk::POS_BOTTOM, 1, 1);
338     } else if (options.curvebboxpos == 1) {
339         paramCurveGrid->attach_next_to(*parambbox, *paramCurveBox, Gtk::POS_RIGHT, 1, 1);
340         paramCurveGrid->attach_next_to(*paramCurveSliderBox, *paramCurveBox, Gtk::POS_BOTTOM, 2, 1);
341     } else if (options.curvebboxpos == 2) {
342         paramCurveGrid->attach_next_to(*parambbox, *paramCurveBox, Gtk::POS_BOTTOM, 1, 1);
343         paramCurveGrid->attach_next_to(*paramCurveSliderBox, *parambbox, Gtk::POS_BOTTOM, 1, 1);
344     } else if (options.curvebboxpos == 3) {
345         paramCurveGrid->attach_next_to(*parambbox, *paramCurveBox, Gtk::POS_LEFT, 1, 1);
346         paramCurveGrid->attach_next_to(*paramCurveSliderBox, *parambbox, Gtk::POS_BOTTOM, 2, 1);
347     }
348 
349     paramCurveGrid->show_all ();
350     // parametric curve end
351 
352 
353     customCurveGrid->reference ();
354     paramCurveGrid->reference ();
355 
356     customCurve->setCurveListener (parent); // Send the message directly to the parent
357     NURBSCurve->setCurveListener (parent);
358     paramCurve->setCurveListener (parent);
359     shcSelector->setSHCListener (this);
360 
361     highlights->setAdjusterListener (this);
362     lights->setAdjusterListener (this);
363     darks->setAdjusterListener (this);
364     shadows->setAdjusterListener (this);
365 
366     evhighlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
367     evlights->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
368     evdarks->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
369     evshadows->set_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK);
370     evhighlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 4));
371     evlights->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 5));
372     evdarks->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 6));
373     evshadows->signal_enter_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterEntered), 7));
374     evhighlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 4));
375     evlights->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 5));
376     evdarks->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 6));
377     evshadows->signal_leave_notify_event().connect (sigc::bind(sigc::mem_fun(*this, &DiagonalCurveEditorSubGroup::adjusterLeft), 7));
378 }
379 
~DiagonalCurveEditorSubGroup()380 DiagonalCurveEditorSubGroup::~DiagonalCurveEditorSubGroup()
381 {
382     delete customCurveGrid;
383     delete paramCurveGrid;
384     delete NURBSCurveGrid;
385 }
386 
387 /*
388  * Add a new curve to the curves list
389  */
addCurve(Glib::ustring curveLabel)390 DiagonalCurveEditor* DiagonalCurveEditorSubGroup::addCurve(Glib::ustring curveLabel)
391 {
392     DiagonalCurveEditor* newCE = new DiagonalCurveEditor(curveLabel, parent, this);
393 
394     // Initialization of the new curve
395     storeCurveValues(newCE, getCurveFromGUI(DCT_Spline));
396     storeCurveValues(newCE, getCurveFromGUI(DCT_Parametric));
397     storeCurveValues(newCE, getCurveFromGUI(DCT_NURBS));
398     storeCurveValues(newCE, getCurveFromGUI(DCT_CatumullRom));
399     return newCE;
400 }
401 
402 /*
403  * Switch off the edit button
404  */
editModeSwitchedOff()405 void DiagonalCurveEditorSubGroup::editModeSwitchedOff ()
406 {
407     // toggling off all edit buttons, even if only one is toggle on
408     bool prevState;
409     prevState = editCustomConn.block(true);
410     editCustom->set_active(false);
411     customCurve->pipetteMouseOver(nullptr, nullptr, 0);
412     customCurve->setDirty(true);
413 
414     if (!prevState) {
415         editCustomConn.block(false);
416     }
417 
418     prevState = editNURBSConn.block(true);
419     editNURBS->set_active(false);
420     NURBSCurve->pipetteMouseOver(nullptr, nullptr, 0);
421     NURBSCurve->setDirty(true);
422 
423     if (!prevState) {
424         editNURBSConn.block(false);
425     }
426 
427     prevState = editParamConn.block(true);
428     editParam->set_active(false);
429     paramCurve->pipetteMouseOver(nullptr, nullptr, 0);
430     paramCurve->setDirty(true);
431 
432     if (!prevState) {
433         editParamConn.block(false);
434     }
435 }
436 
pipetteMouseOver(EditDataProvider * provider,int modifierKey)437 void DiagonalCurveEditorSubGroup::pipetteMouseOver(EditDataProvider *provider, int modifierKey)
438 {
439     CurveEditor *curveEditor = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
440 
441     switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) {
442     case (DCT_Spline):
443     case (DCT_CatumullRom):
444         customCurve->pipetteMouseOver(curveEditor, provider, modifierKey);
445         customCurve->setDirty(true);
446         break;
447 
448     case (DCT_Parametric): {
449         paramCurve->pipetteMouseOver(curveEditor, provider, modifierKey);
450         paramCurve->setDirty(true);
451         float pipetteVal = 0.f;
452         editedAdjuster = nullptr;
453         int n = 0;
454 
455         if (provider->getPipetteVal1() != -1.f) {
456             pipetteVal += provider->getPipetteVal1();
457             ++n;
458         }
459 
460         if (provider->getPipetteVal2() != -1.f) {
461             pipetteVal += provider->getPipetteVal2();
462             ++n;
463         }
464 
465         if (provider->getPipetteVal3() != -1.f) {
466             pipetteVal += provider->getPipetteVal3();
467             ++n;
468         }
469 
470         if (n > 1) {
471             pipetteVal /= n;
472         } else if (!n) {
473             pipetteVal = -1.f;
474         }
475 
476         if (pipetteVal != -1.f) {
477             double pos[3];
478             shcSelector->getPositions(pos[0], pos[1], pos[2]);
479 
480             if     (pipetteVal >= pos[2]) {
481                 editedAdjuster = highlights;
482                 paramCurve->setActiveParam(4);
483             } else if(pipetteVal >= pos[1]) {
484                 editedAdjuster = lights;
485                 paramCurve->setActiveParam(5);
486             } else if(pipetteVal >= pos[0]) {
487                 editedAdjuster = darks;
488                 paramCurve->setActiveParam(6);
489             } else {
490                 editedAdjuster = shadows;
491                 paramCurve->setActiveParam(7);
492             }
493         } else {
494             paramCurve->setActiveParam(-1);
495         }
496     }
497     break;
498 
499     case (DCT_NURBS):
500         NURBSCurve->pipetteMouseOver(curveEditor, provider, modifierKey);
501         NURBSCurve->setDirty(true);
502         break;
503 
504     default:    // (DCT_Linear, DCT_Unchanged)
505         // ... do nothing
506         break;
507     }
508 }
509 
pipetteButton1Pressed(EditDataProvider * provider,int modifierKey)510 bool DiagonalCurveEditorSubGroup::pipetteButton1Pressed(EditDataProvider *provider, int modifierKey)
511 {
512     CurveEditor *curveEditor = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
513 
514     bool isDragging = false;
515 
516     switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) {
517     case (DCT_Spline):
518     case (DCT_CatumullRom):
519         isDragging = customCurve->pipetteButton1Pressed(provider, modifierKey);
520         break;
521 
522     case (DCT_Parametric):
523         if (editedAdjuster) {
524             editedAdjusterValue = editedAdjuster->getIntValue();
525         }
526 
527         break;
528 
529     case (DCT_NURBS):
530         isDragging = NURBSCurve->pipetteButton1Pressed(provider, modifierKey);
531         break;
532 
533     default:    // (DCT_Linear, DCT_Unchanged)
534         // ... do nothing
535         break;
536     }
537 
538     return isDragging;
539 }
540 
pipetteButton1Released(EditDataProvider * provider)541 void DiagonalCurveEditorSubGroup::pipetteButton1Released(EditDataProvider *provider)
542 {
543     CurveEditor *curveEditor = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
544 
545     switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) {
546     case (DCT_Spline):
547     case (DCT_CatumullRom):
548         customCurve->pipetteButton1Released(provider);
549         break;
550 
551     case (DCT_Parametric):
552         editedAdjuster = nullptr;
553         break;
554 
555     case (DCT_NURBS):
556         NURBSCurve->pipetteButton1Released(provider);
557         break;
558 
559     default:    // (DCT_Linear, DCT_Unchanged)
560         // ... do nothing
561         break;
562     }
563 }
564 
pipetteDrag(EditDataProvider * provider,int modifierKey)565 void DiagonalCurveEditorSubGroup::pipetteDrag(EditDataProvider *provider, int modifierKey)
566 {
567     CurveEditor *curveEditor = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
568 
569     switch((DiagonalCurveType)(curveEditor->curveType->getSelected())) {
570     case (DCT_Spline):
571     case (DCT_CatumullRom):
572         customCurve->pipetteDrag(provider, modifierKey);
573         break;
574 
575     case (DCT_Parametric):
576         if (editedAdjuster) {
577             int trimmedValue = editedAdjusterValue - (provider->deltaScreen.y / 2);
578             editedAdjuster->trimValue(trimmedValue);
579 
580             if (trimmedValue != editedAdjuster->getIntValue()) {
581                 editedAdjuster->setValue(trimmedValue);
582                 adjusterChanged(editedAdjuster, trimmedValue);
583             }
584         }
585 
586         break;
587 
588     case (DCT_NURBS):
589         NURBSCurve->pipetteDrag(provider, modifierKey);
590         break;
591 
592     default:    // (DCT_Linear, DCT_Unchanged)
593         // ... do nothing
594         break;
595     }
596 }
597 
showCoordinateAdjuster(CoordinateProvider * provider)598 void DiagonalCurveEditorSubGroup::showCoordinateAdjuster(CoordinateProvider *provider)
599 {
600     if (provider == customCurve) {
601         if (!editPointCustom->get_active()) {
602             editPointCustom->set_active(true);
603         }
604     } else if (provider == NURBSCurve) {
605         if (!editPointNURBS->get_active()) {
606             editPointNURBS->set_active(true);
607         }
608     }
609 }
610 
stopNumericalAdjustment()611 void DiagonalCurveEditorSubGroup::stopNumericalAdjustment()
612 {
613     customCurve->stopNumericalAdjustment();
614     NURBSCurve->stopNumericalAdjustment();
615 }
616 
617 /*
618  * Force the resize of the curve editor, if the displayed one is the requested one
619  */
refresh(CurveEditor * curveToRefresh)620 void DiagonalCurveEditorSubGroup::refresh(CurveEditor *curveToRefresh)
621 {
622     if (curveToRefresh != nullptr && curveToRefresh == static_cast<DiagonalCurveEditor*>(parent->displayedCurve)) {
623         switch((DiagonalCurveType)(curveToRefresh->curveType->getSelected())) {
624         case (DCT_Spline):
625         case (DCT_CatumullRom):
626             customCurve->refresh();
627             break;
628 
629         case (DCT_Parametric):
630             paramCurve->refresh();
631             shcSelector->refresh();
632             break;
633 
634         case (DCT_NURBS):
635             NURBSCurve->refresh();
636             break;
637 
638         default:    // (DCT_Linear, DCT_Unchanged)
639             // ... do nothing
640             break;
641         }
642     }
643 }
644 
645 /*
646  * Switch the editor widgets to the currently edited curve
647  */
switchGUI()648 void DiagonalCurveEditorSubGroup::switchGUI()
649 {
650 
651     removeEditor();
652 
653     DiagonalCurveEditor* dCurve = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
654 
655     if (dCurve) {
656 
657         // Initializing GUI values + attaching the appropriated widget
658         //dCurve->typeconn.block(true);
659 
660         // first we update the colored bar
661 
662         ColorProvider *barColorProvider = dCurve->getLeftBarColorProvider();
663         std::vector<GradientMilestone>  bgGradient = dCurve->getLeftBarBgGradient();
664 
665         if (barColorProvider == nullptr && bgGradient.size() == 0) {
666             // dCurve has no left colored bar, so we delete the object
667             if (leftBar) {
668                 delete leftBar;
669                 leftBar = nullptr;
670             }
671         } else {
672             // dCurve ave a ColorProvider or a background gradient defined, so we create/update the object
673             if (!leftBar) {
674                 leftBar = new ColoredBar(RTO_Bottom2Top);
675             }
676 
677             if (barColorProvider) {
678                 bgGradient.clear();
679                 leftBar->setColorProvider(barColorProvider, dCurve->getLeftBarCallerId());
680                 leftBar->setBgGradient (bgGradient);
681             } else {
682                 leftBar->setColorProvider(nullptr, -1);
683                 leftBar->setBgGradient (bgGradient);
684             }
685         }
686 
687         barColorProvider = dCurve->getBottomBarColorProvider();
688         bgGradient = dCurve->getBottomBarBgGradient();
689 
690         if (barColorProvider == nullptr && bgGradient.size() == 0) {
691             // dCurve has no bottom colored bar, so we delete the object
692             if (bottomBar) {
693                 delete bottomBar;
694                 bottomBar = nullptr;
695             }
696         } else {
697             // dCurve has a ColorProvider or a background gradient defined, so we create/update the object
698             if (!bottomBar) {
699                 bottomBar = new ColoredBar(RTO_Left2Right);
700             }
701 
702             if (barColorProvider) {
703                 bgGradient.clear();
704                 bottomBar->setColorProvider(barColorProvider, dCurve->getBottomBarCallerId());
705                 bottomBar->setBgGradient (bgGradient);
706             } else {
707                 bottomBar->setColorProvider(nullptr, -1);
708                 bottomBar->setBgGradient (bgGradient);
709             }
710         }
711 
712         switch(auto tp = (DiagonalCurveType)(dCurve->curveType->getSelected())) {
713         case (DCT_Spline):
714         case (DCT_CatumullRom):
715             customCurve->setPoints(tp == DCT_Spline ? dCurve->customCurveEd : dCurve->catmullRomCurveEd);
716             customCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId());
717             customCurve->setColoredBar(leftBar, bottomBar);
718             customCurve->queue_resize_no_redraw();
719             updateEditButton(dCurve, editCustom, editCustomConn);
720             parent->attachCurve (customCurveGrid);
721             customCurveGrid->check_resize();
722             break;
723 
724         case (DCT_Parametric): {
725             Glib::ustring label[4];
726             dCurve->getRangeLabels(label[0], label[1], label[2], label[3]);
727             double mileStone[3];
728             dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]);
729             paramCurve->setPoints (dCurve->paramCurveEd);
730             shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]);
731             shcSelector->setPositions (
732                 dCurve->paramCurveEd.at(1),
733                 dCurve->paramCurveEd.at(2),
734                 dCurve->paramCurveEd.at(3)
735             );
736 
737             double s = (double)RTScalable::getScale();
738             highlights->setValue (dCurve->paramCurveEd.at(4));
739             highlights->setLabel(label[3]);
740             lights->setValue (dCurve->paramCurveEd.at(5));
741             lights->setLabel(label[2]);
742             darks->setValue (dCurve->paramCurveEd.at(6));
743             darks->setLabel(label[1]);
744             shadows->setValue (dCurve->paramCurveEd.at(7));
745             shadows->setLabel(label[0]);
746             shcSelector->coloredBar.setColorProvider(barColorProvider, dCurve->getBottomBarCallerId());
747             shcSelector->coloredBar.setBgGradient(bgGradient);
748             shcSelector->setMargins(
749                     (int)( ((leftBar ? (double)CBAR_WIDTH + 2. + (double)CBAR_MARGIN + RADIUS : RADIUS) - 1.5) * s ),
750                     (int)((RADIUS - 1.5) * s)
751                     );
752             paramCurve->setColoredBar(leftBar, nullptr);
753             paramCurve->queue_resize_no_redraw();
754             updateEditButton(dCurve, editParam, editParamConn);
755             parent->attachCurve (paramCurveGrid);
756             break;
757         }
758 
759         case (DCT_NURBS):
760             NURBSCurve->setPoints (dCurve->NURBSCurveEd);
761             NURBSCurve->setColorProvider(dCurve->getCurveColorProvider(), dCurve->getCurveCallerId());
762             NURBSCurve->setColoredBar(leftBar, bottomBar);
763             NURBSCurve->queue_resize_no_redraw();
764             updateEditButton(dCurve, editNURBS, editNURBSConn);
765             parent->attachCurve (NURBSCurveGrid);
766             NURBSCurveGrid->check_resize();
767             break;
768 
769         default:    // (DCT_Linear, DCT_Unchanged)
770             // ... do nothing
771             break;
772         }
773 
774         //dCurve->typeconn.block(false);
775     }
776 }
777 
savePressed()778 void DiagonalCurveEditorSubGroup::savePressed ()
779 {
780 
781     Glib::ustring fname = outputFile();
782 
783     if (fname.size()) {
784         std::ofstream f (fname.c_str());
785         std::vector<double> p;
786         //std::vector<double> p = customCurve->getPoints ();
787 
788         switch (parent->displayedCurve->selected) {
789         case DCT_Spline:    // custom
790         case DCT_CatumullRom:
791             p = customCurve->getPoints ();
792             break;
793 
794         case DCT_NURBS:     // NURBS
795             p = NURBSCurve->getPoints ();
796             break;
797 
798         case DCT_Parametric:
799             p = paramCurve->getPoints ();
800             break;
801 
802         default:
803             break;
804         }
805 
806         int ix = 0;
807 
808         if (p[ix] == (double)(DCT_Linear)) {
809             f << "Linear" << std::endl;
810         } else if (p[ix] == (double)(DCT_Spline)) {
811             f << "Spline" << std::endl;
812         } else if (p[ix] == (double)(DCT_CatumullRom)) {
813             f << "CatmullRom" << std::endl;
814         } else if (p[ix] == (double)(DCT_NURBS)) {
815             f << "NURBS" << std::endl;
816         } else if (p[ix] == (double)(DCT_Parametric)) {
817             f << "Parametric" << std::endl;
818         }
819 
820         if (p[ix] == (double)(DCT_Parametric)) {
821             ix++;
822 
823             for (unsigned int i = 0; i < p.size() - 1; i++, ix++) {
824                 f << p[ix] << std::endl;
825             }
826         } else {
827             ix++;
828 
829             for (unsigned int i = 0; i < p.size() / 2; i++, ix += 2) {
830                 f << p[ix] << ' ' << p[ix + 1] << std::endl;
831             }
832         }
833 
834         f.close ();
835     }
836 }
837 
loadPressed()838 void DiagonalCurveEditorSubGroup::loadPressed ()
839 {
840 
841     Glib::ustring fname = inputFile();
842 
843     if (fname.size()) {
844         std::ifstream f (fname.c_str());
845 
846         if (f) {
847             std::vector<double> p;
848             std::string s;
849             f >> s;
850 
851             if (s == "Linear") {
852                 p.push_back ((double)(DCT_Linear));
853             } else if (s == "Spline") {
854                 p.push_back ((double)(DCT_Spline));
855             } else if (s == "CatmullRom") {
856                 p.push_back ((double)(DCT_CatumullRom));
857             } else if (s == "NURBS") {
858                 p.push_back ((double)(DCT_NURBS));
859             } else if (s == "Parametric") {
860                 p.push_back ((double)(DCT_Parametric));
861             } else {
862                 return;
863             }
864 
865             double x;
866 
867             while (f) {
868                 f >> x;
869 
870                 if (f) {
871                     p.push_back (x);
872                 }
873             }
874 
875             rtengine::sanitizeCurve(p);
876 
877             if (p[0] == (double)(DCT_Spline) || p[0] == (double)(DCT_CatumullRom)) {
878                 customCurve->setPoints (p);
879                 customCurve->queue_draw ();
880                 customCurve->notifyListener ();
881             } else if (p[0] == (double)(DCT_NURBS)) {
882                 NURBSCurve->setPoints (p);
883                 NURBSCurve->queue_draw ();
884                 NURBSCurve->notifyListener ();
885             } else if (p[0] == (double)(DCT_Parametric)) {
886                 shcSelector->setPositions ( p[1], p[2], p[3] );
887                 highlights->setValue (p[4]);
888                 lights->setValue (p[5]);
889                 darks->setValue (p[6]);
890                 shadows->setValue (p[7]);
891                 paramCurve->setPoints (p);
892                 paramCurve->queue_draw ();
893                 paramCurve->notifyListener ();
894             }
895         }
896     }
897 }
898 
copyPressed()899 void DiagonalCurveEditorSubGroup::copyPressed ()
900 {
901 // For compatibility use enum DiagonalCurveType here
902 
903     std::vector<double> curve;
904 
905     switch (parent->displayedCurve->selected) {
906     case DCT_Spline:                // custom
907         curve = customCurve->getPoints ();
908         clipboard.setDiagonalCurveData (curve, DCT_Spline);
909         break;
910 
911     case DCT_Parametric:            // parametric
912         // ... do something, first add save/load functions
913         curve = paramCurve->getPoints ();
914         clipboard.setDiagonalCurveData (curve, DCT_Parametric);
915         break;
916 
917     case DCT_NURBS:                 // NURBS
918         curve = NURBSCurve->getPoints ();
919         clipboard.setDiagonalCurveData (curve, DCT_NURBS);
920         break;
921 
922     case DCT_CatumullRom:
923         curve = customCurve->getPoints ();
924         curve[0] = DCT_CatumullRom;
925         clipboard.setDiagonalCurveData (curve, DCT_CatumullRom);
926         break;
927 
928     default:                       // (DCT_Linear, DCT_Unchanged)
929         // ... do nothing
930         break;
931     }
932 }
933 
pastePressed()934 void DiagonalCurveEditorSubGroup::pastePressed ()
935 {
936 // For compatibility use enum DiagonalCurveType here
937 
938     std::vector<double> curve;
939     DiagonalCurveType type;
940 
941     type = clipboard.hasDiagonalCurveData();
942 
943     if (type == (DiagonalCurveType)parent->displayedCurve->selected) {
944         curve = clipboard.getDiagonalCurveData ();
945 
946         switch (type) {
947         case DCT_Spline:           // custom
948         case DCT_CatumullRom:
949             customCurve->setPoints (curve);
950             customCurve->queue_draw ();
951             customCurve->notifyListener ();
952             break;
953 
954         case DCT_Parametric:       // parametric
955             // ... do something, first add save/load functions
956             shcSelector->setPositions (
957                 curve[1],
958                 curve[2],
959                 curve[3]  );
960             highlights->setValue (curve[4]);
961             lights->setValue (curve[5]);
962             darks->setValue (curve[6]);
963             shadows->setValue (curve[7]);
964             paramCurve->setPoints (curve);
965             paramCurve->queue_draw ();
966             paramCurve->notifyListener ();
967             break;
968 
969         case DCT_NURBS:            // NURBS
970             NURBSCurve->setPoints (curve);
971             NURBSCurve->queue_draw ();
972             NURBSCurve->notifyListener ();
973             break;
974 
975         default:                   // (DCT_Linear, DCT_Unchanged)
976             // ... do nothing
977             break;
978         }
979     }
980 
981     return;
982 }
983 
editPointToggled(Gtk::ToggleButton * button)984 void DiagonalCurveEditorSubGroup::editPointToggled(Gtk::ToggleButton *button)
985 {
986     if (button->get_active()) {
987         customCoordAdjuster->show();
988         NURBSCoordAdjuster->show();
989     } else {
990         if (customCoordAdjuster) {
991             customCurve->stopNumericalAdjustment();
992             customCoordAdjuster->hide();
993             NURBSCurve->stopNumericalAdjustment();
994             NURBSCoordAdjuster->hide();
995         }
996     }
997 
998     if (button == editPointCustom) {
999         editPointNURBSConn.block(true);
1000         editPointNURBS->set_active(!editPointNURBS->get_active());
1001         editPointNURBSConn.block(false);
1002     } else {
1003         editPointCustomConn.block(true);
1004         editPointCustom->set_active(!editPointCustom->get_active());
1005         editPointCustomConn.block(false);
1006     }
1007 }
1008 
editToggled(Gtk::ToggleButton * button)1009 void DiagonalCurveEditorSubGroup::editToggled (Gtk::ToggleButton *button)
1010 {
1011     DiagonalCurveEditor* dCurve = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
1012 
1013     if (!dCurve)
1014         // should never happen!
1015     {
1016         return;
1017     }
1018 
1019     if (button->get_active()) {
1020         dCurve->subscribe();
1021 
1022         if (button == editCustom) {
1023             customCurve->notifyListener ();
1024         } else if (button == editNURBS) {
1025             NURBSCurve->notifyListener ();
1026         } else if (button == editParam) {
1027             paramCurve->notifyListener ();
1028         }
1029 
1030         /*
1031         if (button != editCustom) {
1032             editCustomConn.block(true);
1033             editCustom->set_active(true);
1034             editCustomConn.block(false);
1035         }
1036         else {
1037             // will throw the event of curveChanged, which will now build the edit's buffer
1038             customCurve->notifyListener ();
1039         }
1040         if (button != editNURBS) {
1041             editNURBSConn.block(true);
1042             editNURBS->set_active(true);
1043             editNURBSConn.block(false);
1044         }
1045         else {
1046             NURBSCurve->notifyListener ();
1047         }
1048         if (button != editParam) {
1049             editParamConn.block(true);
1050             editParam->set_active(true);
1051             editParamConn.block(false);
1052         }
1053         else {
1054             paramCurve->notifyListener ();
1055         }
1056         */
1057     } else {
1058         dCurve->unsubscribe();
1059         /*
1060         if (button != editCustom ) { editCustomConn.block(true);  editCustom->set_active(false);  editCustomConn.block(false); }
1061         if (button != editNURBS  ) { editNURBSConn.block(true);   editNURBS->set_active(false);   editNURBSConn.block(false);  }
1062         if (button != editParam  ) { editParamConn.block(true);   editParam->set_active(false);   editParamConn.block(false);  }
1063         */
1064     }
1065 }
1066 
1067 /*
1068  * Store the curves of the currently displayed type from the widgets to the CurveEditor object
1069  */
storeDisplayedCurve()1070 void DiagonalCurveEditorSubGroup::storeDisplayedCurve()
1071 {
1072     if (parent->displayedCurve) {
1073         switch (parent->displayedCurve->selected) {
1074         case (DCT_Spline):
1075             storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Spline));
1076             break;
1077 
1078         case (DCT_Parametric):
1079             storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_Parametric));
1080             break;
1081 
1082         case (DCT_NURBS):
1083             storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_NURBS));
1084             break;
1085 
1086         case (DCT_CatumullRom):
1087             storeCurveValues(parent->displayedCurve, getCurveFromGUI(DCT_CatumullRom));
1088             break;
1089 
1090         default:
1091             break;
1092         }
1093     }
1094 }
1095 
1096 /*
1097  * Restore the histogram to all types from the CurveEditor object to the widgets
1098  */
restoreDisplayedHistogram()1099 void DiagonalCurveEditorSubGroup::restoreDisplayedHistogram()
1100 {
1101     if (parent->displayedCurve /*&& initslope==1*/) {
1102         paramCurve->updateBackgroundHistogram (parent->displayedCurve->histogram);
1103         customCurve->updateBackgroundHistogram (parent->displayedCurve->histogram);
1104         NURBSCurve->updateBackgroundHistogram (parent->displayedCurve->histogram);
1105     }
1106 
1107 }
1108 
storeCurveValues(CurveEditor * ce,const std::vector<double> & p)1109 void DiagonalCurveEditorSubGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p)
1110 {
1111     if (!p.empty()) {
1112         DiagonalCurveType t = (DiagonalCurveType)p[0];
1113 
1114         switch (t) {
1115         case (DCT_Spline):
1116             (static_cast<DiagonalCurveEditor*>(ce))->customCurveEd = p;
1117             break;
1118 
1119         case (DCT_Parametric):
1120             (static_cast<DiagonalCurveEditor*>(ce))->paramCurveEd = p;
1121             break;
1122 
1123         case (DCT_NURBS):
1124             (static_cast<DiagonalCurveEditor*>(ce))->NURBSCurveEd = p;
1125             break;
1126 
1127         case (DCT_CatumullRom):
1128             (static_cast<DiagonalCurveEditor*>(ce))->catmullRomCurveEd = p;
1129             break;
1130 
1131         default:
1132             break;
1133         }
1134     }
1135 }
1136 
1137 /*
1138  * Called to update the parametric curve graph with new slider values
1139  */
getCurveFromGUI(int type)1140 const std::vector<double> DiagonalCurveEditorSubGroup::getCurveFromGUI (int type)
1141 {
1142     switch ((DiagonalCurveType)type) {
1143     case (DCT_Parametric): {
1144         std::vector<double> lcurve (8);
1145         lcurve[0] = (double)(DCT_Parametric);
1146         shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
1147         lcurve[4] = highlights->getValue ();
1148         lcurve[5] = lights->getValue ();
1149         lcurve[6] = darks->getValue ();
1150         lcurve[7] = shadows->getValue ();
1151         return lcurve;
1152     }
1153 
1154     case (DCT_Spline):
1155         return customCurve->getPoints ();
1156 
1157     case (DCT_NURBS):
1158         return NURBSCurve->getPoints ();
1159 
1160     case (DCT_CatumullRom): {
1161         auto ret = customCurve->getPoints();
1162         if (!ret.empty()) {
1163             ret[0] = DCT_CatumullRom;
1164         }
1165         return ret;
1166     }
1167 
1168     default: {
1169         // linear and other solutions
1170         std::vector<double> lcurve (1);
1171         lcurve[0] = (double)(DCT_Linear);
1172         return lcurve;
1173     }
1174     }
1175 }
1176 
1177 /*
1178  * Unlink the tree editor widgets from their parent box to hide them
1179  */
removeEditor()1180 void DiagonalCurveEditorSubGroup::removeEditor ()
1181 {
1182     removeIfThere (parent, customCurveGrid, false);
1183     removeIfThere (parent, paramCurveGrid, false);
1184     removeIfThere (parent, NURBSCurveGrid, false);
1185 }
1186 
curveReset(CurveEditor * ce)1187 bool DiagonalCurveEditorSubGroup::curveReset(CurveEditor *ce)
1188 {
1189     if (!ce) {
1190         return false;
1191     }
1192 
1193     DiagonalCurveEditor *dce = static_cast<DiagonalCurveEditor*>(ce);
1194 
1195     switch (ce->selected) {
1196     case (DCT_NURBS) :  // = Control cage
1197         NURBSCurve->reset (dce->NURBSResetCurve, dce->getIdentityValue());
1198         return true;
1199 
1200     case (DCT_Spline) : // = Custom
1201         customCurve->reset (dce->customResetCurve, dce->getIdentityValue());
1202         return true;
1203 
1204     case (DCT_CatumullRom) :
1205         customCurve->reset (dce->catmullRomResetCurve, dce->getIdentityValue());
1206         return true;
1207 
1208     case (DCT_Parametric) : {
1209         DiagonalCurveEditor* dCurve = static_cast<DiagonalCurveEditor*>(parent->displayedCurve);
1210         double mileStone[3];
1211         dCurve->getRangeDefaultMilestones(mileStone[0], mileStone[1], mileStone[2]);
1212 
1213         highlights->resetPressed(nullptr);
1214         lights->resetPressed(nullptr);
1215         darks->resetPressed(nullptr);
1216         shadows->resetPressed(nullptr);
1217         shcSelector->setDefaults(mileStone[0], mileStone[1], mileStone[2]);
1218         shcSelector->reset();
1219         paramCurve->reset (dce->paramResetCurve, dce->getIdentityValue());
1220         return true;
1221     }
1222 
1223     default:
1224         return false;
1225     }
1226 
1227     return true;
1228 }
1229 
1230 /*
1231  * Listener
1232  */
shcChanged()1233 void DiagonalCurveEditorSubGroup::shcChanged ()
1234 {
1235 
1236     paramCurve->setPoints (getCurveFromGUI(DCT_Parametric));
1237     storeDisplayedCurve();
1238     parent->curveChanged ();
1239 }
1240 
1241 /*
1242  * Listener
1243  */
adjusterChanged(Adjuster * a,double newval)1244 void DiagonalCurveEditorSubGroup::adjusterChanged(Adjuster* a, double newval)
1245 {
1246     paramCurve->setPoints (getCurveFromGUI(DCT_Parametric));
1247     storeDisplayedCurve();
1248     parent->curveChanged ();
1249 }
1250 
1251 /*
1252  * Listener called when the mouse is over a parametric curve's slider
1253  */
adjusterEntered(GdkEventCrossing * ev,int ac)1254 bool DiagonalCurveEditorSubGroup::adjusterEntered (GdkEventCrossing* ev, int ac)
1255 {
1256 
1257     if (ev->detail != GDK_NOTIFY_INFERIOR) {
1258         activeParamControl = ac;
1259         paramCurve->setActiveParam (activeParamControl);
1260     }
1261 
1262     return true;
1263 }
1264 
1265 /*
1266  * Listener called when the mouse left the parametric curve's slider
1267  */
adjusterLeft(GdkEventCrossing * ev,int ac)1268 bool DiagonalCurveEditorSubGroup::adjusterLeft (GdkEventCrossing* ev, int ac)
1269 {
1270 
1271     if (ev->detail != GDK_NOTIFY_INFERIOR) {
1272         activeParamControl = -1;
1273         paramCurve->setActiveParam (activeParamControl);
1274     }
1275 
1276     return true;
1277 }
1278 
updateBackgroundHistogram(CurveEditor * ce)1279 void DiagonalCurveEditorSubGroup::updateBackgroundHistogram (CurveEditor* ce)
1280 {
1281     if (ce == parent->displayedCurve /*&&  initslope==1*/) {
1282         paramCurve->updateBackgroundHistogram (ce->histogram);
1283         customCurve->updateBackgroundHistogram (ce->histogram);
1284         NURBSCurve->updateBackgroundHistogram (ce->histogram);
1285     }
1286 }
1287 
setSubGroupRangeLabels(Glib::ustring r1,Glib::ustring r2,Glib::ustring r3,Glib::ustring r4)1288 void DiagonalCurveEditorSubGroup::setSubGroupRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4)
1289 {
1290     shadows->setLabel(r1);
1291     darks->setLabel(r2);
1292     lights->setLabel(r3);
1293     highlights->setLabel(r4);
1294 }
1295