4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5 <title>The source code</title>
6 <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7 <script type="text/javascript" src="../prettify/prettify.js"></script>
8 <style type="text/css">
9 .highlight { display: block; background-color: #ddd; }
11 <script type="text/javascript">
12 function highlight() {
13 document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
17 <body onload="prettyPrint(); highlight();">
18 <pre class="prettyprint lang-js"><span id='Ext-layout-container-Box'>/**
19 </span> * @class Ext.layout.container.Box
20 * @extends Ext.layout.container.Container
21 * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
24 Ext.define('Ext.layout.container.Box', {
26 /* Begin Definitions */
28 alias: ['layout.box'],
29 extend: 'Ext.layout.container.Container',
30 alternateClassName: 'Ext.layout.BoxLayout',
33 'Ext.layout.container.boxOverflow.None',
34 'Ext.layout.container.boxOverflow.Menu',
35 'Ext.layout.container.boxOverflow.Scroller',
37 'Ext.dd.DragDropManager'
42 <span id='Ext-layout-container-Box-cfg-animate'> /**
43 </span> * @cfg {Mixed} animate
44 * <p>If truthy, child Component are <i>animated</i> into position whenever the Container
45 * is layed out. If this option is numeric, it is used as the animation duration in milliseconds.</p>
46 * <p>May be set as a property at any time.</p>
49 <span id='Ext-layout-container-Box-cfg-defaultMargins'> /**
50 </span> * @cfg {Object} defaultMargins
51 * <p>If the individual contained items do not have a <tt>margins</tt>
52 * property specified or margin specified via CSS, the default margins from this property will be
53 * applied to each item.</p>
54 * <br><p>This property may be specified as an object containing margins
55 * to apply in the format:</p><pre><code>
58 right: (right margin),
59 bottom: (bottom margin),
61 }</code></pre>
62 * <p>This property may also be specified as a string containing
63 * space-separated, numeric margin values. The order of the sides associated
64 * with each value matches the way CSS processes margin values:</p>
65 * <div class="mdetail-params"><ul>
66 * <li>If there is only one value, it applies to all sides.</li>
67 * <li>If there are two values, the top and bottom borders are set to the
68 * first value and the right and left are set to the second.</li>
69 * <li>If there are three values, the top is set to the first value, the left
70 * and right are set to the second, and the bottom is set to the third.</li>
71 * <li>If there are four values, they apply to the top, right, bottom, and
72 * left, respectively.</li>
73 * </ul></div>
74 * <p>Defaults to:</p><pre><code>
75 * {top:0, right:0, bottom:0, left:0}
76 * </code></pre>
85 <span id='Ext-layout-container-Box-cfg-padding'> /**
86 </span> * @cfg {String} padding
87 * <p>Sets the padding to be applied to all child items managed by this layout.</p>
88 * <p>This property must be specified as a string containing
89 * space-separated, numeric padding values. The order of the sides associated
90 * with each value matches the way CSS processes padding values:</p>
91 * <div class="mdetail-params"><ul>
92 * <li>If there is only one value, it applies to all sides.</li>
93 * <li>If there are two values, the top and bottom borders are set to the
94 * first value and the right and left are set to the second.</li>
95 * <li>If there are three values, the top is set to the first value, the left
96 * and right are set to the second, and the bottom is set to the third.</li>
97 * <li>If there are four values, they apply to the top, right, bottom, and
98 * left, respectively.</li>
99 * </ul></div>
100 * <p>Defaults to: <code>"0"</code></p>
103 // documented in subclasses
106 <span id='Ext-layout-container-Box-cfg-pack'> /**
107 </span> * @cfg {String} pack
108 * Controls how the child items of the container are packed together. Acceptable configuration values
109 * for this property are:
110 * <div class="mdetail-params"><ul>
111 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
112 * <b>left</b> side of container</div></li>
113 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
114 * <b>mid-width</b> of container</div></li>
115 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
116 * side of container</div></li>
117 * </ul></div>
119 <span id='Ext-layout-container-Box-cfg-flex'> /**
120 </span> * @cfg {Number} flex
121 * This configuration option is to be applied to <b>child <tt>items</tt></b> of the container managed
122 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
123 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
124 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
125 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
130 itemCls: Ext.baseCSSPrefix + 'box-item',
131 targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
132 innerCls: Ext.baseCSSPrefix + 'box-inner',
134 bindToOwnerCtContainer: true,
136 // availableSpaceOffset is used to adjust the availableWidth, typically used
137 // to reserve space for a scrollbar
138 availableSpaceOffset: 0,
140 // whether or not to reserve the availableSpaceOffset in layout calculations
143 <span id='Ext-layout-container-Box-cfg-clearInnerCtOnLayout'> /**
144 </span> * @cfg {Boolean} clearInnerCtOnLayout
146 clearInnerCtOnLayout: false,
148 flexSortFn: function (a, b) {
149 var maxParallelPrefix = 'max' + this.parallelPrefixCap,
150 infiniteValue = Infinity;
151 a = a.component[maxParallelPrefix] || infiniteValue;
152 b = b.component[maxParallelPrefix] || infiniteValue;
153 // IE 6/7 Don't like Infinity - Infinity...
154 if (!isFinite(a) && !isFinite(b)) {
160 // Sort into *descending* order.
161 minSizeSortFn: function(a, b) {
162 return b.available - a.available;
165 constructor: function(config) {
168 me.callParent(arguments);
170 // The sort function needs access to properties in this, so must be bound.
171 me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
173 me.initOverflowHandler();
176 <span id='Ext-layout-container-Box-method-getChildBox'> /**
178 * Returns the current size and positioning of the passed child item.
179 * @param {Component} child The child Component to calculate the box for
180 * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
182 getChildBox: function(child) {
183 child = child.el || this.owner.getComponent(child).el;
184 var size = child.getBox(false, true);
193 <span id='Ext-layout-container-Box-method-calculateChildBox'> /**
195 * Calculates the size and positioning of the passed child item.
196 * @param {Component} child The child Component to calculate the box for
197 * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
199 calculateChildBox: function(child) {
201 boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
205 child = me.owner.getComponent(child);
206 for (; i < ln; i++) {
207 if (boxes[i].component === child) {
213 <span id='Ext-layout-container-Box-method-calculateChildBoxes'> /**
215 * Calculates the size and positioning of each item in the box. This iterates over all of the rendered,
216 * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
217 * returns meta data such as maxSize which are useful when resizing layout wrappers such as this.innerCt.
218 * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
219 * @param {Object} targetSize Object containing target size and height
220 * @return {Object} Object containing box measurements for each child, plus meta data
222 calculateChildBoxes: function(visibleItems, targetSize) {
226 infiniteValue = Infinity,
229 parallelPrefix = me.parallelPrefix,
230 parallelPrefixCap = me.parallelPrefixCap,
231 perpendicularPrefix = me.perpendicularPrefix,
232 perpendicularPrefixCap = me.perpendicularPrefixCap,
233 parallelMinString = 'min' + parallelPrefixCap,
234 perpendicularMinString = 'min' + perpendicularPrefixCap,
235 perpendicularMaxString = 'max' + perpendicularPrefixCap,
237 parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
238 perpendicularSize = targetSize[perpendicularPrefix],
239 padding = me.padding,
240 parallelOffset = padding[me.parallelBefore],
241 paddingParallel = parallelOffset + padding[me.parallelAfter],
242 perpendicularOffset = padding[me.perpendicularLeftTop],
243 paddingPerpendicular = perpendicularOffset + padding[me.perpendicularRightBottom],
244 availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
246 innerCtBorderWidth = me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB),
248 isStart = me.pack == 'start',
249 isCenter = me.pack == 'center',
250 isEnd = me.pack == 'end',
252 constrain = Ext.Number.constrain,
253 visibleCount = visibleItems.length,
263 i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
264 tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
265 flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
266 perpendicularMargins, stretchSize;
268 //gather the total flex of all flexed items and the width taken up by fixed width items
269 for (i = 0; i < visibleCount; i++) {
270 child = visibleItems[i];
271 childPerpendicular = child[perpendicularPrefix];
272 me.layoutItem(child);
273 childMargins = child.margins;
274 parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
276 // Create the box description object for this child item.
279 margins: childMargins
282 // flex and not 'auto' width
284 totalFlex += child.flex;
285 childParallel = undefinedValue;
287 // Not flexed or 'auto' width or undefined width
289 if (!(child[parallelPrefix] && childPerpendicular)) {
290 childSize = child.getSize();
292 childParallel = child[parallelPrefix] || childSize[parallelPrefix];
293 childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
296 nonFlexSize += parallelMargins + (childParallel || 0);
297 desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
298 minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
300 // Max height for align - force layout of non-laid out subcontainers without a numeric height
301 if (typeof childPerpendicular != 'number') {
302 // Clear any static sizing and revert to flow so we can get a proper measurement
303 // child['set' + perpendicularPrefixCap](null);
304 childPerpendicular = child['get' + perpendicularPrefixCap]();
307 // Track the maximum perpendicular size for use by the stretch and stretchmax align config values.
308 maxSize = mmax(maxSize, childPerpendicular + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
310 tmpObj[parallelPrefix] = childParallel || undefinedValue;
311 tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
314 shortfall = desiredSize - parallelSize;
315 tooNarrow = minimumSize > parallelSize;
317 //the space available to the flexed items
318 availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
321 for (i = 0; i < visibleCount; i++) {
323 minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
324 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
325 box[parallelPrefix] = minSize;
329 //all flexed items should be sized to their minimum size, other items should be shrunk down until
330 //the shortfall has been accounted for
331 if (shortfall > 0) {
333 * When we have a shortfall but are not tooNarrow, we need to shrink the width of each non-flexed item.
334 * Flexed items are immediately reduced to their minWidth and anything already at minWidth is ignored.
335 * The remaining items are collected into the minWidths array, which is later used to distribute the shortfall.
337 for (i = 0; i < visibleCount; i++) {
338 item = visibleItems[i];
339 minSize = item[parallelMinString] || 0;
341 //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
342 //shrunk to their minSize because they're flexible and should be the first to lose size
345 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
346 box[parallelPrefix] = minSize;
351 available: boxes[i][parallelPrefix] - minSize,
357 //sort by descending amount of width remaining before minWidth is reached
358 Ext.Array.sort(minSizes, me.minSizeSortFn);
361 * Distribute the shortfall (difference between total desired size of all items and actual size available)
362 * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
363 * smallest difference between their size and minSize first, so that if reducing the size by the average
364 * amount would make that item less than its minSize, we carry the remainder over to the next item.
366 for (i = 0, length = minSizes.length; i < length; i++) {
367 itemIndex = minSizes[i].index;
369 if (itemIndex == undefinedValue) {
372 item = visibleItems[itemIndex];
373 minSize = minSizes[i].minSize;
375 box = boxes[itemIndex];
376 oldSize = box[parallelPrefix];
377 newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
378 reduction = oldSize - newSize;
380 box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
381 box[parallelPrefix] = newSize;
382 shortfall -= reduction;
386 remainingSpace = availableSpace;
387 remainingFlex = totalFlex;
390 // Create an array containing *just the flexed boxes* for allocation of remainingSpace
391 for (i = 0; i < visibleCount; i++) {
392 child = visibleItems[i];
393 if (isStart && child.flex) {
394 flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
397 // The flexed boxes need to be sorted in ascending order of maxSize to work properly
398 // so that unallocated space caused by maxWidth being less than flexed width
399 // can be reallocated to subsequent flexed boxes.
400 Ext.Array.sort(flexedBoxes, me.flexSortFn);
402 // Calculate the size of each flexed item, and attempt to set it.
403 for (i = 0; i < flexedBoxes.length; i++) {
404 calcs = flexedBoxes[i];
405 child = calcs.component;
406 childMargins = calcs.margins;
408 flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
410 // Implement maxSize and minSize check
411 flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
413 // Remaining space has already had all parallel margins subtracted from it, so just subtract consumed size
414 remainingSpace -= flexedSize;
415 remainingFlex -= child.flex;
417 calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
418 calcs[parallelPrefix] = flexedSize;
424 parallelOffset += availableSpace / 2;
427 parallelOffset += availableSpace;
430 // Fix for left and right docked Components in a dock component layout. This is for docked Headers and docked Toolbars.
431 // Older Microsoft browsers do not size a position:absolute element's width to match its content.
432 // So in this case, in the updateInnerCtSize method we may need to adjust the size of the owning Container's element explicitly based upon
433 // the discovered max width. So here we put a calculatedWidth property in the metadata to facilitate this.
434 if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
436 calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
437 if (me.owner.frameSize) {
438 calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
440 // If the owning element is not sized, calculate the available width to center or stretch in based upon maxSize
441 availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
444 //finally, calculate the left and top position of each item
445 for (i = 0; i < visibleCount; i++) {
446 child = visibleItems[i];
449 childMargins = calcs.margins;
451 perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
453 // Advance past the "before" margin
454 parallelOffset += childMargins[me.parallelBefore];
456 calcs[me.parallelBefore] = parallelOffset;
457 calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
459 if (me.align == 'stretch') {
460 stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
461 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
462 calcs[perpendicularPrefix] = stretchSize;
464 else if (me.align == 'stretchmax') {
465 stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
466 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
467 calcs[perpendicularPrefix] = stretchSize;
469 else if (me.align == me.alignCenteringString) {
470 // When calculating a centered position within the content box of the innerCt, the width of the borders must be subtracted from
471 // the size to yield the space available to center within.
472 // The updateInnerCtSize method explicitly adds the border widths to the set size of the innerCt.
473 diff = mmax(availPerpendicularSize, maxSize) - innerCtBorderWidth - calcs[perpendicularPrefix];
475 calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
479 // Advance past the box size and the "after" margin
480 parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
486 calculatedWidth: calculatedWidth,
488 nonFlexSize: nonFlexSize,
489 desiredSize: desiredSize,
490 minimumSize: minimumSize,
491 shortfall: shortfall,
497 onRemove: function(comp){
498 this.callParent(arguments);
499 if (this.overflowHandler) {
500 this.overflowHandler.onRemove(comp);
504 <span id='Ext-layout-container-Box-method-initOverflowHandler'> /**
507 initOverflowHandler: function() {
508 var handler = this.overflowHandler;
510 if (typeof handler == 'string') {
516 var handlerType = 'None';
517 if (handler && handler.type !== undefined) {
518 handlerType = handler.type;
521 var constructor = Ext.layout.container.boxOverflow[handlerType];
522 if (constructor[this.type]) {
523 constructor = constructor[this.type];
526 this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
529 <span id='Ext-layout-container-Box-method-onLayout'> /**
531 * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
534 onLayout: function() {
536 // Clear the innerCt size so it doesn't influence the child items.
537 if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
538 this.innerCt.setSize(null, null);
542 targetSize = me.getLayoutTargetSize(),
543 items = me.getVisibleItems(),
544 calcs = me.calculateChildBoxes(items, targetSize),
547 handler, method, results;
549 if (me.autoSize && calcs.meta.desiredSize) {
550 targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
553 //invoke the overflow handler, if one is configured
554 if (meta.shortfall > 0) {
555 handler = me.overflowHandler;
556 method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
558 results = handler[method](calcs, targetSize);
561 if (results.targetSize) {
562 targetSize = results.targetSize;
565 if (results.recalculate) {
566 items = me.getVisibleItems();
567 calcs = me.calculateChildBoxes(items, targetSize);
572 me.overflowHandler.clearOverflow();
575 <span id='Ext-layout-container-Box-property-layoutTargetLastSize'> /**
577 * @property layoutTargetLastSize
579 * Private cache of the last measured size of the layout target. This should never be used except by
580 * BoxLayout subclasses during their onLayout run.
582 me.layoutTargetLastSize = targetSize;
584 <span id='Ext-layout-container-Box-property-childBoxCache'> /**
586 * @property childBoxCache
588 * Array of the last calculated height, width, top and left positions of each visible rendered component
589 * within the Box layout.
591 me.childBoxCache = calcs;
593 me.updateInnerCtSize(targetSize, calcs);
594 me.updateChildBoxes(boxes);
595 me.handleTargetOverflow(targetSize);
598 <span id='Ext-layout-container-Box-method-updateChildBoxes'> /**
599 </span> * Resizes and repositions each child component
600 * @param {Array} boxes The box measurements
602 updateChildBoxes: function(boxes) {
605 length = boxes.length,
607 dd = Ext.dd.DDM.getDDById(me.innerCt.id), // Any DD active on this layout's element (The BoxReorderer plugin does this.)
608 oldBox, newBox, changed, comp, boxAnim, animCallback;
610 for (; i < length; i++) {
612 comp = newBox.component;
614 // If a Component is being drag/dropped, skip positioning it.
615 // Accomodate the BoxReorderer plugin: Its current dragEl must not be positioned by the layout
616 if (dd && (dd.getDragEl() === comp.el.dom)) {
622 oldBox = me.getChildBox(comp);
624 // If we are animating, we build up an array of Anim config objects, one for each
625 // child Component which has any changed box properties. Those with unchanged
626 // properties are not animated.
628 // Animate may be a config object containing callback.
629 animCallback = me.animate.callback || me.animate;
631 layoutAnimation: true, // Component Target handler must use set*Calculated*Size
637 // Only set from and to properties when there's a change.
638 // Perform as few Component setter methods as possible.
639 // Temporarily set the property values that we are not animating
640 // so that doComponentLayout does not auto-size them.
641 if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
643 // boxAnim.from.width = oldBox.width;
644 boxAnim.to.width = newBox.width;
646 if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
648 // boxAnim.from.height = oldBox.height;
649 boxAnim.to.height = newBox.height;
651 if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
653 // boxAnim.from.left = oldBox.left;
654 boxAnim.to.left = newBox.left;
656 if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
658 // boxAnim.from.top = oldBox.top;
659 boxAnim.to.top = newBox.top;
662 animQueue.push(boxAnim);
665 if (newBox.dirtySize) {
666 if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
667 me.setItemSize(comp, newBox.width, newBox.height);
670 // Don't set positions to NaN
671 if (isNaN(newBox.left) || isNaN(newBox.top)) {
674 comp.setPosition(newBox.left, newBox.top);
678 // Kick off any queued animations
679 length = animQueue.length;
682 // A function which cleans up when a Component's animation is done.
683 // The last one to finish calls the callback.
684 var afterAnimate = function(anim) {
685 // When we've animated all changed boxes into position, clear our busy flag and call the callback.
688 me.layoutBusy = false;
689 if (Ext.isFunction(animCallback)) {
695 var beforeAnimate = function() {
696 me.layoutBusy = true;
699 // Start each box animation off
700 for (i = 0, length = animQueue.length; i < length; i++) {
701 boxAnim = animQueue[i];
703 // Clean up the Component after. Clean up the *layout* after the last animation finishes
704 boxAnim.listeners.afteranimate = afterAnimate;
706 // The layout is busy during animation, and may not be called, so set the flag when the first animation begins
708 boxAnim.listeners.beforeanimate = beforeAnimate;
710 if (me.animate.duration) {
711 boxAnim.duration = me.animate.duration;
713 comp = boxAnim.target;
714 delete boxAnim.target;
715 // Stop any currently running animation
716 comp.stopAnimation();
717 comp.animate(boxAnim);
722 <span id='Ext-layout-container-Box-method-updateInnerCtSize'> /**
724 * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
725 * to make sure all child items fit within it. We call this before sizing the children because if our child
726 * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
727 * again immediately afterwards, giving a performance hit.
728 * Subclasses should provide an implementation.
729 * @param {Object} currentSize The current height and width of the innerCt
730 * @param {Array} calculations The new box calculations of all items to be laid out
732 updateInnerCtSize: function(tSize, calcs) {
736 padding = me.padding,
738 height = tSize.height,
743 if (me.direction == 'horizontal') {
744 innerCtWidth = width;
745 innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
747 if (align == 'stretch') {
748 innerCtHeight = height;
750 else if (align == 'middle') {
751 innerCtHeight = mmax(height, innerCtHeight);
754 innerCtHeight = height;
755 innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
757 if (align == 'stretch') {
758 innerCtWidth = width;
760 else if (align == 'center') {
761 innerCtWidth = mmax(width, innerCtWidth);
764 me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
766 // If a calculated width has been found (and this only happens for auto-width vertical docked Components in old Microsoft browsers)
767 // then, if the Component has not assumed the size of its content, set it to do so.
768 if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
769 me.owner.el.setWidth(meta.calculatedWidth);
772 if (me.innerCt.dom.scrollTop) {
773 me.innerCt.dom.scrollTop = 0;
777 <span id='Ext-layout-container-Box-method-handleTargetOverflow'> /**
779 * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
780 * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
781 * target. Having a Box layout inside such a target is therefore not recommended.
782 * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
783 * @param {Ext.container.Container} container The container
784 * @param {Ext.core.Element} target The target element
785 * @return True if the layout overflowed, and was reflowed in a secondary onLayout call.
787 handleTargetOverflow: function(previousTargetSize) {
788 var target = this.getTarget(),
789 overflow = target.getStyle('overflow'),
792 if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
793 newTargetSize = this.getLayoutTargetSize();
794 if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
795 this.adjustmentPass = true;
801 delete this.adjustmentPass;
805 isValidParent : function(item, target, position) {
806 // Note: Box layouts do not care about order within the innerCt element because it's an absolutely positioning layout
807 // We only care whether the item is a direct child of the innerCt element.
808 var itemEl = item.el ? item.el.dom : Ext.getDom(item);
809 return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
812 // Overridden method from AbstractContainer.
813 // Used in the base AbstractLayout.beforeLayout method to render all items into.
814 getRenderTarget: function() {
816 // the innerCt prevents wrapping and shuffling while the container is resizing
817 this.innerCt = this.getTarget().createChild({
821 this.padding = Ext.util.Format.parseBox(this.padding);
827 renderItem: function(item, target) {
828 this.callParent(arguments);
830 itemEl = item.getEl(),
831 style = itemEl.dom.style,
832 margins = item.margins || item.margin;
834 // Parse the item's margin/margins specification
836 if (Ext.isString(margins) || Ext.isNumber(margins)) {
837 margins = Ext.util.Format.parseBox(margins);
839 Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
842 margins = Ext.apply({}, me.defaultMargins);
845 // Add any before/after CSS margins to the configured margins, and zero the CSS margins
846 margins.top += itemEl.getMargin('t');
847 margins.right += itemEl.getMargin('r');
848 margins.bottom += itemEl.getMargin('b');
849 margins.left += itemEl.getMargin('l');
850 style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
852 // Item must reference calculated margins.
853 item.margins = margins;
856 <span id='Ext-layout-container-Box-method-destroy'> /**
859 destroy: function() {
860 Ext.destroy(this.overflowHandler);
861 this.callParent(arguments);