summaryrefslogtreecommitdiffstats
path: root/src/xml/node-observer.h
blob: e3173a8463f382d7148fe9be24a3fc0c4ccdaee1 (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
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// SPDX-License-Identifier: GPL-2.0-or-later
/** @file
 * @brief Interface for XML node observers
 *//*
 * Authors:
 *   MenTaLguY <mental@rydia.net>
 *   Krzysztof Kosiński <tweenk.pl@gmail.com> (documentation)
 * 
 * Copyright (C) 2018 Authors
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */
/** @file
 */

#ifndef SEEN_INKSCAPE_XML_NODE_OBSERVER_H
#define SEEN_INKSCAPE_XML_NODE_OBSERVER_H

#include "util/share.h"
typedef unsigned int GQuark;

#ifndef INK_UNUSED
#define INK_UNUSED(x) ((void)(x))
#endif // INK_UNUSED

namespace Inkscape {
namespace XML {

class Node;

/**
 * @brief Interface for XML node observers
 *
 * This class defines an interface for objects that can receive
 * XML node state change notifications. The observer has to be registered using
 * the Node::addObserver() method to be notified of changes of this node only,
 * or using Node::addSubtreeObserver() to also receive notifications about its
 * descendants. All observer methods are called when the operations in question have
 * been completed, just before returning from the modifying methods.
 *
 * Be careful when e.g. changing an attribute of @c node in notifyAttributeChanged().
 * The method will be called again due to the XML modification performed in it. If you
 * don't take special precautions to ignore the second call, it will result in infinite
 * recursion.
 *
 * The virtual methods of this class do nothing by default, so you don't need to provide
 * stubs for things you don't use. A good idea is to make the observer register itself
 * on construction and unregister itself on destruction. This will ensure there are
 * no dangling references.
 */
class NodeObserver {
protected:
    /* the constructor is protected to prevent instantiation */
    NodeObserver() = default;
public:
    virtual ~NodeObserver() = default;

    // FIXME: somebody needs to learn what "pure virtual" means

    /**
     * @brief Child addition callback
     *
     * This method is called whenever a child is added to the observed node. The @c prev
     * parameter is NULL when the newly added child is first in the sibling order.
     *
     * @param node The changed XML node
     * @param child The newly added child node
     * @param prev The node after which the new child was inserted into the sibling order, or NULL
     */
    virtual void notifyChildAdded(Node &node, Node &child, Node *prev) {
        INK_UNUSED(node);
        INK_UNUSED(child);
        INK_UNUSED(prev);
    }

    /**
     * @brief Child removal callback
     *
     * This method is called whenever a child is removed from the observed node. The @c prev
     * parameter is NULL when the removed child was first in the sibling order.
     *
     * @param node The changed XML node
     * @param child The removed child node
     * @param prev The node that was before the removed node in sibling order, or NULL
     */
    virtual void notifyChildRemoved(Node &node, Node &child, Node *prev) {
        INK_UNUSED(node);
        INK_UNUSED(child);
        INK_UNUSED(prev);
    }

    /**
     * @brief Child order change callback
     *
     * This method is called whenever the order of a node's children is changed using
     * Node::changeOrder(). The @c old_prev parameter is NULL if the relocated node
     * was first in the sibling order before the order change, and @c new_prev is NULL
     * if it was moved to the first position by this operation.
     *
     * @param node The changed XML node
     * @param child The child node that was relocated in the sibling order
     * @param old_prev The node that was before @c child prior to the order change
     * @param new_prev The node that is before @c child after the order change
     */
    virtual void notifyChildOrderChanged(Node &node, Node &child,
                                         Node *old_prev, Node *new_prev) {
        INK_UNUSED(node);
        INK_UNUSED(child);
        INK_UNUSED(old_prev);
        INK_UNUSED(new_prev);
    }

    /**
     * @brief Content change callback
     *
     * This method is called whenever a node's content is changed using Node::setContent(),
     * e.g. for text or comment nodes.
     *
     * @param node The changed XML node
     * @param old_content Old content of @c node
     * @param new_content New content of @c node
     */
    virtual void notifyContentChanged(Node &node,
                                      Util::ptr_shared old_content,
                                      Util::ptr_shared new_content) {
        INK_UNUSED(node);
        INK_UNUSED(old_content);
        INK_UNUSED(new_content);
    }

    /**
     * @brief Attribute change callback
     *
     * This method is called whenever one of a node's attributes is changed.
     *
     * @param node The changed XML node
     * @param name GQuark corresponding to the attribute's name
     * @param old_value Old value of the modified attribute
     * @param new_value New value of the modified attribute
     */
    virtual void notifyAttributeChanged(Node &node, GQuark name,
                                        Util::ptr_shared old_value,
                                        Util::ptr_shared new_value) {
        INK_UNUSED(node);
        INK_UNUSED(name);
        INK_UNUSED(old_value);
        INK_UNUSED(new_value);
    }

    /**
     * @brief Element name change callback.
     *
     * This method is called whenever an element node's name is changed.
     *
     * @param node The changed XML node.
     * @param old_name GQuark corresponding to the old element name.
     * @param new_name GQuark corresponding to the new element name.
     */
    virtual void notifyElementNameChanged(Node& node, GQuark old_name, GQuark new_name) {
        INK_UNUSED(node);
        INK_UNUSED(old_name);
        INK_UNUSED(new_name);
    }

};

} // namespace XML
} // namespace Inkscape

#endif
/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :