Code

change API: separate functions creating a blur filter, one for a given item, another...
[inkscape.git] / src / selection-chemistry.cpp
index c87817a40ee8f32d48ae345ab7d7d796a2acd3bb..94e0b709ab8d519b2031e6700384541a40965778 100644 (file)
@@ -39,6 +39,9 @@
 #include "sp-flowregion.h"
 #include "text-editing.h"
 #include "text-context.h"
+#include "connector-context.h"
+#include "sp-path.h"
+#include "sp-conn-end.h"
 #include "dropper-context.h"
 #include <glibmm/i18n.h>
 #include "libnr/nr-matrix-rotate-ops.h"
@@ -62,6 +65,7 @@
 #include "sp-clippath.h"
 #include "sp-mask.h"
 #include "file.h"
+#include "helper/png-write.h"
 #include "layer-fns.h"
 #include "context-fns.h"
 #include <map>
@@ -210,7 +214,8 @@ void sp_selection_delete()
 
     if (tools_isactive (desktop, TOOLS_TEXT))
         if (sp_text_delete_selection(desktop->event_context)) {
-            sp_document_done(sp_desktop_document(desktop));
+            sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT,
+                             _("Delete text"));
             return;
         }
 
@@ -235,7 +240,8 @@ void sp_selection_delete()
      */
     tools_switch ( desktop, tools_active ( desktop ) );
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_DELETE, 
+                     _("Delete"));
 }
 
 /* fixme: sequencing */
@@ -273,7 +279,8 @@ void sp_selection_duplicate()
         Inkscape::GC::release(copy);
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_DUPLICATE, 
+                     _("Duplicate"));
 
     selection->setReprList(newsel);
 
@@ -297,7 +304,8 @@ void sp_edit_clear_all()
         items = g_slist_remove(items, items->data);
     }
 
-    sp_document_done(doc);
+    sp_document_done(doc, SP_VERB_EDIT_CLEAR_ALL,
+                     _("Delete all"));
 }
 
 GSList *
@@ -498,7 +506,8 @@ void sp_selection_group()
     // Move to the position of the topmost, reduced by the number of items deleted from topmost_parent
     group->setPosition(topmost + 1);
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_GROUP, 
+                     _("Group"));
 
     selection->set(group);
     Inkscape::GC::release(group);
@@ -559,7 +568,8 @@ void sp_selection_ungroup()
 
     g_slist_free(items);
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_UNGROUP, 
+                     _("Ungroup"));
 }
 
 static SPGroup *
@@ -660,7 +670,8 @@ sp_selection_raise()
         rev = g_slist_remove(rev, child);
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_RAISE,
+                     _("Raise"));
 }
 
 void sp_selection_raise_to_top()
@@ -695,7 +706,8 @@ void sp_selection_raise_to_top()
 
     g_slist_free(rl);
 
-    sp_document_done(document);
+    sp_document_done(document, SP_VERB_SELECTION_TO_FRONT, 
+                     _("Raise to top"));
 }
 
 void
@@ -751,7 +763,8 @@ sp_selection_lower()
         rev = g_slist_remove(rev, child);
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_LOWER, 
+                     _("Lower"));
 
 }
 
@@ -799,7 +812,8 @@ void sp_selection_lower_to_bottom()
 
     g_slist_free(rl);
 
-    sp_document_done(document);
+    sp_document_done(document, SP_VERB_SELECTION_TO_BACK, 
+                     _("Lower to bottom"));
 }
 
 void
@@ -1099,7 +1113,7 @@ void sp_selection_paste(bool in_place)
 
         /* Snap the offset of the new item(s) to the grid */
         /* FIXME: this gridsnap fiddling is a hack. */
-        Inkscape::GridSnapper &s = desktop->namedview->grid_snapper;
+        Inkscape::GridSnapper &s = desktop->namedview->snap_manager.grid;
         gdouble const curr_gridsnap = s.getDistance();
         s.setDistance(NR_HUGE);
         m = s.freeSnap(Inkscape::Snapper::SNAP_POINT, m, NULL).getPoint();
@@ -1107,7 +1121,8 @@ void sp_selection_paste(bool in_place)
         sp_selection_move_relative(selection, m);
     }
 
-    sp_document_done(document);
+    sp_document_done(document, SP_VERB_EDIT_PASTE, 
+                     _("Paste"));
 }
 
 void sp_selection_paste_style()
@@ -1133,7 +1148,8 @@ void sp_selection_paste_style()
 
     sp_desktop_set_style (desktop, style_clipboard);
 
-    sp_document_done(sp_desktop_document (desktop));
+    sp_document_done(sp_desktop_document (desktop), SP_VERB_EDIT_PASTE_STYLE,
+                     _("Paste style"));
 }
 
 void sp_selection_paste_size (bool apply_x, bool apply_y)
@@ -1168,7 +1184,8 @@ void sp_selection_paste_size (bool apply_x, bool apply_y)
                                      apply_x? scale_x : (desktop->isToolboxButtonActive ("lock")? scale_y : 1.0),
                                      apply_y? scale_y : (desktop->isToolboxButtonActive ("lock")? scale_x : 1.0)));
 
-    sp_document_done(sp_desktop_document (desktop));
+    sp_document_done(sp_desktop_document (desktop), SP_VERB_EDIT_PASTE_SIZE,
+                     _("Paste size"));
 }
 
 void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
@@ -1208,7 +1225,8 @@ void sp_selection_paste_size_separately (bool apply_x, bool apply_y)
 
     }
 
-    sp_document_done(sp_desktop_document (desktop));
+    sp_document_done(sp_desktop_document (desktop), SP_VERB_EDIT_PASTE_SIZE_SEPARATELY,
+                     _("Paste size separately"));
 }
 
 void sp_selection_to_next_layer ()
@@ -1225,18 +1243,31 @@ void sp_selection_to_next_layer ()
 
     const GSList *items = g_slist_copy ((GSList *) selection->itemList());
 
+    bool no_more = false; // Set to true, if no more layers above
     SPObject *next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer());
     if (next) {
         GSList *temp_clip = NULL;
         sp_selection_copy_impl (items, &temp_clip, NULL, NULL); // we're in the same doc, so no need to copy defs
         sp_selection_delete_impl (items);
-        GSList *copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        next=Inkscape::next_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
+        GSList *copied;
+        if(next) {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        } else {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), dt->currentLayer(), &temp_clip, NULL);
+            no_more = true;
+        }
         selection->setReprList((GSList const *) copied);
         g_slist_free (copied);
         if (temp_clip) g_slist_free (temp_clip);
-        dt->setCurrentLayer(next);
-        sp_document_done(sp_desktop_document (dt));
+        if (next) dt->setCurrentLayer(next);
+        sp_document_done(sp_desktop_document (dt), SP_VERB_LAYER_MOVE_TO_NEXT, 
+                         _("Raise to next layer"));
     } else {
+        no_more = true;
+    }
+
+    if (no_more) {
         dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers above."));
     }
 
@@ -1257,18 +1288,31 @@ void sp_selection_to_prev_layer ()
 
     const GSList *items = g_slist_copy ((GSList *) selection->itemList());
 
+    bool no_more = false; // Set to true, if no more layers below
     SPObject *next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer());
     if (next) {
         GSList *temp_clip = NULL;
         sp_selection_copy_impl (items, &temp_clip, NULL, NULL); // we're in the same doc, so no need to copy defs
         sp_selection_delete_impl (items);
-        GSList *copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        next=Inkscape::previous_layer(dt->currentRoot(), dt->currentLayer()); // Fixes bug 1482973: crash while moving layers
+        GSList *copied;
+        if(next) {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), next, &temp_clip, NULL);
+        } else {
+            copied = sp_selection_paste_impl (sp_desktop_document (dt), dt->currentLayer(), &temp_clip, NULL);
+            no_more = true;
+        }
         selection->setReprList((GSList const *) copied);
         g_slist_free (copied);
         if (temp_clip) g_slist_free (temp_clip);
-        dt->setCurrentLayer(next);
-        sp_document_done(sp_desktop_document (dt));
+        if (next) dt->setCurrentLayer(next);
+        sp_document_done(sp_desktop_document (dt), SP_VERB_LAYER_MOVE_TO_PREV,
+                         _("Lower to previous layer"));
     } else {
+        no_more = true;
+    }
+
+    if (no_more) {
         dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("No more layers below."));
     }
 
@@ -1303,7 +1347,21 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, NR::Matrix const
         bool transform_textpath_with_path = (SP_IS_TEXT_TEXTPATH(item) && selection->includes( sp_textpath_get_path_item (SP_TEXTPATH(sp_object_first_child(SP_OBJECT(item)))) ));
         bool transform_flowtext_with_frame = (SP_IS_FLOWTEXT(item) && selection->includes( SP_FLOWTEXT(item)->get_frame (NULL))); // only the first frame so far
         bool transform_offset_with_source = (SP_IS_OFFSET(item) && SP_OFFSET (item)->sourceHref) && selection->includes( sp_offset_get_source (SP_OFFSET(item)) );
-
+       
+        // If we're moving a connector, we want to detach it
+        // from shapes that aren't part of the selection, but
+        // leave it attached if they are
+        if (cc_item_is_connector(item)) {
+            SPItem *attItem[2];
+            SP_PATH(item)->connEndPair.getAttachedItems(attItem);
+            
+            for (int n = 0; n < 2; ++n) {
+                if (!selection->includes(attItem[n])) {
+                    sp_conn_end_detach(item, n);
+                }
+            }
+        }
+        
         // "clones are unmoved when original is moved" preference
         int compensation = prefs_get_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
         bool prefs_unmoved = (compensation == SP_CLONE_COMPENSATION_UNMOVED);
@@ -1396,7 +1454,8 @@ void sp_selection_remove_transform()
         l = l->next;
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_OBJECT_FLATTEN, 
+                     _("Remove transform"));
 }
 
 void
@@ -1504,7 +1563,8 @@ void sp_selection_rotate_90_cw()
         sp_item_rotate_rel(item, rot_neg_90);
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_OBJECT_ROTATE_90_CCW, 
+                     _("Rotate 90&#176; CW"));
 }
 
 
@@ -1531,7 +1591,8 @@ void sp_selection_rotate_90_ccw()
         sp_item_rotate_rel(item, rot_neg_90);
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_OBJECT_ROTATE_90_CW,
+                     _("Rotate 90&#176; CCW"));
 }
 
 void
@@ -1547,7 +1608,9 @@ sp_selection_rotate(Inkscape::Selection *selection, gdouble const angle_degrees)
     sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( ( angle_degrees > 0 )
                              ? "selector:rotate:ccw"
-                             : "selector:rotate:cw" ));
+                             : "selector:rotate:cw" ), 
+                           SP_VERB_CONTEXT_SELECT, 
+                           _("Rotate"));
 }
 
 /**
@@ -1574,7 +1637,9 @@ sp_selection_rotate_screen(Inkscape::Selection *selection, gdouble angle)
     sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( (angle > 0)
                              ? "selector:rotate:ccw"
-                             : "selector:rotate:cw" ));
+                             : "selector:rotate:cw" ),
+                           SP_VERB_CONTEXT_SELECT, 
+                           _("Rotate by pixels"));
 }
 
 void
@@ -1598,7 +1663,9 @@ sp_selection_scale(Inkscape::Selection *selection, gdouble grow)
     sp_document_maybe_done(sp_desktop_document(selection->desktop()),
                            ( (grow > 0)
                              ? "selector:scale:larger"
-                             : "selector:scale:smaller" ));
+                             : "selector:scale:smaller" ),
+                           SP_VERB_CONTEXT_SELECT,
+                           _("Scale"));
 }
 
 void
@@ -1616,7 +1683,8 @@ sp_selection_scale_times(Inkscape::Selection *selection, gdouble times)
 
     NR::Point const center(selection->bounds().midpoint());
     sp_selection_scale_relative(selection, center, NR::scale(times, times));
-    sp_document_done(sp_desktop_document(selection->desktop()));
+    sp_document_done(sp_desktop_document(selection->desktop()), SP_VERB_CONTEXT_SELECT, 
+                     _("Scale by whole factor"));
 }
 
 void
@@ -1631,11 +1699,14 @@ sp_selection_move(gdouble dx, gdouble dy)
     sp_selection_move_relative(selection, dx, dy);
 
     if (dx == 0) {
-        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT, 
+                               _("Move vertically"));
     } else if (dy == 0) {
-        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, 
+                               _("Move horizontally"));
     } else {
-        sp_document_done(sp_desktop_document(desktop));
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT, 
+                         _("Move"));
     }
 }
 
@@ -1656,11 +1727,14 @@ sp_selection_move_screen(gdouble dx, gdouble dy)
     sp_selection_move_relative(selection, zdx, zdy);
 
     if (dx == 0) {
-        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:vertical", SP_VERB_CONTEXT_SELECT, 
+                               _("Nudge vertically by pixels"));
     } else if (dy == 0) {
-        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal");
+        sp_document_maybe_done(sp_desktop_document(desktop), "selector:move:horizontal", SP_VERB_CONTEXT_SELECT, 
+                               _("Nudge horizontally by pixels"));
     } else {
-        sp_document_done(sp_desktop_document(desktop));
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_SELECT, 
+                         _("Move"));
     }
 }
 
@@ -1920,7 +1994,8 @@ sp_selection_clone()
         Inkscape::GC::release(clone);
     }
     
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_CLONE, 
+                     _("Clone"));
 
     selection->setReprList(newsel);
  
@@ -1971,7 +2046,8 @@ sp_selection_unlink()
         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No clones to unlink</b> in the selection."));
     }
 
-    sp_document_done(sp_desktop_document(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_UNLINK_CLONE,
+                     _("Unlink clone"));
 }
 
 void
@@ -2063,6 +2139,8 @@ sp_selection_tile(bool apply)
     // bottommost object, after sorting
     SPObject *parent = SP_OBJECT_PARENT (items->data);
 
+    NR::Matrix parent_transform = sp_item_i2root_affine(SP_ITEM(parent));
+
     // remember the position of the first item
     gint pos = SP_OBJECT_REPR (items->data)->position();
 
@@ -2090,7 +2168,7 @@ sp_selection_tile(bool apply)
     prefs_set_int_attribute("options.clonecompensation", "value", SP_CLONE_COMPENSATION_UNMOVED);
 
     const gchar *pat_id = pattern_tile (repr_copies, bounds, document,
-                                        NR::Matrix(NR::translate(desktop->dt2doc(NR::Point(r.min()[NR::X], r.max()[NR::Y])))), move);
+                                        NR::Matrix(NR::translate(desktop->dt2doc(NR::Point(r.min()[NR::X], r.max()[NR::Y])))) * parent_transform.inverse(), parent_transform * move);
 
     // restore compensation setting
     prefs_set_int_attribute("options.clonecompensation", "value", saved_compensation);
@@ -2098,10 +2176,14 @@ sp_selection_tile(bool apply)
     if (apply) {
         Inkscape::XML::Node *rect = sp_repr_new ("svg:rect");
         rect->setAttribute("style", g_strdup_printf("stroke:none;fill:url(#%s)", pat_id));
-        sp_repr_set_svg_double(rect, "width", bounds.extent(NR::X));
-        sp_repr_set_svg_double(rect, "height", bounds.extent(NR::Y));
-        sp_repr_set_svg_double(rect, "x", bounds.min()[NR::X]);
-        sp_repr_set_svg_double(rect, "y", bounds.min()[NR::Y]);
+
+        NR::Point min = bounds.min() * parent_transform.inverse();
+        NR::Point max = bounds.max() * parent_transform.inverse();
+
+        sp_repr_set_svg_double(rect, "width", max[NR::X] - min[NR::X]);
+        sp_repr_set_svg_double(rect, "height", max[NR::Y] - min[NR::Y]);
+        sp_repr_set_svg_double(rect, "x", min[NR::X]);
+        sp_repr_set_svg_double(rect, "y", min[NR::Y]);
 
         // restore parent and position
         SP_OBJECT_REPR (parent)->appendChild(rect);
@@ -2116,7 +2198,8 @@ sp_selection_tile(bool apply)
 
     g_slist_free (items);
 
-    sp_document_done (document);
+    sp_document_done (document, SP_VERB_EDIT_TILE, 
+                      _("Objects to pattern"));
 }
 
 void
@@ -2187,7 +2270,8 @@ sp_selection_untile()
     if (!did) {
         desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("<b>No pattern fills</b> in the selection."));
     } else {
-        sp_document_done(sp_desktop_document(desktop));
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_EDIT_UNTILE, 
+                         _("Pattern to objects"));
         selection->setList(new_select);
     }
 }
@@ -2291,7 +2375,7 @@ sp_selection_create_bitmap_copy ()
     // Do the export
     sp_export_png_file(document, filepath,
                    bbox.x0, bbox.y0, bbox.x1, bbox.y1,
-                   width, height,
+                   width, height, res, res,
                    (guint32) 0xffffff00,
                    NULL, NULL,
                    true,  /*bool force_overwrite,*/
@@ -2336,7 +2420,8 @@ sp_selection_create_bitmap_copy ()
         gdk_pixbuf_unref (pb);
 
         // Complete undoable transaction
-        sp_document_done (document);
+        sp_document_done (document, SP_VERB_SELECTION_CREATE_BITMAP,
+                          _("Create bitmap"));
     }
 
     g_free (filename);
@@ -2461,7 +2546,10 @@ sp_selection_set_mask(bool apply_clip_path, bool apply_to_layer)
     g_slist_free (mask_items);
     g_slist_free (apply_to_items);
 
-    sp_document_done (document);
+    if (apply_clip_path) 
+        sp_document_done (document, SP_VERB_OBJECT_SET_CLIPPATH, _("Set clipping path"));
+    else 
+        sp_document_done (document, SP_VERB_OBJECT_SET_MASK, _("Set mask"));
 }
 
 void sp_selection_unset_mask(bool apply_clip_path) {
@@ -2541,7 +2629,10 @@ void sp_selection_unset_mask(bool apply_clip_path) {
         g_slist_free (items_to_move);
     }
 
-    sp_document_done (document);
+    if (apply_clip_path) 
+        sp_document_done (document, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path"));
+    else 
+        sp_document_done (document, SP_VERB_OBJECT_UNSET_MASK, _("Release mask"));
 }
 
 void fit_canvas_to_selection(SPDesktop *desktop) {
@@ -2554,9 +2645,9 @@ void fit_canvas_to_selection(SPDesktop *desktop) {
     NRRect bbox = {0,0,0,0};
 
     desktop->selection->bounds(&bbox);
-    g_return_if_fail(!empty(bbox));
-
-    doc->fitToRect(bbox);
+    if (!empty(bbox)) {
+        doc->fitToRect(bbox);
+    }
 };
 
 void fit_canvas_to_drawing(SPDocument *doc) {
@@ -2566,9 +2657,9 @@ void fit_canvas_to_drawing(SPDocument *doc) {
     sp_document_ensure_up_to_date (doc);
     sp_item_invoke_bbox(SP_ITEM(doc->root), &bbox, sp_item_i2r_affine(SP_ITEM(doc->root)), TRUE);
 
-    g_return_if_fail(!empty(bbox));
-
-    doc->fitToRect(bbox);
+    if (!empty(bbox)) {
+        doc->fitToRect(bbox);
+    }
 };
 
 void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
@@ -2584,7 +2675,8 @@ void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
         fit_canvas_to_selection(desktop);
     }
 
-    sp_document_done(doc);
+    sp_document_done(doc, SP_VERB_FIT_CANVAS_TO_DRAWING, 
+                     _("Fit page to selection"));
 };
 
 /*