rawTherapee/rtgui/framing.cc
Daniel Gao 4969fdd989 Clean up framing compiler warnings
* Remove unused variables/dead code
* Add missing `.children = {}`
* Remove relative includes
2024-12-27 18:37:11 -05:00

1094 lines
35 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.
*
* 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 <https://www.gnu.org/licenses/>.
*
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
*/
#include "framing.h"
#include "aspectratios.h"
#include "colorpreview.h"
#include "eventmapper.h"
#include "paramsedited.h"
#include "resize.h"
#include "rtengine/color.h"
#include "rtengine/procparams.h"
#include <array>
#include <iomanip>
#include <vector>
namespace
{
using namespace rtengine;
using rtengine::procparams::FramingParams;
constexpr int EMPTY_COMBO_INDEX = -1;
// Framing method combo box data
constexpr int INDEX_STANDARD = 0;
constexpr int INDEX_BBOX = 1;
constexpr int INDEX_FIXED = 2;
constexpr int INDEX_FRAMING_METHOD_UNCHANGED = 3;
constexpr std::array<const char*, 3> FRAMING_METHODS = {
"TP_FRAMING_METHOD_STANDARD",
"TP_FRAMING_METHOD_BBOX",
"TP_FRAMING_METHOD_FIXED"
};
int mapFramingMethod(FramingParams::FramingMethod framingMethod)
{
using FramingMethod = FramingParams::FramingMethod;
switch (framingMethod) {
case FramingMethod::STANDARD:
return INDEX_STANDARD;
case FramingMethod::BBOX:
return INDEX_BBOX;
case FramingMethod::FIXED_SIZE:
return INDEX_FIXED;
default:
return INDEX_STANDARD;
}
}
FramingParams::FramingMethod mapFramingMethod(int comboIndex)
{
using FramingMethod = FramingParams::FramingMethod;
switch (comboIndex) {
case INDEX_STANDARD:
return FramingMethod::STANDARD;
case INDEX_BBOX:
return FramingMethod::BBOX;
case INDEX_FIXED:
return FramingMethod::FIXED_SIZE;
default:
return FramingMethod::STANDARD;
}
}
// Orientation combo box data
constexpr int INDEX_AS_IMAGE = 0;
constexpr int INDEX_LANDSCAPE = 1;
constexpr int INDEX_PORTRAIT = 2;
constexpr int INDEX_ORIENTATION_UNCHANGED = 3;
constexpr std::array<const char*, 3> ORIENTATION = {
"GENERAL_ASIMAGE",
"GENERAL_LANDSCAPE",
"GENERAL_PORTRAIT"
};
int mapOrientation(FramingParams::Orientation orientation)
{
using Orientation = FramingParams::Orientation;
switch (orientation) {
case Orientation::AS_IMAGE:
return INDEX_AS_IMAGE;
case Orientation::LANDSCAPE:
return INDEX_LANDSCAPE;
case Orientation::PORTRAIT:
return INDEX_PORTRAIT;
default:
return INDEX_AS_IMAGE;
}
}
FramingParams::Orientation mapOrientation(int comboIndex)
{
using Orientation = FramingParams::Orientation;
switch (comboIndex) {
case INDEX_AS_IMAGE:
return Orientation::AS_IMAGE;
case INDEX_LANDSCAPE:
return Orientation::LANDSCAPE;
case INDEX_PORTRAIT:
return Orientation::PORTRAIT;
default:
return Orientation::AS_IMAGE;
}
}
// Border sizing method combo box data
constexpr int INDEX_SIZE_RELATIVE = 0;
constexpr int INDEX_SIZE_UNIFORM_RELATIVE = 1;
constexpr int INDEX_SIZE_ABSOLUTE = 2;
constexpr int INDEX_SIZE_UNCHANGED = 3;
constexpr std::array<const char*, 3> BORDER_SIZE_METHODS = {
"TP_FRAMING_BORDER_SIZE_RELATIVE",
"TP_FRAMING_BORDER_SIZE_UNIFORM_RELATIVE",
"TP_FRAMING_BORDER_SIZE_ABSOLUTE"
};
int mapBorderSizeMethod(FramingParams::BorderSizing sizing)
{
using BorderSizing = FramingParams::BorderSizing;
switch (sizing) {
case BorderSizing::PERCENTAGE:
return INDEX_SIZE_RELATIVE;
case BorderSizing::UNIFORM_PERCENTAGE:
return INDEX_SIZE_UNIFORM_RELATIVE;
case BorderSizing::FIXED_SIZE:
return INDEX_SIZE_ABSOLUTE;
default:
return INDEX_SIZE_RELATIVE;
}
}
FramingParams::BorderSizing mapBorderSizeMethod(int comboIndex)
{
using BorderSizing = FramingParams::BorderSizing;
switch (comboIndex) {
case INDEX_SIZE_RELATIVE:
return BorderSizing::PERCENTAGE;
case INDEX_SIZE_UNIFORM_RELATIVE:
return BorderSizing::UNIFORM_PERCENTAGE;
case INDEX_SIZE_ABSOLUTE:
return BorderSizing::FIXED_SIZE;
default:
return BorderSizing::PERCENTAGE;
}
}
// Relative sizing basis combo box data
constexpr int INDEX_BASIS_AUTO = 0;
constexpr int INDEX_BASIS_WIDTH = 1;
constexpr int INDEX_BASIS_HEIGHT = 2;
constexpr int INDEX_BASIS_LONG = 3;
constexpr int INDEX_BASIS_SHORT = 4;
constexpr int INDEX_BASIS_UNCHANGED = 5;
constexpr std::array<const char*, 5> BORDER_SIZE_BASIS = {
"TP_FRAMING_BASIS_AUTO",
"TP_FRAMING_BASIS_WIDTH",
"TP_FRAMING_BASIS_HEIGHT",
"TP_FRAMING_BASIS_LONG_SIDE",
"TP_FRAMING_BASIS_SHORT_SIDE"
};
int mapBasis(FramingParams::Basis basis)
{
using Basis = FramingParams::Basis;
switch(basis) {
case Basis::AUTO:
return INDEX_BASIS_AUTO;
case Basis::WIDTH:
return INDEX_BASIS_WIDTH;
case Basis::HEIGHT:
return INDEX_BASIS_HEIGHT;
case Basis::LONG:
return INDEX_BASIS_LONG;
case Basis::SHORT:
return INDEX_BASIS_SHORT;
default:
return INDEX_BASIS_AUTO;
}
}
FramingParams::Basis mapBasis(int comboIndex)
{
using Basis = FramingParams::Basis;
switch(comboIndex) {
case INDEX_BASIS_AUTO:
return Basis::AUTO;
case INDEX_BASIS_WIDTH:
return Basis::WIDTH;
case INDEX_BASIS_HEIGHT:
return Basis::HEIGHT;
case INDEX_BASIS_LONG:
return Basis::LONG;
case INDEX_BASIS_SHORT:
return Basis::SHORT;
default:
return Basis::AUTO;
}
}
constexpr int INITIAL_IMG_WIDTH = 100000;
constexpr int INITIAL_IMG_HEIGHT = 100000;
constexpr int MAX_COLOR_VAL = 255;
constexpr int ROW_SPACING = 4;
constexpr float FRAME_LABEL_ALIGN_X = 0.025;
constexpr float FRAME_LABEL_ALIGN_Y = 0.5;
Gtk::Label* createGridLabel(const char* text)
{
Gtk::Label* label = Gtk::manage(new Gtk::Label(M(text)));
label->set_halign(Gtk::ALIGN_START);
return label;
}
MySpinButton* createSpinButton()
{
MySpinButton* button = Gtk::manage(new MySpinButton());
button->set_width_chars(5);
button->set_digits(0);
button->set_increments(1, 100);
setExpandAlignProperties(button, false, false, Gtk::ALIGN_END, Gtk::ALIGN_CENTER);
return button;
}
} // namespace
const Glib::ustring Framing::TOOL_NAME = "framing";
class Framing::AspectRatios
{
public:
static constexpr int INDEX_CURRENT = 0;
AspectRatios() :
ratios{{M("GENERAL_ASIMAGE")}}
{
fillAspectRatios(ratios);
}
void fillCombo(MyComboBoxText* combo) const
{
for (const auto& aspectRatio : ratios) {
combo->append(aspectRatio.label);
}
combo->set_active(INDEX_CURRENT);
}
int unchangedIndex() const { return ratios.size(); }
double value(int index) const
{
return ratios.at(index).value;
}
int findIndex(double aspectRatio) const
{
if (aspectRatio == FramingParams::AS_IMAGE_ASPECT_RATIO) return INDEX_CURRENT;
for (size_t i = 1; i < ratios.size(); i++) {
if (ratios[i].value == aspectRatio) return i;
}
// Couldn't find a matching value
return INDEX_CURRENT;
}
private:
std::vector<AspectRatio> ratios;
};
Framing::DimensionGui::DimensionGui(Gtk::Box* parent, const char* text)
{
box = Gtk::manage(new Gtk::Box());
Gtk::Label* label = Gtk::manage(new Gtk::Label(M(text)));
setExpandAlignProperties(label, false, false, Gtk::ALIGN_START, Gtk::ALIGN_CENTER);
value = createSpinButton();
box->pack_start(*label);
box->pack_start(*value);
parent->pack_start(*box);
}
void Framing::DimensionGui::connect(Framing& framing, CallbackFunc callback)
{
connection = value->signal_value_changed().connect(sigc::mem_fun(framing, callback), true);
}
Framing::Framing() :
FoldableToolPanel(this, TOOL_NAME, M("TP_FRAMING_LABEL"), false, true),
aspectRatioData(new AspectRatios),
imgWidth(INITIAL_IMG_WIDTH),
imgHeight(INITIAL_IMG_HEIGHT),
lastAllowUpscaling(false),
lastMinSizeEnabled(false)
{
setupEvents();
setupFramingMethodGui();
pack_start(*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL)));
setupBorderSizeGui();
pack_start(*Gtk::manage(new Gtk::Separator(Gtk::ORIENTATION_HORIZONTAL)));
setupBorderColorsGui();
}
Framing::~Framing() {
idleRegister.destroy();
}
void Framing::setupEvents()
{
auto m = ProcEventMapper::getInstance();
// clang-format off
EvFramingEnabled = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ENABLED");
EvFramingMethod = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_METHOD");
EvFramingAspectRatio = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ASPECT_RATIO");
EvFramingOrientation = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ORIENTATION");
EvFramingFramedWidth = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_FRAMED_WIDTH");
EvFramingFramedHeight = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_FRAMED_HEIGHT");
EvFramingAllowUpscaling = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ALLOW_UPSCALING");
EvFramingBorderSizingMethod = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BORDER_SIZE_METHOD");
EvFramingBasis = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BASIS");
EvFramingRelativeBorderSize = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BORDER_SIZE");
EvFramingMinSizeEnabled = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_MIN_SIZE_ENABLED");
EvFramingMinWidth = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_MIN_WIDTH");
EvFramingMinHeight = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_MIN_HEIGHT");
EvFramingAbsWidth = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ABSOLUTE_WIDTH");
EvFramingAbsHeight = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_ABSOLUTE_HEIGHT");
EvFramingBorderRed = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BORDER_RED");
EvFramingBorderGreen = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BORDER_GREEN");
EvFramingBorderBlue = m->newEvent(RESIZE, "HISTORY_MSG_FRAMING_BORDER_BLUE");
// clang-format on
}
void Framing::setupFramingMethodGui()
{
Gtk::Grid* combos = Gtk::manage(new Gtk::Grid());
combos->set_row_spacing(ROW_SPACING);
framingMethod = Gtk::manage(new MyComboBoxText());
for (auto label : FRAMING_METHODS) {
framingMethod->append(M(label));
}
framingMethod->set_active(INDEX_STANDARD);
framingMethod->set_hexpand();
framingMethod->set_halign(Gtk::ALIGN_FILL);
combos->attach(*createGridLabel("TP_FRAMING_METHOD"), 0, 0);
combos->attach(*framingMethod, 1, 0);
aspectRatioLabel = createGridLabel("TP_FRAMING_ASPECT_RATIO");
aspectRatio = Gtk::manage(new MyComboBoxText());
aspectRatioData->fillCombo(aspectRatio);
aspectRatio->set_hexpand();
aspectRatio->set_halign(Gtk::ALIGN_FILL);
combos->attach(*aspectRatioLabel, 0, 1);
combos->attach(*aspectRatio, 1, 1);
orientationLabel = createGridLabel("TP_FRAMING_ORIENTATION");
orientation = Gtk::manage(new MyComboBoxText());
for (auto label : ORIENTATION) {
orientation->append(M(label));
}
orientation->set_active(INDEX_AS_IMAGE);
orientation->set_hexpand();
orientation->set_halign(Gtk::ALIGN_FILL);
combos->attach(*orientationLabel, 0, 2);
combos->attach(*orientation, 1, 2);
pack_start(*combos);
width = DimensionGui(this, "TP_FRAMING_FRAMED_WIDTH");
width.setRange(Resize::MIN_SIZE, Resize::MAX_SCALE * imgWidth);
width.setValue(imgWidth);
height = DimensionGui(this, "TP_FRAMING_FRAMED_HEIGHT");
height.setRange(Resize::MIN_SIZE, Resize::MAX_SCALE * imgHeight);
height.setValue(imgHeight);
allowUpscaling = Gtk::manage(new Gtk::CheckButton(M("TP_FRAMING_ALLOW_UPSCALING")));
pack_start(*allowUpscaling);
updateFramingMethodGui();
framingMethodChanged = framingMethod->signal_changed().connect(
sigc::mem_fun(*this, &Framing::onFramingMethodChanged));
aspectRatioChanged = aspectRatio->signal_changed().connect(
sigc::mem_fun(*this, &Framing::onAspectRatioChanged));
orientationChanged = orientation->signal_changed().connect(
sigc::mem_fun(*this, &Framing::onOrientationChanged));
width.connect(*this, &Framing::onWidthChanged);
height.connect(*this, &Framing::onHeightChanged);
allowUpscalingConnection = allowUpscaling->signal_toggled().connect(
sigc::mem_fun(*this, &Framing::onAllowUpscalingToggled));
}
void Framing::setupBorderSizeGui()
{
Gtk::Grid* combos = Gtk::manage(new Gtk::Grid());
combos->set_row_spacing(ROW_SPACING);
borderSizeMethod = Gtk::manage(new MyComboBoxText());
for (auto label : BORDER_SIZE_METHODS) {
borderSizeMethod->append(M(label));
}
borderSizeMethod->set_active(INDEX_SIZE_RELATIVE);
borderSizeMethod->set_hexpand();
borderSizeMethod->set_halign(Gtk::ALIGN_FILL);
combos->attach(*createGridLabel("TP_FRAMING_BORDER_SIZE_METHOD"), 0, 0);
combos->attach(*borderSizeMethod, 1, 0);
basisLabel = createGridLabel("TP_FRAMING_BASIS");
basis = Gtk::manage(new MyComboBoxText());
for (auto label : BORDER_SIZE_BASIS) {
basis->append(M(label));
}
basis->set_active(INDEX_BASIS_AUTO);
basis->set_hexpand();
basis->set_halign(Gtk::ALIGN_FILL);
combos->attach(*basisLabel, 0, 1);
combos->attach(*basis, 1, 1);
pack_start(*combos);
relativeBorderSize = Gtk::manage(new Adjuster(M("TP_FRAMING_BORDER_SIZE"), 0, 1, 0.01, 0.1));
pack_start(*relativeBorderSize);
minSizeFrame = Gtk::manage(new Gtk::Frame());
minSizeFrame->set_label_align(FRAME_LABEL_ALIGN_X, FRAME_LABEL_ALIGN_Y);
minSizeEnabled = Gtk::manage(new Gtk::CheckButton(M("TP_FRAMING_LIMIT_MINIMUM")));
minSizeFrame->set_label_widget(*minSizeEnabled);
minSizeFrameContent = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
minWidth = DimensionGui(minSizeFrameContent, "TP_FRAMING_MIN_WIDTH");
minWidth.setRange(0, imgWidth);
minWidth.setValue(0);
minHeight = DimensionGui(minSizeFrameContent, "TP_FRAMING_MIN_HEIGHT");
minHeight.setRange(0, imgHeight);
minHeight.setValue(0);
minSizeFrame->add(*minSizeFrameContent);
pack_start(*minSizeFrame);
absWidth = DimensionGui(this, "TP_FRAMING_ABSOLUTE_WIDTH");
absWidth.setRange(0, imgWidth);
absWidth.setValue(0);
absHeight = DimensionGui(this, "TP_FRAMING_ABSOLUTE_HEIGHT");
absHeight.setRange(0, imgHeight);
absHeight.setValue(0);
updateBorderSizeGui();
borderSizeMethodChanged = borderSizeMethod->signal_changed().connect(
sigc::mem_fun(*this, &Framing::onBorderSizeMethodChanged));
basisChanged = basis->signal_changed().connect(
sigc::mem_fun(*this, &Framing::onBasisChanged));
relativeBorderSize->setAdjusterListener(this);
minSizeEnabledConnection = minSizeEnabled->signal_toggled().connect(
sigc::mem_fun(*this, &Framing::onMinSizeToggled));
minWidth.connect(*this, &Framing::onMinWidthChanged);
minHeight.connect(*this, &Framing::onMinHeightChanged);
absWidth.connect(*this, &Framing::onAbsWidthChanged);
absHeight.connect(*this, &Framing::onAbsHeightChanged);
}
void Framing::setupBorderColorsGui()
{
Gtk::Frame* const frame = Gtk::manage(new Gtk::Frame());
Gtk::Label* const label = Gtk::manage(new Gtk::Label(M("TP_FRAMING_BORDER_COLOR")));
frame->set_label_align(FRAME_LABEL_ALIGN_X, FRAME_LABEL_ALIGN_Y);
frame->set_label_widget(*label);
Gtk::Box* const box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
redAdj = Gtk::manage(new Adjuster(M("TP_FRAMING_RED"), 0, MAX_COLOR_VAL, 1, MAX_COLOR_VAL));
box->add(*redAdj);
greenAdj = Gtk::manage(new Adjuster(M("TP_FRAMING_GREEN"), 0, MAX_COLOR_VAL, 1, MAX_COLOR_VAL));
box->add(*greenAdj);
blueAdj = Gtk::manage(new Adjuster(M("TP_FRAMING_BLUE"), 0, MAX_COLOR_VAL, 1, MAX_COLOR_VAL));
box->add(*blueAdj);
Gtk::Frame* const colorFrame = Gtk::manage(new Gtk::Frame());
colorPreview = Gtk::manage(new ColorPreview());
colorFrame->add(*colorPreview);
box->add(*colorFrame);
frame->add(*box);
pack_start(*frame);
updateBorderColorGui();
redAdj->setAdjusterListener(this);
greenAdj->setAdjusterListener(this);
blueAdj->setAdjusterListener(this);
}
void Framing::read(const rtengine::procparams::ProcParams* pp, const ParamsEdited* pedited)
{
DisableListener disableListener(this);
std::array<ConnectionBlocker, 13> blockers = {
ConnectionBlocker(framingMethodChanged),
ConnectionBlocker(aspectRatioChanged),
ConnectionBlocker(orientationChanged),
ConnectionBlocker(width.connection),
ConnectionBlocker(height.connection),
ConnectionBlocker(allowUpscalingConnection),
ConnectionBlocker(borderSizeMethodChanged),
ConnectionBlocker(basisChanged),
ConnectionBlocker(minSizeEnabledConnection),
ConnectionBlocker(minWidth.connection),
ConnectionBlocker(minHeight.connection),
ConnectionBlocker(absWidth.connection),
ConnectionBlocker(absHeight.connection)
};
BlockAdjusterEvents blockRelative(relativeBorderSize);
BlockAdjusterEvents blockRed(redAdj);
BlockAdjusterEvents blockGreen(greenAdj);
BlockAdjusterEvents blockBlue(blueAdj);
readParams(pp);
readEdited(pedited);
updateFramingMethodGui();
updateBorderSizeGui();
updateBorderColorGui();
setDimensions();
}
void Framing::readParams(const rtengine::procparams::ProcParams* pp)
{
const rtengine::procparams::FramingParams& params = pp->framing;
setEnabled(params.enabled);
framingMethod->set_active(mapFramingMethod(params.framingMethod));
aspectRatio->set_active(aspectRatioData->findIndex(params.aspectRatio));
orientation->set_active(mapOrientation(params.orientation));
width.setValue(params.framedWidth);
width.isDirty = false;
height.setValue(params.framedHeight);
height.isDirty = false;
allowUpscaling->set_active(params.allowUpscaling);
lastAllowUpscaling = params.allowUpscaling;
borderSizeMethod->set_active(mapBorderSizeMethod(params.borderSizingMethod));
basis->set_active(mapBasis(params.basis));
relativeBorderSize->setValue(params.relativeBorderSize);
minSizeEnabled->set_active(params.minSizeEnabled);
lastMinSizeEnabled = params.minSizeEnabled;
minWidth.setValue(params.minWidth);
minWidth.isDirty = false;
minHeight.setValue(params.minHeight);
minHeight.isDirty = false;
absWidth.setValue(params.absWidth);
absWidth.isDirty = false;
absHeight.setValue(params.absHeight);
absHeight.isDirty = false;
redAdj->setValue(params.borderRed);
greenAdj->setValue(params.borderGreen);
blueAdj->setValue(params.borderBlue);
}
void Framing::readEdited(const ParamsEdited* pedited)
{
if (!pedited) return;
const FramingParamsEdited& edits = pedited->framing;
set_inconsistent(multiImage && !edits.enabled);
if (!edits.framingMethod) {
framingMethod->set_active(EMPTY_COMBO_INDEX);
}
if (!edits.aspectRatio) {
aspectRatio->set_active(EMPTY_COMBO_INDEX);
}
if (!edits.orientation) {
orientation->set_active(EMPTY_COMBO_INDEX);
}
width.isDirty = edits.framedWidth;
height.isDirty = edits.framedHeight;
allowUpscaling->set_inconsistent(edits.allowUpscaling);
if (!edits.borderSizingMethod) {
borderSizeMethod->set_active(EMPTY_COMBO_INDEX);
}
if (!edits.basis) {
basis->set_active(EMPTY_COMBO_INDEX);
}
relativeBorderSize->setEditedState(edits.relativeBorderSize ? Edited : UnEdited);
minSizeEnabled->set_inconsistent(edits.minSizeEnabled);
minWidth.isDirty = edits.minWidth;
minHeight.isDirty = edits.minHeight;
absWidth.isDirty = edits.absWidth;
absHeight.isDirty = edits.absHeight;
redAdj->setEditedState(edits.borderRed ? Edited : UnEdited);
greenAdj->setEditedState(edits.borderGreen ? Edited : UnEdited);
blueAdj->setEditedState(edits.borderBlue ? Edited : UnEdited);
}
void Framing::write(rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
{
writeParams(pp);
writeEdited(pedited);
}
void Framing::writeParams(rtengine::procparams::ProcParams* pp)
{
rtengine::procparams::FramingParams& params = pp->framing;
params.enabled = getEnabled();
params.framingMethod = mapFramingMethod(framingMethod->get_active_row_number());
params.aspectRatio = aspectRatioData->value(aspectRatio->get_active_row_number());
params.orientation = mapOrientation(orientation->get_active_row_number());
params.framedWidth = width.value->get_value_as_int();
params.framedHeight = height.value->get_value_as_int();
params.allowUpscaling = allowUpscaling->get_active();
params.borderSizingMethod = mapBorderSizeMethod(borderSizeMethod->get_active_row_number());
params.basis = mapBasis(basis->get_active_row_number());
params.relativeBorderSize = relativeBorderSize->getValue();
params.minSizeEnabled = minSizeEnabled->get_active();
params.minWidth = minWidth.value->get_value_as_int();
params.minHeight = minHeight.value->get_value_as_int();
params.absWidth = absWidth.value->get_value_as_int();
params.absHeight = absHeight.value->get_value_as_int();
params.borderRed = redAdj->getValue();
params.borderGreen = greenAdj->getValue();
params.borderBlue = blueAdj->getValue();
}
void Framing::writeEdited(ParamsEdited* pedited)
{
if (!pedited) return;
FramingParamsEdited& edits = pedited->framing;
edits.enabled = !get_inconsistent();
edits.framingMethod = framingMethod->get_active_row_number() != INDEX_FRAMING_METHOD_UNCHANGED;
edits.aspectRatio = aspectRatio->get_active_row_number() != aspectRatioData->unchangedIndex();
edits.orientation = orientation->get_active_row_number() != INDEX_ORIENTATION_UNCHANGED;
edits.framedWidth = width.isDirty;
edits.framedHeight = height.isDirty;
edits.allowUpscaling = !allowUpscaling->get_inconsistent();
edits.borderSizingMethod = borderSizeMethod->get_active_row_number() != INDEX_SIZE_UNCHANGED;
edits.basis = basis->get_active_row_number() != INDEX_BASIS_UNCHANGED;
edits.relativeBorderSize = relativeBorderSize->getEditedState();
edits.minSizeEnabled = !minSizeEnabled->get_inconsistent();
edits.minWidth = minWidth.isDirty;
edits.minHeight = minHeight.isDirty;
edits.absWidth = absWidth.isDirty;
edits.absHeight = absHeight.isDirty;
edits.borderRed = redAdj->getEditedState();
edits.borderGreen = greenAdj->getEditedState();
edits.borderBlue = blueAdj->getEditedState();
}
void Framing::setDefaults(const rtengine::procparams::ProcParams* defParams, const ParamsEdited* pedited)
{
const FramingParams& params = defParams->framing;
relativeBorderSize->setDefault(params.relativeBorderSize);
redAdj->setDefault(params.borderRed);
greenAdj->setDefault(params.borderGreen);
blueAdj->setDefault(params.borderBlue);
if (pedited) {
const FramingParamsEdited& edits = pedited->framing;
relativeBorderSize->setDefaultEditedState(edits.relativeBorderSize ? Edited : UnEdited);
redAdj->setDefaultEditedState(edits.borderRed ? Edited : UnEdited);
greenAdj->setDefaultEditedState(edits.borderGreen ? Edited : UnEdited);
blueAdj->setDefaultEditedState(edits.borderBlue ? Edited : UnEdited);
} else {
relativeBorderSize->setDefaultEditedState(Irrelevant);
redAdj->setDefaultEditedState(Irrelevant);
greenAdj->setDefaultEditedState(Irrelevant);
blueAdj->setDefaultEditedState(Irrelevant);
}
}
void Framing::trimValues(rtengine::procparams::ProcParams* pp)
{
relativeBorderSize->trimValue(pp->framing.relativeBorderSize);
redAdj->trimValue(pp->framing.borderRed);
greenAdj->trimValue(pp->framing.borderGreen);
blueAdj->trimValue(pp->framing.borderBlue);
}
void Framing::setBatchMode(bool batchMode)
{
framingMethod->append(M("GENERAL_UNCHANGED"));
aspectRatio->append(M("GENERAL_UNCHANGED"));
orientation->append(M("GENERAL_UNCHANGED"));
borderSizeMethod->append(M("GENERAL_UNCHANGED"));
basis->append(M("GENERAL_UNCHANGED"));
ToolPanel::setBatchMode(batchMode);
relativeBorderSize->showEditedCB();
redAdj->showEditedCB();
greenAdj->showEditedCB();
blueAdj->showEditedCB();
}
void Framing::enabledChanged()
{
if (listener) {
if (get_inconsistent()) {
listener->panelChanged(EvFramingEnabled, M("GENERAL_UNCHANGED"));
} else if (getEnabled()) {
listener->panelChanged(EvFramingEnabled, M("GENERAL_ENABLED"));
} else {
listener->panelChanged(EvFramingEnabled, M("GENERAL_DISABLED"));
}
}
}
void Framing::update(int originalWidth, int originalHeight)
{
// This is how it is checked in resize.cc
if (originalWidth && originalHeight) {
imgWidth = originalWidth;
imgHeight = originalHeight;
}
}
void Framing::setAdjusterBehavior(bool addRelativeBorderSize, bool addRed, bool addGreen,
bool addBlue)
{
relativeBorderSize->setAddMode(addRelativeBorderSize);
redAdj->setAddMode(addRed);
greenAdj->setAddMode(addGreen);
blueAdj->setAddMode(addBlue);
}
void Framing::setDimensions()
{
idleRegister.add([this]() -> bool {
std::array<ConnectionBlocker, 6> blockers = {
ConnectionBlocker(width.connection),
ConnectionBlocker(height.connection),
ConnectionBlocker(minWidth.connection),
ConnectionBlocker(minHeight.connection),
ConnectionBlocker(absWidth.connection),
ConnectionBlocker(absHeight.connection)
};
// 16x the full image size is probably a reasonable max
width.value->set_range(Resize::MIN_SIZE, Resize::MAX_SCALE * imgWidth);
height.value->set_range(Resize::MIN_SIZE, Resize::MAX_SCALE * imgHeight);
minWidth.value->set_range(0, Resize::MAX_SCALE * imgWidth);
minHeight.value->set_range(0, Resize::MAX_SCALE * imgHeight);
absWidth.value->set_range(0, Resize::MAX_SCALE * imgWidth);
absHeight.value->set_range(0, Resize::MAX_SCALE * imgHeight);
return false;
});
}
void Framing::updateFramingMethodGui()
{
if (batchMode) {
aspectRatioLabel->show();
aspectRatio->show();
orientationLabel->show();
orientation->show();
width.show();
height.show();
allowUpscaling->show();
return;
}
int activeRow = framingMethod->get_active_row_number();
if (activeRow == INDEX_STANDARD) {
aspectRatioLabel->show();
aspectRatio->show();
orientationLabel->show();
orientation->show();
width.hide();
height.hide();
allowUpscaling->hide();
} else if (activeRow == INDEX_BBOX) {
aspectRatioLabel->show();
aspectRatio->show();
orientationLabel->show();
orientation->show();
width.show();
height.show();
allowUpscaling->show();
} else if (activeRow == INDEX_FIXED) {
aspectRatioLabel->hide();
aspectRatio->hide();
orientationLabel->hide();
orientation->hide();
width.show();
height.show();
allowUpscaling->show();
}
}
void Framing::updateBorderSizeGui()
{
if (batchMode) {
basisLabel->show();
basis->show();
relativeBorderSize->show();
minSizeFrame->show();
absWidth.show();
absHeight.show();
aspectRatio->set_sensitive(true);
orientation->set_sensitive(true);
minSizeFrameContent->set_sensitive(true);
return;
}
int activeRow = borderSizeMethod->get_active_row_number();
if (activeRow == INDEX_SIZE_RELATIVE) {
basisLabel->show();
basis->show();
relativeBorderSize->show();
minSizeFrame->show();
absWidth.hide();
absHeight.hide();
aspectRatio->set_sensitive(true);
orientation->set_sensitive(true);
} else if (activeRow == INDEX_SIZE_UNIFORM_RELATIVE) {
basisLabel->show();
basis->show();
relativeBorderSize->show();
minSizeFrame->show();
absWidth.hide();
absHeight.hide();
aspectRatio->set_sensitive(false);
orientation->set_sensitive(false);
} else if (activeRow == INDEX_SIZE_ABSOLUTE) {
basisLabel->hide();
basis->hide();
relativeBorderSize->hide();
minSizeFrame->hide();
absWidth.show();
absHeight.show();
aspectRatio->set_sensitive(false);
orientation->set_sensitive(false);
}
minSizeFrameContent->set_sensitive(minSizeEnabled->get_active());
}
void Framing::updateBorderColorGui()
{
auto gamma = [](double val) {
// adjuster is [0.0, 255.0]
// gamma2curve expects [0, 65535]
// setRgb expects [0.0, 1.0]
return Color::gamma2curve[val * (MAX_COLOR_VAL + 1)] / 65535.0;
};
double r = gamma(redAdj->getValue());
double g = gamma(greenAdj->getValue());
double b = gamma(blueAdj->getValue());
colorPreview->setRgb(r, g, b);
}
void Framing::adjusterChanged(Adjuster* adj, double newVal)
{
if (adj == redAdj || adj == greenAdj || adj == blueAdj) {
updateBorderColorGui();
}
if (listener && (getEnabled() || batchMode)) {
Glib::ustring costr;
if (adj == relativeBorderSize) {
costr = Glib::ustring::format(std::setw(3), std::fixed, std::setprecision(2),
adj->getValue());
} else {
costr = Glib::ustring::format(static_cast<int>(adj->getValue()));
}
if (adj == relativeBorderSize) {
listener->panelChanged(EvFramingRelativeBorderSize, costr);
} else if (adj == redAdj) {
listener->panelChanged(EvFramingBorderRed, costr);
} else if (adj == greenAdj) {
listener->panelChanged(EvFramingBorderGreen, costr);
} else if (adj == blueAdj) {
listener->panelChanged(EvFramingBorderBlue, costr);
}
}
}
void Framing::onFramingMethodChanged()
{
updateFramingMethodGui();
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingMethod, framingMethod->get_active_text());
}
}
void Framing::onAspectRatioChanged()
{
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingAspectRatio, aspectRatio->get_active_text());
}
}
void Framing::onOrientationChanged()
{
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingOrientation, orientation->get_active_text());
}
}
void Framing::onWidthChanged()
{
width.isDirty = true;
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingFramedWidth,
Glib::ustring::format(width.value->get_value_as_int()));
}
}
void Framing::onHeightChanged()
{
height.isDirty = true;
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingFramedHeight,
Glib::ustring::format(height.value->get_value_as_int()));
}
}
void Framing::onAllowUpscalingToggled()
{
if (batchMode) {
if (allowUpscaling->get_inconsistent()) {
allowUpscaling->set_inconsistent(false);
ConnectionBlocker block(allowUpscalingConnection);
allowUpscaling->set_active(false);
} else if (lastAllowUpscaling) {
allowUpscaling->set_inconsistent(true);
}
lastAllowUpscaling = allowUpscaling->get_active();
}
if (listener && (getEnabled() || batchMode)) {
if (allowUpscaling->get_inconsistent()) {
listener->panelChanged(EvFramingAllowUpscaling, M("GENERAL_UNCHANGED"));
} else if (allowUpscaling->get_active()) {
listener->panelChanged(EvFramingAllowUpscaling, M("GENERAL_ENABLED"));
} else {
listener->panelChanged(EvFramingAllowUpscaling, M("GENERAL_DISABLED"));
}
}
}
void Framing::onBorderSizeMethodChanged()
{
if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) {
ConnectionBlocker block(minHeight.connection);
minHeight.isDirty = true;
minHeight.value->set_value(minWidth.value->get_value_as_int());
}
updateBorderSizeGui();
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingBorderSizingMethod, borderSizeMethod->get_active_text());
}
}
void Framing::onBasisChanged()
{
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingBasis, basis->get_active_text());
}
}
void Framing::onMinSizeToggled()
{
if (batchMode) {
if (minSizeEnabled->get_inconsistent()) {
minSizeEnabled->set_inconsistent(false);
ConnectionBlocker block(minSizeEnabledConnection);
minSizeEnabled->set_active(false);
} else if (lastMinSizeEnabled) {
minSizeEnabled->set_inconsistent(true);
}
lastMinSizeEnabled = minSizeEnabled->get_active();
}
updateBorderSizeGui();
if (listener && (getEnabled() || batchMode)) {
if (minSizeEnabled->get_inconsistent()) {
listener->panelChanged(EvFramingMinSizeEnabled, M("GENERAL_UNCHANGED"));
} else if (minSizeEnabled->get_active()) {
listener->panelChanged(EvFramingMinSizeEnabled, M("GENERAL_ENABLED"));
} else {
listener->panelChanged(EvFramingMinSizeEnabled, M("GENERAL_DISABLED"));
}
}
}
void Framing::onMinWidthChanged()
{
minWidth.isDirty = true;
int value = minWidth.value->get_value_as_int();
if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) {
ConnectionBlocker block(minHeight.connection);
minHeight.isDirty = true;
minHeight.value->set_value(value);
}
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingMinWidth, Glib::ustring::format(value));
}
}
void Framing::onMinHeightChanged()
{
minHeight.isDirty = true;
int value = minHeight.value->get_value_as_int();
if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) {
ConnectionBlocker block(minWidth.connection);
minWidth.isDirty = true;
minWidth.value->set_value(value);
}
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingMinHeight, Glib::ustring::format(value));
}
}
void Framing::onAbsWidthChanged()
{
absWidth.isDirty = true;
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingAbsWidth,
Glib::ustring::format(absWidth.value->get_value_as_int()));
}
}
void Framing::onAbsHeightChanged()
{
absHeight.isDirty = true;
if (listener && (getEnabled() || batchMode)) {
listener->panelChanged(EvFramingAbsHeight,
Glib::ustring::format(absHeight.value->get_value_as_int()));
}
}