document-subset.cpp revision c0537dcfe264414d52ad86579d57cb0cb2183dcb
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental/*
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental * Inkscape::DocumentSubset - view of a document including only a subset
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental * of nodes
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental *
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental * Copyright 2006 MenTaLguY <mental@rydia.net>
9dc68827cbd515262ecb8d5ae8547d9e82c72e00Jon A. Cruz * Abhishek Sharma
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental *
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental * Released under GNU GPL, read the file 'COPYING' for more information
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "gc-finalized.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "document-subset.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "document.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "sp-object.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
c0537dcfe264414d52ad86579d57cb0cb2183dcbAlex Valavanis#include <glib.h>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include <sigc++/signal.h>
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental#include <sigc++/functors/mem_fun.h>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "util/list.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include "util/reverse-list.h"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include <vector>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include <map>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include <algorithm>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental#include <iterator>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalnamespace Inkscape {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalstruct DocumentSubset::Relations : public GC::Managed<GC::ATOMIC>,
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental public GC::Finalized
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental{
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental typedef std::vector<SPObject *> Siblings;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental struct Record {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental SPObject *parent;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental sigc::connection release_connection;
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental sigc::connection position_changed_connection;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental Record() : parent(NULL) {}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned childIndex(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings::iterator found;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental found = std::find(children.begin(), children.end(), obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if ( found != children.end() ) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return found - children.begin();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return 0;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned findInsertIndex(SPObject *obj) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (children.empty()) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return 0;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings::const_iterator first=children.begin();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings::const_iterator last=children.end() - 1;
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz while ( first != last ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz Siblings::const_iterator mid = first + ( last - first + 1 ) / 2;
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz int pos = sp_object_compare_position(*mid, obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if ( pos < 0 ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz first = mid;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else if ( pos > 0 ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz if ( last == mid ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz last = mid - 1; // already at the top limit
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz } else {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz last = mid;
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_assert_not_reached();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz }
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz if ( first == last ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz // compare to the single possiblity left
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz int pos = sp_object_compare_position(*last, obj);
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz if ( pos < 0 ) {
33e65aa0bff5323a2f8473f4a7f7a74a97ebf5d6joncruz last++;
0832343fd7f087d3b718bc86f2cf74014e56b582joncruz }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
0832343fd7f087d3b718bc86f2cf74014e56b582joncruz
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return last - children.begin();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void addChild(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned index=findInsertIndex(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental children.insert(children.begin()+index, obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental template <typename OutputIterator>
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void extractDescendants(OutputIterator descendants,
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental SPObject *obj)
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings new_children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental bool found_one=false;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( Siblings::iterator iter=children.begin()
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; iter != children.end() ; iter++ )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (obj->isAncestorOf(*iter)) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (!found_one) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental found_one = true;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental new_children.insert(new_children.end(),
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental children.begin(), iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental *descendants++ = *iter;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else if (found_one) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental new_children.push_back(*iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (found_one) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental children.swap(new_children);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned removeChild(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings::iterator found;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental found = std::find(children.begin(), children.end(), obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned index = found - children.begin();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if ( found != children.end() ) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental children.erase(found);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return index;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental };
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental typedef std::map<SPObject *, Record> Map;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Map records;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental sigc::signal<void> changed_signal;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental sigc::signal<void, SPObject *> added_signal;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental sigc::signal<void, SPObject *> removed_signal;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Relations() { records[NULL]; }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ~Relations() {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( Map::iterator iter=records.begin()
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; iter != records.end() ; ++iter )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
3f4648e535d6fb8388685ff9dd7e1ab111977607buliabyak if ((*iter).first) {
40e40a37efaa1e71332d33d2c85cc017595d6285buliabyak sp_object_unref((*iter).first);
3f4648e535d6fb8388685ff9dd7e1ab111977607buliabyak Record &record=(*iter).second;
3f4648e535d6fb8388685ff9dd7e1ab111977607buliabyak record.release_connection.disconnect();
3f4648e535d6fb8388685ff9dd7e1ab111977607buliabyak record.position_changed_connection.disconnect();
3f4648e535d6fb8388685ff9dd7e1ab111977607buliabyak }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *get(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Map::iterator found=records.find(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if ( found != records.end() ) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return &(*found).second;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return NULL;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void addOne(SPObject *obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void remove(SPObject *obj, bool subtree);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void reorder(SPObject *obj);
8dd159d21f0c89ac2a828814284967fc631ab571mental void clear();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalprivate:
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record &_doAdd(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental sp_object_ref(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record &record=records[obj];
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental record.release_connection
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental = obj->connectRelease(
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental sigc::mem_fun(this, &Relations::_release_object)
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental );
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental record.position_changed_connection
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental = obj->connectPositionChanged(
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental sigc::mem_fun(this, &Relations::reorder)
995ef36b2f4a73356bc05e380e05f1a66c8b2c8amental );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return record;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void _notifyAdded(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental added_signal.emit(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void _doRemove(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record &record=records[obj];
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz if ( record.parent == NULL ) {
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz Record &root = records[NULL];
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz for ( Siblings::iterator it = root.children.begin(); it != root.children.end(); ++it ) {
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz if ( *it == obj ) {
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz root.children.erase( it );
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz break;
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz }
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz }
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz }
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz
a767b323d0447407045ed6ca309f373b1c3eab52Krzysztof Kosiński record.release_connection.disconnect();
a767b323d0447407045ed6ca309f373b1c3eab52Krzysztof Kosiński record.position_changed_connection.disconnect();
a767b323d0447407045ed6ca309f373b1c3eab52Krzysztof Kosiński records.erase(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental removed_signal.emit(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental sp_object_unref(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental void _doRemoveSubtree(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *record=get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (record) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings &children=record->children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( Siblings::iterator iter=children.begin()
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; iter != children.end() ; ++iter )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _doRemoveSubtree(*iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _doRemove(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental void _release_object(SPObject *obj) {
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental if (get(obj)) {
9c0a44bb47b022c4cdb319d697ccd5a42d3253ddmental remove(obj, true);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental};
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
f3823063dfabb21265f42696bacbc66c3ffae606mentalDocumentSubset::DocumentSubset()
f3823063dfabb21265f42696bacbc66c3ffae606mental: _relations(new DocumentSubset::Relations())
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental{
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalvoid DocumentSubset::Relations::addOne(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_return_if_fail( obj != NULL );
8f9fc892f53e932a79afe15bd7039b5578983cb2joncruz g_return_if_fail( get(obj) == NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record &record=_doAdd(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* find the nearest ancestor in the subset */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *parent_record=NULL;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( SPObject::ParentIterator parent_iter=obj->parent
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; !parent_record && parent_iter ; ++parent_iter )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record = get(parent_iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (parent_record) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental record.parent = parent_iter;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (!parent_record) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record = get(NULL);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_assert( parent_record != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings &children=record.children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* reparent descendants of obj to obj */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record->extractDescendants(
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental std::back_insert_iterator<Siblings>(children),
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental obj
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( Siblings::iterator iter=children.begin()
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; iter != children.end() ; ++iter )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *child_record=get(*iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_assert( child_record != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental child_record->parent = obj;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* add obj to the child list */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record->addChild(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _notifyAdded(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental changed_signal.emit();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalvoid DocumentSubset::Relations::remove(SPObject *obj, bool subtree) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_return_if_fail( obj != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *record=get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_return_if_fail( record != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *parent_record=get(record->parent);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_assert( parent_record != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned index=parent_record->removeChild(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (subtree) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _doRemoveSubtree(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* reparent obj's orphaned children to their grandparent */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings &siblings=parent_record->children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings &children=record->children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental siblings.insert(siblings.begin()+index,
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental children.begin(), children.end());
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental for ( Siblings::iterator iter=children.begin()
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental ; iter != children.end() ; iter++ )
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *child_record=get(*iter);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental g_assert( child_record != NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental child_record->parent = record->parent;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* remove obj's record */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _doRemove(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
5192adf272fe17670fa94f6aa15f348b132f98e3Jon A. Cruz
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental changed_signal.emit();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
8dd159d21f0c89ac2a828814284967fc631ab571mentalvoid DocumentSubset::Relations::clear() {
8dd159d21f0c89ac2a828814284967fc631ab571mental Record &root=records[NULL];
8dd159d21f0c89ac2a828814284967fc631ab571mental
8dd159d21f0c89ac2a828814284967fc631ab571mental while (!root.children.empty()) {
8dd159d21f0c89ac2a828814284967fc631ab571mental _doRemoveSubtree(root.children.front());
8dd159d21f0c89ac2a828814284967fc631ab571mental }
8dd159d21f0c89ac2a828814284967fc631ab571mental
8dd159d21f0c89ac2a828814284967fc631ab571mental changed_signal.emit();
8dd159d21f0c89ac2a828814284967fc631ab571mental}
8dd159d21f0c89ac2a828814284967fc631ab571mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalvoid DocumentSubset::Relations::reorder(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental SPObject::ParentIterator parent=obj;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* find nearest ancestor in the subset */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Record *parent_record=NULL;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental while (!parent_record) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record = get(++parent);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (get(obj)) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* move the object if it's in the subset */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record->removeChild(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record->addChild(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental changed_signal.emit();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental } else {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental /* otherwise, move any top-level descendants */
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings descendants;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental parent_record->extractDescendants(
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental std::back_insert_iterator<Siblings>(descendants),
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental obj
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental if (!descendants.empty()) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental unsigned index=parent_record->findInsertIndex(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Siblings &family=parent_record->children;
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental family.insert(family.begin()+index,
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental descendants.begin(), descendants.end());
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental changed_signal.emit();
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental }
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalvoid DocumentSubset::_addOne(SPObject *obj) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _relations->addOne(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalvoid DocumentSubset::_remove(SPObject *obj, bool subtree) {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental _relations->remove(obj, subtree);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
8dd159d21f0c89ac2a828814284967fc631ab571mentalvoid DocumentSubset::_clear() {
8dd159d21f0c89ac2a828814284967fc631ab571mental _relations->clear();
8dd159d21f0c89ac2a828814284967fc631ab571mental}
8dd159d21f0c89ac2a828814284967fc631ab571mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalbool DocumentSubset::includes(SPObject *obj) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return _relations->get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalSPObject *DocumentSubset::parentOf(SPObject *obj) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Relations::Record *record=_relations->get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return ( record ? record->parent : NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalunsigned DocumentSubset::childCount(SPObject *obj) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Relations::Record *record=_relations->get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return ( record ? record->children.size() : 0 );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalunsigned DocumentSubset::indexOf(SPObject *obj) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental SPObject *parent=parentOf(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Relations::Record *record=_relations->get(parent);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return ( record ? record->childIndex(obj) : 0 );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalSPObject *DocumentSubset::nthChildOf(SPObject *obj, unsigned n) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Relations::Record *record=_relations->get(obj);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return ( record ? record->children[n] : NULL );
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalsigc::connection DocumentSubset::connectChanged(sigc::slot<void> slot) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return _relations->changed_signal.connect(slot);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalsigc::connection
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalDocumentSubset::connectAdded(sigc::slot<void, SPObject *> slot) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return _relations->added_signal.connect(slot);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalsigc::connection
a8f1a69ef0da383f9b413c3043a74084e23b75c2mentalDocumentSubset::connectRemoved(sigc::slot<void, SPObject *> slot) const {
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental return _relations->removed_signal.connect(slot);
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental}
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental/*
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental Local Variables:
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental mode:c++
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental c-file-style:"stroustrup"
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental indent-tabs-mode:nil
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental fill-column:99
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental End:
a8f1a69ef0da383f9b413c3043a74084e23b75c2mental*/
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :