diff --git a/src/node-context.cpp b/src/node-context.cpp
index 352bac58465b917cb3d2166f8419e761f5109e9b..d8a1ec1d7deb953f20517561dfd35d78ff8b5d2b 100644 (file)
--- a/src/node-context.cpp
+++ b/src/node-context.cpp
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
+#include <cstring>
+#include <string>
#include <gdk/gdkkeysyms.h>
#include "macros.h"
#include <glibmm/i18n.h>
#include "style.h"
#include "splivarot.h"
#include "shape-editor.h"
+#include "live_effects/effect.h"
+
+#include "sp-lpe-item.h"
+
+// needed for flash nodepath upon mouseover:
+#include "display/canvas-bpath.h"
+#include "display/curve.h"
static void sp_node_context_class_init(SPNodeContextClass *klass);
static void sp_node_context_init(SPNodeContext *node_context);
node_context->rightctrl = FALSE;
new (&node_context->sel_changed_connection) sigc::connection();
+
+ node_context->flash_tempitem = NULL;
+ node_context->flashed_item = NULL;
+ node_context->remove_flash_counter = 0;
}
static void
if (((SPEventContextClass *) parent_class)->setup)
((SPEventContextClass *) parent_class)->setup(ec);
+ Inkscape::Selection *selection = sp_desktop_selection (ec->desktop);
nc->sel_changed_connection.disconnect();
- nc->sel_changed_connection = sp_desktop_selection(ec->desktop)->connectChanged(sigc::bind(sigc::ptr_fun(&sp_node_context_selection_changed), (gpointer)nc));
+ nc->sel_changed_connection =
+ selection->connectChanged(sigc::bind(sigc::ptr_fun(&sp_node_context_selection_changed), (gpointer)nc));
- Inkscape::Selection *selection = sp_desktop_selection(ec->desktop);
SPItem *item = selection->singleItem();
nc->shape_editor = new ShapeEditor(ec->desktop);
nc->current_state = SP_NODE_CONTEXT_INACTIVE;
if (item) {
- nc->shape_editor->set_item(item);
+ nc->shape_editor->set_item(item, SH_NODEPATH);
+ nc->shape_editor->set_item(item, SH_KNOTHOLDER);
}
if (prefs_get_int_attribute("tools.nodes", "selcue", 0) != 0) {
ec->enableGrDrag();
}
+ ec->desktop->emitToolSubselectionChanged(NULL); // sets the coord entry fields to inactive
+
nc->_node_message_context = new Inkscape::MessageContext((ec->desktop)->messageStack());
nc->shape_editor->update_statusbar();
}
+static void
+sp_node_context_flash_path(SPEventContext *event_context, SPItem *item, guint timeout) {
+ g_print ("-----> sp_node_context_flash_path(): TODO: generate the helper path!!\n");
+ SPNodeContext *nc = SP_NODE_CONTEXT(event_context);
+
+ nc->remove_flash_counter = 3; // for some reason root_handler is called twice after each item_handler...
+ if (nc->flashed_item != item) {
+ // we entered a new item
+ nc->flashed_item = item;
+ SPDesktop *desktop = event_context->desktop;
+ if (nc->flash_tempitem) {
+ desktop->remove_temporary_canvasitem(nc->flash_tempitem);
+ nc->flash_tempitem = NULL;
+ }
+
+ if (SP_IS_PATH(item)) {
+ SPCanvasItem *canvasitem = sp_nodepath_helperpath_from_path(desktop, SP_PATH(item));
+ nc->flash_tempitem = desktop->add_temporary_canvasitem (canvasitem, timeout);
+ }
+ }
+}
+
/**
\brief Callback that processes the "changed" signal on the selection;
destroys old and creates new nodepath and reassigns listeners to the new selected item's repr
@@ -168,10 +207,11 @@ sp_node_context_selection_changed(Inkscape::Selection *selection, gpointer data)
SPNodeContext *nc = SP_NODE_CONTEXT(data);
// TODO: update ShapeEditorsCollective instead
- nc->shape_editor->unset_item();
+ nc->shape_editor->unset_item(SH_NODEPATH);
+ nc->shape_editor->unset_item(SH_KNOTHOLDER);
SPItem *item = selection->singleItem();
- nc->shape_editor->set_item(item);
-
+ nc->shape_editor->set_item(item, SH_NODEPATH);
+ nc->shape_editor->set_item(item, SH_KNOTHOLDER);
nc->shape_editor->update_statusbar();
}
@@ -185,117 +225,27 @@ sp_node_context_show_modifier_tip(SPEventContext *event_context, GdkEvent *event
_("<b>Alt</b>: lock handle length; <b>Ctrl+Alt</b>: move along handles"));
}
-
static gint
sp_node_context_item_handler(SPEventContext *event_context, SPItem *item, GdkEvent *event)
{
gint ret = FALSE;
- SPDesktop *desktop = event_context->desktop;
- Inkscape::Selection *selection = sp_desktop_selection (desktop);
-
- SPNodeContext *nc = SP_NODE_CONTEXT(event_context);
-
- switch (event->type) {
- case GDK_2BUTTON_PRESS:
- case GDK_BUTTON_RELEASE:
- if (event->button.button == 1) {
- if (!nc->drag) {
-
- // find out clicked item, disregarding groups, honoring Alt
- SPItem *item_clicked = sp_event_context_find_item (desktop,
- NR::Point(event->button.x, event->button.y),
- (event->button.state & GDK_MOD1_MASK) && !(event->button.state & GDK_CONTROL_MASK), TRUE);
- // find out if we're over the selected item, disregarding groups
- SPItem *item_over = sp_event_context_over_item (desktop, selection->singleItem(),
- NR::Point(event->button.x, event->button.y));
-
- bool over_stroke = false;
- if (item_over && nc->shape_editor->has_nodepath()) {
- over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), false);
- }
-
- if (over_stroke || nc->added_node) {
- switch (event->type) {
- case GDK_BUTTON_RELEASE:
- if (event->button.state & GDK_CONTROL_MASK && event->button.state & GDK_MOD1_MASK) {
- //add a node
- nc->shape_editor->add_node_near_point();
- } else {
- if (nc->added_node) { // we just received double click, ignore release
- nc->added_node = false;
- break;
- }
- //select the segment
- if (event->button.state & GDK_SHIFT_MASK) {
- nc->shape_editor->select_segment_near_point(true);
- } else {
- nc->shape_editor->select_segment_near_point(false);
- }
- desktop->updateNow();
- }
- break;
- case GDK_2BUTTON_PRESS:
- //add a node
- nc->shape_editor->add_node_near_point();
- nc->added_node = true;
- break;
- default:
- break;
- }
- } else if (event->button.state & GDK_SHIFT_MASK) {
- selection->toggle(item_clicked);
- desktop->updateNow();
- } else {
- selection->set(item_clicked);
- desktop->updateNow();
- }
-
- ret = TRUE;
- }
- break;
- }
- break;
- case GDK_BUTTON_PRESS:
- if (event->button.button == 1 && !(event->button.state & GDK_SHIFT_MASK)) {
- // save drag origin
- event_context->xp = (gint) event->button.x;
- event_context->yp = (gint) event->button.y;
- event_context->within_tolerance = true;
- nc->shape_editor->cancel_hit();
-
- if (!nc->drag) {
- // find out if we're over the selected item, disregarding groups
- SPItem *item_over = sp_event_context_over_item (desktop, selection->singleItem(),
- NR::Point(event->button.x, event->button.y));
-
- if (nc->shape_editor->has_nodepath() && selection->single() && item_over) {
-
- // save drag origin
- bool over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), true);
- //only dragging curves
- if (over_stroke) {
- ret = TRUE;
- } else {
- break;
- }
- } else {
- break;
- }
-
- ret = TRUE;
- }
- break;
+ if (prefs_get_int_attribute ("tools.nodes", "pathflash_enabled", 0) == 1) {
+ guint timeout = prefs_get_int_attribute("tools.nodes", "pathflash_timeout", 500);
+ if (SP_IS_LPE_ITEM(item)) {
+ Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item));
+ if (lpe && (lpe->providesOwnFlashPaths() ||
+ lpe->pathFlashType() == Inkscape::LivePathEffect::SUPPRESS_FLASH)) {
+ // path should be suppressed or permanent; this is handled in
+ // sp_node_context_selection_changed()
+ return ret;
}
- break;
- default:
- break;
+ }
+ sp_node_context_flash_path(event_context, item, timeout);
}
- if (!ret) {
- if (((SPEventContextClass *) parent_class)->item_handler)
- ret = ((SPEventContextClass *) parent_class)->item_handler(event_context, item, event);
- }
+ if (((SPEventContextClass *) parent_class)->item_handler)
+ ret = ((SPEventContextClass *) parent_class)->item_handler(event_context, item, event);
return ret;
}
int const snaps = prefs_get_int_attribute("options.rotationsnapsperpi", "value", 12);
double const offset = prefs_get_double_attribute_limited("options.defaultscale", "value", 2, 0, 1000);
- gint ret = FALSE;
+ if ( (nc->flash_tempitem) && (nc->remove_flash_counter <= 0) ) {
+ desktop->remove_temporary_canvasitem(nc->flash_tempitem);
+ nc->flash_tempitem = NULL;
+ nc->flashed_item = NULL; // also reset this one, so the next time the same object is hovered over it shows again the highlight
+ } else {
+ nc->remove_flash_counter--;
+ }
+ gint ret = FALSE;
switch (event->type) {
case GDK_BUTTON_PRESS:
- if (event->button.button == 1) {
+ if (event->button.button == 1 && !event_context->space_panning) {
// save drag origin
event_context->xp = (gint) event->button.x;
event_context->yp = (gint) event->button.y;
event_context->within_tolerance = true;
nc->shape_editor->cancel_hit();
+ if (!(event->button.state & GDK_SHIFT_MASK)) {
+ if (!nc->drag) {
+ if (nc->shape_editor->has_nodepath() && selection->single() /* && item_over */) {
+ // save drag origin
+ bool over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), true);
+ //only dragging curves
+ if (over_stroke) {
+ ret = TRUE;
+ break;
+ }
+ }
+ }
+ }
NR::Point const button_w(event->button.x,
event->button.y);
NR::Point const button_dt(desktop->w2d(button_w));
}
break;
case GDK_MOTION_NOTIFY:
- if (event->motion.state & GDK_BUTTON1_MASK) {
+ if (event->motion.state & GDK_BUTTON1_MASK && !event_context->space_panning) {
if ( event_context->within_tolerance
&& ( abs( (gint) event->motion.x - event_context->xp ) < event_context->tolerance )
break;
}
- SPItem *item_over = sp_event_context_over_item (desktop, selection->singleItem(),
- NR::Point(event->motion.x, event->motion.y));
bool over_stroke = false;
- if (item_over && nc->shape_editor->has_nodepath()) {
- over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->motion.x, event->motion.y), false);
- }
+ over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->motion.x, event->motion.y), false);
if (nc->cursor_drag && !over_stroke) {
event_context->cursor_shape = cursor_node_xpm;
}
}
break;
+
+ case GDK_2BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
- event_context->xp = event_context->yp = 0;
- if (event->button.button == 1) {
-
- NR::Maybe<NR::Rect> b = Inkscape::Rubberband::get()->getRectangle();
-
- if (nc->shape_editor->hits_curve() && !event_context->within_tolerance) { //drag curve
- nc->shape_editor->finish_drag();
- } else if (b && !event_context->within_tolerance) { // drag to select
- nc->shape_editor->select_rect(*b, event->button.state & GDK_SHIFT_MASK);
- } else {
- if (!(nc->rb_escaped)) { // unless something was cancelled
- if (nc->shape_editor->has_selection())
- nc->shape_editor->deselect();
- else
- sp_desktop_selection(desktop)->clear();
+ if ( (event->button.button == 1) && (!nc->drag) && !event_context->space_panning) {
+ // find out clicked item, disregarding groups, honoring Alt
+ SPItem *item_clicked = sp_event_context_find_item (desktop,
+ NR::Point(event->button.x, event->button.y),
+ (event->button.state & GDK_MOD1_MASK) && !(event->button.state & GDK_CONTROL_MASK), TRUE);
+
+ event_context->xp = event_context->yp = 0;
+
+ bool over_stroke = false;
+ if (nc->shape_editor->has_nodepath()) {
+ over_stroke = nc->shape_editor->is_over_stroke(NR::Point(event->button.x, event->button.y), false);
+ }
+
+ if (item_clicked || over_stroke) {
+ if (over_stroke || nc->added_node) {
+ switch (event->type) {
+ case GDK_BUTTON_RELEASE:
+ if (event->button.state & GDK_CONTROL_MASK && event->button.state & GDK_MOD1_MASK) {
+ //add a node
+ nc->shape_editor->add_node_near_point();
+ } else {
+ if (nc->added_node) { // we just received double click, ignore release
+ nc->added_node = false;
+ break;
+ }
+ //select the segment
+ if (event->button.state & GDK_SHIFT_MASK) {
+ nc->shape_editor->select_segment_near_point(true);
+ } else {
+ nc->shape_editor->select_segment_near_point(false);
+ }
+ desktop->updateNow();
+ }
+ break;
+ case GDK_2BUTTON_PRESS:
+ //add a node
+ nc->shape_editor->add_node_near_point();
+ nc->added_node = true;
+ break;
+ default:
+ break;
+ }
+ } else if (event->button.state & GDK_SHIFT_MASK) {
+ selection->toggle(item_clicked);
+ desktop->updateNow();
+ } else {
+ selection->set(item_clicked);
+ desktop->updateNow();
}
+ Inkscape::Rubberband::get()->stop();
+ ret = TRUE;
+ break;
+ }
+ }
+ if (event->type == GDK_BUTTON_RELEASE) {
+ event_context->xp = event_context->yp = 0;
+ if (event->button.button == 1) {
+ boost::optional<NR::Rect> b = Inkscape::Rubberband::get()->getRectangle();
+
+ if (nc->shape_editor->hits_curve() && !event_context->within_tolerance) { //drag curve
+ nc->shape_editor->finish_drag();
+ } else if (b && !event_context->within_tolerance) { // drag to select
+ nc->shape_editor->select_rect(*b, event->button.state & GDK_SHIFT_MASK);
+ } else {
+ if (!(nc->rb_escaped)) { // unless something was cancelled
+ if (nc->shape_editor->has_selection())
+ nc->shape_editor->deselect();
+ else
+ sp_desktop_selection(desktop)->clear();
+ }
+ }
+ ret = TRUE;
+ Inkscape::Rubberband::get()->stop();
+ desktop->updateNow();
+ nc->rb_escaped = false;
+ nc->drag = FALSE;
+ nc->shape_editor->cancel_hit();
+ nc->current_state = SP_NODE_CONTEXT_INACTIVE;
}
- ret = TRUE;
- Inkscape::Rubberband::get()->stop();
- desktop->updateNow();
- nc->rb_escaped = false;
- nc->drag = FALSE;
- nc->shape_editor->cancel_hit();
- nc->current_state = SP_NODE_CONTEXT_INACTIVE;
- break;
}
break;
case GDK_KEY_PRESS:
ret = TRUE;
}
break;
+ case GDK_x:
+ case GDK_X:
+ if (MOD__ALT_ONLY) {
+ desktop->setToolboxFocusTo ("altx-nodes");
+ ret = TRUE;
+ }
+ break;
case GDK_Left: // move selection left
case GDK_KP_Left:
case GDK_KP_4:
if (!MOD__CTRL) { // not ctrl
+ gint mul = 1 + gobble_key_events(
+ get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT) { // alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(-10, 0); // shift
- else nc->shape_editor->move_nodes_screen(-1, 0); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(mul*-10, 0); // shift
+ else nc->shape_editor->move_nodes_screen(mul*-1, 0); // no shift
}
else { // no alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes(-10*nudge, 0); // shift
- else nc->shape_editor->move_nodes(-nudge, 0); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes(mul*-10*nudge, 0); // shift
+ else nc->shape_editor->move_nodes(mul*-nudge, 0); // no shift
}
ret = TRUE;
}
case GDK_KP_Up:
case GDK_KP_8:
if (!MOD__CTRL) { // not ctrl
+ gint mul = 1 + gobble_key_events(
+ get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT) { // alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(0, 10); // shift
- else nc->shape_editor->move_nodes_screen(0, 1); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(0, mul*10); // shift
+ else nc->shape_editor->move_nodes_screen(0, mul*1); // no shift
}
else { // no alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes(0, 10*nudge); // shift
- else nc->shape_editor->move_nodes(0, nudge); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes(0, mul*10*nudge); // shift
+ else nc->shape_editor->move_nodes(0, mul*nudge); // no shift
}
ret = TRUE;
}
case GDK_KP_Right:
case GDK_KP_6:
if (!MOD__CTRL) { // not ctrl
+ gint mul = 1 + gobble_key_events(
+ get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT) { // alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(10, 0); // shift
- else nc->shape_editor->move_nodes_screen(1, 0); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(mul*10, 0); // shift
+ else nc->shape_editor->move_nodes_screen(mul*1, 0); // no shift
}
else { // no alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes(10*nudge, 0); // shift
- else nc->shape_editor->move_nodes(nudge, 0); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes(mul*10*nudge, 0); // shift
+ else nc->shape_editor->move_nodes(mul*nudge, 0); // no shift
}
ret = TRUE;
}
case GDK_KP_Down:
case GDK_KP_2:
if (!MOD__CTRL) { // not ctrl
+ gint mul = 1 + gobble_key_events(
+ get_group0_keyval(&event->key), 0); // with any mask
if (MOD__ALT) { // alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(0, -10); // shift
- else nc->shape_editor->move_nodes_screen(0, -1); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes_screen(0, mul*-10); // shift
+ else nc->shape_editor->move_nodes_screen(0, mul*-1); // no shift
}
else { // no alt
- if (MOD__SHIFT) nc->shape_editor->move_nodes(0, -10*nudge); // shift
- else nc->shape_editor->move_nodes(0, -nudge); // no shift
+ if (MOD__SHIFT) nc->shape_editor->move_nodes(0, mul*-10*nudge); // shift
+ else nc->shape_editor->move_nodes(0, mul*-nudge); // no shift
}
ret = TRUE;
}
break;
case GDK_Escape:
{
- NR::Maybe<NR::Rect> const b = Inkscape::Rubberband::get()->getRectangle();
+ boost::optional<NR::Rect> const b = Inkscape::Rubberband::get()->getRectangle();
if (b) {
Inkscape::Rubberband::get()->stop();
nc->current_state = SP_NODE_CONTEXT_INACTIVE;