3 * Copyright(c) 2006-2010 Ext JS, LLC
5 * http://www.extjs.com/license
8 * @class Ext.layout.BoxLayout
9 * @extends Ext.layout.ContainerLayout
10 * <p>Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.</p>
12 Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
14 * @cfg {Object} defaultMargins
15 * <p>If the individual contained items do not have a <tt>margins</tt>
16 * property specified, the default margins from this property will be
17 * applied to each item.</p>
18 * <br><p>This property may be specified as an object containing margins
19 * to apply in the format:</p><pre><code>
22 right: (right margin),
23 bottom: (bottom margin),
26 * <p>This property may also be specified as a string containing
27 * space-separated, numeric margin values. The order of the sides associated
28 * with each value matches the way CSS processes margin values:</p>
29 * <div class="mdetail-params"><ul>
30 * <li>If there is only one value, it applies to all sides.</li>
31 * <li>If there are two values, the top and bottom borders are set to the
32 * first value and the right and left are set to the second.</li>
33 * <li>If there are three values, the top is set to the first value, the left
34 * and right are set to the second, and the bottom is set to the third.</li>
35 * <li>If there are four values, they apply to the top, right, bottom, and
36 * left, respectively.</li>
38 * <p>Defaults to:</p><pre><code>
39 * {top:0, right:0, bottom:0, left:0}
42 defaultMargins : {left:0,top:0,right:0,bottom:0},
44 * @cfg {String} padding
45 * <p>Sets the padding to be applied to all child items managed by this layout.</p>
46 * <p>This property must be specified as a string containing
47 * space-separated, numeric padding values. The order of the sides associated
48 * with each value matches the way CSS processes padding values:</p>
49 * <div class="mdetail-params"><ul>
50 * <li>If there is only one value, it applies to all sides.</li>
51 * <li>If there are two values, the top and bottom borders are set to the
52 * first value and the right and left are set to the second.</li>
53 * <li>If there are three values, the top is set to the first value, the left
54 * and right are set to the second, and the bottom is set to the third.</li>
55 * <li>If there are four values, they apply to the top, right, bottom, and
56 * left, respectively.</li>
58 * <p>Defaults to: <code>"0"</code></p>
61 // documented in subclasses
68 extraCls : 'x-box-item',
69 targetCls : 'x-box-layout-ct',
70 innerCls : 'x-box-inner',
72 constructor : function(config){
73 Ext.layout.BoxLayout.superclass.constructor.call(this, config);
74 if(Ext.isString(this.defaultMargins)){
75 this.defaultMargins = this.parseMargins(this.defaultMargins);
80 isValidParent : function(c, target){
81 return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
85 renderAll : function(ct, target){
87 // the innerCt prevents wrapping and shuffling while
88 // the container is resizing
89 this.innerCt = target.createChild({cls:this.innerCls});
90 this.padding = this.parseMargins(this.padding);
92 Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
95 onLayout : function(ct, target){
96 this.renderAll(ct, target);
99 getLayoutTargetSize : function(){
100 var target = this.container.getLayoutTarget(), ret;
102 ret = target.getViewSize();
103 ret.width -= target.getPadding('lr');
104 ret.height -= target.getPadding('tb');
110 renderItem : function(c){
111 if(Ext.isString(c.margins)){
112 c.margins = this.parseMargins(c.margins);
113 }else if(!c.margins){
114 c.margins = this.defaultMargins;
116 Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
121 * @class Ext.layout.VBoxLayout
122 * @extends Ext.layout.BoxLayout
123 * <p>A layout that arranges items vertically down a Container. This layout optionally divides available vertical
124 * space between child items containing a numeric <code>flex</code> configuration.</p>
125 * This layout may also be used to set the widths of child items by configuring it with the {@link #align} option.
127 Ext.layout.VBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
129 * @cfg {String} align
130 * Controls how the child items of the container are aligned. Acceptable configuration values for this
132 * <div class="mdetail-params"><ul>
133 * <li><b><tt>left</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned horizontally
134 * at the <b>left</b> side of the container</div></li>
135 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are aligned horizontally at the
136 * <b>mid-width</b> of the container</div></li>
137 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched horizontally to fill
138 * the width of the container</div></li>
139 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched horizontally to
140 * the size of the largest item.</div></li>
143 align : 'left', // left, center, stretch, strechmax
147 * Controls how the child items of the container are packed together. Acceptable configuration values
148 * for this property are:
149 * <div class="mdetail-params"><ul>
150 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
151 * <b>top</b> side of container</div></li>
152 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
153 * <b>mid-height</b> of container</div></li>
154 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>bottom</b>
155 * side of container</div></li>
160 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
161 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>vertically</b>
162 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
163 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
164 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
168 onLayout : function(ct, target){
169 Ext.layout.VBoxLayout.superclass.onLayout.call(this, ct, target);
171 var cs = this.getRenderedItems(ct), csLen = cs.length,
172 c, i, cm, ch, margin, cl, diff, aw, availHeight,
173 size = this.getLayoutTargetSize(),
175 h = size.height - this.scrollOffset,
176 l = this.padding.left,
177 t = this.padding.top,
178 isStart = this.pack == 'start',
187 // Do only width calculations and apply those first, as they can affect height
188 for (i = 0 ; i < csLen; i++) {
191 margin = cm.top + cm.bottom;
192 // Max height for align
193 maxWidth = Math.max(maxWidth, c.getWidth() + cm.left + cm.right);
196 var innerCtWidth = maxWidth + this.padding.left + this.padding.right;
199 this.innerCt.setSize(w, h);
203 this.innerCt.setSize(innerCtWidth, h);
206 this.innerCt.setSize(w = Math.max(w, innerCtWidth), h);
210 var availableWidth = Math.max(0, w - this.padding.left - this.padding.right);
212 for (i = 0 ; i < csLen; i++) {
215 if(this.align == 'stretch'){
216 c.setWidth(((w - (this.padding.left + this.padding.right)) - (cm.left + cm.right)).constrain(
217 c.minWidth || 0, c.maxWidth || 1000000));
218 }else if(this.align == 'stretchmax'){
219 c.setWidth((maxWidth - (cm.left + cm.right)).constrain(
220 c.minWidth || 0, c.maxWidth || 1000000));
221 }else if(isStart && c.flex){
227 // Height calculations
228 for (i = 0 ; i < csLen; i++) {
230 // Total of all the flex values
231 totalFlex += c.flex || 0;
232 // Don't run height calculations on flexed items
234 // Render and layout sub-containers without a flex or height, once
235 if (!c.height && !c.hasLayout && c.doLayout) {
244 // Determine how much height is available to flex
245 extraHeight += ch + cm.top + cm.bottom;
247 // Final avail height calc
248 availHeight = Math.max(0, (h - extraHeight - this.padding.top - this.padding.bottom));
250 var leftOver = availHeight;
251 for (i = 0 ; i < csLen; i++) {
253 if(isStart && c.flex){
254 ch = Math.floor(availHeight * (c.flex / totalFlex));
259 if(this.pack == 'center'){
260 t += availHeight ? availHeight / 2 : 0;
261 }else if(this.pack == 'end'){
266 for (i = 0 ; i < csLen; i++) {
271 cl = l + cm.left // default left pos
273 // Adjust left pos for centering
274 if(this.align == 'center'){
275 if((diff = availableWidth - (c.getWidth() + cm.left + cm.right)) > 0){
281 c.setPosition(cl, t);
282 if(isStart && c.flex){
283 ch = Math.max(0, heights[idx++] + (leftOver-- > 0 ? 1 : 0));
290 // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
291 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
292 var ts = this.getLayoutTargetSize();
293 if (ts.width != size.width || ts.height != size.height){
294 this.adjustmentPass = true;
295 this.onLayout(ct, target);
298 delete this.adjustmentPass;
302 Ext.Container.LAYOUTS.vbox = Ext.layout.VBoxLayout;
305 * @class Ext.layout.HBoxLayout
306 * @extends Ext.layout.BoxLayout
307 * <p>A layout that arranges items horizontally across a Container. This layout optionally divides available horizontal
308 * space between child items containing a numeric <code>flex</code> configuration.</p>
309 * This layout may also be used to set the heights of child items by configuring it with the {@link #align} option.
311 Ext.layout.HBoxLayout = Ext.extend(Ext.layout.BoxLayout, {
313 * @cfg {String} align
314 * Controls how the child items of the container are aligned. Acceptable configuration values for this
316 * <div class="mdetail-params"><ul>
317 * <li><b><tt>top</tt></b> : <b>Default</b><div class="sub-desc">child items are aligned vertically
318 * at the <b>top</b> of the container</div></li>
319 * <li><b><tt>middle</tt></b> : <div class="sub-desc">child items are aligned vertically in the
320 * <b>middle</b> of the container</div></li>
321 * <li><b><tt>stretch</tt></b> : <div class="sub-desc">child items are stretched vertically to fill
322 * the height of the container</div></li>
323 * <li><b><tt>stretchmax</tt></b> : <div class="sub-desc">child items are stretched vertically to
324 * the height of the largest item.</div></li>
326 align : 'top', // top, middle, stretch, strechmax
330 * Controls how the child items of the container are packed together. Acceptable configuration values
331 * for this property are:
332 * <div class="mdetail-params"><ul>
333 * <li><b><tt>start</tt></b> : <b>Default</b><div class="sub-desc">child items are packed together at
334 * <b>left</b> side of container</div></li>
335 * <li><b><tt>center</tt></b> : <div class="sub-desc">child items are packed together at
336 * <b>mid-width</b> of container</div></li>
337 * <li><b><tt>end</tt></b> : <div class="sub-desc">child items are packed together at <b>right</b>
338 * side of container</div></li>
343 * This configuation option is to be applied to <b>child <tt>items</tt></b> of the container managed
344 * by this layout. Each child item with a <tt>flex</tt> property will be flexed <b>horizontally</b>
345 * according to each item's <b>relative</b> <tt>flex</tt> value compared to the sum of all items with
346 * a <tt>flex</tt> value specified. Any child items that have either a <tt>flex = 0</tt> or
347 * <tt>flex = undefined</tt> will not be 'flexed' (the initial size will not be changed).
351 onLayout : function(ct, target){
352 Ext.layout.HBoxLayout.superclass.onLayout.call(this, ct, target);
354 var cs = this.getRenderedItems(ct), csLen = cs.length,
355 c, i, cm, cw, ch, diff, availWidth,
356 size = this.getLayoutTargetSize(),
357 w = size.width - this.scrollOffset,
359 l = this.padding.left,
360 t = this.padding.top,
361 isStart = this.pack == 'start',
362 isRestore = ['stretch', 'stretchmax'].indexOf(this.align) == -1,
368 for (i = 0 ; i < csLen; i++) {
370 // Total of all the flex values
371 totalFlex += c.flex || 0;
372 // Don't run width calculations on flexed items
374 // Render and layout sub-containers without a flex or width, once
375 if (!c.width && !c.hasLayout && c.doLayout) {
383 // Determine how much width is available to flex
384 extraWidth += cw + cm.left + cm.right;
385 // Max height for align
386 maxHeight = Math.max(maxHeight, c.getHeight() + cm.top + cm.bottom);
388 // Final avail width calc
389 availWidth = Math.max(0, (w - extraWidth - this.padding.left - this.padding.right));
391 var innerCtHeight = maxHeight + this.padding.top + this.padding.bottom;
394 this.innerCt.setSize(w, h);
398 this.innerCt.setSize(w, innerCtHeight);
401 this.innerCt.setSize(w, h = Math.max(h, innerCtHeight));
405 var leftOver = availWidth,
409 availableHeight = Math.max(0, h - this.padding.top - this.padding.bottom);
411 for (i = 0 ; i < csLen; i++) {
413 if(isStart && c.flex){
414 cw = Math.floor(availWidth * (c.flex / totalFlex));
420 if(this.pack == 'center'){
421 l += availWidth ? availWidth / 2 : 0;
422 }else if(this.pack == 'end'){
425 for (i = 0 ; i < csLen; i++) {
429 c.setPosition(l, t + cm.top);
430 if(isStart && c.flex){
431 cw = Math.max(0, widths[idx++] + (leftOver-- > 0 ? 1 : 0));
433 restore.push(c.getHeight());
435 c.setSize(cw, availableHeight);
443 for (i = 0 ; i < csLen; i++) {
447 if(isStart && c.flex){
450 if(this.align == 'stretch'){
451 c.setHeight(((h - (this.padding.top + this.padding.bottom)) - (cm.top + cm.bottom)).constrain(
452 c.minHeight || 0, c.maxHeight || 1000000));
453 }else if(this.align == 'stretchmax'){
454 c.setHeight((maxHeight - (cm.top + cm.bottom)).constrain(
455 c.minHeight || 0, c.maxHeight || 1000000));
457 if(this.align == 'middle'){
458 diff = availableHeight - (ch + cm.top + cm.bottom);
459 ch = t + cm.top + (diff/2);
461 c.setPosition(c.x, ch);
464 if(isStart && c.flex){
469 // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
470 if (i = target.getStyle('overflow') && i != 'hidden' && !this.adjustmentPass) {
471 var ts = this.getLayoutTargetSize();
472 if (ts.width != size.width || ts.height != size.height){
473 this.adjustmentPass = true;
474 this.onLayout(ct, target);
477 delete this.adjustmentPass;
481 Ext.Container.LAYOUTS.hbox = Ext.layout.HBoxLayout;