Code

bulk trailing spaces removal. consistency through MD5 of binary
[inkscape.git] / src / layer-fns.cpp
1 /*
2  * Inkscape::SelectionDescriber - shows messages describing selection
3  *
4  * Authors:
5  *   MenTaLguY <mental@rydia.net>
6  *
7  * Copyright (C) 2004 MenTaLguY
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include "document.h"
17 #include "sp-item-group.h"
18 #include "xml/repr.h"
19 #include "algorithms/find-last-if.h"
21 namespace Inkscape {
23 /**
24  *  Creates a new layer.  Advances to the next layer id indicated
25  *  by the string "layerNN", then creates a new group object of
26  *  that id with attribute inkscape:groupmode='layer', and finally
27  *  appends the new group object to \a root after object \a layer.
28  *
29  *  \pre \a root should be either \a layer or an ancestor of it
30  */
31 SPObject *create_layer(SPObject *root, SPObject *layer) {
32     SPDocument *document=SP_OBJECT_DOCUMENT(root);
34     static int layer_suffix=1;
35     gchar *id=NULL;
36     do {
37         g_free(id);
38         id = g_strdup_printf("layer%d", layer_suffix++);
39     } while (document->getObjectById(id));
41     Inkscape::XML::Node *repr=sp_repr_new("svg:g");
42     repr->setAttribute("inkscape:groupmode", "layer");
43     repr->setAttribute("id", id);
44     g_free(id);
46     if ( root == layer ) {
47         SP_OBJECT_REPR(root)->appendChild(repr);
48     } else {
49         Inkscape::XML::Node *layer_repr=SP_OBJECT_REPR(layer);
50         sp_repr_parent(layer_repr)->addChild(repr, layer_repr);
51     }
53     return document->getObjectByRepr(repr);
54 }
56 namespace {
58 bool is_layer(SPObject &object) {
59     return SP_IS_GROUP(&object) &&
60            SP_GROUP(&object)->layerMode() == SPGroup::LAYER;
61 }
63 SPObject *next_sibling_layer(SPObject *layer) {
64     using std::find_if;
66     return find_if<SPObject::SiblingIterator>(
67         SP_OBJECT_NEXT(layer), NULL, &is_layer
68     );
69 }
71 SPObject *previous_sibling_layer(SPObject *layer) {
72     using Inkscape::Algorithms::find_last_if;
74     SPObject *sibling(find_last_if<SPObject::SiblingIterator>(
75         SP_OBJECT_PARENT(layer)->firstChild(), layer, &is_layer
76     ));
78     return ( sibling != layer ) ? sibling : NULL;
79 }
81 SPObject *first_descendant_layer(SPObject *layer) {
82     using std::find_if;
84     SPObject *first_descendant=NULL;
85     while (layer) {
86         layer = find_if<SPObject::SiblingIterator>(
87             layer->firstChild(), NULL, &is_layer
88         );
89         if (layer) {
90             first_descendant = layer;
91         }
92     }
94     return first_descendant;
95 }
97 SPObject *last_child_layer(SPObject *layer) {
98     using Inkscape::Algorithms::find_last_if;
100     return find_last_if<SPObject::SiblingIterator>(
101         layer->firstChild(), NULL, &is_layer
102     );
105 SPObject *last_elder_layer(SPObject *root, SPObject *layer) {
106     using Inkscape::Algorithms::find_last_if;
108     while ( layer != root ) {
109         SPObject *sibling(previous_sibling_layer(layer));
110         if (sibling) {
111             return sibling;
112         }
113         layer = SP_OBJECT_PARENT(layer);
114     }
116     return NULL;
121 /** Finds the next layer under \a root, relative to \a layer in
122  *  depth-first order.
123  *
124  *  @returns NULL if there are no further layers under \a root
125  */
126 SPObject *next_layer(SPObject *root, SPObject *layer) {
127     using std::find_if;
129     g_return_val_if_fail(layer != NULL, NULL);
131     SPObject *sibling(next_sibling_layer(layer));
132     if (sibling) {
133         SPObject *descendant(first_descendant_layer(sibling));
134         if (descendant) {
135             return descendant;
136         } else {
137             return sibling;
138         }
139     } else {
140         SPObject *parent=SP_OBJECT_PARENT(layer);
141         if ( parent != root ) {
142             return parent;
143         } else {
144             return NULL;
145         }
146     }
150 /** Finds the previous layer under \a root, relative to \a layer in
151  *  depth-first order.
152  *
153  *  @returns NULL if there are no prior layers under \a root.
154  */
155 SPObject *previous_layer(SPObject *root, SPObject *layer) {
156     using Inkscape::Algorithms::find_last_if;
158     g_return_val_if_fail(layer != NULL, NULL);
160     SPObject *child(last_child_layer(layer));
161     if (child) {
162         return child;
163     } else if ( layer != root ) {
164         SPObject *sibling(previous_sibling_layer(layer));
165         if (sibling) {
166             return sibling;
167         } else {
168             return last_elder_layer(root, SP_OBJECT_PARENT(layer));
169         }
170     }
172     return NULL;
177 /*
178   Local Variables:
179   mode:c++
180   c-file-style:"stroustrup"
181   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
182   indent-tabs-mode:nil
183   fill-column:99
184   End:
185 */
186 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :