[caribou: 9/15] Implement scannable interfaces in keyboard model.



commit c7ceeb7a923e3d1eae2edc8050c52f27fca7fb53
Author: Eitan Isaacson <eitan monotonous org>
Date:   Sat May 28 13:09:00 2011 -0700

    Implement scannable interfaces in keyboard model.

 libcaribou/Makefile.am          |    3 +-
 libcaribou/column-model.vala    |    9 +++-
 libcaribou/key-model.vala       |   18 +++++-
 libcaribou/level-model.vala     |   11 +++-
 libcaribou/row-model.vala       |   10 +++-
 libcaribou/scannable-group.vala |  129 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 174 insertions(+), 6 deletions(-)
---
diff --git a/libcaribou/Makefile.am b/libcaribou/Makefile.am
index d8e1664..50c51f5 100644
--- a/libcaribou/Makefile.am
+++ b/libcaribou/Makefile.am
@@ -41,7 +41,8 @@ libcaribou_la_SOURCES = \
 	util.vala \
 	json-deserializer.vala \
 	iscannable-item.vala \
-	iscannable-group.vala
+	iscannable-group.vala \
+	scannable-group.vala
 
 EXTRA_DIST = \
 	external-libs.vapi \
diff --git a/libcaribou/column-model.vala b/libcaribou/column-model.vala
index c97b700..ffc5b2f 100644
--- a/libcaribou/column-model.vala
+++ b/libcaribou/column-model.vala
@@ -1,5 +1,8 @@
 namespace Caribou {
-    public class ColumnModel : Object {
+    public class ColumnModel : ScannableGroup, IScannableItem {
+        public bool scan_stepping { get; set; }
+        public bool scan_selected { get; set; }
+
         Gee.ArrayList<KeyModel> keys;
 
         public ColumnModel () {
@@ -21,5 +24,9 @@ namespace Caribou {
         public KeyModel first_key () {
             return keys.first();
         }
+
+        public override IScannableItem[] get_scan_children () {
+            return (IScannableItem[]) get_keys ();
+        }
    }
 }
diff --git a/libcaribou/key-model.vala b/libcaribou/key-model.vala
index a4d437f..49e88aa 100644
--- a/libcaribou/key-model.vala
+++ b/libcaribou/key-model.vala
@@ -1,7 +1,7 @@
 using GLib;
 
 namespace Caribou {
-    public class KeyModel : GLib.Object {
+    public class KeyModel : GLib.Object, IScannableItem {
         public double margin_left { get; set; default = 0.0; }
         public double width { get; set; default = 1.0; }
         public string toggle { get; set; default = ""; }
@@ -10,6 +10,22 @@ namespace Caribou {
         public string name { get; private set; }
         public uint keyval { get; private set; }
 
+        public bool scan_stepping { get; internal set; }
+        private bool _scan_selected;
+        public bool scan_selected {
+            get {
+                return _scan_selected;
+            }
+
+            internal set {
+                _scan_selected = value;
+                if (_scan_selected) {
+                    press ();
+                    GLib.Timeout.add(200, () => { release (); return false; });
+                }
+            }
+        }
+
         private uint hold_tid;
         private XAdapter xadapter;
         private Gee.ArrayList<KeyModel> extended_keys;
diff --git a/libcaribou/level-model.vala b/libcaribou/level-model.vala
index c80490e..65db469 100644
--- a/libcaribou/level-model.vala
+++ b/libcaribou/level-model.vala
@@ -1,7 +1,7 @@
 using GLib;
 
 namespace Caribou {
-    public class LevelModel : GLib.Object {
+    public class LevelModel : ScannableGroup {
         public signal void level_toggled (string new_level);
         public string mode { get; private set; default = ""; }
 
@@ -53,5 +53,12 @@ namespace Caribou {
 
             return (KeyModel[]) keys.to_array ();
         }
+
+        public override IScannableItem[] get_scan_children () {
+            if (scan_grouping == ScanGrouping.LINEAR)
+                return (IScannableItem[]) get_keys ();
+            else
+                return (IScannableItem[]) rows.to_array ();
+        }
     }
-}
\ No newline at end of file
+}
diff --git a/libcaribou/row-model.vala b/libcaribou/row-model.vala
index 291d76c..3774519 100644
--- a/libcaribou/row-model.vala
+++ b/libcaribou/row-model.vala
@@ -1,5 +1,7 @@
 namespace Caribou {
-    public class RowModel : GLib.Object {
+    public class RowModel : ScannableGroup, IScannableItem {
+        public bool scan_stepping { get; set; }
+        public bool scan_selected { get; set; }
 
         Gee.ArrayList<ColumnModel> columns;
 
@@ -39,5 +41,11 @@ namespace Caribou {
             return (ColumnModel[]) columns.to_array ();
         }
 
+        public override IScannableItem[] get_scan_children () {
+            if (scan_grouping == ScanGrouping.ROWS)
+                return (IScannableItem[]) get_keys ();
+            else
+                return (IScannableItem[]) columns.to_array ();
+        }
     }
 }
diff --git a/libcaribou/scannable-group.vala b/libcaribou/scannable-group.vala
new file mode 100644
index 0000000..c60d8ce
--- /dev/null
+++ b/libcaribou/scannable-group.vala
@@ -0,0 +1,129 @@
+namespace Caribou {
+    public abstract class ScannableGroup : Object, IScannableGroup {
+        private Gee.LinkedList<IScannableItem> _step_path;
+        private Gee.LinkedList<IScannableItem> _selected_path;
+        private int _cycle_count;
+
+        private ScanGrouping _scan_grouping;
+        public ScanGrouping scan_grouping {
+            get {
+                return _scan_grouping;
+            }
+
+            set {
+                _scan_grouping = value;
+                foreach (IScannableItem item in get_scan_children ()) {
+                    if (item is IScannableGroup)
+                        ((IScannableGroup) item).scan_grouping = value;
+                }
+            }
+        }
+
+        private int scan_child_index { get; set; default=-1; }
+
+        public abstract IScannableItem[] get_scan_children ();
+
+        construct {
+            _step_path = new Gee.LinkedList<IScannableItem> ();
+            _selected_path = new Gee.LinkedList<IScannableItem> ();
+        }
+
+        public IScannableItem[] get_step_path () {
+            return (IScannableItem[]) _step_path.to_array ();
+        }
+
+        public IScannableItem[] get_selected_path () {
+            return (IScannableItem[]) _selected_path.to_array ();
+        }
+
+        private void add_to_step_path (IScannableItem item) {
+            _step_path.add(item);
+            step_item_changed (_step_path.peek_tail ());
+        }
+
+        private void add_to_selected_path (IScannableItem item) {
+            _selected_path.add(item);
+            selected_item_changed (_selected_path.peek_tail ());
+        }
+
+        private IScannableItem? get_steping_child () {
+            if (scan_child_index < 0)
+                return null;
+            return get_scan_children ()[scan_child_index];
+        }
+
+        public virtual IScannableItem? child_select () {
+            IScannableItem step_child = get_steping_child ();
+            IScannableItem selected_leaf = _selected_path.peek_tail ();
+            if (selected_leaf != null) {
+                assert (selected_leaf is IScannableGroup);
+                add_to_selected_path (
+                    ((IScannableGroup) selected_leaf).child_select ());
+            } else if (step_child != null) {
+                step_child.scan_selected = true;;
+                add_to_selected_path (step_child);
+                scan_child_index = -1;
+            }
+
+            return _selected_path.peek_tail ();
+        }
+
+        public void scan_reset () {
+            _selected_path.clear ();
+            _step_path.clear ();
+            scan_child_index = -1;
+
+            foreach (IScannableItem item in get_scan_children ()) {
+                item.scan_stepping = false;
+                item.scan_selected = false;
+
+                if (item is IScannableGroup)
+                    ((IScannableGroup) item).scan_reset ();
+            }
+            scan_cleared ();
+        }
+
+        public IScannableItem? child_step (int cycles) {
+            IScannableItem step_child = get_steping_child ();
+            IScannableItem selected_leaf = _selected_path.peek_tail ();
+            if (selected_leaf != null) {
+                assert (step_child == null);
+                if (selected_leaf is IScannableGroup)
+                    step_child = ((IScannableGroup) selected_leaf).child_step (
+                        cycles);
+
+                if (step_child != null)
+                    add_to_step_path (step_child);
+                else
+                    _step_path.clear ();
+            } else if (step_child != null || scan_child_index == -1) {
+                assert (selected_leaf == null);
+                IScannableItem[] children = get_scan_children ();
+
+                if (scan_child_index == -1)
+                    _cycle_count = 0;
+
+                if (scan_child_index == children.length - 1) {
+                    scan_child_index = -1;
+                    _cycle_count++;
+                }
+
+                if (_cycle_count < cycles) {
+
+                    if (step_child != null)
+                        step_child.scan_stepping = false;
+
+                    step_child = children[++scan_child_index];
+                    step_child.scan_stepping = true;
+                    add_to_step_path (step_child);
+                } else {
+                    _step_path.clear ();
+                }
+            } else {
+                warn_if_reached ();
+            }
+
+            return _step_path.peek_tail ();
+        }
+    }
+}
\ No newline at end of file



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