Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / selection / CellModel.js
1 /**
2  * @class Ext.selection.CellModel
3  * @extends Ext.selection.Model
4  * @private
5  */
6 Ext.define('Ext.selection.CellModel', {
7     extend: 'Ext.selection.Model',
8     alias: 'selection.cellmodel',
9     requires: ['Ext.util.KeyNav'],
10     
11     /**
12      * @cfg {Boolean} enableKeyNav
13      * Turns on/off keyboard navigation within the grid. Defaults to true.
14      */
15     enableKeyNav: true,
16     
17     /**
18      * @cfg {Boolean} preventWrap
19      * Set this configuration to true to prevent wrapping around of selection as
20      * a user navigates to the first or last column. Defaults to false.
21      */
22     preventWrap: false,
23
24     constructor: function(){
25         this.addEvents(
26             /**
27              * @event deselect
28              * Fired after a cell is deselected
29              * @param {Ext.selection.CellModel} this
30              * @param {Ext.data.Model} record The record of the deselected cell
31              * @param {Number} row The row index deselected
32              * @param {Number} column The column index deselected
33              */
34             'deselect',
35             
36             /**
37              * @event select
38              * Fired after a cell is selected
39              * @param {Ext.selection.CellModel} this
40              * @param {Ext.data.Model} record The record of the selected cell
41              * @param {Number} row The row index selected
42              * @param {Number} column The column index selected
43              */
44             'select'
45         );
46         this.callParent(arguments);    
47     },
48
49     bindComponent: function(view) {
50         var me = this;
51         me.primaryView = view;
52         me.views = me.views || [];
53         me.views.push(view);
54         me.bind(view.getStore(), true);
55
56         view.on({
57             cellmousedown: me.onMouseDown,
58             refresh: me.onViewRefresh,
59             scope: me
60         });
61
62         if (me.enableKeyNav) {
63             me.initKeyNav(view);
64         }
65     },
66
67     initKeyNav: function(view) {
68         var me = this;
69         
70         if (!view.rendered) {
71             view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true});
72             return;
73         }
74
75         view.el.set({
76             tabIndex: -1
77         });
78
79         // view.el has tabIndex -1 to allow for
80         // keyboard events to be passed to it.
81         me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
82             up: me.onKeyUp,
83             down: me.onKeyDown,
84             right: me.onKeyRight,
85             left: me.onKeyLeft,
86             tab: me.onKeyTab,
87             scope: me
88         });
89     },
90     
91     getHeaderCt: function() {
92         return this.primaryView.headerCt;
93     },
94
95     onKeyUp: function(e, t) {
96         this.move('up', e);
97     },
98
99     onKeyDown: function(e, t) {
100         this.move('down', e);
101     },
102
103     onKeyLeft: function(e, t) {
104         this.move('left', e);
105     },
106     
107     onKeyRight: function(e, t) {
108         this.move('right', e);
109     },
110     
111     move: function(dir, e) {
112         var me = this,
113             pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
114         if (pos) {
115             me.setCurrentPosition(pos);
116         }
117         return pos;
118     },
119
120     /**
121      * Returns the current position in the format {row: row, column: column}
122      */
123     getCurrentPosition: function() {
124         return this.position;
125     },
126     
127     /**
128      * Sets the current position
129      * @param {Object} position The position to set.
130      */
131     setCurrentPosition: function(pos) {
132         var me = this;
133         
134         if (me.position) {
135             me.onCellDeselect(me.position);
136         }
137         if (pos) {
138             me.onCellSelect(pos);
139         }
140         me.position = pos;
141     },
142
143     /**
144      * Set the current position based on where the user clicks.
145      * @private
146      */
147     onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
148         this.setCurrentPosition({
149             row: rowIndex,
150             column: cellIndex
151         });
152     },
153
154     // notify the view that the cell has been selected to update the ui
155     // appropriately and bring the cell into focus
156     onCellSelect: function(position) {
157         var me = this,
158             store = me.view.getStore(),
159             record = store.getAt(position.row);
160
161         me.doSelect(record);
162         me.primaryView.onCellSelect(position);
163         // TODO: Remove temporary cellFocus call here.
164         me.primaryView.onCellFocus(position);
165         me.fireEvent('select', me, record, position.row, position.column);
166     },
167
168     // notify view that the cell has been deselected to update the ui
169     // appropriately
170     onCellDeselect: function(position) {
171         var me = this,
172             store = me.view.getStore(),
173             record = store.getAt(position.row);
174
175         me.doDeselect(record);
176         me.primaryView.onCellDeselect(position);
177         me.fireEvent('deselect', me, record, position.row, position.column);
178     },
179
180     onKeyTab: function(e, t) {
181         var me = this,
182             direction = e.shiftKey ? 'left' : 'right',
183             editingPlugin = me.view.editingPlugin,
184             position = me.move(direction, e);
185
186         if (editingPlugin && position && me.wasEditing) {
187             editingPlugin.startEditByPosition(position);
188         }
189         delete me.wasEditing;
190     },
191
192     onEditorTab: function(editingPlugin, e) {
193         var me = this,
194             direction = e.shiftKey ? 'left' : 'right',
195             position  = me.move(direction, e);
196
197         if (position) {
198             editingPlugin.startEditByPosition(position);
199             me.wasEditing = true;
200         }
201     },
202
203     refresh: function() {
204         var pos = this.getCurrentPosition();
205         if (pos) {
206             this.onCellSelect(pos);
207         }
208     },
209
210     onViewRefresh: function() {
211         var pos = this.getCurrentPosition();
212         if (pos) {
213             this.onCellDeselect(pos);
214             this.setCurrentPosition(null);
215         }
216     },
217
218     selectByPosition: function(position) {
219         this.setCurrentPosition(position);
220     }
221 });