X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fsp-object.cpp;h=6526435de98101f25ae6fc984d79a4876648b52b;hb=032f77bd082ffeae03d9d4fe85b8029abbfc4213;hp=62a442d0a6483c48de2c2e49eb5b54df4014fad2;hpb=f4f507228b30d55fd7e39386ba513f3a0a54bd5d;p=inkscape.git diff --git a/src/sp-object.cpp b/src/sp-object.cpp index 62a442d0a..6526435de 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -173,7 +173,6 @@ sp_object_init(SPObject *object) object->parent = object->next = NULL; object->repr = NULL; object->id = NULL; - object->style = NULL; object->_collection_policy = SPObject::COLLECT_WITH_PARENT; @@ -183,6 +182,12 @@ sp_object_init(SPObject *object) new (&object->_position_changed_signal) sigc::signal(); object->_successor = NULL; + // FIXME: now we create style for all objects, but per SVG, only the following can have style attribute: + // vg, g, defs, desc, title, symbol, use, image, switch, path, rect, circle, ellipse, line, polyline, + // polygon, text, tspan, tref, textPath, altGlyph, glyphRef, marker, linearGradient, radialGradient, + // stop, pattern, clipPath, mask, filter, feImage, a, font, glyph, missing-glyph, foreignObject + object->style = sp_style_new_from_object(object); + object->_label = NULL; object->_default_label = NULL; } @@ -737,8 +742,9 @@ sp_object_remove_child(SPObject *object, Inkscape::XML::Node *child) { debug("id=%x, typename=%s", object, g_type_name_from_instance((GTypeInstance*)object)); SPObject *ochild = sp_object_get_child_by_repr(object, child); - g_return_if_fail(ochild != NULL); - sp_object_detach(object, ochild); + g_return_if_fail (ochild != NULL || !strcmp("comment", child->name())); // comments have no objects + if (ochild) + sp_object_detach(object, ochild); } /** @@ -815,20 +821,26 @@ sp_object_invoke_build(SPObject *object, SPDocument *document, Inkscape::XML::No object->document->bindObjectToRepr(object->repr, object); if (Inkscape::XML::id_permitted(object->repr)) { - /* If we are not cloned, force unique id */ + /* If we are not cloned, and not seeking, force unique id */ gchar const *id = object->repr->attribute("id"); - gchar *realid = sp_object_get_unique_id(object, id); - g_assert(realid != NULL); - - object->document->bindObjectToId(realid, object); - object->id = realid; - - /* Redefine ID, if required */ - if ((id == NULL) || (strcmp(id, realid) != 0)) { - gboolean undo_sensitive=sp_document_get_undo_sensitive(document); - sp_document_set_undo_sensitive(document, FALSE); - object->repr->setAttribute("id", realid); - sp_document_set_undo_sensitive(document, undo_sensitive); + if (!document->isSeeking()) { + gchar *realid = sp_object_get_unique_id(object, id); + g_assert(realid != NULL); + + object->document->bindObjectToId(realid, object); + object->id = realid; + + /* Redefine ID, if required */ + if ((id == NULL) || (strcmp(id, realid) != 0)) { + object->repr->setAttribute("id", realid); + } + } else if (id) { + // bind if id, but no conflict -- otherwise, we can expect + // a subsequent setting of the id attribute + if (!object->document->getObjectById(id)) { + object->document->bindObjectToId(id, object); + object->id = g_strdup(id); + } } } } else { @@ -851,11 +863,11 @@ void SPObject::releaseReferences() { sp_repr_remove_listener_by_data(this->repr, this); + this->_release_signal.emit(this); SPObjectClass *klass=(SPObjectClass *)G_OBJECT_GET_CLASS(this); if (klass->release) { klass->release(this); } - this->_release_signal.emit(this); /* all hrefs should be released by the "release" handlers */ g_assert(this->hrefcount == 0); @@ -939,16 +951,23 @@ sp_object_private_set(SPObject *object, unsigned int key, gchar const *value) SPDocument *document=object->document; SPObject *conflict=NULL; - if (value) { - conflict = document->getObjectById((char const *)value); + gchar const *new_id = value; + + if (new_id) { + conflict = document->getObjectById((char const *)new_id); } + if ( conflict && conflict != object ) { - sp_object_ref(conflict, NULL); - // give the conflicting object a new ID - gchar *new_conflict_id = sp_object_get_unique_id(conflict, NULL); - SP_OBJECT_REPR(conflict)->setAttribute("id", new_conflict_id); - g_free(new_conflict_id); - sp_object_unref(conflict, NULL); + if (!document->isSeeking()) { + sp_object_ref(conflict, NULL); + // give the conflicting object a new ID + gchar *new_conflict_id = sp_object_get_unique_id(conflict, NULL); + SP_OBJECT_REPR(conflict)->setAttribute("id", new_conflict_id); + g_free(new_conflict_id); + sp_object_unref(conflict, NULL); + } else { + new_id = NULL; + } } if (object->id) { @@ -956,8 +975,8 @@ sp_object_private_set(SPObject *object, unsigned int key, gchar const *value) g_free(object->id); } - if (value) { - object->id = g_strdup((char const*)value); + if (new_id) { + object->id = g_strdup((char const*)new_id); document->bindObjectToId(object->id, object); } else { object->id = NULL; @@ -998,6 +1017,10 @@ sp_object_private_set(SPObject *object, unsigned int key, gchar const *value) } object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); break; + case SP_ATTR_STYLE: + sp_style_read_from_object(object->style, object); + object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + break; default: break; } @@ -1090,7 +1113,7 @@ static Inkscape::XML::Node * sp_object_private_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) { if (!repr && (flags & SP_OBJECT_WRITE_BUILD)) { - repr = SP_OBJECT_REPR(object)->duplicate(); + repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME if (!( flags & SP_OBJECT_WRITE_EXT )) { repr->setAttribute("inkscape:collect", NULL); } @@ -1110,6 +1133,38 @@ sp_object_private_write(SPObject *object, Inkscape::XML::Node *repr, guint flags } else { repr->setAttribute("inkscape:collect", NULL); } + + SPStyle const *const obj_style = SP_OBJECT_STYLE(object); + if (obj_style) { + gchar *s = sp_style_write_string(obj_style, SP_STYLE_FLAG_IFSET); + repr->setAttribute("style", ( *s ? s : NULL )); + g_free(s); + } else { + /** \todo I'm not sure what to do in this case. Bug #1165868 + * suggests that it can arise, but the submitter doesn't know + * how to do so reliably. The main two options are either + * leave repr's style attribute unchanged, or explicitly clear it. + * Must also consider what to do with property attributes for + * the element; see below. + */ + char const *style_str = repr->attribute("style"); + if (!style_str) { + style_str = "NULL"; + } + g_warning("Item's style is NULL; repr style attribute is %s", style_str); + } + + /** \note We treat object->style as authoritative. Its effects have + * been written to the style attribute above; any properties that are + * unset we take to be deliberately unset (e.g. so that clones can + * override the property). + * + * Note that the below has an undesirable consequence of changing the + * appearance on renderers that lack CSS support (e.g. SVG tiny); + * possibly we should write property attributes instead of a style + * attribute. + */ + sp_style_unset_property_attrs (object); } return repr; @@ -1134,6 +1189,10 @@ SPObject::updateRepr(unsigned int flags) { } } +/** Used both to create reprs in the original document, and to create + * reprs in another document (e.g. a temporary document used when + * saving as "Plain SVG" + */ Inkscape::XML::Node * SPObject::updateRepr(Inkscape::XML::Node *repr, unsigned int flags) { if (SP_OBJECT_IS_CLONED(this)) { @@ -1149,9 +1208,10 @@ SPObject::updateRepr(Inkscape::XML::Node *repr, unsigned int flags) { g_warning("Class %s does not implement ::write", G_OBJECT_TYPE_NAME(this)); if (!repr) { if (flags & SP_OBJECT_WRITE_BUILD) { - repr = SP_OBJECT_REPR(this)->duplicate(); + /// \todo FIXME: Plumb an appropriate XML::Document into this + repr = SP_OBJECT_REPR(this)->duplicate(NULL); } - /// \todo fixme: else probably error (Lauris) */ + /// \todo FIXME: else probably error (Lauris) */ } else { repr->mergeFrom(SP_OBJECT_REPR(this), "id"); } @@ -1198,6 +1258,9 @@ SPObject::requestDisplayUpdate(unsigned int flags) } } +/** + * Update views + */ void SPObject::updateDisplay(SPCtx *ctx, unsigned int flags) { @@ -1268,7 +1331,10 @@ SPObject::requestModified(unsigned int flags) } /** - * This is what actually delivers the modified signals + * Emits the MODIFIED signal with the object's flags. + * The object's mflags are the original set aside during the update pass for + * later delivery here. Once emitModified() is called, those flags don't + * need to be stored any longer. */ void SPObject::emitModified(unsigned int flags)