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,
138 // availableSpaceOffset is used to adjust the availableWidth, typically used
139 // to reserve space for a scrollbar
140 availableSpaceOffset: 0,
142 // whether or not to reserve the availableSpaceOffset in layout calculations
145 <span id='Ext-layout-container-Box-cfg-clearInnerCtOnLayout'> /**
146 </span> * @cfg {Boolean} clearInnerCtOnLayout
148 clearInnerCtOnLayout: false,
150 flexSortFn: function (a, b) {
151 var maxParallelPrefix = 'max' + this.parallelPrefixCap,
152 infiniteValue = Infinity;
153 a = a.component[maxParallelPrefix] || infiniteValue;
154 b = b.component[maxParallelPrefix] || infiniteValue;
155 // IE 6/7 Don't like Infinity - Infinity...
156 if (!isFinite(a) && !isFinite(b)) {
162 // Sort into *descending* order.
163 minSizeSortFn: function(a, b) {
164 return b.available - a.available;
167 constructor: function(config) {
170 me.callParent(arguments);
172 // The sort function needs access to properties in this, so must be bound.
173 me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
175 me.initOverflowHandler();
178 <span id='Ext-layout-container-Box-method-getChildBox'> /**
180 * Returns the current size and positioning of the passed child item.
181 * @param {Component} child The child Component to calculate the box for
182 * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
184 getChildBox: function(child) {
185 child = child.el || this.owner.getComponent(child).el;
187 left: child.getLeft(true),
188 top: child.getTop(true),
189 width: child.getWidth(),
190 height: child.getHeight()
194 <span id='Ext-layout-container-Box-method-calculateChildBox'> /**
196 * Calculates the size and positioning of the passed child item.
197 * @param {Component} child The child Component to calculate the box for
198 * @return {Object} Object containing box measurements for the child. Properties are left,top,width,height.
200 calculateChildBox: function(child) {
202 boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
206 child = me.owner.getComponent(child);
207 for (; i < ln; i++) {
208 if (boxes[i].component === child) {
214 <span id='Ext-layout-container-Box-method-calculateChildBoxes'> /**
216 * Calculates the size and positioning of each item in the box. This iterates over all of the rendered,
217 * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
218 * returns meta data such as maxSize which are useful when resizing layout wrappers such as this.innerCt.
219 * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
220 * @param {Object} targetSize Object containing target size and height
221 * @return {Object} Object containing box measurements for each child, plus meta data
223 calculateChildBoxes: function(visibleItems, targetSize) {
227 infiniteValue = Infinity,
230 parallelPrefix = me.parallelPrefix,
231 parallelPrefixCap = me.parallelPrefixCap,
232 perpendicularPrefix = me.perpendicularPrefix,
233 perpendicularPrefixCap = me.perpendicularPrefixCap,
234 parallelMinString = 'min' + parallelPrefixCap,
235 perpendicularMinString = 'min' + perpendicularPrefixCap,
236 perpendicularMaxString = 'max' + perpendicularPrefixCap,
238 parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
239 perpendicularSize = targetSize[perpendicularPrefix],
240 padding = me.padding,
241 parallelOffset = padding[me.parallelBefore],
242 paddingParallel = parallelOffset + padding[me.parallelAfter],
243 perpendicularOffset = padding[me.perpendicularLeftTop],
244 paddingPerpendicular = perpendicularOffset + padding[me.perpendicularRightBottom],
245 availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
247 isStart = me.pack == 'start',
248 isCenter = me.pack == 'center',
249 isEnd = me.pack == 'end',
251 constrain = Ext.Number.constrain,
252 visibleCount = visibleItems.length,
262 i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
263 tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
264 flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
265 perpendicularMargins, stretchSize;
267 //gather the total flex of all flexed items and the width taken up by fixed width items
268 for (i = 0; i < visibleCount; i++) {
269 child = visibleItems[i];
270 childPerpendicular = child[perpendicularPrefix];
271 me.layoutItem(child);
272 childMargins = child.margins;
273 parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
275 // Create the box description object for this child item.
278 margins: childMargins
281 // flex and not 'auto' width
283 totalFlex += child.flex;
284 childParallel = undefinedValue;
286 // Not flexed or 'auto' width or undefined width
288 if (!(child[parallelPrefix] && childPerpendicular)) {
289 childSize = child.getSize();
291 childParallel = child[parallelPrefix] || childSize[parallelPrefix];
292 childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
295 nonFlexSize += parallelMargins + (childParallel || 0);
296 desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
297 minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
299 // Max height for align - force layout of non-laid out subcontainers without a numeric height
300 if (typeof childPerpendicular != 'number') {
301 // Clear any static sizing and revert to flow so we can get a proper measurement
302 // child['set' + perpendicularPrefixCap](null);
303 childPerpendicular = child['get' + perpendicularPrefixCap]();
306 // Track the maximum perpendicular size for use by the stretch and stretchmax align config values.
307 maxSize = mmax(maxSize, childPerpendicular + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
309 tmpObj[parallelPrefix] = childParallel || undefinedValue;
310 tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
313 shortfall = desiredSize - parallelSize;
314 tooNarrow = minimumSize > parallelSize;
316 //the space available to the flexed items
317 availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
320 for (i = 0; i < visibleCount; i++) {
322 minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
323 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
324 box[parallelPrefix] = minSize;
328 //all flexed items should be sized to their minimum size, other items should be shrunk down until
329 //the shortfall has been accounted for
330 if (shortfall > 0) {
332 * When we have a shortfall but are not tooNarrow, we need to shrink the width of each non-flexed item.
333 * Flexed items are immediately reduced to their minWidth and anything already at minWidth is ignored.
334 * The remaining items are collected into the minWidths array, which is later used to distribute the shortfall.
336 for (i = 0; i < visibleCount; i++) {
337 item = visibleItems[i];
338 minSize = item[parallelMinString] || 0;
340 //shrink each non-flex tab by an equal amount to make them all fit. Flexed items are all
341 //shrunk to their minSize because they're flexible and should be the first to lose size
344 box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
345 box[parallelPrefix] = minSize;
350 available: boxes[i][parallelPrefix] - minSize,
356 //sort by descending amount of width remaining before minWidth is reached
357 Ext.Array.sort(minSizes, me.minSizeSortFn);
360 * Distribute the shortfall (difference between total desired size of all items and actual size available)
361 * between the non-flexed items. We try to distribute the shortfall evenly, but apply it to items with the
362 * smallest difference between their size and minSize first, so that if reducing the size by the average
363 * amount would make that item less than its minSize, we carry the remainder over to the next item.
365 for (i = 0, length = minSizes.length; i < length; i++) {
366 itemIndex = minSizes[i].index;
368 if (itemIndex == undefinedValue) {
371 item = visibleItems[itemIndex];
372 minSize = minSizes[i].minSize;
374 box = boxes[itemIndex];
375 oldSize = box[parallelPrefix];
376 newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
377 reduction = oldSize - newSize;
379 box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
380 box[parallelPrefix] = newSize;
381 shortfall -= reduction;
385 remainingSpace = availableSpace;
386 remainingFlex = totalFlex;
389 // Create an array containing *just the flexed boxes* for allocation of remainingSpace
390 for (i = 0; i < visibleCount; i++) {
391 child = visibleItems[i];
392 if (isStart && child.flex) {
393 flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
396 // The flexed boxes need to be sorted in ascending order of maxSize to work properly
397 // so that unallocated space caused by maxWidth being less than flexed width
398 // can be reallocated to subsequent flexed boxes.
399 Ext.Array.sort(flexedBoxes, me.flexSortFn);
401 // Calculate the size of each flexed item, and attempt to set it.
402 for (i = 0; i < flexedBoxes.length; i++) {
403 calcs = flexedBoxes[i];
404 child = calcs.component;
405 childMargins = calcs.margins;
407 flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
409 // Implement maxSize and minSize check
410 flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
412 // Remaining space has already had all parallel margins subtracted from it, so just subtract consumed size
413 remainingSpace -= flexedSize;
414 remainingFlex -= child.flex;
416 calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
417 calcs[parallelPrefix] = flexedSize;
423 parallelOffset += availableSpace / 2;
426 parallelOffset += availableSpace;
429 // Fix for left and right docked Components in a dock component layout. This is for docked Headers and docked Toolbars.
430 // Older Microsoft browsers do not size a position:absolute element's width to match its content.
431 // So in this case, in the updateInnerCtSize method we may need to adjust the size of the owning Container's element explicitly based upon
432 // the discovered max width. So here we put a calculatedWidth property in the metadata to facilitate this.
433 if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
435 calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
436 if (me.owner.frameSize) {
437 calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
439 // If the owning element is not sized, calculate the available width to center or stretch in based upon maxSize
440 availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
443 //finally, calculate the left and top position of each item
444 for (i = 0; i < visibleCount; i++) {
445 child = visibleItems[i];
448 childMargins = calcs.margins;
450 perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
452 // Advance past the "before" margin
453 parallelOffset += childMargins[me.parallelBefore];
455 calcs[me.parallelBefore] = parallelOffset;
456 calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
458 if (me.align == 'stretch') {
459 stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
460 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
461 calcs[perpendicularPrefix] = stretchSize;
463 else if (me.align == 'stretchmax') {
464 stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
465 calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
466 calcs[perpendicularPrefix] = stretchSize;
468 else if (me.align == me.alignCenteringString) {
469 // When calculating a centered position within the content box of the innerCt, the width of the borders must be subtracted from
470 // the size to yield the space available to center within.
471 // The updateInnerCtSize method explicitly adds the border widths to the set size of the innerCt.
472 diff = mmax(availPerpendicularSize, maxSize) - me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB) - calcs[perpendicularPrefix];
474 calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
478 // Advance past the box size and the "after" margin
479 parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
485 calculatedWidth: calculatedWidth,
487 nonFlexSize: nonFlexSize,
488 desiredSize: desiredSize,
489 minimumSize: minimumSize,
490 shortfall: shortfall,
496 onRemove: function(comp){
497 this.callParent(arguments);
498 if (this.overflowHandler) {
499 this.overflowHandler.onRemove(comp);
503 <span id='Ext-layout-container-Box-method-initOverflowHandler'> /**
506 initOverflowHandler: function() {
507 var handler = this.overflowHandler;
509 if (typeof handler == 'string') {
515 var handlerType = 'None';
516 if (handler && handler.type !== undefined) {
517 handlerType = handler.type;
520 var constructor = Ext.layout.container.boxOverflow[handlerType];
521 if (constructor[this.type]) {
522 constructor = constructor[this.type];
525 this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
528 <span id='Ext-layout-container-Box-method-onLayout'> /**
530 * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
533 onLayout: function() {
535 // Clear the innerCt size so it doesn't influence the child items.
536 if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
537 this.innerCt.setSize(null, null);
541 targetSize = me.getLayoutTargetSize(),
542 items = me.getVisibleItems(),
543 calcs = me.calculateChildBoxes(items, targetSize),
546 handler, method, results;
548 if (me.autoSize && calcs.meta.desiredSize) {
549 targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
552 //invoke the overflow handler, if one is configured
553 if (meta.shortfall > 0) {
554 handler = me.overflowHandler;
555 method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
557 results = handler[method](calcs, targetSize);
560 if (results.targetSize) {
561 targetSize = results.targetSize;
564 if (results.recalculate) {
565 items = me.getVisibleItems(owner);
566 calcs = me.calculateChildBoxes(items, targetSize);
571 me.overflowHandler.clearOverflow();
574 <span id='Ext-layout-container-Box-property-layoutTargetLastSize'> /**
576 * @property layoutTargetLastSize
578 * Private cache of the last measured size of the layout target. This should never be used except by
579 * BoxLayout subclasses during their onLayout run.
581 me.layoutTargetLastSize = targetSize;
583 <span id='Ext-layout-container-Box-property-childBoxCache'> /**
585 * @property childBoxCache
587 * Array of the last calculated height, width, top and left positions of each visible rendered component
588 * within the Box layout.
590 me.childBoxCache = calcs;
592 me.updateInnerCtSize(targetSize, calcs);
593 me.updateChildBoxes(boxes);
594 me.handleTargetOverflow(targetSize);
597 <span id='Ext-layout-container-Box-method-updateChildBoxes'> /**
598 </span> * Resizes and repositions each child component
599 * @param {Array} boxes The box measurements
601 updateChildBoxes: function(boxes) {
604 length = boxes.length,
606 dd = Ext.dd.DDM.getDDById(me.innerCt.id), // Any DD active on this layout's element (The BoxReorderer plugin does this.)
607 oldBox, newBox, changed, comp, boxAnim, animCallback;
609 for (; i < length; i++) {
611 comp = newBox.component;
613 // If a Component is being drag/dropped, skip positioning it.
614 // Accomodate the BoxReorderer plugin: Its current dragEl must not be positioned by the layout
615 if (dd && (dd.getDragEl() === comp.el.dom)) {
621 oldBox = me.getChildBox(comp);
623 // If we are animating, we build up an array of Anim config objects, one for each
624 // child Component which has any changed box properties. Those with unchanged
625 // properties are not animated.
627 // Animate may be a config object containing callback.
628 animCallback = me.animate.callback || me.animate;
630 layoutAnimation: true, // Component Target handler must use set*Calculated*Size
636 // Only set from and to properties when there's a change.
637 // Perform as few Component setter methods as possible.
638 // Temporarily set the property values that we are not animating
639 // so that doComponentLayout does not auto-size them.
640 if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
642 // boxAnim.from.width = oldBox.width;
643 boxAnim.to.width = newBox.width;
645 if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
647 // boxAnim.from.height = oldBox.height;
648 boxAnim.to.height = newBox.height;
650 if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
652 // boxAnim.from.left = oldBox.left;
653 boxAnim.to.left = newBox.left;
655 if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
657 // boxAnim.from.top = oldBox.top;
658 boxAnim.to.top = newBox.top;
661 animQueue.push(boxAnim);
664 if (newBox.dirtySize) {
665 if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
666 me.setItemSize(comp, newBox.width, newBox.height);
669 // Don't set positions to NaN
670 if (isNaN(newBox.left) || isNaN(newBox.top)) {
673 comp.setPosition(newBox.left, newBox.top);
677 // Kick off any queued animations
678 length = animQueue.length;
681 // A function which cleans up when a Component's animation is done.
682 // The last one to finish calls the callback.
683 var afterAnimate = function(anim) {
684 // When we've animated all changed boxes into position, clear our busy flag and call the callback.
687 me.layoutBusy = false;
688 if (Ext.isFunction(animCallback)) {
694 var beforeAnimate = function() {
695 me.layoutBusy = true;
698 // Start each box animation off
699 for (i = 0, length = animQueue.length; i < length; i++) {
700 boxAnim = animQueue[i];
702 // Clean up the Component after. Clean up the *layout* after the last animation finishes
703 boxAnim.listeners.afteranimate = afterAnimate;
705 // The layout is busy during animation, and may not be called, so set the flag when the first animation begins
707 boxAnim.listeners.beforeanimate = beforeAnimate;
709 if (me.animate.duration) {
710 boxAnim.duration = me.animate.duration;
712 comp = boxAnim.target;
713 delete boxAnim.target;
714 // Stop any currently running animation
715 comp.stopAnimation();
716 comp.animate(boxAnim);
721 <span id='Ext-layout-container-Box-method-updateInnerCtSize'> /**
723 * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
724 * to make sure all child items fit within it. We call this before sizing the children because if our child
725 * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
726 * again immediately afterwards, giving a performance hit.
727 * Subclasses should provide an implementation.
728 * @param {Object} currentSize The current height and width of the innerCt
729 * @param {Array} calculations The new box calculations of all items to be laid out
731 updateInnerCtSize: function(tSize, calcs) {
735 padding = me.padding,
737 height = tSize.height,
742 if (me.direction == 'horizontal') {
743 innerCtWidth = width;
744 innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
746 if (align == 'stretch') {
747 innerCtHeight = height;
749 else if (align == 'middle') {
750 innerCtHeight = mmax(height, innerCtHeight);
753 innerCtHeight = height;
754 innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
756 if (align == 'stretch') {
757 innerCtWidth = width;
759 else if (align == 'center') {
760 innerCtWidth = mmax(width, innerCtWidth);
763 me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
765 // If a calculated width has been found (and this only happens for auto-width vertical docked Components in old Microsoft browsers)
766 // then, if the Component has not assumed the size of its content, set it to do so.
767 if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
768 me.owner.el.setWidth(meta.calculatedWidth);
771 if (me.innerCt.dom.scrollTop) {
772 me.innerCt.dom.scrollTop = 0;
776 <span id='Ext-layout-container-Box-method-handleTargetOverflow'> /**
778 * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
779 * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
780 * target. Having a Box layout inside such a target is therefore not recommended.
781 * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
782 * @param {Ext.container.Container} container The container
783 * @param {Ext.core.Element} target The target element
784 * @return True if the layout overflowed, and was reflowed in a secondary onLayout call.
786 handleTargetOverflow: function(previousTargetSize) {
787 var target = this.getTarget(),
788 overflow = target.getStyle('overflow'),
791 if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
792 newTargetSize = this.getLayoutTargetSize();
793 if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
794 this.adjustmentPass = true;
800 delete this.adjustmentPass;
804 isValidParent : function(item, target, position) {
805 // Note: Box layouts do not care about order within the innerCt element because it's an absolutely positioning layout
806 // We only care whether the item is a direct child of the innerCt element.
807 var itemEl = item.el ? item.el.dom : Ext.getDom(item);
808 return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
811 // Overridden method from AbstractContainer.
812 // Used in the base AbstractLayout.beforeLayout method to render all items into.
813 getRenderTarget: function() {
815 // the innerCt prevents wrapping and shuffling while the container is resizing
816 this.innerCt = this.getTarget().createChild({
820 this.padding = Ext.util.Format.parseBox(this.padding);
826 renderItem: function(item, target) {
827 this.callParent(arguments);
829 itemEl = item.getEl(),
830 style = itemEl.dom.style,
831 margins = item.margins || item.margin;
833 // Parse the item's margin/margins specification
835 if (Ext.isString(margins) || Ext.isNumber(margins)) {
836 margins = Ext.util.Format.parseBox(margins);
838 Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
841 margins = Ext.apply({}, me.defaultMargins);
844 // Add any before/after CSS margins to the configured margins, and zero the CSS margins
845 margins.top += itemEl.getMargin('t');
846 margins.right += itemEl.getMargin('r');
847 margins.bottom += itemEl.getMargin('b');
848 margins.left += itemEl.getMargin('l');
849 style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
851 // Item must reference calculated margins.
852 item.margins = margins;
855 <span id='Ext-layout-container-Box-method-destroy'> /**
858 destroy: function() {
859 Ext.destroy(this.overflowHandler);
860 this.callParent(arguments);