summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ganv/port.h8
-rw-r--r--src/Canvas.cpp85
-rw-r--r--src/ganv_test.c11
3 files changed, 64 insertions, 40 deletions
diff --git a/ganv/port.h b/ganv/port.h
index a3769f7..454c4a8 100644
--- a/ganv/port.h
+++ b/ganv/port.h
@@ -33,10 +33,10 @@ typedef struct _GanvPortClass GanvPortClass;
typedef struct {
GanvBox* rect;
- float value;
- float min;
- float max;
- gboolean is_toggle;
+ float value;
+ float min;
+ float max;
+ gboolean is_toggle;
} GanvPortControl;
struct _GanvPort
diff --git a/src/Canvas.cpp b/src/Canvas.cpp
index 601c882..5c0c082 100644
--- a/src/Canvas.cpp
+++ b/src/Canvas.cpp
@@ -953,7 +953,7 @@ GanvCanvasImpl::connect_drag_handler(GdkEvent* event)
{
static GanvEdge* drag_edge = NULL;
static GanvNode* drag_node = NULL;
- static bool snapped = false;
+ static bool snapped = false;
if (_drag_state != EDGE) {
return false;
@@ -1060,9 +1060,11 @@ GanvCanvasImpl::connect_drag_handler(GdkEvent* event)
bool
GanvCanvasImpl::port_event(GdkEvent* event, GanvPort* port)
{
- static bool port_dragging = false;
- static bool control_dragging = false;
- static bool ignore_button_release = false;
+ static bool port_dragging = false;
+ static bool control_dragging = false;
+ static double control_start_x = 0;
+ static double control_start_y = 0;
+ static float control_start_value = 0;
bool handled = true;
@@ -1071,14 +1073,19 @@ GanvCanvasImpl::port_event(GdkEvent* event, GanvPort* port)
case GDK_BUTTON_PRESS:
if (event->button.button == 1) {
GanvModule* const module = ganv_port_get_module(port);
- if (module && _gcanvas->locked && port->is_input) {
- std::cerr << "FIXME: port control drag" << std::endl;
-#if 0
- if (port->is_toggled()) {
- port->toggle();
- ignore_button_release = true;
+ if (module && port->is_input && port->control) {
+ if (port->control->is_toggle) {
+ if (port->control->value >= 0.5) {
+ ganv_port_set_control_value(port, 0.0);
+ } else {
+ ganv_port_set_control_value(port, 1.0);
+ }
} else {
- control_dragging = true;
+ control_dragging = true;
+ control_start_x = event->button.x_root;
+ control_start_y = event->button.y_root;
+ control_start_value = ganv_port_get_control_value(port);
+ #if 0
const double port_x = module->get_x() + port->get_x();
float new_control = ((event->button.x - port_x) / (double)port->get_width());
if (new_control < 0.0)
@@ -1093,10 +1100,10 @@ GanvCanvasImpl::port_event(GdkEvent* event, GanvPort* port)
if (new_control > port->control_max())
new_control = port->control_max();
if (new_control != port->control_value())
- port->set_control(new_control);
+ port->set_control_value(new_control);
+ #endif
}
-#endif
- } else {
+ } else if (!port->is_input) {
port_dragging = true;
}
} else {
@@ -1107,26 +1114,34 @@ GanvCanvasImpl::port_event(GdkEvent* event, GanvPort* port)
case GDK_MOTION_NOTIFY:
if (control_dragging) {
- GanvModule* const module = ganv_port_get_module(port);
- if (module) {
- const double port_x = ganv_box_get_x1(GANV_BOX(module))
- + ganv_box_get_x1(GANV_BOX(port));
- float new_control = ((event->button.x - port_x)
- / ganv_box_get_width(GANV_BOX(port)));
- if (new_control < 0.0)
- new_control = 0.0;
- else if (new_control > 1.0)
- new_control = 1.0;
-
- new_control *= (port->control->max - port->control->min);
- new_control += port->control->min;
- assert(new_control >= port->control->min);
- assert(new_control <= port->control->max);
-
- if (new_control != port->control->value) {
- ganv_port_set_control_value(port, new_control);
- }
- }
+ const double mouse_x = event->button.x_root;
+ const double mouse_y = event->button.y_root;
+ GdkScreen* screen = gdk_screen_get_default();
+ const int screen_width = gdk_screen_get_width(screen);
+ const int screen_height = gdk_screen_get_height(screen);
+ const double drag_dx = mouse_x - control_start_x;
+ const double drag_dy = mouse_y - control_start_y;
+
+ const double range_x = (drag_dx > 0)
+ ? (screen_width - control_start_x)
+ : control_start_x;
+
+ const double range_y = (drag_dy > 0)
+ ? (screen_height - control_start_y)
+ : control_start_y;
+
+ const double dx = drag_dx / range_x;
+ const double dy = drag_dy / range_y;
+
+ const double value_range = (drag_dx > 0)
+ ? port->control->max - control_start_value
+ : control_start_value - port->control->min;
+
+ const double sens = fmaxf(1.0 - fabs(dy), value_range / range_x);
+
+ const double dvalue = (dx * value_range) * sens;
+ const double value = control_start_value + dvalue;
+ ganv_port_set_control_value(port, value);
}
break;
@@ -1147,8 +1162,6 @@ GanvCanvasImpl::port_event(GdkEvent* event, GanvPort* port)
port_dragging = false;
} else if (control_dragging) {
control_dragging = false;
- } else if (ignore_button_release) {
- ignore_button_release = false;
} else {
handled = false;
}
diff --git a/src/ganv_test.c b/src/ganv_test.c
index a2df8af..4c1fc40 100644
--- a/src/ganv_test.c
+++ b/src/ganv_test.c
@@ -44,6 +44,17 @@ main(int argc, char** argv)
"label", "test",
NULL);
+ GanvPort* cport = ganv_port_new(module, TRUE,
+ "label", "Control",
+ NULL);
+ ganv_port_show_control(cport);
+
+ GanvPort* tport = ganv_port_new(module, TRUE,
+ "label", "Toggle",
+ NULL);
+ ganv_port_show_control(tport);
+ ganv_port_set_control_is_toggle(tport, TRUE);
+
gnome_canvas_item_show(GNOME_CANVAS_ITEM(module));
gnome_canvas_item_raise_to_top(GNOME_CANVAS_ITEM(module));