align-and-distribute.cpp revision e898e8dd3fbc3e21f3a35f089a0d1c1dc6d48850
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @brief Align and Distribute dialog - implementation
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Bryce W. Harrington <bryce@bryceharrington.org>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Aubanel MONNIER <aubi@libertysurf.fr>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Frank Felfe <innerspace@iname.com>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Lauris Kaplinski <lauris@kaplinski.com>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Tim Dwyer <tgdwyer@gmail.com>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Jon A. Cruz <jon@joncruz.org>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Abhishek Sharma
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 1999-2004, 2005 Authors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Released under GNU GPL. Read the file 'COPYING' for more information.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/////////helper classes//////////////////////////////////
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( _id, Inkscape::ICON_SIZE_LARGE_TOOLBAR) );
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Gtk::Button * pButton = Gtk::manage(new Gtk::Button());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh .connect(sigc::mem_fun(*this, &Action::on_button_click));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh parent.attach(*pButton, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh virtual ~Action(){}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh virtual void on_button_click(){}
1667116521643e2475184b048e0abb77a2aa9735miklosh virtual void on_button_click() {
1667116521643e2475184b048e0abb77a2aa9735miklosh //Retreive selected objects
1667116521643e2475184b048e0abb77a2aa9735miklosh if (!desktop) return;
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh if (!selection) return;
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups");
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh AlignAndDistribute::AlignTarget target = _dialog.getAlignTarget();
68664e00e2372534b4df2fdc5f54f836bafece18miklosh //Check 2 or more selected objects
68664e00e2372534b4df2fdc5f54f836bafece18miklosh std::list<SPItem *>::iterator second(selected.begin());
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //Find the master (anchor on which the other objects are aligned)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //remove the master from the selection
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // TODO: either uncomment or remove the following commented lines, depending on which
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // behaviour of moving objects makes most sense; also cf. discussion at
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh /*if (!sel_as_group) { */
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //Compute the anchor point
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
1667116521643e2475184b048e0abb77a2aa9735miklosh mp = Geom::Point(a.mx1 * sp_desktop_document(desktop)->getWidth(),
1667116521643e2475184b048e0abb77a2aa9735miklosh Geom::OptRect b = sp_desktop_document(desktop)->getRoot()->getBboxDesktop();
1667116521643e2475184b048e0abb77a2aa9735miklosh mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
1667116521643e2475184b048e0abb77a2aa9735miklosh a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }; // end of switch
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Top hack: temporarily set clone compensation to unmoved, so that we can align/distribute
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // clones with their original (and the move of the original does not disturb the
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // clones). The only problem with this is that if there are outside-of-selection clones of
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // a selected original, they will be unmoved too, possibly contrary to user's
1667116521643e2475184b048e0abb77a2aa9735miklosh // expecation. However this is a minor point compared to making align/distribute always
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh // work as expected, and "unmoved" is the default option anyway.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool changed = false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Move each item in the selected list separately
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point const sp(a.sx0 * b->min()[Geom::X] + a.sx1 * b->max()[Geom::X],
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh a.sy0 * b->min()[Geom::Y] + a.sy1 * b->max()[Geom::Y]);
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done( sp_desktop_document(desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Align"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshBBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //NOTE : this copy ctor is called O(sort) when sorting the vector
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //this is bad. The vector should be a vector of pointers.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //But I'll wait the bohem GC before doing that
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshbool operator< (const BBoxSort &a, const BBoxSort &b)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.distribute_table(), dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click() {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Retreive selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!desktop) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!selection) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *>::iterator second(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //sort bbox by anchors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // see comment in ActionAlign above
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool changed = false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //overall bboxes span
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float dist = (sorted.back().bbox.max()[_orientation] -
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //space eaten by bboxes
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (unsigned int i = 0; i < len; i++)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //new distance between each bbox
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float pos = sorted.front().bbox.min()[_orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for ( std::vector<BBoxSort> ::iterator it (sorted.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!Geom::are_near(pos, it->bbox.min()[_orientation], 1e-6)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh t[_orientation] = pos - it->bbox.min()[_orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //overall anchor span
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh float dist = sorted.back().anchor - sorted.front().anchor;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh //distance between anchors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for ( unsigned int i = 0; i < len ; i ++ )
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //new anchor position
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Don't move if we are really close
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Compute translation
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //translate
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Distribute"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPEventContext *event_context = sp_desktop_event_context(_dialog.getDesktop());
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh dialog.removeOverlap_table(), dialog.tooltips(), dialog)
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh _("Minimum horizontal gap (in px units) between bounding boxes"));
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh //TRANSLATORS: "H:" stands for horizontal gap
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGapLabel.set_text_with_mnemonic(C_("Gap", "_H:"));
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapXGapLabel.set_mnemonic_widget(removeOverlapXGap);
1db439af43130c9695dbbb661e893d56006bb072miklosh _("Minimum vertical gap (in px units) between bounding boxes"));
1db439af43130c9695dbbb661e893d56006bb072miklosh /* TRANSLATORS: Vertical gap */
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGapLabel.set_text_with_mnemonic(C_("Gap", "_V:"));
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGapLabel.set_mnemonic_widget(removeOverlapYGap);
1db439af43130c9695dbbb661e893d56006bb072miklosh dialog.removeOverlap_table().attach(removeOverlapXGapLabel, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
1db439af43130c9695dbbb661e893d56006bb072miklosh dialog.removeOverlap_table().attach(removeOverlapXGap, column+1, column+2, row, row+1, Gtk::FILL, Gtk::FILL);
1db439af43130c9695dbbb661e893d56006bb072miklosh dialog.removeOverlap_table().attach(removeOverlapYGapLabel, column+2, column+3, row, row+1, Gtk::FILL, Gtk::FILL);
1db439af43130c9695dbbb661e893d56006bb072miklosh dialog.removeOverlap_table().attach(removeOverlapYGap, column+3, column+4, row, row+1, Gtk::FILL, Gtk::FILL);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh virtual void on_button_click()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // see comment in ActionAlign above
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // xGap and yGap are the minimum space required between bounding rectangles.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh removeoverlap(sp_desktop_selection(_dialog.getDesktop())->itemList(),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Remove overlaps"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh virtual void on_button_click()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // see comment in ActionAlign above
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh graphlayout(sp_desktop_selection(_dialog.getDesktop())->itemList());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Arrange connector network"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog, SortOrder order = None) :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.rearrange_table(), dialog.tooltips(), dialog),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh static bool sort_compare(const SPItem * a,const SPItem * b) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (a == NULL) return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (b == NULL) return true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // First criteria: Sort according to the angle to the center point
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double angle_a = atan2(double(point_a[Geom::Y]), double(point_a[Geom::X]));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double angle_b = atan2(double(point_b[Geom::Y]), double(point_b[Geom::X]));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Second criteria: Sort according to the distance the center point
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (length_a != length_b) return (length_a > length_b);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Last criteria: Sort according to the z-coordinate
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return (a->isSiblingOf(b));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh virtual void on_button_click()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!desktop) return;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (!selection) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // see comment in ActionAlign above
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // sort the list
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh } else { // sorting by ZOrder is outomatically done by not setting the center
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh selected.sort(ActionExchangePositions::sort_compare);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_item_move_rel((*it),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_item_move_rel(selected.front(),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // restore compensation setting
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh _("Exchange Positions"));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh// instantiae the private static member
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshboost::optional<Geom::Point> ActionExchangePositions::center;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh virtual void on_button_click()
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // see comment in ActionAlign above
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh unclump ((GSList *) sp_desktop_selection(_dialog.getDesktop())->itemList());
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Unclump"));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!desktop) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!selection) return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // This bbox is cached between calls to randomize, so that there's no growth nor shrink
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // nor drift on sequential randomizations. Discard cache on global (or better active
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // desktop's) selection_change signal.
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // see comment in ActionAlign above
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // find new center, staying within bbox
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double x = _dialog.randomize_bbox->min()[Geom::X] + (*item_box)[Geom::X].extent() /2 +
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh g_random_double_range (0, (*_dialog.randomize_bbox)[Geom::X].extent() - (*item_box)[Geom::X].extent());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double y = _dialog.randomize_bbox->min()[Geom::Y] + (*item_box)[Geom::Y].extent()/2 +
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_random_double_range (0, (*_dialog.randomize_bbox)[Geom::Y].extent() - (*item_box)[Geom::Y].extent());
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh // displacement is the new center minus old:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point t = Geom::Point (x, y) - 0.5*(item_box->max() + item_box->min());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Randomize positions"));
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Baselines(SPItem *item, Geom::Point base, Geom::Dim2 orientation) :
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emikloshbool operator< (const Baselines &a, const Baselines &b)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh return (a._base[a._orientation] < b._base[b._orientation]);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh virtual void on_button_click()
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if (!desktop) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if (!selection) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point b_min = Geom::Point (HUGE_VAL, HUGE_VAL);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point b_max = Geom::Point (-HUGE_VAL, -HUGE_VAL);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Text::Layout const *layout = te_get_layout(*it);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (base[Geom::X] < b_min[Geom::X]) b_min[Geom::X] = base[Geom::X];
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (base[Geom::Y] < b_min[Geom::Y]) b_min[Geom::Y] = base[Geom::Y];
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (base[Geom::X] > b_max[Geom::X]) b_max[Geom::X] = base[Geom::X];
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (base[Geom::Y] > b_max[Geom::Y]) b_max[Geom::Y] = base[Geom::Y];
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh //sort baselines
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh bool changed = false;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh double step = (b_max[_orientation] - b_min[_orientation])/(sorted.size() - 1);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh t[_orientation] = b_min[_orientation] + step * i - base[_orientation];
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute text baselines"));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it(selected.begin());
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Inkscape::Text::Layout const *layout = te_get_layout(*it);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh t[_orientation] = b_min[_orientation] - base[_orientation];
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Align text baselines"));
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh daad->setMode(tools_active(desktop) == TOOLS_NODES);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmikloshvoid on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/////////////////////////////////////////////////////////
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh : UI::Widget::Panel ("", "/dialogs/align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
77364929ced3ec0bc5c9f47440606615c559084emiklosh //Instanciate the align buttons
77364929ced3ec0bc5c9f47440606615c559084emiklosh addAlignButton(INKSCAPE_ICON("align-horizontal-right-to-anchor"),
77364929ced3ec0bc5c9f47440606615c559084emiklosh _("Align right edges of objects to the left edge of the anchor"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addAlignButton(INKSCAPE_ICON("align-horizontal-left"),
77364929ced3ec0bc5c9f47440606615c559084emiklosh _("Align left edges"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-center"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Center on vertical axis"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-right"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align right sides"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-left-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align left edges of objects to the right edge of the anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-bottom-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align bottom edges of objects to the top edge of the anchor"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Align top edges"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addAlignButton(INKSCAPE_ICON("align-vertical-center"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Center on horizontal axis"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-bottom"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align bottom edges"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-top-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align top edges of objects to the bottom edge of the anchor"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh //Baseline aligns
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("align-horizontal-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align baseline anchors of texts horizontally"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("align-vertical-baseline"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _("Align baselines of texts"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //The distribute buttons
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-gaps"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Make horizontal gaps between objects equal"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-left"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Distribute left edges equidistantly"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-center"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Distribute centers equidistantly horizontally"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-right"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _("Distribute right edges equidistantly"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-gaps"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Make vertical gaps between objects equal"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-top"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute top edges equidistantly"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-center"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute centers equidistantly vertically"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-bottom"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute bottom edges equidistantly"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Baseline distribs
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("distribute-horizontal-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute baseline anchors of texts horizontally"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("distribute-vertical-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute baselines of texts vertically"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Rearrange
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Graph Layout
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addGraphLayoutButton(INKSCAPE_ICON("distribute-graph"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Nicely arrange selected connector network"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsButton(INKSCAPE_ICON("exchange-positions"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - selection order"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsByZOrderButton(INKSCAPE_ICON("exchange-positions-zorder"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - stacking order"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsClockwiseButton(INKSCAPE_ICON("exchange-positions-clockwise"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - clockwise rotate"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Randomize & Unclump
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addRandomizeButton(INKSCAPE_ICON("distribute-randomize"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Randomize centers in both dimensions"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addUnclumpButton(INKSCAPE_ICON("distribute-unclump"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Unclump objects: try to equalize edge-to-edge distances"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Remove overlaps
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addRemoveOverlapsButton(INKSCAPE_ICON("distribute-remove-overlaps"),
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _("Move objects as little as possible so that their bounding boxes do not overlap"),
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh //Node Mode buttons
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh // NOTE: "align nodes vertically" means "move nodes vertically until they align on a common
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh // _horizontal_ line". This is analogous to what the "align-vertical-center" icon means.
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh // There is no doubt some ambiguity. For this reason the descriptions are different.
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align selected nodes to a common horizontal line"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, Geom::X, false);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addNodeButton(INKSCAPE_ICON("align-horizontal-node"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align selected nodes to a common vertical line"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addNodeButton(INKSCAPE_ICON("distribute-horizontal-node"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute selected nodes horizontally"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addNodeButton(INKSCAPE_ICON("distribute-vertical-node"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute selected nodes vertically"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh //Rest of the widgetry
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.set_active(prefs->getInt("/dialogs/align/align-to", 6));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrp.set_active(prefs->getBool("/dialogs/align/sel-as-groups"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrp.signal_toggled().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_selgrp_toggled));
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh // Notebook for individual transformations
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_removeOverlapFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh //Connect to the global tool change signal
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh // Connect to the global selection change, to invalidate cached randomize_bbox
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh on_tool_changed (NULL, NULL, this); // set current mode
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<Action *>::iterator it = _actionList.begin();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh prefs->setInt("/dialogs/align/align-to", _combo.get_active_row_number());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Make blink the master
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh prefs->setInt("/dialogs/align/sel-as-groups", _selgrp.get_active());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Make blink the master
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Act on widgets used in node mode
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Act on widgets used in selection mode
e45563a3c46261d8c32014f8e516857ba01bd7b7mikloshvoid AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addRemoveOverlapsButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addGraphLayoutButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addExchangePositionsButton(const Glib::ustring &id, const Glib::ustring tiptext,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8mikloshvoid AlignAndDistribute::addExchangePositionsByZOrderButton(const Glib::ustring &id, const Glib::ustring tiptext,
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh id, tiptext, row, col, *this, ActionExchangePositions::ZOrder)
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::addExchangePositionsClockwiseButton(const Glib::ustring &id, const Glib::ustring tiptext,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh id, tiptext, row, col, *this, ActionExchangePositions::Clockwise)
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute)
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshstd::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem *> &list, bool horizontal){
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } // end of switch statement
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshAlignAndDistribute::AlignTarget AlignAndDistribute::getAlignTarget()const {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh} // namespace Dialog
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace UI
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace Inkscape
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Local Variables:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-style:"stroustrup"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh indent-tabs-mode:nil
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh fill-column:99
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :