Code

merged patch #1447043 from Andrius "knutux" R. to create sub-layers
authormental <mental@users.sourceforge.net>
Wed, 15 Mar 2006 22:58:35 +0000 (22:58 +0000)
committermental <mental@users.sourceforge.net>
Wed, 15 Mar 2006 22:58:35 +0000 (22:58 +0000)
ChangeLog
src/dialogs/layer-properties.cpp
src/dialogs/layer-properties.h
src/layer-fns.cpp
src/layer-fns.h

index d6a4c057fa77fec46c414d42309fc2b3a434f1d5..2825548545702a69db07533a3318e4c590fd9b61 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2005-03-14  MenTaLguY  <mental@rydia.net>
+
+       * src/layer-fns.h, src/dialogs/layer-properties.cpp,
+         src/dialogs/layer-properties.h, src/layer-fns.cpp:
+
+         merged patch #1447043 from Andrius "knutux" R. to create sub-layers
+
 2006-03-14  MenTaLguY  <mental@rydia.net>
 
        * src/Makefile_insert, src/display/nr-arena-item.cpp,
index 8806e97f0be4431f0edfa7e889d0e6198dc50277..086b24b0790fc8ee4d4c41b99fdc548f432c232a 100644 (file)
@@ -4,8 +4,10 @@
  *
  * Author:
  *   Bryce W. Harrington <bryce@bryceharrington.com>
+ *   Andreas R. <knutux@users.sourceforge.net>
  *
  * Copyright (C) 2004 Bryce Harrington
+ * Copyright (C) 2006 Andreas R.
  *
  * Released under GNU GPL.  Read the file 'COPYING' for more information
  */
@@ -22,8 +24,8 @@
 #include "document.h"
 #include "message-stack.h"
 #include "desktop-handles.h"
-#include "layer-fns.h"
 #include "sp-object.h"
+#include "sp-item.h"
 
 #include "layer-properties.h"
 
@@ -39,12 +41,19 @@ LayerPropertiesDialog::LayerPropertiesDialog()
 
     Gtk::VBox *mainVBox = get_vbox();
 
+    _layout_table.set_spacings(4);
+    _layout_table.resize (1, 2);
+
     // Layer name widgets
     _layer_name_entry.set_activates_default(true);
-    _layer_name_hbox.pack_end(_layer_name_entry, false, false, 4);
     _layer_name_label.set_label(_("Layer name:"));
-    _layer_name_hbox.pack_end(_layer_name_label, false, false, 4);
-    mainVBox->pack_start(_layer_name_hbox, false, false, 4);
+    _layer_name_label.set_alignment(1.0, 0.5);
+
+    _layout_table.attach(_layer_name_label,
+                         0, 1, 0, 1, Gtk::FILL, Gtk::FILL);
+    _layout_table.attach(_layer_name_entry,
+                         1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+    mainVBox->pack_start(_layout_table, false, false, 4);
 
     // Buttons
     _close_button.set_use_stock(true);
@@ -123,6 +132,51 @@ LayerPropertiesDialog::_close()
     );
 }
 
+void
+LayerPropertiesDialog::_setup_position_controls() {
+    if ( NULL == _layer || _desktop->currentRoot() == _layer ) {
+        // no layers yet, so option above/below/sublayer is useless
+        return;
+        }
+        
+    _dropdown_list = Gtk::ListStore::create(_dropdown_columns);
+    _layer_position_combo.set_model(_dropdown_list);
+    _layer_position_combo.pack_start(_label_renderer);
+    _layer_position_combo.set_cell_data_func(_label_renderer,
+                                             sigc::mem_fun(*this, &LayerPropertiesDialog::_prepareLabelRenderer));
+
+    _layout_table.resize (2, 2);
+
+    Gtk::ListStore::iterator row;
+    row = _dropdown_list->append();
+    row->set_value(_dropdown_columns.position, LPOS_ABOVE);
+    row->set_value(_dropdown_columns.name, Glib::ustring(_("Above current")));
+    _layer_position_combo.set_active(row);
+    row = _dropdown_list->append();
+    row->set_value(_dropdown_columns.position, LPOS_BELOW);
+    row->set_value(_dropdown_columns.name, Glib::ustring(_("Below current")));
+    row = _dropdown_list->append();
+    row->set_value(_dropdown_columns.position, LPOS_CHILD);
+    row->set_value(_dropdown_columns.name, Glib::ustring(_("As sublayer of current")));
+
+    _layout_table.attach(_layer_position_combo,
+                         1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL);
+    _layer_position_label.set_label(_("Position:"));
+    _layer_position_label.set_alignment(1.0, 0.5);
+    _layout_table.attach(_layer_position_label,
+                         0, 1, 1, 2, Gtk::FILL, Gtk::FILL);
+    show_all_children();
+}
+
+/** Formats the label for a given layer row 
+ */
+void LayerPropertiesDialog::_prepareLabelRenderer(
+    Gtk::TreeModel::const_iterator const &row
+) {
+    Glib::ustring name=(*row)[_dropdown_columns.name];
+    _label_renderer.property_markup() = name.c_str();
+}
+
 void LayerPropertiesDialog::Rename::setup(LayerPropertiesDialog &dialog) {
     SPDesktop *desktop=dialog._desktop;
     dialog.set_title(_("Rename Layer"));
@@ -146,13 +200,17 @@ void LayerPropertiesDialog::Create::setup(LayerPropertiesDialog &dialog) {
     dialog.set_title(_("Add Layer"));
     dialog._layer_name_entry.set_text("");
     dialog._apply_button.set_label(_("_Add"));
+    dialog._setup_position_controls();
 }
 
 void LayerPropertiesDialog::Create::perform(LayerPropertiesDialog &dialog) {
     SPDesktop *desktop=dialog._desktop;
-    SPObject *new_layer=Inkscape::create_layer(
-        desktop->currentRoot(), dialog._layer
-    );
+
+    Gtk::ListStore::iterator activeRow(dialog._layer_position_combo.get_active());
+    LayerRelativePosition position = activeRow->get_value(dialog._dropdown_columns.position);
+
+    SPObject *new_layer=Inkscape::create_layer(desktop->currentRoot(), dialog._layer, position);
+    
     Glib::ustring name(dialog._layer_name_entry.get_text());
     if (!name.empty()) {
         new_layer->setLabel((gchar *)name.c_str());
index 15404b2e5c7c9513eed9ae64bc00b01736d39889..93cd4f7e0cb7dbd021064b29ccf4466cdc946ff7 100644 (file)
 #include <gtkmm/entry.h>
 #include <gtkmm/label.h>
 #include <gtkmm/table.h>
+#include <gtkmm/combobox.h>
+#include <gtkmm/liststore.h>
 
 #include "selection.h"
+#include "layer-fns.h"
 
 namespace Inkscape {
 namespace UI {
@@ -65,9 +68,25 @@ protected:
     SPDesktop *_desktop;
     SPObject *_layer;
 
-    Gtk::HBox         _layer_name_hbox;
+    class PositionDropdownColumns : public Gtk::TreeModel::ColumnRecord {
+    public:
+        Gtk::TreeModelColumn<LayerRelativePosition> position;
+        Gtk::TreeModelColumn<Glib::ustring> name;
+
+        PositionDropdownColumns() {
+            add(position); add(name);
+        }
+    };
+
     Gtk::Label        _layer_name_label;
     Gtk::Entry        _layer_name_entry;
+    Gtk::Label        _layer_position_label;
+    Gtk::ComboBox     _layer_position_combo;
+    Gtk::Table        _layout_table;
+
+    PositionDropdownColumns _dropdown_columns;
+    Gtk::CellRendererText _label_renderer;
+    Glib::RefPtr<Gtk::ListStore> _dropdown_list;
 
     Gtk::Button       _close_button;
     Gtk::Button       _apply_button;
@@ -86,6 +105,9 @@ protected:
     void _apply();
     void _close();
 
+    void _setup_position_controls();
+    void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row);
+
 private:
     LayerPropertiesDialog(LayerPropertiesDialog const &); // no copy
     LayerPropertiesDialog &operator=(LayerPropertiesDialog const &); // no assign
index c143336cc26a273f622b884f3a2f5b6742774d41..2d58796af59edf222146080c8ab6b5543e36a7af 100644 (file)
 #include "sp-item-group.h"
 #include "xml/repr.h"
 #include "algorithms/find-last-if.h"
+#include "layer-fns.h"
 
 namespace Inkscape {
 
-/**
- *  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 {
 
 bool is_layer(SPObject &object) {
@@ -60,6 +28,10 @@ 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;
 
@@ -68,6 +40,10 @@ SPObject *next_sibling_layer(SPObject *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 +54,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 +74,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;
 
@@ -172,6 +156,51 @@ SPObject *previous_layer(SPObject *root, SPObject *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::Node *repr=sp_repr_new("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);
+}
+
 }
 
 /*
index ba11bab6a310747756d01e176001f5b05ef80222..c3e74c47200652da0529f1a232e47193d21ff5a9 100644 (file)
@@ -16,8 +16,14 @@ class SPObject;
 
 namespace Inkscape {
 
-SPObject *create_layer(SPObject *root, SPObject *layer);
-
+enum LayerRelativePosition {
+    LPOS_ABOVE,
+    LPOS_BELOW,
+    LPOS_CHILD,
+};
+    
+SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position);
+    
 SPObject *next_layer(SPObject *root, SPObject *layer);
 
 SPObject *previous_layer(SPObject *root, SPObject *layer);