/*! * Ext JS Library 3.2.1 * Copyright(c) 2006-2010 Ext JS, Inc. * licensing@extjs.com * http://www.extjs.com/license */ /** * @class Ext.layout.BoxLayout * @extends Ext.layout.ContainerLayout *Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.
*/ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, { /** * @cfg {Object} defaultMargins *If the individual contained items do not have a margins * property specified, the default margins from this property will be * applied to each item.
*This property may be specified as an object containing margins * to apply in the format:
*{ top: (top margin), right: (right margin), bottom: (bottom margin), left: (left margin) }
This property may also be specified as a string containing * space-separated, numeric margin values. The order of the sides associated * with each value matches the way CSS processes margin values:
***
- If there is only one value, it applies to all sides.
*- If there are two values, the top and bottom borders are set to the * first value and the right and left are set to the second.
*- If there are three values, the top is set to the first value, the left * and right are set to the second, and the bottom is set to the third.
*- If there are four values, they apply to the top, right, bottom, and * left, respectively.
*Defaults to:
*/ defaultMargins : {left:0,top:0,right:0,bottom:0}, /** * @cfg {String} padding ** {top:0, right:0, bottom:0, left:0} *
Sets the padding to be applied to all child items managed by this layout.
*This property must be specified as a string containing * space-separated, numeric padding values. The order of the sides associated * with each value matches the way CSS processes padding values:
***
- If there is only one value, it applies to all sides.
*- If there are two values, the top and bottom borders are set to the * first value and the right and left are set to the second.
*- If there are three values, the top is set to the first value, the left * and right are set to the second, and the bottom is set to the third.
*- If there are four values, they apply to the top, right, bottom, and * left, respectively.
*Defaults to:
*/ padding : '0', // documented in subclasses pack : 'start', // private monitorResize : true, type: 'box', scrollOffset : 0, extraCls : 'x-box-item', targetCls : 'x-box-layout-ct', innerCls : 'x-box-inner', constructor : function(config){ Ext.layout.BoxLayout.superclass.constructor.call(this, config); if (Ext.isString(this.defaultMargins)) { this.defaultMargins = this.parseMargins(this.defaultMargins); } }, /** * @private * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values * when laying out */ onLayout: function(container, target) { Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target); var items = this.getVisibleItems(container), tSize = this.getLayoutTargetSize(); /** * @private * @property layoutTargetLastSize * @type Object * Private cache of the last measured size of the layout target. This should never be used except by * BoxLayout subclasses during their onLayout run. */ this.layoutTargetLastSize = tSize; /** * @private * @property childBoxCache * @type Array * Array of the last calculated height, width, top and left positions of each visible rendered component * within the Box layout. */ this.childBoxCache = this.calculateChildBoxes(items, tSize); this.updateInnerCtSize(tSize, this.childBoxCache); this.updateChildBoxes(this.childBoxCache.boxes); // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary. this.handleTargetOverflow(tSize, container, target); }, /** * Resizes and repositions each child component * @param {Array} boxes The box measurements */ updateChildBoxes: function(boxes) { for (var i = 0, length = boxes.length; i < length; i++) { var box = boxes[i], comp = box.component; if (box.dirtySize) { comp.setSize(box.width, box.height); } // Don't set positions to NaN if (isNaN(box.left) || isNaN(box.top)) { continue; } comp.setPosition(box.left, box.top); } }, /** * @private * Called by onRender just before the child components are sized and positioned. This resizes the innerCt * to make sure all child items fit within it. We call this before sizing the children because if our child * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them * again immediately afterwards, giving a performance hit. * Subclasses should provide an implementation. * @param {Object} currentSize The current height and width of the innerCt * @param {Array} calculations The new box calculations of all items to be laid out */ updateInnerCtSize: Ext.emptyFn, /** * @private * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden', * we need to lay out a second time because the scrollbars may have modified the height and width of the layout * target. Having a Box layout inside such a target is therefore not recommended. * @param {Object} previousTargetSize The size and height of the layout target before we just laid out * @param {Ext.Container} container The container * @param {Ext.Element} target The target element */ handleTargetOverflow: function(previousTargetSize, container, target) { var overflow = target.getStyle('overflow'); if (overflow && overflow != 'hidden' &&!this.adjustmentPass) { var newTargetSize = this.getLayoutTargetSize(); if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){ this.adjustmentPass = true; this.onLayout(container, target); } } delete this.adjustmentPass; }, // private isValidParent : function(c, target){ return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom; }, /** * @private * Returns all items that are both rendered and visible * @return {Array} All matching items */ getVisibleItems: function(ct) { var ct = ct || this.container, t = ct.getLayoutTarget(), cti = ct.items.items, len = cti.length, i, c, items = []; for (i = 0; i < len; i++) { if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true){ items.push(c); } } return items; }, // private renderAll : function(ct, target){ if(!this.innerCt){ // the innerCt prevents wrapping and shuffling while // the container is resizing this.innerCt = target.createChild({cls:this.innerCls}); this.padding = this.parseMargins(this.padding); } Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt); }, getLayoutTargetSize : function(){ var target = this.container.getLayoutTarget(), ret; if (target) { ret = target.getViewSize(); // IE in strict mode will return a width of 0 on the 1st pass of getViewSize. // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly // with getViewSize if (Ext.isIE && Ext.isStrict && ret.width == 0){ ret = target.getStyleSize(); } ret.width -= target.getPadding('lr'); ret.height -= target.getPadding('tb'); } return ret; }, // private renderItem : function(c){ if(Ext.isString(c.margins)){ c.margins = this.parseMargins(c.margins); }else if(!c.margins){ c.margins = this.defaultMargins; } Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments); } }); /** * @class Ext.layout.VBoxLayout * @extends Ext.layout.BoxLayout *"0"
A layout that arranges items vertically down a Container. This layout optionally divides available vertical * space between child items containing a numeric
* This layout may also be used to set the widths of child items by configuring it with the {@link #align} option. */ Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, { /** * @cfg {String} align * Controls how the child items of the container are aligned. Acceptable configuration values for this * property are: *flex
configuration.*/ align : 'left', // left, center, stretch, strechmax type: 'vbox', /** * @cfg {String} pack * Controls how the child items of the container are packed together. Acceptable configuration values * for this property are: **
- left : Default
*child items are aligned horizontally * at the left side of the container- center :
*child items are aligned horizontally at the * mid-width of the container- stretch :
*child items are stretched horizontally to fill * the width of the container- stretchmax :
*child items are stretched horizontally to * the size of the largest item.*/ /** * @cfg {Number} flex * This configuation option is to be applied to child items of the container managed * by this layout. Each child item with a flex property will be flexed vertically * according to each item's relative flex value compared to the sum of all items with * a flex value specified. Any child items that have either a flex = 0 or * flex = undefined will not be 'flexed' (the initial size will not be changed). */ /** * @private * See parent documentation */ updateInnerCtSize: function(tSize, calcs) { var innerCtHeight = tSize.height, innerCtWidth = calcs.meta.maxWidth + this.padding.left + this.padding.right; if (this.align == 'stretch') { innerCtWidth = tSize.width; } else if (this.align == 'center') { innerCtWidth = Math.max(tSize.width, innerCtWidth); } //we set the innerCt size first because if our child items are larger than the previous innerCt size //the browser will insert scrollbars and then remove them again immediately afterwards this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined); }, /** * @private * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered, * visible items and returns a height, width, top and left for each, as well as a reference to each. Also * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt. * @param {Array} visibleItems The array of all rendered, visible items to be calculated for * @param {Object} targetSize Object containing target size and height * @return {Object} Object containing box measurements for each child, plus meta data */ calculateChildBoxes: function(visibleItems, targetSize) { var visibleCount = visibleItems.length, padding = this.padding, topOffset = padding.top, leftOffset = padding.left, paddingVert = topOffset + padding.bottom, paddingHoriz = leftOffset + padding.right, width = targetSize.width - this.scrollOffset, height = targetSize.height, availWidth = Math.max(0, width - paddingHoriz), isStart = this.pack == 'start', isCenter = this.pack == 'center', isEnd = this.pack == 'end', nonFlexHeight= 0, maxWidth = 0, totalFlex = 0, //used to cache the calculated size and position values for each child item boxes = [], //used in the for loops below, just declared here for brevity child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth; //gather the total flex of all flexed items and the width taken up by fixed width items for (i = 0; i < visibleCount; i++) { child = visibleItems[i]; childHeight = child.height; childWidth = child.width; canLayout = !child.hasLayout && Ext.isFunction(child.doLayout); // Static height (numeric) requires no calcs if (!Ext.isNumber(childHeight)) { // flex and not 'auto' height if (child.flex && !childHeight) { totalFlex += child.flex; // Not flexed or 'auto' height or undefined height } else { //Render and layout sub-containers without a flex or width defined, as otherwise we //don't know how wide the sub-container should be and cannot calculate flexed widths if (!childHeight && canLayout) { child.doLayout(); } childSize = child.getSize(); childWidth = childSize.width; childHeight = childSize.height; } } childMargins = child.margins; nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom; // Max width for align - force layout of non-layed out subcontainers without a numeric width if (!Ext.isNumber(childWidth)) { if (canLayout) { child.doLayout(); } childWidth = child.getWidth(); } maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right); //cache the size of each child component boxes.push({ component: child, height : childHeight || undefined, width : childWidth || undefined }); } //the height available to the flexed items var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert)); if (isCenter) { topOffset += availableHeight / 2; } else if (isEnd) { topOffset += availableHeight; } //temporary variables used in the flex height calculations below var remainingHeight = availableHeight, remainingFlex = totalFlex; //calculate the height of each flexed item, and the left + top positions of every item for (i = 0; i < visibleCount; i++) { child = visibleItems[i]; calcs = boxes[i]; childMargins = child.margins; horizMargins = childMargins.left + childMargins.right; topOffset += childMargins.top; if (isStart && child.flex && !child.height) { flexedHeight = Math.ceil((child.flex / remainingFlex) * remainingHeight); remainingHeight -= flexedHeight; remainingFlex -= child.flex; calcs.height = flexedHeight; calcs.dirtySize = true; } calcs.left = leftOffset + childMargins.left; calcs.top = topOffset; switch (this.align) { case 'stretch': stretchWidth = availWidth - horizMargins; calcs.width = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000); calcs.dirtySize = true; break; case 'stretchmax': stretchWidth = maxWidth - horizMargins; calcs.width = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000); calcs.dirtySize = true; break; case 'center': var diff = availWidth - calcs.width - horizMargins; if (diff > 0) { calcs.left = leftOffset + horizMargins + (diff / 2); } } topOffset += calcs.height + childMargins.bottom; } return { boxes: boxes, meta : { maxWidth: maxWidth } }; } }); Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout; /** * @class Ext.layout.HBoxLayout * @extends Ext.layout.BoxLayout **
- start : Default
*child items are packed together at * top side of container- center :
*child items are packed together at * mid-height of container- end :
*child items are packed together at bottom * side of containerA layout that arranges items horizontally across a Container. This layout optionally divides available horizontal * space between child items containing a numeric
* This layout may also be used to set the heights of child items by configuring it with the {@link #align} option. */ Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, { /** * @cfg {String} align * Controls how the child items of the container are aligned. Acceptable configuration values for this * property are: *flex
configuration.*
- top : Default
*child items are aligned vertically * at the top of the container- middle :
*child items are aligned vertically in the * middle of the container- stretch :
*child items are stretched vertically to fill * the height of the container- stretchmax :
*/ align: 'top', // top, middle, stretch, strechmax type : 'hbox', /** * @private * See parent documentation */ updateInnerCtSize: function(tSize, calcs) { var innerCtWidth = tSize.width, innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom; if (this.align == 'stretch') { innerCtHeight = tSize.height; } else if (this.align == 'middle') { innerCtHeight = Math.max(tSize.height, innerCtHeight); } this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined); }, /** * @cfg {String} pack * Controls how the child items of the container are packed together. Acceptable configuration values * for this property are: *child items are stretched vertically to * the height of the largest item.*/ /** * @cfg {Number} flex * This configuation option is to be applied to child items of the container managed * by this layout. Each child item with a flex property will be flexed horizontally * according to each item's relative flex value compared to the sum of all items with * a flex value specified. Any child items that have either a flex = 0 or * flex = undefined will not be 'flexed' (the initial size will not be changed). */ /** * @private * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered, * visible items and returns a height, width, top and left for each, as well as a reference to each. Also * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt. * @param {Array} visibleItems The array of all rendered, visible items to be calculated for * @param {Object} targetSize Object containing target size and height * @return {Object} Object containing box measurements for each child, plus meta data */ calculateChildBoxes: function(visibleItems, targetSize) { var visibleCount = visibleItems.length, padding = this.padding, topOffset = padding.top, leftOffset = padding.left, paddingVert = topOffset + padding.bottom, paddingHoriz = leftOffset + padding.right, width = targetSize.width - this.scrollOffset, height = targetSize.height, availHeight = Math.max(0, height - paddingVert), isStart = this.pack == 'start', isCenter = this.pack == 'center', isEnd = this.pack == 'end', // isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1, nonFlexWidth = 0, maxHeight = 0, totalFlex = 0, //used to cache the calculated size and position values for each child item boxes = [], //used in the for loops below, just declared here for brevity child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight; //gather the total flex of all flexed items and the width taken up by fixed width items for (i = 0; i < visibleCount; i++) { child = visibleItems[i]; childHeight = child.height; childWidth = child.width; canLayout = !child.hasLayout && Ext.isFunction(child.doLayout); // Static width (numeric) requires no calcs if (!Ext.isNumber(childWidth)) { // flex and not 'auto' width if (child.flex && !childWidth) { totalFlex += child.flex; // Not flexed or 'auto' width or undefined width } else { //Render and layout sub-containers without a flex or width defined, as otherwise we //don't know how wide the sub-container should be and cannot calculate flexed widths if (!childWidth && canLayout) { child.doLayout(); } childSize = child.getSize(); childWidth = childSize.width; childHeight = childSize.height; } } childMargins = child.margins; nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right; // Max height for align - force layout of non-layed out subcontainers without a numeric height if (!Ext.isNumber(childHeight)) { if (canLayout) { child.doLayout(); } childHeight = child.getHeight(); } maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom); //cache the size of each child component boxes.push({ component: child, height : childHeight || undefined, width : childWidth || undefined }); } //the width available to the flexed items var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz)); if (isCenter) { leftOffset += availableWidth / 2; } else if (isEnd) { leftOffset += availableWidth; } //temporary variables used in the flex width calculations below var remainingWidth = availableWidth, remainingFlex = totalFlex; //calculate the widths of each flexed item, and the left + top positions of every item for (i = 0; i < visibleCount; i++) { child = visibleItems[i]; calcs = boxes[i]; childMargins = child.margins; vertMargins = childMargins.top + childMargins.bottom; leftOffset += childMargins.left; if (isStart && child.flex && !child.width) { flexedWidth = Math.ceil((child.flex / remainingFlex) * remainingWidth); remainingWidth -= flexedWidth; remainingFlex -= child.flex; calcs.width = flexedWidth; calcs.dirtySize = true; } calcs.left = leftOffset; calcs.top = topOffset + childMargins.top; switch (this.align) { case 'stretch': stretchHeight = availHeight - vertMargins; calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000); calcs.dirtySize = true; break; case 'stretchmax': stretchHeight = maxHeight - vertMargins; calcs.height = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000); calcs.dirtySize = true; break; case 'middle': var diff = availHeight - calcs.height - vertMargins; if (diff > 0) { calcs.top = topOffset + vertMargins + (diff / 2); } } leftOffset += calcs.width + childMargins.right; } return { boxes: boxes, meta : { maxHeight: maxHeight } }; } }); Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;*
- start : Default
*child items are packed together at * left side of container- center :
*child items are packed together at * mid-width of container- end :
*child items are packed together at right * side of container