Upgrade to ExtJS 3.2.0 - Released 03/30/2010
[extjs.git] / src / widgets / grid / GridPanel.js
1 /*!
2  * Ext JS Library 3.2.0
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.grid.GridPanel
9  * @extends Ext.Panel
10  * <p>This class represents the primary interface of a component based grid control to represent data
11  * in a tabular format of rows and columns. The GridPanel is composed of the following:</p>
12  * <div class="mdetail-params"><ul>
13  * <li><b>{@link Ext.data.Store Store}</b> : The Model holding the data records (rows)
14  * <div class="sub-desc"></div></li>
15  * <li><b>{@link Ext.grid.ColumnModel Column model}</b> : Column makeup
16  * <div class="sub-desc"></div></li>
17  * <li><b>{@link Ext.grid.GridView View}</b> : Encapsulates the user interface
18  * <div class="sub-desc"></div></li>
19  * <li><b>{@link Ext.grid.AbstractSelectionModel selection model}</b> : Selection behavior
20  * <div class="sub-desc"></div></li>
21  * </ul></div>
22  * <p>Example usage:</p>
23  * <pre><code>
24 var grid = new Ext.grid.GridPanel({
25     {@link #store}: new {@link Ext.data.Store}({
26         {@link Ext.data.Store#autoDestroy autoDestroy}: true,
27         {@link Ext.data.Store#reader reader}: reader,
28         {@link Ext.data.Store#data data}: xg.dummyData
29     }),
30     {@link #colModel}: new {@link Ext.grid.ColumnModel}({
31         {@link Ext.grid.ColumnModel#defaults defaults}: {
32             width: 120,
33             sortable: true
34         },
35         {@link Ext.grid.ColumnModel#columns columns}: [
36             {id: 'company', header: 'Company', width: 200, sortable: true, dataIndex: 'company'},
37             {header: 'Price', renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
38             {header: 'Change', dataIndex: 'change'},
39             {header: '% Change', dataIndex: 'pctChange'},
40             // instead of specifying renderer: Ext.util.Format.dateRenderer('m/d/Y') use xtype
41             {
42                 header: 'Last Updated', width: 135, dataIndex: 'lastChange',
43                 xtype: 'datecolumn', format: 'M d, Y'
44             }
45         ],
46     }),
47     {@link #viewConfig}: {
48         {@link Ext.grid.GridView#forceFit forceFit}: true,
49
50 //      Return CSS class to apply to rows depending upon data values
51         {@link Ext.grid.GridView#getRowClass getRowClass}: function(record, index) {
52             var c = record.{@link Ext.data.Record#get get}('change');
53             if (c < 0) {
54                 return 'price-fall';
55             } else if (c > 0) {
56                 return 'price-rise';
57             }
58         }
59     },
60     {@link #sm}: new Ext.grid.RowSelectionModel({singleSelect:true}),
61     width: 600,
62     height: 300,
63     frame: true,
64     title: 'Framed with Row Selection and Horizontal Scrolling',
65     iconCls: 'icon-grid'
66 });
67  * </code></pre>
68  * <p><b><u>Notes:</u></b></p>
69  * <div class="mdetail-params"><ul>
70  * <li>Although this class inherits many configuration options from base classes, some of them
71  * (such as autoScroll, autoWidth, layout, items, etc) are not used by this class, and will
72  * have no effect.</li>
73  * <li>A grid <b>requires</b> a width in which to scroll its columns, and a height in which to
74  * scroll its rows. These dimensions can either be set explicitly through the
75  * <tt>{@link Ext.BoxComponent#height height}</tt> and <tt>{@link Ext.BoxComponent#width width}</tt>
76  * configuration options or implicitly set by using the grid as a child item of a
77  * {@link Ext.Container Container} which will have a {@link Ext.Container#layout layout manager}
78  * provide the sizing of its child items (for example the Container of the Grid may specify
79  * <tt>{@link Ext.Container#layout layout}:'fit'</tt>).</li>
80  * <li>To access the data in a Grid, it is necessary to use the data model encapsulated
81  * by the {@link #store Store}. See the {@link #cellclick} event for more details.</li>
82  * </ul></div>
83  * @constructor
84  * @param {Object} config The config object
85  * @xtype grid
86  */
87 Ext.grid.GridPanel = Ext.extend(Ext.Panel, {
88     /**
89      * @cfg {String} autoExpandColumn
90      * <p>The <tt>{@link Ext.grid.Column#id id}</tt> of a {@link Ext.grid.Column column} in
91      * this grid that should expand to fill unused space. This value specified here can not
92      * be <tt>0</tt>.</p>
93      * <br><p><b>Note</b>: If the Grid's {@link Ext.grid.GridView view} is configured with
94      * <tt>{@link Ext.grid.GridView#forceFit forceFit}=true</tt> the <tt>autoExpandColumn</tt>
95      * is ignored. See {@link Ext.grid.Column}.<tt>{@link Ext.grid.Column#width width}</tt>
96      * for additional details.</p>
97      * <p>See <tt>{@link #autoExpandMax}</tt> and <tt>{@link #autoExpandMin}</tt> also.</p>
98      */
99     autoExpandColumn : false,
100     /**
101      * @cfg {Number} autoExpandMax The maximum width the <tt>{@link #autoExpandColumn}</tt>
102      * can have (if enabled). Defaults to <tt>1000</tt>.
103      */
104     autoExpandMax : 1000,
105     /**
106      * @cfg {Number} autoExpandMin The minimum width the <tt>{@link #autoExpandColumn}</tt>
107      * can have (if enabled). Defaults to <tt>50</tt>.
108      */
109     autoExpandMin : 50,
110     /**
111      * @cfg {Boolean} columnLines <tt>true</tt> to add css for column separation lines.
112      * Default is <tt>false</tt>.
113      */
114     columnLines : false,
115     /**
116      * @cfg {Object} cm Shorthand for <tt>{@link #colModel}</tt>.
117      */
118     /**
119      * @cfg {Object} colModel The {@link Ext.grid.ColumnModel} to use when rendering the grid (required).
120      */
121     /**
122      * @cfg {Array} columns An array of {@link Ext.grid.Column columns} to auto create a
123      * {@link Ext.grid.ColumnModel}.  The ColumnModel may be explicitly created via the
124      * <tt>{@link #colModel}</tt> configuration property.
125      */
126     /**
127      * @cfg {String} ddGroup The DD group this GridPanel belongs to. Defaults to <tt>'GridDD'</tt> if not specified.
128      */
129     /**
130      * @cfg {String} ddText
131      * Configures the text in the drag proxy.  Defaults to:
132      * <pre><code>
133      * ddText : '{0} selected row{1}'
134      * </code></pre>
135      * <tt>{0}</tt> is replaced with the number of selected rows.
136      */
137     ddText : '{0} selected row{1}',
138     /**
139      * @cfg {Boolean} deferRowRender <P>Defaults to <tt>true</tt> to enable deferred row rendering.</p>
140      * <p>This allows the GridPanel to be initially rendered empty, with the expensive update of the row
141      * structure deferred so that layouts with GridPanels appear more quickly.</p>
142      */
143     deferRowRender : true,
144     /**
145      * @cfg {Boolean} disableSelection <p><tt>true</tt> to disable selections in the grid. Defaults to <tt>false</tt>.</p>
146      * <p>Ignored if a {@link #selModel SelectionModel} is specified.</p>
147      */
148     /**
149      * @cfg {Boolean} enableColumnResize <tt>false</tt> to turn off column resizing for the whole grid. Defaults to <tt>true</tt>.
150      */
151     /**
152      * @cfg {Boolean} enableColumnHide
153      * Defaults to <tt>true</tt> to enable {@link Ext.grid.Column#hidden hiding of columns}
154      * with the {@link #enableHdMenu header menu}.
155      */
156     enableColumnHide : true,
157     /**
158      * @cfg {Boolean} enableColumnMove Defaults to <tt>true</tt> to enable drag and drop reorder of columns. <tt>false</tt>
159      * to turn off column reordering via drag drop.
160      */
161     enableColumnMove : true,
162     /**
163      * @cfg {Boolean} enableDragDrop <p>Enables dragging of the selected rows of the GridPanel. Defaults to <tt>false</tt>.</p>
164      * <p>Setting this to <b><tt>true</tt></b> causes this GridPanel's {@link #getView GridView} to
165      * create an instance of {@link Ext.grid.GridDragZone}. <b>Note</b>: this is available only <b>after</b>
166      * the Grid has been rendered as the GridView's <tt>{@link Ext.grid.GridView#dragZone dragZone}</tt>
167      * property.</p>
168      * <p>A cooperating {@link Ext.dd.DropZone DropZone} must be created who's implementations of
169      * {@link Ext.dd.DropZone#onNodeEnter onNodeEnter}, {@link Ext.dd.DropZone#onNodeOver onNodeOver},
170      * {@link Ext.dd.DropZone#onNodeOut onNodeOut} and {@link Ext.dd.DropZone#onNodeDrop onNodeDrop} are able
171      * to process the {@link Ext.grid.GridDragZone#getDragData data} which is provided.</p>
172      */
173     enableDragDrop : false,
174     /**
175      * @cfg {Boolean} enableHdMenu Defaults to <tt>true</tt> to enable the drop down button for menu in the headers.
176      */
177     enableHdMenu : true,
178     /**
179      * @cfg {Boolean} hideHeaders True to hide the grid's header. Defaults to <code>false</code>.
180      */
181     /**
182      * @cfg {Object} loadMask An {@link Ext.LoadMask} config or true to mask the grid while
183      * loading. Defaults to <code>false</code>.
184      */
185     loadMask : false,
186     /**
187      * @cfg {Number} maxHeight Sets the maximum height of the grid - ignored if <tt>autoHeight</tt> is not on.
188      */
189     /**
190      * @cfg {Number} minColumnWidth The minimum width a column can be resized to. Defaults to <tt>25</tt>.
191      */
192     minColumnWidth : 25,
193     /**
194      * @cfg {Object} sm Shorthand for <tt>{@link #selModel}</tt>.
195      */
196     /**
197      * @cfg {Object} selModel Any subclass of {@link Ext.grid.AbstractSelectionModel} that will provide
198      * the selection model for the grid (defaults to {@link Ext.grid.RowSelectionModel} if not specified).
199      */
200     /**
201      * @cfg {Ext.data.Store} store The {@link Ext.data.Store} the grid should use as its data source (required).
202      */
203     /**
204      * @cfg {Boolean} stripeRows <tt>true</tt> to stripe the rows. Default is <tt>false</tt>.
205      * <p>This causes the CSS class <tt><b>x-grid3-row-alt</b></tt> to be added to alternate rows of
206      * the grid. A default CSS rule is provided which sets a background colour, but you can override this
207      * with a rule which either overrides the <b>background-color</b> style using the '!important'
208      * modifier, or which uses a CSS selector of higher specificity.</p>
209      */
210     stripeRows : false,
211     /**
212      * @cfg {Boolean} trackMouseOver True to highlight rows when the mouse is over. Default is <tt>true</tt>
213      * for GridPanel, but <tt>false</tt> for EditorGridPanel.
214      */
215     trackMouseOver : true,
216     /**
217      * @cfg {Array} stateEvents
218      * An array of events that, when fired, should trigger this component to save its state.
219      * Defaults to:<pre><code>
220      * stateEvents: ['columnmove', 'columnresize', 'sortchange', 'groupchange']
221      * </code></pre>
222      * <p>These can be any types of events supported by this component, including browser or
223      * custom events (e.g., <tt>['click', 'customerchange']</tt>).</p>
224      * <p>See {@link Ext.Component#stateful} for an explanation of saving and restoring
225      * Component state.</p>
226      */
227     stateEvents : ['columnmove', 'columnresize', 'sortchange', 'groupchange'],
228     /**
229      * @cfg {Object} view The {@link Ext.grid.GridView} used by the grid. This can be set
230      * before a call to {@link Ext.Component#render render()}.
231      */
232     view : null,
233
234     /**
235      * @cfg {Array} bubbleEvents
236      * <p>An array of events that, when fired, should be bubbled to any parent container.
237      * See {@link Ext.util.Observable#enableBubble}.
238      * Defaults to <tt>[]</tt>.
239      */
240     bubbleEvents: [],
241
242     /**
243      * @cfg {Object} viewConfig A config object that will be applied to the grid's UI view.  Any of
244      * the config options available for {@link Ext.grid.GridView} can be specified here. This option
245      * is ignored if <tt>{@link #view}</tt> is specified.
246      */
247
248     // private
249     rendered : false,
250     // private
251     viewReady : false,
252
253     // private
254     initComponent : function(){
255         Ext.grid.GridPanel.superclass.initComponent.call(this);
256
257         if(this.columnLines){
258             this.cls = (this.cls || '') + ' x-grid-with-col-lines';
259         }
260         // override any provided value since it isn't valid
261         // and is causing too many bug reports ;)
262         this.autoScroll = false;
263         this.autoWidth = false;
264
265         if(Ext.isArray(this.columns)){
266             this.colModel = new Ext.grid.ColumnModel(this.columns);
267             delete this.columns;
268         }
269
270         // check and correct shorthanded configs
271         if(this.ds){
272             this.store = this.ds;
273             delete this.ds;
274         }
275         if(this.cm){
276             this.colModel = this.cm;
277             delete this.cm;
278         }
279         if(this.sm){
280             this.selModel = this.sm;
281             delete this.sm;
282         }
283         this.store = Ext.StoreMgr.lookup(this.store);
284
285         this.addEvents(
286             // raw events
287             /**
288              * @event click
289              * The raw click event for the entire grid.
290              * @param {Ext.EventObject} e
291              */
292             'click',
293             /**
294              * @event dblclick
295              * The raw dblclick event for the entire grid.
296              * @param {Ext.EventObject} e
297              */
298             'dblclick',
299             /**
300              * @event contextmenu
301              * The raw contextmenu event for the entire grid.
302              * @param {Ext.EventObject} e
303              */
304             'contextmenu',
305             /**
306              * @event mousedown
307              * The raw mousedown event for the entire grid.
308              * @param {Ext.EventObject} e
309              */
310             'mousedown',
311             /**
312              * @event mouseup
313              * The raw mouseup event for the entire grid.
314              * @param {Ext.EventObject} e
315              */
316             'mouseup',
317             /**
318              * @event mouseover
319              * The raw mouseover event for the entire grid.
320              * @param {Ext.EventObject} e
321              */
322             'mouseover',
323             /**
324              * @event mouseout
325              * The raw mouseout event for the entire grid.
326              * @param {Ext.EventObject} e
327              */
328             'mouseout',
329             /**
330              * @event keypress
331              * The raw keypress event for the entire grid.
332              * @param {Ext.EventObject} e
333              */
334             'keypress',
335             /**
336              * @event keydown
337              * The raw keydown event for the entire grid.
338              * @param {Ext.EventObject} e
339              */
340             'keydown',
341
342             // custom events
343             /**
344              * @event cellmousedown
345              * Fires before a cell is clicked
346              * @param {Grid} this
347              * @param {Number} rowIndex
348              * @param {Number} columnIndex
349              * @param {Ext.EventObject} e
350              */
351             'cellmousedown',
352             /**
353              * @event rowmousedown
354              * Fires before a row is clicked
355              * @param {Grid} this
356              * @param {Number} rowIndex
357              * @param {Ext.EventObject} e
358              */
359             'rowmousedown',
360             /**
361              * @event headermousedown
362              * Fires before a header is clicked
363              * @param {Grid} this
364              * @param {Number} columnIndex
365              * @param {Ext.EventObject} e
366              */
367             'headermousedown',
368
369             /**
370              * @event groupmousedown
371              * Fires before a group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.
372              * @param {Grid} this
373              * @param {String} groupField
374              * @param {String} groupValue
375              * @param {Ext.EventObject} e
376              */
377             'groupmousedown',
378
379             /**
380              * @event rowbodymousedown
381              * Fires before the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>
382              * @param {Grid} this
383              * @param {Number} rowIndex
384              * @param {Ext.EventObject} e
385              */
386             'rowbodymousedown',
387
388             /**
389              * @event containermousedown
390              * Fires before the container is clicked. The container consists of any part of the grid body that is not covered by a row.
391              * @param {Grid} this
392              * @param {Ext.EventObject} e
393              */
394             'containermousedown',
395
396             /**
397              * @event cellclick
398              * Fires when a cell is clicked.
399              * The data for the cell is drawn from the {@link Ext.data.Record Record}
400              * for this row. To access the data in the listener function use the
401              * following technique:
402              * <pre><code>
403 function(grid, rowIndex, columnIndex, e) {
404     var record = grid.getStore().getAt(rowIndex);  // Get the Record
405     var fieldName = grid.getColumnModel().getDataIndex(columnIndex); // Get field name
406     var data = record.get(fieldName);
407 }
408 </code></pre>
409              * @param {Grid} this
410              * @param {Number} rowIndex
411              * @param {Number} columnIndex
412              * @param {Ext.EventObject} e
413              */
414             'cellclick',
415             /**
416              * @event celldblclick
417              * Fires when a cell is double clicked
418              * @param {Grid} this
419              * @param {Number} rowIndex
420              * @param {Number} columnIndex
421              * @param {Ext.EventObject} e
422              */
423             'celldblclick',
424             /**
425              * @event rowclick
426              * Fires when a row is clicked
427              * @param {Grid} this
428              * @param {Number} rowIndex
429              * @param {Ext.EventObject} e
430              */
431             'rowclick',
432             /**
433              * @event rowdblclick
434              * Fires when a row is double clicked
435              * @param {Grid} this
436              * @param {Number} rowIndex
437              * @param {Ext.EventObject} e
438              */
439             'rowdblclick',
440             /**
441              * @event headerclick
442              * Fires when a header is clicked
443              * @param {Grid} this
444              * @param {Number} columnIndex
445              * @param {Ext.EventObject} e
446              */
447             'headerclick',
448             /**
449              * @event headerdblclick
450              * Fires when a header cell is double clicked
451              * @param {Grid} this
452              * @param {Number} columnIndex
453              * @param {Ext.EventObject} e
454              */
455             'headerdblclick',
456             /**
457              * @event groupclick
458              * Fires when group header is clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.
459              * @param {Grid} this
460              * @param {String} groupField
461              * @param {String} groupValue
462              * @param {Ext.EventObject} e
463              */
464             'groupclick',
465             /**
466              * @event groupdblclick
467              * Fires when group header is double clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.
468              * @param {Grid} this
469              * @param {String} groupField
470              * @param {String} groupValue
471              * @param {Ext.EventObject} e
472              */
473             'groupdblclick',
474             /**
475              * @event containerclick
476              * Fires when the container is clicked. The container consists of any part of the grid body that is not covered by a row.
477              * @param {Grid} this
478              * @param {Ext.EventObject} e
479              */
480             'containerclick',
481             /**
482              * @event containerdblclick
483              * Fires when the container is double clicked. The container consists of any part of the grid body that is not covered by a row.
484              * @param {Grid} this
485              * @param {Ext.EventObject} e
486              */
487             'containerdblclick',
488
489             /**
490              * @event rowbodyclick
491              * Fires when the row body is clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>
492              * @param {Grid} this
493              * @param {Number} rowIndex
494              * @param {Ext.EventObject} e
495              */
496             'rowbodyclick',
497             /**
498              * @event rowbodydblclick
499              * Fires when the row body is double clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>
500              * @param {Grid} this
501              * @param {Number} rowIndex
502              * @param {Ext.EventObject} e
503              */
504             'rowbodydblclick',
505
506             /**
507              * @event rowcontextmenu
508              * Fires when a row is right clicked
509              * @param {Grid} this
510              * @param {Number} rowIndex
511              * @param {Ext.EventObject} e
512              */
513             'rowcontextmenu',
514             /**
515              * @event cellcontextmenu
516              * Fires when a cell is right clicked
517              * @param {Grid} this
518              * @param {Number} rowIndex
519              * @param {Number} cellIndex
520              * @param {Ext.EventObject} e
521              */
522             'cellcontextmenu',
523             /**
524              * @event headercontextmenu
525              * Fires when a header is right clicked
526              * @param {Grid} this
527              * @param {Number} columnIndex
528              * @param {Ext.EventObject} e
529              */
530             'headercontextmenu',
531             /**
532              * @event groupcontextmenu
533              * Fires when group header is right clicked. <b>Only applies for grids with a {@link Ext.grid.GroupingView GroupingView}</b>.
534              * @param {Grid} this
535              * @param {String} groupField
536              * @param {String} groupValue
537              * @param {Ext.EventObject} e
538              */
539             'groupcontextmenu',
540             /**
541              * @event containercontextmenu
542              * Fires when the container is right clicked. The container consists of any part of the grid body that is not covered by a row.
543              * @param {Grid} this
544              * @param {Ext.EventObject} e
545              */
546             'containercontextmenu',
547             /**
548              * @event rowbodycontextmenu
549              * Fires when the row body is right clicked. <b>Only applies for grids with {@link Ext.grid.GridView#enableRowBody enableRowBody} configured.</b>
550              * @param {Grid} this
551              * @param {Number} rowIndex
552              * @param {Ext.EventObject} e
553              */
554             'rowbodycontextmenu',
555             /**
556              * @event bodyscroll
557              * Fires when the body element is scrolled
558              * @param {Number} scrollLeft
559              * @param {Number} scrollTop
560              */
561             'bodyscroll',
562             /**
563              * @event columnresize
564              * Fires when the user resizes a column
565              * @param {Number} columnIndex
566              * @param {Number} newSize
567              */
568             'columnresize',
569             /**
570              * @event columnmove
571              * Fires when the user moves a column
572              * @param {Number} oldIndex
573              * @param {Number} newIndex
574              */
575             'columnmove',
576             /**
577              * @event sortchange
578              * Fires when the grid's store sort changes
579              * @param {Grid} this
580              * @param {Object} sortInfo An object with the keys field and direction
581              */
582             'sortchange',
583             /**
584              * @event groupchange
585              * Fires when the grid's grouping changes (only applies for grids with a {@link Ext.grid.GroupingView GroupingView})
586              * @param {Grid} this
587              * @param {String} groupField A string with the grouping field, null if the store is not grouped.
588              */
589             'groupchange',
590             /**
591              * @event reconfigure
592              * Fires when the grid is reconfigured with a new store and/or column model.
593              * @param {Grid} this
594              * @param {Ext.data.Store} store The new store
595              * @param {Ext.grid.ColumnModel} colModel The new column model
596              */
597             'reconfigure',
598             /**
599              * @event viewready
600              * Fires when the grid view is available (use this for selecting a default row).
601              * @param {Grid} this
602              */
603             'viewready'
604         );
605     },
606
607     // private
608     onRender : function(ct, position){
609         Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
610
611         var c = this.getGridEl();
612
613         this.el.addClass('x-grid-panel');
614
615         this.mon(c, {
616             scope: this,
617             mousedown: this.onMouseDown,
618             click: this.onClick,
619             dblclick: this.onDblClick,
620             contextmenu: this.onContextMenu
621         });
622
623         this.relayEvents(c, ['mousedown','mouseup','mouseover','mouseout','keypress', 'keydown']);
624
625         var view = this.getView();
626         view.init(this);
627         view.render();
628         this.getSelectionModel().init(this);
629     },
630
631     // private
632     initEvents : function(){
633         Ext.grid.GridPanel.superclass.initEvents.call(this);
634
635         if(this.loadMask){
636             this.loadMask = new Ext.LoadMask(this.bwrap,
637                     Ext.apply({store:this.store}, this.loadMask));
638         }
639     },
640
641     initStateEvents : function(){
642         Ext.grid.GridPanel.superclass.initStateEvents.call(this);
643         this.mon(this.colModel, 'hiddenchange', this.saveState, this, {delay: 100});
644     },
645
646     applyState : function(state){
647         var cm = this.colModel,
648             cs = state.columns,
649             store = this.store,
650             s,
651             c,
652             oldIndex;
653
654         if(cs){
655             for(var i = 0, len = cs.length; i < len; i++){
656                 s = cs[i];
657                 c = cm.getColumnById(s.id);
658                 if(c){
659                     c.hidden = s.hidden;
660                     c.width = s.width;
661                     oldIndex = cm.getIndexById(s.id);
662                     if(oldIndex != i){
663                         cm.moveColumn(oldIndex, i);
664                     }
665                 }
666             }
667         }
668         if(store){
669             s = state.sort;
670             if(s){
671                 store[store.remoteSort ? 'setDefaultSort' : 'sort'](s.field, s.direction);
672             }
673             s = state.group;
674             if(store.groupBy){
675                 if(s){
676                     store.groupBy(s);
677                 }else{
678                     store.clearGrouping();
679                 }
680             }
681
682         }
683         var o = Ext.apply({}, state);
684         delete o.columns;
685         delete o.sort;
686         Ext.grid.GridPanel.superclass.applyState.call(this, o);
687     },
688
689     getState : function(){
690         var o = {columns: []},
691             store = this.store,
692             ss,
693             gs;
694
695         for(var i = 0, c; (c = this.colModel.config[i]); i++){
696             o.columns[i] = {
697                 id: c.id,
698                 width: c.width
699             };
700             if(c.hidden){
701                 o.columns[i].hidden = true;
702             }
703         }
704         if(store){
705             ss = store.getSortState();
706             if(ss){
707                 o.sort = ss;
708             }
709             if(store.getGroupState){
710                 gs = store.getGroupState();
711                 if(gs){
712                     o.group = gs;
713                 }
714             }
715         }
716         return o;
717     },
718
719     // private
720     afterRender : function(){
721         Ext.grid.GridPanel.superclass.afterRender.call(this);
722         var v = this.view;
723         this.on('bodyresize', v.layout, v);
724         v.layout();
725         if(this.deferRowRender){
726             if (!this.deferRowRenderTask){
727                 this.deferRowRenderTask = new Ext.util.DelayedTask(v.afterRender, this.view);
728             }
729             this.deferRowRenderTask.delay(10);
730         }else{
731             v.afterRender();
732         }
733         this.viewReady = true;
734     },
735
736     /**
737      * <p>Reconfigures the grid to use a different Store and Column Model
738      * and fires the 'reconfigure' event. The View will be bound to the new
739      * objects and refreshed.</p>
740      * <p>Be aware that upon reconfiguring a GridPanel, certain existing settings <i>may</i> become
741      * invalidated. For example the configured {@link #autoExpandColumn} may no longer exist in the
742      * new ColumnModel. Also, an existing {@link Ext.PagingToolbar PagingToolbar} will still be bound
743      * to the old Store, and will need rebinding. Any {@link #plugins} might also need reconfiguring
744      * with the new data.</p>
745      * @param {Ext.data.Store} store The new {@link Ext.data.Store} object
746      * @param {Ext.grid.ColumnModel} colModel The new {@link Ext.grid.ColumnModel} object
747      */
748     reconfigure : function(store, colModel){
749         var rendered = this.rendered;
750         if(rendered){
751             if(this.loadMask){
752                 this.loadMask.destroy();
753                 this.loadMask = new Ext.LoadMask(this.bwrap,
754                         Ext.apply({}, {store:store}, this.initialConfig.loadMask));
755             }
756         }
757         if(this.view){
758             this.view.initData(store, colModel);
759         }
760         this.store = store;
761         this.colModel = colModel;
762         if(rendered){
763             this.view.refresh(true);
764         }
765         this.fireEvent('reconfigure', this, store, colModel);
766     },
767
768     // private
769     onDestroy : function(){
770         if (this.deferRowRenderTask && this.deferRowRenderTask.cancel){
771             this.deferRowRenderTask.cancel();
772         }
773         if(this.rendered){
774             Ext.destroy(this.view, this.loadMask);
775         }else if(this.store && this.store.autoDestroy){
776             this.store.destroy();
777         }
778         Ext.destroy(this.colModel, this.selModel);
779         this.store = this.selModel = this.colModel = this.view = this.loadMask = null;
780         Ext.grid.GridPanel.superclass.onDestroy.call(this);
781     },
782
783     // private
784     processEvent : function(name, e){
785         this.view.processEvent(name, e);
786     },
787
788     // private
789     onClick : function(e){
790         this.processEvent('click', e);
791     },
792
793     // private
794     onMouseDown : function(e){
795         this.processEvent('mousedown', e);
796     },
797
798     // private
799     onContextMenu : function(e, t){
800         this.processEvent('contextmenu', e);
801     },
802
803     // private
804     onDblClick : function(e){
805         this.processEvent('dblclick', e);
806     },
807
808     // private
809     walkCells : function(row, col, step, fn, scope){
810         var cm    = this.colModel,
811             clen  = cm.getColumnCount(),
812             ds    = this.store,
813             rlen  = ds.getCount(),
814             first = true;
815
816         if(step < 0){
817             if(col < 0){
818                 row--;
819                 first = false;
820             }
821             while(row >= 0){
822                 if(!first){
823                     col = clen-1;
824                 }
825                 first = false;
826                 while(col >= 0){
827                     if(fn.call(scope || this, row, col, cm) === true){
828                         return [row, col];
829                     }
830                     col--;
831                 }
832                 row--;
833             }
834         } else {
835             if(col >= clen){
836                 row++;
837                 first = false;
838             }
839             while(row < rlen){
840                 if(!first){
841                     col = 0;
842                 }
843                 first = false;
844                 while(col < clen){
845                     if(fn.call(scope || this, row, col, cm) === true){
846                         return [row, col];
847                     }
848                     col++;
849                 }
850                 row++;
851             }
852         }
853         return null;
854     },
855
856     /**
857      * Returns the grid's underlying element.
858      * @return {Element} The element
859      */
860     getGridEl : function(){
861         return this.body;
862     },
863
864     // private for compatibility, overridden by editor grid
865     stopEditing : Ext.emptyFn,
866
867     /**
868      * Returns the grid's selection model configured by the <code>{@link #selModel}</code>
869      * configuration option. If no selection model was configured, this will create
870      * and return a {@link Ext.grid.RowSelectionModel RowSelectionModel}.
871      * @return {SelectionModel}
872      */
873     getSelectionModel : function(){
874         if(!this.selModel){
875             this.selModel = new Ext.grid.RowSelectionModel(
876                     this.disableSelection ? {selectRow: Ext.emptyFn} : null);
877         }
878         return this.selModel;
879     },
880
881     /**
882      * Returns the grid's data store.
883      * @return {Ext.data.Store} The store
884      */
885     getStore : function(){
886         return this.store;
887     },
888
889     /**
890      * Returns the grid's ColumnModel.
891      * @return {Ext.grid.ColumnModel} The column model
892      */
893     getColumnModel : function(){
894         return this.colModel;
895     },
896
897     /**
898      * Returns the grid's GridView object.
899      * @return {Ext.grid.GridView} The grid view
900      */
901     getView : function(){
902         if(!this.view){
903             this.view = new Ext.grid.GridView(this.viewConfig);
904         }
905         return this.view;
906     },
907     /**
908      * Called to get grid's drag proxy text, by default returns this.ddText.
909      * @return {String} The text
910      */
911     getDragDropText : function(){
912         var count = this.selModel.getCount();
913         return String.format(this.ddText, count, count == 1 ? '' : 's');
914     }
915
916     /**
917      * @cfg {String/Number} activeItem
918      * @hide
919      */
920     /**
921      * @cfg {Boolean} autoDestroy
922      * @hide
923      */
924     /**
925      * @cfg {Object/String/Function} autoLoad
926      * @hide
927      */
928     /**
929      * @cfg {Boolean} autoWidth
930      * @hide
931      */
932     /**
933      * @cfg {Boolean/Number} bufferResize
934      * @hide
935      */
936     /**
937      * @cfg {String} defaultType
938      * @hide
939      */
940     /**
941      * @cfg {Object} defaults
942      * @hide
943      */
944     /**
945      * @cfg {Boolean} hideBorders
946      * @hide
947      */
948     /**
949      * @cfg {Mixed} items
950      * @hide
951      */
952     /**
953      * @cfg {String} layout
954      * @hide
955      */
956     /**
957      * @cfg {Object} layoutConfig
958      * @hide
959      */
960     /**
961      * @cfg {Boolean} monitorResize
962      * @hide
963      */
964     /**
965      * @property items
966      * @hide
967      */
968     /**
969      * @method add
970      * @hide
971      */
972     /**
973      * @method cascade
974      * @hide
975      */
976     /**
977      * @method doLayout
978      * @hide
979      */
980     /**
981      * @method find
982      * @hide
983      */
984     /**
985      * @method findBy
986      * @hide
987      */
988     /**
989      * @method findById
990      * @hide
991      */
992     /**
993      * @method findByType
994      * @hide
995      */
996     /**
997      * @method getComponent
998      * @hide
999      */
1000     /**
1001      * @method getLayout
1002      * @hide
1003      */
1004     /**
1005      * @method getUpdater
1006      * @hide
1007      */
1008     /**
1009      * @method insert
1010      * @hide
1011      */
1012     /**
1013      * @method load
1014      * @hide
1015      */
1016     /**
1017      * @method remove
1018      * @hide
1019      */
1020     /**
1021      * @event add
1022      * @hide
1023      */
1024     /**
1025      * @event afterlayout
1026      * @hide
1027      */
1028     /**
1029      * @event beforeadd
1030      * @hide
1031      */
1032     /**
1033      * @event beforeremove
1034      * @hide
1035      */
1036     /**
1037      * @event remove
1038      * @hide
1039      */
1040
1041
1042
1043     /**
1044      * @cfg {String} allowDomMove  @hide
1045      */
1046     /**
1047      * @cfg {String} autoEl @hide
1048      */
1049     /**
1050      * @cfg {String} applyTo  @hide
1051      */
1052     /**
1053      * @cfg {String} autoScroll  @hide
1054      */
1055     /**
1056      * @cfg {String} bodyBorder  @hide
1057      */
1058     /**
1059      * @cfg {String} bodyStyle  @hide
1060      */
1061     /**
1062      * @cfg {String} contentEl  @hide
1063      */
1064     /**
1065      * @cfg {String} disabledClass  @hide
1066      */
1067     /**
1068      * @cfg {String} elements  @hide
1069      */
1070     /**
1071      * @cfg {String} html  @hide
1072      */
1073     /**
1074      * @cfg {Boolean} preventBodyReset
1075      * @hide
1076      */
1077     /**
1078      * @property disabled
1079      * @hide
1080      */
1081     /**
1082      * @method applyToMarkup
1083      * @hide
1084      */
1085     /**
1086      * @method enable
1087      * @hide
1088      */
1089     /**
1090      * @method disable
1091      * @hide
1092      */
1093     /**
1094      * @method setDisabled
1095      * @hide
1096      */
1097 });
1098 Ext.reg('grid', Ext.grid.GridPanel);