Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / src / grid / ColumnLayout.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.grid.ColumnLayout
17  * @extends Ext.layout.container.HBox
18  * @private
19  *
20  * <p>This class is used only by the grid's HeaderContainer docked child.</p>
21  *
22  * <p>This class adds the ability to shrink the vertical size of the inner container element back if a grouped
23  * column header has all its child columns dragged out, and the whole HeaderContainer needs to shrink back down.</p>
24  *
25  * <p>It also enforces the grid's HeaderContainer's forceFit config by, after every calaculateChildBoxes call, converting
26  * all pixel widths into flex values, so that propertions are maintained upon width change of the grid.</p>
27  *
28  * <p>Also, after every layout, after all headers have attained their 'stretchmax' height, it goes through and calls
29  * <code>setPadding</code> on the columns so that they lay out correctly. TODO: implement a ColumnHeader component
30  * layout which takes responsibility for this, and will run upon resize.</p>
31  */
32 Ext.define('Ext.grid.ColumnLayout', {
33     extend: 'Ext.layout.container.HBox',
34     alias: 'layout.gridcolumn',
35     type : 'column',
36
37     reserveOffset: false,
38
39     // Height-stretched innerCt must be able to revert back to unstretched height
40     clearInnerCtOnLayout: false,
41
42     beforeLayout: function() {
43         var me = this,
44             i = 0,
45             items = me.getLayoutItems(),
46             len = items.length,
47             item, returnValue,
48             s;
49
50         // Scrollbar offset defined by width of any vertical scroller in the owning grid
51         if (!Ext.isDefined(me.availableSpaceOffset)) {
52             s = me.owner.up('tablepanel').verticalScroller;
53             me.availableSpaceOffset = s ? s.width-1 : 0;
54         }
55
56         returnValue = me.callParent(arguments);
57
58         // Size to a sane minimum height before possibly being stretched to accommodate grouped headers
59         me.innerCt.setHeight(23);
60
61         // Unstretch child items before the layout which stretches them.
62         if (me.align == 'stretchmax') {
63             for (; i < len; i++) {
64                 item = items[i];
65                 item.el.setStyle({
66                     height: 'auto'
67                 });
68                 item.titleContainer.setStyle({
69                     height: 'auto',
70                     paddingTop: '0'
71                 });
72                 if (item.componentLayout && item.componentLayout.lastComponentSize) {
73                     item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
74                 }
75             }
76         }
77         return returnValue;
78     },
79
80     // Override to enforce the forceFit config.
81     calculateChildBoxes: function(visibleItems, targetSize) {
82         var me = this,
83             calculations = me.callParent(arguments),
84             boxes = calculations.boxes,
85             metaData = calculations.meta,
86             len = boxes.length, i = 0, box, item;
87
88         if (targetSize.width && !me.isColumn) {
89             // If configured forceFit then all columns will be flexed
90             if (me.owner.forceFit) {
91
92                 for (; i < len; i++) {
93                     box = boxes[i];
94                     item = box.component;
95
96                     // Set a sane minWidth for the Box layout to be able to squeeze flexed Headers down to.
97                     item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
98
99                     // For forceFit, just use allocated width as the flex value, and the proportions
100                     // will end up the same whatever HeaderContainer width they are being forced into.
101                     item.flex = box.width;
102                 }
103
104                 // Recalculate based upon all columns now being flexed instead of sized.
105                 calculations = me.callParent(arguments);
106             }
107             else if (metaData.tooNarrow) {
108                 targetSize.width = metaData.desiredSize;
109             }
110         }
111
112         return calculations;
113     },
114
115     afterLayout: function() {
116         var me = this,
117             i = 0,
118             items = me.getLayoutItems(),
119             len = items.length;
120
121         me.callParent(arguments);
122
123         // Set up padding in items
124         if (!me.owner.hideHeaders && me.align == 'stretchmax') {
125             for (; i < len; i++) {
126                 items[i].setPadding();
127             }
128         }
129     },
130
131     // FIX: when flexing we actually don't have enough space as we would
132     // typically because of the scrollOffset on the GridView, must reserve this
133     updateInnerCtSize: function(tSize, calcs) {
134         var me = this,
135             extra;
136
137         // Columns must not account for scroll offset
138         if (!me.isColumn) {
139             me.tooNarrow = calcs.meta.tooNarrow;
140             extra = (me.reserveOffset ? me.availableSpaceOffset : 0);
141
142             if (calcs.meta.tooNarrow) {
143                 tSize.width = calcs.meta.desiredSize + extra;
144             } else {
145                 tSize.width += extra;
146             }
147         }
148
149         return me.callParent(arguments);
150     },
151
152     doOwnerCtLayouts: function() {
153         var ownerCt = this.owner.ownerCt;
154         if (!ownerCt.componentLayout.layoutBusy) {
155             ownerCt.doComponentLayout();
156         }
157     }
158 });