X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdocument.cpp;h=9fc6dc4dae13491a348cbecf999dbe60164a39e8;hb=9336a24ccde2bdbbe7d3bd069e29b2cce87cb4be;hp=71f607b6524dcdc2e88a1c974c565243c1d830fc;hpb=bc651d80137d321dcc45b10a2dc5d603856a62ee;p=inkscape.git diff --git a/src/document.cpp b/src/document.cpp index 71f607b65..9fc6dc4da 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -91,6 +91,8 @@ SPDocument::SPDocument() { // Initialise instance of connector router. router = new Avoid::Router(); + // Don't use the Consolidate moves optimisation. + router->ConsolidateMoves = false; p = new SPDocumentPrivate(); @@ -106,6 +108,9 @@ SPDocument::SPDocument() { p->redo = NULL; priv = p; + + // XXX only for testing! + priv->undoStackObservers.add(p->console_output_undo_observer); } SPDocument::~SPDocument() { @@ -123,7 +128,7 @@ SPDocument::~SPDocument() { sp_document_clear_undo(this); if (root) { - sp_object_invoke_release(root); + root->releaseReferences(); sp_object_unref(root); root = NULL; } @@ -204,7 +209,7 @@ void SPDocument::reset_key (void *dummy) actionkey = NULL; } -static SPDocument * +SPDocument * sp_document_create(Inkscape::XML::Document *rdoc, gchar const *uri, gchar const *base, @@ -272,7 +277,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, // see if there's a template with id="base" in the preferences if (!r) { // if there's none, create an empty element - rnew = sp_repr_new("sodipodi:namedview"); + rnew = rdoc->createElement("sodipodi:namedview"); rnew->setAttribute("id", "base"); } else { // otherwise, take from preferences @@ -287,7 +292,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, /* Defs */ if (!SP_ROOT(document->root)->defs) { Inkscape::XML::Node *r; - r = sp_repr_new("svg:defs"); + r = rdoc->createElement("svg:defs"); rroot->addChild(r, NULL); Inkscape::GC::release(r); g_assert(SP_ROOT(document->root)->defs); @@ -300,7 +305,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, inkscape_ref(); } - sp_document_set_undo_sensitive(document, TRUE); + sp_document_set_undo_sensitive(document, true); // reset undo key when selection changes, so that same-key actions on different objects are not coalesced if (!Inkscape::NSApplication::Application::getNewGui()) { @@ -541,8 +546,8 @@ void sp_document_set_uri(SPDocument *document, gchar const *uri) // Update saveable repr attributes. Inkscape::XML::Node *repr = sp_document_repr_root(document); // changing uri in the document repr must not be not undoable - gboolean saved = sp_document_get_undo_sensitive(document); - sp_document_set_undo_sensitive(document, FALSE); + bool saved = sp_document_get_undo_sensitive(document); + sp_document_set_undo_sensitive(document, false); if (document->base) repr->setAttribute("sodipodi:docbase", document->base); @@ -603,6 +608,12 @@ SPDocument::emitReconstructionFinish(void) return; } +sigc::connection SPDocument::connectCommit(SPDocument::CommitSignal::slot_type slot) +{ + return priv->commit_signal.connect(slot); +} + + void SPDocument::_emitModified() { static guint const flags = SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG; @@ -732,69 +743,75 @@ sp_document_setup_viewport (SPDocument *doc, SPItemCtx *ctx) ctx->i2vp = NR::identity(); } +/** + * Tries to update the document state based on the modified and + * "update required" flags, and return true if the document has + * been brought fully up to date. + */ +bool +SPDocument::_updateDocument() +{ + /* Process updates */ + if (this->root->uflags || this->root->mflags) { + if (this->root->uflags) { + SPItemCtx ctx; + sp_document_setup_viewport (this, &ctx); + + bool saved = sp_document_get_undo_sensitive(this); + sp_document_set_undo_sensitive(this, false); + + this->root->updateDisplay((SPCtx *)&ctx, 0); + + sp_document_set_undo_sensitive(this, saved); + } + this->_emitModified(); + } + + return !(this->root->uflags || this->root->mflags); +} + + +/** + * Repeatedly works on getting the document updated, since sometimes + * it takes more than one pass to get the document updated. But it + * usually should not take more than a few loops, and certainly never + * more than 32 iterations. So we bail out if we hit 32 iterations, + * since this typically indicates we're stuck in an update loop. + */ gint sp_document_ensure_up_to_date(SPDocument *doc) { - int lc; - lc = 32; - while (doc->root->uflags || doc->root->mflags) { - lc -= 1; - if (lc < 0) { - g_warning("More than 32 iterations while updating document '%s'", doc->uri); - if (doc->modified_id) { - /* Remove handler */ - gtk_idle_remove(doc->modified_id); - doc->modified_id = 0; - } - return FALSE; - } - /* Process updates */ - if (doc->root->uflags) { - SPItemCtx ctx; - sp_document_setup_viewport (doc, &ctx); - doc->root->updateDisplay((SPCtx *)&ctx, 0); + int counter = 32; + while (!doc->_updateDocument()) { + if (counter == 0) { + g_warning("More than 32 iteration while updating document '%s'", doc->uri); + break; } - doc->_emitModified(); + counter--; } + if (doc->modified_id) { /* Remove handler */ gtk_idle_remove(doc->modified_id); doc->modified_id = 0; } - return TRUE; + return counter>0; } +/** + * An idle handler to update the document. Returns true if + * the document needs further updates. + */ static gint sp_document_idle_handler(gpointer data) { - SPDocument *doc; - int repeat; - - doc = static_cast(data); - -#ifdef SP_DOCUMENT_DEBUG_IDLE - g_print("->\n"); -#endif - - /* Process updates */ - if (doc->root->uflags) { - SPItemCtx ctx; - sp_document_setup_viewport (doc, &ctx); - - gboolean saved = sp_document_get_undo_sensitive(doc); - sp_document_set_undo_sensitive(doc, FALSE); - - doc->root->updateDisplay((SPCtx *)&ctx, 0); - - sp_document_set_undo_sensitive(doc, saved); - /* if (doc->root->uflags & SP_OBJECT_MODIFIED_FLAG) return TRUE; */ + SPDocument *doc = static_cast(data); + if (doc->_updateDocument()) { + doc->modified_id = 0; + return false; + } else { + return true; } - - doc->_emitModified(); - - repeat = (doc->root->uflags || doc->root->mflags); - if (!repeat) doc->modified_id = 0; - return repeat; } static bool is_within(NR::Rect const &area, NR::Rect const &box)