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