sp-item-group.cpp revision 944f5bdd5dee98094cceca7bdaaabd18cba5277c
/*
* SVG <g> implementation
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* bulia byak <buliabyak@users.sf.net>
* Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
* Jon A. Cruz <jon@joncruz.org>
* Abhishek Sharma
*
* Copyright (C) 1999-2006 authors
* Copyright (C) 2000-2001 Ximian, Inc.
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <cstring>
#include <string>
#include "display/drawing-group.h"
#include "document.h"
#include "document-undo.h"
#include "style.h"
#include "attributes.h"
#include "sp-item-transform.h"
#include "sp-root.h"
#include "sp-use.h"
#include "sp-offset.h"
#include "sp-clippath.h"
#include "sp-mask.h"
#include "sp-path.h"
#include "box3d.h"
#include "persp3d.h"
#include "inkscape.h"
#include "desktop-handles.h"
#include "selection.h"
#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
#include "live_effects/lpeobject-reference.h"
#include "sp-title.h"
#include "sp-desc.h"
#include "sp-switch.h"
#include "sp-defs.h"
#include "verbs.h"
#include "layer-model.h"
#include "sp-textpath.h"
#include "sp-flowtext.h"
using Inkscape::DocumentUndo;
static void sp_group_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
static void sp_group_order_changed (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * old_ref, Inkscape::XML::Node * new_ref);
static Inkscape::XML::Node *sp_group_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
static Geom::OptRect sp_group_bbox(SPItem const *item, Geom::Affine const &transform, SPItem::BBoxType type);
static Inkscape::DrawingItem *sp_group_show (SPItem *item, Inkscape::Drawing &drawing, unsigned int key, unsigned int flags);
static void sp_group_snappoints (SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs);
static void
{
}
static void
{
}
{
}
}
}
}
}
static void
{
}
static void sp_group_child_added(SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
{
}
}
/* fixme: hide (Lauris) */
static void
{
}
static void
sp_group_order_changed (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref)
{
}
static void
{
}
static void
{
}
static Inkscape::XML::Node * sp_group_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
if (flags & SP_OBJECT_WRITE_BUILD) {
GSList *l;
if (!repr) {
if (SP_IS_SWITCH(object)) {
} else {
}
}
l = NULL;
if (crepr) {
l = g_slist_prepend (l, crepr);
}
}
}
while (l) {
l = g_slist_remove (l, l->data);
}
} else {
}
}
}
if ( flags & SP_OBJECT_WRITE_EXT ) {
const char *value;
value = "layer";
value = "maskhelper";
} else if ( flags & SP_OBJECT_WRITE_ALL ) {
value = "group";
} else {
}
}
}
return repr;
}
{
}
static void
{
}
{
}
switch (key) {
} else {
}
break;
default: {
}
}
}
}
static Inkscape::DrawingItem *
{
}
static void
{
}
static void sp_group_snappoints(SPItem const *item, std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs)
{
{
if (SP_IS_ITEM(o)) {
}
}
}
void
{
if (SP_IS_BOX3D(gitem)) {
}
/* Step 1 - generate lists of children objects */
if (SP_IS_ITEM (child)) {
/* Merging of style */
// it here _before_ the new transform is set, so as to use the pre-transform bbox
/*
* fixme: We currently make no allowance for the case where child is cloned
* and the group has any style settings.
*
* (This should never occur with documents created solely with the current
* version of inkscape without using the XML editor: we usually apply group
* style changes to children rather than to the group itself.)
*
* If the group has no style settings, then
* sp_style_merge_from_dying_parent should be a no-op. Otherwise (i.e. if
* we change the child's style to compensate for its parent going away)
* then those changes will typically be reflected in any clones of child,
* whereas we'd prefer for Ungroup not to affect the visual appearance.
*
* The only way of preserving styling appearance in general is for child to
* be put into a new group -- a somewhat surprising response to an Ungroup
* command. We could add a new groupmode:transparent that would mostly
* hide the existence of such groups from the user (i.e. editing behaves as
* if the transparent group's children weren't in a group), though that's
* extra complication & maintenance burden and this case is rare.
*/
child->updateRepr();
// Merging transform
// make sure a clone's effective transform is the same as was under group
} else {
// We should not apply the group's transformation to both a linked offset AND to its source
// When dealing with a chain of linked offsets, the transformation of an offset will be
// tied to the transformation of the top-most source, not to any of the intermediate
// offsets. So let's find the top-most source
}
ctrans = citem->transform * g; // then we should apply the transformation of the group to the offset
} else {
}
} else {
}
}
// FIXME: constructing a transform that would fully preserve the appearance of a
// textpath if it is ungrouped with its path seems to be impossible in general
// case. E.g. if the group was squeezed, to keep the ungrouped textpath squeezed
// as well, we'll need to relink it to some "virtual" path which is inversely
// stretched relative to the actual path, and then squeeze the textpath back so it
// would both fit the actual path _and_ be squeezed as before. It's a bummer.
// This is just a way to temporarily remember the transform in repr. When repr is
// reattached outside of the group, the transform will be written more properly
// (i.e. optimized into the object if the corresponding preference is set)
} else {
}
}
/* Step 2 - clear group */
// remember the position of the group
// the group is leaving forever, no heir, clones should take note; its children however are going to reemerge
group->deleteObject(true, false);
/* Step 3 - add nonitems */
if (objects) {
while (objects) {
if (!sp_repr_is_meta_element(repr)) {
}
}
}
/* Step 4 - add items */
while (items) {
// add item
// restore position; since the items list was prepended (i.e. reverse), we now add
// all children at the same pos, which inverts the order once again
// fill in the children list if non-null
}
}
if (do_done) {
}
}
/*
* some API for list aspect of SPGroup
*/
{
if ( SP_IS_ITEM(o) ) {
s = g_slist_prepend(s, o);
}
}
return g_slist_reverse (s);
}
{
}
return child;
}
if ( _layer_mode != mode ) {
} else if ( _layer_mode == LAYER ) {
}
_layer_mode = mode;
}
}
} else {
return GROUP;
}
}
}
}
if (g) {
}
}
}
}
{
if ( hasChildren() ) {
if ( SP_IS_ITEM(o) ) {
}
}
}
}
// Recursively scale child items around a point
{
if ( hasChildren() ) {
if ( SP_IS_ITEM(o) ) {
if (SP_IS_GROUP(o) && !SP_IS_BOX3D(o)) {
} else {
if (bbox) {
// Scale item
if (item->isCenterSet()) {
}
if (SP_IS_TEXT_TEXTPATH(item)) {
} else if (SP_IS_FLOWTEXT(item)) {
} else if (SP_IS_BOX3D(item)) {
// Force recalculation from perspective
}
// Save and reset current transform
// Apply scale
// Scale translation and restore original transform
// calculate the matrix we need to apply to the clone
// to cancel its induced transform from its original
} else {
}
item->updateRepr();
}
}
}
}
}
}
}
}
}
// optimization for the common special case where the child is being added at the end
if ( SP_IS_ITEM(ochild) ) {
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
if (ac) {
}
}
}
} else { // general case
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
if (ac) {
}
}
}
}
}
}
if (flags & SP_OBJECT_MODIFIED_FLAG) {
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
}
}
while (l) {
l = g_slist_remove (l, child);
if (SP_IS_ITEM (child)) {
} else {
}
}
}
}
if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) {
}
}
while (l) {
l = g_slist_remove (l, child);
}
}
}
{
while (l) {
}
l = g_slist_remove (l, o);
}
return bbox;
}
while (l) {
if (SP_IS_ITEM(o)) {
}
l = g_slist_remove (l, o);
}
}
if (SP_IS_ITEM(o)) {
len++;
}
}
return len;
}
return g_strdup_printf(
ngettext("<b>Group</b> of <b>%d</b> object",
"<b>Group</b> of <b>%d</b> objects",
}
Inkscape::DrawingItem *CGroup::show (Inkscape::Drawing &drawing, unsigned int key, unsigned int flags) {
return ai;
}
void CGroup::_showChildren (Inkscape::Drawing &drawing, Inkscape::DrawingItem *ai, unsigned int key, unsigned int flags) {
while (l) {
if (SP_IS_ITEM (o)) {
if (ac) {
}
}
l = g_slist_remove (l, o);
}
}
while (l) {
if (SP_IS_ITEM (o)) {
}
l = g_slist_remove (l, o);
}
}
void CGroup::onOrderChanged (Inkscape::XML::Node *child, Inkscape::XML::Node *, Inkscape::XML::Node *)
{
/* TODO: this should be moved into SPItem somehow */
SPItemView *v;
}
}
}
static void
{
#ifdef GROUP_VERBOSE
#endif
if (SP_IS_LPE_ITEM(subitem)) {
}
}
}
for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++)
{
}
}
}
}
static void
{
if (SP_IS_GROUP(subitem)) {
} else if (SP_IS_SHAPE(subitem)) {
if (SP_IS_PATH(subitem)) {
} else {
}
// only run LPEs when the shape has a curve defined
if (c) {
if (write) {
#ifdef GROUP_VERBOSE
g_message("sp_group_perform_patheffect writes 'd' attribute");
#endif
}
c->unref();
}
}
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :