[latexila/structure-update: 2/2] Structure: update structure on the fly (test)



commit 6d17dbf5413f221d3acf4deeee00316077855e5c
Author: Sébastien Wilmet <sebastien wilmet gmail com>
Date:   Wed May 4 20:34:47 2011 +0200

    Structure: update structure on the fly (test)
    
    It becomes a little too hackish.
    A custom TreeStore would be a cleaner approach, to get rid of updating
    all the time the TreeStore from the GNodes.

 src/document_structure.vala |  145 +++++++++++++++++++++++++++++++++++++++---
 1 files changed, 134 insertions(+), 11 deletions(-)
---
diff --git a/src/document_structure.vala b/src/document_structure.vala
index b2854e3..7d8322c 100644
--- a/src/document_structure.vala
+++ b/src/document_structure.vala
@@ -34,6 +34,7 @@ public class DocumentStructure : GLib.Object
 
     private bool _insert_at_end = true;
     private Node<DataNode?> _tree;
+    private TreeStore _tree_store = null;
 
     private static Regex? _comment_regex = null;
 
@@ -59,6 +60,8 @@ public class DocumentStructure : GLib.Object
                 stderr.printf ("Structure: %s\n", e.message);
             }
         }
+
+        update_structure_on_the_fly ();
     }
 
     public void parse ()
@@ -315,7 +318,7 @@ public class DocumentStructure : GLib.Object
             return;
         }
 
-        int pos = get_position_from_mark (item.mark);
+        int pos = get_mark_position (item.mark);
         unowned Node<DataNode?> cur_parent = _tree;
         while (true)
         {
@@ -323,7 +326,7 @@ public class DocumentStructure : GLib.Object
             int child_index = 0;
             while (true)
             {
-                int cur_pos = get_position_from_mark (cur_child.data.mark);
+                int cur_pos = get_mark_position (cur_child.data.mark);
 
                 if (cur_pos > pos)
                 {
@@ -451,7 +454,7 @@ public class DocumentStructure : GLib.Object
         parent.insert (cur_pos, (owned) new_node);
     }
 
-    private static int get_position_from_mark (TextMark mark)
+    private static int get_mark_position (TextMark mark)
     {
         TextIter iter;
         TextBuffer doc = mark.get_buffer ();
@@ -484,30 +487,30 @@ public class DocumentStructure : GLib.Object
 
     public void populate_tree_store (TreeStore store)
     {
-        populate_tree_store_at_node (store, _tree);
+        _tree_store = store;
+        populate_tree_store_at_node (_tree);
     }
 
     // The data are first inserted in Gnodes. When the parsing is done, this method is
     // called to populate the tree store with the data contained in the GNodes.
-    private void populate_tree_store_at_node (TreeStore store, Node<DataNode?> node,
+    private void populate_tree_store_at_node (Node<DataNode?> node,
         TreeIter? parent = null, bool root_node = true)
     {
         TreeIter? iter = null;
         if (! root_node)
-            iter = add_item_to_tree_store (store, parent, node.data);
+            iter = add_item_to_tree_store (parent, node.data);
 
         node.children_foreach (TraverseFlags.ALL, (child_node) =>
         {
-            populate_tree_store_at_node (store, child_node, iter, false);
+            populate_tree_store_at_node (child_node, iter, false);
         });
     }
 
-    private TreeIter add_item_to_tree_store (TreeStore store, TreeIter? parent,
-        DataNode data)
+    private TreeIter add_item_to_tree_store (TreeIter? parent, DataNode data)
     {
         TreeIter iter;
-        store.append (out iter, parent);
-        store.set (iter,
+        _tree_store.append (out iter, parent);
+        _tree_store.set (iter,
             StructItem.PIXBUF, Structure.get_icon_from_type (data.type),
             StructItem.TYPE, data.type,
             StructItem.TEXT, data.text,
@@ -518,6 +521,126 @@ public class DocumentStructure : GLib.Object
         return iter;
     }
 
+    // remove all items that are located at 'pos'
+    private void remove_items_at_node (Node<DataNode?> node, int pos, string[] indices)
+    {
+        unowned Node<DataNode?>? child = node.first_child ();
+        if (child == null)
+            return;
+
+        int cur_pos = get_mark_position (child.data.mark);
+        int i = 0;
+
+        while (child != null)
+        {
+            if (cur_pos > pos)
+                return;
+
+            unowned Node<DataNode?>? next_child = child.next_sibling ();
+            int next_pos = 0;
+            if (next_child != null)
+            {
+                next_pos = get_mark_position (next_child.data.mark);
+                if (next_pos < pos)
+                {
+                    child = next_child;
+                    cur_pos = next_pos;
+                    i++;
+                    continue;
+                }
+            }
+
+            string[] cur_indices = indices;
+            cur_indices += i.to_string ();
+
+            remove_items_at_node (child, pos, cur_indices);
+
+            if (cur_pos == pos)
+                remove_item_from_tree_store (child, cur_indices);
+
+            child = next_child;
+            cur_pos = next_pos;
+            i++;
+        }
+    }
+
+    private void remove_item_from_tree_store (Node<DataNode?> node, string[] indices)
+    {
+        if (node.is_leaf ())
+        {
+            string path_string = string.joinv (":", indices);
+            TreeIter iter;
+            stdout.printf ("path string: %s\n", path_string);
+            bool success = _tree_store.get_iter_from_string (out iter, path_string);
+            return_if_fail (success);
+
+            string text;
+            TreeModel model = (TreeModel) _tree_store;
+            model.get (iter, StructItem.TEXT, out text, -1);
+            stdout.printf ("remove item '%s'\n", text);
+
+            _tree_store.remove (iter);
+            return;
+        }
+    }
+
+    private void update_structure_on_the_fly ()
+    {
+        // some text is deleted
+        _doc.delete_range.connect_after (on_delete_range_after);
+    }
+
+    private void on_delete_range_after (TextIter iter)
+    {
+        // The text is already deleted. If there were some marks in the range, these marks
+        // will now be located at 'iter'.
+
+        /* Is there some marks? */
+        SList<weak TextMark> marks = iter.get_marks ();
+
+        // We keep a sample mark (one is enough, since they are all at the same place)
+        TextMark? sample_mark = null;
+
+        bool found = false;
+        foreach (weak TextMark mark in marks)
+        {
+            string? name = mark.get_name ();
+            if (name == null)
+                continue;
+
+            if (name.has_prefix (MARK_NAME_PREFIX))
+            {
+                found = true;
+                sample_mark = mark;
+                break;
+            }
+        }
+
+        if (! found)
+            return;
+
+        // We can run the rest in an IdleSource, so the UI is not frozen.
+        // I think we can't put the above code in the Idle, since the TextIter could be
+        // invalid.
+        Idle.add (() =>
+        {
+            // If the active document has changed (why not?)
+
+            // Delete all marks located at the same place as sample_mark.
+            int pos = get_mark_position (sample_mark);
+            string[] indices = {};
+            remove_items_at_node (_tree, pos, indices);
+
+            // But maybe one mark was actually good.
+            // Example:
+            // before: blabla \nicecommand{blabla}
+            // after: \nicecommand{blabla}
+            // In this example, we find a mark which is still good, so we recreate it.
+
+            return false;
+        });
+    }
+
     private StructType? get_type_from_simple_command_name (string name)
     {
         switch (name)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]