X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=inline;f=src%2Fdocument.cpp;h=356fba577055c7cab0d165401117f68c68fcadc6;hb=96d7f74ab56c7ce6cf9df0108ce925f59bcf0035;hp=3579c4c91ffc1906ae25060816f0c804093c0d90;hpb=89949341e299d2857fc2435d5a8758845947dc0a;p=inkscape.git diff --git a/src/document.cpp b/src/document.cpp index 3579c4c91..356fba577 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -38,6 +38,8 @@ # include "config.h" #endif #include +#include +#include #include "application/application.h" #include "application/editor.h" #include "libnr/nr-matrix-fns.h" @@ -46,6 +48,8 @@ #include "inkscape-private.h" #include "inkscape_version.h" #include "sp-object-repr.h" +#include "sp-namedview.h" +#include "desktop.h" #include "document-private.h" #include "dir-util.h" #include "unit-constants.h" @@ -53,13 +57,14 @@ #include "libavoid/router.h" #include "libnr/nr-rect.h" #include "sp-item-group.h" +#include "profile-manager.h" +#include "persp3d.h" #include "display/nr-arena-item.h" #include "dialogs/rdf.h" -#define A4_WIDTH_STR "210mm" -#define A4_HEIGHT_STR "297mm" +#include "transf_mat_3x4.h" #define SP_DOCUMENT_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE - 1) @@ -70,31 +75,34 @@ gboolean sp_document_resource_list_free(gpointer key, gpointer value, gpointer d static gint doc_count = 0; -SPDocument::SPDocument() { - SPDocumentPrivate *p; - - keepalive = FALSE; - virgin = TRUE; - - modified_id = 0; - - rdoc = NULL; - rroot = NULL; - root = NULL; - style_cascade = cr_cascade_new(NULL, NULL, NULL); - - uri = NULL; - base = NULL; - name = NULL; - - _collection_queue = NULL; - - // Initialise instance of connector router. - router = new Avoid::Router(); +static unsigned long next_serial = 0; + +SPDocument::SPDocument() : + keepalive(FALSE), + virgin(TRUE), + modified_since_save(FALSE), + rdoc(0), + rroot(0), + root(0), + style_cascade(cr_cascade_new(NULL, NULL, NULL)), + uri(0), + base(0), + name(0), + priv(0), // reset in ctor + actionkey(0), + modified_id(0), + profileManager(0), // deferred until after other initialization + router(new Avoid::Router()), + perspectives(0), + current_persp3d(0), + _collection_queue(0) +{ // Don't use the Consolidate moves optimisation. router->ConsolidateMoves = false; - p = new SPDocumentPrivate(); + SPDocumentPrivate *p = new SPDocumentPrivate(); + + p->serial = next_serial++; p->iddef = g_hash_table_new(g_direct_hash, g_direct_equal); p->reprdef = g_hash_table_new(g_direct_hash, g_direct_equal); @@ -106,9 +114,13 @@ SPDocument::SPDocument() { p->history_size = 0; p->undo = NULL; p->redo = NULL; + p->seeking = false; priv = p; + // Once things are set, hook in the manager + profileManager = new Inkscape::ProfileManager(this); + // XXX only for testing! priv->undoStackObservers.add(p->console_output_undo_observer); } @@ -116,9 +128,13 @@ SPDocument::SPDocument() { SPDocument::~SPDocument() { collectOrphans(); - if (priv) { - inkscape_remove_document(this); + // kill/unhook this first + if ( profileManager ) { + delete profileManager; + profileManager = 0; + } + if (priv) { if (priv->partial) { sp_repr_free_log(priv->partial); priv->partial = NULL; @@ -181,6 +197,31 @@ SPDocument::~SPDocument() { } //delete this->_whiteboard_session_manager; + +} + +void SPDocument::add_persp3d (Persp3D * const /*persp*/) +{ + SPDefs *defs = SP_ROOT(this->root)->defs; + for (SPObject *i = sp_object_first_child(SP_OBJECT(defs)); i != NULL; i = SP_OBJECT_NEXT(i) ) { + if (SP_IS_PERSP3D(i)) { + g_print ("Encountered a Persp3D in defs\n"); + } + } + + g_print ("Adding Persp3D to defs\n"); + persp3d_create_xml_element (this); +} + +void SPDocument::remove_persp3d (Persp3D * const /*persp*/) +{ + // TODO: Delete the repr, maybe perform a check if any boxes are still linked to the perspective. + // Anything else? + g_print ("Please implement deletion of perspectives here.\n"); +} + +unsigned long SPDocument::serial() const { + return priv->serial; } void SPDocument::queueForOrphanCollection(SPObject *object) { @@ -204,7 +245,7 @@ void SPDocument::collectOrphans() { } } -void SPDocument::reset_key (void *dummy) +void SPDocument::reset_key (void */*dummy*/) { actionkey = NULL; } @@ -255,19 +296,22 @@ sp_document_create(Inkscape::XML::Document *rdoc, /* fixme: Again, I moved these here to allow version determining in ::build (Lauris) */ /* Quick hack 2 - get default image size into document */ - if (!rroot->attribute("width")) rroot->setAttribute("width", A4_WIDTH_STR); - if (!rroot->attribute("height")) rroot->setAttribute("height", A4_HEIGHT_STR); + if (!rroot->attribute("width")) rroot->setAttribute("width", "100%"); + if (!rroot->attribute("height")) rroot->setAttribute("height", "100%"); /* End of quick hack 2 */ /* Quick hack 3 - Set uri attributes */ if (uri) { - /* fixme: Think, what this means for images (Lauris) */ rroot->setAttribute("sodipodi:docname", uri); - if (document->base) - rroot->setAttribute("sodipodi:docbase", document->base); } /* End of quick hack 3 */ + /* Eliminate obsolete sodipodi:docbase, for privacy reasons */ + rroot->setAttribute("sodipodi:docbase", NULL); + + /* Eliminate any claim to adhere to a profile, as we don't try to */ + rroot->setAttribute("baseProfile", NULL); + // creating namedview if (!sp_item_group_get_child_by_name((SPGroup *) document->root, NULL, "sodipodi:namedview")) { // if there's none in the document already, @@ -281,7 +325,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, rnew->setAttribute("id", "base"); } else { // otherwise, take from preferences - rnew = r->duplicate(); + rnew = r->duplicate(rroot->document()); } // insert into the document rroot->addChild(rnew, NULL); @@ -305,6 +349,15 @@ sp_document_create(Inkscape::XML::Document *rdoc, inkscape_ref(); } + // Remark: Here, we used to create a "currentpersp3d" element in the document defs. + // But this is probably a bad idea since we need to adapt it for every change of selection, which will + // completely clutter the undo history. Maybe rather save it to prefs on exit and re-read it on startup? + + document->current_persp3d = persp3d_document_first_persp(document); + if (!document->current_persp3d) { + document->current_persp3d = persp3d_create_xml_element (document); + } + sp_document_set_undo_sensitive(document, true); // reset undo key when selection changes, so that same-key actions on different objects are not coalesced @@ -317,7 +370,6 @@ sp_document_create(Inkscape::XML::Document *rdoc, document->_selection_changed_connection = Inkscape::NSApplication::Editor::connectSelectionChanged (sigc::mem_fun (*document, &SPDocument::reset_key)); document->_desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*document, &SPDocument::reset_key)); } - inkscape_add_document(document); return document; } @@ -402,12 +454,6 @@ sp_document_new_from_mem(gchar const *buffer, gint length, unsigned int keepaliv return doc; } -SPDocument *sp_document_new_dummy() { - SPDocument *document = new SPDocument(); - inkscape_add_document(document); - return document; -} - SPDocument * sp_document_ref(SPDocument *doc) { @@ -430,7 +476,11 @@ gdouble sp_document_width(SPDocument *document) g_return_val_if_fail(document->priv != NULL, 0.0); g_return_val_if_fail(document->root != NULL, 0.0); - return SP_ROOT(document->root)->width.computed; + SPRoot *root = SP_ROOT(document->root); + + if (root->width.unit == SVGLength::PERCENT && root->viewBox_set) + return root->viewBox.x1 - root->viewBox.x0; + return root->width.computed; } void @@ -484,27 +534,42 @@ gdouble sp_document_height(SPDocument *document) g_return_val_if_fail(document->priv != NULL, 0.0); g_return_val_if_fail(document->root != NULL, 0.0); - return SP_ROOT(document->root)->height.computed; + SPRoot *root = SP_ROOT(document->root); + + if (root->height.unit == SVGLength::PERCENT && root->viewBox_set) + return root->viewBox.y1 - root->viewBox.y0; + return root->height.computed; } /** - * Given an NRRect that may, for example, correspond to the bbox of an object + * Given an NR::Rect that may, for example, correspond to the bbox of an object, * this function fits the canvas to that rect by resizing the canvas * and translating the document root into position. */ -void SPDocument::fitToRect(NRRect const & rect) +void SPDocument::fitToRect(NR::Rect const &rect) { - g_return_if_fail(!empty(rect)); - - gdouble w = rect.x1 - rect.x0; - gdouble h = rect.y1 - rect.y0; - gdouble old_height = sp_document_height(this); - SPUnit unit = sp_unit_get_by_id(SP_UNIT_PX); - sp_document_set_width(this, w, &unit); - sp_document_set_height(this, h, &unit); - - NR::translate tr = NR::translate::translate(-rect.x0,-(rect.y0 + (h - old_height))); - static_cast(root)->translateChildItems(tr); + g_return_if_fail(!rect.isEmpty()); + + using NR::X; using NR::Y; + double const w = rect.extent(X); + double const h = rect.extent(Y); + + double const old_height = sp_document_height(this); + SPUnit const &px(sp_unit_get_by_id(SP_UNIT_PX)); + sp_document_set_width(this, w, &px); + sp_document_set_height(this, h, &px); + + NR::translate const tr(NR::Point(0, (old_height - h)) + - rect.min()); + SP_GROUP(root)->translateChildItems(tr); + SPNamedView *nv = sp_document_namedview(this, 0); + if(nv) { + NR::translate tr2(-rect.min()); + nv->translateGuides(tr2); + + // update the viewport so the drawing appears to stay where it was + nv->scrollAllDesktops(-tr2[0], tr2[1], false); + } } void sp_document_set_uri(SPDocument *document, gchar const *uri) @@ -548,8 +613,6 @@ void sp_document_set_uri(SPDocument *document, gchar const *uri) // changing uri in the document repr must not be not undoable bool saved = sp_document_get_undo_sensitive(document); sp_document_set_undo_sensitive(document, false); - if (document->base) - repr->setAttribute("sodipodi:docbase", document->base); repr->setAttribute("sodipodi:docname", document->name); sp_document_set_undo_sensitive(document, saved); @@ -647,13 +710,13 @@ void SPDocument::bindObjectToId(gchar const *id, SPObject *object) { void SPDocument::addUndoObserver(Inkscape::UndoStackObserver& observer) { - this->priv->undoStackObservers.add(observer); + this->priv->undoStackObservers.add(observer); } void SPDocument::removeUndoObserver(Inkscape::UndoStackObserver& observer) { - this->priv->undoStackObservers.remove(observer); + this->priv->undoStackObservers.remove(observer); } SPObject *SPDocument::getObjectById(gchar const *id) { @@ -699,7 +762,7 @@ Glib::ustring SPDocument::getLanguage() { if ( NULL == document_language || *document_language == 0 ) { document_language = getenv ("LANG"); } - + if ( NULL != document_language ) { gchar *pos = strchr(document_language, '_'); if ( NULL != pos ) { @@ -744,7 +807,7 @@ sp_document_setup_viewport (SPDocument *doc, SPItemCtx *ctx) } /** - * Tries to update the document state based on the modified and + * 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. */ @@ -837,8 +900,8 @@ static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, s = find_items_in_area(s, SP_GROUP(o), dkey, area, test); } else { SPItem *child = SP_ITEM(o); - NR::Rect box = sp_item_bbox_desktop(child); - if (test(area, box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { + NR::Maybe box = sp_item_bbox_desktop(child); + if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { s = g_slist_append(s, child); } } @@ -917,7 +980,7 @@ find_item_at_point(unsigned int dkey, SPGroup *group, NR::Point const p, gboolea if (upto && SP_ITEM(o) == upto) break; - if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { + if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { // if nothing found yet, recurse into the group newseen = find_item_at_point(dkey, SP_GROUP(o), p, into_groups, take_insensitive, upto); if (newseen) { @@ -1004,6 +1067,30 @@ GSList *sp_document_partial_items_in_box(SPDocument *document, unsigned int dkey return find_items_in_area(NULL, SP_GROUP(document->root), dkey, box, overlaps); } +GSList * +sp_document_items_at_points(SPDocument *document, unsigned const key, std::vector points) +{ + GSList *items = NULL; + + // When picking along the path, we don't want small objects close together + // (such as hatching strokes) to obscure each other by their deltas, + // so we temporarily set delta to a small value + gdouble saved_delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0); + prefs_set_double_attribute ("options.cursortolerance", "value", 0.25); + + for(unsigned int i = 0; i < points.size(); i++) { + SPItem *item = sp_document_item_at_point(document, key, points[i], + false, NULL); + if (item && !g_slist_find(items, item)) + items = g_slist_prepend (items, item); + } + + // and now we restore it back + prefs_set_double_attribute ("options.cursortolerance", "value", saved_delta); + + return items; +} + SPItem * sp_document_item_at_point(SPDocument *document, unsigned const key, NR::Point const p, gboolean const into_groups, SPItem *upto) @@ -1098,7 +1185,7 @@ sigc::connection sp_document_resources_changed_connect(SPDocument *document, /* Helpers */ gboolean -sp_document_resource_list_free(gpointer key, gpointer value, gpointer data) +sp_document_resource_list_free(gpointer /*key*/, gpointer value, gpointer /*data*/) { g_slist_free((GSList *) value); return TRUE; @@ -1160,6 +1247,10 @@ vacuum_document(SPDocument *document) return start - newend; } +bool SPDocument::isSeeking() const { + return priv->seeking; +} + /* Local Variables: