summaryrefslogtreecommitdiffstats
path: root/src/object-set.cpp
diff options
context:
space:
mode:
authorAdrian Boguszewski <adrbogus1@student.pg.gda.pl>2016-06-05 21:20:55 +0000
committerAdrian Boguszewski <adrbogus1@student.pg.gda.pl>2016-06-05 21:20:55 +0000
commit9abb5e658d005b3ac82afeec13fd59384a8e65eb (patch)
treea6bdcceacd73ff829dd54d891ac7dc3cf70273ee /src/object-set.cpp
parent[Bug #1545333] Convenience option (default: ON) for cmake builds to enable SV... (diff)
downloadinkscape-9abb5e658d005b3ac82afeec13fd59384a8e65eb.tar.gz
inkscape-9abb5e658d005b3ac82afeec13fd59384a8e65eb.zip
Added object set
(bzr r14954.1.1)
Diffstat (limited to '')
-rw-r--r--src/object-set.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/object-set.cpp b/src/object-set.cpp
new file mode 100644
index 000000000..f071aa4d6
--- /dev/null
+++ b/src/object-set.cpp
@@ -0,0 +1,133 @@
+/*
+ * Multiindex container for selection
+ *
+ * Authors:
+ * Adrian Boguszewski
+ *
+ * Copyright (C) 2016 Adrian Boguszewski
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "object-set.h"
+
+bool ObjectSet::add(Object* object) {
+ // any ancestor is in the set - do nothing
+ if (_anyAncestorIsInSet(object)) {
+ return false;
+ }
+
+ // check if there is mutual ancestor for some elements, which can replace all of them in the set
+ Object* o = _getMutualAncestor(object);
+
+ // remove all descendants from the set
+ _removeDescendantsFromSet(o);
+
+ _add(o);
+ return true;
+}
+
+bool ObjectSet::remove(Object* object) {
+ // object is the top of subtree
+ if (contains(object)) {
+ _remove(object);
+ return true;
+ }
+
+ // any ancestor of object is in the set
+ if (_anyAncestorIsInSet(object)) {
+ _removeAncestorsFromSet(object);
+ return true;
+ }
+
+ // no object nor any parent in the set
+ return false;
+}
+
+bool ObjectSet::contains(Object* object) {
+ return container.get<hashed>().find(object) != container.get<hashed>().end();
+}
+
+void ObjectSet::clear() {
+ for (auto object: container) {
+ _remove(object);
+ }
+}
+
+int ObjectSet::size() {
+ return container.size();
+}
+
+bool ObjectSet::_anyAncestorIsInSet(Object *object) {
+ Object* o = object;
+ while (o != nullptr) {
+ if (contains(o)) {
+ return true;
+ }
+ o = o->getParent();
+ }
+
+ return false;
+}
+
+void ObjectSet::_removeDescendantsFromSet(Object *object) {
+ for (auto& child: object->getChildren()) {
+ if (contains(&child)) {
+ _remove(&child);
+ // there is certainly no children of this child in the set
+ continue;
+ }
+
+ _removeDescendantsFromSet(&child);
+ }
+}
+
+void ObjectSet::_remove(Object *object) {
+ releaseConnections[object].disconnect();
+ releaseConnections.erase(object);
+ container.get<hashed>().erase(object);
+}
+
+void ObjectSet::_add(Object *object) {
+ releaseConnections[object] = object->connectRelease(sigc::mem_fun(*this, &ObjectSet::remove));
+ container.push_back(object);
+}
+
+Object *ObjectSet::_getMutualAncestor(Object *object) {
+ Object *o = object;
+
+ bool flag = true;
+ while (o->getParent() != nullptr) {
+ for (auto &child: o->getParent()->getChildren()) {
+ if(&child != o && !contains(&child)) {
+ flag = false;
+ break;
+ }
+ }
+ if (!flag) {
+ break;
+ }
+ o = o->getParent();
+ }
+ return o;
+}
+
+void ObjectSet::_removeAncestorsFromSet(Object *object) {
+ Object* o = object;
+ while (o->getParent() != nullptr) {
+ for (auto &child: o->getParent()->getChildren()) {
+ if (&child != o) {
+ _add(&child);
+ }
+ }
+ if (contains(o->getParent())) {
+ _remove(o->getParent());
+ break;
+ }
+ o = o->getParent();
+ }
+}
+
+ObjectSet::~ObjectSet() {
+ clear();
+}