Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / grid / ColumnLayout.js
index cfa5a69..749aefc 100644 (file)
@@ -1,3 +1,17 @@
+/*
+
+This file is part of Ext JS 4
+
+Copyright (c) 2011 Sencha Inc
+
+Contact:  http://www.sencha.com/contact
+
+GNU General Public License Usage
+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.
+
+If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
+
+*/
 /**
  * @class Ext.grid.ColumnLayout
  * @extends Ext.layout.container.HBox
  *
  * <p>This class is used only by the grid's HeaderContainer docked child.</p>
  *
- * <p>This class adds the ability to shrink the vertical size of the inner container element back if a grouped
+ * <p>It adds the ability to shrink the vertical size of the inner container element back if a grouped
  * column header has all its child columns dragged out, and the whole HeaderContainer needs to shrink back down.</p>
  *
- * <p>It also enforces the grid's HeaderContainer's forceFit config by, after every calaculateChildBoxes call, converting
- * all pixel widths into flex values, so that propertions are maintained upon width change of the grid.</p>
- *
  * <p>Also, after every layout, after all headers have attained their 'stretchmax' height, it goes through and calls
- * <code>setPadding</code> on the columns so that they lay out correctly. TODO: implement a ColumnHeader component
- * layout which takes responsibility for this, and will run upon resize.</p>
+ * <code>setPadding</code> on the columns so that they lay out correctly.</p>
  */
 Ext.define('Ext.grid.ColumnLayout', {
     extend: 'Ext.layout.container.HBox',
     alias: 'layout.gridcolumn',
     type : 'column',
 
-    // Height-stretched innerCt must be able to revert back to unstretched height
-    clearInnerCtOnLayout: false,
+    reserveOffset: false,
 
-    constructor: function() {
-        var me = this;
-        me.callParent(arguments);
-        if (!Ext.isDefined(me.availableSpaceOffset)) {
-            me.availableSpaceOffset = (Ext.getScrollBarWidth() - 2);
-        }
-    },
+    shrinkToFit: false,
+
+    // Height-stretched innerCt must be able to revert back to unstretched height
+    clearInnerCtOnLayout: true,
 
     beforeLayout: function() {
         var me = this,
             i = 0,
             items = me.getLayoutItems(),
             len = items.length,
-            item, returnValue;
+            item, returnValue,
+            s;
+
+        // Scrollbar offset defined by width of any vertical scroller in the owning grid
+        if (!Ext.isDefined(me.availableSpaceOffset)) {
+            s = me.owner.up('tablepanel').verticalScroller;
+            me.availableSpaceOffset = s ? s.width-1 : 0;
+        }
 
         returnValue = me.callParent(arguments);
 
@@ -44,19 +57,17 @@ Ext.define('Ext.grid.ColumnLayout', {
         me.innerCt.setHeight(23);
 
         // Unstretch child items before the layout which stretches them.
-        if (me.align == 'stretchmax') {
-            for (; i < len; i++) {
-                item = items[i];
-                item.el.setStyle({
-                    height: 'auto'
-                });
-                item.titleContainer.setStyle({
-                    height: 'auto',
-                    paddingTop: '0'
-                });
-                if (item.componentLayout && item.componentLayout.lastComponentSize) {
-                    item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
-                }
+        for (; i < len; i++) {
+            item = items[i];
+            item.el.setStyle({
+                height: 'auto'
+            });
+            item.titleContainer.setStyle({
+                height: 'auto',
+                paddingTop: '0'
+            });
+            if (item.componentLayout && item.componentLayout.lastComponentSize) {
+                item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
             }
         }
         return returnValue;
@@ -70,7 +81,7 @@ Ext.define('Ext.grid.ColumnLayout', {
             metaData = calculations.meta,
             len = boxes.length, i = 0, box, item;
 
-        if (targetSize.width && !me.isColumn) {
+        if (targetSize.width && !me.isHeader) {
             // If configured forceFit then all columns will be flexed
             if (me.owner.forceFit) {
 
@@ -99,16 +110,84 @@ Ext.define('Ext.grid.ColumnLayout', {
 
     afterLayout: function() {
         var me = this,
+            owner = me.owner,
+            topGrid,
+            bothHeaderCts,
+            otherHeaderCt,
+            thisHeight,
+            otherHeight,
+            modifiedGrid,
             i = 0,
-            items = me.getLayoutItems(),
-            len = items.length;
+            items,
+            len,
+            headerHeight;
 
         me.callParent(arguments);
 
         // Set up padding in items
-        if (me.align == 'stretchmax') {
+        if (!me.owner.hideHeaders) {
+
+            // If this is one HeaderContainer of a pair in a side-by-side locking view, then find the height
+            // of the highest one, and sync the other one to that height.
+            if (owner.lockableInjected) {
+                topGrid = owner.up('tablepanel').up('tablepanel');
+                bothHeaderCts = topGrid.query('headercontainer:not([isHeader])');
+                otherHeaderCt = (bothHeaderCts[0] === owner) ? bothHeaderCts[1] : bothHeaderCts[0];
+
+                // Both sides must be rendered for this syncing operation to work.
+                if (!otherHeaderCt.rendered) {
+                    return;
+                }
+
+                // Get the height of the highest of both HeaderContainers
+                otherHeight = otherHeaderCt.layout.getRenderTarget().getViewSize().height;
+                if (!otherHeight) {
+                    return;
+                }
+                thisHeight = this.getRenderTarget().getViewSize().height;
+                if (!thisHeight) {
+                    return;
+                }
+
+                // Prevent recursion back into here when the "other" grid, after adjusting to the new hight of its headerCt, attempts to inform its ownerCt
+                // Block the upward notification by flagging the top grid's component layout as busy.
+                topGrid.componentLayout.layoutBusy = true;
+
+                // Assume that the correct header height is the height of this HeaderContainer
+                headerHeight = thisHeight;
+
+                // Synch the height of the smaller HeaderContainer to the height of the highest one.
+                if (thisHeight > otherHeight) {
+                    otherHeaderCt.layout.align = 'stretch';
+                    otherHeaderCt.setCalculatedSize(otherHeaderCt.getWidth(), owner.getHeight(), otherHeaderCt.ownerCt);
+                    delete otherHeaderCt.layout.align;
+                    modifiedGrid = otherHeaderCt.up('tablepanel');
+                } else if (otherHeight > thisHeight) {
+                    headerHeight = otherHeight;
+                    this.align = 'stretch';
+                    owner.setCalculatedSize(owner.getWidth(), otherHeaderCt.getHeight(), owner.ownerCt);
+                    delete this.align;
+                    modifiedGrid = owner.up('tablepanel');
+                }
+                topGrid.componentLayout.layoutBusy = false;
+
+                // Gather all Header items across both Grids.
+                items = bothHeaderCts[0].layout.getLayoutItems().concat(bothHeaderCts[1].layout.getLayoutItems());
+            } else {
+                headerHeight = this.getRenderTarget().getViewSize().height;
+                items = me.getLayoutItems();
+            }
+
+            len = items.length;
             for (; i < len; i++) {
-                items[i].setPadding();
+                items[i].setPadding(headerHeight);
+            }
+
+            // Size the View within the grid which has had its HeaderContainer entallened (That's a perfectly cromulent word BTW)
+            if (modifiedGrid) {
+                setTimeout(function() {
+                    modifiedGrid.doLayout();
+                }, 1);
             }
         }
     },
@@ -116,26 +195,21 @@ Ext.define('Ext.grid.ColumnLayout', {
     // FIX: when flexing we actually don't have enough space as we would
     // typically because of the scrollOffset on the GridView, must reserve this
     updateInnerCtSize: function(tSize, calcs) {
-        var me    = this,
-            extra = 0;
+        var me = this,
+            extra;
 
         // Columns must not account for scroll offset
-        if (!me.isColumn && calcs.meta.tooNarrow) {
-            if (
-                Ext.isWebKit ||
-                Ext.isGecko ||
-                (Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7 || Ext.isIE8))
-            ) {
-                extra = 1;
-            // IE6-8 not quirks
-            } else if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
-                extra = 2;
+        if (!me.isHeader) {
+            me.tooNarrow = calcs.meta.tooNarrow;
+            extra = (me.reserveOffset ? me.availableSpaceOffset : 0);
+
+            if (calcs.meta.tooNarrow) {
+                tSize.width = calcs.meta.desiredSize + extra;
+            } else {
+                tSize.width += extra;
             }
-            
-            // this is the 1px accounted for in the Scroller when subtracting 1px.
-            extra++;
-            tSize.width = calcs.meta.desiredSize + (me.reserveOffset ? me.availableSpaceOffset : 0) + extra;
         }
+
         return me.callParent(arguments);
     },
 
@@ -145,4 +219,4 @@ Ext.define('Ext.grid.ColumnLayout', {
             ownerCt.doComponentLayout();
         }
     }
-});
\ No newline at end of file
+});