summaryrefslogtreecommitdiffstats
path: root/src/object-set.cpp
blob: f071aa4d6f092ef2785214914186d6a506a6fbaa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
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();
}