X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/2e847cf21b8ab9d15fa167b315ca5b2fa92638fc..0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6:/docs/source/BoxLayout.html diff --git a/docs/source/BoxLayout.html b/docs/source/BoxLayout.html index b096bd21..804cb151 100644 --- a/docs/source/BoxLayout.html +++ b/docs/source/BoxLayout.html @@ -1,12 +1,18 @@ - - - - The source code - - - - -
/** + + + + The source code + + + + +
/*!
+ * Ext JS Library 3.3.1
+ * Copyright(c) 2006-2010 Sencha Inc.
+ * licensing@sencha.com
+ * http://www.sencha.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.

@@ -73,414 +79,277 @@ Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, { constructor : function(config){ Ext.layout.BoxLayout.superclass.constructor.call(this, config); - if(Ext.isString(this.defaultMargins)){ + + 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); }, - // private - isValidParent : function(c, target){ - return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom; - }, + /** + * @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); - // 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); + 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; + } + } } - Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt); - }, + + /** + * @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 = calcs; + + this.updateInnerCtSize(tSize, calcs); + this.updateChildBoxes(boxes); - onLayout : function(ct, target){ - this.renderAll(ct, target); + // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary. + this.handleTargetOverflow(tSize, container, target); }, - getLayoutTargetSize : function(){ - var target = this.container.getLayoutTarget(), ret; - if (target) { - ret = target.getViewSize(); - ret.width -= target.getPadding('lr'); - ret.height -= target.getPadding('tb'); +
/** + * 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); } - 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 - *

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 + * 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: 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; - // private - onLayout : function(ct, target){ - Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target); - - var cs = this.getRenderedItems(ct), csLen = cs.length, - c, i, cm, ch, margin, cl, diff, aw, availHeight, - size = this.getLayoutTargetSize(), - w = size.width, - h = size.height - this.scrollOffset, - l = this.padding.left, - t = this.padding.top, - isStart = this.pack == 'start', - extraHeight = 0, - maxWidth = 0, - totalFlex = 0, - usedHeight = 0, - idx = 0, - heights = [], - restore = []; - - // Do only width calculations and apply those first, as they can affect height - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - cm = c.margins; - margin = cm.top + cm.bottom; - // Max height for align - maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right); - } - - var innerCtWidth = maxWidth + this.padding.left + this.padding.right; - switch(this.align){ - case 'stretch': - this.innerCt.setSize(w, h); - break; - case 'stretchmax': - case 'left': - this.innerCt.setSize(innerCtWidth, h); - break; - case 'center': - this.innerCt.setSize(w = Math.max(w, innerCtWidth), h); - break; - } - - var availableWidth = Math.max(0, w - this.padding.left - this.padding.right); - // Apply widths - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - cm = c.margins; - if(this.align == 'stretch'){ - c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain( - c.minWidth || 0, c.maxWidth || 1000000)); - }else if(this.align == 'stretchmax'){ - c.setWidth((maxWidth - (cm.left + cm.right)).constrain( - c.minWidth || 0, c.maxWidth || 1000000)); - }else if(isStart && c.flex){ - c.setWidth(); + 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; - } - - // Height calculations - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - // Total of all the flex values - totalFlex += c.flex || 0; - // Don't run height calculations on flexed items - if (!c.flex) { - // Render and layout sub-containers without a flex or height, once - if (!c.height && !c.hasLayout && c.doLayout) { - c.doLayout(); - } - ch = c.getHeight(); - } else { - ch = 0; + if (align == 'stretch') { + innerCtWidth = width; + } else if (align == 'center') { + innerCtWidth = Math.max(width, innerCtWidth); } - - cm = c.margins; - // Determine how much height is available to flex - extraHeight += ch + cm.top + cm.bottom; } - // Final avail height calc - availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom)); - var leftOver = availHeight; - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - if(isStart && c.flex){ - ch = Math.floor(availHeight * (c.flex / totalFlex)); - leftOver -= ch; - heights.push(ch); - } - } - if(this.pack == 'center'){ - t += availHeight ? availHeight / 2 : 0; - }else if(this.pack == 'end'){ - t += availHeight; - } - idx = 0; - // Apply heights - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - cm = c.margins; - t += cm.top; - aw = availableWidth; - cl = l + cm.left // default left pos + this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined); + }, - // Adjust left pos for centering - if(this.align == 'center'){ - if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){ - cl += (diff/2); - aw -= diff; - } - } + /** + * @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'); - c.setPosition(cl, t); - if(isStart && c.flex){ - ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0)); - c.setSize(aw, ch); - }else{ - ch = c.getHeight(); - } - t += ch + cm.bottom; - } - // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary. - if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) { - var ts = this.getLayoutTargetSize(); - if (ts.width != size.width || ts.height != size.height){ + if (overflow && overflow != 'hidden' &&!this.adjustmentPass) { + var newTargetSize = this.getLayoutTargetSize(); + if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){ this.adjustmentPass = true; - this.onLayout(ct, target); + this.onLayout(container, target); } } + delete this.adjustmentPass; - } -}); + }, -Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout; + // private + isValidParent : function(c, target) { + return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom; + }, -
/** - * @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', -
    /** - * @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 + * 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, - // private - onLayout : function(ct, target){ - Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target); + i, c, items = []; - var cs = this.getRenderedItems(ct), csLen = cs.length, - c, i, cm, cw, ch, diff, availWidth, - size = this.getLayoutTargetSize(), - w = size.width - this.scrollOffset, - h = size.height, - l = this.padding.left, - t = this.padding.top, - isStart = this.pack == 'start', - isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1, - extraWidth = 0, - maxHeight = 0, - totalFlex = 0, - usedWidth = 0; - - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - // Total of all the flex values - totalFlex += c.flex || 0; - // Don't run width calculations on flexed items - if (!c.flex) { - // Render and layout sub-containers without a flex or width, once - if (!c.width && !c.hasLayout && c.doLayout) { - c.doLayout(); - } - cw = c.getWidth(); - } else { - cw = 0; + for (i = 0; i < len; i++) { + if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true && c.collapsed !== true && c.shouldLayout !== false){ + items.push(c); } - cm = c.margins; - // Determine how much width is available to flex - extraWidth += cw + cm.left + cm.right; - // Max height for align - maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom); } - // Final avail width calc - availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right)); - var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom; - switch(this.align){ - case 'stretch': - this.innerCt.setSize(w, h); - break; - case 'stretchmax': - case 'top': - this.innerCt.setSize(w, innerCtHeight); - break; - case 'middle': - this.innerCt.setSize(w, h = Math.max(h, innerCtHeight)); - break; + 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); + }, - var leftOver = availWidth, - widths = [], - restore = [], - idx = 0, - availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom); + getLayoutTargetSize : function() { + var target = this.container.getLayoutTarget(), ret; + + if (target) { + ret = target.getViewSize(); - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - if(isStart && c.flex){ - cw = Math.floor(availWidth * (c.flex / totalFlex)); - leftOver -= cw; - widths.push(cw); + // 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(); } - } - if(this.pack == 'center'){ - l += availWidth ? availWidth / 2 : 0; - }else if(this.pack == 'end'){ - l += availWidth; - } - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - cm = c.margins; - l += cm.left; - c.setPosition(l, t + cm.top); - if(isStart && c.flex){ - cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0)); - if(isRestore){ - restore.push(c.getHeight()); - } - c.setSize(cw, availableHeight); - }else{ - cw = c.getWidth(); - } - l += cw + cm.right; + ret.width -= target.getPadding('lr'); + ret.height -= target.getPadding('tb'); } + + return ret; + }, - idx = 0; - for (i = 0 ; i < csLen; i++) { - c = cs[i]; - cm = c.margins; - ch = c.getHeight(); - if(isStart && c.flex){ - ch = restore[idx++]; - } - if(this.align == 'stretch'){ - c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain( - c.minHeight || 0, c.maxHeight || 1000000)); - }else if(this.align == 'stretchmax'){ - c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain( - c.minHeight || 0, c.maxHeight || 1000000)); - }else{ - if(this.align == 'middle'){ - diff = availableHeight - (ch + cm.top + cm.bottom); - ch = t + cm.top + (diff/2); - if(diff > 0){ - c.setPosition(c.x, ch); - } - } - if(isStart && c.flex){ - c.setHeight(ch); - } - } - } - // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary. - if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) { - var ts = this.getLayoutTargetSize(); - if (ts.width != size.width || ts.height != size.height){ - this.adjustmentPass = true; - this.onLayout(ct, target); - } + // private + renderItem : function(c) { + if(Ext.isString(c.margins)){ + c.margins = this.parseMargins(c.margins); + }else if(!c.margins){ + c.margins = this.defaultMargins; } - delete this.adjustmentPass; + Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments); + }, + + /** + * @private + */ + destroy: function() { + Ext.destroy(this.overflowHandler); + + Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments); } }); -Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout; -
- + + +Ext.ns('Ext.layout.boxOverflow'); + +
/** + * @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. + */ + +Ext.layout.boxOverflow.None = Ext.extend(Object, { + constructor: function(layout, config) { + this.layout = layout; + + Ext.apply(this, config || {}); + }, + + handleOverflow: Ext.emptyFn, + + clearOverflow: Ext.emptyFn +}); + + +Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None; +
+ \ No newline at end of file