Code

patch #1450307 - option for select all to work in layer with it's sub-layers:
authorknutux <knutux@users.sourceforge.net>
Fri, 31 Mar 2006 11:50:44 +0000 (11:50 +0000)
committerknutux <knutux@users.sourceforge.net>
Fri, 31 Mar 2006 11:50:44 +0000 (11:50 +0000)
* Replaced check-box in preferences with 3 radio buttons (in all document in current layer only, in current layer with sub-layers)
* Altered "Select all" functionality to include objects in sub-layers (if preference is on)
* Altered TAB functionality to include sub-layers (had to introduce "context layer" concept in Selection class - without it TAB'ing would end in deepest child, but it needs to return to parent on subsequent TAB key press)

ChangeLog
src/enums.h
src/selection-chemistry.cpp
src/selection.cpp
src/selection.h
src/ui/dialog/inkscape-preferences.cpp
src/ui/dialog/inkscape-preferences.h

index 88edb807bb32cec1b107c9a87b0fd1641a22aa69..e8bd87cfd360a0753cfbd36d676c7a9b7c6d6cbb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2006-03-29  Andrius R. <knutux@gmail.com>
+
+       * src/layer-fns.h, src/dialogs/layer-properties.cpp,
+         src/dialogs/layer-properties.h, src/layer-fns.cpp:
+
+         patch #1450307 - option for select all to work in layer with it's sub-layers
+
 2006-03-29  Andrius R. <knutux@gmail.com>
 
        * po/lt.po: Translated and added new language - Lithuanian.
index fb8a30c50a0a5e1b3501d28ccec6443873d57295..4d3c75c208e1f108b1f97720bf58cfbd788ed299 100644 (file)
@@ -73,5 +73,13 @@ enum {
        SP_CLONE_ORPHANS_ASKME
 };
 
+/* "inlayer" preference values */
+
+enum PrefsSelectionContext {
+    PREFS_SELECTION_ALL = 0,
+    PREFS_SELECTION_LAYER = 1,
+    PREFS_SELECTION_LAYER_RECURSIVE = 2,
+};
+
 #endif
 
index 4da9b33b86e15680b3588c2cee35c1ab2826a41d..d4bc26c5d08a68879f9d9ae2a555ecced6bb3384 100644 (file)
@@ -330,7 +330,7 @@ void sp_edit_select_all_full (bool force_all_layers, bool invert)
 
     g_return_if_fail(SP_IS_GROUP(dt->currentLayer()));
 
-    bool inlayer = prefs_get_int_attribute ("options.kbselection", "inlayer", 1);
+    PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs_get_int_attribute ("options.kbselection", "inlayer", PREFS_SELECTION_LAYER);
     bool onlyvisible = prefs_get_int_attribute ("options.kbselection", "onlyvisible", 1);
     bool onlysensitive = prefs_get_int_attribute ("options.kbselection", "onlysensitive", 1);
 
@@ -341,8 +341,11 @@ void sp_edit_select_all_full (bool force_all_layers, bool invert)
         exclude = selection->itemList();
     }
 
-    if (inlayer && !force_all_layers) {
+    if (force_all_layers)
+        inlayer = PREFS_SELECTION_ALL;
 
+    switch (inlayer) {
+        case PREFS_SELECTION_LAYER: {
         if ( (onlysensitive && SP_ITEM(dt->currentLayer())->isLocked()) ||
              (onlyvisible && dt->itemIsHidden(SP_ITEM(dt->currentLayer()))) )
         return;
@@ -364,9 +367,16 @@ void sp_edit_select_all_full (bool force_all_layers, bool invert)
         }
 
         g_slist_free (all_items);
-
-    } else {
+            break;
+        }
+        case PREFS_SELECTION_LAYER_RECURSIVE: {
+            items = get_all_items (NULL, dt->currentLayer(), dt, onlyvisible, onlysensitive, exclude);
+            break;
+        }
+        default: {
         items = get_all_items (NULL, dt->currentRoot(), dt, onlyvisible, onlysensitive, exclude);
+            break;
+    }
     }
 
     selection->setList (items);
@@ -1656,11 +1666,11 @@ namespace {
 
 template <typename D>
 SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
-                  bool only_in_viewport, bool inlayer, bool onlyvisible, bool onlysensitive);
+                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive);
 
 template <typename D>
 SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items, SPObject *root,
-                  bool only_in_viewport, bool inlayer, bool onlyvisible, bool onlysensitive);
+                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive);
 
 struct Forward {
     typedef SPObject *Iterator;
@@ -1711,13 +1721,13 @@ sp_selection_item_next(void)
     g_return_if_fail(desktop != NULL);
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
 
-    bool inlayer = prefs_get_int_attribute ("options.kbselection", "inlayer", 1);
+    PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs_get_int_attribute ("options.kbselection", "inlayer", PREFS_SELECTION_LAYER);
     bool onlyvisible = prefs_get_int_attribute ("options.kbselection", "onlyvisible", 1);
     bool onlysensitive = prefs_get_int_attribute ("options.kbselection", "onlysensitive", 1);
 
     SPObject *root;
-    if (inlayer) {
-        root = desktop->currentLayer();
+    if (PREFS_SELECTION_ALL != inlayer) {
+        root = selection->activeContext();
     } else {
         root = desktop->currentRoot();
     }
@@ -1725,7 +1735,7 @@ sp_selection_item_next(void)
     SPItem *item=next_item_from_list<Forward>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive);
 
     if (item) {
-        selection->set(item);
+        selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer);
         if ( SP_CYCLING == SP_CYCLE_FOCUS ) {
             scroll_to_show_item(desktop, item);
         }
@@ -1741,13 +1751,13 @@ sp_selection_item_prev(void)
     g_return_if_fail(desktop != NULL);
     Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
 
-    bool inlayer = prefs_get_int_attribute ("options.kbselection", "inlayer", 1);
+    PrefsSelectionContext inlayer = (PrefsSelectionContext)prefs_get_int_attribute ("options.kbselection", "inlayer", PREFS_SELECTION_LAYER);
     bool onlyvisible = prefs_get_int_attribute ("options.kbselection", "onlyvisible", 1);
     bool onlysensitive = prefs_get_int_attribute ("options.kbselection", "onlysensitive", 1);
 
     SPObject *root;
-    if (inlayer) {
-        root = desktop->currentLayer();
+    if (PREFS_SELECTION_ALL != inlayer) {
+        root = selection->activeContext();
     } else {
         root = desktop->currentRoot();
     }
@@ -1755,7 +1765,7 @@ sp_selection_item_prev(void)
     SPItem *item=next_item_from_list<Reverse>(desktop, selection->itemList(), root, SP_CYCLING == SP_CYCLE_VISIBLE, inlayer, onlyvisible, onlysensitive);
 
     if (item) {
-        selection->set(item);
+        selection->set(item, PREFS_SELECTION_LAYER_RECURSIVE == inlayer);
         if ( SP_CYCLING == SP_CYCLE_FOCUS ) {
             scroll_to_show_item(desktop, item);
         }
@@ -1766,7 +1776,7 @@ namespace {
 
 template <typename D>
 SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items,
-                            SPObject *root, bool only_in_viewport, bool inlayer, bool onlyvisible, bool onlysensitive)
+                            SPObject *root, bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
 {
     SPObject *current=root;
     while (items) {
@@ -1800,7 +1810,7 @@ SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items,
 
 template <typename D>
 SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
-                  bool only_in_viewport, bool inlayer, bool onlyvisible, bool onlysensitive)
+                  bool only_in_viewport, PrefsSelectionContext inlayer, bool onlyvisible, bool onlysensitive)
 {
     typename D::Iterator children;
     typename D::Iterator iter;
@@ -1821,7 +1831,7 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root,
     while ( iter && !found ) {
         SPObject *object=D::object(iter);
         if (desktop->isLayer(object)) {
-            if (!inlayer) { // recurse into sublayers
+            if (PREFS_SELECTION_LAYER != inlayer) { // recurse into sublayers
                 found = next_item<D>(desktop, NULL, object, only_in_viewport, inlayer, onlyvisible, onlysensitive);
             }
         } else if ( SP_IS_ITEM(object) &&
index 473a7202e594e1eecabcac3e1b9067774d7a64c9..0b17eefe98d0a5814ff0fef502e885165d78a239 100644 (file)
@@ -5,7 +5,9 @@
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   MenTaLguY <mental@rydia.net>
  *   bulia byak <buliabyak@users.sf.net>
+ *   Andrius R. <knutux@gmail.com>
  *
+ * Copyright (C)      2006 Andrius R.
  * Copyright (C) 2004-2005 MenTaLguY
  * Copyright (C) 1999-2002 Lauris Kaplinski
  * Copyright (C) 2001-2002 Ximian, Inc.
@@ -36,6 +38,8 @@ Selection::Selection(SPDesktop *desktop) :
     _reprs(NULL),
     _items(NULL),
     _desktop(desktop),
+    _selection_context(NULL),
+    _context_release_handler_id(0),
     _flags(0),
     _idle(0)
 {
@@ -89,11 +93,40 @@ void Selection::_emitModified(guint flags) {
     _modified_signal.emit(this, flags);
 }
 
-void Selection::_emitChanged() {
+void Selection::_emitChanged(bool persist_selection_context/* = false */) {
+    if (persist_selection_context) {
+        if (NULL == _selection_context) {
+            _selection_context = desktop()->currentLayer();
+            sp_object_ref(_selection_context, NULL);
+            g_signal_connect(G_OBJECT(_selection_context), "release",
+                             G_CALLBACK(&Selection::_releaseSelectionContext), this);
+        }
+    } else {
+        _releaseContext(_selection_context);
+    }
+
     inkscape_selection_changed(this);
     _changed_signal.emit(this);
 }
 
+void
+Selection::_releaseSelectionContext(SPObject *obj, Selection *selection)
+{
+    selection->_releaseContext(obj);
+}
+
+void
+Selection::_releaseContext(SPObject *obj)
+{
+    if (NULL == _selection_context || _selection_context != obj)
+        return;
+
+    g_signal_handler_disconnect(G_OBJECT(_selection_context), _context_release_handler_id);
+    sp_object_unref(_selection_context, NULL);
+    _context_release_handler_id = 0;
+    _selection_context = NULL;
+}
+
 void Selection::_invalidateCachedLists() {
     g_slist_free(_items);
     _items = NULL;
@@ -111,6 +144,12 @@ void Selection::_clear() {
     }
 }
 
+SPObject *Selection::activeContext() {
+    if (NULL != _selection_context)
+        return _selection_context;
+    return desktop()->currentLayer();
+    }
+
 bool Selection::includes(SPObject *obj) const {
     if (obj == NULL)
         return FALSE;
@@ -120,7 +159,7 @@ bool Selection::includes(SPObject *obj) const {
     return ( g_slist_find(_objs, obj) != NULL );
 }
 
-void Selection::add(SPObject *obj) {
+void Selection::add(SPObject *obj, bool persist_selection_context/* = false */) {
     g_return_if_fail(obj != NULL);
     g_return_if_fail(SP_IS_OBJECT(obj));
 
@@ -130,7 +169,7 @@ void Selection::add(SPObject *obj) {
 
     _invalidateCachedLists();
     _add(obj);
-    _emitChanged();
+    _emitChanged(persist_selection_context);
 }
 
 void Selection::_add(SPObject *obj) {
@@ -152,9 +191,9 @@ void Selection::_add(SPObject *obj) {
     */
 }
 
-void Selection::set(SPObject *object) {
+void Selection::set(SPObject *object, bool persist_selection_context) {
     _clear();
-    add(object);
+    add(object, persist_selection_context);
 }
 
 void Selection::toggle(SPObject *obj) {
index 6d403c426986c084be840f32dc751b237d3a16ff..c78a1fdbb04fd09fa0219768b1addd85a55b062b 100644 (file)
@@ -76,12 +76,19 @@ public:
      */
     SPDesktop *desktop() { return _desktop; }
 
+    /**
+     * @brief Returns active layer for selection (currentLayer or its parent)
+     *
+     * @return layer item the selection is bound to
+     */
+    SPObject *activeContext();
+
     /**
      * @brief Add an SPObject to the set of selected objects
      *
      * @param obj the SPObject to add
      */
-    void add(SPObject *obj);
+    void add(SPObject *obj, bool persist_selection_context = false);
 
     /**
      * @brief Add an XML node's SPObject to the set of selected objects
@@ -95,7 +102,7 @@ public:
      *
      * @param obj the object to select
      */
-    void set(SPObject *obj);
+    void set(SPObject *obj, bool persist_selection_context = false);
 
     /**
      * @brief Set the selection to an XML node's SPObject
@@ -308,11 +315,13 @@ private:
     static void _schedule_modified(SPObject *obj, guint flags, Selection *selection);
     /** @brief Releases a selected object that is being removed */
     static void _release(SPObject *obj, Selection *selection);
+    /** @brief Releases an active layer object that is being removed */
+    static void _releaseSelectionContext(SPObject *obj, Selection *selection);
 
     /** @brief Issues modified selection signal */
     void _emitModified(guint flags);
     /** @brief Issues changed selection signal */
-    void _emitChanged();
+    void _emitChanged(bool persist_selection_context = false);
 
     void _invalidateCachedLists();
 
@@ -328,12 +337,16 @@ private:
     void _remove(SPObject *obj);
     /** @brief returns the SPObject corresponding to an xml node (if any) */
     SPObject *_objectForXMLNode(XML::Node *repr) const;
+    /** @brief Releases an active layer object that is being removed */
+    void _releaseContext(SPObject *obj);
 
     mutable GSList *_objs;
     mutable GSList *_reprs;
     mutable GSList *_items;
 
     GC::soft_ptr<SPDesktop> _desktop;
+    SPObject* _selection_context;
+    gulong _context_release_handler_id;
     guint _flags;
     guint _idle;
 
index b90ed8d986df30b27c805e9c1b4fde911fc69c58..a1e87b854be7f3768621bfb83381a3d6887d7c6c 100644 (file)
@@ -468,13 +468,19 @@ void InkscapePreferences::initPageTransforms()
 
 void InkscapePreferences::initPageSelecting()
 {
-    _sel_current.init ( _("Select only within current layer"), "options.kbselection", "inlayer", true);
+    _sel_all.init ( _("Select in all layers"), "options.kbselection", "inlayer", PREFS_SELECTION_ALL, false, 0);
+    _sel_current.init ( _("Select only within current layer"), "options.kbselection", "inlayer", PREFS_SELECTION_LAYER, true, &_sel_all);
+    _sel_recursive.init ( _("Select in current layer and sublayers"), "options.kbselection", "inlayer", PREFS_SELECTION_LAYER_RECURSIVE, false, &_sel_all);
     _sel_hidden.init ( _("Ignore hidden objects"), "options.kbselection", "onlyvisible", true);
     _sel_locked.init ( _("Ignore locked objects"), "options.kbselection", "onlysensitive", true);
 
     _page_select.add_group_header( _("Ctrl+A, Tab, Shift+Tab:"));
+    _page_select.add_line( true, "", _sel_all, "", 
+                           _("Make keyboard selection commands work on objects in all layers"));
     _page_select.add_line( true, "", _sel_current, "", 
-                           _("Uncheck this to make keyboard selection commands work on objects in all layers"));
+                           _("Make keyboard selection commands work on objects in current layer only"));
+    _page_select.add_line( true, "", _sel_recursive, "", 
+                           _("Make keyboard selection commands work on objects in current layer and all its sublayers"));
     _page_select.add_line( true, "", _sel_hidden, "", 
                            _("Uncheck this to be able to select objects that are hidden (either by themselves or by being in a hidden group or layer)"));
     _page_select.add_line( true, "", _sel_locked, "", 
index af3dfa44b03ace56e9cc2ae49f29d850ed7c7a5a..3702c88f35eeb74dc664f7ac62b5ccb8ff60b7e5 100644 (file)
@@ -120,7 +120,10 @@ protected:
     PrefCheckButton _trans_scale_stroke, _trans_scale_corner, _trans_gradient,_trans_pattern;
     PrefRadioButton _trans_optimized, _trans_preserved;
 
-    PrefCheckButton _sel_current, _sel_hidden, _sel_locked;
+    PrefRadioButton _sel_all;
+    PrefRadioButton _sel_current;
+    PrefRadioButton _sel_recursive;
+    PrefCheckButton _sel_hidden, _sel_locked;
 
     PrefSpinButton  _misc_export, _misc_recent, _misc_simpl;
     PrefCheckButton _misc_imp_bitmap, _misc_comment, _misc_scripts;