summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: e292128)
raw | patch | inline | side by side (parent: e292128)
author | cilix42 <cilix42@users.sourceforge.net> | |
Wed, 5 Dec 2007 04:09:29 +0000 (04:09 +0000) | ||
committer | cilix42 <cilix42@users.sourceforge.net> | |
Wed, 5 Dec 2007 04:09:29 +0000 (04:09 +0000) |
src/node-context.cpp | patch | blob | history | |
src/nodepath.cpp | patch | blob | history | |
src/nodepath.h | patch | blob | history | |
src/widgets/toolbox.cpp | patch | blob | history |
diff --git a/src/node-context.cpp b/src/node-context.cpp
index 3e7903227c3c11d01bb8de5f483b15551fd013f1..1cac6f164651829e88a97815a351daf962d3ea99 100644 (file)
--- a/src/node-context.cpp
+++ b/src/node-context.cpp
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:
diff --git a/src/nodepath.cpp b/src/nodepath.cpp
index 1239f961bc2f399f149b650b34f36bb5852dc4cd..4c0727d15fae3baf1c2fd69cc67b47713e53df3b 100644 (file)
--- a/src/nodepath.cpp
+++ b/src/nodepath.cpp
@@ -1372,6 +1372,50 @@ sp_node_selected_move_screen(Inkscape::NodePath::Path *nodepath, gdouble dx, gdo
}
}
+/**
+ * Move selected nodes to the absolute position given
+ */
+void sp_node_selected_move_absolute(Inkscape::NodePath::Path *nodepath, NR::Coord val, NR::Dim2 axis)
+{
+ for (GList *l = nodepath->selected; l != NULL; l = l->next) {
+ Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
+ NR::Point npos(axis == NR::X ? val : n->pos[NR::X], axis == NR::Y ? val : n->pos[NR::Y]);
+ sp_node_moveto(n, npos);
+ }
+
+ sp_nodepath_update_repr(nodepath, _("Move nodes"));
+}
+
+/**
+ * If the coordinates of all selected nodes coincide, return the common coordinate; otherwise return NR::Nothing
+ */
+NR::Maybe<NR::Coord> sp_node_selected_common_coord (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis)
+{
+ g_return_val_if_fail(nodepath->selected, NR::Nothing());
+
+ // determine coordinate of first selected node
+ GList *nsel = nodepath->selected;
+ Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) nsel->data;
+ NR::Coord coord = n->pos[axis];
+ bool coincide = true;
+
+ // compare it to the coordinates of all the other selected nodes
+ for (GList *l = nsel->next; l != NULL; l = l->next) {
+ n = (Inkscape::NodePath::Node *) l->data;
+ if (n->pos[axis] != coord) {
+ coincide = false;
+ }
+ }
+ if (coincide) {
+ return coord;
+ } else {
+ NR::Rect bbox = sp_node_selected_bbox(nodepath);
+ // currently we return the coordinate of the bounding box midpoint because I don't know how
+ // to erase the spin button entry field :), but maybe this can be useful behaviour anyway
+ return bbox.midpoint()[axis];
+ }
+}
+
/** If they don't yet exist, creates knot and line for the given side of the node */
static void sp_node_ensure_knot_exists (SPDesktop *desktop, Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeSide *side)
{
@@ -3933,13 +3977,7 @@ void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis, NR::Ma
} else {
// scale nodes as an "object":
- Inkscape::NodePath::Node *n0 = (Inkscape::NodePath::Node *) nodepath->selected->data;
- NR::Rect box (n0->pos, n0->pos); // originally includes the first selected node
- for (GList *l = nodepath->selected; l != NULL; l = l->next) {
- Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
- box.expandTo (n->pos); // contain all selected nodes
- }
-
+ NR::Rect box = sp_node_selected_bbox (nodepath);
if (!center) {
center = box.midpoint();
}
@@ -3960,6 +3998,19 @@ void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis, NR::Ma
sp_nodepath_update_repr(nodepath, _("Flip nodes"));
}
+NR::Rect sp_node_selected_bbox (Inkscape::NodePath::Path *nodepath)
+{
+ g_assert (nodepath->selected);
+
+ Inkscape::NodePath::Node *n0 = (Inkscape::NodePath::Node *) nodepath->selected->data;
+ NR::Rect box (n0->pos, n0->pos); // originally includes the first selected node
+ for (GList *l = nodepath->selected; l != NULL; l = l->next) {
+ Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
+ box.expandTo (n->pos); // contain all selected nodes
+ }
+ return box;
+}
+
//-----------------------------------------------
/**
* Return new subpath under given nodepath.
@@ -4392,6 +4443,8 @@ sp_nodepath_update_statusbar(Inkscape::NodePath::Path *nodepath)//!!!move to Sha
Inkscape::MessageContext *mc = SP_NODE_CONTEXT (ec)->_node_message_context;
if (!mc) return;
+ inkscape_active_desktop()->emitToolSubselectionChanged(NULL);
+
if (selected_nodes == 0) {
Inkscape::Selection *sel = desktop->selection;
if (!sel || sel->isEmpty()) {
diff --git a/src/nodepath.h b/src/nodepath.h
index ee828f4aca4d245a4a955c6b45e77c607b1f1de6..8f17ecb14b966a76596abfb54120f7912cf53dd1 100644 (file)
--- a/src/nodepath.h
+++ b/src/nodepath.h
@@ -302,6 +302,9 @@ void sp_node_selected_set_type (Inkscape::NodePath::Path *nodepath, Inkscape::No
void sp_node_selected_set_line_type (Inkscape::NodePath::Path *nodepath, NRPathcode code);
void sp_node_selected_move (Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy);
void sp_node_selected_move_screen (Inkscape::NodePath::Path *nodepath, gdouble dx, gdouble dy);
+void sp_node_selected_move_absolute (Inkscape::NodePath::Path *nodepath, NR::Coord val, NR::Dim2 axis);
+NR::Rect sp_node_selected_bbox (Inkscape::NodePath::Path *nodepath);
+NR::Maybe<NR::Coord> sp_node_selected_common_coord (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis);
void sp_nodepath_show_handles(Inkscape::NodePath::Path *nodepath, bool show);
index 3609a48dd981ff6c1b92e33c1b803532699b707f..a4d24203f95bfae6fe2ab1f8adba82ba69379c5b 100644 (file)
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
" <toolitem action='StrokeToPath' />"
" <separator />"
" <toolitem action='NodesShowHandlesAction' />"
+ " <separator />"
+ " <toolitem action='NodeXAction' />"
+ " <toolitem action='NodeYAction' />"
" </toolbar>"
" <toolbar name='TweakToolbar'>"
return hb;
}
+static EgeAdjustmentAction * create_adjustment_action( gchar const *name,
+ gchar const *label, gchar const *shortLabel, gchar const *tooltip,
+ gchar const *path, gchar const *data, gdouble def,
+ GtkWidget *focusTarget,
+ GtkWidget *us,
+ GObject *dataKludge,
+ gboolean altx, gchar const *altx_mark,
+ gdouble lower, gdouble upper, gdouble step, gdouble page,
+ gchar const** descrLabels, gdouble const* descrValues, guint descrCount,
+ void (*callback)(GtkAdjustment *, GObject *),
+ gdouble climb = 0.1, guint digits = 3, double factor = 1.0 )
+{
+ GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( prefs_get_double_attribute(path, data, def) * factor,
+ lower, upper, step, page, page ) );
+ if (us) {
+ sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us), adj );
+ }
+
+ gtk_signal_connect( GTK_OBJECT(adj), "value-changed", GTK_SIGNAL_FUNC(callback), dataKludge );
+
+ EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits );
+ if ( shortLabel ) {
+ g_object_set( act, "short_label", shortLabel, NULL );
+ }
+
+ if ( (descrCount > 0) && descrLabels && descrValues ) {
+ ege_adjustment_action_set_descriptions( act, descrLabels, descrValues, descrCount );
+ }
+
+ if ( focusTarget ) {
+ ege_adjustment_action_set_focuswidget( act, focusTarget );
+ }
+
+ if ( altx && altx_mark ) {
+ g_object_set( G_OBJECT(act), "self-id", altx_mark, NULL );
+ }
+
+ if ( dataKludge ) {
+ g_object_set_data( dataKludge, data, adj );
+ }
+
+ // Using a cast just to make sure we pass in the right kind of function pointer
+ g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL );
+
+ return act;
+}
+
//####################################
//# node editing callbacks
if (shape_editor) shape_editor->show_handles(show);
}
+/* is called when the node selection is modified */
+static void
+sp_node_toolbox_coord_changed(gpointer /*shape_editor*/, GObject *tbl)
+{
+ GtkAction* xact = GTK_ACTION( g_object_get_data( tbl, "nodes_x_action" ) );
+ GtkAction* yact = GTK_ACTION( g_object_get_data( tbl, "nodes_y_action" ) );
+ GtkAdjustment *xadj = ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION(xact));
+ GtkAdjustment *yadj = ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION(yact));
+
+ // quit if run by the attr_changed listener
+ if (g_object_get_data( tbl, "freeze" )) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
+
+ ShapeEditor *shape_editor = get_current_shape_editor();
+ if (shape_editor && shape_editor->has_nodepath()) {
+ Inkscape::NodePath::Path *nodepath = shape_editor->get_nodepath();
+ int n_selected = 0;
+ if (nodepath) {
+ n_selected = nodepath->numSelected();
+ }
+
+ if (n_selected == 0) {
+ gtk_action_set_sensitive(xact, FALSE);
+ gtk_action_set_sensitive(yact, FALSE);
+ } else {
+ gtk_action_set_sensitive(xact, TRUE);
+ gtk_action_set_sensitive(yact, TRUE);
+ NR::Coord oldx = gtk_adjustment_get_value(xadj);
+ NR::Coord oldy = gtk_adjustment_get_value(xadj);
+
+ if (n_selected == 1) {
+ NR::Point sel_node = nodepath->singleSelectedCoords();
+ if (oldx != sel_node[NR::X] || oldy != sel_node[NR::Y]) {
+ gtk_adjustment_set_value(xadj, sel_node[NR::X]);
+ gtk_adjustment_set_value(yadj, sel_node[NR::Y]);
+ }
+ } else {
+ NR::Maybe<NR::Coord> x = sp_node_selected_common_coord(nodepath, NR::X);
+ NR::Maybe<NR::Coord> y = sp_node_selected_common_coord(nodepath, NR::Y);
+ if ((x && ((*x) != oldx)) || (y && ((*y) != oldy))) {
+ /* Note: Currently x and y will always have a value, even if the coordinates of the
+ selected nodes don't coincide (in this case we use the coordinates of the center
+ of the bounding box). So the entries are never set to zero. */
+ gtk_adjustment_set_value(xadj, x ? (*x) : 0.0); // FIXME: Maybe we should clear the entry
+ gtk_adjustment_set_value(yadj, y ? (*y) : 0.0); // fields, not set them to zero.
+ }
+ }
+ }
+ }
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+static void
+sp_node_path_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const *value_name)
+{
+ // quit if run by the attr_changed listener
+ if (g_object_get_data( tbl, "freeze" )) {
+ return;
+ }
+
+ // in turn, prevent listener from responding
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE));
+
+ ShapeEditor *shape_editor = get_current_shape_editor();
+ if (shape_editor && shape_editor->has_nodepath()) {
+ if (!strcmp(value_name, "x")) {
+ sp_node_selected_move_absolute(shape_editor->get_nodepath(), gtk_adjustment_get_value(adj), NR::X);
+ }
+ if (!strcmp(value_name, "y")) {
+ sp_node_selected_move_absolute(shape_editor->get_nodepath(), gtk_adjustment_get_value(adj), NR::Y);
+ }
+ }
+
+ g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) );
+}
+
+static void
+sp_node_path_x_value_changed(GtkAdjustment *adj, GObject *tbl)
+{
+ sp_node_path_value_changed(adj, tbl, "x");
+}
+
+static void
+sp_node_path_y_value_changed(GtkAdjustment *adj, GObject *tbl)
+{
+ sp_node_path_value_changed(adj, tbl, "y");
+}
+
//################################
//## Node Editing Toolbox ##
//################################
-static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* /*holder*/)
+static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions, GObject* holder)
{
{
InkAction* inky = ink_action_new( "NodeInsertAction",
@@ -924,6 +1067,46 @@ static void sp_node_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions
gtk_toggle_action_set_active( GTK_TOGGLE_ACTION(act), prefs_get_int_attribute( "tools.nodes", "show_handles", 1 ) );
}
+ /* X coord of selected node(s) */
+ {
+ EgeAdjustmentAction* eact = 0;
+ gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
+ eact = create_adjustment_action( "NodeXAction",
+ _("X coordinate:"), _("X:"), _("X coordinate of selected node(s)"),
+ "tools.nodes", "Xcoord", 0,
+ GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, "altx-nodes",
+ -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_node_path_x_value_changed );
+ g_object_set_data( holder, "nodes_x_action", eact );
+ gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ }
+
+ /* Y coord of selected node(s) */
+ {
+ EgeAdjustmentAction* eact = 0;
+ gchar const* labels[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+ gdouble values[] = {1, 2, 3, 5, 10, 20, 50, 100, 200, 500};
+ eact = create_adjustment_action( "NodeYAction",
+ _("Y coordinate:"), _("Y:"), _("Y coordinate of selected node(s)"),
+ "tools.nodes", "Ycoord", 0,
+ GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, FALSE, NULL,
+ -1e6, 1e6, SPIN_STEP, SPIN_PAGE_STEP,
+ labels, values, G_N_ELEMENTS(labels),
+ sp_node_path_y_value_changed );
+ g_object_set_data( holder, "nodes_y_action", eact );
+ gtk_action_set_sensitive( GTK_ACTION(eact), FALSE );
+ gtk_action_group_add_action( mainActions, GTK_ACTION(eact) );
+ }
+
+ sigc::connection *connection = new sigc::connection (
+ desktop->connectToolSubselectionChanged(sigc::bind (sigc::ptr_fun(sp_node_toolbox_coord_changed), (GObject *)holder))
+ );
+
+ g_signal_connect( holder, "destroy", G_CALLBACK(delete_connection), connection );
+ g_signal_connect( holder, "destroy", G_CALLBACK(purge_repr_listener), holder );
} // end of sp_node_toolbox_prep()
return hb;
}
-static EgeAdjustmentAction * create_adjustment_action( gchar const *name,
- gchar const *label, gchar const *shortLabel, gchar const *tooltip,
- gchar const *path, gchar const *data, gdouble def,
- GtkWidget *focusTarget,
- GtkWidget *us,
- GObject *dataKludge,
- gboolean altx, gchar const *altx_mark,
- gdouble lower, gdouble upper, gdouble step, gdouble page,
- gchar const** descrLabels, gdouble const* descrValues, guint descrCount,
- void (*callback)(GtkAdjustment *, GObject *),
- gdouble climb = 0.1, guint digits = 3, double factor = 1.0 )
-{
- GtkAdjustment* adj = GTK_ADJUSTMENT( gtk_adjustment_new( prefs_get_double_attribute(path, data, def) * factor,
- lower, upper, step, page, page ) );
- if (us) {
- sp_unit_selector_add_adjustment( SP_UNIT_SELECTOR(us), adj );
- }
-
- gtk_signal_connect( GTK_OBJECT(adj), "value-changed", GTK_SIGNAL_FUNC(callback), dataKludge );
-
- EgeAdjustmentAction* act = ege_adjustment_action_new( adj, name, label, tooltip, 0, climb, digits );
- if ( shortLabel ) {
- g_object_set( act, "short_label", shortLabel, NULL );
- }
-
- if ( (descrCount > 0) && descrLabels && descrValues ) {
- ege_adjustment_action_set_descriptions( act, descrLabels, descrValues, descrCount );
- }
-
- if ( focusTarget ) {
- ege_adjustment_action_set_focuswidget( act, focusTarget );
- }
-
- if ( altx && altx_mark ) {
- g_object_set( G_OBJECT(act), "self-id", altx_mark, NULL );
- }
-
- if ( dataKludge ) {
- g_object_set_data( dataKludge, data, adj );
- }
-
- // Using a cast just to make sure we pass in the right kind of function pointer
- g_object_set( G_OBJECT(act), "tool-post", static_cast<EgeWidgetFixup>(sp_set_font_size_smaller), NULL );
-
- return act;
-}
-
-
#define MODE_LABEL_WIDTH 70
//########################