PopUpButton widget and PopUpToggleButton added ; Curve editor changed to handle any numbe of curve, since the curve editor is now shared between the curves. (CMakeLists changed -> CMake you project)

This commit is contained in:
Hombre
2010-11-04 01:04:11 +01:00
parent 4f3da272a2
commit 37c8063f41
30 changed files with 1618 additions and 629 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 584 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 161 B

View File

@@ -10,6 +10,8 @@
!ADJUSTER_RESET_TO_DEFAULT;Reset to default !ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start !BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing !BATCH_PROCESSING;Batch processing
!CURVEEDITOR_CURVE;Curve
!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom !CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks !CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files !CURVEEDITOR_FILEDLGFILTERANY;Any files
@@ -230,6 +232,8 @@
!HISTORY_MSG_90;Directional pyramid luminance !HISTORY_MSG_90;Directional pyramid luminance
!HISTORY_MSG_91;Directional pyramid chominance !HISTORY_MSG_91;Directional pyramid chominance
!HISTORY_MSG_92;Directional pyramid gamma !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_MSG_9;Highlight Compression
!HISTORY_NEWSNAPSHOT;Add !HISTORY_NEWSNAPSHOT;Add
!HISTORY_NEWSNAPSHOTAS;As... !HISTORY_NEWSNAPSHOTAS;As...

View File

@@ -39,6 +39,8 @@ TP_HLREC_COLOR;Colour Propagation
!ADJUSTER_RESET_TO_DEFAULT;Reset to default !ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start !BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing !BATCH_PROCESSING;Batch processing
!CURVEEDITOR_CURVE;Curve
!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom !CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks !CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files !CURVEEDITOR_FILEDLGFILTERANY;Any files

View File

@@ -10,6 +10,8 @@
!ADJUSTER_RESET_TO_DEFAULT;Reset to default !ADJUSTER_RESET_TO_DEFAULT;Reset to default
!BATCHQUEUE_AUTOSTART;Auto start !BATCHQUEUE_AUTOSTART;Auto start
!BATCH_PROCESSING;Batch processing !BATCH_PROCESSING;Batch processing
!CURVEEDITOR_CURVE;Curve
!CURVEEDITOR_CURVES;Curves
!CURVEEDITOR_CUSTOM;Custom !CURVEEDITOR_CUSTOM;Custom
!CURVEEDITOR_DARKS;Darks !CURVEEDITOR_DARKS;Darks
!CURVEEDITOR_FILEDLGFILTERANY;Any files !CURVEEDITOR_FILEDLGFILTERANY;Any files

View File

@@ -7,6 +7,8 @@
ADJUSTER_RESET_TO_DEFAULT;Réglages par défaut ADJUSTER_RESET_TO_DEFAULT;Réglages par défaut
BATCHQUEUE_AUTOSTART;Démarrage auto BATCHQUEUE_AUTOSTART;Démarrage auto
BATCH_PROCESSING;Traitement par lot BATCH_PROCESSING;Traitement par lot
CURVEEDITOR_CURVE;Courbe
CURVEEDITOR_CURVES;Courbes
CURVEEDITOR_CUSTOM;Personnalisé CURVEEDITOR_CUSTOM;Personnalisé
CURVEEDITOR_DARKS;Zones sombres CURVEEDITOR_DARKS;Zones sombres
CURVEEDITOR_FILEDLGFILTERANY;Tous les fichiers 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_90;Réd. de bruit Luminance
HISTORY_MSG_91;Réd. de bruit Chominance HISTORY_MSG_91;Réd. de bruit Chominance
HISTORY_MSG_92;Réd. de bruit Gamma 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_MSG_9;Compression des hautes lumières
HISTORY_NEWSNAPSHOT;Ajouter HISTORY_NEWSNAPSHOT;Ajouter
HISTORY_NEWSNAPSHOTAS;Sous... HISTORY_NEWSNAPSHOTAS;Sous...

View File

@@ -3,6 +3,8 @@
ADJUSTER_RESET_TO_DEFAULT;Reset to default ADJUSTER_RESET_TO_DEFAULT;Reset to default
BATCHQUEUE_AUTOSTART;Auto start BATCHQUEUE_AUTOSTART;Auto start
BATCH_PROCESSING;Batch processing BATCH_PROCESSING;Batch processing
CURVEEDITOR_CURVE;Curve
CURVEEDITOR_CURVES;Curves
CURVEEDITOR_CUSTOM;Custom CURVEEDITOR_CUSTOM;Custom
CURVEEDITOR_DARKS;Darks CURVEEDITOR_DARKS;Darks
CURVEEDITOR_FILEDLGFILTERANY;Any files CURVEEDITOR_FILEDLGFILTERANY;Any files
@@ -223,6 +225,8 @@ HISTORY_MSG_8;Exposure Compensation
HISTORY_MSG_90;Directional pyramid luminance HISTORY_MSG_90;Directional pyramid luminance
HISTORY_MSG_91;Directional pyramid chominance HISTORY_MSG_91;Directional pyramid chominance
HISTORY_MSG_92;Directional pyramid gamma 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_MSG_9;Highlight Compression
HISTORY_NEWSNAPSHOT;Add HISTORY_NEWSNAPSHOT;Add
HISTORY_NEWSNAPSHOTAS;As... HISTORY_NEWSNAPSHOTAS;As...

View File

@@ -12,7 +12,7 @@ set (BASESOURCEFILES
exifpanel.cc exifpanel.cc
sharpening.cc sharpening.cc
whitebalance.cc vignetting.cc rotate.cc distortion.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 filecatalog.cc
previewloader.cc previewloader.cc
histogrampanel.cc history.cc imagearea.cc histogrampanel.cc history.cc imagearea.cc
@@ -26,7 +26,8 @@ set (BASESOURCEFILES
batchqueue.cc lwbutton.cc lwbuttonset.cc batchqueue.cc lwbutton.cc lwbuttonset.cc
batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc batchqueuebuttonset.cc browserfilter.cc exiffiltersettings.cc
profilestore.cc partialpastedlg.cc rawprocess.cc preprocess.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) if (WIN32)
set (EXTRA_SRC windirmonitor.cc myicon.o) set (EXTRA_SRC windirmonitor.cc myicon.o)

View File

@@ -17,6 +17,7 @@
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <curveeditor.h> #include <curveeditor.h>
#include <curveeditorgroup.h>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <guiutils.h> #include <guiutils.h>
@@ -24,495 +25,96 @@
extern Glib::ustring argv0; 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 ()); bgHistValid = false;
Gtk::Label* tslab = Gtk::manage (new Gtk::Label (M("CURVEEDITOR_TYPE"))); selected = Linear;
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"));
tsbox->pack_start (*tslab, Gtk::PACK_SHRINK, 8); group = ceGroup;
tsbox->pack_start (*curveType);
tsbox->pack_start (*curve_reset, Gtk::PACK_SHRINK, 0);
pack_start (*tsbox); 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 // Order set in the same order than "enum CurveType". Shouldn't change, for compatibility reason
curveType->append_text (M("CURVEEDITOR_LINEAR")); // 0 Linear curveType->addEntry(argv0+"/images/curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
curveType->append_text (M("CURVEEDITOR_CUSTOM")); // 1 Spline curveType->addEntry(argv0+"/images/curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline
curveType->append_text (M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric curveType->addEntry(argv0+"/images/curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric
curveType->append_text (M("CURVEEDITOR_NURBS")); // 3 NURBS curveType->addEntry(argv0+"/images/curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS
curveType->set_active (Linear); 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) ); curveType->show();
// 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 ();
} }
/*
CurveEditor::~CurveEditor () { CurveEditor::~CurveEditor () {
delete customCurveBox;
delete paramCurveBox;
} }
*/
void CurveEditor::savePressed () { void CurveEditor::setCurve (const std::vector<double>& p) {
tempCurve = p;
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_SAVEDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_SAVE); group->setCurveExternal(this, p);
// 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("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
int response = msgd.run ();
if (response==Gtk::RESPONSE_NO)
return;
}
std::ofstream f (fname.c_str());
std::vector<double> 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.size()/2; i++, ix+=2)
f << p[ix] << ' ' << p[ix+1] << std::endl;
f.close ();
}
}
void CurveEditor::loadPressed () {
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN);
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
dialog.add_button(Gtk::StockID("gtk-open"), 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);
int result = dialog.run();
if (result==Gtk::RESPONSE_OK) {
std::ifstream f (dialog.get_filename().c_str());
if (f) {
std::vector<double> p;
std::string s;
f >> s;
if (s=="Linear")
p.push_back ((double)(Linear));
else if (s=="Spline")
p.push_back ((double)(Spline));
else if (s=="NURBS")
p.push_back ((double)(NURBS));
else return;
double x;
while (f) {
f >> x;
if (f)
p.push_back (x);
}
if (p[0] == (double)(Spline)) {
customCurve->setPoints (p);
customCurve->queue_draw ();
customCurve->notifyListener ();
}
else if (p[0] == (double)(NURBS)) {
NURBSCurve->setPoints (p);
NURBSCurve->queue_draw ();
NURBSCurve->notifyListener ();
}
}
}
}
void CurveEditor::on_realize () {
Gtk::VBox::on_realize();
realized = true;
setCurve (tmpCurve);
}
void CurveEditor::setCurve (const std::vector<double>& 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);
}
} }
std::vector<double> CurveEditor::getCurve () { std::vector<double> CurveEditor::getCurve () {
std::vector<double> curve;
if (!realized || curveType->get_active_row_number()==Unchanged) switch (selected) {
return tmpCurve; case (Spline):
return curve = customCurveEd;
// linear case (Parametric):
if (curveTypeIx<=Linear) { return curve = paramCurveEd;
std::vector<double> lcurve (1); case (NURBS):
lcurve[0] = (double)(Linear); return curve = NURBSCurveEd;
return lcurve;
}
// parametric
else if (curveTypeIx==Parametric) {
std::vector<double> lcurve (8);
lcurve[0] = (double)(Parametric);
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
lcurve[4] = highlights->getValue ();
lcurve[5] = lights->getValue ();
lcurve[6] = darks->getValue ();
lcurve[7] = shadows->getValue ();
return lcurve;
}
// 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;
default: default:
break; // returning Linear or Unchanged
curve.push_back((double)(selected));
return curve;
} }
curveChanged ();
} }
void CurveEditor::shcChanged () { void CurveEditor::typeSelectionChanged (int n) {
group->typeSelectionChanged(this, n);
paramCurve->setPoints (getCurve());
if (cl) {
if (cl->isMulti())
cl->curveChanged (this);
else
cl->curveChanged ();
}
} }
void CurveEditor::adjusterChanged (Adjuster* a, double newval) { void CurveEditor::curveTypeToggled() {
group->curveTypeToggled(this);
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"));
} }
bool CurveEditor::isUnChanged () { bool CurveEditor::isUnChanged () {
return curveType->getSelected()==Unchanged;
return curveType->get_active_row_number()==Unchanged;
} }
void CurveEditor::setUnChanged (bool uc) { void CurveEditor::setUnChanged (bool uc) {
group->setUnChanged(uc, this);
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);
}
} }
/*
* Update the backgrounds histograms
*/
void CurveEditor::updateBackgroundHistogram (unsigned int* hist) { 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); // Then call the curve editor group to eventually update the histogram
customCurve->updateBackgroundHistogram (hist); group->updateBackgroundHistogram (this);
NURBSCurve->updateBackgroundHistogram (hist);
} }

View File

@@ -20,65 +20,51 @@
#define _CURVEEDITOR_ #define _CURVEEDITOR_
#include <gtkmm.h> #include <gtkmm.h>
#include <popuptogglebutton.h>
#include <curveeditorgroup.h>
#include <mycurve.h> #include <mycurve.h>
#include <shcselector.h>
#include <adjuster.h>
class CurveEditor : public Gtk::VBox, public CurveListener, public SHCListener, public AdjusterListener { class CurveEditorGroup;
Gtk::ComboBoxText* curveType; /*
Gtk::Button* curve_reset; * This class is an interface between RT and the curve editor group ; it handles the methods
Gtk::VBox* paramCurveBox; * related to a specific curve. It is created by CurveEditorGroup::addCurve
Gtk::VBox* customCurveBox; */
Gtk::VBox* NURBSCurveBox; class CurveEditor {
MyCurve* customCurve; private:
MyCurve* NURBSCurve;
MyCurve* paramCurve;
SHCSelector* shcSelector;
Adjuster* highlights; /*
Adjuster* lights; * The curve editor contains only one widget (the curve type button) to receive the signals
Adjuster* darks; * but it's co-handled by the CurveEditorGroup too
Adjuster* shadows; */
Gtk::Button* saveCustom; // reflects the buttonType active selection ; used as a pre-'selectionChange' reminder value
Gtk::Button* loadCustom; CurveType selected;
Gtk::Button* saveNURBS;
Gtk::Button* loadNURBS;
CurveListener* cl; PopUpToggleButton* curveType;
unsigned int histogram[256]; // histogram values
bool bgHistValid;
bool realized; CurveEditorGroup* group;
std::vector<double> tmpCurve; std::vector<double> tempCurve;
CurveType curveTypeIx; std::vector<double> customCurveEd;
std::vector<double> paramCurveEd;
std::vector<double> NURBSCurveEd;
sigc::connection typeconn;
int activeParamControl; public:
sigc::connection typeconn; friend class CurveEditorGroup;
CurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup);
public: //~CurveEditor ();
void typeSelectionChanged (int n);
CurveEditor (); void curveTypeToggled();
virtual ~CurveEditor (); void setCurve (const std::vector<double>& p);
void setBatchMode (bool batchMode); std::vector<double> getCurve ();
bool isUnChanged (); bool isUnChanged ();
void setUnChanged (bool uc); void setUnChanged (bool uc);
void updateBackgroundHistogram (unsigned int* hist);
void on_realize ();
void setCurveListener (CurveListener* l) { cl = l; }
void savePressed ();
void loadPressed ();
void typeSelectionChanged ();
void setCurve (const std::vector<double>& c);
std::vector<double> 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);
}; };

733
rtgui/curveeditorgroup.cc Normal file
View File

@@ -0,0 +1,733 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#include <curveeditorgroup.h>
#include <multilangmgr.h>
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<CurveEditor*>::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)<Unchanged)
ce->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 && n<Unchanged );
if (n==Linear || n==Unchanged) {
// Since we do not activate the curve when the user switch the a toggled off button to 'Linear', we have to
// to call the curve listener manually, because 'curveChanged' uses displayedCurve...
if (cl) {
if (cl->isMulti())
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("<b>") + fname + ": " + M("MAIN_MSG_ALREADYEXISTS") + "\n" + M("MAIN_MSG_QOVERWRITE") + "</b>";
Gtk::MessageDialog msgd (msg_, true, Gtk::MESSAGE_WARNING, Gtk::BUTTONS_YES_NO, true);
int response = msgd.run ();
if (response==Gtk::RESPONSE_NO)
return;
}
std::ofstream f (fname.c_str());
std::vector<double> p = customCurve->getPoints ();
switch (displayedCurve->selected) {
case Spline: // custom
p = customCurve->getPoints ();
break;
case NURBS: // NURBS
p = NURBSCurve->getPoints ();
break;
default:
break;
}
int ix = 0;
if (p[ix]==(double)(Linear))
f << "Linear\n";
else if (p[ix]==(double)(Spline))
f << "Spline\n";
else if (p[ix]==(double)(NURBS))
f << "NURBS\n";
ix++;
for (unsigned int i=0; i<p.size()/2; i++, ix+=2)
f << p[ix] << ' ' << p[ix+1] << std::endl;
f.close ();
}
}
void CurveEditorGroup::loadPressed () {
Gtk::FileChooserDialog dialog(M("CURVEEDITOR_LOADDLGLABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN);
dialog.add_button(Gtk::StockID("gtk-cancel"), Gtk::RESPONSE_CANCEL);
dialog.add_button(Gtk::StockID("gtk-open"), 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);
int result = dialog.run();
if (result==Gtk::RESPONSE_OK) {
std::ifstream f (dialog.get_filename().c_str());
if (f) {
std::vector<double> p;
std::string s;
f >> s;
if (s=="Linear")
p.push_back ((double)(Linear));
else if (s=="Spline")
p.push_back ((double)(Spline));
else if (s=="NURBS")
p.push_back ((double)(NURBS));
else return;
double x;
while (f) {
f >> x;
if (f)
p.push_back (x);
}
if (p[0] == (double)(Spline)) {
customCurve->setPoints (p);
customCurve->queue_draw ();
customCurve->notifyListener ();
}
else if (p[0] == (double)(NURBS)) {
NURBSCurve->setPoints (p);
NURBSCurve->queue_draw ();
NURBSCurve->notifyListener ();
}
}
}
}
/*
* Store the curves of the currently displayed type from the widgets to the CurveEditor object
*/
void CurveEditorGroup::storeDisplayedCurve() {
if (displayedCurve) {
switch (displayedCurve->selected) {
case (Spline):
storeCurveValues(displayedCurve, getCurveFromGUI(Spline));
break;
case (Parametric):
storeCurveValues(displayedCurve, getCurveFromGUI(Parametric));
break;
case (NURBS):
storeCurveValues(displayedCurve, getCurveFromGUI(NURBS));
break;
default:
break;
}
}
}
/*
* Restore the histogram to all types from the CurveEditor object to the widgets
*/
void CurveEditorGroup::restoreDisplayedHistogram() {
if (displayedCurve) {
paramCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
customCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
NURBSCurve->updateBackgroundHistogram (displayedCurve->bgHistValid ? displayedCurve->histogram : NULL);
}
}
void CurveEditorGroup::storeCurveValues (CurveEditor* ce, const std::vector<double>& p) {
if (p.size()) {
CurveType t = (CurveType)p[0];
for (int i=0; i<(int)p.size(); i++)
switch (t) {
case (Spline):
ce->customCurveEd = p;
break;
case (Parametric):
ce->paramCurveEd = p;
break;
case (NURBS):
ce->NURBSCurveEd = p;
break;
default:
break;
}
}
}
/*
* Update the GUI if the given curveEditor is currently displayed
*/
void CurveEditorGroup::updateGUI (CurveEditor* ce) {
if (!ce) {
return;
}
// we update the curve type button to the corresponding curve type, only if it is not currently set to 'Unchanged'
if (ce->curveType->getSelected()<Unchanged)
ce->curveType->setSelected(ce->selected);
// if not displayed or "unchanged" is selected, do not change gui
if (ce==displayedCurve && ce->curveType->getSelected()<Unchanged) {
switchGUI();
}
}
/*
* Called from the outside to set the curve type & values
*/
void CurveEditorGroup::setCurveExternal (CurveEditor* ce, const std::vector<double>& c) {
if (c.size()) {
storeCurveValues(ce, c); // The new curve is saved in the CurveEditor
ce->selected = (CurveType)(c[0]); // We set the selected curve type in the CurveEditor to the one of the specified curve
}
updateGUI(ce); // And we update the GUI if necessary
}
/*
* Called to update the parametric curve graph with new slider values
*/
const std::vector<double> CurveEditorGroup::getCurveFromGUI (CurveType type) {
switch (type) {
case (Parametric): {
std::vector<double> lcurve (8);
lcurve[0] = (double)(Parametric);
shcSelector->getPositions (lcurve[1], lcurve[2], lcurve[3]);
lcurve[4] = highlights->getValue ();
lcurve[5] = lights->getValue ();
lcurve[6] = darks->getValue ();
lcurve[7] = shadows->getValue ();
return lcurve;
}
case (Spline):
return customCurve->getPoints ();
case (NURBS):
return NURBSCurve->getPoints ();
default: {
// linear and other solutions
std::vector<double> lcurve (1);
lcurve[0] = (double)(Linear);
return lcurve;
}
}
}
/*
* Unlink the tree editor widgets from their parent box to hide them
*/
void CurveEditorGroup::removeEditor () {
removeIfThere (this, customCurveBox, false);
removeIfThere (this, paramCurveBox, false);
removeIfThere (this, NURBSCurveBox, false);
}
/*
* Listener called when the user has modified the curve
*/
void CurveEditorGroup::curveChanged () {
storeDisplayedCurve();
if (cl) {
if (cl->isMulti())
cl->curveChanged (displayedCurve);
else
cl->curveChanged ();
}
}
/*
* Listener
*/
void CurveEditorGroup::shcChanged () {
paramCurve->setPoints (getCurveFromGUI(Parametric));
storeDisplayedCurve();
if (cl->isMulti())
cl->curveChanged (displayedCurve);
else
cl->curveChanged ();
}
/*
* Listener
*/
void CurveEditorGroup::adjusterChanged (Adjuster* a, double newval) {
paramCurve->setPoints (getCurveFromGUI(Parametric));
storeDisplayedCurve();
if (cl->isMulti())
cl->curveChanged (displayedCurve);
else
cl->curveChanged ();
}
/*
* Listener called when the mouse is over a parametric curve's slider
*/
bool CurveEditorGroup::adjusterEntered (GdkEventCrossing* ev, int ac) {
if (ev->detail != GDK_NOTIFY_INFERIOR) {
activeParamControl = ac;
paramCurve->setActiveParam (activeParamControl);
}
return true;
}
/*
* Listener called when the mouse left the parametric curve's slider
*/
bool CurveEditorGroup::adjusterLeft (GdkEventCrossing* ev, int ac) {
if (ev->detail != GDK_NOTIFY_INFERIOR) {
activeParamControl = -1;
paramCurve->setActiveParam (activeParamControl);
}
return true;
}
/*
* Call back method when the reset button is pressed :
* reset the currently toggled on curve editor
*/
void CurveEditorGroup::curveResetPressed() {
if (displayedCurve) {
switch (displayedCurve->selected) {
case (NURBS) : // = Control cage
NURBSCurve->reset ();
curveChanged ();
break;
case (Spline) : // = Custom
customCurve->reset ();
curveChanged ();
break;
case (Parametric) :
highlights->resetPressed();
lights->resetPressed();
darks->resetPressed();
shadows->resetPressed();
shcSelector->reset();
paramCurve->reset ();
curveChanged ();
break;
default:
break;
}
}
}
void CurveEditorGroup::setBatchMode (bool batchMode) {
for (std::vector<CurveEditor*>::iterator i = curveEditors.begin(); i != curveEditors.end(); ++i) {
(*i)->curveType->addEntry(argv0+"/images/curveType-unchanged.png", M("GENERAL_UNCHANGED"));
(*i)->curveType->show();
}
}
void CurveEditorGroup::setUnChanged (bool uc, CurveEditor* ce) {
if (uc) {
// the user selected several thumbnails, so we hide the editors and set the curveEditor selection to 'Unchanged'
//ce->typeconn.block(true);
// we hide the editor widgets
hideCurrentCurve();
// the curve type selected option is set to unchanged
ce->curveType->setSelected(Unchanged);
//ce->typeconn.block(false);
}
else {
// we want it to use back the 'CurveEditor::setCurve' memorized in CurveEditor::tempCurve
//ce->typeconn.block(true);
// we switch back the curve type selected option to the one of the used curve
ce->curveType->setSelected(ce->selected);
updateGUI (ce);
//ce->typeconn.block(false);
}
}
void CurveEditorGroup::updateBackgroundHistogram (CurveEditor* ce) {
if (ce==displayedCurve) {
paramCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
customCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
NURBSCurve->updateBackgroundHistogram (ce->bgHistValid ? ce->histogram : NULL);
printf(" - fait! (ce==displayedCurve)");
}
}

108
rtgui/curveeditorgroup.h Normal file
View File

@@ -0,0 +1,108 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _CURVEEDITORGROUP_
#define _CURVEEDITORGROUP_
#include <gtkmm.h>
#include <fstream>
#include <string>
#include <guiutils.h>
#include <mycurve.h>
#include <shcselector.h>
#include <adjuster.h>
#include <curveeditor.h>
/*
* 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<CurveEditor*> 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<double>& p);
void typeSelectionChanged (int n);
void switchGUI();
void updateGUI (CurveEditor* ce);
void removeEditor ();
void curveChanged ();
void shcChanged ();
void adjusterChanged (Adjuster* a, double newval);
bool adjusterEntered (GdkEventCrossing* ev, int ac);
bool adjusterLeft (GdkEventCrossing* ev, int ac);
const std::vector<double> getCurveFromGUI (CurveType type);
void updateBackgroundHistogram (CurveEditor* ce);
public:
friend class CurveEditor;
CurveEditorGroup(Glib::ustring groupLabel = "");
~CurveEditorGroup();
CurveEditor* addCurve(Glib::ustring curveLabel = "");
void newLine();
void curveListComplete();
void setBatchMode (bool batchMode);
void setCurveExternal (CurveEditor* ce, const std::vector<double>& c);
//void on_realize ();
void setCurveListener (CurveListener* l) { cl = l; }
};
#endif

View File

@@ -24,28 +24,6 @@ using namespace rtengine::procparams;
LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) { 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)); 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)); contrast = Gtk::manage (new Adjuster (M("TP_LABCURVE_CONTRAST"), -100, 100, 1, 0));
saturation = Gtk::manage (new Adjuster (M("TP_LABCURVE_SATURATION"), -100, 100, 1, 0)); saturation = Gtk::manage (new Adjuster (M("TP_LABCURVE_SATURATION"), -100, 100, 1, 0));
@@ -63,25 +41,19 @@ LCurve::LCurve () : ToolPanel(), brAdd(false), contrAdd(false), satAdd(false) {
hsep3->show (); hsep3->show ();
pack_start (*hsep3); pack_start (*hsep3);
lshape = Gtk::manage (new CurveEditor ()); curveEditorG = new CurveEditorGroup ();
lshape->show (); curveEditorG->setCurveListener (this);
lshape->setCurveListener (this);
CurveListener::setMulti(true);
ashape = Gtk::manage (new CurveEditor ()); lshape = curveEditorG->addCurve("L");
ashape->show (); ashape = curveEditorG->addCurve("a");
ashape->setCurveListener (this); bshape = curveEditorG->addCurve("b");
CurveListener::setMulti(true);
bshape = Gtk::manage (new CurveEditor ()); // This will add the reset button at the end of the curveType buttons
bshape->show (); curveEditorG->curveListComplete();
bshape->setCurveListener (this);
CurveListener::setMulti(true);
pack_start (*lshape, Gtk::PACK_SHRINK, 4); pack_start (*curveEditorG, Gtk::PACK_SHRINK, 4);
pack_start (*ashape, Gtk::PACK_SHRINK, 4);
pack_start (*bshape, Gtk::PACK_SHRINK, 4);
//curveEditorG->show();
brightness->setAdjusterListener (this); brightness->setAdjusterListener (this);
contrast->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) { void LCurve::read (const ProcParams* pp, const ParamsEdited* pedited) {
disableListener (); 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) { void LCurve::curveChanged (CurveEditor* ce) {
if (listener) { if (listener) {
@@ -217,9 +199,7 @@ void LCurve::setBatchMode (bool batchMode) {
contrast->showEditedCB (); contrast->showEditedCB ();
saturation->showEditedCB (); saturation->showEditedCB ();
lshape->setBatchMode (batchMode); curveEditorG->setBatchMode (batchMode);
ashape->setBatchMode (batchMode);
bshape->setBatchMode (batchMode);
} }
void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) { void LCurve::setAdjusterBehavior (bool bradd, bool contradd, bool satadd) {

View File

@@ -30,6 +30,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, publ
protected: protected:
Gtk::ComboBoxText* channel; Gtk::ComboBoxText* channel;
CurveEditorGroup* curveEditorG;
Adjuster* brightness; Adjuster* brightness;
Adjuster* contrast; Adjuster* contrast;
Adjuster* saturation; Adjuster* saturation;
@@ -42,6 +43,7 @@ class LCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, publ
public: public:
LCurve (); LCurve ();
~LCurve ();
void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL); void read (const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited=NULL);
void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL); void write (rtengine::procparams::ProcParams* pp, ParamsEdited* pedited=NULL);

View File

@@ -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); 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) ); signal_event().connect( sigc::mem_fun(*this, &MyCurve::handleEvents) );
curve.x.push_back(0); curve.x.push_back(0.);
curve.y.push_back(0); curve.y.push_back(0.);
curve.x.push_back(1); curve.x.push_back(1.);
curve.y.push_back(1); curve.y.push_back(1.);
curve.type = Spline; curve.type = Spline;
mcih = new MyCurveIdleHelper; mcih = new MyCurveIdleHelper;
@@ -54,8 +54,8 @@ MyCurve::~MyCurve () {
mcih->destroyed = true; mcih->destroyed = true;
else else
delete mcih; delete mcih;
curve.x.empty(); //curve.x.clear();
curve.y.empty(); //curve.y.clear();
} }
std::vector<double> MyCurve::get_vector (int veclen) { std::vector<double> MyCurve::get_vector (int veclen) {
@@ -563,12 +563,12 @@ void MyCurve::findClosestPoint() {
} }
std::vector<double> MyCurve::getPoints () { std::vector<double> MyCurve::getPoints () {
std::vector<double> result; std::vector<double> result;
if (curve.type==Parametric) { if (curve.type==Parametric) {
result.push_back ((double)(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]); result.push_back (curve.x[i]);
}
} }
else { else {
// the first value gives the type of the curve // the first value gives the type of the curve
@@ -579,17 +579,17 @@ std::vector<double> MyCurve::getPoints () {
else if (curve.type==NURBS) else if (curve.type==NURBS)
result.push_back ((double)(NURBS)); result.push_back ((double)(NURBS));
// then we push all the points coordinate // 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) { if (curve.x[i]>=0) {
result.push_back (curve.x[i]); result.push_back (curve.x[i]);
result.push_back (curve.y[i]); result.push_back (curve.y[i]);
} }
}
} }
return result; return result;
} }
void MyCurve::setPoints (const std::vector<double>& p) { void MyCurve::setPoints (const std::vector<double>& p) {
int ix = 0; int ix = 0;
CurveType t = (CurveType)p[ix++]; CurveType t = (CurveType)p[ix++];
curve.type = t; curve.type = t;

View File

@@ -105,7 +105,7 @@ void Options::setDefaults () {
editorToSendTo = 1; editorToSendTo = 1;
liveThumbnails = true; liveThumbnails = true;
tpOpen.clear (); tpOpen.clear ();
crvOpen.clear (); //crvOpen.clear ();
parseExtensions.clear (); parseExtensions.clear ();
parseExtensionsEnabled.clear (); parseExtensionsEnabled.clear ();
renameUseTemplates = false; 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", "FrameColor")) bgcolor = keyFile.get_integer ("GUI", "FrameColor");
if (keyFile.has_key ("GUI", "ProcessingQueueEnbled"))procQueueEnabled = keyFile.get_boolean ("GUI", "ProcessingQueueEnbled"); 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", "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); keyFile.set_boolean ("GUI", "ProcessingQueueEnbled", procQueueEnabled);
Glib::ArrayHandle<int> tpopen = tpOpen; Glib::ArrayHandle<int> tpopen = tpOpen;
keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen); keyFile.set_integer_list ("GUI", "ToolPanelsExpanded", tpopen);
Glib::ArrayHandle<int> crvopen = crvOpen; //Glib::ArrayHandle<int> crvopen = crvOpen;
keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen); //keyFile.set_integer_list ("GUI", "CurvePanelsExpanded", crvopen);
keyFile.set_integer ("Crop Settings", "DPI", cropDPI); keyFile.set_integer ("Crop Settings", "DPI", cropDPI);

View File

@@ -116,7 +116,7 @@ class Options {
std::vector<Glib::ustring> parseExtensions; std::vector<Glib::ustring> parseExtensions;
std::vector<int> parseExtensionsEnabled; std::vector<int> parseExtensionsEnabled;
std::vector<int> tpOpen; std::vector<int> tpOpen;
std::vector<int> crvOpen; //std::vector<int> crvOpen;
std::vector<int> baBehav; std::vector<int> baBehav;
rtengine::Settings rtSettings; rtengine::Settings rtSettings;

41
rtgui/popupbutton.cc Normal file
View File

@@ -0,0 +1,41 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#include <popupbutton.h>
/*
* 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);
}

35
rtgui/popupbutton.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#ifndef _POPUPBUTTON_
#define _POPUPBUTTON_
#include <gtkmm.h>
#include <popupcommon.h>
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

141
rtgui/popupcommon.cc Normal file
View File

@@ -0,0 +1,141 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#include <popupcommon.h>
#include <safegtk.h>
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<Gtk::Image*>::iterator i = images.begin(); i != images.end(); ++i)
{
delete *i;
}
for (std::vector<Gtk::ImageMenuItem*>::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;
}

68
rtgui/popupcommon.h Normal file
View File

@@ -0,0 +1,68 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#ifndef _POPUPCOMMON_
#define _POPUPCOMMON_
#include <gtkmm.h>
#include <sigc++/sigc++.h>
class PopUpCommon {
public:
typedef sigc::signal<void, int> 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<Glib::ustring> sItems;
std::vector<Glib::ustring> imagePaths;
std::vector<Gtk::Image*> images;
std::vector<Gtk::ImageMenuItem*> 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

View File

@@ -0,0 +1,41 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#include <popuptogglebutton.h>
/*
* 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);
}

35
rtgui/popuptogglebutton.h Normal file
View File

@@ -0,0 +1,35 @@
/*
* This file is part of RawTherapee.
*
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
*
* RawTherapee is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* RawTherapee is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*
* Class created by Jean-Christophe FRISCH, aka 'Hombre'
*/
#ifndef _POPUPTOGGLEBUTTON_
#define _POPUPTOGGLEBUTTON_
#include <popupbutton.h>
#include <popupcommon.h>
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

View File

@@ -72,12 +72,17 @@ ToneCurve::ToneCurve () : ToolPanel(), expAdd(false), blackAdd(false), brAdd(fal
//----------- Curve ------------------------------ //----------- Curve ------------------------------
pack_start (*Gtk::manage (new Gtk::HSeparator())); pack_start (*Gtk::manage (new Gtk::HSeparator()));
shape = Gtk::manage (new CurveEditor ()); curveEditorG = new CurveEditorGroup (M("TP_EXPOSURE_CURVEEDITOR"));
shape->setCurveListener (this); curveEditorG->setCurveListener (this);
curvexp = Gtk::manage (new Gtk::Expander (M("TP_EXPOSURE_CURVEEDITOR")));
curvexp->add (*shape);
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 ------------- // --------- Set Up Listeners -------------
expcomp->setAdjusterListener (this); expcomp->setAdjusterListener (this);
@@ -267,7 +272,7 @@ void ToneCurve::waitForAutoExp () {
hlcompr->setEnabled (false); hlcompr->setEnabled (false);
shcompr->setEnabled (false); shcompr->setEnabled (false);
contrast->setEnabled (false); contrast->setEnabled (false);
shape->set_sensitive (false); curveEditorG->set_sensitive (false);
} }
int aexpcomputed (void* data) { int aexpcomputed (void* data) {
@@ -296,7 +301,7 @@ void ToneCurve::enableAll () {
hlcompr->setEnabled (true); hlcompr->setEnabled (true);
shcompr->setEnabled (true); shcompr->setEnabled (true);
contrast->setEnabled (true); contrast->setEnabled (true);
shape->set_sensitive (true); curveEditorG->set_sensitive (true);
} }
bool ToneCurve::autoExpComputed_ () { bool ToneCurve::autoExpComputed_ () {
@@ -310,17 +315,6 @@ bool ToneCurve::autoExpComputed_ () {
return false; return false;
} }
void ToneCurve::expandCurve (bool isExpanded) {
curvexp->set_expanded (isExpanded);
}
bool ToneCurve::isCurveExpanded () {
return curvexp->get_expanded ();
}
void ToneCurve::setBatchMode (bool batchMode) { void ToneCurve::setBatchMode (bool batchMode) {
removeIfThere (abox, autolevels, false); removeIfThere (abox, autolevels, false);
@@ -336,7 +330,7 @@ void ToneCurve::setBatchMode (bool batchMode) {
brightness->showEditedCB (); brightness->showEditedCB ();
contrast->showEditedCB (); contrast->showEditedCB ();
shape->setBatchMode (batchMode); curveEditorG->setBatchMode (batchMode);
} }
void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) { void ToneCurve::setAdjusterBehavior (bool expadd, bool bradd, bool blackadd, bool contradd) {

View File

@@ -23,6 +23,7 @@
#include <adjuster.h> #include <adjuster.h>
#include <toolpanel.h> #include <toolpanel.h>
#include <curveeditor.h> #include <curveeditor.h>
#include <curveeditorgroup.h>
#include <mycurve.h> #include <mycurve.h>
class ToneCurve : public Gtk::VBox, public AdjusterListener, public ToolPanel, public rtengine::AutoExpListener, public CurveListener { 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; Adjuster* contrast;
bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto; bool expAdd, blackAdd, brAdd, contrAdd, clipDirty, lastAuto;
sigc::connection autoconn; sigc::connection autoconn;
CurveEditorGroup* curveEditorG;
CurveEditor* shape; CurveEditor* shape;
Gtk::Expander* curvexp;
double nextBr; double nextBr;
int nextBl; int nextBl;

View File

@@ -275,8 +275,8 @@ void ToolPanelCoordinator::readOptions () {
if (i<expList.size()) if (i<expList.size())
expList[i]->set_expanded (options.tpOpen[i]); expList[i]->set_expanded (options.tpOpen[i]);
if (options.crvOpen.size()>1) //if (options.crvOpen.size()>1)
curve->expandCurve (options.crvOpen[0]); // curve->expandCurve (options.crvOpen[0]);
} }
void ToolPanelCoordinator::writeOptions () { void ToolPanelCoordinator::writeOptions () {
@@ -286,8 +286,8 @@ void ToolPanelCoordinator::writeOptions () {
for (int i=0; i<expList.size(); i++) for (int i=0; i<expList.size(); i++)
options.tpOpen.push_back (expList[i]->get_expanded ()); options.tpOpen.push_back (expList[i]->get_expanded ());
options.crvOpen.clear (); //options.crvOpen.clear ();
options.crvOpen.push_back (curve->isCurveExpanded()); //options.crvOpen.push_back (curve->isCurveExpanded());
} }

205
tools/CurveType.svg Normal file
View File

@@ -0,0 +1,205 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="24"
height="24"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
version="1.0"
sodipodi:docname="CurveType.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
inkscape:export-filename="D:\Jean-Christophe\Developpement\WorkspaceCPP\rawtherapee-head\rtdata\images\curveType-unchanged.png"
inkscape:export-xdpi="67.5"
inkscape:export-ydpi="67.5">
<defs
id="defs4">
<linearGradient
id="linearGradient3205">
<stop
style="stop-color:#000000;stop-opacity:0.19512194;"
offset="0"
id="stop3207" />
<stop
style="stop-color:#ffffff;stop-opacity:0.19607843;"
offset="1"
id="stop3209" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3205"
id="linearGradient3211"
x1="12"
y1="24"
x2="12"
y2="0"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0434783,0,0,1.0434783,119.47826,-40.521739)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3205"
id="linearGradient3176"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0434783,0,0,1.0434783,79.47826,-40.521739)"
x1="12"
y1="24"
x2="12"
y2="0" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3205"
id="linearGradient3180"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0434783,0,0,1.0434783,39.47826,-40.521739)"
x1="12"
y1="24"
x2="12"
y2="0" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3205"
id="linearGradient3184"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.0434783,0,0,1.0434783,159.47826,-40.521739)"
x1="12"
y1="24"
x2="12"
y2="0" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#212121"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="2.84"
inkscape:cx="104.59733"
inkscape:cy="31.731418"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:window-width="1680"
inkscape:window-height="994"
inkscape:window-x="-4"
inkscape:window-y="-4" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1">
<rect
y="-40"
x="160"
height="24"
width="24"
id="rect3182"
style="fill:url(#linearGradient3184);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<rect
style="fill:url(#linearGradient3180);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect3178"
width="24"
height="24"
x="40"
y="-40" />
<rect
style="fill:url(#linearGradient3211);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="rect2383"
width="24"
height="24"
x="120"
y="-40" />
<rect
y="-40"
x="80"
height="24"
width="24"
id="rect3174"
style="fill:url(#linearGradient3176);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#be0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 79.92808,24.660312 C 82.91811,16.699566 92.18207,4.622125 104.45279,0.242516"
id="path3159"
sodipodi:nodetypes="cc" />
<path
style="opacity:0.7;fill:none;fill-rule:evenodd;stroke:#76a400;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 161.27126,22.542893 L 164.43049,6.364908 L 183.17098,0.797204"
id="path3167"
sodipodi:nodetypes="ccc" />
<path
sodipodi:nodetypes="cc"
id="path3181"
d="M 160.42808,24.472812 C 163.41811,16.512066 172.49457,4.372125 184.76529,-0.007484"
style="fill:none;fill-rule:evenodd;stroke:#be0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path3183"
d="M 40.02126,24.105393 L 64.29598,-0.265296"
style="opacity:1;fill:none;fill-rule:evenodd;stroke:#be0000;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path3195"
d="M 120.34597,24.205807 C 123.336,16.245061 132.01862,4.462353 144.28934,0.082744"
style="fill:none;fill-rule:evenodd;stroke:#be0000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
style="fill:none;fill-rule:evenodd;stroke:#76a400;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 132,20 L 140,20"
id="path3197"
sodipodi:nodetypes="cc" />
<path
sodipodi:nodetypes="cc"
id="path3199"
d="M 132,17 L 140,17"
style="fill:none;fill-rule:evenodd;stroke:#76a400;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path3201"
d="M 132,14 L 140,14"
style="fill:none;fill-rule:evenodd;stroke:#76a400;stroke-width:2;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
transform="matrix(2.7600806,0,0,2.7600806,148.12887,-22.689217)"
d="M 7.0710679,10.497826 A 1.1711456,1.1711456 0 1 1 4.7287768,10.497826 A 1.1711456,1.1711456 0 1 1 7.0710679,10.497826 z"
sodipodi:ry="1.1711456"
sodipodi:rx="1.1711456"
sodipodi:cy="10.497826"
sodipodi:cx="5.8999224"
id="path3373"
style="fill:#76a400;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
sodipodi:type="arc"
style="fill:#76a400;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3155"
sodipodi:cx="5.8999224"
sodipodi:cy="10.497826"
sodipodi:rx="1.1711456"
sodipodi:ry="1.1711456"
d="M 7.0710679,10.497826 A 1.1711456,1.1711456 0 1 1 4.7287768,10.497826 A 1.1711456,1.1711456 0 1 1 7.0710679,10.497826 z"
transform="matrix(2.7600806,0,0,2.7600806,69.37757,-14.600829)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.4 KiB