On preview widgets for the Gradient tool (center & angle). Also includes some rudimentary bounds checking (optional) when accessing some kind of array.
This commit is contained in:
@@ -2,12 +2,14 @@
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
#include "gradient.h"
|
||||
#include "rtimage.h"
|
||||
#include <iomanip>
|
||||
#include "../rtengine/rt_math.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this), EditSubscriber(ET_OBJECTS), lastObject(-1), draggedPointOldAngle(-1000.)
|
||||
{
|
||||
set_border_width(4);
|
||||
|
||||
@@ -15,6 +17,10 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
enabled->set_active (false);
|
||||
enaConn = enabled->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::enabledChanged) );
|
||||
|
||||
edit = Gtk::manage (new Gtk::ToggleButton());
|
||||
edit->add (*Gtk::manage (new RTImage ("editmodehand.png")));
|
||||
editConn = edit->signal_toggled().connect( sigc::mem_fun(*this, &Gradient::editToggled) );
|
||||
|
||||
strength = Gtk::manage (new Adjuster (M("TP_GRADIENT_STRENGTH"), -5, 5, 0.01, 0));
|
||||
strength->set_tooltip_text (M("TP_GRADIENT_STRENGTH_TOOLTIP"));
|
||||
strength->setAdjusterListener (this);
|
||||
@@ -35,7 +41,10 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
centerY->set_tooltip_text (M("TP_GRADIENT_CENTER_Y_TOOLTIP"));
|
||||
centerY->setAdjusterListener (this);
|
||||
|
||||
pack_start(*enabled);
|
||||
Gtk::HBox* enaBox = Gtk::manage (new Gtk::HBox());
|
||||
enaBox->pack_start(*enabled);
|
||||
enaBox->pack_end(*edit, false, false, 0);
|
||||
pack_start(*enaBox);
|
||||
pack_start(*Gtk::manage (new Gtk::HSeparator()), Gtk::PACK_EXPAND_WIDGET, 4);
|
||||
pack_start (*strength);
|
||||
pack_start (*degree);
|
||||
@@ -43,9 +52,52 @@ Gradient::Gradient () : Gtk::VBox(), FoldableToolPanel(this)
|
||||
pack_start (*centerX);
|
||||
pack_start (*centerY);
|
||||
|
||||
// Instantiating the Editing geometry; positions will be initialized later
|
||||
Line *hLine, *vLine;
|
||||
Circle *centerCircle;
|
||||
|
||||
// Visible geometry
|
||||
hLine = new Line(); hLine->innerLineWidth=2;
|
||||
vLine = new Line();
|
||||
hLine->datum = vLine->datum = Geometry::IMAGE;
|
||||
|
||||
centerCircle = new Circle();
|
||||
centerCircle->datum = Geometry::IMAGE;
|
||||
centerCircle->radiusInImageSpace = false;
|
||||
centerCircle->radius = 6;
|
||||
centerCircle->filled = true;
|
||||
|
||||
EditSubscriber::visibleGeometry.push_back( hLine );
|
||||
EditSubscriber::visibleGeometry.push_back( vLine );
|
||||
EditSubscriber::visibleGeometry.push_back( centerCircle );
|
||||
|
||||
// MouseOver geometry
|
||||
hLine = new Line(); hLine->innerLineWidth=2;
|
||||
vLine = new Line();
|
||||
hLine->datum = vLine->datum = Geometry::IMAGE;
|
||||
|
||||
centerCircle = new Circle();
|
||||
centerCircle->datum = Geometry::IMAGE;
|
||||
centerCircle->radiusInImageSpace = false;
|
||||
centerCircle->radius = 30;
|
||||
centerCircle->filled = true;
|
||||
|
||||
EditSubscriber::mouseOverGeometry.push_back( hLine );
|
||||
EditSubscriber::mouseOverGeometry.push_back( vLine );
|
||||
EditSubscriber::mouseOverGeometry.push_back( centerCircle );
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
||||
Gradient::~Gradient() {
|
||||
for (std::vector<Geometry*>::const_iterator i = visibleGeometry.begin(); i != visibleGeometry.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
for (std::vector<Geometry*>::const_iterator i = mouseOverGeometry.begin(); i != mouseOverGeometry.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
}
|
||||
|
||||
void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
{
|
||||
disableListener ();
|
||||
@@ -70,9 +122,43 @@ void Gradient::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
|
||||
lastEnabled = pp->gradient.enabled;
|
||||
|
||||
updateGeometry (pp->gradient.centerX, pp->gradient.centerY, pp->gradient.strength, pp->gradient.degree);
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
void Gradient::updateGeometry(int centerX_, int centerY_, double strength_, double degree_) {
|
||||
EditDataProvider* dataProvider = getEditProvider();
|
||||
if (dataProvider) {
|
||||
int imW, imH;
|
||||
dataProvider->getImageSize(imW, imH);
|
||||
|
||||
Coord origin(imW/2+centerX_*imW/200.f, imH/2+centerY_*imH/200.f);
|
||||
|
||||
Line *currLine;
|
||||
Circle *currCircle;
|
||||
// update left line
|
||||
currLine = static_cast<Line*>(visibleGeometry.at(0));
|
||||
currLine->begin.setFromPolar(PolarCoord(1500.f, float(-degree_+180))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord(1500.f, float(-degree_ ))); currLine->end += origin;
|
||||
currLine = static_cast<Line*>(mouseOverGeometry.at(0));
|
||||
currLine->begin.setFromPolar(PolarCoord(1500.f, float(-degree_+180))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord(1500.f, float(-degree_ ))); currLine->end += origin;
|
||||
// update right line
|
||||
currLine = static_cast<Line*>(visibleGeometry.at(1));
|
||||
currLine->begin.setFromPolar(PolarCoord( 700.f, float(-degree_+90 ))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord( 700.f, float(-degree_+270))); currLine->end += origin;
|
||||
currLine = static_cast<Line*>(mouseOverGeometry.at(1));
|
||||
currLine->begin.setFromPolar(PolarCoord( 700.f, float(-degree_+90 ))); currLine->begin += origin;
|
||||
currLine->end.setFromPolar (PolarCoord( 700.f, float(-degree_+270))); currLine->end += origin;
|
||||
// update circle's position
|
||||
currCircle = static_cast<Circle*>(visibleGeometry.at(2));
|
||||
currCircle->center = origin;
|
||||
currCircle = static_cast<Circle*>(mouseOverGeometry.at(2));
|
||||
currCircle->center = origin;
|
||||
}
|
||||
}
|
||||
|
||||
void Gradient::write (ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
pp->gradient.degree = degree->getValue ();
|
||||
@@ -118,6 +204,8 @@ void Gradient::setDefaults (const ProcParams* defParams, const ParamsEdited* ped
|
||||
void Gradient::adjusterChanged (Adjuster* a, double newval) {
|
||||
|
||||
if (listener && enabled->get_active()) {
|
||||
updateGeometry (int(centerX->getValue()), int(centerY->getValue()), strength->getValue(), degree->getValue());
|
||||
|
||||
if (a == degree)
|
||||
listener->panelChanged (EvGradientDegree, degree->getTextValue());
|
||||
else if (a == feather)
|
||||
@@ -178,3 +266,146 @@ void Gradient::setBatchMode (bool batchMode)
|
||||
centerX->showEditedCB ();
|
||||
centerY->showEditedCB ();
|
||||
}
|
||||
|
||||
void Gradient::setEditProvider (EditDataProvider* provider) {
|
||||
EditSubscriber::setEditProvider(provider);
|
||||
}
|
||||
|
||||
void Gradient::editToggled () {
|
||||
if (edit->get_active()) {
|
||||
subscribe();
|
||||
}
|
||||
else
|
||||
unsubscribe();
|
||||
}
|
||||
|
||||
// TODO
|
||||
CursorShape Gradient::getCursor(int objectID) {
|
||||
return CSOpenHand;
|
||||
}
|
||||
|
||||
bool Gradient::mouseOver(int modifierKey) {
|
||||
EditDataProvider* editProvider = getEditProvider();
|
||||
if (editProvider && editProvider->object!=lastObject) {
|
||||
if (lastObject > -1)
|
||||
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
|
||||
if (editProvider->object > -1)
|
||||
EditSubscriber::visibleGeometry.at(editProvider->object)->state = Geometry::PRELIGHT;
|
||||
lastObject = editProvider->object;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Gradient::button1Pressed(int modifierKey) {
|
||||
if (!(modifierKey & (GDK_CONTROL_MASK | GDK_CONTROL_MASK))) {
|
||||
// button press is valid (no modifier key)
|
||||
PolarCoord pCoord;
|
||||
EditDataProvider *provider = getEditProvider();
|
||||
int imW, imH;
|
||||
provider->getImageSize(imW, imH);
|
||||
double halfSizeW = imW/2.;
|
||||
double halfSizeH = imH/2.;
|
||||
draggedCenter.set(int(halfSizeW+halfSizeW*(centerX->getValue()/100.)), int(halfSizeH+halfSizeH*(centerY->getValue()/100.)));
|
||||
|
||||
// trick to get the correct angle (clockwise/counter-clockwise)
|
||||
Coord p1 = draggedCenter;
|
||||
Coord p2 = provider->posImage;
|
||||
int p = p1.y;
|
||||
p1.y = p2.y;
|
||||
p2.y = p;
|
||||
|
||||
pCoord.setFromCartesian(p1, p2);
|
||||
draggedPointOldAngle = pCoord.angle;
|
||||
draggedPointAdjusterAngle = degree->getValue();
|
||||
//printf("\ndraggedPointOldAngle=%.3f\n\n", draggedPointOldAngle);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
// this will let this class ignore further drag events
|
||||
if (lastObject > -1) // should theoretically always be true
|
||||
EditSubscriber::visibleGeometry.at(lastObject)->state = Geometry::NORMAL;
|
||||
lastObject = -1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool Gradient::button1Released() {
|
||||
draggedPointOldAngle = -1000.;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Gradient::drag(int modifierKey) {
|
||||
// compute the polar coordinate of the mouse position
|
||||
EditDataProvider *provider = getEditProvider();
|
||||
int imW, imH;
|
||||
provider->getImageSize(imW, imH);
|
||||
double halfSizeW = imW/2.;
|
||||
double halfSizeH = imH/2.;
|
||||
|
||||
if (lastObject==0 || lastObject==1) {
|
||||
|
||||
// Dragging a line to change the angle
|
||||
PolarCoord draggedPoint;
|
||||
Coord currPos;
|
||||
currPos = provider->posImage+provider->deltaImage;
|
||||
Coord centerPos = draggedCenter;
|
||||
|
||||
// trick to get the correct angle (clockwise/counter-clockwise)
|
||||
int p = centerPos.y;
|
||||
centerPos.y = currPos.y;
|
||||
currPos.y = p;
|
||||
|
||||
draggedPoint.setFromCartesian(centerPos, currPos);
|
||||
double deltaAngle = draggedPoint.angle - draggedPointOldAngle;
|
||||
if (deltaAngle>180.) // crossing the boundary (0->360)
|
||||
deltaAngle -= 360.;
|
||||
else if (deltaAngle<-180.) // crossing the boundary (360->0)
|
||||
deltaAngle += 360.;
|
||||
draggedPointOldAngle = draggedPoint.angle;
|
||||
|
||||
draggedPointAdjusterAngle += deltaAngle;
|
||||
if (draggedPointAdjusterAngle > 180.)
|
||||
draggedPointAdjusterAngle = -360. + draggedPointAdjusterAngle;
|
||||
else if (draggedPointAdjusterAngle < -180.)
|
||||
draggedPointAdjusterAngle = 360. - draggedPointAdjusterAngle;
|
||||
//printf("draggedPointOldAngle: %.3f / From %d,%d to %d,%d -> angle = %.3f / ", draggedPointAdjusterAngle, centerPos.x, centerPos.y, currPos.x, currPos.y, draggedPoint.angle);
|
||||
//printf("currAngle: %.3f = degree: %.3f + deltaAngle: %.3f %s / draggedPointOldAngle: %.3f\n", draggedPointAdjusterAngle, degree->getValue(), deltaAngle, degree->getValue()>180.?">180":degree->getValue()<180.?"<180":"", draggedPointOldAngle);
|
||||
if (int(draggedPointAdjusterAngle) != degree->getIntValue()) {
|
||||
degree->setValue(draggedPointAdjusterAngle);
|
||||
updateGeometry (int(centerX->getValue()), int(centerY->getValue()), strength->getValue(), degree->getValue());
|
||||
if (listener)
|
||||
listener->panelChanged (EvGradientDegree, degree->getTextValue());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (lastObject==2) {
|
||||
// Dragging the circle to change the center
|
||||
Coord currPos;
|
||||
draggedCenter += provider->deltaPrevImage;
|
||||
currPos = draggedCenter;
|
||||
currPos.clip(imW, imH);
|
||||
int newCenterX = int((double(currPos.x)-halfSizeW)/halfSizeW*100.);
|
||||
int newCenterY = int((double(currPos.y)-halfSizeH)/halfSizeH*100.);
|
||||
if (newCenterX!=centerX->getIntValue() || newCenterY!=centerY->getIntValue()) {
|
||||
centerX->setValue(newCenterX);
|
||||
centerY->setValue(newCenterY);
|
||||
updateGeometry (newCenterX, newCenterY, strength->getValue(), degree->getValue());
|
||||
if (listener)
|
||||
listener->panelChanged (EvGradientCenter, Glib::ustring::compose ("X=%1\nY=%2", centerX->getTextValue(), centerY->getTextValue()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Gradient::switchOffEditMode () {
|
||||
if (edit->get_active()) {
|
||||
// switching off the toggle button
|
||||
bool wasBlocked = editConn.block(true);
|
||||
edit->set_active(false);
|
||||
if (!wasBlocked) editConn.block(false);
|
||||
}
|
||||
EditSubscriber::switchOffEditMode(); // disconnect
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user