# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: sambut1987@gmail.com-20111115175353-pmnyw4yn26zyvn9o # target_branch: lp:inkscape # testament_sha1: 3e6cd4fb44c0b5f4ae2d62864c44d690d10f7149 # timestamp: 2011-11-15 18:55:06 +0100 # base_revision_id: kris.de.gussem@hotmail.com-20111110222306-\ # 2dvfsczce37xsbru # # 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-15 17:53:53 +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,9 +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(_("Average")); + _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.set_active(prefs->getInt("/dialogs/align/align-to", 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); @@ -1051,12 +1065,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 +1086,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 +1111,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 +1119,13 @@ //Make blink the master } +void AlignAndDistribute::on_node_ref_change(){ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setInt("/dialogs/align/align-to", _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 +1151,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 +1177,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 +1317,21 @@ return AlignTarget(_combo.get_active_row_number()); } - +MultiPathManipulator::TargetMode AlignAndDistribute::getNodeAlignTarget() { + + if(_node_anchor_combo.is_visible()) + { + switch (NodeAlignTarget(_node_anchor_combo.get_active_row_number())) + { + case AlignAndDistribute::AVERAGE: return MultiPathManipulator::AVERAGE; break; + 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; + }; + } + else return MultiPathManipulator::AVERAGE; +} } // 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-15 17:53:53 +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 { AVERAGE=0, TOP, BOTTOM, LEFT, RIGHT }; + 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-15 17:53:53 +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::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; + } + 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; + } + };//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-15 17:53:53 +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-15 17:53:53 +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-15 17:53:53 +0000 @@ -37,7 +37,8 @@ MultiPathManipulator(PathSharedData &data, sigc::connection &chg); virtual ~MultiPathManipulator(); virtual bool event(GdkEvent *event); - + enum TargetMode { AVERAGE=0, TOP, BOTTOM, LEFT, RIGHT }; + 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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