diff --git a/src/document.cpp b/src/document.cpp
index ebc65830f1bbc90c9db4969b5ea5129cf8c8aed1..8503c7841e153a117d57f802ba133e898860d38c 100644 (file)
--- a/src/document.cpp
+++ b/src/document.cpp
# include "config.h"
#endif
#include <gtk/gtkmain.h>
+#include <string>
+#include <cstring>
+
#include "application/application.h"
#include "application/editor.h"
-#include "libnr/nr-matrix-fns.h"
-#include "xml/repr.h"
+#include "desktop.h"
+#include "dir-util.h"
+#include "display/nr-arena-item.h"
+#include "document-private.h"
#include "helper/units.h"
#include "inkscape-private.h"
-#include "inkscape_version.h"
-#include "sp-object-repr.h"
-#include "document-private.h"
-#include "dir-util.h"
-#include "unit-constants.h"
-#include "prefs-utils.h"
+#include "inkscape-version.h"
#include "libavoid/router.h"
-#include "libnr/nr-rect.h"
+#include "persp3d.h"
+#include "preferences.h"
+#include "profile-manager.h"
+#include "rdf.h"
#include "sp-item-group.h"
-
-#include "display/nr-arena-item.h"
-
-#include "dialogs/rdf.h"
-
-#define A4_WIDTH_STR "210mm"
-#define A4_HEIGHT_STR "297mm"
+#include "sp-namedview.h"
+#include "sp-object-repr.h"
+#include "transf_mat_3x4.h"
+#include "unit-constants.h"
+#include "xml/repr.h"
+#include "xml/rebase-hrefs.h"
#define SP_DOCUMENT_UPDATE_PRIORITY (G_PRIORITY_HIGH_IDLE - 1)
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;
-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),
+ oldSignalsConnected(false)
+{
// 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);
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);
}
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;
modified_id = 0;
}
- _selection_changed_connection.disconnect();
- _desktop_activated_connection.disconnect();
+ if (oldSignalsConnected) {
+ g_signal_handlers_disconnect_by_func(G_OBJECT(INKSCAPE),
+ reinterpret_cast<gpointer>(sp_document_reset_key),
+ static_cast<gpointer>(this));
+ } else {
+ _selection_changed_connection.disconnect();
+ _desktop_activated_connection.disconnect();
+ }
if (keepalive) {
inkscape_unref();
}
//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) {
}
}
-void SPDocument::reset_key (void *dummy)
+void SPDocument::reset_key (void */*dummy*/)
{
actionkey = NULL;
}
{
SPDocument *document;
Inkscape::XML::Node *rroot;
- Inkscape::Version sodipodi_version;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- rroot = sp_repr_document_root(rdoc);
+ rroot = rdoc->root();
document = new SPDocument();
document->rroot = rroot;
#ifndef WIN32
- prepend_current_dir_if_relative(&(document->uri), uri);
+ document->uri = prepend_current_dir_if_relative(uri);
#else
// FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test!
document->uri = uri? g_strdup(uri) : NULL;
document->root = sp_object_repr_build_tree(document, rroot);
- sodipodi_version = SP_ROOT(document->root)->version.sodipodi;
-
/* fixme: Not sure about this, but lets assume ::build updates */
- rroot->setAttribute("sodipodi:version", SODIPODI_VERSION);
- rroot->setAttribute("inkscape:version", INKSCAPE_VERSION);
+ rroot->setAttribute("inkscape:version", Inkscape::version_string);
/* 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,
- Inkscape::XML::Node *r = NULL;
Inkscape::XML::Node *rnew = NULL;
- r = inkscape_get_repr(INKSCAPE, "template.base");
- // 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->setAttribute("id", "base");
- } else {
- // otherwise, take from preferences
- rnew = r->duplicate();
+
+ rnew = rdoc->createElement("sodipodi:namedview");
+ //rnew->setAttribute("id", "base");
+
+ // Add namedview data from the preferences
+ // we can't use getAllEntries because this could produce non-SVG doubles
+ Glib::ustring pagecolor = prefs->getString("/template/base/pagecolor");
+ if (!pagecolor.empty()) {
+ rnew->setAttribute("pagecolor", pagecolor.data());
+ }
+ Glib::ustring bordercolor = prefs->getString("/template/base/bordercolor");
+ if (!bordercolor.empty()) {
+ rnew->setAttribute("bordercolor", bordercolor.data());
}
+ sp_repr_set_svg_double(rnew, "borderopacity",
+ prefs->getDouble("/template/base/borderopacity", 1.0));
+ sp_repr_set_svg_double(rnew, "objecttolerance",
+ prefs->getDouble("/template/base/objecttolerance", 10.0));
+ sp_repr_set_svg_double(rnew, "gridtolerance",
+ prefs->getDouble("/template/base/gridtolerance", 10.0));
+ sp_repr_set_svg_double(rnew, "guidetolerance",
+ prefs->getDouble("/template/base/guidetolerance", 10.0));
+ sp_repr_set_svg_double(rnew, "inkscape:pageopacity",
+ prefs->getDouble("/template/base/inkscape:pageopacity", 0.0));
+ sp_repr_set_int(rnew, "inkscape:pageshadow",
+ prefs->getInt("/template/base/inkscape:pageshadow", 2));
+ sp_repr_set_int(rnew, "inkscape:window-width",
+ prefs->getInt("/template/base/inkscape:window-width", 640));
+ sp_repr_set_int(rnew, "inkscape:window-height",
+ prefs->getInt("/template/base/inkscape:window-height", 480));
+
// insert into the document
rroot->addChild(rnew, NULL);
// clean up
/* 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);
inkscape_ref();
}
- sp_document_set_undo_sensitive(document, TRUE);
+ // 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
if (!Inkscape::NSApplication::Application::getNewGui()) {
G_CALLBACK(sp_document_reset_key), document);
g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop",
G_CALLBACK(sp_document_reset_key), document);
+ document->oldSignalsConnected = true;
} else {
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));
+ document->oldSignalsConnected = false;
}
- inkscape_add_document(document);
return document;
}
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 +465,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 +477,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)
{
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
if (root->width.unit == SVGLength::PERCENT && root->viewBox_set) { // set to viewBox=
root->viewBox.x1 = root->viewBox.x0 + sp_units_get_pixels (width, *unit);
} else { // set to width=
+ gdouble old_computed = root->width.computed;
root->width.computed = sp_units_get_pixels (width, *unit);
/* SVG does not support meters as a unit, so we must translate meters to
* cm when writing */
root->width.value = width;
root->width.unit = (SVGLength::Unit) sp_unit_get_svg_unit(unit);
}
+
+ if (root->viewBox_set)
+ root->viewBox.x1 = root->viewBox.x0 + (root->width.computed / old_computed) * (root->viewBox.x1 - root->viewBox.x0);
}
SP_OBJECT (root)->updateRepr();
@@ -468,6 +540,7 @@ void sp_document_set_height (SPDocument * document, gdouble height, const SPUnit
if (root->height.unit == SVGLength::PERCENT && root->viewBox_set) { // set to viewBox=
root->viewBox.y1 = root->viewBox.y0 + sp_units_get_pixels (height, *unit);
} else { // set to height=
+ gdouble old_computed = root->height.computed;
root->height.computed = sp_units_get_pixels (height, *unit);
/* SVG does not support meters as a unit, so we must translate meters to
* cm when writing */
@@ -478,6 +551,9 @@ void sp_document_set_height (SPDocument * document, gdouble height, const SPUnit
root->height.value = height;
root->height.unit = (SVGLength::Unit) sp_unit_get_svg_unit(unit);
}
+
+ if (root->viewBox_set)
+ root->viewBox.y1 = root->viewBox.y0 + (root->height.computed / old_computed) * (root->viewBox.y1 - root->viewBox.y0);
}
SP_OBJECT (root)->updateRepr();
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;
+}
+
+Geom::Point sp_document_dimensions(SPDocument *doc)
+{
+ return Geom::Point(sp_document_width(doc), sp_document_height(doc));
}
/**
- * Given an NRRect that may, for example, correspond to the bbox of an object
+ * Given a Geom::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(Geom::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<SPGroup *>(root)->translateChildItems(tr);
+ double const w = rect.width();
+ double const h = rect.height();
+
+ 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);
+
+ Geom::Translate const tr(Geom::Point(0, (old_height - h))
+ - to_2geom(rect.min()));
+ SP_GROUP(root)->translateChildItems(tr);
+ SPNamedView *nv = sp_document_namedview(this, 0);
+ if(nv) {
+ Geom::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)
+static void
+do_change_uri(SPDocument *const document, gchar const *const filename, bool const rebase)
{
g_return_if_fail(document != NULL);
- if (document->name) {
- g_free(document->name);
- document->name = NULL;
- }
- if (document->base) {
- g_free(document->base);
- document->base = NULL;
- }
- if (document->uri) {
- g_free(document->uri);
- document->uri = NULL;
- }
-
- if (uri) {
+ gchar *new_base;
+ gchar *new_name;
+ gchar *new_uri;
+ if (filename) {
#ifndef WIN32
- prepend_current_dir_if_relative(&(document->uri), uri);
+ new_uri = prepend_current_dir_if_relative(filename);
#else
// FIXME: it may be that prepend_current_dir_if_relative works OK on windows too, test!
- document->uri = g_strdup(uri);
+ new_uri = g_strdup(filename);
#endif
- /* fixme: Think, what this means for images (Lauris) */
- document->base = g_path_get_dirname(document->uri);
- document->name = g_path_get_basename(document->uri);
-
+ new_base = g_path_get_dirname(new_uri);
+ new_name = g_path_get_basename(new_uri);
} else {
- document->uri = g_strdup_printf(_("Unnamed document %d"), ++doc_count);
- document->base = NULL;
- document->name = g_strdup(document->uri);
+ new_uri = g_strdup_printf(_("Unnamed document %d"), ++doc_count);
+ new_base = NULL;
+ new_name = g_strdup(document->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
- bool saved = sp_document_get_undo_sensitive(document);
- sp_document_set_undo_sensitive(document, FALSE);
- if (document->base)
- repr->setAttribute("sodipodi:docbase", document->base);
+
+ // Changing uri in the document repr must not be not undoable.
+ bool const saved = sp_document_get_undo_sensitive(document);
+ sp_document_set_undo_sensitive(document, false);
+
+ if (rebase) {
+ Inkscape::XML::rebase_hrefs(document, new_base, true);
+ }
repr->setAttribute("sodipodi:docname", document->name);
sp_document_set_undo_sensitive(document, saved);
+
+ g_free(document->name);
+ g_free(document->base);
+ g_free(document->uri);
+ document->name = new_name;
+ document->base = new_base;
+ document->uri = new_uri;
+
document->priv->uri_set_signal.emit(document->uri);
}
+/**
+ * Sets base, name and uri members of \a document. Doesn't update
+ * any relative hrefs in the document: thus, this is primarily for
+ * newly-created documents.
+ *
+ * \see sp_document_change_uri_and_hrefs
+ */
+void sp_document_set_uri(SPDocument *document, gchar const *filename)
+{
+ g_return_if_fail(document != NULL);
+
+ do_change_uri(document, filename, false);
+}
+
+/**
+ * Changes the base, name and uri members of \a document, and updates any
+ * relative hrefs in the document to be relative to the new base.
+ *
+ * \see sp_document_set_uri
+ */
+void sp_document_change_uri_and_hrefs(SPDocument *document, gchar const *filename)
+{
+ g_return_if_fail(document != NULL);
+
+ do_change_uri(document, filename, true);
+}
+
void
sp_document_resized_signal_emit(SPDocument *doc, gdouble width, gdouble height)
{
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);
-}
-
-Inkscape::EventLog&
-SPDocument::getEventLog() const
-{
- return priv->event_log;
+ this->priv->undoStackObservers.remove(observer);
}
SPObject *SPDocument::getObjectById(gchar const *id) {
if ( NULL == document_language || *document_language == 0 ) {
document_language = getenv ("LANG");
}
-
+
if ( NULL != document_language ) {
- gchar *pos = strchr(document_language, '_');
+ const char *pos = strchr(document_language, '_');
if ( NULL != pos ) {
return Glib::ustring(document_language, pos - document_language);
}
sp_document_setup_viewport (SPDocument *doc, SPItemCtx *ctx)
{
ctx->ctx.flags = 0;
- ctx->i2doc = NR::identity();
+ ctx->i2doc = Geom::identity();
/* Set up viewport in case svg has it defined as percentages */
if (SP_ROOT(doc->root)->viewBox_set) { // if set, take from viewBox
ctx->vp.x0 = SP_ROOT(doc->root)->viewBox.x0;
ctx->vp.x1 = 210 * PX_PER_MM;
ctx->vp.y1 = 297 * PX_PER_MM;
}
- ctx->i2vp = NR::identity();
+ ctx->i2vp = Geom::identity();
}
/**
- * 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.
*/
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);
* 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,
+ * more than 64 iterations. So we bail out if we hit 64 iterations,
* since this typically indicates we're stuck in an update loop.
*/
gint
sp_document_ensure_up_to_date(SPDocument *doc)
{
- int counter = 32;
+ int counter = 64;
while (!doc->_updateDocument()) {
if (counter == 0) {
- g_warning("More than 32 iteration while updating document '%s'", doc->uri);
+ g_warning("More than 64 iteration while updating document '%s'", doc->uri? doc->uri:"<unknown URI, probably clipboard>");
break;
}
counter--;
}
}
-static bool is_within(NR::Rect const &area, NR::Rect const &box)
+static bool is_within(Geom::Rect const &area, Geom::Rect const &box)
{
return area.contains(box);
}
-static bool overlaps(NR::Rect const &area, NR::Rect const &box)
+static bool overlaps(Geom::Rect const &area, Geom::Rect const &box)
{
return area.intersects(box);
}
-static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, NR::Rect const &area,
- bool (*test)(NR::Rect const &, NR::Rect const &), bool take_insensitive = false)
+static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, Geom::Rect const &area,
+ bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false)
{
g_return_val_if_fail(SP_IS_GROUP(group), s);
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))) {
+ Geom::OptRect box = sp_item_bbox_desktop(child);
+ if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) {
s = g_slist_append(s, child);
}
}
@@ -879,11 +993,11 @@ Returns the bottommost item from the list which is at the point, or NULL if none
*/
SPItem*
sp_document_item_from_list_at_point_bottom(unsigned int dkey, SPGroup *group, GSList const *list,
- NR::Point const p, bool take_insensitive)
+ Geom::Point const p, bool take_insensitive)
{
g_return_val_if_fail(group, NULL);
-
- gdouble delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0);
for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
@@ -916,11 +1030,11 @@ 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, Geom::Point const p, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL)
{
SPItem *seen = NULL, *newseen = NULL;
-
- gdouble delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0);
for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
if (!SP_IS_ITEM(o)) continue;
@@ -928,7 +1042,7 @@ find_item_at_point(unsigned int dkey, SPGroup *group, NR::Point const p, bool in
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) {
@@ -958,11 +1072,11 @@ Returns the topmost non-layer group from the descendants of group which is at po
p, or NULL if none. Recurses into layers but not into groups.
*/
SPItem*
-find_group_at_point(unsigned int dkey, SPGroup *group, NR::Point const p)
+find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Point const p)
{
SPItem *seen = NULL;
-
- gdouble delta = prefs_get_double_attribute ("options.cursortolerance", "value", 1.0);
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0);
for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) {
if (!SP_IS_ITEM(o)) continue;
*
*/
-GSList *sp_document_items_in_box(SPDocument *document, unsigned int dkey, NR::Rect const &box)
+GSList *sp_document_items_in_box(SPDocument *document, unsigned int dkey, Geom::Rect const &box)
{
g_return_val_if_fail(document != NULL, NULL);
g_return_val_if_fail(document->priv != NULL, NULL);
@@ -1007,7 +1121,7 @@ GSList *sp_document_items_in_box(SPDocument *document, unsigned int dkey, NR::Re
*
*/
-GSList *sp_document_partial_items_in_box(SPDocument *document, unsigned int dkey, NR::Rect const &box)
+GSList *sp_document_partial_items_in_box(SPDocument *document, unsigned int dkey, Geom::Rect const &box)
{
g_return_val_if_fail(document != NULL, NULL);
g_return_val_if_fail(document->priv != NULL, NULL);
@@ -1015,9 +1129,34 @@ 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<Geom::Point> points)
+{
+ GSList *items = NULL;
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+ // 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->getDouble("/options/cursortolerance/value", 1.0);
+ prefs->setDouble("/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->setDouble("/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)
+sp_document_item_at_point(SPDocument *document, unsigned const key, Geom::Point const p,
+ gboolean const into_groups, SPItem *upto)
{
g_return_val_if_fail(document != NULL, NULL);
g_return_val_if_fail(document->priv != NULL, NULL);
@@ -1026,7 +1165,7 @@ sp_document_item_at_point(SPDocument *document, unsigned const key, NR::Point co
}
SPItem*
-sp_document_group_at_point(SPDocument *document, unsigned int key, NR::Point const p)
+sp_document_group_at_point(SPDocument *document, unsigned int key, Geom::Point const p)
{
g_return_val_if_fail(document != NULL, NULL);
g_return_val_if_fail(document->priv != NULL, NULL);
@@ -1037,7 +1176,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 +1201,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;
/* 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;
return start - newend;
}
+bool SPDocument::isSeeking() const {
+ return priv->seeking;
+}
+
/*
Local Variables: