X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6a7e4474cba9d8be4b2ec445e10f1691f7277c50..f5240829880f87e0cf581c6a296e436fdef0ef80:/src/widgets/layout/BoxLayout.js?ds=inline
diff --git a/src/widgets/layout/BoxLayout.js b/src/widgets/layout/BoxLayout.js
index 3d3719d9..c7a35d82 100644
--- a/src/widgets/layout/BoxLayout.js
+++ b/src/widgets/layout/BoxLayout.js
@@ -1,5 +1,5 @@
/*!
- * Ext JS Library 3.2.0
+ * Ext JS Library 3.3.0
* Copyright(c) 2006-2010 Ext JS, Inc.
* licensing@extjs.com
* http://www.extjs.com/license
@@ -75,6 +75,26 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
if (Ext.isString(this.defaultMargins)) {
this.defaultMargins = this.parseMargins(this.defaultMargins);
}
+
+ var handler = this.overflowHandler;
+
+ if (typeof handler == 'string') {
+ handler = {
+ type: handler
+ };
+ }
+
+ var handlerType = 'none';
+ if (handler && handler.type != undefined) {
+ handlerType = handler.type;
+ }
+
+ var constructor = Ext.layout.boxOverflow[handlerType];
+ if (constructor[this.type]) {
+ constructor = constructor[this.type];
+ }
+
+ this.overflowHandler = new constructor(this, handler);
},
/**
@@ -85,9 +105,32 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
onLayout: function(container, target) {
Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
- var items = this.getVisibleItems(container),
- tSize = this.getLayoutTargetSize();
-
+ var tSize = this.getLayoutTargetSize(),
+ items = this.getVisibleItems(container),
+ calcs = this.calculateChildBoxes(items, tSize),
+ boxes = calcs.boxes,
+ meta = calcs.meta;
+
+ //invoke the overflow handler, if one is configured
+ if (tSize.width > 0) {
+ var handler = this.overflowHandler,
+ method = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
+
+ var results = handler[method](calcs, tSize);
+
+ if (results) {
+ if (results.targetSize) {
+ tSize = results.targetSize;
+ }
+
+ if (results.recalculate) {
+ items = this.getVisibleItems(container);
+ calcs = this.calculateChildBoxes(items, tSize);
+ boxes = calcs.boxes;
+ }
+ }
+ }
+
/**
* @private
* @property layoutTargetLastSize
@@ -96,7 +139,7 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
* BoxLayout subclasses during their onLayout run.
*/
this.layoutTargetLastSize = tSize;
-
+
/**
* @private
* @property childBoxCache
@@ -104,10 +147,10 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
* 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);
+ this.childBoxCache = calcs;
+
+ this.updateInnerCtSize(tSize, calcs);
+ this.updateChildBoxes(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);
@@ -121,7 +164,7 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
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);
}
@@ -129,6 +172,7 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
if (isNaN(box.left) || isNaN(box.top)) {
continue;
}
+
comp.setPosition(box.left, box.top);
}
},
@@ -143,7 +187,34 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
* @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,
+ updateInnerCtSize: function(tSize, calcs) {
+ var align = this.align,
+ padding = this.padding,
+ width = tSize.width,
+ height = tSize.height;
+
+ if (this.type == 'hbox') {
+ var innerCtWidth = width,
+ innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
+
+ if (align == 'stretch') {
+ innerCtHeight = height;
+ } else if (align == 'middle') {
+ innerCtHeight = Math.max(height, innerCtHeight);
+ }
+ } else {
+ var innerCtHeight = height,
+ innerCtWidth = calcs.meta.maxWidth + padding.left + padding.right;
+
+ if (align == 'stretch') {
+ innerCtWidth = width;
+ } else if (align == 'center') {
+ innerCtWidth = Math.max(width, innerCtWidth);
+ }
+ }
+
+ this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+ },
/**
* @private
@@ -169,7 +240,7 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
},
// private
- isValidParent : function(c, target){
+ isValidParent : function(c, target) {
return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
},
@@ -187,7 +258,7 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
i, c, items = [];
for (i = 0; i < len; i++) {
- if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true){
+ if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true && c.shouldLayout !== false){
items.push(c);
}
}
@@ -196,18 +267,18 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
},
// private
- renderAll : function(ct, target){
- if(!this.innerCt){
- // the innerCt prevents wrapping and shuffling while
- // the container is resizing
+ 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(){
+ getLayoutTargetSize : function() {
var target = this.container.getLayoutTarget(), ret;
+
if (target) {
ret = target.getViewSize();
@@ -218,459 +289,56 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
ret = target.getStyleSize();
}
- ret.width -= target.getPadding('lr');
+ ret.width -= target.getPadding('lr');
ret.height -= target.getPadding('tb');
}
+
return ret;
},
// private
- renderItem : function(c){
+ 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
- *
A layout that arranges items vertically down a Container. This layout optionally divides available vertical
- * space between child items containing a numeric flex
configuration.
- * 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:
- *
- * - 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.
- *
- */
- 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:
- *
- * - 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 container
- *
- */
-
- /**
- * @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.minHeight || 0, child.maxWidth || 1000000);
- calcs.dirtySize = true;
- break;
- case 'stretchmax':
- stretchWidth = maxWidth - horizMargins;
- calcs.width = stretchWidth.constrain(child.minHeight || 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
- }
- };
+ destroy: function() {
+ Ext.destroy(this.overflowHandler);
+
+ Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
}
});
-Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
-/**
- * @class Ext.layout.HBoxLayout
- * @extends Ext.layout.BoxLayout
- * A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
- * space between child items containing a numeric flex
configuration.
- * 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:
- *
- * - 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 :
child items are stretched vertically to
- * the height of the largest item.
- */
- 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;
+Ext.ns('Ext.layout.boxOverflow');
- if (this.align == 'stretch') {
- innerCtHeight = tSize.height;
- } else if (this.align == 'middle') {
- innerCtHeight = Math.max(tSize.height, innerCtHeight);
- }
+/**
+ * @class Ext.layout.boxOverflow.None
+ * @extends Object
+ * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
+ * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
+ * for its container.
+ */
- this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
+Ext.layout.boxOverflow.None = Ext.extend(Object, {
+ constructor: function(layout, config) {
+ this.layout = layout;
+
+ Ext.apply(this, config || {});
},
-
- /**
- * @cfg {String} pack
- * Controls how the child items of the container are packed together. Acceptable configuration values
- * for this property are:
- *
- * - 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
- *
- */
- /**
- * @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
- }
- };
- }
+
+ handleOverflow: Ext.emptyFn,
+
+ clearOverflow: Ext.emptyFn
});
-Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
+
+Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;