rawTherapee/rtgui/curveeditor.cc
Hombre c7be386c3a Solving issue #3531, assign classes to Gtk::Window and MyWidget
- Curve editor buttons are set to expand by default, but they are set to
shrink as soon as an accompagnying widget is set to expand
- White Balance's method button now has a centered ellipse ("...")
- White Balance's buttons are now aligned on their right
- A "withScrollbar" class is added to MyExpander if the ToolPanel's
vertical scrollbar is visible. This can let you add padding space for
the scrollbar (see #MyExpander.withScrollbar in RT default theme)
- A "maximized" and "fullscreen" class is added to the RTWindow whenever
it change state ; BEWARE: if you maximize the window then make it
fullscreen, Gtk says that the window is in a "maximized & fullscreen"
state, which mean that both class can be added at the same time to the
window.

One Gtk oddity (at least on Windows) is that you can make your window
fullscreen and still drag it around by its header bar... That's not very
practical to click on the unfullscreen button if in Single Editor mode
with vertical Tab.

I also managed to see the window in a Inconified + Maximized state. This
part of Gtk doesn't seem very robust, on Windows at least.
2016-12-20 01:58:37 +01:00

445 lines
11 KiB
C++

/*
* 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.
*
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
*/
#include "curveeditor.h"
#include "curveeditorgroup.h"
#include <fstream>
#include <string>
#include "guiutils.h"
#include "multilangmgr.h"
#include "../rtengine/LUT.h"
#include <cstring>
bool CurveEditor::reset()
{
return subGroup->curveReset(this);
}
DiagonalCurveEditor::DiagonalCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup) : CurveEditor::CurveEditor(text, static_cast<CurveEditorGroup*>(ceGroup), ceSubGroup)
{
// Order set in the same order than "enum DiagonalCurveType". Shouldn't change, for compatibility reason
curveType->addEntry("curveType-linear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
curveType->addEntry("curveType-spline.png", M("CURVEEDITOR_CUSTOM")); // 1 Spline
curveType->addEntry("curveType-parametric.png", M("CURVEEDITOR_PARAMETRIC")); // 2 Parametric
curveType->addEntry("curveType-NURBS.png", M("CURVEEDITOR_NURBS")); // 3 NURBS
curveType->setSelected(DCT_Linear);
curveType->show();
rangeLabels[0] = M("CURVEEDITOR_SHADOWS");
rangeLabels[1] = M("CURVEEDITOR_DARKS");
rangeLabels[2] = M("CURVEEDITOR_LIGHTS");
rangeLabels[3] = M("CURVEEDITOR_HIGHLIGHTS");
rangeMilestones[0] = 0.25;
rangeMilestones[1] = 0.50;
rangeMilestones[2] = 0.75;
}
std::vector<double> DiagonalCurveEditor::getCurve ()
{
std::vector<double> curve;
switch (selected) {
case (DCT_Spline):
return curve = customCurveEd;
case (DCT_Parametric):
return curve = paramCurveEd;
case (DCT_NURBS):
return curve = NURBSCurveEd;
default:
// returning Linear or Unchanged
curve.push_back((double)(selected));
return curve;
}
}
void DiagonalCurveEditor::setResetCurve(DiagonalCurveType cType, const std::vector<double> &resetCurve)
{
switch (cType) {
case (DCT_NURBS):
if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) {
NURBSResetCurve = resetCurve;
}
break;
case (DCT_Parametric):
if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) {
paramResetCurve = resetCurve;
}
break;
case (DCT_Spline):
if (resetCurve.size() && DiagonalCurveType(resetCurve.at(0)) == cType) {
customResetCurve = resetCurve;
}
break;
default:
break;
}
}
void DiagonalCurveEditor::setRangeLabels(Glib::ustring r1, Glib::ustring r2, Glib::ustring r3, Glib::ustring r4)
{
rangeLabels[0] = r1;
rangeLabels[1] = r2;
rangeLabels[2] = r3;
rangeLabels[3] = r4;
}
void DiagonalCurveEditor::getRangeLabels(Glib::ustring &r1, Glib::ustring &r2, Glib::ustring &r3, Glib::ustring &r4)
{
r1 = rangeLabels[0];
r2 = rangeLabels[1];
r3 = rangeLabels[2];
r4 = rangeLabels[3];
}
/*
* Admittedly that this method is called just after the instantiation of this class, we set the shcselector's default values
*/
void DiagonalCurveEditor::setRangeDefaultMilestones(double m1, double m2, double m3)
{
rangeMilestones[0] = m1;
rangeMilestones[1] = m2;
rangeMilestones[2] = m3;
paramCurveEd.at(1) = m1;
paramCurveEd.at(2) = m2;
paramCurveEd.at(3) = m3;
}
void DiagonalCurveEditor::getRangeDefaultMilestones(double &m1, double &m2, double &m3)
{
m1 = rangeMilestones[0];
m2 = rangeMilestones[1];
m3 = rangeMilestones[2];
}
FlatCurveEditor::FlatCurveEditor (Glib::ustring text, CurveEditorGroup* ceGroup, CurveEditorSubGroup* ceSubGroup, bool isPeriodic) : CurveEditor::CurveEditor(text, static_cast<CurveEditorGroup*>(ceGroup), ceSubGroup)
{
periodic = isPeriodic;
identityValue = 0.5;
// Order set in the same order than "enum FlatCurveType". Shouldn't change, for compatibility reason
curveType->addEntry("curveType-flatLinear.png", M("CURVEEDITOR_LINEAR")); // 0 Linear
curveType->addEntry("curveType-controlPoints.png", M("CURVEEDITOR_MINMAXCPOINTS")); // 1 Min/Max ControlPoints
curveType->setSelected(FCT_Linear);
curveType->show();
}
std::vector<double> FlatCurveEditor::getCurve ()
{
std::vector<double> curve;
switch (selected) {
//case (Parametric):
// return curve = paramCurveEd;
case (FCT_MinMaxCPoints):
return curve = controlPointsCurveEd;
default:
// returning Linear or Unchanged
curve.push_back((double)(selected));
return curve;
}
}
void FlatCurveEditor::setResetCurve(FlatCurveType cType, const std::vector<double> &resetCurve)
{
switch (cType) {
case (FCT_MinMaxCPoints):
if (resetCurve.size() && FlatCurveType(resetCurve.at(0)) == cType) {
controlPointsResetCurve = resetCurve;
}
break;
default:
break;
}
}
/*
* 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, CurveEditorSubGroup* ceSubGroup) : EditSubscriber(ET_PIPETTE)
{
bgHistValid = false;
remoteDrag = false;
selected = DCT_Linear;
bottomBarCP = nullptr;
leftBarCP = nullptr;
curveCP = nullptr;
relatedWidget = nullptr;
expandRelatedWidget = true;
group = ceGroup;
subGroup = ceSubGroup;
if (group && text.size()) {
curveType = new PopUpToggleButton(text + ":");
} else {
curveType = new PopUpToggleButton();
}
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) );
}
void CurveEditor::setCurve (const std::vector<double>& p)
{
tempCurve = p;
group->setCurveExternal(this, p);
}
CurveEditor::~CurveEditor ()
{
delete curveType;
}
void CurveEditor::typeSelectionChanged (int n)
{
group->typeSelectionChanged(this, n);
}
void CurveEditor::curveTypeToggled()
{
group->curveTypeToggled(this);
}
bool CurveEditor::isUnChanged ()
{
return curveType->getSelected() == subGroup->getValUnchanged();
}
void CurveEditor::setUnChanged (bool uc)
{
group->setUnChanged(uc, this);
}
/*
* Update the backgrounds histograms
*/
void CurveEditor::updateBackgroundHistogram (LUTu & hist)
{
// Copy the histogram in the curve editor cache
if (hist) {
histogram = hist;
bgHistValid = true;
} else {
bgHistValid = false;
}
// Then call the curve editor group to eventually update the histogram
subGroup->updateBackgroundHistogram (this);
}
// Open up the curve if it has modifications and it's not already opened
// Returns: true if curve was non linear and opened
bool CurveEditor::openIfNonlinear()
{
bool nonLinear = tempCurve.size() && (tempCurve[0] > subGroup->getValLinear()) && (tempCurve[0] < subGroup->getValUnchanged());
if (nonLinear && !curveType->get_active()) {
// Will trigger the signal_clicked event doing the display
curveType->set_active( true );
}
return nonLinear;
}
// Handles markup tooltips
void CurveEditor::setTooltip(Glib::ustring ttip)
{
curveType->set_tooltip_text(ttip.empty() ?
Glib::ustring::compose("<b>%1</b> ", M("CURVEEDITOR_TYPE")) :
Glib::ustring::compose("%1\n<b>%2</b>", ttip, M("CURVEEDITOR_TYPE")));
}
void CurveEditor::setLeftBarColorProvider(ColorProvider* cp, int callerId)
{
leftBarCP = cp;
leftBarCId = callerId;
}
void CurveEditor::setBottomBarColorProvider(ColorProvider* cp, int callerId)
{
bottomBarCP = cp;
bottomBarCId = callerId;
}
void CurveEditor::setLeftBarBgGradient (const std::vector<GradientMilestone> &milestones)
{
leftBarBgGradient = milestones;
}
void CurveEditor::setBottomBarBgGradient (const std::vector<GradientMilestone> &milestones)
{
bottomBarBgGradient = milestones;
}
void CurveEditor::refresh ()
{
subGroup->refresh(this);
}
void CurveEditor::setCurveColorProvider(ColorProvider* cp, int callerId)
{
curveCP = cp;
curveCId = callerId;
}
ColorProvider* CurveEditor::getLeftBarColorProvider()
{
return leftBarCP;
}
ColorProvider* CurveEditor::getBottomBarColorProvider()
{
return bottomBarCP;
}
ColorProvider* CurveEditor::getCurveColorProvider()
{
return curveCP;
}
int CurveEditor::getLeftBarCallerId()
{
return leftBarCId;
}
int CurveEditor::getBottomBarCallerId()
{
return bottomBarCId;
}
int CurveEditor::getCurveCallerId()
{
return curveCId;
}
std::vector<GradientMilestone> CurveEditor::getBottomBarBgGradient () const
{
return bottomBarBgGradient;
}
std::vector<GradientMilestone> CurveEditor::getLeftBarBgGradient () const
{
return leftBarBgGradient;
}
sigc::signal<void> CurveEditor::signal_curvegraph_enter()
{
return sig_curvegraph_enter;
}
sigc::signal<void> CurveEditor::signal_curvegraph_leave()
{
return sig_curvegraph_leave;
}
sigc::signal<void> CurveEditor::signal_curvepoint_click()
{
return sig_curvepoint_click;
}
sigc::signal<void> CurveEditor::signal_curvepoint_release()
{
return sig_curvepoint_release;
}
void CurveEditor::switchOffEditMode ()
{
if (EditSubscriber::getEditID() != EUID_None) {
// switching off the toggle button
if (group->displayedCurve == this) {
subGroup->editModeSwitchedOff();
}
}
EditSubscriber::switchOffEditMode(); // disconnect
}
bool CurveEditor::mouseOver(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
subGroup->pipetteMouseOver(provider, modifierKey);
subGroup->refresh(this);
return true; // return true will ask the preview to be redrawn, for the cursor
}
bool CurveEditor::button1Pressed(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
if (provider->object) {
remoteDrag = subGroup->pipetteButton1Pressed(provider, modifierKey);
}
if (remoteDrag) {
action = ES_ACTION_DRAGGING;
}
subGroup->refresh(this);
return true;
}
bool CurveEditor::button1Released()
{
EditDataProvider* provider = getEditProvider();
subGroup->pipetteButton1Released(provider);
remoteDrag = false;
subGroup->refresh(this);
return true;
}
bool CurveEditor::drag1(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
subGroup->pipetteDrag(provider, modifierKey);
subGroup->refresh(this);
return false;
}
CursorShape CurveEditor::getCursor(const int objectID)
{
if (remoteDrag) {
return CSResizeHeight;
}
return CSOpenHand;
}