/**
* @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);
}
});