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