index 81bce14c30ea84b4de0f23a3bea0ec793ae33874..3203816d36f96850cdd956bade4456b46d03c163 100644 (file)
-/**
- * \brief Align and Distribute dialog
- *
- * Authors:
+/** @file
+ * @brief Align and Distribute dialog - implementation
+ */
+/* Authors:
* Bryce W. Harrington <bryce@bryceharrington.org>
* Aubanel MONNIER <aubi@libertysurf.fr>
* Frank Felfe <innerspace@iname.com>
#include "desktop-handles.h"
#include "macros.h"
#include "sp-item-transform.h"
-#include "prefs-utils.h"
+#include "preferences.h"
#include "enums.h"
#include "sp-text.h"
#include "sp-flowtext.h"
#include "text-editing.h"
-#include "node-context.h" //For node align/distribute function
+#include "node-context.h" //For access to ShapeEditor
+#include "shape-editor.h" //For node align/distribute methods
#include "tools-switch.h"
public :
struct Coeffs {
double mx0, mx1, my0, my1;
- double sx0, sx1, sy0, sy1;
+ double sx0, sx1, sy0, sy1;
};
ActionAlign(const Glib::ustring &id,
const Glib::ustring &tiptext,
virtual void on_button_click() {
//Retreive selected objects
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDesktop *desktop = _dialog.getDesktop();
if (!desktop) return;
Inkscape::Selection *selection = sp_desktop_selection(desktop);
if (!selection) return;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool sel_as_group = prefs->getBool("/dialogs/align/sel-as-groups");
+
using Inkscape::Util::GSListConstIterator;
std::list<SPItem *> selected;
selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
if (selected.empty()) return;
- NR::Point mp; //Anchor point
+ Geom::Point mp; //Anchor point
AlignAndDistribute::AlignTarget target = _dialog.getAlignTarget();
const Coeffs &a= _allCoeffs[_index];
switch (target)
);
//remove the master from the selection
SPItem * thing = *master;
- selected.erase(master);
+ // TODO: either uncomment or remove the following commented lines, depending on which
+ // behaviour of moving objects makes most sense; also cf. discussion at
+ // https://bugs.launchpad.net/inkscape/+bug/255933
+ /*if (!sel_as_group) { */
+ selected.erase(master);
+ /*}*/
//Compute the anchor point
- NR::Rect b = sp_item_bbox_desktop (thing);
- mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
- a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ Geom::OptRect b = sp_item_bbox_desktop (thing);
+ if (b) {
+ mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
+ a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
+ } else {
+ return;
+ }
break;
}
case AlignAndDistribute::PAGE:
- mp = NR::Point(a.mx1 * sp_document_width(sp_desktop_document(desktop)),
+ mp = Geom::Point(a.mx1 * sp_document_width(sp_desktop_document(desktop)),
a.my1 * sp_document_height(sp_desktop_document(desktop)));
break;
case AlignAndDistribute::DRAWING:
{
- NR::Rect b = sp_item_bbox_desktop
+ Geom::OptRect b = sp_item_bbox_desktop
( (SPItem *) sp_document_root (sp_desktop_document (desktop)) );
- mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
- a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ if (b) {
+ mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
+ a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
+ } else {
+ return;
+ }
break;
}
case AlignAndDistribute::SELECTION:
{
- NR::Rect b = selection->bounds();
- mp = NR::Point(a.mx0 * b.min()[NR::X] + a.mx1 * b.max()[NR::X],
- a.my0 * b.min()[NR::Y] + a.my1 * b.max()[NR::Y]);
+ Geom::OptRect b = selection->bounds();
+ if (b) {
+ mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
+ a.my0 * b->min()[Geom::Y] + a.my1 * b->max()[Geom::Y]);
+ } else {
+ return;
+ }
break;
}
// a selected original, they will be unmoved too, possibly contrary to user's
// expecation. However this is a minor point compared to making align/distribute always
// work as expected, and "unmoved" is the default option anyway.
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
bool changed = false;
- //Move each item in the selected list
+ Geom::OptRect b;
+ if (sel_as_group)
+ b = selection->bounds();
+
+ //Move each item in the selected list separately
for (std::list<SPItem *>::iterator it(selected.begin());
it != selected.end();
it++)
{
sp_document_ensure_up_to_date(sp_desktop_document (desktop));
- NR::Rect b = sp_item_bbox_desktop (*it);
- NR::Point const sp(a.sx0 * b.min()[NR::X] + a.sx1 * b.max()[NR::X],
- a.sy0 * b.min()[NR::Y] + a.sy1 * b.max()[NR::Y]);
- NR::Point const mp_rel( mp - sp );
- if (LInfty(mp_rel) > 1e-9) {
- sp_item_move_rel(*it, NR::translate(mp_rel));
- changed = true;
+ if (!sel_as_group)
+ b = sp_item_bbox_desktop (*it);
+ if (b) {
+ Geom::Point const sp(a.sx0 * b->min()[Geom::X] + a.sx1 * b->max()[Geom::X],
+ a.sy0 * b->min()[Geom::Y] + a.sy1 * b->max()[Geom::Y]);
+ Geom::Point const mp_rel( mp - sp );
+ if (LInfty(mp_rel) > 1e-9) {
+ sp_item_move_rel(*it, Geom::Translate(mp_rel));
+ changed = true;
+ }
}
}
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
if (changed) {
sp_document_done ( sp_desktop_document (desktop) , SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
{0., 0., 1., 0., 0., 0., 0., 1.}
};
-struct BBoxSort
-{
- SPItem *item;
- float anchor;
- NR::Rect bbox;
- BBoxSort(SPItem *pItem, NR::Dim2 orientation, double kBegin, double kEnd) :
+BBoxSort::BBoxSort(SPItem *pItem, Geom::Rect bounds, Geom::Dim2 orientation, double kBegin, double kEnd) :
item(pItem),
- bbox (sp_item_bbox_desktop (pItem))
- {
+ bbox (bounds)
+{
anchor = kBegin * bbox.min()[orientation] + kEnd * bbox.max()[orientation];
- }
- BBoxSort(const BBoxSort &rhs):
+}
+BBoxSort::BBoxSort(const BBoxSort &rhs) :
//NOTE : this copy ctor is called O(sort) when sorting the vector
//this is bad. The vector should be a vector of pointers.
//But I'll wait the bohem GC before doing that
- item(rhs.item), anchor(rhs.anchor), bbox(rhs.bbox) {
- }
-};
+ item(rhs.item), anchor(rhs.anchor), bbox(rhs.bbox)
+{
+}
+
bool operator< (const BBoxSort &a, const BBoxSort &b)
{
return (a.anchor < b.anchor);
guint row, guint column,
AlignAndDistribute &dialog,
bool onInterSpace,
- NR::Dim2 orientation,
+ Geom::Dim2 orientation,
double kBegin, double kEnd
):
Action(id, tiptext, row, column,
private :
virtual void on_button_click() {
//Retreive selected objects
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDesktop *desktop = _dialog.getDesktop();
if (!desktop) return;
Inkscape::Selection *selection = sp_desktop_selection(desktop);
it != selected.end();
++it)
{
- BBoxSort b (*it, _orientation, _kBegin, _kEnd);
- sorted.push_back(b);
+ Geom::OptRect bbox = sp_item_bbox_desktop(*it);
+ if (bbox) {
+ sorted.push_back(BBoxSort(*it, *bbox, _orientation, _kBegin, _kEnd));
+ }
}
//sort bbox by anchors
std::sort(sorted.begin(), sorted.end());
// see comment in ActionAlign above
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
unsigned int len = sorted.size();
bool changed = false;
float span = 0;
for (unsigned int i = 0; i < len; i++)
{
- span += sorted[i].bbox.extent(_orientation);
+ span += sorted[i].bbox[_orientation].extent();
}
//new distance between each bbox
float step = (dist - span) / (len - 1);
it ++ )
{
if (!NR_DF_TEST_CLOSE (pos, it->bbox.min()[_orientation], 1e-6)) {
- NR::Point t(0.0, 0.0);
+ Geom::Point t(0.0, 0.0);
t[_orientation] = pos - it->bbox.min()[_orientation];
- sp_item_move_rel(it->item, NR::translate(t));
+ sp_item_move_rel(it->item, Geom::Translate(t));
changed = true;
}
- pos += it->bbox.extent(_orientation);
+ pos += it->bbox[_orientation].extent();
pos += step;
}
}
//Don't move if we are really close
if (!NR_DF_TEST_CLOSE (pos, it.anchor, 1e-6)) {
//Compute translation
- NR::Point t(0.0, 0.0);
+ Geom::Point t(0.0, 0.0);
t[_orientation] = pos - it.anchor;
//translate
- sp_item_move_rel(it.item, NR::translate(t));
+ sp_item_move_rel(it.item, Geom::Translate(t));
changed = true;
}
}
}
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
if (changed) {
- sp_document_done ( sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done ( sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Distribute"));
}
}
guint _index;
AlignAndDistribute &_dialog;
bool _onInterSpace;
- NR::Dim2 _orientation;
+ Geom::Dim2 _orientation;
double _kBegin;
double _kEnd;
const Glib::ustring &tiptext,
guint column,
AlignAndDistribute &dialog,
- NR::Dim2 orientation, bool distribute):
+ Geom::Dim2 orientation, bool distribute):
Action(id, tiptext, 0, column,
dialog.nodes_table(), dialog.tooltips(), dialog),
_orientation(orientation),
{}
private :
- NR::Dim2 _orientation;
+ Geom::Dim2 _orientation;
bool _distribute;
virtual void on_button_click()
{
- if (!SP_ACTIVE_DESKTOP) return;
- SPEventContext *event_context = sp_desktop_event_context(SP_ACTIVE_DESKTOP);
- if (!SP_IS_NODE_CONTEXT (event_context)) return ;
+ if (!_dialog.getDesktop()) return;
+ SPEventContext *event_context = sp_desktop_event_context(_dialog.getDesktop());
+ if (!SP_IS_NODE_CONTEXT (event_context)) return ;
- Inkscape::NodePath::Path *nodepath = SP_NODE_CONTEXT (event_context)->nodepath;
- if (!nodepath) return;
if (_distribute)
- sp_nodepath_selected_distribute(nodepath, _orientation);
+ event_context->shape_editor->distribute((Geom::Dim2)_orientation);
else
- sp_nodepath_selected_align(nodepath, _orientation);
+ event_context->shape_editor->align((Geom::Dim2)_orientation);
}
};
dialog.removeOverlap_table(), dialog.tooltips(), dialog)
{
dialog.removeOverlap_table().set_col_spacings(3);
-
+
removeOverlapXGap.set_digits(1);
removeOverlapXGap.set_size_request(60, -1);
removeOverlapXGap.set_increments(1.0, 5.0);
removeOverlapXGap.set_value(0);
dialog.tooltips().set_tip(removeOverlapXGap,
_("Minimum horizontal gap (in px units) between bounding boxes"));
- /* TRANSLATORS: Horizontal gap */
- removeOverlapXGapLabel.set_label(_("H:"));
+ /* TRANSLATORS: Horizontal gap. Only put "H:" equivalent in the translation */
+ removeOverlapXGapLabel.set_label(Q_("gap|H:"));
removeOverlapYGap.set_digits(1);
removeOverlapYGap.set_size_request(60, -1);
private :
virtual void on_button_click()
{
- if (!SP_ACTIVE_DESKTOP) return;
+ if (!_dialog.getDesktop()) return;
// see comment in ActionAlign above
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
// xGap and yGap are the minimum space required between bounding rectangles.
double const xGap = removeOverlapXGap.get_value();
double const yGap = removeOverlapYGap.get_value();
- removeoverlap(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList(),
+ removeoverlap(sp_desktop_selection(_dialog.getDesktop())->itemList(),
xGap, yGap);
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
- sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Remove overlaps"));
}
};
private :
virtual void on_button_click()
{
- if (!SP_ACTIVE_DESKTOP) return;
+ if (!_dialog.getDesktop()) return;
// see comment in ActionAlign above
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
- graphlayout(sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
+ graphlayout(sp_desktop_selection(_dialog.getDesktop())->itemList());
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
- sp_document_done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done(sp_desktop_document(_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Arrange connector network"));
}
};
private :
virtual void on_button_click()
{
- if (!SP_ACTIVE_DESKTOP) return;
+ if (!_dialog.getDesktop()) return;
// see comment in ActionAlign above
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
- unclump ((GSList *) sp_desktop_selection(SP_ACTIVE_DESKTOP)->itemList());
+ unclump ((GSList *) sp_desktop_selection(_dialog.getDesktop())->itemList());
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
- sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done (sp_desktop_document (_dialog.getDesktop()), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Unclump"));
}
};
private :
virtual void on_button_click()
{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDesktop *desktop = _dialog.getDesktop();
if (!desktop) return;
Inkscape::Selection *selection = sp_desktop_selection(desktop);
//Check 2 or more selected objects
if (selected.size() < 2) return;
+ Geom::OptRect sel_bbox = selection->bounds();
+ if (!sel_bbox) {
+ return;
+ }
+
// This bbox is cached between calls to randomize, so that there's no growth nor shrink
// nor drift on sequential randomizations. Discard cache on global (or better active
// desktop's) selection_change signal.
- if (!_dialog.randomize_bbox_set) {
- _dialog.randomize_bbox = selection->bounds();
- _dialog.randomize_bbox_set = true;
+ if (!_dialog.randomize_bbox) {
+ _dialog.randomize_bbox = *sel_bbox;
}
// see comment in ActionAlign above
- int saved_compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
- prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ int saved_compensation = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
+ prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED);
for (std::list<SPItem *>::iterator it(selected.begin());
it != selected.end();
++it)
{
sp_document_ensure_up_to_date(sp_desktop_document (desktop));
- NR::Rect item_box = sp_item_bbox_desktop (*it);
- // find new center, staying within bbox
- double x = _dialog.randomize_bbox.min()[NR::X] + item_box.extent(NR::X)/2 +
- g_random_double_range (0, _dialog.randomize_bbox.extent(NR::X) - item_box.extent(NR::X));
- double y = _dialog.randomize_bbox.min()[NR::Y] + item_box.extent(NR::Y)/2 +
- g_random_double_range (0, _dialog.randomize_bbox.extent(NR::Y) - item_box.extent(NR::Y));
- // displacement is the new center minus old:
- NR::Point t = NR::Point (x, y) - 0.5*(item_box.max() + item_box.min());
- sp_item_move_rel(*it, NR::translate(t));
+ Geom::OptRect item_box = sp_item_bbox_desktop (*it);
+ if (item_box) {
+ // find new center, staying within bbox
+ double x = _dialog.randomize_bbox->min()[Geom::X] + (*item_box)[Geom::X].extent() /2 +
+ g_random_double_range (0, (*_dialog.randomize_bbox)[Geom::X].extent() - (*item_box)[Geom::X].extent());
+ double y = _dialog.randomize_bbox->min()[Geom::Y] + (*item_box)[Geom::Y].extent()/2 +
+ g_random_double_range (0, (*_dialog.randomize_bbox)[Geom::Y].extent() - (*item_box)[Geom::Y].extent());
+ // displacement is the new center minus old:
+ Geom::Point t = Geom::Point (x, y) - 0.5*(item_box->max() + item_box->min());
+ sp_item_move_rel(*it, Geom::Translate(t));
+ }
}
// restore compensation setting
- prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
+ prefs->setInt("/options/clonecompensation/value", saved_compensation);
- sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Randomize positions"));
}
};
struct Baselines
{
SPItem *_item;
- NR::Point _base;
- NR::Dim2 _orientation;
- Baselines(SPItem *item, NR::Point base, NR::Dim2 orientation) :
+ Geom::Point _base;
+ Geom::Dim2 _orientation;
+ Baselines(SPItem *item, Geom::Point base, Geom::Dim2 orientation) :
_item (item),
_base (base),
_orientation (orientation)
guint column,
AlignAndDistribute &dialog,
Gtk::Table &table,
- NR::Dim2 orientation, bool distribute):
+ Geom::Dim2 orientation, bool distribute):
Action(id, tiptext, row, column,
table, dialog.tooltips(), dialog),
_orientation(orientation),
{}
private :
- NR::Dim2 _orientation;
+ Geom::Dim2 _orientation;
bool _distribute;
virtual void on_button_click()
{
- SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPDesktop *desktop = _dialog.getDesktop();
if (!desktop) return;
Inkscape::Selection *selection = sp_desktop_selection(desktop);
//Check 2 or more selected objects
if (selected.size() < 2) return;
- NR::Point b_min = NR::Point (HUGE_VAL, HUGE_VAL);
- NR::Point b_max = NR::Point (-HUGE_VAL, -HUGE_VAL);
+ Geom::Point b_min = Geom::Point (HUGE_VAL, HUGE_VAL);
+ Geom::Point b_max = Geom::Point (-HUGE_VAL, -HUGE_VAL);
std::vector<Baselines> sorted;
{
if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
Inkscape::Text::Layout const *layout = te_get_layout(*it);
- NR::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
- if (base[NR::X] < b_min[NR::X]) b_min[NR::X] = base[NR::X];
- if (base[NR::Y] < b_min[NR::Y]) b_min[NR::Y] = base[NR::Y];
- if (base[NR::X] > b_max[NR::X]) b_max[NR::X] = base[NR::X];
- if (base[NR::Y] > b_max[NR::Y]) b_max[NR::Y] = base[NR::Y];
+ Geom::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
+ if (base[Geom::X] < b_min[Geom::X]) b_min[Geom::X] = base[Geom::X];
+ if (base[Geom::Y] < b_min[Geom::Y]) b_min[Geom::Y] = base[Geom::Y];
+ if (base[Geom::X] > b_max[Geom::X]) b_max[Geom::X] = base[Geom::X];
+ if (base[Geom::Y] > b_max[Geom::Y]) b_max[Geom::Y] = base[Geom::Y];
Baselines b (*it, base, _orientation);
sorted.push_back(b);
double step = (b_max[_orientation] - b_min[_orientation])/(sorted.size() - 1);
for (unsigned int i = 0; i < sorted.size(); i++) {
SPItem *item = sorted[i]._item;
- NR::Point base = sorted[i]._base;
- NR::Point t(0.0, 0.0);
+ Geom::Point base = sorted[i]._base;
+ Geom::Point t(0.0, 0.0);
t[_orientation] = b_min[_orientation] + step * i - base[_orientation];
- sp_item_move_rel(item, NR::translate(t));
+ sp_item_move_rel(item, Geom::Translate(t));
changed = true;
}
if (changed) {
- sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Distribute text baselines"));
}
{
if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
Inkscape::Text::Layout const *layout = te_get_layout(*it);
- NR::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
- NR::Point t(0.0, 0.0);
+ Geom::Point base = layout->characterAnchorPoint(layout->begin()) * sp_item_i2d_affine(*it);
+ Geom::Point t(0.0, 0.0);
t[_orientation] = b_min[_orientation] - base[_orientation];
- sp_item_move_rel(*it, NR::translate(t));
+ sp_item_move_rel(*it, Geom::Translate(t));
changed = true;
}
}
if (changed) {
- sp_document_done (sp_desktop_document (SP_ACTIVE_DESKTOP), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
+ sp_document_done (sp_desktop_document (desktop), SP_VERB_DIALOG_ALIGN_DISTRIBUTE,
_("Align text baselines"));
}
}
-void on_tool_changed(Inkscape::Application *inkscape, SPEventContext *context, AlignAndDistribute *daad)
+void on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*context*/, AlignAndDistribute *daad)
{
SPDesktop *desktop = SP_ACTIVE_DESKTOP;
if (desktop && sp_desktop_event_context(desktop))
daad->setMode(tools_active(desktop) == TOOLS_NODES);
}
-void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *selection, AlignAndDistribute *daad)
+void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
{
- daad->randomize_bbox_set = false;
+ daad->randomize_bbox = Geom::OptRect();
}
/////////////////////////////////////////////////////////
@@ -753,9 +788,9 @@ void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection *
-AlignAndDistribute::AlignAndDistribute()
- : Dialog ("dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
- randomize_bbox (NR::Point (0, 0), NR::Point (0, 0)),
+AlignAndDistribute::AlignAndDistribute()
+ : UI::Widget::Panel ("", "/dialogs/align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
+ randomize_bbox(),
_alignFrame(_("Align")),
_distributeFrame(_("Distribute")),
_removeOverlapFrame(_("Remove overlaps")),
_removeOverlapTable(1, 5, false),
_graphLayoutTable(1, 5, false),
_nodesTable(1, 4, true),
- _anchorLabel(_("Relative to: "))
+ _anchorLabel(_("Relative to: ")),
+ _selgrpLabel(_("Treat selection as group: "))
{
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
//Instanciate the align buttons
addAlignButton("al_left_out",
//Baseline aligns
addBaselineButton("al_baselines_vert",
_("Align baseline anchors of texts vertically"),
- 0, 5, this->align_table(), NR::X, false);
+ 0, 5, this->align_table(), Geom::X, false);
addBaselineButton("al_baselines_hor",
_("Align baseline anchors of texts horizontally"),
- 1, 5, this->align_table(), NR::Y, false);
+ 1, 5, this->align_table(), Geom::Y, false);
//The distribute buttons
addDistributeButton("distribute_hdist",
_("Make horizontal gaps between objects equal"),
- 0, 4, true, NR::X, .5, .5);
+ 0, 4, true, Geom::X, .5, .5);
addDistributeButton("distribute_left",
_("Distribute left sides equidistantly"),
- 0, 1, false, NR::X, 1., 0.);
+ 0, 1, false, Geom::X, 1., 0.);
addDistributeButton("distribute_hcentre",
_("Distribute centers equidistantly horizontally"),
- 0, 2, false, NR::X, .5, .5);
+ 0, 2, false, Geom::X, .5, .5);
addDistributeButton("distribute_right",
_("Distribute right sides equidistantly"),
- 0, 3, false, NR::X, 0., 1.);
+ 0, 3, false, Geom::X, 0., 1.);
addDistributeButton("distribute_vdist",
_("Make vertical gaps between objects equal"),
- 1, 4, true, NR::Y, .5, .5);
+ 1, 4, true, Geom::Y, .5, .5);
addDistributeButton("distribute_top",
_("Distribute tops equidistantly"),
- 1, 1, false, NR::Y, 0, 1);
+ 1, 1, false, Geom::Y, 0, 1);
addDistributeButton("distribute_vcentre",
_("Distribute centers equidistantly vertically"),
- 1, 2, false, NR::Y, .5, .5);
+ 1, 2, false, Geom::Y, .5, .5);
addDistributeButton("distribute_bottom",
_("Distribute bottoms equidistantly"),
- 1, 3, false, NR::Y, 1., 0.);
+ 1, 3, false, Geom::Y, 1., 0.);
//Baseline distribs
addBaselineButton("distribute_baselines_hor",
_("Distribute baseline anchors of texts horizontally"),
- 0, 5, this->distribute_table(), NR::X, true);
+ 0, 5, this->distribute_table(), Geom::X, true);
addBaselineButton("distribute_baselines_vert",
_("Distribute baseline anchors of texts vertically"),
- 1, 5, this->distribute_table(), NR::Y, true);
+ 1, 5, this->distribute_table(), Geom::Y, true);
//Randomize & Unclump
addRandomizeButton("distribute_randomize",
//Node Mode buttons
addNodeButton("node_halign",
_("Align selected nodes horizontally"),
- 0, NR::X, false);
+ 0, Geom::X, false);
addNodeButton("node_valign",
_("Align selected nodes vertically"),
- 1, NR::Y, false);
+ 1, Geom::Y, false);
addNodeButton("node_hdistribute",
_("Distribute selected nodes horizontally"),
- 2, NR::X, true);
+ 2, Geom::X, true);
addNodeButton("node_vdistribute",
_("Distribute selected nodes vertically"),
- 3, NR::Y, true);
+ 3, Geom::Y, true);
//Rest of the widgetry
_combo.append_text(_("Drawing"));
_combo.append_text(_("Selection"));
- _combo.set_active(6);
+ _combo.set_active(prefs->getInt("/dialogs/align/align-to", 6));
_combo.signal_changed().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_ref_change));
_anchorBox.pack_start(_anchorLabel);
_anchorBox.pack_start(_combo);
+ _selgrpBox.pack_start(_selgrpLabel);
+ _selgrpBox.pack_start(_selgrp);
+ _selgrp.set_active(prefs->getBool("/dialogs/align/sel-as-groups"));
+ _selgrp.signal_toggled().connect(sigc::mem_fun(*this, &AlignAndDistribute::on_selgrp_toggled));
+
_alignBox.pack_start(_anchorBox);
+ _alignBox.pack_start(_selgrpBox);
_alignBox.pack_start(_alignTable);
_alignFrame.add(_alignBox);
_graphLayoutFrame.add(_graphLayoutTable);
_nodesFrame.add(_nodesTable);
- // Top level vbox
- Gtk::VBox *vbox = get_vbox();
- vbox->set_spacing(4);
+ Gtk::Box *contents = _getContents();
+ contents->set_spacing(4);
// Notebook for individual transformations
- vbox->pack_start(_alignFrame, true, true);
- vbox->pack_start(_distributeFrame, true, true);
- vbox->pack_start(_removeOverlapFrame, true, true);
- vbox->pack_start(_graphLayoutFrame, true, true);
- vbox->pack_start(_nodesFrame, true, true);
+ contents->pack_start(_alignFrame, true, true);
+ contents->pack_start(_distributeFrame, true, true);
+ contents->pack_start(_removeOverlapFrame, true, true);
+ contents->pack_start(_graphLayoutFrame, true, true);
+ contents->pack_start(_nodesFrame, true, true);
//Connect to the global tool change signal
g_signal_connect (G_OBJECT (INKSCAPE), "set_eventcontext", G_CALLBACK (on_tool_changed), this);
// Connect to the global selection change, to invalidate cached randomize_bbox
g_signal_connect (G_OBJECT (INKSCAPE), "change_selection", G_CALLBACK (on_selection_changed), this);
- randomize_bbox = NR::Rect (NR::Point (0, 0), NR::Point (0, 0));
- randomize_bbox_set = false;
+ randomize_bbox = Geom::OptRect();
show_all_children();
on_tool_changed (NULL, NULL, this); // set current mode
}
-AlignAndDistribute::~AlignAndDistribute()
+AlignAndDistribute::~AlignAndDistribute()
{
sp_signal_disconnect_by_data (G_OBJECT (INKSCAPE), this);
}
void AlignAndDistribute::on_ref_change(){
-//Make blink the master
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/dialogs/align/align-to", _combo.get_active_row_number());
+
+ //Make blink the master
+}
+
+void AlignAndDistribute::on_selgrp_toggled(){
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ prefs->setInt("/dialogs/align/sel-as-groups", _selgrp.get_active());
+
+ //Make blink the master
}
@@ -972,7 +1023,7 @@ void AlignAndDistribute::addAlignButton(const Glib::ustring &id, const Glib::ust
}
void AlignAndDistribute::addDistributeButton(const Glib::ustring &id, const Glib::ustring tiptext,
guint row, guint col, bool onInterSpace,
- NR::Dim2 orientation, float kBegin, float kEnd)
+ Geom::Dim2 orientation, float kBegin, float kEnd)
{
_actionList.push_back(
new ActionDistribute(
@@ -984,7 +1035,7 @@ void AlignAndDistribute::addDistributeButton(const Glib::ustring &id, const Glib
}
void AlignAndDistribute::addNodeButton(const Glib::ustring &id, const Glib::ustring tiptext,
- guint col, NR::Dim2 orientation, bool distribute)
+ guint col, Geom::Dim2 orientation, bool distribute)
{
_actionList.push_back(
new ActionNode(
@@ -1029,11 +1080,11 @@ void AlignAndDistribute::addRandomizeButton(const Glib::ustring &id, const Glib:
}
void AlignAndDistribute::addBaselineButton(const Glib::ustring &id, const Glib::ustring tiptext,
- guint row, guint col, Gtk::Table &table, NR::Dim2 orientation, bool distribute)
+ guint row, guint col, Gtk::Table &table, Geom::Dim2 orientation, bool distribute)
{
_actionList.push_back(
new ActionBaseline(
- id, tiptext, row, col,
+ id, tiptext, row, col,
*this, table, orientation, distribute));
}
@@ -1055,11 +1106,13 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem
{
gdouble max = -1e18;
for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
- NR::Rect b = sp_item_bbox_desktop (*it);
- gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
- if (dim > max) {
- max = dim;
- master = it;
+ Geom::OptRect b = sp_item_bbox_desktop (*it);
+ if (b) {
+ gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
+ if (dim > max) {
+ max = dim;
+ master = it;
+ }
}
}
return master;
@@ -1070,11 +1123,13 @@ std::list<SPItem *>::iterator AlignAndDistribute::find_master( std::list<SPItem
{
gdouble max = 1e18;
for (std::list<SPItem *>::iterator it = list.begin(); it != list.end(); it++) {
- NR::Rect b = sp_item_bbox_desktop (*it);
- gdouble dim = b.extent(horizontal ? NR::X : NR::Y);
- if (dim < max) {
- max = dim;
- master = it;
+ Geom::OptRect b = sp_item_bbox_desktop (*it);
+ if (b) {
+ gdouble dim = (*b)[horizontal ? Geom::X : Geom::Y].extent();
+ if (dim < max) {
+ max = dim;
+ master = it;
+ }
}
}
return master;