~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/xml/node.h

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Node - interface for XML nodes
 
1
/** @file
 
2
 * @brief Interface for XML nodes
 
3
 */
 
4
/* Authors:
 
5
 *   MenTaLguY <mental@rydia.net>
 
6
 *   Krzysztof Kosiński <tweenk.pl@gmail.com> (documentation)
3
7
 *
4
 
 * Copyright 2005 MenTaLguY <mental@rydia.net>
 
8
 * Copyright 2005-2008 Authors
5
9
 *
6
10
 * This program is free software; you can redistribute it and/or
7
11
 * modify it under the terms of the GNU General Public License
9
13
 * of the License, or (at your option) any later version.
10
14
 *
11
15
 * See the file COPYING for details.
12
 
 *
13
16
 */
14
17
 
15
18
#ifndef SEEN_INKSCAPE_XML_NODE_H
18
21
#include <glib/gtypes.h>
19
22
#include "gc-anchored.h"
20
23
#include "util/list.h"
 
24
#include "xml/xml-forward.h"
21
25
 
22
26
namespace Inkscape {
23
27
namespace XML {
24
28
 
25
 
class AttributeRecord;
26
 
class Document;
27
 
class NodeEventVector;
28
 
class NodeObserver;
29
 
 
 
29
/**
 
30
 * @brief Enumeration containing all supported node types.
 
31
 */
30
32
enum NodeType {
31
 
    DOCUMENT_NODE,
32
 
    ELEMENT_NODE,
33
 
    TEXT_NODE,
34
 
    COMMENT_NODE
 
33
    DOCUMENT_NODE, ///< Top-level document node. Do not confuse with the root node.
 
34
    ELEMENT_NODE, ///< Regular element node, e.g. &lt;group /&gt;.
 
35
    TEXT_NODE, ///< Text node, e.g. "Some text" in &lt;group&gt;Some text&lt;/group&gt; is represented by a text node.
 
36
    COMMENT_NODE, ///< Comment node, e.g. &lt;!-- some comment --&gt;
 
37
    PI_NODE ///< Processing instruction node, e.g. &lt;?xml version="1.0" encoding="utf-8" standalone="no"?&gt;
35
38
};
36
39
 
37
40
// careful; GC::Anchored should only appear once in the inheritance
38
 
// hierarcy; else there will be leaks
 
41
// hierarchy; otherwise there will be leaks
 
42
 
 
43
/**
 
44
 * @brief Interface for refcounted XML nodes
 
45
 *
 
46
 * This class is an abstract base type for all nodes in an XML document - this includes
 
47
 * everything except attributes. An XML document is also a node itself. This is the main
 
48
 * class used for interfacing with Inkscape's documents. Everything that has to be stored
 
49
 * in the SVG has to go through this class at some point.
 
50
 *
 
51
 * Each node unconditionally has to belong to a document. There no "documentless" nodes,
 
52
 * and it's not possible to move nodes between documents - they have to be duplicated.
 
53
 * Each node can only refer to the nodes in the same document. Name of the node is immutable,
 
54
 * it cannot be changed after its creation. Same goes for the type of the node. To simplify
 
55
 * the use of this class, you can perform all operations on all nodes, but only some of them
 
56
 * make any sense. For example, only element nodes can have attributes, only element and
 
57
 * document nodes can have children, and all nodes except element and document nodes can
 
58
 * have content. Although you can set content for element nodes, it won't make any difference
 
59
 * in the XML output.
 
60
 *
 
61
 * To create new nodes, use the methods of the Inkscape::XML::Document class. You can obtain
 
62
 * the nodes' document using the document() method. To destroy a node, just unparent it
 
63
 * by calling sp_repr_unparent() or node->parent->removeChild() and release any references
 
64
 * to it. The garbage collector will reclaim the memory in the next pass. There are additional
 
65
 * convenience functions defined in @ref xml/repr.h
 
66
 *
 
67
 * In addition to regular DOM manipulations, you can register observer objects that will
 
68
 * receive notifications about changes made to the node. See the NodeObserver class.
 
69
 *
 
70
 * @see Inkscape::XML::Document
 
71
 * @see Inkscape::XML::NodeObserver
 
72
 */
39
73
class Node : public Inkscape::GC::Anchored {
40
74
public:
41
75
    Node() {}
42
 
    
43
76
    virtual ~Node() {}
44
77
 
 
78
    /**
 
79
     * @name Retrieve information about the node
 
80
     * @{
 
81
     */
 
82
 
 
83
    /**
 
84
     * @brief Get the type of the node
 
85
     * @return NodeType enumeration member corresponding to the type of the node.
 
86
     */
45
87
    virtual NodeType type() const=0;
46
88
 
 
89
    /**
 
90
     * @brief Get the name of the element node
 
91
     *
 
92
     * This method only makes sense for element nodes. Names are stored as
 
93
     * GQuarks to accelerate conversions.
 
94
     *
 
95
     * @return Name for element nodes, NULL for others
 
96
     */
47
97
    virtual gchar const *name() const=0;
 
98
    /**
 
99
     * @brief Get the integer code corresponding to the node's name
 
100
     * @return GQuark code corresponding to the name
 
101
     */
48
102
    virtual int code() const=0;
 
103
    
 
104
    /**
 
105
     * @brief Get the index of this node in parent's child order
 
106
     *
 
107
     * If this method is used on a node that doesn't have a parent, the method will return 0,
 
108
     * and a warning will be printed on the console.
 
109
     *
 
110
     * @return The node's index, or 0 if the node does not have a parent
 
111
     */
 
112
    virtual unsigned position() const=0;
 
113
 
 
114
    /**
 
115
     * @brief Get the number of children of this node
 
116
     * @return The number of children
 
117
     */
 
118
    virtual unsigned childCount() const=0;
 
119
    
 
120
    /**
 
121
     * @brief Get the content of a text or comment node
 
122
     *
 
123
     * This method makes no sense for element nodes. To retrieve the element node's name,
 
124
     * use the name() method.
 
125
     *
 
126
     * @return The node's content
 
127
     */
 
128
    virtual gchar const *content() const=0;
 
129
    
 
130
    /**
 
131
     * @brief Get the string representation of a node's attribute
 
132
     *
 
133
     * If there is no attribute with the given name, the method will return NULL.
 
134
     * All strings returned by this method are owned by the node and may not be freed.
 
135
     * The returned pointer will become invalid when the attribute changes. If you need
 
136
     * to store the return value, use g_strdup(). To parse the string, use methods
 
137
     * in repr.h
 
138
     *
 
139
     * @param key The name of the node's attribute
 
140
     */
 
141
    virtual gchar const *attribute(gchar const *key) const=0;
 
142
    
 
143
    /**
 
144
     * @brief Get a list of the node's attributes
 
145
     *
 
146
     * The returned list is a functional programming style list rather than a standard one.
 
147
     *
 
148
     * @return A list of AttributeRecord structures describing the attributes
 
149
     * @todo This method should return std::map<Glib::Quark const, gchar const *>
 
150
     *       or something similar with a custom allocator
 
151
     */
 
152
    virtual Inkscape::Util::List<AttributeRecord const> attributeList() const=0;
 
153
 
 
154
    /**
 
155
     * @brief Check whether this node has any attribute that matches a string
 
156
     *
 
157
     * This method checks whether this node has any attributes whose names
 
158
     * have @c partial_name as their substrings. The check is done using
 
159
     * the strstr() function of the C library. I don't know what would require that
 
160
     * functionality, because matchAttributeName("id") matches both "identity" and "hidden".
 
161
     *
 
162
     * @param partial_name The string to match against all attributes
 
163
     * @return true if there is such an attribute, false otherwise
 
164
     */
 
165
    virtual bool matchAttributeName(gchar const *partial_name) const=0;
 
166
 
 
167
    /*@}*/
 
168
    
 
169
    /**
 
170
     * @name Modify the node
 
171
     * @{
 
172
     */
 
173
    
 
174
    /**
 
175
     * @brief Set the position of this node in parent's child order
 
176
     *
 
177
     * To move the node to the end of the parent's child order, pass a negative argument.
 
178
     *
 
179
     * @param pos The new position in parent's child order
 
180
     */
 
181
    virtual void setPosition(int pos)=0;
 
182
    
 
183
    /**
 
184
     * @brief Set the content of a text or comment node
 
185
     *
 
186
     * This method doesn't make sense for element nodes.
 
187
     *
 
188
     * @param value The node's new content
 
189
     */
 
190
    virtual void setContent(gchar const *value)=0;
 
191
    
 
192
    /**
 
193
     * @brief Change an attribute of this node
 
194
     *
 
195
     * The strings passed to this method are copied, so you can free them after use.
 
196
     *
 
197
     * @param key Name of the attribute to change
 
198
     * @param value The new value of the attribute
 
199
     * @param is_interactive Ignored
 
200
     */
 
201
    virtual void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false)=0;
 
202
    
 
203
    /**
 
204
     * @brief Directly set the integer GQuark code for the name of the node
 
205
     *
 
206
     * This function is a hack to easily move elements with no namespace to the SVG namespace.
 
207
     * Do not use this function unless you really have a good reason.
 
208
     *
 
209
     * @param code The integer value corresponding to the string to be set as the name of this node
 
210
     */
49
211
    virtual void setCodeUnsafe(int code)=0;
 
212
    
 
213
    /*@}*/
50
214
 
 
215
    
 
216
    /**
 
217
     * @name Traverse the XML tree
 
218
     * @{
 
219
     */
 
220
     
 
221
    //@{
 
222
    /**
 
223
     * @brief Get the node's associated document
 
224
     * @return The document to which the node belongs. Never NULL.
 
225
     */
51
226
    virtual Document *document()=0;
52
227
    virtual Document const *document() const=0;
53
 
 
54
 
    virtual Node *duplicate(Document *doc) const=0;
55
 
 
 
228
    //@}
 
229
 
 
230
    //@{
 
231
    /**
 
232
     * @brief Get the root node of this node's document
 
233
     *
 
234
     * This method works on any node that is part of an XML document, and returns
 
235
     * the root node of the document in which it resides. For detached node hierarchies
 
236
     * (i.e. nodes that are not descendants of a document node) this method
 
237
     * returns the highest-level element node. For detached non-element nodes this method
 
238
     * returns NULL.
 
239
     *
 
240
     * @return A pointer to the root element node, or NULL if the node is detached
 
241
     */
56
242
    virtual Node *root()=0;
57
243
    virtual Node const *root() const=0;
 
244
    //@}
58
245
 
 
246
    //@{
 
247
    /**
 
248
     * @brief Get the parent of this node
 
249
     *
 
250
     * This method will return NULL for detached nodes.
 
251
     *
 
252
     * @return Pointer to the parent, or NULL
 
253
     */
59
254
    virtual Node *parent()=0;
60
255
    virtual Node const *parent() const=0;
 
256
    //@}
61
257
 
 
258
    //@{
 
259
    /**
 
260
     * @brief Get the next sibling of this node
 
261
     *
 
262
     * This method will return NULL if the node is the last sibling element of the parent.
 
263
     * The nodes form a singly-linked list, so there is no "prev()" method. Use the provided
 
264
     * external function for that.
 
265
     *
 
266
     * @return Pointer to the next sibling, or NULL
 
267
     * @see Inkscape::XML::previous_node()
 
268
     */
62
269
    virtual Node *next()=0;
63
270
    virtual Node const *next() const=0;
 
271
    //@}
64
272
 
 
273
    //@{
 
274
    /**
 
275
     * @brief Get the first child of this node
 
276
     *
 
277
     * For nodes without any children, this method returns NULL.
 
278
     *
 
279
     * @return Pointer to the first child, or NULL
 
280
     */
65
281
    virtual Node *firstChild()=0;
66
282
    virtual Node const *firstChild() const=0;
 
283
    //@}
 
284
    
 
285
    //@{
 
286
    /**
 
287
     * @brief Get the last child of this node
 
288
     *
 
289
     * For nodes without any children, this method returns NULL.
 
290
     *
 
291
     * @return Pointer to the last child, or NULL
 
292
     */
67
293
    virtual Node *lastChild()=0;
68
294
    virtual Node const *lastChild() const=0;
69
 
 
70
 
    virtual unsigned childCount() const=0;
 
295
    //@}
 
296
    
 
297
    //@{
 
298
    /**
 
299
     * @brief Get the child of this node with a given index
 
300
     *
 
301
     * If there is no child with the specified index number, this method will return NULL.
 
302
     *
 
303
     * @param index The zero-based index of the child to retrieve
 
304
     * @return Pointer to the appropriate child, or NULL
 
305
     */
71
306
    virtual Node *nthChild(unsigned index)=0;
72
307
    virtual Node const *nthChild(unsigned index) const=0;
73
 
 
74
 
    virtual void addChild(Node *child, Node *ref)=0;
 
308
    //@}
 
309
    
 
310
    /*@}*/
 
311
    
 
312
    /**
 
313
     * @name Manipulate the XML tree
 
314
     * @{
 
315
     */
 
316
 
 
317
    /**
 
318
     * @brief Create a duplicate of this node
 
319
     *
 
320
     * The newly created node has no parent, and a refcount equal 1.
 
321
     * You need to manually insert it into the document, using e.g. appendChild().
 
322
     * Afterwards, call Inkscape::GC::release on it, so that it will be
 
323
     * automatically collected when the parent is collected.
 
324
     *
 
325
     * @param doc The document in which the duplicate should be created
 
326
     * @return A pointer to the duplicated node
 
327
     */
 
328
    virtual Node *duplicate(Document *doc) const=0;
 
329
 
 
330
    /**
 
331
     * @brief Insert another node as a child of this node
 
332
     *
 
333
     * When @c after is NULL, the inserted node will be placed as the first child
 
334
     * of this node. @c after must be a child of this node.
 
335
     *
 
336
     * @param child The node to insert
 
337
     * @param after The node after which the inserted node should be placed, or NULL
 
338
     */
 
339
    virtual void addChild(Node *child, Node *after)=0;
 
340
    
 
341
    /**
 
342
     * @brief Append a node as the last child of this node
 
343
     * @param child The node to append
 
344
     */
75
345
    virtual void appendChild(Node *child)=0;
 
346
    
 
347
    /**
 
348
     * @brief Remove a child of this node
 
349
     *
 
350
     * Once the pointer to the removed node disappears from the stack, the removed node
 
351
     * will be collected in the next GC pass, but only as long as its refcount is zero.
 
352
     * You should keep a refcount of zero for all nodes in the document except for
 
353
     * the document node itself, because they will be held in memory by the parent.
 
354
     *
 
355
     * @param child The child to remove
 
356
     */
76
357
    virtual void removeChild(Node *child)=0;
77
 
    virtual void changeOrder(Node *child, Node *ref)=0;
78
 
 
79
 
    virtual unsigned position() const=0;
80
 
    virtual void setPosition(int pos)=0;
81
 
 
82
 
    virtual gchar const *attribute(gchar const *key) const=0;
83
 
    virtual void setAttribute(gchar const *key, gchar const *value, bool is_interactive=false)=0;
84
 
    virtual bool matchAttributeName(gchar const *partial_name) const=0;
85
 
 
86
 
    virtual gchar const *content() const=0;
87
 
    virtual void setContent(gchar const *value)=0;
88
 
 
 
358
    
 
359
    /**
 
360
     * @brief Move a given node in this node's child order
 
361
     *
 
362
     * Both @c child and @c after must be children of this node for the method to work.
 
363
     *
 
364
     * @param child The node to move in the order
 
365
     * @param after The sibling node after which the moved node should be placed
 
366
     */
 
367
    virtual void changeOrder(Node *child, Node *after)=0;
 
368
 
 
369
    /**
 
370
     * @brief Merge all children of another node with the current
 
371
     *
 
372
     * This method merges two node hierarchies, where @c src takes precedence.
 
373
     * @c key is the name of the attribute that determines whether two nodes are
 
374
     * corresponding (it must be the same for both, and all of their ancestors). If there is
 
375
     * a corresponding node in @c src hierarchy, their attributes and content override the ones
 
376
     * already present in this node's hierarchy. If there is no corresponding node,
 
377
     * it is copied from @c src to this node. This method is used when merging the user's
 
378
     * preferences file with the defaults, and has little use beyond that.
 
379
     *
 
380
     * @param src The node to merge into this node
 
381
     * @param key The attribute to use as the identity attribute
 
382
     */
89
383
    virtual void mergeFrom(Node const *src, gchar const *key)=0;
90
 
 
91
 
    virtual Inkscape::Util::List<AttributeRecord const> attributeList() const=0;
92
 
 
93
 
    virtual void synthesizeEvents(NodeEventVector const *vector, void *data)=0;
94
 
    virtual void synthesizeEvents(NodeObserver &observer)=0;
 
384
    
 
385
    /*@}*/
 
386
 
 
387
 
 
388
    /**
 
389
     * @name Notify observers about operations on the node
 
390
     * @{
 
391
     */
 
392
 
 
393
    /**
 
394
     * @brief Add an object that will be notified of the changes to this node
 
395
     *
 
396
     * @c observer must be an object deriving from the NodeObserver class.
 
397
     * The virtual methods of this object will be called when a corresponding change
 
398
     * happens to this node. You can also notify the observer of the node's current state
 
399
     * using synthesizeEvents(NodeObserver &).
 
400
     *
 
401
     * @param observer The observer object
 
402
     */
95
403
    virtual void addObserver(NodeObserver &observer)=0;
96
 
    virtual void addListener(NodeEventVector const *vector, void *data)=0;
 
404
    /**
 
405
     * @brief Remove an object from the list of observers
 
406
     * @param observer The object to be removed
 
407
     */
97
408
    virtual void removeObserver(NodeObserver &observer)=0;
98
 
    virtual void removeListenerByData(void *data)=0;
 
409
    /**
 
410
     * @brief Generate a sequence of events corresponding to the state of this node
 
411
     *
 
412
     * This function notifies the specified observer of all the events that would
 
413
     * recreate the current state of this node; e.g. the observer is notified of
 
414
     * all the attributes, children and content like they were just created.
 
415
     * This function can greatly simplify observer logic.
 
416
     *
 
417
     * @param observer The node observer to notify of the events
 
418
     */
 
419
    virtual void synthesizeEvents(NodeObserver &observer)=0;
99
420
 
 
421
    /**
 
422
     * @brief Add an object that will be notified of the changes to this node and its descendants
 
423
     *
 
424
     * The difference between adding a regular observer and a subtree observer is that
 
425
     * the subtree observer will also be notified if a change occurs to any of the node's
 
426
     * descendants, while a regular observer will only be notified of changes to the node
 
427
     * it was assigned to.
 
428
     *
 
429
     * @param observer The observer object
 
430
     */
100
431
    virtual void addSubtreeObserver(NodeObserver &observer)=0;
 
432
    
 
433
    /**
 
434
     * @brief Remove an object from the subtree observers list
 
435
     * @param observer The object to be removed
 
436
     */
101
437
    virtual void removeSubtreeObserver(NodeObserver &observer)=0;
102
438
 
 
439
    /**
 
440
     * @brief Add a set node change callbacks with an associated data
 
441
     * @deprecated Use addObserver(NodeObserver &) instead
 
442
     */
 
443
    virtual void addListener(NodeEventVector const *vector, void *data)=0;
 
444
    /**
 
445
     * @brief Remove a set of node change callbacks by their associated data
 
446
     * @deprecated Use removeObserver(NodeObserver &) instead
 
447
     */
 
448
    virtual void removeListenerByData(void *data)=0;
 
449
    /**
 
450
     * @brief Generate a sequence of events corresponding to the state of this node
 
451
     * @deprecated Use synthesizeEvents(NodeObserver &) instead
 
452
     */
 
453
    virtual void synthesizeEvents(NodeEventVector const *vector, void *data)=0;
 
454
    
 
455
    /*@}*/
 
456
 
103
457
protected:
104
458
    Node(Node const &) : Anchored() {}
105
 
 
106
 
public: // ideally these should be protected too somehow...
107
 
    virtual NodeObserver &_subtreeObservers()=0;
108
 
    virtual void _setParent(Node *parent)=0;
109
 
    virtual void _setNext(Node *next)=0;
110
 
    virtual void _bindDocument(Document &document)=0;
111
 
 
112
 
    virtual unsigned _childPosition(Node const &child) const=0;
113
 
    virtual unsigned _cachedPosition() const=0;
114
 
    virtual void _setCachedPosition(unsigned position) const=0;
115
459
};
116
460
 
117
461
}