initial import
[roojs1] / Roo / grid / CellSelectionModel.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11 /**
12  * @class Roo.grid.CellSelectionModel
13  * @extends Roo.grid.AbstractSelectionModel
14  * This class provides the basic implementation for cell selection in a grid.
15  * @constructor
16  * @param {Object} config The object containing the configuration of this model.
17  */
18 Roo.grid.CellSelectionModel = function(config){
19     Roo.apply(this, config);
20
21     this.selection = null;
22
23     this.addEvents({
24         /**
25              * @event beforerowselect
26              * Fires before a cell is selected.
27              * @param {SelectionModel} this
28              * @param {Number} rowIndex The selected row index
29              * @param {Number} colIndex The selected cell index
30              */
31             "beforecellselect" : true,
32         /**
33              * @event cellselect
34              * Fires when a cell is selected.
35              * @param {SelectionModel} this
36              * @param {Number} rowIndex The selected row index
37              * @param {Number} colIndex The selected cell index
38              */
39             "cellselect" : true,
40         /**
41              * @event selectionchange
42              * Fires when the active selection changes.
43              * @param {SelectionModel} this
44              * @param {Object} selection null for no selection or an object (o) with two properties
45                 <ul>
46                 <li>o.record: the record object for the row the selection is in</li>
47                 <li>o.cell: An array of [rowIndex, columnIndex]</li>
48                 </ul>
49              */
50             "selectionchange" : true
51     });
52     Roo.grid.CellSelectionModel.superclass.constructor.call(this);
53 };
54
55 Roo.extend(Roo.grid.CellSelectionModel, Roo.grid.AbstractSelectionModel,  {
56
57     /** @ignore */
58     initEvents : function(){
59         this.grid.on("mousedown", this.handleMouseDown, this);
60         this.grid.getGridEl().on(Roo.isIE ? "keydown" : "keypress", this.handleKeyDown, this);
61         var view = this.grid.view;
62         view.on("refresh", this.onViewChange, this);
63         view.on("rowupdated", this.onRowUpdated, this);
64         view.on("beforerowremoved", this.clearSelections, this);
65         view.on("beforerowsinserted", this.clearSelections, this);
66         if(this.grid.isEditor){
67             this.grid.on("beforeedit", this.beforeEdit,  this);
68         }
69     },
70
71         //private
72     beforeEdit : function(e){
73         this.select(e.row, e.column, false, true, e.record);
74     },
75
76         //private
77     onRowUpdated : function(v, index, r){
78         if(this.selection && this.selection.record == r){
79             v.onCellSelect(index, this.selection.cell[1]);
80         }
81     },
82
83         //private
84     onViewChange : function(){
85         this.clearSelections(true);
86     },
87
88         /**
89          * Returns the currently selected cell,.
90          * @return {Array} The selected cell (row, column) or null if none selected.
91          */
92     getSelectedCell : function(){
93         return this.selection ? this.selection.cell : null;
94     },
95
96     /**
97      * Clears all selections.
98      * @param {Boolean} true to prevent the gridview from being notified about the change.
99      */
100     clearSelections : function(preventNotify){
101         var s = this.selection;
102         if(s){
103             if(preventNotify !== true){
104                 this.grid.view.onCellDeselect(s.cell[0], s.cell[1]);
105             }
106             this.selection = null;
107             this.fireEvent("selectionchange", this, null);
108         }
109     },
110
111     /**
112      * Returns true if there is a selection.
113      * @return {Boolean}
114      */
115     hasSelection : function(){
116         return this.selection ? true : false;
117     },
118
119     /** @ignore */
120     handleMouseDown : function(e, t){
121         var v = this.grid.getView();
122         if(this.isLocked()){
123             return;
124         };
125         var row = v.findRowIndex(t);
126         var cell = v.findCellIndex(t);
127         if(row !== false && cell !== false){
128             this.select(row, cell);
129         }
130     },
131
132     /**
133      * Selects a cell.
134      * @param {Number} rowIndex
135      * @param {Number} collIndex
136      */
137     select : function(rowIndex, colIndex, preventViewNotify, preventFocus, /*internal*/ r){
138         if(this.fireEvent("beforecellselect", this, rowIndex, colIndex) !== false){
139             this.clearSelections();
140             r = r || this.grid.dataSource.getAt(rowIndex);
141             this.selection = {
142                 record : r,
143                 cell : [rowIndex, colIndex]
144             };
145             if(!preventViewNotify){
146                 var v = this.grid.getView();
147                 v.onCellSelect(rowIndex, colIndex);
148                 if(preventFocus !== true){
149                     v.focusCell(rowIndex, colIndex);
150                 }
151             }
152             this.fireEvent("cellselect", this, rowIndex, colIndex);
153             this.fireEvent("selectionchange", this, this.selection);
154         }
155     },
156
157         //private
158     isSelectable : function(rowIndex, colIndex, cm){
159         return !cm.isHidden(colIndex);
160     },
161
162     /** @ignore */
163     handleKeyDown : function(e){
164         if(!e.isNavKeyPress()){
165             return;
166         }
167         var g = this.grid, s = this.selection;
168         if(!s){
169             e.stopEvent();
170             var cell = g.walkCells(0, 0, 1, this.isSelectable,  this);
171             if(cell){
172                 this.select(cell[0], cell[1]);
173             }
174             return;
175         }
176         var sm = this;
177         var walk = function(row, col, step){
178             return g.walkCells(row, col, step, sm.isSelectable,  sm);
179         };
180         var k = e.getKey(), r = s.cell[0], c = s.cell[1];
181         var newCell;
182
183         switch(k){
184              case e.TAB:
185                  if(e.shiftKey){
186                      newCell = walk(r, c-1, -1);
187                  }else{
188                      newCell = walk(r, c+1, 1);
189                  }
190              break;
191              case e.DOWN:
192                  newCell = walk(r+1, c, 1);
193              break;
194              case e.UP:
195                  newCell = walk(r-1, c, -1);
196              break;
197              case e.RIGHT:
198                  newCell = walk(r, c+1, 1);
199              break;
200              case e.LEFT:
201                  newCell = walk(r, c-1, -1);
202              break;
203              case e.ENTER:
204                  if(g.isEditor && !g.editing){
205                     g.startEditing(r, c);
206                     e.stopEvent();
207                     return;
208                 }
209              break;
210         };
211         if(newCell){
212             this.select(newCell[0], newCell[1]);
213             e.stopEvent();
214         }
215     },
216
217     acceptsNav : function(row, col, cm){
218         return !cm.isHidden(col) && cm.isCellEditable(col, row);
219     },
220
221     onEditorKey : function(field, e){
222         var k = e.getKey(), newCell, g = this.grid, ed = g.activeEditor;
223         if(k == e.TAB){
224             if(e.shiftKey){
225                 newCell = g.walkCells(ed.row, ed.col-1, -1, this.acceptsNav, this);
226             }else{
227                 newCell = g.walkCells(ed.row, ed.col+1, 1, this.acceptsNav, this);
228             }
229             e.stopEvent();
230         }else if(k == e.ENTER && !e.ctrlKey){
231             ed.completeEdit();
232             e.stopEvent();
233         }else if(k == e.ESC){
234             ed.cancelEdit();
235         }
236         if(newCell){
237             g.startEditing(newCell[0], newCell[1]);
238         }
239     }
240 });