/** * @private * * This class is used only by the grid's HeaderContainer docked child. * * 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. * * Also, after every layout, after all headers have attained their 'stretchmax' height, it goes through and calls * `setPadding` on the columns so that they lay out correctly. */ Ext.define('Ext.grid.ColumnLayout', { extend: 'Ext.layout.container.HBox', alias: 'layout.gridcolumn', type : 'gridcolumn', reserveOffset: false, firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first', lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last', initLayout: function() { this.grid = this.owner.up('[scrollerOwner]'); this.callParent(); }, // Collect the height of the table of data upon layout begin beginLayout: function (ownerContext) { var me = this, grid = me.grid, view = grid.view, i = 0, items = me.getVisibleItems(), len = items.length, item; ownerContext.gridContext = ownerContext.context.getCmp(me.grid); // If we are one side of a locking grid, then if we are on the "normal" side, we have to grab the normal view // for use in determining whether to subtract scrollbar width from available width. // The locked side does not have scrollbars, so it should not look at the view. if (grid.lockable) { if (me.owner.up('tablepanel') === view.normalGrid) { view = view.normalGrid.getView(); } else { view = null; } } me.callParent(arguments); // Unstretch child items before the layout which stretches them. for (; i < len; i++) { item = items[i]; item.removeCls([me.firstHeaderCls, me.lastHeaderCls]); item.el.setStyle({ height: 'auto' }); item.titleEl.setStyle({ height: 'auto', paddingTop: '' // reset back to default padding of the style }); } // Add special first/last classes if (len > 0) { items[0].addCls(me.firstHeaderCls); items[len - 1].addCls(me.lastHeaderCls); } // If the owner is the grid's HeaderContainer, and the UI displays old fashioned scrollbars and there is a rendered View with data in it, // AND we are scrolling vertically: // collect the View context to interrogate it for overflow, and possibly invalidate it if there is overflow if (!me.owner.isHeader && Ext.getScrollbarSize().width && !grid.collapsed && view && view.table.dom && (view.autoScroll || view.overflowY)) { ownerContext.viewContext = ownerContext.context.getCmp(view); } }, roundFlex: function(width) { return Math.floor(width); }, calculate: function(ownerContext) { var me = this, viewContext = ownerContext.viewContext, tableHeight, viewHeight; me.callParent(arguments); if (ownerContext.state.parallelDone) { ownerContext.setProp('columnWidthsDone', true); } // If we have a viewContext (Only created if there is an existing within the view, AND we are scolling vertically AND scrollbars take up space) // we are not already in the second pass, and we are not shrinkWrapping... // Then we have to see if we know enough to determine whether there is vertical opverflow so that we can // invalidate and loop back for the second pass with a narrower target width. if (viewContext && !ownerContext.state.overflowAdjust.width && !ownerContext.gridContext.heightModel.shrinkWrap) { tableHeight = viewContext.tableContext.getProp('height'); viewHeight = viewContext.getProp('height'); // Heights of both view and its table content have not both been published; we cannot complete if (isNaN(tableHeight + viewHeight)) { me.done = false; } // Heights have been published, and there is vertical overflow; invalidate with a width adjustment to allow for the scrollbar else if (tableHeight >= viewHeight) { ownerContext.gridContext.invalidate({ after: function() { ownerContext.state.overflowAdjust = { width: Ext.getScrollbarSize().width, height: 0 }; } }); } } }, completeLayout: function(ownerContext) { var me = this, owner = me.owner, state = ownerContext.state, needsInvalidate = false, calculated = me.sizeModels.calculated, childItems, len, i, childContext, item; me.callParent(arguments); // If we have not been through this already, and the owning Container is configured // forceFit, is not a group column and and there is a valid width, then convert // widths to flexes, and loop back. if (!state.flexesCalculated && owner.forceFit && !owner.isHeader) { childItems = ownerContext.childItems; len = childItems.length; for (i = 0; i < len; i++) { childContext = childItems[i]; item = childContext.target; // For forceFit, just use allocated width as the flex value, and the proportions // will end up the same whatever HeaderContainer width they are being forced into. if (item.width) { item.flex = ownerContext.childItems[i].flex = item.width; delete item.width; childContext.widthModel = calculated; needsInvalidate = true; } } // Recalculate based upon all columns now being flexed instead of sized. // Set flag, so that we do not do this infinitely if (needsInvalidate) { me.cacheFlexes(ownerContext); ownerContext.invalidate({ state: { flexesCalculated: true } }); } } }, finalizeLayout: function() { var me = this, i = 0, items, len, itemsHeight, owner = me.owner, titleEl = owner.titleEl; // Set up padding in items items = me.getVisibleItems(); len = items.length; // header container's items take up the whole height itemsHeight = owner.el.getViewSize().height; if (titleEl) { // if owner is a grouped column with children, we need to subtract the titleEl's height // to determine the remaining available height for the child items itemsHeight -= titleEl.getHeight(); } for (; i < len; i++) { items[i].setPadding(itemsHeight); } }, // FIX: when flexing we actually don't have enough space as we would // typically because of the scrollOffset on the GridView, must reserve this publishInnerCtSize: function(ownerContext) { var me = this, size = ownerContext.state.boxPlan.targetSize, cw = ownerContext.peek('contentWidth'), view; // InnerCt MUST stretch to accommodate all columns so that left/right scrolling is enabled in the header container. if ((cw != null) && !me.owner.isHeader) { size.width = cw; // innerCt must also encompass any vertical scrollbar width if there may be one view = me.owner.ownerCt.view; if (view.autoScroll || view.overflowY) { size.width += Ext.getScrollbarSize().width; } } return me.callParent(arguments); } });