index 9d60399fecdd85ec83815d729b9c10162b6fb606..dfe47bee842f9b1b08aa2534c919099172723813 100644 (file)
#include "helper/units.h"
#include "sp-item.h"
#include "box3d.h"
+#include "persp3d.h"
#include "unit-constants.h"
#include "xml/simple-document.h"
#include "sp-filter-reference.h"
// For clippath editing
#include "tools-switch.h"
-#include "shape-editor.h"
-#include "node-context.h"
-#include "nodepath.h"
+#include "ui/tool/node-tool.h"
#include "ui/clipboard.h"
}
sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_RAISE,
- //TRANSLATORS: Only put the word "Raise" in the translation. Means "to raise an object" in the undo history
+ //TRANSLATORS: only translate "string" in "context|string".
+ // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
+ // "Raise" means "to raise an object" in the undo history
Q_("undo_action|Raise"));
}
return clone_with_original;
}
-
/** Apply matrix to the selection. \a set_i2d is normally true, which means objects are in the
original transform, synced with their reprs, and need to jump to the new transform in one go. A
value of set_i2d==false is only used by seltrans when it's dragging objects live (not outlines); in
that case, items are already in the new position, but the repr is in the old, and this function
then simply updates the repr from item->transform.
*/
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d)
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d, bool compensate)
{
if (selection->isEmpty())
return;
+ // For each perspective with a box in selection, check whether all boxes are selected and
+ // unlink all non-selected boxes.
+ Persp3D *persp;
+ Persp3D *transf_persp;
+ std::list<Persp3D *> plist = selection->perspList();
+ for (std::list<Persp3D *>::iterator i = plist.begin(); i != plist.end(); ++i) {
+ persp = (Persp3D *) (*i);
+
+ if (!persp3d_has_all_boxes_in_selection (persp, selection)) {
+ std::list<SPBox3D *> selboxes = selection->box3DList(persp);
+
+ // create a new perspective as a copy of the current one and link the selected boxes to it
+ transf_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp->perspective_impl);
+
+ for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b)
+ box3d_switch_perspectives(*b, persp, transf_persp);
+ } else {
+ transf_persp = persp;
+ }
+
+ persp3d_apply_affine_transformation(transf_persp, affine);
+ }
+
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
SPItem *item = SP_ITEM(l->data);
@@ -1240,7 +1263,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
continue;
for (SPObject *use = region->firstChild() ; use ; use = SP_OBJECT_NEXT(use)) {
if (!SP_IS_USE(use)) continue;
- sp_item_write_transform(SP_USE(use), SP_OBJECT_REPR(use), item->transform.inverse(), NULL);
+ sp_item_write_transform(SP_USE(use), SP_OBJECT_REPR(use), item->transform.inverse(), NULL, compensate);
}
}
} else if (transform_clone_with_original) {
@@ -1266,25 +1289,25 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
if (prefs_parallel) {
Geom::Matrix move = result * clone_move * t_inv;
- sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &move);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &move, compensate);
} else if (prefs_unmoved) {
//if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
// clone_move = Geom::identity();
Geom::Matrix move = result * clone_move;
- sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &t);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &t, compensate);
}
} else {
// just apply the result
- sp_item_write_transform(item, SP_OBJECT_REPR(item), result, &t);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), result, &t, compensate);
}
} else {
if (set_i2d) {
sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * (Geom::Matrix)affine);
}
- sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, NULL);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, NULL, compensate);
}
// if we're moving the actual object, not just updating the repr, we can transform the
@@ -1384,9 +1407,9 @@ sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &al
sp_selection_apply_affine(selection, final);
}
-void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move)
+void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move, bool compensate)
{
- sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)));
+ sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)), true, compensate);
}
void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy)
}
}
-void sp_selection_edit_clip_or_mask(SPDesktop * dt, bool clip)
+/*bool has_path_recursive(SPObject *obj)
{
- if (!dt) return;
-
- Inkscape::Selection *selection = sp_desktop_selection(dt);
- if ( selection && !selection->isEmpty() ) {
- SPItem *item = selection->singleItem();
- if ( item ) {
- SPObject *obj = NULL;
- if (clip)
- obj = item->clip_ref ? SP_OBJECT(item->clip_ref->getObject()) : NULL;
- else
- obj = item->mask_ref ? SP_OBJECT(item->mask_ref->getObject()) : NULL;
-
- if (obj) {
- // obj is a group object, the children are the actual clippers
- for ( SPObject *child = obj->children ; child ; child = child->next ) {
- if ( SP_IS_ITEM(child) ) {
- // If not already in nodecontext, goto it!
- if (!tools_isactive(dt, TOOLS_NODES)) {
- tools_switch(dt, TOOLS_NODES);
- }
-
- ShapeEditor * shape_editor = dt->event_context->shape_editor;
- // TODO: should we set the item for nodepath or knotholder or both? seems to work with both.
- shape_editor->set_item(SP_ITEM(child), SH_NODEPATH);
- shape_editor->set_item(SP_ITEM(child), SH_KNOTHOLDER);
- Inkscape::NodePath::Path *np = shape_editor->get_nodepath();
- if (np) {
- // take colors from prefs (same as used in outline mode)
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- np->helperpath_rgba = clip ?
- prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff) :
- prefs->getInt("/options/wireframecolors/masks", 0x0000ffff);
- np->helperpath_width = 1.0;
- sp_nodepath_show_helperpath(np, true);
- }
- break; // break out of for loop after 1st encountered item
- }
- }
- } else if (clip) {
- dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("The selection has no applied clip path."));
- } else {
- dt->messageStack()->flash(Inkscape::WARNING_MESSAGE, _("The selection has no applied mask."));
- }
+ if (!obj) return false;
+ if (SP_IS_PATH(obj)) {
+ return true;
+ }
+ if (SP_IS_GROUP(obj) || SP_IS_OBJECTGROUP(obj)) {
+ for (SPObject *c = obj->children; c; c = c->next) {
+ if (has_path_recursive(c)) return true;
}
}
+ return false;
+}*/
+
+void sp_selection_edit_clip_or_mask(SPDesktop * /*dt*/, bool /*clip*/)
+{
+ return;
+ /*if (!dt) return;
+ using namespace Inkscape::UI;
+
+ Inkscape::Selection *selection = sp_desktop_selection(dt);
+ if (!selection || selection->isEmpty()) return;
+
+ GSList const *items = selection->itemList();
+ bool has_path = false;
+ for (GSList *i = const_cast<GSList*>(items); i; i= i->next) {
+ SPItem *item = SP_ITEM(i->data);
+ SPObject *search = clip
+ ? SP_OBJECT(item->clip_ref ? item->clip_ref->getObject() : NULL)
+ : SP_OBJECT(item->mask_ref ? item->mask_ref->getObject() : NULL);
+ has_path |= has_path_recursive(search);
+ if (has_path) break;
+ }
+ if (has_path) {
+ if (!tools_isactive(dt, TOOLS_NODES)) {
+ tools_switch(dt, TOOLS_NODES);
+ }
+ ink_node_tool_set_mode(INK_NODE_TOOL(dt->event_context),
+ clip ? NODE_TOOL_EDIT_CLIPPING_PATHS : NODE_TOOL_EDIT_MASKS);
+ } else if (clip) {
+ dt->messageStack()->flash(Inkscape::WARNING_MESSAGE,
+ _("The selection has no applied clip path."));
+ } else {
+ dt->messageStack()->flash(Inkscape::WARNING_MESSAGE,
+ _("The selection has no applied mask."));
+ }*/
}
}
/**
- * Returns true if an undoable change should be recorded.
+ * \param with_margins margins defined in the xml under <sodipodi:namedview>
+ * "fit-margin-..." attributes. See SPDocument::fitToRect.
+ * \return true if an undoable change should be recorded.
*/
bool
-fit_canvas_to_selection(SPDesktop *desktop)
+fit_canvas_to_selection(SPDesktop *desktop, bool with_margins)
{
g_return_val_if_fail(desktop != NULL, false);
SPDocument *doc = sp_desktop_document(desktop);
}
Geom::OptRect const bbox(desktop->selection->bounds());
if (bbox) {
- doc->fitToRect(*bbox);
+ doc->fitToRect(*bbox, with_margins);
return true;
} else {
return false;
}
}
+/**
+ * \param with_margins margins defined in the xml under <sodipodi:namedview>
+ * "fit-margin-..." attributes. See SPDocument::fitToRect.
+ */
bool
-fit_canvas_to_drawing(SPDocument *doc)
+fit_canvas_to_drawing(SPDocument *doc, bool with_margins)
{
g_return_val_if_fail(doc != NULL, false);
SPItem const *const root = SP_ITEM(doc->root);
Geom::OptRect const bbox(root->getBounds(sp_item_i2d_affine(root)));
if (bbox) {
- doc->fitToRect(*bbox);
+ doc->fitToRect(*bbox, with_margins);
return true;
} else {
return false;
}
}
+/**
+ * Fits canvas to selection or drawing with margins from <sodipodi:namedview>
+ * "fit-margin-..." attributes. See SPDocument::fitToRect and
+ * ui/dialog/page-sizer.
+ */
void fit_canvas_to_selection_or_drawing(SPDesktop *desktop) {
g_return_if_fail(desktop != NULL);
SPDocument *doc = sp_desktop_document(desktop);
g_return_if_fail(desktop->selection != NULL);
bool const changed = ( desktop->selection->isEmpty()
- ? fit_canvas_to_drawing(doc)
- : fit_canvas_to_selection(desktop) );
+ ? fit_canvas_to_drawing(doc, true)
+ : fit_canvas_to_selection(desktop, true) );
if (changed) {
sp_document_done(sp_desktop_document(desktop), SP_VERB_FIT_CANVAS_TO_SELECTION_OR_DRAWING,
_("Fit Page to Selection or Drawing"));