Upgrade to ExtJS 3.2.1 - Released 04/27/2010
[extjs.git] / docs / source / BoxLayout.html
1 <html>
2 <head>
3   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    
4   <title>The source code</title>
5     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
6     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
7 </head>
8 <body  onload="prettyPrint();">
9     <pre class="prettyprint lang-js">/*!
10  * Ext JS Library 3.2.1
11  * Copyright(c) 2006-2010 Ext JS, Inc.
12  * licensing@extjs.com
13  * http://www.extjs.com/license
14  */
15 <div id="cls-Ext.layout.BoxLayout"></div>/**
16  * @class Ext.layout.BoxLayout
17  * @extends Ext.layout.ContainerLayout
18  * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
19  */
20 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
21     <div id="cfg-Ext.layout.BoxLayout-defaultMargins"></div>/**
22      * @cfg {Object} defaultMargins
23      * <p>If the individual contained items do not have a <tt>margins</tt>
24      * property specified, the default margins from this property will be
25      * applied to each item.</p>
26      * <br><p>This property may be specified as an object containing margins
27      * to apply in the format:</p><pre><code>
28 {
29     top: (top margin),
30     right: (right margin),
31     bottom: (bottom margin),
32     left: (left margin)
33 }</code></pre>
34      * <p>This property may also be specified as a string containing
35      * space-separated, numeric margin values. The order of the sides associated
36      * with each value matches the way CSS processes margin values:</p>
37      * <div class="mdetail-params"><ul>
38      * <li>If there is only one value, it applies to all sides.</li>
39      * <li>If there are two values, the top and bottom borders are set to the
40      * first value and the right and left are set to the second.</li>
41      * <li>If there are three values, the top is set to the first value, the left
42      * and right are set to the second, and the bottom is set to the third.</li>
43      * <li>If there are four values, they apply to the top, right, bottom, and
44      * left, respectively.</li>
45      * </ul></div>
46      * <p>Defaults to:</p><pre><code>
47      * {top:0, right:0, bottom:0, left:0}
48      * </code></pre>
49      */
50     defaultMargins : {left:0,top:0,right:0,bottom:0},
51     <div id="cfg-Ext.layout.BoxLayout-padding"></div>/**
52      * @cfg {String} padding
53      * <p>Sets the padding to be applied to all child items managed by this layout.</p>
54      * <p>This property must be specified as a string containing
55      * space-separated, numeric padding values. The order of the sides associated
56      * with each value matches the way CSS processes padding values:</p>
57      * <div class="mdetail-params"><ul>
58      * <li>If there is only one value, it applies to all sides.</li>
59      * <li>If there are two values, the top and bottom borders are set to the
60      * first value and the right and left are set to the second.</li>
61      * <li>If there are three values, the top is set to the first value, the left
62      * and right are set to the second, and the bottom is set to the third.</li>
63      * <li>If there are four values, they apply to the top, right, bottom, and
64      * left, respectively.</li>
65      * </ul></div>
66      * <p>Defaults to: <code>"0"</code></p>
67      */
68     padding : '0',
69     // documented in subclasses
70     pack : 'start',
71
72     // private
73     monitorResize : true,
74     type: 'box',
75     scrollOffset : 0,
76     extraCls : 'x-box-item',
77     targetCls : 'x-box-layout-ct',
78     innerCls : 'x-box-inner',
79
80     constructor : function(config){
81         Ext.layout.BoxLayout.superclass.constructor.call(this, config);
82
83         if (Ext.isString(this.defaultMargins)) {
84             this.defaultMargins = this.parseMargins(this.defaultMargins);
85         }
86     },
87
88     /**
89      * @private
90      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
91      * when laying out
92      */
93     onLayout: function(container, target) {
94         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
95
96         var items = this.getVisibleItems(container),
97             tSize = this.getLayoutTargetSize();
98
99         /**
100          * @private
101          * @property layoutTargetLastSize
102          * @type Object
103          * Private cache of the last measured size of the layout target. This should never be used except by
104          * BoxLayout subclasses during their onLayout run.
105          */
106         this.layoutTargetLastSize = tSize;
107
108         /**
109          * @private
110          * @property childBoxCache
111          * @type Array
112          * Array of the last calculated height, width, top and left positions of each visible rendered component
113          * within the Box layout.
114          */
115         this.childBoxCache = this.calculateChildBoxes(items, tSize);
116
117         this.updateInnerCtSize(tSize, this.childBoxCache);
118         this.updateChildBoxes(this.childBoxCache.boxes);
119
120         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
121         this.handleTargetOverflow(tSize, container, target);
122     },
123
124     <div id="method-Ext.layout.BoxLayout-updateChildBoxes"></div>/**
125      * Resizes and repositions each child component
126      * @param {Array} boxes The box measurements
127      */
128     updateChildBoxes: function(boxes) {
129         for (var i = 0, length = boxes.length; i < length; i++) {
130             var box  = boxes[i],
131                 comp = box.component;
132
133             if (box.dirtySize) {
134                 comp.setSize(box.width, box.height);
135             }
136             // Don't set positions to NaN
137             if (isNaN(box.left) || isNaN(box.top)) {
138                 continue;
139             }
140             comp.setPosition(box.left, box.top);
141         }
142     },
143
144     /**
145      * @private
146      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
147      * to make sure all child items fit within it. We call this before sizing the children because if our child
148      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
149      * again immediately afterwards, giving a performance hit.
150      * Subclasses should provide an implementation.
151      * @param {Object} currentSize The current height and width of the innerCt
152      * @param {Array} calculations The new box calculations of all items to be laid out
153      */
154     updateInnerCtSize: Ext.emptyFn,
155
156     /**
157      * @private
158      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
159      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
160      * target. Having a Box layout inside such a target is therefore not recommended.
161      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
162      * @param {Ext.Container} container The container
163      * @param {Ext.Element} target The target element
164      */
165     handleTargetOverflow: function(previousTargetSize, container, target) {
166         var overflow = target.getStyle('overflow');
167
168         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
169             var newTargetSize = this.getLayoutTargetSize();
170             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
171                 this.adjustmentPass = true;
172                 this.onLayout(container, target);
173             }
174         }
175
176         delete this.adjustmentPass;
177     },
178
179     // private
180     isValidParent : function(c, target){
181         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
182     },
183
184     /**
185      * @private
186      * Returns all items that are both rendered and visible
187      * @return {Array} All matching items
188      */
189     getVisibleItems: function(ct) {
190         var ct  = ct || this.container,
191             t   = ct.getLayoutTarget(),
192             cti = ct.items.items,
193             len = cti.length,
194
195             i, c, items = [];
196
197         for (i = 0; i < len; i++) {
198             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true){
199                 items.push(c);
200             }
201         }
202
203         return items;
204     },
205
206     // private
207     renderAll : function(ct, target){
208         if(!this.innerCt){
209             // the innerCt prevents wrapping and shuffling while
210             // the container is resizing
211             this.innerCt = target.createChild({cls:this.innerCls});
212             this.padding = this.parseMargins(this.padding);
213         }
214         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
215     },
216
217     getLayoutTargetSize : function(){
218         var target = this.container.getLayoutTarget(), ret;
219         if (target) {
220             ret = target.getViewSize();
221
222             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
223             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
224             // with getViewSize
225             if (Ext.isIE && Ext.isStrict && ret.width == 0){
226                 ret =  target.getStyleSize();
227             }
228
229             ret.width -= target.getPadding('lr');
230             ret.height -= target.getPadding('tb');
231         }
232         return ret;
233     },
234
235     // private
236     renderItem : function(c){
237         if(Ext.isString(c.margins)){
238             c.margins = this.parseMargins(c.margins);
239         }else if(!c.margins){
240             c.margins = this.defaultMargins;
241         }
242         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
243     }
244 });
245
246 <div id="cls-Ext.layout.VBoxLayout"></div>/**
247  * @class Ext.layout.VBoxLayout
248  * @extends Ext.layout.BoxLayout
249  * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
250  * space between child items containing a numeric <code>flex</code> configuration.</p>
251  * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
252  */
253 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
254     <div id="cfg-Ext.layout.VBoxLayout-align"></div>/**
255      * @cfg {String} align
256      * Controls how the child items of the container are aligned. Acceptable configuration values for this
257      * property are:
258      * <div class="mdetail-params"><ul>
259      * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
260      * at the <b>left</b> side of the container</div></li>
261      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
262      * <b>mid-width</b> of the container</div></li>
263      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
264      * the width of the container</div></li>
265      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
266      * the size of the largest item.</div></li>
267      * </ul></div>
268      */
269     align : 'left', // left, center, stretch, strechmax
270     type: 'vbox',
271
272     <div id="cfg-Ext.layout.VBoxLayout-pack"></div>/**
273      * @cfg {String} pack
274      * Controls how the child items of the container are packed together. Acceptable configuration values
275      * for this property are:
276      * <div class="mdetail-params"><ul>
277      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
278      * <b>top</b> side of container</div></li>
279      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
280      * <b>mid-height</b> of container</div></li>
281      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
282      * side of container</div></li>
283      * </ul></div>
284      */
285
286     <div id="cfg-Ext.layout.VBoxLayout-flex"></div>/**
287      * @cfg {Number} flex
288      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
289      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
290      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
291      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
292      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
293      */
294
295     /**
296      * @private
297      * See parent documentation
298      */
299     updateInnerCtSize: function(tSize, calcs) {
300         var innerCtHeight = tSize.height,
301             innerCtWidth  = calcs.meta.maxWidth + this.padding.left + this.padding.right;
302
303         if (this.align == 'stretch') {
304             innerCtWidth = tSize.width;
305         } else if (this.align == 'center') {
306             innerCtWidth = Math.max(tSize.width, innerCtWidth);
307         }
308
309         //we set the innerCt size first because if our child items are larger than the previous innerCt size
310         //the browser will insert scrollbars and then remove them again immediately afterwards
311         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
312     },
313
314     /**
315      * @private
316      * Calculates the size and positioning of each item in the VBox. This iterates over all of the rendered,
317      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
318      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
319      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
320      * @param {Object} targetSize Object containing target size and height
321      * @return {Object} Object containing box measurements for each child, plus meta data
322      */
323     calculateChildBoxes: function(visibleItems, targetSize) {
324         var visibleCount = visibleItems.length,
325
326             padding      = this.padding,
327             topOffset    = padding.top,
328             leftOffset   = padding.left,
329             paddingVert  = topOffset  + padding.bottom,
330             paddingHoriz = leftOffset + padding.right,
331
332             width        = targetSize.width - this.scrollOffset,
333             height       = targetSize.height,
334             availWidth   = Math.max(0, width - paddingHoriz),
335
336             isStart      = this.pack == 'start',
337             isCenter     = this.pack == 'center',
338             isEnd        = this.pack == 'end',
339
340             nonFlexHeight= 0,
341             maxWidth     = 0,
342             totalFlex    = 0,
343
344             //used to cache the calculated size and position values for each child item
345             boxes        = [],
346
347             //used in the for loops below, just declared here for brevity
348             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedHeight, horizMargins, stretchWidth;
349
350             //gather the total flex of all flexed items and the width taken up by fixed width items
351             for (i = 0; i < visibleCount; i++) {
352                 child = visibleItems[i];
353                 childHeight = child.height;
354                 childWidth  = child.width;
355                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
356
357
358                 // Static height (numeric) requires no calcs
359                 if (!Ext.isNumber(childHeight)) {
360
361                     // flex and not 'auto' height
362                     if (child.flex && !childHeight) {
363                         totalFlex += child.flex;
364
365                     // Not flexed or 'auto' height or undefined height
366                     } else {
367                         //Render and layout sub-containers without a flex or width defined, as otherwise we
368                         //don't know how wide the sub-container should be and cannot calculate flexed widths
369                         if (!childHeight && canLayout) {
370                             child.doLayout();
371                         }
372
373                         childSize = child.getSize();
374                         childWidth = childSize.width;
375                         childHeight = childSize.height;
376                     }
377                 }
378
379                 childMargins = child.margins;
380
381                 nonFlexHeight += (childHeight || 0) + childMargins.top + childMargins.bottom;
382
383                 // Max width for align - force layout of non-layed out subcontainers without a numeric width
384                 if (!Ext.isNumber(childWidth)) {
385                     if (canLayout) {
386                         child.doLayout();
387                     }
388                     childWidth = child.getWidth();
389                 }
390
391                 maxWidth = Math.max(maxWidth, childWidth + childMargins.left + childMargins.right);
392
393                 //cache the size of each child component
394                 boxes.push({
395                     component: child,
396                     height   : childHeight || undefined,
397                     width    : childWidth || undefined
398                 });
399             }
400
401             //the height available to the flexed items
402             var availableHeight = Math.max(0, (height - nonFlexHeight - paddingVert));
403
404             if (isCenter) {
405                 topOffset += availableHeight / 2;
406             } else if (isEnd) {
407                 topOffset += availableHeight;
408             }
409
410             //temporary variables used in the flex height calculations below
411             var remainingHeight = availableHeight,
412                 remainingFlex   = totalFlex;
413
414             //calculate the height of each flexed item, and the left + top positions of every item
415             for (i = 0; i < visibleCount; i++) {
416                 child = visibleItems[i];
417                 calcs = boxes[i];
418
419                 childMargins = child.margins;
420                 horizMargins = childMargins.left + childMargins.right;
421
422                 topOffset   += childMargins.top;
423
424                 if (isStart && child.flex && !child.height) {
425                     flexedHeight     = Math.ceil((child.flex / remainingFlex) * remainingHeight);
426                     remainingHeight -= flexedHeight;
427                     remainingFlex   -= child.flex;
428
429                     calcs.height = flexedHeight;
430                     calcs.dirtySize = true;
431                 }
432
433                 calcs.left = leftOffset + childMargins.left;
434                 calcs.top  = topOffset;
435
436                 switch (this.align) {
437                     case 'stretch':
438                         stretchWidth = availWidth - horizMargins;
439                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
440                         calcs.dirtySize = true;
441                         break;
442                     case 'stretchmax':
443                         stretchWidth = maxWidth - horizMargins;
444                         calcs.width  = stretchWidth.constrain(child.minWidth || 0, child.maxWidth || 1000000);
445                         calcs.dirtySize = true;
446                         break;
447                     case 'center':
448                         var diff = availWidth - calcs.width - horizMargins;
449                         if (diff > 0) {
450                             calcs.left = leftOffset + horizMargins + (diff / 2);
451                         }
452                 }
453
454                 topOffset += calcs.height + childMargins.bottom;
455             }
456
457         return {
458             boxes: boxes,
459             meta : {
460                 maxWidth: maxWidth
461             }
462         };
463     }
464 });
465
466 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
467
468 <div id="cls-Ext.layout.HBoxLayout"></div>/**
469  * @class Ext.layout.HBoxLayout
470  * @extends Ext.layout.BoxLayout
471  * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
472  * space between child items containing a numeric <code>flex</code> configuration.</p>
473  * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
474  */
475 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
476     <div id="cfg-Ext.layout.HBoxLayout-align"></div>/**
477      * @cfg {String} align
478      * Controls how the child items of the container are aligned. Acceptable configuration values for this
479      * property are:
480      * <div class="mdetail-params"><ul>
481      * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
482      * at the <b>top</b> of the container</div></li>
483      * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
484      * <b>middle</b> of the container</div></li>
485      * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
486      * the height of the container</div></li>
487      * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
488      * the height of the largest item.</div></li>
489      */
490     align: 'top', // top, middle, stretch, strechmax
491
492     type : 'hbox',
493
494     /**
495      * @private
496      * See parent documentation
497      */
498     updateInnerCtSize: function(tSize, calcs) {
499         var innerCtWidth  = tSize.width,
500             innerCtHeight = calcs.meta.maxHeight + this.padding.top + this.padding.bottom;
501
502         if (this.align == 'stretch') {
503             innerCtHeight = tSize.height;
504         } else if (this.align == 'middle') {
505             innerCtHeight = Math.max(tSize.height, innerCtHeight);
506         }
507
508         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
509     },
510
511     <div id="cfg-Ext.layout.HBoxLayout-pack"></div>/**
512      * @cfg {String} pack
513      * Controls how the child items of the container are packed together. Acceptable configuration values
514      * for this property are:
515      * <div class="mdetail-params"><ul>
516      * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
517      * <b>left</b> side of container</div></li>
518      * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
519      * <b>mid-width</b> of container</div></li>
520      * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
521      * side of container</div></li>
522      * </ul></div>
523      */
524     <div id="cfg-Ext.layout.HBoxLayout-flex"></div>/**
525      * @cfg {Number} flex
526      * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
527      * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
528      * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
529      * a <tt>flex</tt> value specified.  Any child items that have either a <tt>flex = 0</tt> or
530      * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
531      */
532
533     /**
534      * @private
535      * Calculates the size and positioning of each item in the HBox. This iterates over all of the rendered,
536      * visible items and returns a height, width, top and left for each, as well as a reference to each. Also
537      * returns meta data such as maxHeight which are useful when resizing layout wrappers such as this.innerCt.
538      * @param {Array} visibleItems The array of all rendered, visible items to be calculated for
539      * @param {Object} targetSize Object containing target size and height
540      * @return {Object} Object containing box measurements for each child, plus meta data
541      */
542     calculateChildBoxes: function(visibleItems, targetSize) {
543         var visibleCount = visibleItems.length,
544
545             padding      = this.padding,
546             topOffset    = padding.top,
547             leftOffset   = padding.left,
548             paddingVert  = topOffset  + padding.bottom,
549             paddingHoriz = leftOffset + padding.right,
550
551             width        = targetSize.width - this.scrollOffset,
552             height       = targetSize.height,
553             availHeight  = Math.max(0, height - paddingVert),
554
555             isStart      = this.pack == 'start',
556             isCenter     = this.pack == 'center',
557             isEnd        = this.pack == 'end',
558             // isRestore    = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
559
560             nonFlexWidth = 0,
561             maxHeight    = 0,
562             totalFlex    = 0,
563
564             //used to cache the calculated size and position values for each child item
565             boxes        = [],
566
567             //used in the for loops below, just declared here for brevity
568             child, childWidth, childHeight, childSize, childMargins, canLayout, i, calcs, flexedWidth, vertMargins, stretchHeight;
569
570             //gather the total flex of all flexed items and the width taken up by fixed width items
571             for (i = 0; i < visibleCount; i++) {
572                 child       = visibleItems[i];
573                 childHeight = child.height;
574                 childWidth  = child.width;
575                 canLayout   = !child.hasLayout && Ext.isFunction(child.doLayout);
576
577                 // Static width (numeric) requires no calcs
578                 if (!Ext.isNumber(childWidth)) {
579
580                     // flex and not 'auto' width
581                     if (child.flex && !childWidth) {
582                         totalFlex += child.flex;
583
584                     // Not flexed or 'auto' width or undefined width
585                     } else {
586                         //Render and layout sub-containers without a flex or width defined, as otherwise we
587                         //don't know how wide the sub-container should be and cannot calculate flexed widths
588                         if (!childWidth && canLayout) {
589                             child.doLayout();
590                         }
591
592                         childSize   = child.getSize();
593                         childWidth  = childSize.width;
594                         childHeight = childSize.height;
595                     }
596                 }
597
598                 childMargins = child.margins;
599
600                 nonFlexWidth += (childWidth || 0) + childMargins.left + childMargins.right;
601
602                 // Max height for align - force layout of non-layed out subcontainers without a numeric height
603                 if (!Ext.isNumber(childHeight)) {
604                     if (canLayout) {
605                         child.doLayout();
606                     }
607                     childHeight = child.getHeight();
608                 }
609
610                 maxHeight = Math.max(maxHeight, childHeight + childMargins.top + childMargins.bottom);
611
612                 //cache the size of each child component
613                 boxes.push({
614                     component: child,
615                     height   : childHeight || undefined,
616                     width    : childWidth || undefined
617                 });
618             }
619
620             //the width available to the flexed items
621             var availableWidth = Math.max(0, (width - nonFlexWidth - paddingHoriz));
622
623             if (isCenter) {
624                 leftOffset += availableWidth / 2;
625             } else if (isEnd) {
626                 leftOffset += availableWidth;
627             }
628
629             //temporary variables used in the flex width calculations below
630             var remainingWidth = availableWidth,
631                 remainingFlex  = totalFlex;
632
633             //calculate the widths of each flexed item, and the left + top positions of every item
634             for (i = 0; i < visibleCount; i++) {
635                 child = visibleItems[i];
636                 calcs = boxes[i];
637
638                 childMargins = child.margins;
639                 vertMargins  = childMargins.top + childMargins.bottom;
640
641                 leftOffset  += childMargins.left;
642
643                 if (isStart && child.flex && !child.width) {
644                     flexedWidth     = Math.ceil((child.flex / remainingFlex) * remainingWidth);
645                     remainingWidth -= flexedWidth;
646                     remainingFlex  -= child.flex;
647
648                     calcs.width = flexedWidth;
649                     calcs.dirtySize = true;
650                 }
651
652                 calcs.left = leftOffset;
653                 calcs.top  = topOffset + childMargins.top;
654
655                 switch (this.align) {
656                     case 'stretch':
657                         stretchHeight = availHeight - vertMargins;
658                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
659                         calcs.dirtySize = true;
660                         break;
661                     case 'stretchmax':
662                         stretchHeight = maxHeight - vertMargins;
663                         calcs.height  = stretchHeight.constrain(child.minHeight || 0, child.maxHeight || 1000000);
664                         calcs.dirtySize = true;
665                         break;
666                     case 'middle':
667                         var diff = availHeight - calcs.height - vertMargins;
668                         if (diff > 0) {
669                             calcs.top = topOffset + vertMargins + (diff / 2);
670                         }
671                 }
672                 leftOffset += calcs.width + childMargins.right;
673             }
674
675         return {
676             boxes: boxes,
677             meta : {
678                 maxHeight: maxHeight
679             }
680         };
681     }
682 });
683
684 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;
685 </pre>    
686 </body>
687 </html>