Code

GSoC C++-ificiation merge and cleanup.
[inkscape.git] / src / layer-fns.cpp
index fadcd0f1e319338e02c97b72640396b1343f853a..84f21cd979b2377dc214c5e384a28a8294ea2ce7 100644 (file)
@@ -3,6 +3,7 @@
  *
  * Authors:
  *   MenTaLguY <mental@rydia.net>
+ *   Jon A. Cruz <jon@joncruz.org>
  *
  * Copyright (C) 2004 MenTaLguY
  *
 #include "document.h"
 #include "sp-item-group.h"
 #include "xml/repr.h"
-#include "algorithms/find-last-if.h"
+#include "util/find-last-if.h"
+#include "layer-fns.h"
 
-namespace Inkscape {
+// TODO move the documentation comments into the .h file
 
-/** 
- *  Creates a new layer.  Advances to the next layer id indicated
- *  by the string "layerNN", then creates a new group object of 
- *  that id with attribute inkscape:groupmode='layer', and finally
- *  appends the new group object to \a root after object \a layer.
- *
- *  \pre \a root should be either \a layer or an ancestor of it
- */
-SPObject *create_layer(SPObject *root, SPObject *layer) {
-    SPDocument *document=SP_OBJECT_DOCUMENT(root);
-
-    static int layer_suffix=1;
-    gchar *id=NULL;
-    do {
-        g_free(id);
-        id = g_strdup_printf("layer%d", layer_suffix++);
-    } while (document->getObjectById(id));
-
-    Inkscape::XML::Node *repr=sp_repr_new("svg:g");
-    repr->setAttribute("inkscape:groupmode", "layer");
-    repr->setAttribute("id", id);
-    g_free(id);
-
-    if ( root == layer ) {
-        SP_OBJECT_REPR(root)->appendChild(repr);
-    } else {
-        Inkscape::XML::Node *layer_repr=SP_OBJECT_REPR(layer);
-        sp_repr_parent(layer_repr)->addChild(repr, layer_repr);
-    }
-
-    return document->getObjectByRepr(repr);
-}
+namespace Inkscape {
 
 namespace {
 
@@ -60,14 +31,22 @@ bool is_layer(SPObject &object) {
            SP_GROUP(&object)->layerMode() == SPGroup::LAYER;
 }
 
+/** Finds the next sibling layer for a \a layer
+ *
+ *  @returns NULL if there are no further layers under a parent
+ */
 SPObject *next_sibling_layer(SPObject *layer) {
     using std::find_if;
 
     return find_if<SPObject::SiblingIterator>(
-        SP_OBJECT_NEXT(layer), NULL, &is_layer
+        layer->getNext(), NULL, &is_layer
     );
 }
 
+/** Finds the previous sibling layer for a \a layer
+ *
+ *  @returns NULL if there are no further layers under a parent
+ */
 SPObject *previous_sibling_layer(SPObject *layer) {
     using Inkscape::Algorithms::find_last_if;
 
@@ -78,6 +57,10 @@ SPObject *previous_sibling_layer(SPObject *layer) {
     return ( sibling != layer ) ? sibling : NULL;
 }
 
+/** Finds the first child of a \a layer
+ *
+ *  @returns NULL if layer has no sublayers
+ */
 SPObject *first_descendant_layer(SPObject *layer) {
     using std::find_if;
 
@@ -94,6 +77,10 @@ SPObject *first_descendant_layer(SPObject *layer) {
     return first_descendant;
 }
 
+/** Finds the last (topmost) child of a \a layer
+ *
+ *  @returns NULL if layer has no sublayers
+ */
 SPObject *last_child_layer(SPObject *layer) {
     using Inkscape::Algorithms::find_last_if;
 
@@ -167,11 +154,57 @@ SPObject *previous_layer(SPObject *root, SPObject *layer) {
         } else {
             return last_elder_layer(root, SP_OBJECT_PARENT(layer));
         }
-    } 
+    }
 
     return NULL;
 }
 
+/**
+*  Creates a new layer.  Advances to the next layer id indicated
+ *  by the string "layerNN", then creates a new group object of
+ *  that id with attribute inkscape:groupmode='layer', and finally
+ *  appends the new group object to \a root after object \a layer.
+ *
+ *  \pre \a root should be either \a layer or an ancestor of it
+ */
+SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position) {
+    SPDocument *document=SP_OBJECT_DOCUMENT(root);
+    
+    static int layer_suffix=1;
+    gchar *id=NULL;
+    do {
+        g_free(id);
+        id = g_strdup_printf("layer%d", layer_suffix++);
+    } while (document->getObjectById(id));
+    
+    Inkscape::XML::Document *xml_doc = document->getReprDoc();
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:g");
+    repr->setAttribute("inkscape:groupmode", "layer");
+    repr->setAttribute("id", id);
+    g_free(id);
+    
+    if ( LPOS_CHILD == position ) {
+        root = layer;
+        SPObject *child_layer = Inkscape::last_child_layer(layer);
+        if ( NULL != child_layer ) {
+            layer = child_layer;
+        }
+    }
+    
+    if ( root == layer ) {
+        SP_OBJECT_REPR(root)->appendChild(repr);
+    } else {
+        Inkscape::XML::Node *layer_repr=SP_OBJECT_REPR(layer);
+        sp_repr_parent(layer_repr)->addChild(repr, layer_repr);
+        
+        if ( LPOS_BELOW == position ) {
+            SP_ITEM(document->getObjectByRepr(repr))->lowerOne();
+        }
+    }
+    
+    return document->getObjectByRepr(repr);
+}
+
 }
 
 /*
@@ -183,4 +216,4 @@ SPObject *previous_layer(SPObject *root, SPObject *layer) {
   fill-column:99
   End:
 */
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :