align-and-distribute.cpp revision e898e8dd3fbc3e21f3a35f089a0d1c1dc6d48850
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/** @file
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * @brief Align and Distribute dialog - implementation
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh/* Authors:
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 *
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Copyright (C) 1999-2004, 2005 Authors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh *
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh * Released under GNU GPL. Read the file 'COPYING' for more information.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#ifdef HAVE_CONFIG_H
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh# include <config.h>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#endif
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include <2geom/transforms.h>
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "ui/widget/spinbutton.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "desktop-handles.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "unclump.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "document.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "enums.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "graphlayout.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "inkscape.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "macros.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "preferences.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "removeoverlap.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "selection.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "sp-flowtext.h"
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh#include "sp-item-transform.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "sp-text.h"
fba63a357654d8b3e84c60007e40aa698cd45d19miklosh#include "text-editing.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "tools-switch.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "ui/icon-names.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "ui/tool/node-tool.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "ui/tool/multi-path-manipulator.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "util/glib-list-iterators.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "verbs.h"
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh#include "widgets/icon.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh#include "sp-root.h"
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh#include "align-and-distribute.h"
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshnamespace Inkscape {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshnamespace UI {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshnamespace Dialog {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/////////helper classes//////////////////////////////////
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshclass Action {
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshpublic :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Action(const Glib::ustring &id,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh const Glib::ustring &tiptext,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh guint row, guint column,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Gtk::Table &parent,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Gtk::Tooltips &tooltips,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh AlignAndDistribute &dialog):
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _dialog(dialog),
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _id(id),
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _parent(parent)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh {
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());
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh pButton->set_relief(Gtk::RELIEF_NONE);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh pIcon->show();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh pButton->add(*pIcon);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh pButton->show();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pButton->signal_clicked()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh .connect(sigc::mem_fun(*this, &Action::on_button_click));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh tooltips.set_tip(*pButton, tiptext);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh parent.attach(*pButton, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh }
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh virtual ~Action(){}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh AlignAndDistribute &_dialog;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshprivate :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh virtual void on_button_click(){}
a4d12a5147f3d1d6b568a326e39ef5dca384248dmiklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh Glib::ustring _id;
cb814cb0df20053ca3ef16ce55da474435daf045miklosh Gtk::Table &_parent;
cb814cb0df20053ca3ef16ce55da474435daf045miklosh};
cb814cb0df20053ca3ef16ce55da474435daf045miklosh
cb814cb0df20053ca3ef16ce55da474435daf045miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshclass ActionAlign : public Action {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshpublic :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh struct Coeffs {
1cda9431ef400135f5e1bd899a94b921bdad0eafmiklosh double mx0, mx1, my0, my1;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double sx0, sx1, sy0, sy1;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh };
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh ActionAlign(const Glib::ustring &id,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh const Glib::ustring &tiptext,
cb814cb0df20053ca3ef16ce55da474435daf045miklosh guint row, guint column,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh AlignAndDistribute &dialog,
1667116521643e2475184b048e0abb77a2aa9735miklosh guint coeffIndex):
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Action(id, tiptext, row, column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.align_table(), dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _index(coeffIndex),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _dialog(dialog)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {}
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735mikloshprivate :
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh virtual void on_button_click() {
1667116521643e2475184b048e0abb77a2aa9735miklosh //Retreive selected objects
1667116521643e2475184b048e0abb77a2aa9735miklosh SPDesktop *desktop = _dialog.getDesktop();
1667116521643e2475184b048e0abb77a2aa9735miklosh if (!desktop) return;
1667116521643e2475184b048e0abb77a2aa9735miklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh if (!selection) return;
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups");
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh using Inkscape::Util::GSListConstIterator;
1667116521643e2475184b048e0abb77a2aa9735miklosh std::list<SPItem *> selected;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (selected.empty()) return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::Point mp; //Anchor point
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh AlignAndDistribute::AlignTarget target = _dialog.getAlignTarget();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh const Coeffs &a= _allCoeffs[_index];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh switch (target)
68664e00e2372534b4df2fdc5f54f836bafece18miklosh {
68664e00e2372534b4df2fdc5f54f836bafece18miklosh case AlignAndDistribute::LAST:
68664e00e2372534b4df2fdc5f54f836bafece18miklosh case AlignAndDistribute::FIRST:
68664e00e2372534b4df2fdc5f54f836bafece18miklosh case AlignAndDistribute::BIGGEST:
68664e00e2372534b4df2fdc5f54f836bafece18miklosh case AlignAndDistribute::SMALLEST:
68664e00e2372534b4df2fdc5f54f836bafece18miklosh {
68664e00e2372534b4df2fdc5f54f836bafece18miklosh //Check 2 or more selected objects
68664e00e2372534b4df2fdc5f54f836bafece18miklosh std::list<SPItem *>::iterator second(selected.begin());
68664e00e2372534b4df2fdc5f54f836bafece18miklosh ++second;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh if (second == selected.end())
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh return;
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //Find the master (anchor on which the other objects are aligned)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh std::list<SPItem *>::iterator master(
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _dialog.find_master (
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh selected,
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh (a.mx0 != 0.0) ||
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh (a.mx1 != 0.0) )
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh );
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //remove the master from the selection
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh SPItem * thing = *master;
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 // https://bugs.launchpad.net/inkscape/+bug/255933
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh /*if (!sel_as_group) { */
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.erase(master);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh /*}*/
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh //Compute the anchor point
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect b = thing->getBboxDesktop ();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (b) {
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]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh } else {
1667116521643e2475184b048e0abb77a2aa9735miklosh return;
1667116521643e2475184b048e0abb77a2aa9735miklosh }
1667116521643e2475184b048e0abb77a2aa9735miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh case AlignAndDistribute::PAGE:
1667116521643e2475184b048e0abb77a2aa9735miklosh mp = Geom::Point(a.mx1 * sp_desktop_document(desktop)->getWidth(),
1667116521643e2475184b048e0abb77a2aa9735miklosh a.my1 * sp_desktop_document(desktop)->getHeight());
1667116521643e2475184b048e0abb77a2aa9735miklosh break;
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh case AlignAndDistribute::DRAWING:
1667116521643e2475184b048e0abb77a2aa9735miklosh {
1667116521643e2475184b048e0abb77a2aa9735miklosh Geom::OptRect b = sp_desktop_document(desktop)->getRoot()->getBboxDesktop();
1667116521643e2475184b048e0abb77a2aa9735miklosh if (b) {
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]);
1667116521643e2475184b048e0abb77a2aa9735miklosh } else {
1667116521643e2475184b048e0abb77a2aa9735miklosh return;
1667116521643e2475184b048e0abb77a2aa9735miklosh }
1667116521643e2475184b048e0abb77a2aa9735miklosh break;
1667116521643e2475184b048e0abb77a2aa9735miklosh }
1667116521643e2475184b048e0abb77a2aa9735miklosh
1667116521643e2475184b048e0abb77a2aa9735miklosh case AlignAndDistribute::SELECTION:
1667116521643e2475184b048e0abb77a2aa9735miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect b = selection->bounds();
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh if (b) {
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]);
68664e00e2372534b4df2fdc5f54f836bafece18miklosh } else {
68664e00e2372534b4df2fdc5f54f836bafece18miklosh return;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh }
68664e00e2372534b4df2fdc5f54f836bafece18miklosh break;
68664e00e2372534b4df2fdc5f54f836bafece18miklosh }
68664e00e2372534b4df2fdc5f54f836bafece18miklosh
68664e00e2372534b4df2fdc5f54f836bafece18miklosh default:
68664e00e2372534b4df2fdc5f54f836bafece18miklosh g_assert_not_reached ();
68664e00e2372534b4df2fdc5f54f836bafece18miklosh break;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }; // end of switch
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
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);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool changed = false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect b;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (sel_as_group)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh b = selection->bounds();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Move each item in the selected list separately
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh it != selected.end();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh it++)
fba63a357654d8b3e84c60007e40aa698cd45d19miklosh {
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh sp_desktop_document (desktop)->ensureUpToDate();
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh if (!sel_as_group)
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh b = (*it)->getBboxDesktop();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (b) {
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]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point const mp_rel( mp - sp );
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (LInfty(mp_rel) > 1e-9) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh sp_item_move_rel(*it, Geom::Translate(mp_rel));
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh changed = true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
b5b35fce2e3df933e5223ef6645d814eacf51cfamiklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (changed) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done( sp_desktop_document(desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Align"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint _index;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &_dialog;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh static const Coeffs _allCoeffs[10];
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh};
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshActionAlign::Coeffs const ActionAlign::_allCoeffs[10] = {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {1., 0., 0., 0., 0., 1., 0., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {1., 0., 0., 0., 1., 0., 0., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {.5, .5, 0., 0., .5, .5, 0., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 1., 0., 0., 0., 1., 0., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 1., 0., 0., 1., 0., 0., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 0., 0., 1., 0., 0., 1., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 0., 0., 1., 0., 0., 0., 1.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 0., .5, .5, 0., 0., .5, .5},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 0., 1., 0., 0., 0., 1., 0.},
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {0., 0., 1., 0., 0., 0., 0., 1.}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh};
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshBBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh item(pItem),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bbox (bounds)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshBBoxSort::BBoxSort(const BBoxSort &rhs) :
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
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh item(rhs.item), anchor(rhs.anchor), bbox(rhs.bbox)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshbool operator< (const BBoxSort &a, const BBoxSort &b)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return (a.anchor < b.anchor);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshclass ActionDistribute : public Action {
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshpublic :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ActionDistribute(const Glib::ustring &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh const Glib::ustring &tiptext,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint row, guint column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh bool onInterSpace,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Dim2 orientation,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double kBegin, double kEnd
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ):
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Action(id, tiptext, row, column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.distribute_table(), dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _dialog(dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _onInterSpace(onInterSpace),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _orientation(orientation),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _kBegin(kBegin),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _kEnd( kEnd)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshprivate :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click() {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Retreive selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDesktop *desktop = _dialog.getDesktop();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!desktop) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!selection) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh using Inkscape::Util::GSListConstIterator;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *> selected;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selected.empty()) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *>::iterator second(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ++second;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (second == selected.end()) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::vector< BBoxSort > sorted;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for (std::list<SPItem *>::iterator it(selected.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh it != selected.end();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ++it)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect bbox = (*it)->getBboxDesktop();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (bbox) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //sort bbox by anchors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::sort(sorted.begin(), sorted.end());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
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
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh unsigned int len = sorted.size();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool changed = false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (_onInterSpace)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //overall bboxes span
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float dist = (sorted.back().bbox.max()[_orientation] -
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sorted.front().bbox.min()[_orientation]);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //space eaten by bboxes
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float span = 0;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (unsigned int i = 0; i < len; i++)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh span += sorted[i].bbox[_orientation].extent();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //new distance between each bbox
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float step = (dist - span) / (len - 1);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float pos = sorted.front().bbox.min()[_orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for ( std::vector<BBoxSort> ::iterator it (sorted.begin());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh it < sorted.end();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh it ++ )
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!Geom::are_near(pos, it->bbox.min()[_orientation], 1e-6)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point t(0.0, 0.0);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh t[_orientation] = pos - it->bbox.min()[_orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_item_move_rel(it->item, Geom::Translate(t));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh changed = true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pos += it->bbox[_orientation].extent();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh pos += step;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh else
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //overall anchor span
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh float dist = sorted.back().anchor - sorted.front().anchor;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh //distance between anchors
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float step = dist / (len - 1);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh for ( unsigned int i = 0; i < len ; i ++ )
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh BBoxSort & it(sorted[i]);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //new anchor position
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh float pos = sorted.front().anchor + i * step;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Don't move if we are really close
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!Geom::are_near(pos, it.anchor, 1e-6)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Compute translation
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point t(0.0, 0.0);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh t[_orientation] = pos - it.anchor;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //translate
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_item_move_rel(it.item, Geom::Translate(t));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh changed = true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (changed) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Distribute"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint _index;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &_dialog;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool _onInterSpace;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Dim2 _orientation;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh double _kBegin;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double _kEnd;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh};
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshclass ActionNode : public Action {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshpublic :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ActionNode(const Glib::ustring &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh const Glib::ustring &tiptext,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Dim2 orientation, bool distribute):
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Action(id, tiptext, 0, column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.nodes_table(), dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _orientation(orientation),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _distribute(distribute)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshprivate :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Dim2 _orientation;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh bool _distribute;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!_dialog.getDesktop()) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPEventContext *event_context = sp_desktop_event_context(_dialog.getDesktop());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!INK_IS_NODE_TOOL (event_context)) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh InkNodeTool *nt = INK_NODE_TOOL(event_context);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (_distribute)
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh nt->_multipath->distributeNodes(_orientation);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh else
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh nt->_multipath->alignNodes(_orientation);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh }
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh};
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020mikloshclass ActionRemoveOverlaps : public Action {
3686c32a570c3df738a09b34e85fc5d6bd50d020mikloshprivate:
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Gtk::Label removeOverlapXGapLabel;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Gtk::Label removeOverlapYGapLabel;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::UI::Widget::SpinButton removeOverlapXGap;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::UI::Widget::SpinButton removeOverlapYGap;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
d27f5758e12c3107ee69e66702043931e0756f6bmikloshpublic:
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh ActionRemoveOverlaps(Glib::ustring const &id,
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Glib::ustring const &tiptext,
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh guint row,
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh guint column,
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh AlignAndDistribute &dialog) :
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Action(id, tiptext, row, column + 4,
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh dialog.removeOverlap_table(), dialog.tooltips(), dialog)
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh dialog.removeOverlap_table().set_col_spacings(3);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGap.set_digits(1);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGap.set_size_request(60, -1);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGap.set_increments(1.0, 0);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGap.set_range(-1000.0, 1000.0);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh removeOverlapXGap.set_value(0);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh dialog.tooltips().set_tip(removeOverlapXGap,
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
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGap.set_digits(1);
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGap.set_size_request(60, -1);
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGap.set_increments(1.0, 0);
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGap.set_range(-1000.0, 1000.0);
1db439af43130c9695dbbb661e893d56006bb072miklosh removeOverlapYGap.set_value(0);
1db439af43130c9695dbbb661e893d56006bb072miklosh dialog.tooltips().set_tip(removeOverlapYGap,
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
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);
1db439af43130c9695dbbb661e893d56006bb072miklosh
1db439af43130c9695dbbb661e893d56006bb072miklosh }
1db439af43130c9695dbbb661e893d56006bb072miklosh
1db439af43130c9695dbbb661e893d56006bb072mikloshprivate :
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh virtual void on_button_click()
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!_dialog.getDesktop()) return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
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
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // xGap and yGap are the minimum space required between bounding rectangles.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double const xGap = removeOverlapXGap.get_value();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh double const yGap = removeOverlapYGap.get_value();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh removeoverlap(sp_desktop_selection(_dialog.getDesktop())->itemList(),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh xGap, yGap);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Remove overlaps"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh};
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmiklosh
920fbbf5386a5d3b1d0a1304cb71eb48112abe0dmikloshclass ActionGraphLayout : public Action {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshpublic:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ActionGraphLayout(Glib::ustring const &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Glib::ustring const &tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog) :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Action(id, tiptext, row, column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshprivate :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh virtual void on_button_click()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!_dialog.getDesktop()) return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
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);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh graphlayout(sp_desktop_selection(_dialog.getDesktop())->itemList());
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Arrange connector network"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh};
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshclass ActionExchangePositions : public Action {
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshpublic:
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh enum SortOrder {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh None,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ZOrder,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Clockwise
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh };
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh ActionExchangePositions(Glib::ustring const &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Glib::ustring const &tiptext,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint row,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog, SortOrder order = None) :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Action(id, tiptext, row, column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh dialog.rearrange_table(), dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sortOrder(order)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {};
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshprivate :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh const SortOrder sortOrder;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh static boost::optional<Geom::Point> center;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh static bool sort_compare(const SPItem * a,const SPItem * b) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (a == NULL) return false;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (b == NULL) return true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (center) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point point_a = a->getCenter() - (*center);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::Point point_b = b->getCenter() - (*center);
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 if (angle_a != angle_b) return (angle_a < angle_b);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Second criteria: Sort according to the distance the center point
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Coord length_a = point_a.length();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Coord length_b = point_b.length();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (length_a != length_b) return (length_a > length_b);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // Last criteria: Sort according to the z-coordinate
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return (a->isSiblingOf(b));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh virtual void on_button_click()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh SPDesktop *desktop = _dialog.getDesktop();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (!desktop) return;
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (!selection) return;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh using Inkscape::Util::GSListConstIterator;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *> selected;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selected.empty()) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selected.size() < 2) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
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
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // sort the list
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (sortOrder != None) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (sortOrder == Clockwise) {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh center = selection->center();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh } else { // sorting by ZOrder is outomatically done by not setting the center
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh center.reset();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh selected.sort(ActionExchangePositions::sort_compare);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh std::list<SPItem *>::iterator it(selected.begin());
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Point p1 = (*it)->getCenter();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh for (++it ;it != selected.end(); ++it)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Point p2 = (*it)->getCenter();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Point delta = p1 - p2;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_item_move_rel((*it),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh p1 = p2;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Point p2 = selected.front()->getCenter();
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Geom::Point delta = p1 - p2;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh sp_item_move_rel(selected.front(),Geom::Translate(delta[Geom::X],delta[Geom::Y] ));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // restore compensation setting
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh _("Exchange Positions"));
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh }
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh};
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh// instantiae the private static member
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshboost::optional<Geom::Point> ActionExchangePositions::center;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshclass ActionUnclump : public Action {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshpublic :
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh ActionUnclump(const Glib::ustring &id,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh const Glib::ustring &tiptext,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh guint row,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh guint column,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh AlignAndDistribute &dialog):
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh Action(id, tiptext, row, column,
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh {}
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7mikloshprivate :
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh virtual void on_button_click()
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh {
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh if (!_dialog.getDesktop()) return;
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
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
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh unclump ((GSList *) sp_desktop_selection(_dialog.getDesktop())->itemList());
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh
dc4f69a188c203f2fdc65f22d0d57904a8c52dd7miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Unclump"));
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh};
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshclass ActionRandomize : public Action {
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshpublic :
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh ActionRandomize(const Glib::ustring &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh const Glib::ustring &tiptext,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint row,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh guint column,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh AlignAndDistribute &dialog):
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Action(id, tiptext, row, column,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh dialog.rearrange_table(), dialog.tooltips(), dialog)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {}
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9mikloshprivate :
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh virtual void on_button_click()
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPDesktop *desktop = _dialog.getDesktop();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!desktop) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!selection) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh using Inkscape::Util::GSListConstIterator;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *> selected;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selected.empty()) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (selected.size() < 2) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::OptRect sel_bbox = selection->bounds();
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!sel_bbox) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
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.
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (!_dialog.randomize_bbox) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _dialog.randomize_bbox = *sel_bbox;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
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
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for (std::list<SPItem *>::iterator it(selected.begin());
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh it != selected.end();
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh ++it)
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh {
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh sp_desktop_document (desktop)->ensureUpToDate();
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh Geom::OptRect item_box = (*it)->getBboxDesktop ();
3686c32a570c3df738a09b34e85fc5d6bd50d020miklosh if (item_box) {
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 sp_item_move_rel(*it, Geom::Translate(t));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh // restore compensation setting
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh prefs->setInt("/options/clonecompensation/value", saved_compensation);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _("Randomize positions"));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh};
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
d27f5758e12c3107ee69e66702043931e0756f6bmikloshstruct Baselines
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh{
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh SPItem *_item;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point _base;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Dim2 _orientation;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Baselines(SPItem *item, Geom::Point base, Geom::Dim2 orientation) :
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _item (item),
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _base (base),
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh _orientation (orientation)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh {}
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh};
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emikloshbool operator< (const Baselines &a, const Baselines &b)
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh{
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh return (a._base[a._orientation] < b._base[b._orientation]);
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh}
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emiklosh
c53f16f52840e8c0f2be9c1cc3af633c0ba1552emikloshclass ActionBaseline : public Action {
d27f5758e12c3107ee69e66702043931e0756f6bmikloshpublic :
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh ActionBaseline(const Glib::ustring &id,
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh const Glib::ustring &tiptext,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh guint row,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh guint column,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh AlignAndDistribute &dialog,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Gtk::Table &table,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Dim2 orientation, bool distribute):
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Action(id, tiptext, row, column,
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh table, dialog.tooltips(), dialog),
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh _orientation(orientation),
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh _distribute(distribute)
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh {}
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmikloshprivate :
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Dim2 _orientation;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh bool _distribute;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh virtual void on_button_click()
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh SPDesktop *desktop = _dialog.getDesktop();
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if (!desktop) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Inkscape::Selection *selection = sp_desktop_selection(desktop);
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if (!selection) return;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh using Inkscape::Util::GSListConstIterator;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh std::list<SPItem *> selected;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (selected.empty()) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh //Check 2 or more selected objects
8ec52d39f409ecf67125cd4d878b844e9391e7e8miklosh if (selected.size() < 2) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point b_min = Geom::Point (HUGE_VAL, HUGE_VAL);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point b_max = Geom::Point (-HUGE_VAL, -HUGE_VAL);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh std::vector<Baselines> sorted;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for (std::list<SPItem *>::iterator it(selected.begin());
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh it != selected.end();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ++it)
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Inkscape::Text::Layout const *layout = te_get_layout(*it);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (pt) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh Geom::Point base = *pt * (*it)->i2dt_affine();
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 Baselines b (*it, base, _orientation);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh sorted.push_back(b);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh }
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (sorted.size() <= 1) return;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh //sort baselines
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh std::sort(sorted.begin(), sorted.end());
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh bool changed = false;
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh if (_distribute) {
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh double step = (b_max[_orientation] - b_min[_orientation])/(sorted.size() - 1);
d27f5758e12c3107ee69e66702043931e0756f6bmiklosh for (unsigned int i = 0; i < sorted.size(); i++) {
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh SPItem *item = sorted[i]._item;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point base = sorted[i]._base;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh Geom::Point t(0.0, 0.0);
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh t[_orientation] = b_min[_orientation] + step * i - base[_orientation];
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh sp_item_move_rel(item, Geom::Translate(t));
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh changed = true;
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh }
7a7fa095a483e8b652af9f00e5169f62c84f09b9miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (changed) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute text baselines"));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } else {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it(selected.begin());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh it != selected.end();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ++it)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Inkscape::Text::Layout const *layout = te_get_layout(*it);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh boost::optional<Geom::Point> pt = layout->baselineAnchorPoint();
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh if (pt) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Geom::Point base = *pt * (*it)->i2dt_affine();
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh Geom::Point t(0.0, 0.0);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh t[_orientation] = b_min[_orientation] - base[_orientation];
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh sp_item_move_rel(*it, Geom::Translate(t));
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh changed = true;
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh if (changed) {
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Align text baselines"));
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh }
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh};
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh SPDesktop *desktop = SP_ACTIVE_DESKTOP;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (desktop && sp_desktop_event_context(desktop))
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh daad->setMode(tools_active(desktop) == TOOLS_NODES);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmikloshvoid on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh daad->randomize_bbox = Geom::OptRect();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/////////////////////////////////////////////////////////
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
082cac3fb4c7fc60e92bbd4de269550801dcea6bmikloshAlignAndDistribute::AlignAndDistribute()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh : UI::Widget::Panel ("", "/dialogs/align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
082cac3fb4c7fc60e92bbd4de269550801dcea6bmiklosh randomize_bbox(),
082cac3fb4c7fc60e92bbd4de269550801dcea6bmiklosh _alignFrame(_("Align")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _distributeFrame(_("Distribute")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _rearrangeFrame(_("Rearrange")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _removeOverlapFrame(_("Remove overlaps")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _nodesFrame(_("Nodes")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _alignTable(2, 6, true),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _distributeTable(2, 6, true),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _rearrangeTable(1, 5, false),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _removeOverlapTable(1, 5, false),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _nodesTable(1, 4, true),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _anchorLabel(_("Relative to: ")),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _selgrpLabel(_("_Treat selection as group: "), 1)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
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"),
77364929ced3ec0bc5c9f47440606615c559084emiklosh 0, 0);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addAlignButton(INKSCAPE_ICON("align-horizontal-left"),
77364929ced3ec0bc5c9f47440606615c559084emiklosh _("Align left edges"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 1);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-center"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Center on vertical axis"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 2);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-right"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align right sides"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 3);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-horizontal-left-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align left edges of objects to the right edge of the anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 4);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-bottom-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align bottom edges of objects to the top edge of the anchor"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 1, 0);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addAlignButton(INKSCAPE_ICON("align-vertical-top"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Align top edges"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 1, 1);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addAlignButton(INKSCAPE_ICON("align-vertical-center"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Center on horizontal axis"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 1, 2);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-bottom"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align bottom edges"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 3);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addAlignButton(INKSCAPE_ICON("align-vertical-top-to-anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align top edges of objects to the bottom edge of the anchor"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 4);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh //Baseline aligns
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("align-horizontal-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Align baseline anchors of texts horizontally"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh 0, 5, this->align_table(), Geom::X, false);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("align-vertical-baseline"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _("Align baselines of texts"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 5, this->align_table(), Geom::Y, false);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //The distribute buttons
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-gaps"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Make horizontal gaps between objects equal"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 0, 4, true, Geom::X, .5, .5);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-left"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Distribute left edges equidistantly"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 0, 1, false, Geom::X, 1., 0.);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-center"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Distribute centers equidistantly horizontally"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 0, 2, false, Geom::X, .5, .5);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-horizontal-right"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _("Distribute right edges equidistantly"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh 0, 3, false, Geom::X, 0., 1.);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-gaps"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh _("Make vertical gaps between objects equal"),
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh 1, 4, true, Geom::Y, .5, .5);
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh
c4723fe0caa2096d00cb31a7d1506351ba8102dbmiklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-top"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute top edges equidistantly"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 1, false, Geom::Y, 0, 1);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-center"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute centers equidistantly vertically"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 2, false, Geom::Y, .5, .5);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addDistributeButton(INKSCAPE_ICON("distribute-vertical-bottom"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute bottom edges equidistantly"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 3, false, Geom::Y, 1., 0.);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Baseline distribs
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("distribute-horizontal-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute baseline anchors of texts horizontally"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 5, this->distribute_table(), Geom::X, true);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addBaselineButton(INKSCAPE_ICON("distribute-vertical-baseline"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute baselines of texts vertically"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 1, 5, this->distribute_table(), Geom::Y, true);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh // Rearrange
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Graph Layout
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addGraphLayoutButton(INKSCAPE_ICON("distribute-graph"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Nicely arrange selected connector network"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 0);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsButton(INKSCAPE_ICON("exchange-positions"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - selection order"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 1);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsByZOrderButton(INKSCAPE_ICON("exchange-positions-zorder"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - stacking order"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 2);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addExchangePositionsClockwiseButton(INKSCAPE_ICON("exchange-positions-clockwise"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Exchange positions of selected objects - clockwise rotate"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 3);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Randomize & Unclump
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addRandomizeButton(INKSCAPE_ICON("distribute-randomize"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Randomize centers in both dimensions"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 4);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addUnclumpButton(INKSCAPE_ICON("distribute-unclump"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Unclump objects: try to equalize edge-to-edge distances"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 0, 5);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
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 0, 0);
fd39535b3a5276f8962a3f99072668f3e63421edmiklosh
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.
77364929ced3ec0bc5c9f47440606615c559084emiklosh addNodeButton(INKSCAPE_ICON("align-vertical-node"),
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 1, Geom::Y, false);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addNodeButton(INKSCAPE_ICON("distribute-horizontal-node"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute selected nodes horizontally"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh 2, Geom::X, true);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh addNodeButton(INKSCAPE_ICON("distribute-vertical-node"),
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _("Distribute selected nodes vertically"),
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh 3, Geom::Y, true);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh //Rest of the widgetry
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Last selected"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("First selected"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Biggest object"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Smallest object"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Page"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Drawing"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _combo.append_text(_("Selection"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
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
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _anchorBox.pack_start(_anchorLabel);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _anchorBox.pack_start(_combo);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrpLabel.set_mnemonic_widget(_selgrp);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrpBox.pack_start(_selgrpLabel);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrpBox.pack_start(_selgrp);
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrp.set_active(prefs->getBool("/dialogs/align/sel-as-groups"));
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh _selgrp.signal_toggled().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_selgrp_toggled));
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _alignBox.pack_start(_anchorBox);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _alignBox.pack_start(_selgrpBox);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _alignBox.pack_start(_alignTable);
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _alignFrame.add(_alignBox);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _distributeFrame.add(_distributeTable);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _rearrangeFrame.add(_rearrangeTable);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _removeOverlapFrame.add(_removeOverlapTable);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh _nodesFrame.add(_nodesTable);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh Gtk::Box *contents = _getContents();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->set_spacing(4);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh // Notebook for individual transformations
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_alignFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_distributeFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_rearrangeFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_removeOverlapFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh contents->pack_start(_nodesFrame, true, true);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh //Connect to the global tool change signal
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
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);
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh randomize_bbox = Geom::OptRect();
03e63790ef0fa2919fc5f9f3e0d018adf317919dmiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh show_all_children();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh on_tool_changed (NULL, NULL, this); // set current mode
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshAlignAndDistribute::~AlignAndDistribute()
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<Action *>::iterator it = _actionList.begin();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh it != _actionList.end();
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh it ++)
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh delete *it;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::on_ref_change(){
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh prefs->setInt("/dialogs/align/align-to", _combo.get_active_row_number());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Make blink the master
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::on_selgrp_toggled(){
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh Inkscape::Preferences *prefs = Inkscape::Preferences::get();
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh prefs->setInt("/dialogs/align/sel-as-groups", _selgrp.get_active());
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Make blink the master
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::setMode(bool nodeEdit)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Act on widgets used in node mode
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh void ( Gtk::Widget::*mNode) () = nodeEdit ?
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh &Gtk::Widget::show_all : &Gtk::Widget::hide_all;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh //Act on widgets used in selection mode
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh void ( Gtk::Widget::*mSel) () = nodeEdit ?
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh &Gtk::Widget::hide_all : &Gtk::Widget::show_all;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ((_alignFrame).*(mSel))();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ((_distributeFrame).*(mSel))();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ((_rearrangeFrame).*(mSel))();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh ((_removeOverlapFrame).*(mSel))();
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh ((_nodesFrame).*(mNode))();
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh}
e45563a3c46261d8c32014f8e516857ba01bd7b7mikloshvoid AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh new ActionAlign(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, row, col,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh *this , col + row * 5));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh guint row, guint col, bool onInterSpace,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh Geom::Dim2 orientation, float kBegin, float kEnd)
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh{
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh _actionList.push_back(
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh new ActionDistribute(
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh id, tiptext, row, col, *this ,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh onInterSpace, orientation,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh kBegin, kEnd
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh )
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext,
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh guint col, Geom::Dim2 orientation, bool distribute)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionNode(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, col,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh *this, orientation, distribute));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addRemoveOverlapsButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionRemoveOverlaps(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, row, col, *this)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addGraphLayoutButton(const Glib::ustring &id, const Glib::ustring tiptext,
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _actionList.push_back(
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh new ActionGraphLayout(
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh id, tiptext, row, col, *this)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addExchangePositionsButton(const Glib::ustring &id, const Glib::ustring tiptext,
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh new ActionExchangePositions(
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh id, tiptext, row, col, *this)
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh );
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh}
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8mikloshvoid AlignAndDistribute::addExchangePositionsByZOrderButton(const Glib::ustring &id, const Glib::ustring tiptext,
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh new ActionExchangePositions(
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh id, tiptext, row, col, *this, ActionExchangePositions::ZOrder)
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh );
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamikloshvoid AlignAndDistribute::addExchangePositionsClockwiseButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionExchangePositions(
522aa9b8f493ba0c8e8b0bb536a563c96f5430a8miklosh id, tiptext, row, col, *this, ActionExchangePositions::Clockwise)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addUnclumpButton(const Glib::ustring &id, const Glib::ustring tiptext,
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionUnclump(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, row, col, *this)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addRandomizeButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionRandomize(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, row, col, *this)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh );
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshvoid AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib::ustring tiptext,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute)
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh{
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh _actionList.push_back(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh new ActionBaseline(
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh id, tiptext, row, col,
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh *this, table, orientation, distribute));
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshstd::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem *> &list, bool horizontal){
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh std::list<SPItem *>::iterator master = list.end();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh switch (getAlignTarget()) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh case LAST:
797add969622b3786436365fdd275aff9a9a6373miklosh return list.begin();
797add969622b3786436365fdd275aff9a9a6373miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh case FIRST:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return --(list.end());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh case BIGGEST:
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble max = -1e18;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::OptRect b = (*it)->getBboxDesktop ();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (b) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (dim > max) {
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh max = dim;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh master = it;
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
7ec85862d9730e449ed5c2a86201bc9ca1daa0aamiklosh }
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return master;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh case SMALLEST:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble max = 1e18;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Geom::OptRect b = (*it)->getBboxDesktop ();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (b) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh if (dim < max) {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh max = dim;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh master = it;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return master;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh }
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh default:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh g_assert_not_reached ();
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh break;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh } // end of switch statement
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return master;
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322mikloshAlignAndDistribute::AlignTarget AlignAndDistribute::getAlignTarget()const {
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh return AlignTarget(_combo.get_active_row_number());
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh}
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh
e45563a3c46261d8c32014f8e516857ba01bd7b7miklosh} // namespace Dialog
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace UI
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh} // namespace Inkscape
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh/*
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh Local Variables:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh mode:c++
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 End:
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh*/
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
3711b3e25395437ee0a09dbbb2a76d999c4ef322miklosh