Enhanced edit mechanism, with "element picking" possibility

This commit is contained in:
Hombre 2016-03-03 00:25:10 +01:00
parent 98dd99103d
commit 06c26ff1b3
11 changed files with 706 additions and 288 deletions

View File

@ -41,7 +41,7 @@ PolarCoord& PolarCoord::operator= (const Coord& other)
const double y = other.y;
radius = rtengine::norm2 (x, y);
angle = std::atan2 (x, y) * 180.0 / M_PI;
angle = std::atan2 (y, x) * 180.0 / M_PI;
return *this;
}

View File

@ -66,20 +66,19 @@ ZoomStep zoomSteps[] = {
#define ZOOM11INDEX 13
CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow)
: ObjectMOBuffer(parent), onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_),
backColor(options.bgcolor), decorated(true), titleHeight(30),
sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2),
xpos(30), ypos(30), imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent),
cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL), ipc(ipc_), isFlawnOver(false)
: ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false),
fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), cropLabel(Glib::ustring("100%")),
backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3),
upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0),
imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(NULL),
pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL), ipc(ipc_)
{
Glib::RefPtr<Pango::Context> context = parent->get_pango_context () ;
Pango::FontDescription fontd = context->get_font_description ();
fontd.set_weight (Pango::WEIGHT_BOLD);
fontd.set_size(8 * Pango::SCALE);
context->set_font_description (fontd);
cropLabel = "100%";
Glib::RefPtr<Pango::Layout> cllayout = parent->create_pango_layout("1000%");
exposeVersion = zoomVersion = 0;
int iw, ih;
cllayout->get_pixel_size (iw, ih);
@ -111,8 +110,6 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_,
cropHandler.setDisplayHandler(this);
cropHandler.newImage (ipc_, isDetailWindow);
state = SNormal;
}
void CropWindow::enable()
@ -272,109 +269,182 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
{
bool needRedraw = true; // most common case ; not redrawing are exceptions
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
iarea->grabFocus (this);
if (button == 1 && type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) {
if (fitZoomEnabled) {
if (fitZoom) {
state = SNormal;
zoomVersion = exposeVersion;
screenCoordToImage (x, y, action_x, action_y);
changeZoom (ZOOM11INDEX, true, action_x, action_y);
fitZoom = false;
if (button == 1) {
if (type == GDK_2BUTTON_PRESS && onArea (CropImage, x, y) && (state == SNormal || state == SCropImgMove)) {
if (fitZoomEnabled) {
if (fitZoom) {
state = SNormal;
zoomVersion = exposeVersion;
screenCoordToImage (x, y, action_x, action_y);
changeZoom (ZOOM11INDEX, true, action_x, action_y);
fitZoom = false;
} else {
zoomFit ();
}
} else {
zoomFit ();
zoom11 ();
}
} else {
zoom11 ();
}
state = SNormal;
}
else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropToolBar, x, y)) {
if (!decorated || !buttonSet.pressNotify (x, y)) {
state = SCropWinMove;
action_x = x;
action_y = y;
press_x = xpos;
press_y = ypos;
state = SNormal;
}
} else if (button == 1 && type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropResize, x, y)) {
state = SCropWinResize;
action_x = x;
action_y = y;
press_x = width;
press_y = height;
} else if (type == GDK_BUTTON_PRESS && state == SNormal && onArea (CropImage, x, y)) {
if (button == 1 && onArea (CropTopLeft, x, y)) {
state = SResizeTL;
press_x = x;
action_x = cropHandler.cropParams.x;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (button == 1 && onArea (CropTopRight, x, y)) {
state = SResizeTR;
press_x = x;
action_x = cropHandler.cropParams.w;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (button == 1 && onArea (CropBottomLeft, x, y)) {
state = SResizeBL;
press_x = x;
action_x = cropHandler.cropParams.x;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (button == 1 && onArea (CropBottomRight, x, y)) {
state = SResizeBR;
press_x = x;
action_x = cropHandler.cropParams.w;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (button == 1 && onArea (CropTop, x, y)) {
state = SResizeH1;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (button == 1 && onArea (CropBottom, x, y)) {
state = SResizeH2;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (button == 1 && onArea (CropLeft, x, y)) {
state = SResizeW1;
press_x = x;
action_x = cropHandler.cropParams.x;
} else if (button == 1 && onArea (CropRight, x, y)) {
state = SResizeW2;
press_x = x;
action_x = cropHandler.cropParams.w;
} else if (button == 1 && (bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) {
state = SCropMove;
press_x = x;
press_y = y;
action_x = cropHandler.cropParams.x;
action_y = cropHandler.cropParams.y;
} else if (iarea->getToolMode () == TMHand) {
else if (type == GDK_BUTTON_PRESS && state == SNormal) {
if (onArea (CropToolBar, x, y)) {
if (!decorated || !buttonSet.pressNotify (x, y)) {
state = SCropWinMove;
action_x = x;
action_y = y;
press_x = xpos;
press_y = ypos;
}
} else if (onArea (CropResize, x, y)) {
state = SCropWinResize;
action_x = x;
action_y = y;
press_x = width;
press_y = height;
} else {
if (onArea (CropImage, x, y)) { // events inside of the image domain
if (onArea (CropTopLeft, x, y)) {
state = SResizeTL;
press_x = x;
action_x = cropHandler.cropParams.x;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (onArea (CropTopRight, x, y)) {
state = SResizeTR;
press_x = x;
action_x = cropHandler.cropParams.w;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (onArea (CropBottomLeft, x, y)) {
state = SResizeBL;
press_x = x;
action_x = cropHandler.cropParams.x;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (onArea (CropBottomRight, x, y)) {
state = SResizeBR;
press_x = x;
action_x = cropHandler.cropParams.w;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (onArea (CropTop, x, y)) {
state = SResizeH1;
press_y = y;
action_y = cropHandler.cropParams.y;
} else if (onArea (CropBottom, x, y)) {
state = SResizeH2;
press_y = y;
action_y = cropHandler.cropParams.h;
} else if (onArea (CropLeft, x, y)) {
state = SResizeW1;
press_x = x;
action_x = cropHandler.cropParams.x;
} else if (onArea (CropRight, x, y)) {
state = SResizeW2;
press_x = x;
action_x = cropHandler.cropParams.w;
} else if ((bstate & GDK_SHIFT_MASK) && onArea (CropInside, x, y)) {
state = SCropMove;
press_x = x;
press_y = y;
action_x = cropHandler.cropParams.x;
action_y = cropHandler.cropParams.y;
} else if (onArea (CropObserved, x, y)) {
state = SObservedMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
} else if (iarea->getToolMode () == TMStraighten) {
state = SRotateSelecting;
press_x = x;
press_y = y;
action_x = x;
action_y = y;
rot_deg = 0;
} else if (iarea->getToolMode () == TMSpotWB) {
int spotx, spoty;
screenCoordToImage (x, y, spotx, spoty);
iarea->spotWBSelected (spotx, spoty);
} else if (iarea->getToolMode () == TMCropSelect && cropgl) {
state = SCropSelecting;
screenCoordToImage (x, y, press_x, press_y);
cropHandler.cropParams.enabled = true;
cropHandler.cropParams.x = press_x;
cropHandler.cropParams.y = press_y;
cropHandler.cropParams.w = cropHandler.cropParams.h = 1;
cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h);
} else if (iarea->getToolMode () == TMHand) {
if (editSubscriber) {
needRedraw = editSubscriber->button1Pressed(bstate);
if ((cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK))) || editSubscriber->getEditingType() == ET_OBJECTS) {
if (editSubscriber->isDragging()) {
state = SEditDrag1;
} else if (editSubscriber->isPicking()) {
state = SEditPick1;
pickedObject = iarea->object;
pickModifierKey = bstate;
}
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
}
if (state != SEditDrag1) {
state = SCropImgMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
} else { // if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible
state = SCropImgMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
} else if (iarea->getToolMode () == TMHand) { // events outside of the image domain
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
needRedraw = editSubscriber->button1Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag1;
} else if (editSubscriber->isPicking()) {
state = SEditPick1;
pickedObject = iarea->object;
pickModifierKey = bstate;
}
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
}
}
}
} else if (button == 2) {
if (iarea->getToolMode () == TMHand) {
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
if (button == 1) {
needRedraw = editSubscriber->button1Pressed(bstate);
needRedraw = editSubscriber->button2Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag1;
}
} else if (button == 2) {
needRedraw = editSubscriber->button2Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag2;
}
} else if (button == 3) {
needRedraw = editSubscriber->button3Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag3;
}
if (editSubscriber->isDragging()) {
state = SEditDrag2;
} else if (editSubscriber->isPicking()) {
state = SEditPick2;
pickedObject = iarea->object;
pickModifierKey = bstate;
}
press_x = x;
@ -382,100 +452,26 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y)
action_x = 0;
action_y = 0;
}
if (state != SEditDrag1 && state != SEditDrag2 && state != SEditDrag3) {
if (button == 1 && onArea (CropObserved, x, y)) {
state = SObservedMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
} else if (button == 1 && editSubscriber && cropgl && cropgl->inImageArea(iarea->posImage.x, iarea->posImage.y) && (editSubscriber->getEditingType() == ET_PIPETTE && (bstate & GDK_CONTROL_MASK)) ) {
editSubscriber->button1Pressed(bstate);
state = SEditDrag1;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
} else if (button == 1) { // if(zoomSteps[cropZoom].zoom > cropHandler.getFitZoom()) { // only allow move when image is only partial visible
state = SCropImgMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
}
} else if (button == 1 && onArea (CropObserved, x, y)) {
state = SObservedMove;
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
} else if (button == 1 && iarea->getToolMode () == TMStraighten) {
state = SRotateSelecting;
press_x = x;
press_y = y;
action_x = x;
action_y = y;
rot_deg = 0;
} else if (button == 1 && iarea->getToolMode () == TMSpotWB) {
int spotx, spoty;
screenCoordToImage (x, y, spotx, spoty);
iarea->spotWBSelected (spotx, spoty);
} else if (button == 1 && iarea->getToolMode () == TMCropSelect && cropgl) {
state = SCropSelecting;
screenCoordToImage (x, y, press_x, press_y);
cropHandler.cropParams.enabled = true;
cropHandler.cropParams.x = press_x;
cropHandler.cropParams.y = press_y;
cropHandler.cropParams.w = cropHandler.cropParams.h = 1;
cropgl->cropInit (cropHandler.cropParams.x, cropHandler.cropParams.y, cropHandler.cropParams.w, cropHandler.cropParams.h);
}
} else if (type == GDK_BUTTON_PRESS && state == SNormal && iarea->getToolMode () == TMHand) {
// Any other case... i.e. we're assuming to be on the canvas, looking for editing objects
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
if (button == 1) {
needRedraw = editSubscriber->button1Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag1;
}
} else if (button == 2) {
needRedraw = editSubscriber->button2Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag2;
}
} else if (button == 3) {
} else if (button == 3) {
if (iarea->getToolMode () == TMHand) {
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_OBJECTS) {
needRedraw = editSubscriber->button3Pressed(bstate);
if (editSubscriber->isDragging()) {
state = SEditDrag3;
} else if (editSubscriber->isPicking()) {
state = SEditPick3;
pickedObject = iarea->object;
pickModifierKey = bstate;
}
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
press_x = x;
press_y = y;
action_x = 0;
action_y = 0;
}
}
if (button == 3) {
iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f;
EditSubscriber *editSubscriber = iarea->getCurrSubscriber();
if (editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE) {
editSubscriber->mouseOver(0);
}
state = SNormal;
iarea->setToolHand ();
if (pmhlistener) {
pmhlistener->toggleFreeze();
}
}
@ -529,7 +525,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
state = SNormal;
needRedraw = true;
} else if (state == SEditDrag1 || state == SEditDrag2 || state == SEditDrag3) {
if (state == SEditDrag1) {
if (state == SEditDrag1) {
needRedraw = editSubscriber->button1Released();
} else if (state == SEditDrag2) {
needRedraw = editSubscriber->button2Released();
@ -562,12 +558,7 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
}
} else if (editSubscriber->getEditingType() == ET_OBJECTS) {
screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y);
if (onArea (CropImage, x, y)) {
iarea->object = ObjectMOBuffer::getObjectID(cropPos);
} else {
iarea->object = -1;
}
iarea->object = ObjectMOBuffer::getObjectID(cropPos);
}
needRedraw |= editSubscriber->mouseOver(bstate);
@ -579,7 +570,38 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
iarea->deltaScreen.set(0, 0);
iarea->deltaPrevImage.set(0, 0);
iarea->deltaPrevScreen.set(0, 0);
state = SNormal;
} else if (state == SEditPick1 || state == SEditPick2 || state == SEditPick3) {
if (editSubscriber) {
Coord imgPos;
action_x = x;
action_y = y;
screenCoordToImage (x, y, imgPos.x, imgPos.y);
iarea->posImage.set (imgPos.x, imgPos.y);
iarea->posScreen.set (x, y);
Coord cropPos;
screenCoordToCropCanvas (x, y, cropPos.x, cropPos.y);
iarea->object = ObjectMOBuffer::getObjectID(cropPos);
bool elemPicked = iarea->object == pickedObject && bstate == pickModifierKey;
if (state == SEditPick1) {
needRedraw = editSubscriber->pick1 (elemPicked);
} else if (state == SEditPick2) {
needRedraw = editSubscriber->pick2 (elemPicked);
} else if (state == SEditPick3) {
needRedraw = editSubscriber->pick3 (elemPicked);
}
iarea->object = pickedObject = -1;
pickModifierKey = 0;
needRedraw |= editSubscriber->mouseOver (bstate);
} else {
iarea->object = 0;
}
}
if (cropgl && (state == SCropSelecting || state == SResizeH1 || state == SResizeH2 || state == SResizeW1 || state == SResizeW2 || state == SResizeTL || state == SResizeTR || state == SResizeBL || state == SResizeBR || state == SCropMove)) {
@ -598,6 +620,20 @@ void CropWindow::buttonRelease (int button, int num, int bstate, int x, int y)
return;
}
if (state != SEditDrag3 && state != SEditPick3 && button == 3 && !(bstate & (GDK_SHIFT_MASK|GDK_CONTROL_MASK))) {
iarea->pipetteVal[0] = iarea->pipetteVal[1] = iarea->pipetteVal[2] = -1.f;
if (editSubscriber && editSubscriber->getEditingType() == ET_PIPETTE) {
editSubscriber->mouseOver(0);
}
iarea->setToolHand ();
if (pmhlistener) {
pmhlistener->toggleFreeze();
}
}
state = SNormal;
iarea->grabFocus (NULL);
@ -743,7 +779,7 @@ void CropWindow::pointerMoved (int bstate, int x, int y)
} else if (editSubscriber) {
rtengine::Crop* crop = static_cast<rtengine::Crop*>(cropHandler.getCrop());
if (state == SNormal) {
if (state == SNormal || state == SEditPick1 || state == SEditPick2 || state == SEditPick3) {
Coord imgPos;
action_x = x;
action_y = y;

View File

@ -47,9 +47,11 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed
{
// state management
ImgEditState state; // current state of user (see enum State)
ImgEditState state; // current state of user (see enum State)
int press_x, press_y; // position of the cursor in the GUI space on button press
int action_x, action_y; // parameter that will evolve during a pan or drag action
int pickedObject;
int pickModifierKey;
double rot_deg;
bool onResizeArea;
bool deleted;

View File

@ -392,7 +392,7 @@ void CurveEditor::switchOffEditMode ()
EditSubscriber::switchOffEditMode(); // disconnect
}
bool CurveEditor::mouseOver(int modifierKey)
bool CurveEditor::mouseOver(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
subGroup->pipetteMouseOver(provider, modifierKey);
@ -400,7 +400,7 @@ bool CurveEditor::mouseOver(int modifierKey)
return true; // return true will ask the preview to be redrawn, for the cursor
}
bool CurveEditor::button1Pressed(int modifierKey)
bool CurveEditor::button1Pressed(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
@ -422,7 +422,7 @@ bool CurveEditor::button1Released()
return true;
}
bool CurveEditor::drag1(int modifierKey)
bool CurveEditor::drag1(const int modifierKey)
{
EditDataProvider* provider = getEditProvider();
subGroup->pipetteDrag(provider, modifierKey);
@ -430,7 +430,7 @@ bool CurveEditor::drag1(int modifierKey)
return false;
}
CursorShape CurveEditor::getCursor(int objectID)
CursorShape CurveEditor::getCursor(const int objectID)
{
if (remoteDrag) {
return CSResizeHeight;

View File

@ -127,11 +127,11 @@ public:
sigc::signal<void> signal_curvepoint_release();
void switchOffEditMode ();
bool mouseOver(int modifierKey);
bool button1Pressed(int modifierKey);
bool mouseOver(const int modifierKey);
bool button1Pressed(const int modifierKey);
bool button1Released();
bool drag1(int modifierKey);
CursorShape getCursor(int objectID);
bool drag1(const int modifierKey);
CursorShape getCursor(const int objectID);
};

View File

@ -747,7 +747,294 @@ void Rectangle::drawToMOChannel(Cairo::RefPtr<Cairo::Context> &cr, unsigned shor
}
}
EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL), dragging(false) {}
void OPIcon::drivenPointToRectangle(rtengine::Coord &pos,
rtengine::Coord &topLeft, rtengine::Coord &bottomRight, int W, int H)
{
switch (drivenPoint) {
case (DP_CENTERCENTER):
topLeft.x = pos.x - W / 2;
topLeft.y = pos.y - H / 2;
break;
case (DP_TOPLEFT):
topLeft.x = pos.x;
topLeft.y = pos.y;
break;
case (DP_TOPCENTER):
topLeft.x = pos.x - W / 2;
topLeft.y = pos.y;
break;
case (DP_TOPRIGHT):
topLeft.x = pos.x - W;
topLeft.y = pos.y;
break;
case (DP_CENTERRIGHT):
topLeft.x = pos.x - W;
topLeft.y = pos.y - H / 2;
break;
case (DP_BOTTOMRIGHT):
topLeft.x = pos.x - W;
topLeft.y = pos.y - H;
break;
case (DP_BOTTOMCENTER):
topLeft.x = pos.x - W / 2;
topLeft.y = pos.y - H;
break;
case (DP_BOTTOMLEFT):
topLeft.x = pos.x;
topLeft.y = pos.y - H;
break;
case (DP_CENTERLEFT):
topLeft.x = pos.x;
topLeft.y = pos.y - H / 2;
break;
}
bottomRight.x = topLeft.x + W - 1;
bottomRight.y = topLeft.y + H - 1;
}
OPIcon::OPIcon(Cairo::RefPtr<Cairo::ImageSurface> *normal,
Cairo::RefPtr<Cairo::ImageSurface> *active,
Cairo::RefPtr<Cairo::ImageSurface> *prelight,
Cairo::RefPtr<Cairo::ImageSurface> *dragged,
Cairo::RefPtr<Cairo::ImageSurface> *insensitive,
enum DrivenPoint drivenPoint) :
drivenPoint(drivenPoint)
{
if (normal) {
normalImg = *normal;
}
if (prelight) {
prelightImg = *prelight;
}
if (active) {
activeImg = *active;
}
if (dragged) {
draggedImg = *active;
}
if (insensitive) {
insensitiveImg = *insensitive;
}
}
OPIcon::OPIcon(Glib::ustring normalImage, Glib::ustring activeImage, Glib::ustring prelightImage,
Glib::ustring draggedImage, Glib::ustring insensitiveImage, enum DrivenPoint drivenPoint) : drivenPoint(drivenPoint)
{
if (!normalImage.empty()) {
normalImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(normalImage) );
}
if (!prelightImage.empty()) {
prelightImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(prelightImage) );
}
if (!activeImage.empty()) {
activeImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(activeImage) );
}
if (!draggedImage.empty()) {
draggedImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(draggedImage) );
}
if (!insensitiveImage.empty()) {
insensitiveImg = Cairo::ImageSurface::create_from_png( RTImage::findIconAbsolutePath(insensitiveImage) );
}
}
Cairo::RefPtr<Cairo::ImageSurface> OPIcon::getNormalImg()
{
return normalImg;
}
Cairo::RefPtr<Cairo::ImageSurface> OPIcon::getPrelightImg()
{
return prelightImg;
}
Cairo::RefPtr<Cairo::ImageSurface> OPIcon::getActiveImg()
{
return activeImg;
}
Cairo::RefPtr<Cairo::ImageSurface> OPIcon::getDraggedImg()
{
return draggedImg;
}
Cairo::RefPtr<Cairo::ImageSurface> OPIcon::getInsensitiveImg()
{
return insensitiveImg;
}
void OPIcon::drawImage(Cairo::RefPtr<Cairo::ImageSurface> img,
Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer,
EditCoordSystem &coordSystem)
{
int imgW = img->get_width();
int imgH = img->get_height();
rtengine::Coord pos;
if (datum == IMAGE) {
coordSystem.imageCoordToScreen(position.x, position.y, pos.x, pos.y);
} else if (datum == CLICKED_POINT) {
pos = position + objectBuffer->getDataProvider()->posScreen;
} else if (datum == CURSOR)
pos = position + objectBuffer->getDataProvider()->posScreen
+ objectBuffer->getDataProvider()->deltaScreen;
rtengine::Coord tl, br; // Coordinate of the rectangle in the CropBuffer coordinate system
drivenPointToRectangle(pos, tl, br, imgW, imgH);
cr->set_source(img, tl.x, tl.y);
cr->set_line_width(0.);
cr->rectangle(tl.x, tl.y, imgW, imgH);
cr->fill();
}
void OPIcon::drawMOImage(Cairo::RefPtr<Cairo::ImageSurface> img, Cairo::RefPtr<Cairo::Context> &cr,
unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
// test of F_HOVERABLE has already been done
int imgW = img->get_width();
int imgH = img->get_height();
rtengine::Coord pos;
if (datum == IMAGE)
coordSystem.imageCoordToCropCanvas (position.x, position.y, pos.x, pos.y);
else if (datum == CLICKED_POINT) {
pos = position + objectBuffer->getDataProvider()->posScreen;
} else if (datum == CURSOR)
pos = position + objectBuffer->getDataProvider()->posScreen
+ objectBuffer->getDataProvider()->deltaScreen;
rtengine::Coord tl, br; // Coordinate of the rectangle in the CropBuffer coordinate system
drivenPointToRectangle(pos, tl, br, imgW, imgH);
// drawing the lower byte's value
if (objectBuffer->getObjectMode() == OM_255) {
cr->set_source_rgba (0., 0., 0., ((id + 1) & 0xFF) / 255.);
} else {
cr->set_source_rgba (0., 0., 0., (id + 1) / 65535.);
}
cr->set_line_width(0.);
cr->rectangle(tl.x, tl.y, imgW, imgH);
cr->fill();
}
void OPIcon::drawOuterGeometry(Cairo::RefPtr<Cairo::Context> &cr,
ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) {}
void OPIcon::drawInnerGeometry(Cairo::RefPtr<Cairo::Context> &cr,
ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
if (flags & F_VISIBLE) {
// Here we will handle fallback solutions
State tmpState = state;
if (tmpState == INSENSITIVE) {
if (!insensitiveImg) {
tmpState = NORMAL;
} else {
OPIcon::drawImage(insensitiveImg, cr, objectBuffer, coordSystem);
return;
}
}
if (tmpState == DRAGGED) {
if (!draggedImg) {
tmpState = ACTIVE;
} else {
OPIcon::drawImage(draggedImg, cr, objectBuffer, coordSystem);
return;
}
}
if (tmpState == ACTIVE) {
if (!activeImg) {
tmpState = PRELIGHT;
} else {
OPIcon::drawImage(activeImg, cr, objectBuffer, coordSystem);
return;
}
}
if (tmpState == PRELIGHT) {
if (!prelightImg) {
tmpState = NORMAL;
} else {
OPIcon::drawImage(prelightImg, cr, objectBuffer, coordSystem);
return;
}
}
if (tmpState == NORMAL && normalImg) {
OPIcon::drawImage(normalImg, cr, objectBuffer, coordSystem);
}
}
}
void OPIcon::drawToMOChannel(Cairo::RefPtr<Cairo::Context> &cr, unsigned short id,
ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem)
{
if (flags & F_HOVERABLE) {
// Here we will handle fallback solutions
State tmpState = state;
if (tmpState == INSENSITIVE) {
if (!insensitiveImg) {
tmpState = NORMAL;
} else {
OPIcon::drawMOImage(insensitiveImg, cr, id, objectBuffer, coordSystem);
return;
}
}
if (tmpState == DRAGGED) {
if (!draggedImg) {
tmpState = ACTIVE;
} else {
OPIcon::drawMOImage(draggedImg, cr, id, objectBuffer, coordSystem);
return;
}
}
if (tmpState == ACTIVE) {
if (!activeImg) {
tmpState = PRELIGHT;
} else {
OPIcon::drawMOImage(activeImg, cr, id, objectBuffer, coordSystem);
return;
}
}
if (tmpState == PRELIGHT) {
if (!prelightImg) {
tmpState = NORMAL;
} else {
OPIcon::drawMOImage(prelightImg, cr, id, objectBuffer, coordSystem);
return;
}
}
if (tmpState == NORMAL && normalImg) {
OPIcon::drawMOImage(normalImg, cr, id, objectBuffer, coordSystem);
}
}
}
EditSubscriber::EditSubscriber (EditType editType) : ID(EUID_None), editingType(editType), bufferType(BT_SINGLEPLANE_FLOAT), provider(NULL), action(ES_ACTION_NONE) {}
void EditSubscriber::setEditProvider(EditDataProvider *provider)
{
@ -791,24 +1078,29 @@ void EditSubscriber::switchOffEditMode()
unsubscribe();
}
EditUniqueID EditSubscriber::getEditID()
const EditUniqueID EditSubscriber::getEditID()
{
return ID;
}
EditType EditSubscriber::getEditingType()
const EditType EditSubscriber::getEditingType()
{
return editingType;
}
BufferType EditSubscriber::getPipetteBufferType()
const BufferType EditSubscriber::getPipetteBufferType()
{
return bufferType;
}
bool EditSubscriber::isDragging()
const bool EditSubscriber::isDragging()
{
return dragging;
return action == ES_ACTION_DRAGGING;
}
const bool EditSubscriber::isPicking()
{
return action == ES_ACTION_PICKING;
}
//--------------------------------------------------------------------------------------------------

View File

@ -63,10 +63,10 @@ class EditSubscriber;
* ### Event handling
*
* The mouseOver method is called on each mouse movement, excepted when dragging a point. This method can then access
* the pipetteVal array values, which contain the mean of the pixel read in the buffer, or -1 of the cursor is outside
* the pipetteVal array values, which contain the mean of the pixel read in the buffer, or -1 if the cursor is outside
* of the image. In this case, EditDataProvider::object is also set to 0 (and 1 if over the image).
*
* When the user will click on the left mouse button while pressing the CTRL key, the button1Pressed will be called.
* When the user will click on the left mouse button while pressing the CTRL key, button1Pressed will be called.
* Setting "dragging" to true (or false) is not required for the pipette type editing.
*
* The drag1 method will be called on all subsequent mouse move. The pipetteVal[3] array will already be filled with
@ -79,7 +79,7 @@ class EditSubscriber;
*
* By using this class, objects can be drawn and manipulated on the preview.
*
* The developer has to handle the buttonPress, buttonRelease, drag and mouseOver method that he needs. There
* The developer has to handle the buttonPress, buttonRelease, drag and mouseOver methods that he needs. There
* are buttonPress, buttonRelease and drag methods dedicated to each mouse button, for better flexibility
* (e.g.button2Press, button2Release, drag2 will handle event when mouse button 2 is used first). RT actually
* does not handle multiple mouse button event (e.g. button1 + button2), only one at a time. The first button pressed
@ -93,10 +93,11 @@ class EditSubscriber;
* specific values. To be displayed, the F_VISIBLE flag has to be set through the setActive or setVisible methods.
*
* The second list (mouseOverGeometry) is used in a backbuffer, the color used to draw the shape being the id of the
* mouseOverGeometry. As an example, you could use a circle line to represent the line to the user, but use another
* Circle object, filled, to be used as mouseOver detection. The association between both shape (visible and mouseOver)
* mouseOverGeometry. As an example, you could create a line to be shown in the preview, but create 2 filled Circle object
* to be used as mouseOver detection, one on each end of the line. The association between both shape (visible and mouseOver)
* is handled by the developer. To be displayed on this backbuffer, the F_HOVERABLE flag has to be set through the
* setActive or setHoverable methods.
* setActive or setHoverable methods. For overlapping mouse over geometry, the priority is set by the order in the list :
* the last item is detected first (think of it like a stack piled up).
*
*
* ### Event handling
@ -106,17 +107,28 @@ class EditSubscriber;
*
* RT will call the mouseOver method on each mouse movement where no mouse button is pressed.
*
* On mouse button press over a mouseOverGeometry, it will call the button press method corresponding to the button
* (e.g. button1Pressed for mouse button 1), with the modifier key as parameter. Any other mouse button pressed at
* the same time will be ignored. It's up to the developer to decide whether it leads to a drag movement or not,
* by setting the "dragging" boolean to true.
* On mouse button press over a mouseOverGeometry (that has F_HOVERABLE set), it will call the button press method corresponding
* to the button (e.g. button1Pressed for mouse button 1), with the modifier key as parameter. Any other mouse button pressed at
* the same time will be ignored. It's up to the developer to decide whether this action is starting a 'drag' or 'pick' action,
* by setting the 'action' parameter to the appropriated value.
*
* In this case, RT will then sent drag1 event (to stay with our button 1 pressed example) on each mouse movement. It's up
* to the developer of the tool to handle the dragging. The EditProvider class will help you in this by handling the actual
* position in various coordinate system and ways.
* If the user sets action to ES_ACTION_DRAGGING, RT will then send drag1 events (to stay with our button 1 pressed example) on each
* mouse movement. It's up to the developer of the tool to handle the dragging. The EditProvider class will help you in this by
* handling the actual position in various coordinate system and ways.
*
* When the user will release the mouse button, RT will call the button1Release event (in our example). The developer have
* then to set the "dragging" flag to false.
* then to set action to ES_ACTION_NONE.
*
* If the user sets action to ES_ACTION_PICKING, RT will keep in memory the mouseOver object that was selected when pressing the mouse
* (e.g. button 1), as well as the modifier keys.
*
* The element is said to be picked when the mouse button is released over the same mouse over object and with the same active
* modifier keys. In this case, the corresponding picked event (e.g. picked1 in our example) and the 'picked' flag will be true.
* If any of those condition is false, picked1 will still be be called to terminate the initiated picking action, but 'picked'
* will be false. This is necessary because the user may want to update the geometry if the picking is aborted. The developer have
* then to set action to ES_ACTION_NONE.
*
* Picking an on-screen element correspond to single-clicking on it. No double click is supported so far.
*
* Each of these methods have to returns a boolean value saying that the preview has to be refreshed or not (i.e. the displayed
* geometry).
@ -134,11 +146,9 @@ class EditSubscriber;
* the HSV tool, the Hue and Saturation and Value curves are applied on the current state of the image. That's why the pipette
* of the H, S and V curve will share the same data of this "current state", otherwise the read value would be wrong.
*
* When the mouse button 1 is pressed while pressing the CTRL key, the button1Pressed method will be called.
*
* When the Edit process stops, the Subscriber is removed from the DataProvider, so buffers can be freed up.
* A new ToolPanelListener::panelChanged event is also thrown to update the preview again, without the tool's
* graphical objects. The Edit button is also toggled off (by the user or programmatically).
* graphical objects. The Edit button is also toggled off (by the user or programatically).
*
* It means that each Edit buttons toggled on will start an update of the preview which might or might not create
* a new History entry, depending on the ProcEvent used.
@ -315,12 +325,13 @@ public:
bool isHoverable ();
void setHoverable (bool visible);
// setActive will enable/disable the visible and hoverable flags in one shot!
void setActive (bool active);
virtual void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *parent, EditCoordSystem &coordSystem) = 0;
virtual void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *parent, EditCoordSystem &coordSystem) = 0;
virtual void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem) = 0;
virtual void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0;
virtual void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0;
virtual void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem) = 0;
};
class Circle : public Geometry
@ -335,9 +346,9 @@ public:
Circle (rtengine::Coord& center, int radius, bool filled = false, bool radiusInImageSpace = false);
Circle (int centerX, int centerY, int radius, bool filled = false, bool radiusInImageSpace = false);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
};
class Line : public Geometry
@ -350,9 +361,9 @@ public:
Line (rtengine::Coord& begin, rtengine::Coord& end);
Line (int beginX, int beginY, int endX, int endY);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
};
class Polyline : public Geometry
@ -363,9 +374,9 @@ public:
Polyline ();
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
};
class Rectangle : public Geometry
@ -381,9 +392,49 @@ public:
void setXYXY(int left, int top, int right, int bottom);
void setXYWH(rtengine::Coord topLeft, rtengine::Coord widthHeight);
void setXYXY(rtengine::Coord topLeft, rtengine::Coord bottomRight);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *pipetteBuffer, EditCoordSystem &coordSystem);
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
};
class OPIcon : public Geometry // OP stands for "On Preview"
{
protected:
Cairo::RefPtr<Cairo::ImageSurface> normalImg;
Cairo::RefPtr<Cairo::ImageSurface> prelightImg;
Cairo::RefPtr<Cairo::ImageSurface> activeImg;
Cairo::RefPtr<Cairo::ImageSurface> draggedImg;
Cairo::RefPtr<Cairo::ImageSurface> insensitiveImg;
static void setPaths(Options &opt);
static void updateImages();
void changeImage(Glib::ustring &newImage);
static Glib::ustring findIconAbsolutePath(const Glib::ustring &iconFName);
void drawImage (Cairo::RefPtr<Cairo::ImageSurface> img, Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawMOImage (Cairo::RefPtr<Cairo::ImageSurface> img, Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drivenPointToRectangle(rtengine::Coord &pos, rtengine::Coord &topLeft, rtengine::Coord &bottomRight, int W, int H);
public:
enum DrivenPoint drivenPoint;
rtengine::Coord position;
OPIcon (Cairo::RefPtr<Cairo::ImageSurface> *normal, Cairo::RefPtr<Cairo::ImageSurface> *active, Cairo::RefPtr<Cairo::ImageSurface> *prelight = NULL, Cairo::RefPtr<Cairo::ImageSurface> *dragged = NULL, Cairo::RefPtr<Cairo::ImageSurface> *insensitive = NULL,
enum DrivenPoint drivenPoint = DP_CENTERCENTER);
OPIcon (Glib::ustring normalImage, Glib::ustring activeImage, Glib::ustring prelightImage = "", Glib::ustring draggedImage = "", Glib::ustring insensitiveImage = "", enum DrivenPoint drivenPoint = DP_CENTERCENTER);
Cairo::RefPtr<Cairo::ImageSurface> getNormalImg();
Cairo::RefPtr<Cairo::ImageSurface> getPrelightImg();
Cairo::RefPtr<Cairo::ImageSurface> getActiveImg();
Cairo::RefPtr<Cairo::ImageSurface> getDraggedImg();
Cairo::RefPtr<Cairo::ImageSurface> getInsensitiveImg();
void drawOuterGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawInnerGeometry (Cairo::RefPtr<Cairo::Context> &cr, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
void drawToMOChannel (Cairo::RefPtr<Cairo::Context> &cr, unsigned short id, ObjectMOBuffer *objectBuffer, EditCoordSystem &coordSystem);
};
class OPAdjuster : public Geometry // OP stands for "On Preview"
{
};
/// @brief Method for client tools needing Edit information
@ -401,7 +452,11 @@ private:
protected:
std::vector<Geometry*> visibleGeometry; /// displayed geometry
std::vector<Geometry*> mouseOverGeometry; /// mouseOver geometry, drawn in a hidden buffer
bool dragging; /// in object mode, set this to true in buttonPressed events to start dragging and ask for drag event (ignored in pipette mode)
enum {
ES_ACTION_NONE, ///
ES_ACTION_DRAGGING, /// set action to this value in the buttonPressed event to start dragging and ask for drag event
ES_ACTION_PICKING /// set action to this value in the buttonPressed event whenever the user is picking something through a single click. In this case, the pickX events will be called INSTEAD of buttonXReleased !
} action; /// object mode only, ignored in Pipette mode
public:
EditSubscriber (EditType editType);
@ -409,31 +464,32 @@ public:
void setEditProvider(EditDataProvider *provider);
EditDataProvider* getEditProvider ();
void setEditID(EditUniqueID ID, BufferType buffType);
bool isCurrentSubscriber();
virtual void subscribe();
virtual void unsubscribe();
virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode
EditUniqueID getEditID();
EditType getEditingType();
BufferType getPipetteBufferType();
bool isDragging(); /// Returns true if something is being dragged and drag events has to be sent (object mode only)
void setEditID(EditUniqueID ID, BufferType buffType);
bool isCurrentSubscriber();
virtual void subscribe();
virtual void unsubscribe();
virtual void switchOffEditMode (); /// Occurs when the user want to stop the editing mode
const EditUniqueID getEditID();
const EditType getEditingType();
const BufferType getPipetteBufferType();
const bool isDragging(); /// Returns true if something is being dragged and drag events has to be sent (object mode only)
const bool isPicking(); /// Returns true if something is being picked
/** @brief Get the cursor to be displayed when above handles
@param objectID object currently "hovered" */
virtual CursorShape getCursor (int objectID);
virtual CursorShape getCursor (const int objectID);
/** @brief Triggered when the mouse is moving over an object
This method is also triggered when the cursor is moving over the image in ET_PIPETTE mode
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool mouseOver (int modifierKey);
virtual bool mouseOver (const int modifierKey);
/** @brief Triggered when mouse button 1 is pressed, together with the CTRL modifier key if the subscriber is of type ET_PIPETTE
Once the key is pressed, RT will enter in drag1 mode on subsequent mouse movements
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool button1Pressed (int modifierKey);
virtual bool button1Pressed (const int modifierKey);
/** @brief Triggered when mouse button 1 is released
@return true if the preview has to be redrawn, false otherwise */
@ -443,7 +499,7 @@ public:
Once the key is pressed, RT will enter in drag2 mode on subsequent mouse movements
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool button2Pressed (int modifierKey);
virtual bool button2Pressed (const int modifierKey);
/** @brief Triggered when mouse button 2 is released (middle button)
@return true if the preview has to be redrawn, false otherwise */
@ -453,7 +509,7 @@ public:
Once the key is pressed, RT will enter in drag3 mode on subsequent mouse movements
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool button3Pressed (int modifierKey);
virtual bool button3Pressed (const int modifierKey);
/** @brief Triggered when mouse button 3 is released (right button)
@return true if the preview has to be redrawn, false otherwise */
@ -462,17 +518,36 @@ public:
/** @brief Triggered when the user is moving while holding down mouse button 1
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool drag1 (int modifierKey);
virtual bool drag1 (const int modifierKey);
/** @brief Triggered when the user is moving while holding down mouse button 2
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool drag2 (int modifierKey);
virtual bool drag2 (const int modifierKey);
/** @brief Triggered when the user is moving while holding down mouse button 3
@param modifierKey Gtk's event modifier key (GDK_CONTROL_MASK | GDK_SHIFT_MASK | ...)
@return true if the preview has to be redrawn, false otherwise */
virtual bool drag3 (int modifierKey);
virtual bool drag3 (const int modifierKey);
/** @brief Triggered when the user is releasing mouse button 1 while in action==ES_ACTION_PICKING mode
No modifier key is provided, since having a different modifier key than on button press will set picked to false.
@param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
@return true if the preview has to be redrawn, false otherwise */
virtual bool pick1 (const bool picked);
/** @brief Triggered when the user is releasing mouse button 2 while in action==ES_ACTION_PICKING mode
@param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
@return true if the preview has to be redrawn, false otherwise */
virtual bool pick2 (const bool picked);
/** @brief Triggered when the user is releasing mouse button 3 while in action==ES_ACTION_PICKING mode
@param picked True if the cursor is still above the the same object than on button pressed and with the same modifier keys.
If false, the user moved the cursor away or the modifier key is different, so the element is considered as NOT selected.
@return true if the preview has to be redrawn, false otherwise */
virtual bool pick3 (const bool picked);
/** @brief Get the geometry to be shown to the user */
const std::vector<Geometry*>& getVisibleGeometry ();
@ -617,8 +692,8 @@ inline bool Geometry::isHoverable () {
return flags & F_HOVERABLE;
}
inline void Geometry::setHoverable (bool visible) {
if (visible) {
inline void Geometry::setHoverable (bool hoverable) {
if (hoverable) {
flags |= F_HOVERABLE;
} else {
flags &= ~F_HOVERABLE;
@ -637,15 +712,15 @@ inline EditDataProvider* EditSubscriber::getEditProvider () {
return provider;
}
inline CursorShape EditSubscriber::getCursor (int objectID) {
inline CursorShape EditSubscriber::getCursor (const int objectID) {
return CSOpenHand;
}
inline bool EditSubscriber::mouseOver (int modifierKey) {
inline bool EditSubscriber::mouseOver (const int modifierKey) {
return false;
}
inline bool EditSubscriber::button1Pressed (int modifierKey) {
inline bool EditSubscriber::button1Pressed (const int modifierKey) {
return false;
}
@ -653,7 +728,7 @@ inline bool EditSubscriber::button1Released () {
return false;
}
inline bool EditSubscriber::button2Pressed (int modifierKey) {
inline bool EditSubscriber::button2Pressed (const int modifierKey) {
return false;
}
@ -661,7 +736,7 @@ inline bool EditSubscriber::button2Released () {
return false;
}
inline bool EditSubscriber::button3Pressed (int modifierKey) {
inline bool EditSubscriber::button3Pressed (const int modifierKey) {
return false;
}
@ -669,15 +744,27 @@ inline bool EditSubscriber::button3Released () {
return false;
}
inline bool EditSubscriber::drag1 (int modifierKey) {
inline bool EditSubscriber::drag1 (const int modifierKey) {
return false;
}
inline bool EditSubscriber::drag2 (int modifierKey) {
inline bool EditSubscriber::drag2 (const int modifierKey) {
return false;
}
inline bool EditSubscriber::drag3 (int modifierKey) {
inline bool EditSubscriber::drag3 (const int modifierKey) {
return false;
}
inline bool EditSubscriber::pick1 (const bool picked) {
return false;
}
inline bool EditSubscriber::pick2 (const bool picked) {
return false;
}
inline bool EditSubscriber::pick3 (const bool picked) {
return false;
}

View File

@ -20,7 +20,8 @@
#define _EDITENUMS_
enum ImgEditState {SNormal, SCropMove, SHandMove, SResizeW1, SResizeW2, SResizeH1, SResizeH2, SResizeTL, SResizeTR, SResizeBL, SResizeBR,
SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove, SEditDrag1, SEditDrag2, SEditDrag3
SCropSelecting, SRotateSelecting, SCropWinMove, SCropFrameMove, SCropImgMove, SCropWinResize, SObservedMove,
SEditDrag1, SEditDrag2, SEditDrag3, SEditPick1, SEditPick2, SEditPick3
};
enum CursorArea {CropWinButtons, CropToolBar, CropImage, CropBorder, CropTop, CropTopLeft, CropTopRight, CropBottom, CropBottomLeft,
CropBottomRight, CropLeft, CropRight, CropInside, CropResize, CropObserved

View File

@ -57,9 +57,9 @@ enum EditType {
/// @brief Buffer type for ET_PIPETTE type editing
enum BufferType {
BT_IMAGEFLOAT,
BT_LABIMAGE,
BT_SINGLEPLANE_FLOAT
BT_IMAGEFLOAT, /// Imagefloat buffer type (3 channels of float values)
BT_LABIMAGE, /// LabImage buffer type (3 channels of float values)
BT_SINGLEPLANE_FLOAT /// All purpose, 1 channel buffer of float values
};
/// @brief Number of object to be handled (for optimization purpose)

View File

@ -323,7 +323,7 @@ void Gradient::editToggled ()
}
}
CursorShape Gradient::getCursor(int objectID)
CursorShape Gradient::getCursor(const int objectID)
{
switch (objectID) {
case (0):
@ -349,7 +349,7 @@ CursorShape Gradient::getCursor(int objectID)
}
}
bool Gradient::mouseOver(int modifierKey)
bool Gradient::mouseOver(const int modifierKey)
{
EditDataProvider* editProvider = getEditProvider();
@ -379,7 +379,7 @@ bool Gradient::mouseOver(int modifierKey)
return false;
}
bool Gradient::button1Pressed(int modifierKey)
bool Gradient::button1Pressed(const int modifierKey)
{
if (lastObject < 0) {
return false;
@ -433,7 +433,7 @@ bool Gradient::button1Pressed(int modifierKey)
draggedFeatherOffset -= (feather->getValue() / 200. * diagonal);
}
EditSubscriber::dragging = true;
EditSubscriber::action = ES_ACTION_DRAGGING;
return false;
} else { // should theoretically always be true
// this will let this class ignore further drag events
@ -454,11 +454,11 @@ bool Gradient::button1Pressed(int modifierKey)
bool Gradient::button1Released()
{
draggedPointOldAngle = -1000.;
EditSubscriber::dragging = false;
EditSubscriber::action = ES_ACTION_NONE;
return true;
}
bool Gradient::drag1(int modifierKey)
bool Gradient::drag1(const int modifierKey)
{
// compute the polar coordinate of the mouse position
EditDataProvider *provider = getEditProvider();

View File

@ -51,11 +51,11 @@ public:
void setEditProvider (EditDataProvider* provider);
// EditSubscriber interface
CursorShape getCursor(int objectID);
bool mouseOver(int modifierKey);
bool button1Pressed(int modifierKey);
CursorShape getCursor(const int objectID);
bool mouseOver(const int modifierKey);
bool button1Pressed(const int modifierKey);
bool button1Released();
bool drag1(int modifierKey);
bool drag1(const int modifierKey);
void switchOffEditMode ();
};