Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / selection / TreeModel.js
diff --git a/src/selection/TreeModel.js b/src/selection/TreeModel.js
new file mode 100644 (file)
index 0000000..fd10aa4
--- /dev/null
@@ -0,0 +1,82 @@
+/**
+ * @class Ext.selection.TreeModel
+ * @extends Ext.selection.RowModel
+ *
+ * Adds custom behavior for left/right keyboard navigation for use with a tree.
+ * Depends on the view having an expand and collapse method which accepts a
+ * record.
+ * 
+ * @private
+ */
+Ext.define('Ext.selection.TreeModel', {
+    extend: 'Ext.selection.RowModel',
+    alias: 'selection.treemodel',
+    
+    // typically selection models prune records from the selection
+    // model when they are removed, because the TreeView constantly
+    // adds/removes records as they are expanded/collapsed
+    pruneRemoved: false,
+    
+    onKeyRight: function(e, t) {
+        var focused = this.getLastFocused(),
+            view    = this.view;
+            
+        if (focused) {
+            // tree node is already expanded, go down instead
+            // this handles both the case where we navigate to firstChild and if
+            // there are no children to the nextSibling
+            if (focused.isExpanded()) {
+                this.onKeyDown(e, t);
+            // if its not a leaf node, expand it
+            } else if (!focused.isLeaf()) {
+                view.expand(focused);
+            }
+        }
+    },
+    
+    onKeyLeft: function(e, t) {
+        var focused = this.getLastFocused(),
+            view    = this.view,
+            viewSm  = view.getSelectionModel(),
+            parentNode, parentRecord;
+
+        if (focused) {
+            parentNode = focused.parentNode;
+            // if focused node is already expanded, collapse it
+            if (focused.isExpanded()) {
+                view.collapse(focused);
+            // has a parentNode and its not root
+            // TODO: this needs to cover the case where the root isVisible
+            } else if (parentNode && !parentNode.isRoot()) {
+                // Select a range of records when doing multiple selection.
+                if (e.shiftKey) {
+                    viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
+                    viewSm.setLastFocused(parentNode);
+                // just move focus, not selection
+                } else if (e.ctrlKey) {
+                    viewSm.setLastFocused(parentNode);
+                // select it
+                } else {
+                    viewSm.select(parentNode);
+                }
+            }
+        }
+    },
+    
+    onKeyPress: function(e, t) {
+        var selected, checked;
+        
+        if (e.getKey() === e.SPACE || e.getKey() === e.ENTER) {
+            e.stopEvent();
+            selected = this.getLastSelected();
+            if (selected && selected.isLeaf()) {
+                checked = selected.get('checked');
+                if (Ext.isBoolean(checked)) {
+                    selected.set('checked', !checked);
+                }
+            }
+        } else {
+            this.callParent(arguments);
+        }
+    }
+});