X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fdocument.cpp;h=4b71576096b3ce85f633fa0b7dd76053d980f2c3;hb=84e5676034b77e63dbc43746cec0a8b48fd06f7c;hp=ebc65830f1bbc90c9db4969b5ea5129cf8c8aed1;hpb=34bbe9388eab58e6a7ab25d664595e0ed3b8dee8;p=inkscape.git diff --git a/src/document.cpp b/src/document.cpp index ebc65830f..4b7157609 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -53,11 +53,15 @@ #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" +#include "transf_mat_3x4.h" + #define A4_WIDTH_STR "210mm" #define A4_HEIGHT_STR "297mm" @@ -66,12 +70,12 @@ static gint sp_document_idle_handler(gpointer data); -// JON: This must stay as gboolean because its used as a callback into -// our legacy c stuff in here. Would like to make bool gboolean sp_document_resource_list_free(gpointer key, gpointer value, gpointer data); static gint doc_count = 0; +static unsigned long next_serial = 0; + SPDocument::SPDocument() { SPDocumentPrivate *p; @@ -96,8 +100,12 @@ SPDocument::SPDocument() { // Don't use the Consolidate moves optimisation. router->ConsolidateMoves = false; + perspectives = NULL; + 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); @@ -108,12 +116,13 @@ SPDocument::SPDocument() { p->history_size = 0; p->undo = NULL; p->redo = NULL; - - p->undoStackObservers.add(p->event_log); - p->event_log.setDocument(this); + 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); } @@ -121,9 +130,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; @@ -186,6 +199,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) { @@ -209,7 +247,7 @@ void SPDocument::collectOrphans() { } } -void SPDocument::reset_key (void *dummy) +void SPDocument::reset_key (void */*dummy*/) { actionkey = NULL; } @@ -225,7 +263,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, Inkscape::XML::Node *rroot; Inkscape::Version sodipodi_version; - rroot = sp_repr_document_root(rdoc); + rroot = rdoc->root(); document = new SPDocument(); @@ -266,10 +304,7 @@ sp_document_create(Inkscape::XML::Document *rdoc, /* 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 */ @@ -282,11 +317,11 @@ 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 - rnew = r->duplicate(); + rnew = r->duplicate(rroot->document()); } // insert into the document rroot->addChild(rnew, NULL); @@ -297,7 +332,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); @@ -310,7 +345,60 @@ sp_document_create(Inkscape::XML::Document *rdoc, inkscape_ref(); } - sp_document_set_undo_sensitive(document, TRUE); + /* Create an initial perspective, make it current and append it to the list of existing perspectives */ + /*** + document->current_perspective = new Box3D::Perspective3D ( + // VP in x-direction + Box3D::VanishingPoint( NR::Point(-50.0, 600.0), + NR::Point( -1.0, 0.0), Box3D::VP_FINITE), + // VP in y-direction + Box3D::VanishingPoint( NR::Point(500.0,1000.0), + NR::Point( 0.0, 1.0), Box3D::VP_INFINITE), + // VP in z-direction + Box3D::VanishingPoint( NR::Point(700.0, 600.0), + NR::Point(sqrt(3.0),1.0), Box3D::VP_FINITE), + document); + + document->add_perspective (document->current_perspective); + ***/ + + // 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? + + Proj::Pt2 proj_vp_x = Proj::Pt2 (-50.0, 600.0, 1.0); + Proj::Pt2 proj_vp_y = Proj::Pt2 ( 0.0,1000.0, 0.0); + Proj::Pt2 proj_vp_z = Proj::Pt2 (700.0, 600.0, 1.0); + Proj::Pt2 proj_origin = Proj::Pt2 (300.0, 400.0, 1.0); + + document->current_persp3d = (Persp3D *) persp3d_create_xml_element (document); + Inkscape::XML::Node *repr = SP_OBJECT_REPR(document->current_persp3d); + + gchar *str = NULL; + str = proj_vp_x.coord_string(); + repr->setAttribute("inkscape:vp_x", str); + g_free (str); + str = proj_vp_y.coord_string(); + repr->setAttribute("inkscape:vp_y", str); + g_free (str); + str = proj_vp_z.coord_string(); + repr->setAttribute("inkscape:vp_z", str); + g_free (str); + str = proj_origin.coord_string(); + repr->setAttribute("inkscape:persp3d-origin", str); + g_free (str); + Inkscape::GC::release(repr); + + /*** + document->current_persp3d = (Persp3D *) sp_object_get_child_by_repr (SP_OBJECT(defs), repr); + g_assert (document->current_persp3d != NULL); + persp3d_update_with_point (document->current_persp3d, Proj::X, proj_vp_x); + persp3d_update_with_point (document->current_persp3d, Proj::Y, proj_vp_y); + persp3d_update_with_point (document->current_persp3d, Proj::Z, proj_vp_z); + persp3d_update_with_point (document->current_persp3d, Proj::W, proj_origin); + ***/ + + 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()) { @@ -322,7 +410,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; } @@ -346,7 +433,7 @@ sp_document_new(gchar const *uri, unsigned int keepalive, bool make_new) rdoc = sp_repr_read_file(uri, SP_SVG_NS_URI); /* If file cannot be loaded, return NULL without warning */ if (rdoc == NULL) return NULL; - rroot = sp_repr_document_root(rdoc); + rroot = rdoc->root(); /* If xml file is not svg, return NULL without warning */ /* fixme: destroy document */ if (strcmp(rroot->name(), "svg:svg") != 0) return NULL; @@ -395,7 +482,7 @@ sp_document_new_from_mem(gchar const *buffer, gint length, unsigned int keepaliv /* If it cannot be loaded, return NULL without warning */ if (rdoc == NULL) return NULL; - rroot = sp_repr_document_root(rdoc); + rroot = rdoc->root(); /* If xml file is not svg, return NULL without warning */ /* fixme: destroy document */ if (strcmp(rroot->name(), "svg:svg") != 0) return NULL; @@ -407,12 +494,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) { @@ -493,23 +574,26 @@ gdouble sp_document_height(SPDocument *document) } /** - * 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); + 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 tr = NR::translate::translate(-rect.x0,-(rect.y0 + (h - old_height))); - static_cast(root)->translateChildItems(tr); + NR::translate const tr(NR::Point(0, (old_height - h)) + - rect.min()); + SP_GROUP(root)->translateChildItems(tr); } void sp_document_set_uri(SPDocument *document, gchar const *uri) @@ -552,9 +636,7 @@ void sp_document_set_uri(SPDocument *document, gchar const *uri) Inkscape::XML::Node *repr = sp_document_repr_root(document); // 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); + sp_document_set_undo_sensitive(document, false); repr->setAttribute("sodipodi:docname", document->name); sp_document_set_undo_sensitive(document, saved); @@ -661,12 +743,6 @@ SPDocument::removeUndoObserver(Inkscape::UndoStackObserver& observer) this->priv->undoStackObservers.remove(observer); } -Inkscape::EventLog& -SPDocument::getEventLog() const -{ - return priv->event_log; -} - SPObject *SPDocument::getObjectById(gchar const *id) { g_return_val_if_fail(id != NULL, NULL); @@ -769,7 +845,7 @@ SPDocument::_updateDocument() sp_document_setup_viewport (this, &ctx); bool saved = sp_document_get_undo_sensitive(this); - sp_document_set_undo_sensitive(this, FALSE); + sp_document_set_undo_sensitive(this, false); this->root->updateDisplay((SPCtx *)&ctx, 0); @@ -848,8 +924,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); } } @@ -916,7 +992,7 @@ upwards in z-order and returns what it has found so far (i.e. the found item is guaranteed to be lower than upto). */ SPItem* -find_item_at_point(unsigned int dkey, SPGroup *group, NR::Point const p, bool into_groups, bool take_insensitive = false, SPItem *upto = NULL) +find_item_at_point(unsigned int dkey, SPGroup *group, NR::Point const p, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) { SPItem *seen = NULL, *newseen = NULL; @@ -1015,9 +1091,33 @@ 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, - bool const into_groups, SPItem *upto) + gboolean const into_groups, SPItem *upto) { g_return_val_if_fail(document != NULL, NULL); g_return_val_if_fail(document->priv != NULL, NULL); @@ -1037,7 +1137,7 @@ sp_document_group_at_point(SPDocument *document, unsigned int key, NR::Point con /* Resource management */ -bool +gboolean sp_document_add_resource(SPDocument *document, gchar const *key, SPObject *object) { GSList *rlist; @@ -1062,7 +1162,7 @@ sp_document_add_resource(SPDocument *document, gchar const *key, SPObject *objec return TRUE; } -bool +gboolean sp_document_remove_resource(SPDocument *document, gchar const *key, SPObject *object) { GSList *rlist; @@ -1108,10 +1208,8 @@ sigc::connection sp_document_resources_changed_connect(SPDocument *document, /* Helpers */ -// JON: This must stay this way because it is used as a callback for -// legacy glib code which needs to be moved to glibmm 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; @@ -1173,6 +1271,10 @@ vacuum_document(SPDocument *document) return start - newend; } +bool SPDocument::isSeeking() const { + return priv->seeking; +} + /* Local Variables: