From: Krzysztof KosiƄski Date: Thu, 14 Jan 2010 08:42:20 +0000 (+0100) Subject: Implement segment weld to make segment join similar to node join X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=288519e6a6826169154ca9f49d8863e04b87358b;p=inkscape.git Implement segment weld to make segment join similar to node join --- diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 2cc9bc97b..3ae7e4d24 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -304,15 +304,10 @@ void MultiPathManipulator::deleteNodes(bool keep_shape) } /** Join selected endpoints to create segments. */ -void MultiPathManipulator::joinSegment() +void MultiPathManipulator::joinSegments() { IterPairList joins; find_join_iterators(_selection, joins); - if (joins.empty()) { - _desktop->messageStack()->flash(Inkscape::WARNING_MESSAGE, - _("There must be at least 2 endnodes in selection")); - return; - } for (IterPairList::iterator i = joins.begin(); i != joins.end(); ++i) { bool same_path = prepare_join(*i); @@ -328,6 +323,9 @@ void MultiPathManipulator::joinSegment() } } + if (joins.empty()) { + invokeForAll(&PathManipulator::weldSegments); + } _doneWithCleanup("Join segments"); } @@ -421,7 +419,7 @@ bool MultiPathManipulator::event(GdkEvent *event) return true; } if (held_only_alt(event->key)) { - joinSegment(); + joinSegments(); return true; } break; diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index 46ad3a8d2..151e153ec 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -55,7 +55,7 @@ public: void joinNodes(); void breakNodes(); void deleteNodes(bool keep_shape = true); - void joinSegment(); + void joinSegments(); void deleteSegments(); void alignNodes(Geom::Dim2 d); void distributeNodes(Geom::Dim2 d); diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index cfa3846f8..9889eb787 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -317,19 +317,21 @@ void PathManipulator::weldNodes(NodeList::iterator preserve_pos) } // Start from unselected node in closed paths, so that we don't start in the middle - // of a contiguous selection + // of a selection NodeList::iterator sel_beg = sp->begin(), sel_end; if (sp->closed()) { while (sel_beg->selected()) ++sel_beg; } - // Main loop + // Work loop while (num_selected > 0) { // Find selected node while (sel_beg && !sel_beg->selected()) sel_beg = sel_beg.next(); if (!sel_beg) throw std::logic_error("Join nodes: end of open path reached, " "but there are still nodes to process!"); + // note: this is initialized to zero, because the loop below counts sel_beg as well + // the loop conditions are simpler that way unsigned num_points = 0; bool use_pos = false; Geom::Point back_pos, front_pos; @@ -373,7 +375,57 @@ void PathManipulator::weldNodes(NodeList::iterator preserve_pos) /** Remove nodes in the middle of selected segments. */ void PathManipulator::weldSegments() { - // TODO + if (!_num_selected) return; + _dragpoint->setVisible(false); + + for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { + SubpathPtr sp = *i; + unsigned num_selected = 0, num_unselected = 0; + for (NodeList::iterator j = sp->begin(); j != sp->end(); ++j) { + if (j->selected()) ++num_selected; + else ++num_unselected; + } + if (num_selected < 3) continue; + if (num_unselected == 0 && sp->closed()) { + // if all nodes in a closed subpath are selected, the operation doesn't make much sense + continue; + } + + // Start from unselected node in closed paths, so that we don't start in the middle + // of a selection + NodeList::iterator sel_beg = sp->begin(), sel_end; + if (sp->closed()) { + while (sel_beg->selected()) ++sel_beg; + } + + // Work loop + while (num_selected > 0) { + // Find selected node + while (sel_beg && !sel_beg->selected()) sel_beg = sel_beg.next(); + if (!sel_beg) throw std::logic_error("Join nodes: end of open path reached, " + "but there are still nodes to process!"); + + // note: this is initialized to zero, because the loop below counts sel_beg as well + // the loop conditions are simpler that way + unsigned num_points = 0; + + // find the end of selected segment + for (sel_end = sel_beg; sel_end && sel_end->selected(); sel_end = sel_end.next()) { + ++num_points; + } + if (num_points > 2) { + // remove nodes in the middle + sel_beg = sel_beg.next(); + while (sel_beg != sel_end.prev()) { + NodeList::iterator next = sel_beg.next(); + sp->erase(sel_beg); + sel_beg = next; + } + sel_beg = sel_end; + } + num_selected -= num_points; + } + } } /** Break the subpath at selected nodes. It also works for single node closed paths. */ diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index bb13bfdad..e3d309c47 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -1061,7 +1061,7 @@ void sp_node_path_edit_join_segment(void) { InkNodeTool *nt = get_node_tool(); - if (nt) nt->_multipath->joinSegment(); + if (nt) nt->_multipath->joinSegments(); } void