Code

Add option to align & distribute dialog to treat the selection as a group (closes...
[inkscape.git] / src / ui / dialog / align-and-distribute.cpp
index 7d4820663b319e47bc1631218a1f1d5631601e75..627f10c0c4c12c3ab1ba0ee0d8f7013729b886f8 100644 (file)
@@ -122,6 +122,8 @@ private :
         Inkscape::Selection *selection = sp_desktop_selection(desktop);
         if (!selection) return;
 
+        bool sel_as_group = (prefs_get_int_attribute("dialogs.align", "sel-as-groups", 0) != 0);
+
         using Inkscape::Util::GSListConstIterator;
         std::list<SPItem *> selected;
         selected.insert<GSListConstIterator<SPItem *> >(selected.end(), selection->itemList(), NULL);
@@ -151,9 +153,11 @@ private :
                 );
             //remove the master from the selection
             SPItem * thing = *master;
-            selected.erase(master);
+            if (!sel_as_group) {
+                selected.erase(master);
+            }
             //Compute the anchor point
-            NR::Maybe<NR::Rect> b = sp_item_bbox_desktop (thing);
+            boost::optional<NR::Rect> 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]);
@@ -170,7 +174,7 @@ private :
 
         case AlignAndDistribute::DRAWING:
         {
-            NR::Maybe<NR::Rect> b = sp_item_bbox_desktop
+            boost::optional<NR::Rect> b = sp_item_bbox_desktop
                 ( (SPItem *) sp_document_root (sp_desktop_document (desktop)) );
             if (b) {
                 mp = Geom::Point(a.mx0 * b->min()[Geom::X] + a.mx1 * b->max()[Geom::X],
@@ -183,7 +187,7 @@ private :
 
         case AlignAndDistribute::SELECTION:
         {
-            NR::Maybe<NR::Rect> b =  selection->bounds();
+            boost::optional<NR::Rect> 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]);
@@ -208,16 +212,21 @@ private :
         prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
 
         bool changed = false;
-        //Move each item in the selected list
+        boost::optional<NR::Rect> 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::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
+            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]);
+                                     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, NR::translate(mp_rel));
@@ -318,7 +327,7 @@ private :
             it != selected.end();
             ++it)
         {
-            NR::Maybe<NR::Rect> bbox = sp_item_bbox_desktop(*it);
+            boost::optional<NR::Rect> bbox = sp_item_bbox_desktop(*it);
             if (bbox) {
                 sorted.push_back(BBoxSort(*it, to_2geom(*bbox), _orientation, _kBegin, _kEnd));
             }
@@ -590,7 +599,7 @@ private :
         //Check 2 or more selected objects
         if (selected.size() < 2) return;
 
-        NR::Maybe<NR::Rect> sel_bbox = selection->bounds();
+        boost::optional<NR::Rect> sel_bbox = selection->bounds();
         if (!sel_bbox) {
             return;
         }
@@ -611,7 +620,7 @@ private :
             ++it)
         {
             sp_document_ensure_up_to_date(sp_desktop_document (desktop));
-            NR::Maybe<NR::Rect> item_box = sp_item_bbox_desktop (*it);
+            boost::optional<NR::Rect> 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).extent(Geom::X)/2 +
@@ -694,7 +703,7 @@ private :
         {
             if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
                 Inkscape::Text::Layout const *layout = te_get_layout(*it);
-                Geom::Point base = layout->characterAnchorPoint(layout->begin()) * from_2geom(sp_item_i2d_affine(*it));
+                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];
@@ -735,7 +744,7 @@ private :
             {
                 if (SP_IS_TEXT (*it) || SP_IS_FLOWTEXT (*it)) {
                     Inkscape::Text::Layout const *layout = te_get_layout(*it);
-                    Geom::Point base = layout->characterAnchorPoint(layout->begin()) * from_2geom(sp_item_i2d_affine(*it));
+                    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));
@@ -762,7 +771,7 @@ void on_tool_changed(Inkscape::Application */*inkscape*/, SPEventContext */*cont
 
 void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad)
 {
-    daad->randomize_bbox = NR::Nothing();
+    daad->randomize_bbox = boost::optional<Geom::Rect>();
 }
 
 /////////////////////////////////////////////////////////
@@ -772,7 +781,7 @@ void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selecti
 
 AlignAndDistribute::AlignAndDistribute()
     : UI::Widget::Panel ("", "dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE),
-      randomize_bbox(NR::Nothing()),
+      randomize_bbox(),
       _alignFrame(_("Align")),
       _distributeFrame(_("Distribute")),
       _removeOverlapFrame(_("Remove overlaps")),
@@ -783,7 +792,8 @@ AlignAndDistribute::AlignAndDistribute()
       _removeOverlapTable(1, 5, false),
       _graphLayoutTable(1, 5, false),
       _nodesTable(1, 4, true),
-      _anchorLabel(_("Relative to: "))
+      _anchorLabel(_("Relative to: ")),
+      _selgrpLabel(_("Treat selection as group: "))
 {
 
     //Instanciate the align buttons
@@ -910,7 +920,13 @@ AlignAndDistribute::AlignAndDistribute()
     _anchorBox.pack_start(_anchorLabel);
     _anchorBox.pack_start(_combo);
 
+    _selgrpBox.pack_start(_selgrpLabel);
+    _selgrpBox.pack_start(_selgrp);
+    _selgrp.set_active(prefs_get_int_attribute("dialogs.align", "sel-as-groups", 0));
+    _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);
@@ -935,7 +951,7 @@ AlignAndDistribute::AlignAndDistribute()
 
     // 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::Nothing();
+    randomize_bbox = boost::optional<Geom::Rect>();
 
     show_all_children();
 
@@ -959,6 +975,13 @@ void AlignAndDistribute::on_ref_change(){
     //Make blink the master
 }
 
+void AlignAndDistribute::on_selgrp_toggled(){
+
+    prefs_set_int_attribute("dialogs.align", "sel-as-groups", _selgrp.get_active());
+
+    //Make blink the master
+}
+
 
 
 
@@ -1073,7 +1096,7 @@ 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::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
+            boost::optional<NR::Rect> b = sp_item_bbox_desktop (*it);
             if (b) {
                 gdouble dim = (*b).extent(horizontal ? Geom::X : Geom::Y);
                 if (dim > max) {
@@ -1090,7 +1113,7 @@ 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::Maybe<NR::Rect> b = sp_item_bbox_desktop (*it);
+            boost::optional<NR::Rect> b = sp_item_bbox_desktop (*it);
             if (b) {
                 gdouble dim = (*b).extent(horizontal ? Geom::X : Geom::Y);
                 if (dim < max) {