Code

Selection and event handling cleanup. Added deeper display.
authorjoncruz <joncruz@users.sourceforge.net>
Fri, 19 May 2006 08:27:22 +0000 (08:27 +0000)
committerjoncruz <joncruz@users.sourceforge.net>
Fri, 19 May 2006 08:27:22 +0000 (08:27 +0000)
src/dialogs/layers-panel.cpp
src/dialogs/layers-panel.h
src/preferences-skeleton.h

index 707ba1880377da5b37a53d9d8f8fe9f38daa110b..186aad70b2e7e81fec1bed86eafeab199d097e10 100644 (file)
@@ -30,6 +30,7 @@
 #include "sp-item.h"
 #include "widgets/icon.h"
 #include <gtkmm/widget.h>
+#include "prefs-utils.h"
 
 //#define DUMP_LAYERS 1
 
@@ -64,6 +65,25 @@ enum {
     BUTTON_DELETE
 };
 
+class LayersPanel::InternalUIBounce
+{
+public:
+    int _actionCode;
+    SPObject* _target;
+};
+
+static gboolean layers_panel_activated( GtkObject *object, GdkEvent * /*event*/, gpointer data )
+{
+    if ( data )
+    {
+        LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
+        panel->setDesktop( SP_ACTIVE_DESKTOP );
+    }
+
+    return FALSE;
+}
+
+
 void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
 {
     bool set = false;
@@ -97,6 +117,7 @@ void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned i
     }
 }
 
+
 Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
 {
     GtkWidget* iconWidget = 0;
@@ -165,47 +186,67 @@ void LayersPanel::_fireAction( unsigned int code )
 //     SP_VERB_LAYER_PREV,
 void LayersPanel::_takeAction( int val )
 {
-    switch ( val ) {
-        case BUTTON_NEW:
-        {
-            _fireAction( SP_VERB_LAYER_NEW );
-        }
-        break;
-        case BUTTON_RENAME:
-        {
-            _fireAction( SP_VERB_LAYER_RENAME );
-        }
-        break;
-        case BUTTON_TOP:
-        {
-            _fireAction( SP_VERB_LAYER_TO_TOP );
-        }
-        break;
-        case BUTTON_BOTTOM:
-        {
-            _fireAction( SP_VERB_LAYER_TO_BOTTOM );
-        }
-        break;
-        case BUTTON_UP:
-        {
-            _fireAction( SP_VERB_LAYER_RAISE );
-        }
-        break;
-        case BUTTON_DOWN:
-        {
-            _fireAction( SP_VERB_LAYER_LOWER );
-        }
-        break;
-        case BUTTON_DELETE:
-        {
-            _fireAction( SP_VERB_LAYER_DELETE );
-        }
-        break;
+    if ( !_pending ) {
+        _pending = new InternalUIBounce();
+        _pending->_actionCode = val;
+        _pending->_target = _selectedLayer();
+        Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
     }
+}
+
+bool LayersPanel::_executeAction()
+{
+    // Make sure selected layer hasn't changed since the action was triggered
+    if ( _pending
+         && !( (_desktop && _desktop->currentLayer())
+               && (_desktop->currentLayer() != _pending->_target)
+             ) ) {
+        int val = _pending->_actionCode;
+//        SPObject* target = _pending->_target;
+
+        switch ( val ) {
+            case BUTTON_NEW:
+            {
+                _fireAction( SP_VERB_LAYER_NEW );
+            }
+            break;
+            case BUTTON_RENAME:
+            {
+                _fireAction( SP_VERB_LAYER_RENAME );
+            }
+            break;
+            case BUTTON_TOP:
+            {
+                _fireAction( SP_VERB_LAYER_TO_TOP );
+            }
+            break;
+            case BUTTON_BOTTOM:
+            {
+                _fireAction( SP_VERB_LAYER_TO_BOTTOM );
+            }
+            break;
+            case BUTTON_UP:
+            {
+                _fireAction( SP_VERB_LAYER_RAISE );
+            }
+            break;
+            case BUTTON_DOWN:
+            {
+                _fireAction( SP_VERB_LAYER_LOWER );
+            }
+            break;
+            case BUTTON_DELETE:
+            {
+                _fireAction( SP_VERB_LAYER_DELETE );
+            }
+            break;
+        }
 
-    if ( _desktop && _desktop->currentLayer() ) {
-        _selectLayer( _desktop->currentLayer() );
+        delete _pending;
+        _pending = 0;
     }
+
+    return false;
 }
 
 class LayersPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
@@ -227,20 +268,16 @@ public:
     Gtk::TreeModelColumn<bool> _colLocked;
 };
 
-
-static gboolean layers_panel_activated( GtkObject *object, GdkEvent * /*event*/, gpointer data )
-{
-    if ( data )
-    {
-        LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
-        panel->setDesktop( SP_ACTIVE_DESKTOP );
+void LayersPanel::_selectLayer( SPObject *layer ) {
+    if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
+        if ( _tree.get_selection()->count_selected_rows() != 0 ) {
+            _tree.get_selection()->unselect_all();
+        }
+    } else {
+        _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
     }
 
-    return FALSE;
-}
-
-void LayersPanel::_selectLayer( SPObject *layer ) {
-    _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
+    _checkTreeSelection();
 }
 
 bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
@@ -269,47 +306,47 @@ void LayersPanel::_layersChanged()
     SPObject* root = document->root;
     if ( root ) {
         if ( _mgr && _mgr->includes( root ) ) {
+            SPObject* target = _desktop->currentLayer();
             _store->clear();
 
 #if DUMP_LAYERS
             g_message("root:%p  {%s}   [%s]", root, root->id, root->label() );
 #endif // DUMP_LAYERS
-            unsigned int counter = _mgr->childCount(root);
-            for ( unsigned int i = 0; i < counter; i++ ) {
-                SPObject *child = _mgr->nthChildOf(root, i);
-                if ( child ) {
+            _addLayer( document, root, 0, target, 0 );
+        }
+    }
+}
+
+void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
+{
+    if ( layer && (level < _maxNestDepth) ) {
+        unsigned int counter = _mgr->childCount(layer);
+        for ( unsigned int i = 0; i < counter; i++ ) {
+            SPObject *child = _mgr->nthChildOf(layer, i);
+            if ( child ) {
 #if DUMP_LAYERS
-                    g_message("    layer:%p  {%s}   [%s]", child, child->id, child->label() );
+                g_message(" %3d    layer:%p  {%s}   [%s]", level, child, child->id, child->label() );
 #endif // DUMP_LAYERS
 
-                    Gtk::TreeModel::Row row = *(_store->prepend());
-                    row[_model->_colObject] = child;
-                    row[_model->_colLabel] = child->label() ? child->label() : SP_OBJECT_ID(child);
-                    row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
-                    row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
-
-                    // TODO - implement walking deeper, not hardcoded
+                Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
+                Gtk::TreeModel::Row row = *iter;
+                row[_model->_colObject] = child;
+                row[_model->_colLabel] = child->label() ? child->label() : SP_OBJECT_ID(child);
+                row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
+                row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
 
-                    unsigned int counter2 = _mgr->childCount(child);
-                    for ( unsigned int i2 = 0; i2 < counter2; i2++ ) {
-                        SPObject *child2 = _mgr->nthChildOf(child, i2);
-                        if ( child2 ) {
-#if DUMP_LAYERS
-                            g_message("        layer:%p  {%s}   [%s]", child, child->id, child->label() );
-#endif // DUMP_LAYERS
-                            Gtk::TreeModel::Row row2 = *(_store->prepend(row.children()));
-                            row2[_model->_colObject] = child2;
-                            row2[_model->_colLabel] = child2->label() ? child2->label() : SP_OBJECT_ID(child2);
-                            row2[_model->_colVisible] = SP_IS_ITEM(child2) ? !SP_ITEM(child2)->isHidden() : false;
-                            row2[_model->_colLocked] = SP_IS_ITEM(child2) ? SP_ITEM(child2)->isLocked() : false;
-                        }
-                    }
+                if ( target && child == target ) {
+                    _tree.expand_to_path( _store->get_path(iter) );
 
+                    Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
+                    select->select(iter);
+                    _checkTreeSelection();
                 }
+
+                _addLayer( doc, child, &row, target, level + 1 );
             }
         }
     }
-
 }
 
 SPObject* LayersPanel::_selectedLayer()
@@ -325,6 +362,19 @@ SPObject* LayersPanel::_selectedLayer()
     return obj;
 }
 
+void LayersPanel::_pushTreeSelectionToCurrent()
+{
+    SPObject* inTree = _selectedLayer();
+    if ( inTree ) {
+        SPObject* curr = _desktop->currentLayer();
+        if ( curr != inTree ) {
+            _desktop->setCurrentLayer( inTree );
+        }
+    } else {
+        _desktop->setCurrentLayer( _desktop->doc()->root );
+    }
+}
+
 void LayersPanel::_checkTreeSelection()
 {
     bool sensitive = false;
@@ -338,19 +388,7 @@ void LayersPanel::_checkTreeSelection()
 
             sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
             sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
-
-            SPObject* curr = _desktop->currentLayer();
-            if ( curr != inTree ) {
-                _layerChangedConnection.block();
-                _desktop->setCurrentLayer(inTree);
-                _layerChangedConnection.unblock();
-                if ( _tree.get_selection()->count_selected_rows() < 1 ) {
-                    _selectLayer( inTree );
-                }
-            }
         }
-    } else {
-        sensitive = false;
     }
 
     for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
@@ -441,10 +479,14 @@ void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeM
  */
 LayersPanel::LayersPanel() :
     Inkscape::UI::Widget::Panel( "dialogs.layers" ),
+    _maxNestDepth(20),
     _mgr(0),
     _desktop(0),
-    _model(0)
+    _model(0),
+    _pending(0)
 {
+    _maxNestDepth = prefs_get_int_attribute_limited("dialogs.layers", "maxDepth", 20, 1, 1000);
+
     ModelColumns *zoop = new ModelColumns();
     _model = zoop;
 
@@ -470,7 +512,7 @@ LayersPanel::LayersPanel() :
         cell->property_activatable() = true;
     }
 
-    _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_checkTreeSelection) );
+    _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
 
     _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
     _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
@@ -595,7 +637,6 @@ void LayersPanel::setDesktop( SPDesktop* desktop )
             }
 
             _layersChanged();
-            _selectLayer( _desktop->currentLayer() );
         }
     }
 /*
index ba135e20202522cca24e07ea93dc85c3dfc25f28..bdfab6b29d29a4075138a13008d1e99c3e486d6b 100644 (file)
@@ -49,6 +49,7 @@ protected:
 
 private:
     class ModelColumns;
+    class InternalUIBounce;
 
     LayersPanel(LayersPanel const &); // no copy
     LayersPanel &operator=(LayersPanel const &); // no assign
@@ -64,14 +65,17 @@ private:
     void _handleButtonEvent(GdkEventButton* evt);
     void _handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeModel::iterator const& iter );
 
+    void _pushTreeSelectionToCurrent();
     void _checkTreeSelection();
 
     void _takeAction( int val );
+    bool _executeAction();
 
     void _selectLayer(SPObject *layer);
     bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer);
 
     void _layersChanged();
+    void _addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level );
 
     SPObject* _selectedLayer();
 
@@ -83,9 +87,11 @@ private:
     sigc::connection _addedConnection;
     sigc::connection _removedConnection;
 
+    int _maxNestDepth;
     Inkscape::LayerManager* _mgr;
     SPDesktop* _desktop;
     ModelColumns* _model;
+    InternalUIBounce* _pending;
     Glib::RefPtr<Gtk::TreeStore> _store;
     std::vector<Gtk::Widget*> _watching;
     std::vector<Gtk::Widget*> _watchingNonTop;
index 830e0fa76983ec130d7d1741d29dbbc2b26f3192..b9304635ddaf8fe2bf414e1c76b6c8c9ee7765ba 100644 (file)
@@ -140,7 +140,7 @@ static char const preferences_skeleton[] =
 "    <group id=\"iconpreview\" />\n"
 "    <group id=\"aboutextensions\" />\n"
 "    <group id=\"treeeditor\" />\n"
-"    <group id=\"layers\" />\n"
+"    <group id=\"layers\" maxDepth=\"20\"/>\n"
 "    <group id=\"extensioneditor\" />\n"
 "    <group id=\"trace\" />\n"
 "    <group id=\"script\" />\n"