Enhanced curve editor :
- graphical celan up (surrounding frame deleted, histogram realigned) - a feedback tell what point is going to move - on Button press, the point doesn't move to the cursor anymore. Instead, the cursor is hidden during the drag and reappear in the same place it disappeared - by default, a 0.5 factor is used to move the point during the drag (i.e. you have to move the move of 2 pixel to move the point of one pixel) - keyboard can be used to fine tune the point position (subpixel placement) : - CTRL : factor = 0.1 - SHIFT : factor = 0.02 - CTRL+SHIFT : factor = 0.005 In the mean time, i had to create a new "Empty" cursor to hide it. A new method has been created to easily modify the cursor of the main window.
This commit is contained in:
@@ -30,21 +30,25 @@ void CursorManager::init (Glib::RefPtr<Gdk::Window> mainWin) {
|
|||||||
cCropMove = new Gdk::Cursor (Gdk::FLEUR);
|
cCropMove = new Gdk::Cursor (Gdk::FLEUR);
|
||||||
cCropMoving = new Gdk::Cursor (Gdk::HAND2);
|
cCropMoving = new Gdk::Cursor (Gdk::HAND2);
|
||||||
cCropSelection = new Gdk::Cursor (Gdk::CROSSHAIR);
|
cCropSelection = new Gdk::Cursor (Gdk::CROSSHAIR);
|
||||||
#ifdef _WIN32
|
cAdd = new Gdk::Cursor (Gdk::PLUS);
|
||||||
cNormal = new Gdk::Cursor (Gdk::LAST_CURSOR);
|
//#ifdef _WIN32
|
||||||
#else
|
// cNormal = new Gdk::Cursor (Gdk::LAST_CURSOR);
|
||||||
|
//#else
|
||||||
cNormal = new Gdk::Cursor (Gdk::ARROW);
|
cNormal = new Gdk::Cursor (Gdk::ARROW);
|
||||||
#endif
|
//#endif
|
||||||
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
Glib::RefPtr<Gdk::Pixbuf> hand = safe_create_from_file(argv0+"/images/openhand22.png");
|
||||||
Glib::RefPtr<Gdk::Pixbuf> close_hand = safe_create_from_file(argv0+"/images/closedhand22.png");
|
Glib::RefPtr<Gdk::Pixbuf> close_hand = safe_create_from_file(argv0+"/images/closedhand22.png");
|
||||||
Glib::RefPtr<Gdk::Pixbuf> wbpick = safe_create_from_file(argv0+"/images/wbpicker16.png");
|
Glib::RefPtr<Gdk::Pixbuf> wbpick = safe_create_from_file(argv0+"/images/wbpicker16.png");
|
||||||
cHand = hand ? new Gdk::Cursor (cNormal->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
Glib::RefPtr<Gdk::Pixbuf> empty = safe_create_from_file(argv0+"/images/empty.png");
|
||||||
|
cHand = hand ? new Gdk::Cursor (cNormal->get_display(), hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||||
cClosedHand = close_hand ? new Gdk::Cursor (cNormal->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
cClosedHand = close_hand ? new Gdk::Cursor (cNormal->get_display(), close_hand, 10, 10) : new Gdk::Cursor (Gdk::HAND2);
|
||||||
cWB = wbpick ? new Gdk::Cursor (cNormal->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW);
|
cWB = wbpick ? new Gdk::Cursor (cNormal->get_display(), wbpick, 1, 12) : new Gdk::Cursor (Gdk::ARROW);
|
||||||
|
cHidden = empty ? new Gdk::Cursor (cNormal->get_display(), empty, 12, 12) : new Gdk::Cursor (Gdk::FLEUR);
|
||||||
|
|
||||||
mainWindow = mainWin;
|
mainWindow = mainWin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the cursor of the given window */
|
||||||
void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape) {
|
void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape) {
|
||||||
|
|
||||||
if (shape==CSArrow)
|
if (shape==CSArrow)
|
||||||
@@ -67,6 +71,14 @@ void CursorManager::setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape sha
|
|||||||
window->set_cursor (*cCropSelection);
|
window->set_cursor (*cCropSelection);
|
||||||
else if (shape==CSStraighten)
|
else if (shape==CSStraighten)
|
||||||
window->set_cursor (*cCropSelection);
|
window->set_cursor (*cCropSelection);
|
||||||
|
else if (shape==CSPlus)
|
||||||
|
window->set_cursor (*cAdd);
|
||||||
|
else if (shape==CSEmpty)
|
||||||
|
window->set_cursor (*cHidden);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set the cursor of the main window */
|
||||||
|
void CursorManager::setCursor (CursorShape shape) {
|
||||||
|
setCursor(mainWindow, shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
|
|
||||||
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten};
|
enum CursorShape {CSArrow, CSOpenHand, CSClosedHand, CSMove, CSResizeWidth, CSResizeHeight, CSResizeDiagonal, CSSpotWB, CSCropSelect, CSStraighten, CSPlus, CSEmpty};
|
||||||
|
|
||||||
class CursorManager {
|
class CursorManager {
|
||||||
|
|
||||||
@@ -33,14 +33,17 @@ class CursorManager {
|
|||||||
Gdk::Cursor* cCropMoving;
|
Gdk::Cursor* cCropMoving;
|
||||||
Gdk::Cursor* cNormal;
|
Gdk::Cursor* cNormal;
|
||||||
Gdk::Cursor* cCropSelection;
|
Gdk::Cursor* cCropSelection;
|
||||||
|
Gdk::Cursor* cAdd;
|
||||||
Gdk::Cursor* cHand;
|
Gdk::Cursor* cHand;
|
||||||
Gdk::Cursor* cClosedHand;
|
Gdk::Cursor* cClosedHand;
|
||||||
Gdk::Cursor* cWB;
|
Gdk::Cursor* cWB;
|
||||||
|
Gdk::Cursor* cHidden;
|
||||||
Glib::RefPtr<Gdk::Window> mainWindow;
|
Glib::RefPtr<Gdk::Window> mainWindow;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init (Glib::RefPtr<Gdk::Window> mainWin);
|
void init (Glib::RefPtr<Gdk::Window> mainWin);
|
||||||
void setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
|
void setCursor (Glib::RefPtr<Gdk::Window> window, CursorShape shape);
|
||||||
|
void setCursor (CursorShape shape);
|
||||||
};
|
};
|
||||||
|
|
||||||
extern CursorManager cursorManager;
|
extern CursorManager cursorManager;
|
||||||
|
@@ -40,12 +40,16 @@ CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false),
|
|||||||
|
|
||||||
// custom curve
|
// custom curve
|
||||||
customCurveBox = new Gtk::VBox ();
|
customCurveBox = new Gtk::VBox ();
|
||||||
|
Gtk::HBox* tmpa = Gtk::manage (new Gtk::HBox ());
|
||||||
customCurve = Gtk::manage (new MyCurve ());
|
customCurve = Gtk::manage (new MyCurve ());
|
||||||
Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
Gtk::Table* cctab = Gtk::manage (new Gtk::Table (2,1));
|
||||||
af->add (*customCurve);
|
//Gtk::AspectFrame* af = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||||
customCurve->set_size_request (-1, 200);
|
//af->add (*customCurve);
|
||||||
|
customCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||||
customCurve->setType (Spline);
|
customCurve->setType (Spline);
|
||||||
customCurveBox->pack_start (*af, Gtk::PACK_EXPAND_WIDGET);
|
tmpa->pack_start (*customCurve, true, false, 4);
|
||||||
|
customCurveBox->pack_start (*tmpa, true, true,4);
|
||||||
|
//customCurveBox->set_size_request (0, -1);
|
||||||
|
|
||||||
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
|
Gtk::HBox* bbox = Gtk::manage (new Gtk::HBox ());
|
||||||
save = Gtk::manage (new Gtk::Button ());
|
save = Gtk::manage (new Gtk::Button ());
|
||||||
@@ -67,19 +71,19 @@ CurveEditor::CurveEditor () : cl(NULL), activeParamControl(-1), realized(false),
|
|||||||
// parametric curve
|
// parametric curve
|
||||||
paramCurveBox = new Gtk::VBox ();
|
paramCurveBox = new Gtk::VBox ();
|
||||||
paramCurve = Gtk::manage (new MyCurve ());
|
paramCurve = Gtk::manage (new MyCurve ());
|
||||||
Gtk::Table* ctab = Gtk::manage (new Gtk::Table (2,1));
|
Gtk::Table* paramctab = Gtk::manage (new Gtk::Table (2,1));
|
||||||
Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
//Gtk::AspectFrame* afp = Gtk::manage (new Gtk::AspectFrame ("",Gtk::ALIGN_CENTER,Gtk::ALIGN_CENTER,1,false));
|
||||||
afp->add (*paramCurve);
|
//afp->add (*paramCurve);
|
||||||
paramCurve->set_size_request (200, 200);
|
paramCurve->set_size_request (GRAPH_SIZE+2*RADIUS, GRAPH_SIZE+2*RADIUS);
|
||||||
paramCurve->setType (Parametric);
|
paramCurve->setType (Parametric);
|
||||||
shcSelector = Gtk::manage (new SHCSelector ());
|
shcSelector = Gtk::manage (new SHCSelector ());
|
||||||
shcSelector->set_size_request (200, 20);
|
shcSelector->set_size_request (GRAPH_SIZE, 20);
|
||||||
|
|
||||||
ctab->attach (*afp, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
paramctab->attach (*paramCurve, 0, 1, 0, 1, Gtk::FILL, Gtk::SHRINK, RADIUS+2, RADIUS+2);
|
||||||
ctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, 2, 2);
|
paramctab->attach (*shcSelector, 0, 1, 1, 2, Gtk::FILL, Gtk::SHRINK, RADIUS+2, 2);
|
||||||
|
|
||||||
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
Gtk::HBox* tmpb = Gtk::manage (new Gtk::HBox ());
|
||||||
tmpb->pack_start (*ctab, true, false);
|
tmpb->pack_start (*paramctab, true, false);
|
||||||
|
|
||||||
paramCurveBox->pack_start (*tmpb, true, true);
|
paramCurveBox->pack_start (*tmpb, true, true);
|
||||||
|
|
||||||
|
187
rtgui/mycurve.cc
187
rtgui/mycurve.cc
@@ -19,18 +19,17 @@
|
|||||||
#include <mycurve.h>
|
#include <mycurve.h>
|
||||||
#include <curves.h>
|
#include <curves.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <gdkmm/types.h>
|
||||||
#define RADIUS 3 /* radius of the control points */
|
|
||||||
#define MIN_DISTANCE 8 /* min distance between control points */
|
|
||||||
|
|
||||||
MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
|
MyCurve::MyCurve () : listener(NULL), activeParam(-1), bghistvalid(false) {
|
||||||
|
|
||||||
cursor_type = Gdk::TOP_LEFT_ARROW;
|
cursor_type = CSArrow;
|
||||||
curve.type = Spline;
|
curve.type = Spline;
|
||||||
height = 0;
|
height = 0;
|
||||||
grab_point = -1;
|
grab_point = -1;
|
||||||
|
lit_point = -1;
|
||||||
|
|
||||||
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
add_events(Gdk::EXPOSURE_MASK | Gdk::POINTER_MOTION_MASK | Gdk::POINTER_MOTION_HINT_MASK | Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK | Gdk::BUTTON_PRESS_MASK | Gdk::BUTTON_RELEASE_MASK | Gdk::BUTTON1_MOTION_MASK);
|
||||||
signal_event().connect( sigc::mem_fun(*this, &MyCurve::handleEvents) );
|
signal_event().connect( sigc::mem_fun(*this, &MyCurve::handleEvents) );
|
||||||
|
|
||||||
curve.x.push_back(0);
|
curve.x.push_back(0);
|
||||||
@@ -126,7 +125,8 @@ void MyCurve::interpolate (int width, int height) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyCurve::draw (int width, int height) {
|
void MyCurve::draw (int width, int height, int handle) {
|
||||||
|
// width and heigth are the size of the graph
|
||||||
|
|
||||||
if (!pixmap)
|
if (!pixmap)
|
||||||
return;
|
return;
|
||||||
@@ -135,7 +135,6 @@ void MyCurve::draw (int width, int height) {
|
|||||||
if (this->height != height || point.size() != width)
|
if (this->height != height || point.size() != width)
|
||||||
interpolate (width, height);
|
interpolate (width, height);
|
||||||
|
|
||||||
|
|
||||||
Gtk::StateType state = Gtk::STATE_NORMAL;
|
Gtk::StateType state = Gtk::STATE_NORMAL;
|
||||||
if (!is_sensitive())
|
if (!is_sensitive())
|
||||||
state = Gtk::STATE_INSENSITIVE;
|
state = Gtk::STATE_INSENSITIVE;
|
||||||
@@ -159,16 +158,16 @@ void MyCurve::draw (int width, int height) {
|
|||||||
// draw histogram
|
// draw histogram
|
||||||
cr->set_line_width (1.0);
|
cr->set_line_width (1.0);
|
||||||
double stepSize = (width-1) / 256.0;
|
double stepSize = (width-1) / 256.0;
|
||||||
cr->move_to (0, height-1);
|
cr->move_to (RADIUS, height-1+RADIUS);
|
||||||
cr->set_source_rgb (0.75, 0.75, 0.75);
|
cr->set_source_rgb (0.75, 0.75, 0.75);
|
||||||
for (int i=0; i<256; i++) {
|
for (int i=0; i<256; i++) {
|
||||||
double val = bghist[i] * (double)(height-2) / histheight;
|
double val = bghist[i] * (double)(height-2) / histheight;
|
||||||
if (val>height-1)
|
if (val>height-1)
|
||||||
val = height-1;
|
val = height-1;
|
||||||
if (i>0)
|
if (i>0)
|
||||||
cr->line_to (i*stepSize, height-1-val);
|
cr->line_to (i*stepSize+RADIUS, height-1+RADIUS-val);
|
||||||
}
|
}
|
||||||
cr->line_to (width-1, height-1);
|
cr->line_to (width-1+RADIUS, height-1+RADIUS);
|
||||||
cr->fill ();
|
cr->fill ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,10 +177,10 @@ void MyCurve::draw (int width, int height) {
|
|||||||
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
cr->set_source_rgb (c.get_red_p(), c.get_green_p(), c.get_blue_p());
|
||||||
cr->set_antialias (Cairo::ANTIALIAS_NONE);
|
cr->set_antialias (Cairo::ANTIALIAS_NONE);
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
cr->move_to (RADIUS, i * height / 4 + RADIUS);
|
cr->move_to (RADIUS, MAX(0,i * height / 4 - 1) + RADIUS);
|
||||||
cr->line_to (width + RADIUS, i * height / 4 + RADIUS);
|
cr->line_to (width + RADIUS, MAX(0,i * height / 4 - 1) + RADIUS);
|
||||||
cr->move_to (i * width / 4 + RADIUS, RADIUS);
|
cr->move_to (MAX(0,i * width / 4 - 1) + RADIUS, RADIUS);
|
||||||
cr->line_to (i * width / 4 + RADIUS, height + RADIUS);
|
cr->line_to (MAX(0,i * width / 4 - 1) + RADIUS, height + RADIUS);
|
||||||
}
|
}
|
||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
|
|
||||||
@@ -195,6 +194,7 @@ void MyCurve::draw (int width, int height) {
|
|||||||
cr->stroke ();
|
cr->stroke ();
|
||||||
cr->unset_dash ();
|
cr->unset_dash ();
|
||||||
|
|
||||||
|
|
||||||
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
cr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL);
|
||||||
cr->set_line_width (1.0);
|
cr->set_line_width (1.0);
|
||||||
|
|
||||||
@@ -221,10 +221,11 @@ void MyCurve::draw (int width, int height) {
|
|||||||
// draw bullets
|
// draw bullets
|
||||||
if (curve.type!=Parametric)
|
if (curve.type!=Parametric)
|
||||||
for (int i = 0; i < curve.x.size(); ++i) {
|
for (int i = 0; i < curve.x.size(); ++i) {
|
||||||
|
cr->set_source_rgb ((i == handle ? 1.0 : 0.0), 0.0, 0.0);
|
||||||
double x = ((width-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, width);
|
double x = ((width-1) * curve.x[i] + 0.5)+RADIUS; // project (curve.x[i], 0, 1, width);
|
||||||
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height);
|
double y = height - ((height-1) * curve.y[i] + 0.5)+RADIUS; // project (curve.y[i], 0, 1, height);
|
||||||
|
|
||||||
cr->arc (x, y, RADIUS, 0, 2*M_PI);
|
cr->arc (x, y, RADIUS+0.5, 0, 2*M_PI);
|
||||||
cr->fill ();
|
cr->fill ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,13 +234,17 @@ void MyCurve::draw (int width, int height) {
|
|||||||
|
|
||||||
bool MyCurve::handleEvents (GdkEvent* event) {
|
bool MyCurve::handleEvents (GdkEvent* event) {
|
||||||
|
|
||||||
Gdk::CursorType new_type = cursor_type;
|
CursorShape new_type = cursor_type;
|
||||||
int src, dst;
|
int src, dst;
|
||||||
GdkEventMotion *mevent;
|
GdkEventMotion *mevent;
|
||||||
std::vector<double>::iterator itx, ity;
|
std::vector<double>::iterator itx, ity;
|
||||||
|
|
||||||
|
Glib::RefPtr<Gdk::Display> rt_display = Gtk::Widget::get_display();
|
||||||
|
Glib::RefPtr<Gdk::Screen> rt_screen = Gtk::Widget::get_screen();
|
||||||
|
|
||||||
bool retval = false;
|
bool retval = false;
|
||||||
|
|
||||||
|
/* width and height are the size of the graph */
|
||||||
int width = get_allocation().get_width() - RADIUS * 2;
|
int width = get_allocation().get_width() - RADIUS * 2;
|
||||||
int height = get_allocation().get_height() - RADIUS * 2;
|
int height = get_allocation().get_height() - RADIUS * 2;
|
||||||
|
|
||||||
@@ -250,12 +255,12 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
|||||||
int tx, ty;
|
int tx, ty;
|
||||||
Gdk::ModifierType gm;
|
Gdk::ModifierType gm;
|
||||||
get_window()->get_pointer (tx, ty, gm);
|
get_window()->get_pointer (tx, ty, gm);
|
||||||
int x = CLAMP ((tx - RADIUS), 0, width-1);
|
int x = CLAMP ((tx - RADIUS), 0, width-1); // X position of the pointer from the origin of the graph
|
||||||
int y = CLAMP ((ty - RADIUS), 0, height-1);
|
int y = height-1 - CLAMP ((ty - RADIUS), 0, height-1); // Y position of the pointer from the origin of the graph
|
||||||
|
|
||||||
unsigned int distance = ~0U;
|
unsigned int distance = ~0U;
|
||||||
int num = curve.x.size();
|
int num = curve.x.size();
|
||||||
int closest_point = 0;
|
int closest_point = -1;
|
||||||
|
|
||||||
if (curve.type!=Parametric) {
|
if (curve.type!=Parametric) {
|
||||||
for (int i = 0; i < num; ++i) {
|
for (int i = 0; i < num; ++i) {
|
||||||
@@ -273,17 +278,23 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
|||||||
pixmap.clear ();
|
pixmap.clear ();
|
||||||
|
|
||||||
case Gdk::EXPOSE:
|
case Gdk::EXPOSE:
|
||||||
|
// When does this event occurs ???
|
||||||
if (!pixmap) {
|
if (!pixmap) {
|
||||||
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
|
pixmap = Gdk::Pixmap::create (get_window(), get_allocation().get_width(), get_allocation().get_height());
|
||||||
interpolate (width, height);
|
interpolate (width, height);
|
||||||
}
|
}
|
||||||
draw (width, height);
|
draw (width, height, lit_point);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Gdk::BUTTON_PRESS:
|
case Gdk::BUTTON_PRESS:
|
||||||
if (curve.type!=Parametric) {
|
if (curve.type!=Parametric) {
|
||||||
add_modal_grab ();
|
add_modal_grab ();
|
||||||
new_type = Gdk::PLUS;
|
|
||||||
|
// get cursor position
|
||||||
|
Gdk::ModifierType mod_type;
|
||||||
|
rt_display->get_pointer(cursor_x, cursor_y, mod_type);
|
||||||
|
|
||||||
|
new_type = CSEmpty;
|
||||||
if (distance > MIN_DISTANCE) {
|
if (distance > MIN_DISTANCE) {
|
||||||
/* insert a new control point */
|
/* insert a new control point */
|
||||||
if (num > 0) {
|
if (num > 0) {
|
||||||
@@ -294,24 +305,30 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
|||||||
itx = curve.x.begin();
|
itx = curve.x.begin();
|
||||||
ity = curve.y.begin();
|
ity = curve.y.begin();
|
||||||
for (int i=0; i<closest_point; i++) { itx++; ity++; }
|
for (int i=0; i<closest_point; i++) { itx++; ity++; }
|
||||||
curve.x.insert (itx, 0);
|
curve.x.insert (itx, 0);
|
||||||
curve.y.insert (ity, 0);
|
curve.y.insert (ity, 0);
|
||||||
num++;
|
num++;
|
||||||
}
|
|
||||||
grab_point = closest_point;
|
// the graph is refreshed only if a new point is created (snaped to a pixel)
|
||||||
curve.x[grab_point] = (double) x / (width-1);
|
curve.x[closest_point] = (double) x / (width-1);
|
||||||
curve.y[grab_point] = (double) (height-y) / (height-1);
|
curve.y[closest_point] = (double) y / (height-1);
|
||||||
interpolate (width, height);
|
interpolate (width, height);
|
||||||
notifyListener ();
|
draw (width, height, closest_point);
|
||||||
break;
|
}
|
||||||
|
grab_point = closest_point;
|
||||||
|
lit_point = closest_point;
|
||||||
|
ugp_x = curve.x[closest_point];
|
||||||
|
ugp_y = curve.y[closest_point];
|
||||||
|
notifyListener ();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
draw (width, height);
|
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Gdk::BUTTON_RELEASE:
|
case Gdk::BUTTON_RELEASE:
|
||||||
if (curve.type!=Parametric) {
|
if (curve.type!=Parametric) {
|
||||||
remove_modal_grab ();
|
remove_modal_grab ();
|
||||||
|
int previous_lit_point = lit_point;
|
||||||
/* delete inactive points: */
|
/* delete inactive points: */
|
||||||
itx = curve.x.begin();
|
itx = curve.x.begin();
|
||||||
ity = curve.y.begin();
|
ity = curve.y.begin();
|
||||||
@@ -330,61 +347,115 @@ bool MyCurve::handleEvents (GdkEvent* event) {
|
|||||||
curve.x.push_back (0);
|
curve.x.push_back (0);
|
||||||
curve.y.push_back (0);
|
curve.y.push_back (0);
|
||||||
interpolate (width, height);
|
interpolate (width, height);
|
||||||
draw (width, height);
|
draw (width, height, lit_point);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
new_type = Gdk::FLEUR;
|
if (distance <= MIN_DISTANCE) {
|
||||||
|
new_type = CSMove;
|
||||||
|
lit_point = closest_point;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
new_type = CSPlus;
|
||||||
|
lit_point = -1;
|
||||||
|
}
|
||||||
|
if (lit_point != previous_lit_point)
|
||||||
|
draw (width, height, lit_point);
|
||||||
grab_point = -1;
|
grab_point = -1;
|
||||||
retval = true;
|
retval = true;
|
||||||
notifyListener ();
|
notifyListener ();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Gdk::LEAVE_NOTIFY:
|
||||||
|
// Pointer can LEAVE even when dragging the point, so we don't modify the cursor in this case
|
||||||
|
// The cursor will have to LEAVE another time after the drag...
|
||||||
|
if (grab_point == -1)
|
||||||
|
new_type = CSArrow;
|
||||||
|
break;
|
||||||
|
|
||||||
case Gdk::MOTION_NOTIFY:
|
case Gdk::MOTION_NOTIFY:
|
||||||
mevent = (GdkEventMotion *) event;
|
mevent = (GdkEventMotion *) event;
|
||||||
|
|
||||||
if (curve.type == Linear || curve.type == Spline) {
|
if (curve.type == Linear || curve.type == Spline) {
|
||||||
if (grab_point == -1) {
|
if (grab_point == -1) {
|
||||||
|
int previous_lit_point = lit_point;
|
||||||
/* if no point is grabbed... */
|
/* if no point is grabbed... */
|
||||||
if (distance <= MIN_DISTANCE)
|
if (distance <= MIN_DISTANCE) {
|
||||||
new_type = Gdk::FLEUR;
|
new_type = CSMove;
|
||||||
else
|
lit_point = closest_point;
|
||||||
new_type = Gdk::PLUS;
|
}
|
||||||
|
else {
|
||||||
|
new_type = CSPlus;
|
||||||
|
lit_point = -1;
|
||||||
|
}
|
||||||
|
if ((new_type != cursor_type) || (lit_point != previous_lit_point))
|
||||||
|
draw (width, height, lit_point);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* drag the grabbed point */
|
int new_cursor_x, new_cursor_y;
|
||||||
new_type = Gdk::FLEUR;
|
double factor = 0.5;
|
||||||
int leftbound = -MIN_DISTANCE;
|
|
||||||
if (grab_point > 0)
|
|
||||||
leftbound = (int)((width-1)*curve.x[grab_point-1]+0.5);
|
|
||||||
|
|
||||||
int rightbound = width + RADIUS * 2 + MIN_DISTANCE;
|
// get cursor position
|
||||||
if (grab_point + 1 < num)
|
Gdk::ModifierType mod_type;
|
||||||
rightbound = (int)((width-1)*curve.x[grab_point+1]+0.5);
|
rt_display->get_pointer(new_cursor_x, new_cursor_y, mod_type);
|
||||||
|
|
||||||
if (tx <= leftbound || tx >= rightbound || ty > height + RADIUS * 2 + MIN_DISTANCE || ty < -MIN_DISTANCE)
|
// set the dragging factor
|
||||||
curve.x[grab_point] = -1.0;
|
int control_key = gm & GDK_CONTROL_MASK;
|
||||||
else {
|
int shift_key = gm & GDK_SHIFT_MASK;
|
||||||
curve.x[grab_point] = (double) x / (width-1);
|
|
||||||
curve.y[grab_point] = (double) (height-y) / (height-1);
|
// what is the speed factor
|
||||||
|
if (control_key && shift_key) factor = 0.005;
|
||||||
|
else if (shift_key) factor = 0.02;
|
||||||
|
else if (control_key) factor = 0.1;
|
||||||
|
|
||||||
|
// calculate the delta in [0.0 ; 1.0] range
|
||||||
|
double delta_x = (double)(new_cursor_x - cursor_x) * factor / (double)(width-1);
|
||||||
|
double delta_y = (double)(cursor_y - new_cursor_y) * factor / (double)(height-1);
|
||||||
|
|
||||||
|
// modification of the unclamped grabed point
|
||||||
|
ugp_x += delta_x;
|
||||||
|
ugp_y += delta_y;
|
||||||
|
|
||||||
|
// first and last point cannot be deleted anymore (there's no point to do it)
|
||||||
|
// for intermediate points, we look if the point must be deleted
|
||||||
|
if (grab_point > 0 && grab_point < num-1) {
|
||||||
|
double leftbound = curve.x[grab_point-1];
|
||||||
|
double rightbound = curve.x[grab_point+1];
|
||||||
|
double bottombound = (double)(-MIN_DISTANCE) * factor / (double)(height-1);
|
||||||
|
double topbound = (double)1.0 + (double)(MIN_DISTANCE) * factor / (double)(height-1);
|
||||||
|
|
||||||
|
if (ugp_x <= leftbound || ugp_x >= rightbound || ugp_y > topbound || ugp_y < bottombound) {
|
||||||
|
curve.x[grab_point] = -1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// first and last points are clamped to the [0.0 ; 1.0] range
|
||||||
|
if (curve.x[grab_point] != -1.0) {
|
||||||
|
double new_curve_x = curve.x[grab_point] + delta_x;
|
||||||
|
double new_curve_y = curve.y[grab_point] + delta_y;
|
||||||
|
curve.x[grab_point] = CLAMP(new_curve_x,0.0,1.0);
|
||||||
|
curve.y[grab_point] = CLAMP(new_curve_y,0.0,1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
interpolate (width, height);
|
interpolate (width, height);
|
||||||
draw (width, height);
|
|
||||||
|
// move the cursor back (to avoid being limited by the screen)
|
||||||
|
rt_display->warp_pointer(rt_screen, cursor_x, cursor_y);
|
||||||
|
|
||||||
|
draw (width, height, lit_point);
|
||||||
notifyListener ();
|
notifyListener ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_type != cursor_type) {
|
|
||||||
cursor_type = new_type;
|
|
||||||
Gdk::Cursor* cursor = new Gdk::Cursor (get_display(), cursor_type);
|
|
||||||
get_window ()->set_cursor (*cursor);
|
|
||||||
delete cursor;
|
|
||||||
}
|
|
||||||
retval = true;
|
retval = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (new_type != cursor_type) {
|
||||||
|
cursor_type = new_type;
|
||||||
|
cursorManager.setCursor(cursor_type);
|
||||||
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,6 +22,11 @@
|
|||||||
#include <gtkmm.h>
|
#include <gtkmm.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <curvelistener.h>
|
#include <curvelistener.h>
|
||||||
|
#include <cursormanager.h>
|
||||||
|
|
||||||
|
#define RADIUS 3 /* radius of the control points. Assuming that the center of the spot is in the center of the pixel, the real RADIUS will be this value +0.5 */
|
||||||
|
#define MIN_DISTANCE 8 /* min distance between control points */
|
||||||
|
#define GRAPH_SIZE 200 /* size of the curve editor graphic */
|
||||||
|
|
||||||
enum CurveType {Linear, Spline, Parametric};
|
enum CurveType {Linear, Spline, Parametric};
|
||||||
|
|
||||||
@@ -46,10 +51,11 @@ class MyCurve : public Gtk::DrawingArea {
|
|||||||
protected:
|
protected:
|
||||||
CurveListener* listener;
|
CurveListener* listener;
|
||||||
CurveDescr curve;
|
CurveDescr curve;
|
||||||
Gdk::CursorType cursor_type;
|
CursorShape cursor_type;
|
||||||
Glib::RefPtr<Gdk::Pixmap> pixmap;
|
Glib::RefPtr<Gdk::Pixmap> pixmap;
|
||||||
int height;
|
int height;
|
||||||
int grab_point;
|
int grab_point;
|
||||||
|
int lit_point;
|
||||||
int last;
|
int last;
|
||||||
std::vector<Gdk::Point> point;
|
std::vector<Gdk::Point> point;
|
||||||
std::vector<Gdk::Point> upoint;
|
std::vector<Gdk::Point> upoint;
|
||||||
@@ -58,8 +64,10 @@ class MyCurve : public Gtk::DrawingArea {
|
|||||||
unsigned int bghist[256];
|
unsigned int bghist[256];
|
||||||
bool bghistvalid;
|
bool bghistvalid;
|
||||||
MyCurveIdleHelper* mcih;
|
MyCurveIdleHelper* mcih;
|
||||||
|
int cursor_x, cursor_y;
|
||||||
|
double ugp_x, ugp_y; // unclamped grabed point coordinates
|
||||||
|
|
||||||
void draw (int width, int height);
|
void draw (int width, int height, int handle);
|
||||||
void interpolate (int width, int height);
|
void interpolate (int width, int height);
|
||||||
std::vector<double> get_vector (int veclen);
|
std::vector<double> get_vector (int veclen);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user