diff options
| -rw-r--r-- | src/selection.cpp | 30 | ||||
| -rw-r--r-- | src/selection.h | 18 | ||||
| -rw-r--r-- | src/ui/dialog/align-and-distribute.cpp | 127 | ||||
| -rw-r--r-- | src/ui/dialog/align-and-distribute.h | 10 |
4 files changed, 68 insertions, 117 deletions
diff --git a/src/selection.cpp b/src/selection.cpp index d018aba0c..83caaf459 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -42,6 +42,7 @@ namespace Inkscape { Selection::Selection(LayerModel *layers, SPDesktop *desktop) : + align_point(NULL), _objs(NULL), _reprs(NULL), _items(NULL), @@ -358,6 +359,35 @@ SPItem *Selection::singleItem() { } } +SPItem *Selection::smallestItem(Selection::CompareSize compare) { + return _sizeistItem(true, compare); +} + +SPItem *Selection::largestItem(Selection::CompareSize compare) { + return _sizeistItem(false, compare); +} + +SPItem *Selection::_sizeistItem(bool small, Selection::CompareSize compare) { + GSList const *items = const_cast<Selection *>(this)->itemList(); + gdouble max = small ? 1e18 : 0; + SPItem *ist = NULL; + + for ( GSList const *i = items; i != NULL ; i = i->next ) { + Geom::OptRect bbox = SP_ITEM(i->data)->desktopPreferredBounds(); + if (!bbox) continue; + + gdouble size = compare == 2 ? + (*bbox)[Geom::X].extent() * (*bbox)[Geom::Y].extent() : + (*bbox)[compare == 1 ? Geom::X : Geom::Y].extent(); + size = small ? size : size * -1; + if (size < max) { + max = size; + ist = SP_ITEM(i->data); + } + } + return ist; +} + Inkscape::XML::Node *Selection::singleRepr() { SPObject *obj=single(); return obj ? obj->getRepr() : NULL; diff --git a/src/selection.h b/src/selection.h index f076cf7aa..25c018f7b 100644 --- a/src/selection.h +++ b/src/selection.h @@ -27,6 +27,7 @@ #include "sp-item.h" #include "snapped-point.h" + class SPDesktop; class SPItem; class SPBox3D; @@ -63,6 +64,7 @@ class Selection : public Inkscape::GC::Managed<>, public Inkscape::GC::Anchored { public: + enum CompareSize { HORIZONTAL, VERTICAL, AREA }; /** * Constructs an selection object, bound to a particular * layer model @@ -220,6 +222,16 @@ public: SPItem *singleItem(); /** + * Returns the smallest item from this selection. + */ + SPItem *smallestItem(CompareSize compare); + + /** + * Returns the largest item from this selection. + */ + SPItem *largestItem(CompareSize compare); + + /** * Returns a single selected object's xml node. * * @return NULL unless exactly one object is selected @@ -308,6 +320,11 @@ public: return _modified_signal.connect(slot); } + /** + * Selection wants to be aligned to this point, not bbox + */ + Geom::Point *align_point; + private: /** no copy. */ Selection(Selection const &); @@ -349,6 +366,7 @@ private: void add_3D_boxes_recursively(SPObject *obj); void remove_box_perspective(SPBox3D *box); void remove_3D_boxes_recursively(SPObject *obj); + SPItem *_sizeistItem(bool small, CompareSize compare); std::list<SPBox3D *> _3dboxes; diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 6a1cfc0ba..ed3f3adce 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -103,45 +103,30 @@ void ActionAlign::do_action(SPDesktop *desktop, int index) const Coeffs &a = _allCoeffs[index]; Geom::OptRect b = Geom::OptRect(); - AlignAndDistribute::AlignTarget target = AlignAndDistribute::getAlignTarget(); + Selection::CompareSize horiz = (a.mx0 != 0.0) || (a.mx1 != 0.0) + ? Selection::HORIZONTAL : Selection::VERTICAL; - switch (target) + switch (AlignTarget(prefs->getInt("/dialogs/align/align-to", 6))) { - case AlignAndDistribute::LAST: - case AlignAndDistribute::FIRST: - case AlignAndDistribute::BIGGEST: - case AlignAndDistribute::SMALLEST: - { - //Check 2 or more selected objects - std::list<SPItem *>::iterator second(selected.begin()); - ++second; - if (second == selected.end()) - return; - //Find the master (anchor on which the other objects are aligned) - std::list<SPItem *>::iterator master( - AlignAndDistribute::find_master ( - selected, - (a.mx0 != 0.0) || - (a.mx1 != 0.0) ) - ); - //remove the master from the selection - SPItem * thing = *master; - // TODO: either uncomment or remove the following commented lines, depending on which - // behaviour of moving objects makes most sense; also cf. discussion at - // https://bugs.launchpad.net/inkscape/+bug/255933 - /*if (!sel_as_group) { */ - selected.erase(master); - /*}*/ - b = thing->desktopPreferredBounds(); + case LAST: + b = SP_ITEM(*selected.begin())->desktopPreferredBounds(); break; - } - case AlignAndDistribute::PAGE: + case FIRST: + b = SP_ITEM(*--(selected.end()))->desktopPreferredBounds(); + break; + case BIGGEST: + b = selection->largestItem(horiz)->desktopPreferredBounds(); + break; + case SMALLEST: + b = selection->smallestItem(horiz)->desktopPreferredBounds(); + break; + case PAGE: b = sp_desktop_document(desktop)->preferredBounds(); break; - case AlignAndDistribute::DRAWING: + case DRAWING: b = sp_desktop_document(desktop)->getRoot()->desktopPreferredBounds(); break; - case AlignAndDistribute::SELECTION: + case SELECTION: b = selection->preferredBounds(); break; default: @@ -151,18 +136,10 @@ void ActionAlign::do_action(SPDesktop *desktop, int index) g_return_if_fail(b); + // Generate the move point from the selected bounding box Geom::Point mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X], a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]); - // 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 - // a selected original, they will be unmoved too, possibly contrary to user's - // expecation. However this is a minor point compared to making align/distribute always - // work as expected, and "unmoved" is the default option anyway. - int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); - prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); - bool changed = false; if (sel_as_group) b = selection->preferredBounds(); @@ -186,15 +163,10 @@ void ActionAlign::do_action(SPDesktop *desktop, int index) } } - // restore compensation setting - prefs->setInt("/options/clonecompensation/value", saved_compensation); - if (changed) { DocumentUndo::done( sp_desktop_document(desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE, _("Align")); } - - } @@ -1240,69 +1212,6 @@ void AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib:: *this, table, orientation, distribute)); } - - - -std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem *> &list, bool horizontal){ - std::list<SPItem *>::iterator master = list.end(); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - int prefs_bbox = prefs->getBool("/tools/bounding_box"); - switch (getAlignTarget()) { - case LAST: - return list.begin(); - break; - - case FIRST: - return --(list.end()); - break; - - case BIGGEST: - { - gdouble max = -1e18; - for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); ++it) { - Geom::OptRect b = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds(); - if (b) { - gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent(); - if (dim > max) { - max = dim; - master = it; - } - } - } - return master; - } - - case SMALLEST: - { - gdouble max = 1e18; - for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); ++it) { - Geom::OptRect b = !prefs_bbox ? (*it)->desktopVisualBounds() : (*it)->desktopGeometricBounds(); - if (b) { - gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent(); - if (dim < max) { - max = dim; - master = it; - } - } - } - return master; - } - - default: - g_assert_not_reached (); - break; - - } // end of switch statement - return master; -} - -AlignAndDistribute::AlignTarget AlignAndDistribute::getAlignTarget() { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - return AlignTarget(prefs->getInt("/dialogs/align/align-to", 6)); -} - - - } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index c9165a83e..dfd84535b 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -47,12 +47,6 @@ public: static AlignAndDistribute &getInstance() { return *new AlignAndDistribute(); } - enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION }; - - - - static AlignTarget getAlignTarget(); - #if WITH_GTKMM_3_0 Gtk::Grid &align_table(){return _alignTable;} Gtk::Grid &distribute_table(){return _distributeTable;} @@ -67,7 +61,6 @@ public: Gtk::Table &nodes_table(){return _nodesTable;} #endif - static std::list<SPItem *>::iterator find_master(std::list <SPItem *> &list, bool horizontal); void setMode(bool nodeEdit); Geom::OptRect randomize_bbox; @@ -189,6 +182,7 @@ public : double sx0, sx1, sy0, sy1; int verb_id; }; + enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION }; ActionAlign(const Glib::ustring &id, const Glib::ustring &tiptext, guint row, guint column, @@ -204,6 +198,7 @@ public : * Static function called to align from a keyboard shortcut */ static void do_verb_action(SPDesktop *desktop, int verb); + static int verb_to_coeff(int verb); private : @@ -217,7 +212,6 @@ private : } static void do_action(SPDesktop *desktop, int index); - static int verb_to_coeff(int verb); guint _index; AlignAndDistribute &_dialog; |
