gchar* SPUse::description() const { if (this->child) { if( SP_IS_SYMBOL( this->child ) ) { if (this->child->title()) { return g_strdup_printf(_("called %s"), Glib::Markup::escape_text(Glib::ustring( g_dpgettext2(NULL, "Symbol", this->child->title()))).c_str()); } else { return g_strdup_printf(_("called %s"), _("Unnamed Symbol")); } } static unsigned recursion_depth = 0; if (recursion_depth >= 4) { /* TRANSLATORS: Used for statusbar description for long <use> chains: * "Clone of: Clone of: ... in Layer 1". */ return g_strdup(_("...")); /* We could do better, e.g. chasing the href chain until we reach something other than * a <use>, and giving its description. */ } ++recursion_depth; char *child_desc = this->child->detailedDescription(); --recursion_depth; char *ret = g_strdup_printf(_("of: %s"), child_desc); g_free(child_desc); return ret; } else { return g_strdup(_("[orphaned]")); } }
const char* SPUse::displayName() const { if (this->child && SP_IS_SYMBOL( this->child )) { return _("Symbol"); } return _("Clone"); }
void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *selection) { GSList const *items = selection->itemList(); if (!items) { // no items _context.set(Inkscape::NORMAL_MESSAGE, _when_nothing); } else { SPItem *item = SP_ITEM(items->data); SPObject *layer = selection->desktop()->layerForObject(item); SPObject *root = selection->desktop()->currentRoot(); // Layer name gchar *layer_name; if (layer == root) { layer_name = g_strdup(_("root")); } else { char const *layer_label; bool is_label = false; if (layer->label()) { layer_label = layer->label(); is_label = true; } else { layer_label = layer->defaultLabel(); } char *quoted_layer_label = xml_quote_strdup(layer_label); if (is_label) { layer_name = g_strdup_printf(_("layer <b>%s</b>"), quoted_layer_label); } else { layer_name = g_strdup_printf(_("layer <b><i>%s</i></b>"), quoted_layer_label); } g_free(quoted_layer_label); } // Parent name SPObject *parent = item->parent; gchar const *parent_label = parent->getId(); char *quoted_parent_label = xml_quote_strdup(parent_label); gchar *parent_name = g_strdup_printf(_("<i>%s</i>"), quoted_parent_label); g_free(quoted_parent_label); gchar *in_phrase; guint num_layers = selection->numberOfLayers(); guint num_parents = selection->numberOfParents(); if (num_layers == 1) { if (num_parents == 1) { if (layer == parent) in_phrase = g_strdup_printf(_(" in %s"), layer_name); else in_phrase = g_strdup_printf(_(" in group %s (%s)"), parent_name, layer_name); } else { in_phrase = g_strdup_printf(ngettext(" in <b>%i</b> parents (%s)", " in <b>%i</b> parents (%s)", num_parents), num_parents, layer_name); } } else { in_phrase = g_strdup_printf(ngettext(" in <b>%i</b> layers", " in <b>%i</b> layers", num_layers), num_layers); } g_free (layer_name); g_free (parent_name); if (!items->next) { // one item char *item_desc = item->description(); if (SP_IS_USE(item) && SP_IS_SYMBOL(item->firstChild())) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Convert symbol to group to edit"), _when_selected); } else if (SP_IS_USE(item) || (SP_IS_OFFSET(item) && SP_OFFSET (item)->sourceHref)) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Use <b>Shift+D</b> to look up original"), _when_selected); } else if (SP_IS_TEXT_TEXTPATH(item)) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Use <b>Shift+D</b> to look up path"), _when_selected); } else if (SP_IS_FLOWTEXT(item) && !SP_FLOWTEXT(item)->has_internal_frame()) { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s. %s.", item_desc, in_phrase, _("Use <b>Shift+D</b> to look up frame"), _when_selected); } else { _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s. %s.", item_desc, in_phrase, _when_selected); } g_free(item_desc); } else { // multiple items int object_count = g_slist_length((GSList *)items); gchar *objects_str = NULL; GSList *terms = collect_terms ((GSList *)items); int n_terms = g_slist_length(terms); if (n_terms == 0) { objects_str = g_strdup_printf ( // this is only used with 2 or more objects ngettext("<b>%i</b> object selected", "<b>%i</b> objects selected", object_count), object_count); } else if (n_terms == 1) { objects_str = g_strdup_printf ( // this is only used with 2 or more objects ngettext("<b>%i</b> object of type <b>%s</b>", "<b>%i</b> objects of type <b>%s</b>", object_count), object_count, (gchar *) terms->data); } else if (n_terms == 2) { objects_str = g_strdup_printf ( // this is only used with 2 or more objects ngettext("<b>%i</b> object of types <b>%s</b>, <b>%s</b>", "<b>%i</b> objects of types <b>%s</b>, <b>%s</b>", object_count), object_count, (gchar *) terms->data, (gchar *) terms->next->data); } else if (n_terms == 3) { objects_str = g_strdup_printf ( // this is only used with 2 or more objects ngettext("<b>%i</b> object of types <b>%s</b>, <b>%s</b>, <b>%s</b>", "<b>%i</b> objects of types <b>%s</b>, <b>%s</b>, <b>%s</b>", object_count), object_count, (gchar *) terms->data, (gchar *) terms->next->data, (gchar *) terms->next->next->data); } else { objects_str = g_strdup_printf ( // this is only used with 2 or more objects ngettext("<b>%i</b> object of <b>%i</b> types", "<b>%i</b> objects of <b>%i</b> types", object_count), object_count, n_terms); } g_slist_free (terms); // indicate all, some, or none filtered gchar *filt_str = NULL; int n_filt = count_filtered((GSList *)items); //all filtered if (n_filt) { filt_str = g_strdup_printf(ngettext("; <i>%d filtered object</i> ", "; <i>%d filtered objects</i> ", n_filt), n_filt); } else { filt_str = g_strdup_printf("%s", ""); } _context.setF(Inkscape::NORMAL_MESSAGE, "%s%s%s. %s.", objects_str, filt_str, in_phrase, _when_selected); if (objects_str) { g_free(objects_str); objects_str = 0; } if (filt_str) { g_free(filt_str); objects_str = 0; } } g_free(in_phrase); } }
void SPUse::update(SPCtx *ctx, unsigned flags) { // std::cout << "SPUse::update: " << (getId()?getId():"null") << std::endl; SPItemCtx *ictx = (SPItemCtx *) ctx; SPItemCtx cctx = *ictx; unsigned childflags = flags; if (flags & SP_OBJECT_MODIFIED_FLAG) { childflags |= SP_OBJECT_PARENT_MODIFIED_FLAG; } childflags &= SP_OBJECT_MODIFIED_CASCADE; /* Set up child viewport */ if (this->x.unit == SVGLength::PERCENT) { this->x.computed = this->x.value * ictx->viewport.width(); } if (this->y.unit == SVGLength::PERCENT) { this->y.computed = this->y.value * ictx->viewport.height(); } if (this->width.unit == SVGLength::PERCENT) { this->width.computed = this->width.value * ictx->viewport.width(); } if (this->height.unit == SVGLength::PERCENT) { this->height.computed = this->height.value * ictx->viewport.height(); } childflags &= ~SP_OBJECT_USER_MODIFIED_FLAG_B; if (this->child) { sp_object_ref(this->child); // viewport is only changed if referencing a symbol or svg element if( SP_IS_SYMBOL(this->child) || SP_IS_ROOT(this->child) ) { cctx.viewport = Geom::Rect::from_xywh(0, 0, this->width.computed, this->height.computed); cctx.i2vp = Geom::identity(); } if (childflags || (this->child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { SPItem const *chi = dynamic_cast<SPItem const *>(child); g_assert(chi != NULL); cctx.i2doc = chi->transform * ictx->i2doc; cctx.i2vp = chi->transform * ictx->i2vp; this->child->updateDisplay((SPCtx *)&cctx, childflags); } sp_object_unref(this->child); } SPItem::update(ctx, flags); if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); this->context_style = this->style; g->setStyle(this->style, this->context_style); } } /* As last step set additional transform of arena group */ for (SPItemView *v = this->display; v != NULL; v = v->next) { Inkscape::DrawingGroup *g = dynamic_cast<Inkscape::DrawingGroup *>(v->arenaitem); Geom::Affine t(Geom::Translate(this->x.computed, this->y.computed)); g->setChildTransform(t); } }
SPItem *SPUse::unlink() { Inkscape::XML::Node *repr = this->getRepr(); if (!repr) { return NULL; } Inkscape::XML::Node *parent = repr->parent(); SPDocument *document = this->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); // Track the ultimate source of a chain of uses. SPItem *orig = this->root(); if (!orig) { return NULL; } // Calculate the accumulated transform, starting from the original. Geom::Affine t = this->get_root_transform(); Inkscape::XML::Node *copy = NULL; if (SP_IS_SYMBOL(orig)) { // make a group, copy children copy = xml_doc->createElement("svg:g"); for (Inkscape::XML::Node *child = orig->getRepr()->firstChild() ; child != NULL; child = child->next()) { Inkscape::XML::Node *newchild = child->duplicate(xml_doc); copy->appendChild(newchild); } } else { // just copy copy = orig->getRepr()->duplicate(xml_doc); } // Add the duplicate repr just after the existing one. parent->addChild(copy, repr); // Retrieve the SPItem of the resulting repr. SPObject *unlinked = document->getObjectByRepr(copy); // Merge style from the use. SPStyle *unli_sty = unlinked->style; SPStyle const *use_sty = this->style; sp_style_merge_from_dying_parent(unli_sty, use_sty); sp_style_merge_from_parent(unli_sty, unlinked->parent->style); unlinked->updateRepr(); // Hold onto our SPObject and repr for now. sp_object_ref(this, NULL); Inkscape::GC::anchor(repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. this->deleteObject(false); // Give the copy our old id and let go of our old repr. copy->setAttribute("id", repr->attribute("id")); Inkscape::GC::release(repr); // Remove tiled clone attrs. copy->setAttribute("inkscape:tiled-clone-of", NULL); copy->setAttribute("inkscape:tile-w", NULL); copy->setAttribute("inkscape:tile-h", NULL); copy->setAttribute("inkscape:tile-cx", NULL); copy->setAttribute("inkscape:tile-cy", NULL); // Establish the succession and let go of our object. this->setSuccessor(unlinked); sp_object_unref(this, NULL); SPItem *item = SP_ITEM(unlinked); // Set the accummulated transform. { Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. item->doWriteTransform(item->getRepr(), t, &nomove); } return item; }