# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: sambut1987@gmail.com-20111117164331-x7gmnyuljvyz23et # target_branch: lp:inkscape # testament_sha1: 42463875bda5fc45e7b02bbbfc35af6809bde58a # timestamp: 2011-11-17 17:48:51 +0100 # base_revision_id: tweenk.pl@gmail.com-20111114184711-\ # a1usfp9ysevugprv # # Begin patch === modified file 'src/ui/dialog/align-and-distribute.cpp' --- src/ui/dialog/align-and-distribute.cpp 2011-10-18 05:54:57 +0000 +++ src/ui/dialog/align-and-distribute.cpp 2011-11-17 16:43:31 +0000 @@ -40,7 +40,6 @@ #include "tools-switch.h" #include "ui/icon-names.h" #include "ui/tool/node-tool.h" -#include "ui/tool/multi-path-manipulator.h" #include "util/glib-list-iterators.h" #include "verbs.h" #include "widgets/icon.h" @@ -76,7 +75,7 @@ pButton->signal_clicked() .connect(sigc::mem_fun(*this, &Action::on_button_click)); tooltips.set_tip(*pButton, tiptext); - parent.attach(*pButton, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL); + _parent.attach(*pButton, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL); } virtual ~Action(){} @@ -199,7 +198,7 @@ g_assert_not_reached (); break; }; // end of switch - + // Top hack: temporarily set clone compensation to unmoved, so that we can align/distribute // clones with their original (and the move of the original does not disturb the // clones). The only problem with this is that if there are outside-of-selection clones of @@ -417,9 +416,9 @@ const Glib::ustring &tiptext, guint column, AlignAndDistribute &dialog, - Geom::Dim2 orientation, bool distribute): + Geom::Dim2 orientation, bool distribute, Gtk::Table &parent): Action(id, tiptext, 0, column, - dialog.nodes_table(), dialog.tooltips(), dialog), + parent, dialog.tooltips(), dialog), _orientation(orientation), _distribute(distribute) {} @@ -438,8 +437,7 @@ if (_distribute) nt->_multipath->distributeNodes(_orientation); else - nt->_multipath->alignNodes(_orientation); - + nt->_multipath->alignNodes(_orientation, _dialog.getNodeAlignTarget()); } }; @@ -893,13 +891,16 @@ _distributeFrame(_("Distribute")), _rearrangeFrame(_("Rearrange")), _removeOverlapFrame(_("Remove overlaps")), - _nodesFrame(_("Nodes")), + _nodesAlignFrame(_("Align Nodes")), + _nodesDistributeFrame(_("Distribute Nodes")), _alignTable(2, 6, true), _distributeTable(2, 6, true), _rearrangeTable(1, 5, false), _removeOverlapTable(1, 5, false), - _nodesTable(1, 4, true), + _nodesAlignTable(1, 2, true), + _nodesDistributeTable(1, 2, true), _anchorLabel(_("Relative to: ")), + _node_anchorLabel(_("Relative to: ")), _selgrpLabel(_("_Treat selection as group: "), 1) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1015,16 +1016,16 @@ // There is no doubt some ambiguity. For this reason the descriptions are different. addNodeButton(INKSCAPE_ICON("align-vertical-node"), _("Align selected nodes to a common horizontal line"), - 0, Geom::X, false); + 0, Geom::X, false, nodes_align_table()); addNodeButton(INKSCAPE_ICON("align-horizontal-node"), _("Align selected nodes to a common vertical line"), - 1, Geom::Y, false); + 1, Geom::Y, false, nodes_align_table()); addNodeButton(INKSCAPE_ICON("distribute-horizontal-node"), _("Distribute selected nodes horizontally"), - 2, Geom::X, true); + 0, Geom::X, true, nodes_distribute_table()); addNodeButton(INKSCAPE_ICON("distribute-vertical-node"), _("Distribute selected nodes vertically"), - 3, Geom::Y, true); + 1, Geom::Y, true, nodes_distribute_table()); //Rest of the widgetry @@ -1038,10 +1039,22 @@ _combo.set_active(prefs->getInt("/dialogs/align/align-to", 6)); _combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change)); - + _anchorBox.pack_start(_anchorLabel); _anchorBox.pack_start(_combo); + _node_anchor_combo.append_text(_("Top Node")); + _node_anchor_combo.append_text(_("Bottom Node")); + _node_anchor_combo.append_text(_("Left Most Node")); + _node_anchor_combo.append_text(_("Right Most Node")); + _node_anchor_combo.append_text(_("Average")); + + _node_anchor_combo.set_active(prefs->getInt("/dialogs/align/align-to-node", 4)); + _node_anchor_combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_node_ref_change)); + + _node_anchorBox.pack_start(_node_anchorLabel); + _node_anchorBox.pack_start(_node_anchor_combo); + _selgrpLabel.set_mnemonic_widget(_selgrp); _selgrpBox.pack_start(_selgrpLabel); _selgrpBox.pack_start(_selgrp); @@ -1051,12 +1064,17 @@ _alignBox.pack_start(_anchorBox); _alignBox.pack_start(_selgrpBox); _alignBox.pack_start(_alignTable); + + _node_alignBox.pack_start(_node_anchorBox); + _node_alignBox.pack_start(_nodesAlignTable); + _node_distributeBox.pack_start(_nodesDistributeTable); _alignFrame.add(_alignBox); _distributeFrame.add(_distributeTable); _rearrangeFrame.add(_rearrangeTable); _removeOverlapFrame.add(_removeOverlapTable); - _nodesFrame.add(_nodesTable); + _nodesAlignFrame.add(_node_alignBox); + _nodesDistributeFrame.add(_node_distributeBox); Gtk::Box *contents = _getContents(); contents->set_spacing(4); @@ -1067,7 +1085,8 @@ contents->pack_start(_distributeFrame, true, true); contents->pack_start(_rearrangeFrame, true, true); contents->pack_start(_removeOverlapFrame, true, true); - contents->pack_start(_nodesFrame, true, true); + contents->pack_start(_nodesAlignFrame, true, true); + contents->pack_start(_nodesDistributeFrame, true, true); //Connect to the global tool change signal g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this); @@ -1091,6 +1110,7 @@ delete *it; } + void AlignAndDistribute::on_ref_change(){ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/dialogs/align/align-to", _combo.get_active_row_number()); @@ -1098,6 +1118,13 @@ //Make blink the master } +void AlignAndDistribute::on_node_ref_change(){ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/dialogs/align/align-to-node", _node_anchor_combo.get_active_row_number()); + + //Make blink the master +} + void AlignAndDistribute::on_selgrp_toggled(){ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setInt("/dialogs/align/sel-as-groups", _selgrp.get_active()); @@ -1123,7 +1150,8 @@ ((_distributeFrame).*(mSel))(); ((_rearrangeFrame).*(mSel))(); ((_removeOverlapFrame).*(mSel))(); - ((_nodesFrame).*(mNode))(); + ((_nodesAlignFrame).*(mNode))(); + ((_nodesDistributeFrame).*(mNode))(); } void AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext, @@ -1148,12 +1176,12 @@ } void AlignAndDistribute::addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext, - guint col, Geom::Dim2 orientation, bool distribute) + guint col, Geom::Dim2 orientation, bool distribute, Gtk::Table &parent) { _actionList.push_back( new ActionNode( id, tiptext, col, - *this, orientation, distribute)); + *this, orientation, distribute, parent)); } void AlignAndDistribute::addRemoveOverlapsButton(const Glib::ustring &id, const Glib::ustring tiptext, @@ -1288,7 +1316,19 @@ return AlignTarget(_combo.get_active_row_number()); } +MultiPathManipulator::TargetMode AlignAndDistribute::getNodeAlignTarget() { + + switch (NodeAlignTarget(_node_anchor_combo.get_active_row_number())) + { + case AlignAndDistribute::TOP: return MultiPathManipulator::TOP; break; + case AlignAndDistribute::BOTTOM: return MultiPathManipulator::BOTTOM; break; + case AlignAndDistribute::RIGHT: return MultiPathManipulator::RIGHT; break; + case AlignAndDistribute::LEFT: return MultiPathManipulator::LEFT; break; + case AlignAndDistribute::AVERAGE: return MultiPathManipulator::AVERAGE; break; + default: return MultiPathManipulator::AVERAGE; break; + } +} } // namespace Dialog } // namespace UI === modified file 'src/ui/dialog/align-and-distribute.h' --- src/ui/dialog/align-and-distribute.h 2011-08-27 16:05:32 +0000 +++ src/ui/dialog/align-and-distribute.h 2011-11-17 16:43:31 +0000 @@ -26,6 +26,7 @@ #include #include +#include "ui/tool/multi-path-manipulator.h" #include "ui/widget/panel.h" #include "ui/widget/notebook-page.h" @@ -47,17 +48,21 @@ static AlignAndDistribute &getInstance() { return *new AlignAndDistribute(); } enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION }; - + enum NodeAlignTarget {TOP=0, BOTTOM, LEFT, RIGHT, AVERAGE }; + AlignTarget getAlignTarget() const; + MultiPathManipulator::TargetMode getNodeAlignTarget(); Gtk::Table &align_table(){return _alignTable;} Gtk::Table &distribute_table(){return _distributeTable;} Gtk::Table &rearrange_table(){return _rearrangeTable;} Gtk::Table &removeOverlap_table(){return _removeOverlapTable;} - Gtk::Table &nodes_table(){return _nodesTable;} + Gtk::Table &nodes_align_table(){return _nodesAlignTable;} + Gtk::Table &nodes_distribute_table(){return _nodesDistributeTable;} Gtk::Tooltips &tooltips(){return _tooltips;} std::list::iterator find_master(std::list &list, bool horizontal); + void setMode(bool nodeEdit); Geom::OptRect randomize_bbox; @@ -66,13 +71,14 @@ void on_ref_change(); void on_selgrp_toggled(); + void on_node_ref_change(); void addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col, bool onInterSpace, Geom::Dim2 orientation, float kBegin, float kEnd); void addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col); void addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext, - guint col, Geom::Dim2 orientation, bool distribute); + guint col, Geom::Dim2 orientation, bool distribute, Gtk::Table &parent); void addRemoveOverlapsButton(const Glib::ustring &id, const Glib::ustring tiptext, guint row, guint col); @@ -96,15 +102,20 @@ guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute); std::list _actionList; - Gtk::Frame _alignFrame, _distributeFrame, _rearrangeFrame, _removeOverlapFrame, _nodesFrame; - Gtk::Table _alignTable, _distributeTable, _rearrangeTable, _removeOverlapTable, _nodesTable; + Gtk::Frame _alignFrame, _distributeFrame, _rearrangeFrame, _removeOverlapFrame, _nodesAlignFrame, _nodesDistributeFrame; + Gtk::Table _alignTable, _distributeTable, _rearrangeTable, _removeOverlapTable, _nodesAlignTable, _nodesDistributeTable; Gtk::HBox _anchorBox; + Gtk::HBox _node_anchorBox; Gtk::HBox _selgrpBox; Gtk::VBox _alignBox; + Gtk::VBox _node_alignBox; + Gtk::VBox _node_distributeBox; Gtk::Label _anchorLabel; + Gtk::Label _node_anchorLabel; Gtk::Label _selgrpLabel; Gtk::CheckButton _selgrp; Gtk::ComboBoxText _combo; + Gtk::ComboBoxText _node_anchor_combo; Gtk::Tooltips _tooltips; private: === modified file 'src/ui/tool/control-point-selection.cpp' --- src/ui/tool/control-point-selection.cpp 2011-11-04 21:30:19 +0000 +++ src/ui/tool/control-point-selection.cpp 2011-11-17 16:43:31 +0000 @@ -182,17 +182,71 @@ } /** Align control points on the specified axis. */ -void ControlPointSelection::align(Geom::Dim2 axis) +void ControlPointSelection::align(Geom::Dim2 axis, MultiPathManipulator::TargetMode alignMode) { if (empty()) return; Geom::Dim2 d = static_cast((axis + 1) % 2); - Geom::OptInterval bound; + std::vectorcoordsVec; for (iterator i = _points.begin(); i != _points.end(); ++i) { - bound.unionWith(Geom::OptInterval((*i)->position()[d])); + Geom::Point nodePos = (*i)->position(); + nodePoint np; + np.x = nodePos[Geom::X]; + np.y = nodePos[Geom::Y]; + coordsVec.push_back(np); } - double new_coord = bound->middle(); + double new_coord = 0; + switch(alignMode) + { + case MultiPathManipulator::TOP: + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByY); + if (d==Geom::Y) + new_coord = coordsVec[coordsVec.size()-1].y; + else new_coord = coordsVec[coordsVec.size()-1].x; + break; + } + case MultiPathManipulator::BOTTOM: + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByY); + if (d==Geom::Y) + new_coord = coordsVec[0].y; + else new_coord = coordsVec[0].x; + break; + } + case MultiPathManipulator::LEFT: + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByX); + if (d==Geom::Y) + new_coord = coordsVec[coordsVec.size()-1].y; + else new_coord = coordsVec[coordsVec.size()-1].x; + break; + } + case MultiPathManipulator::RIGHT: + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByX); + if (d==Geom::Y) + new_coord = coordsVec[0].y; + else new_coord = coordsVec[0].x; + break; + } + case MultiPathManipulator::AVERAGE: + { + if (d==Geom::Y) + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByY); + new_coord = (coordsVec[0].y + coordsVec[coordsVec.size()-1].y)/2; + } + else + { + std::sort(coordsVec.begin(), coordsVec.end(), SortByX); + new_coord = (coordsVec[0].x + coordsVec[coordsVec.size()-1].x)/2; + } + break; + } + };//end switch + for (iterator i = _points.begin(); i != _points.end(); ++i) { Geom::Point pos = (*i)->position(); pos[d] = new_coord; === modified file 'src/ui/tool/control-point-selection.h' --- src/ui/tool/control-point-selection.h 2011-09-16 23:00:05 +0000 +++ src/ui/tool/control-point-selection.h 2011-11-17 16:43:31 +0000 @@ -23,6 +23,7 @@ #include "util/unordered-containers.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" +#include "multi-path-manipulator.h" #include "snap-candidate.h" class SPDesktop; @@ -51,6 +52,17 @@ typedef SelectableControlPoint *value_type; typedef SelectableControlPoint *key_type; + //store node coordinates for sorting + struct nodePoint { + double x, y; + }; + + static bool SortByX(nodePoint p1, nodePoint p2 ) + { return p1.x > p2.x; } + + static bool SortByY(nodePoint p1, nodePoint p2 ) + { return p1.y < p2.y; } + // size bool empty() { return _points.empty(); } size_type size() { return _points.size(); } @@ -93,7 +105,7 @@ virtual bool event(GdkEvent *); void transform(Geom::Affine const &m); - void align(Geom::Dim2 d); + void align(Geom::Dim2 axis, MultiPathManipulator::TargetMode alignMode); void distribute(Geom::Dim2 d); Geom::OptRect pointwiseBounds(); === modified file 'src/ui/tool/multi-path-manipulator.cpp' --- src/ui/tool/multi-path-manipulator.cpp 2011-11-05 23:46:09 +0000 +++ src/ui/tool/multi-path-manipulator.cpp 2011-11-17 16:43:31 +0000 @@ -452,9 +452,9 @@ _doneWithCleanup("Delete segments", true); } -void MultiPathManipulator::alignNodes(Geom::Dim2 d) +void MultiPathManipulator::alignNodes(Geom::Dim2 d, TargetMode alignMode) { - _selection.align(d); + _selection.align(d,alignMode); if (d == Geom::X) { _done("Align nodes to a horizontal line"); } else { === modified file 'src/ui/tool/multi-path-manipulator.h' --- src/ui/tool/multi-path-manipulator.h 2011-11-05 23:46:09 +0000 +++ src/ui/tool/multi-path-manipulator.h 2011-11-17 16:43:31 +0000 @@ -37,7 +37,8 @@ MultiPathManipulator(PathSharedData &data, sigc::connection &chg); virtual ~MultiPathManipulator(); virtual bool event(GdkEvent *event); - + enum TargetMode { TOP=0, BOTTOM, LEFT, RIGHT, AVERAGE }; + bool empty() { return _mmap.empty(); } unsigned size() { return _mmap.empty(); } void setItems(std::set const &); @@ -58,7 +59,7 @@ void deleteNodes(bool keep_shape = true); void joinSegments(); void deleteSegments(); - void alignNodes(Geom::Dim2 d); + void alignNodes(Geom::Dim2 d, TargetMode alignMode); void distributeNodes(Geom::Dim2 d); void reverseSubpaths(); void move(Geom::Point const &delta); # Begin bundle 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 D2etHoIYguNQbrAygkS4I/4u5IpwoSCs/eRi