Upgrade to ExtJS 3.3.1 - Released 11/30/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.3.1
11  * Copyright(c) 2006-2010 Sencha Inc.
12  * licensing@sencha.com
13  * http://www.sencha.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         var handler = this.overflowHandler;
88         
89         if (typeof handler == 'string') {
90             handler = {
91                 type: handler
92             };
93         }
94         
95         var handlerType = 'none';
96         if (handler && handler.type != undefined) {
97             handlerType = handler.type;
98         }
99         
100         var constructor = Ext.layout.boxOverflow[handlerType];
101         if (constructor[this.type]) {
102             constructor = constructor[this.type];
103         }
104         
105         this.overflowHandler = new constructor(this, handler);
106     },
107
108     /**
109      * @private
110      * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
111      * when laying out
112      */
113     onLayout: function(container, target) {
114         Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);
115
116         var tSize = this.getLayoutTargetSize(),
117             items = this.getVisibleItems(container),
118             calcs = this.calculateChildBoxes(items, tSize),
119             boxes = calcs.boxes,
120             meta  = calcs.meta;
121         
122         //invoke the overflow handler, if one is configured
123         if (tSize.width > 0) {
124             var handler = this.overflowHandler,
125                 method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';
126             
127             var results = handler[method](calcs, tSize);
128             
129             if (results) {
130                 if (results.targetSize) {
131                     tSize = results.targetSize;
132                 }
133                 
134                 if (results.recalculate) {
135                     items = this.getVisibleItems(container);
136                     calcs = this.calculateChildBoxes(items, tSize);
137                     boxes = calcs.boxes;
138                 }
139             }
140         }
141         
142         /**
143          * @private
144          * @property layoutTargetLastSize
145          * @type Object
146          * Private cache of the last measured size of the layout target. This should never be used except by
147          * BoxLayout subclasses during their onLayout run.
148          */
149         this.layoutTargetLastSize = tSize;
150         
151         /**
152          * @private
153          * @property childBoxCache
154          * @type Array
155          * Array of the last calculated height, width, top and left positions of each visible rendered component
156          * within the Box layout.
157          */
158         this.childBoxCache = calcs;
159         
160         this.updateInnerCtSize(tSize, calcs);
161         this.updateChildBoxes(boxes);
162
163         // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
164         this.handleTargetOverflow(tSize, container, target);
165     },
166
167     <div id="method-Ext.layout.BoxLayout-updateChildBoxes"></div>/**
168      * Resizes and repositions each child component
169      * @param {Array} boxes The box measurements
170      */
171     updateChildBoxes: function(boxes) {
172         for (var i = 0, length = boxes.length; i < length; i++) {
173             var box  = boxes[i],
174                 comp = box.component;
175             
176             if (box.dirtySize) {
177                 comp.setSize(box.width, box.height);
178             }
179             // Don't set positions to NaN
180             if (isNaN(box.left) || isNaN(box.top)) {
181                 continue;
182             }
183             
184             comp.setPosition(box.left, box.top);
185         }
186     },
187
188     /**
189      * @private
190      * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
191      * to make sure all child items fit within it. We call this before sizing the children because if our child
192      * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
193      * again immediately afterwards, giving a performance hit.
194      * Subclasses should provide an implementation.
195      * @param {Object} currentSize The current height and width of the innerCt
196      * @param {Array} calculations The new box calculations of all items to be laid out
197      */
198     updateInnerCtSize: function(tSize, calcs) {
199         var align   = this.align,
200             padding = this.padding,
201             width   = tSize.width,
202             height  = tSize.height;
203         
204         if (this.type == 'hbox') {
205             var innerCtWidth  = width,
206                 innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;
207
208             if (align == 'stretch') {
209                 innerCtHeight = height;
210             } else if (align == 'middle') {
211                 innerCtHeight = Math.max(height, innerCtHeight);
212             }
213         } else {
214             var innerCtHeight = height,
215                 innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;
216
217             if (align == 'stretch') {
218                 innerCtWidth = width;
219             } else if (align == 'center') {
220                 innerCtWidth = Math.max(width, innerCtWidth);
221             }
222         }
223
224         this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
225     },
226
227     /**
228      * @private
229      * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
230      * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
231      * target. Having a Box layout inside such a target is therefore not recommended.
232      * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
233      * @param {Ext.Container} container The container
234      * @param {Ext.Element} target The target element
235      */
236     handleTargetOverflow: function(previousTargetSize, container, target) {
237         var overflow = target.getStyle('overflow');
238
239         if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
240             var newTargetSize = this.getLayoutTargetSize();
241             if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
242                 this.adjustmentPass = true;
243                 this.onLayout(container, target);
244             }
245         }
246
247         delete this.adjustmentPass;
248     },
249
250     // private
251     isValidParent : function(c, target) {
252         return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
253     },
254
255     /**
256      * @private
257      * Returns all items that are both rendered and visible
258      * @return {Array} All matching items
259      */
260     getVisibleItems: function(ct) {
261         var ct  = ct || this.container,
262             t   = ct.getLayoutTarget(),
263             cti = ct.items.items,
264             len = cti.length,
265
266             i, c, items = [];
267
268         for (i = 0; i < len; i++) {
269             if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
270                 items.push(c);
271             }
272         }
273
274         return items;
275     },
276
277     // private
278     renderAll : function(ct, target) {
279         if (!this.innerCt) {
280             // the innerCt prevents wrapping and shuffling while the container is resizing
281             this.innerCt = target.createChild({cls:this.innerCls});
282             this.padding = this.parseMargins(this.padding);
283         }
284         Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
285     },
286
287     getLayoutTargetSize : function() {
288         var target = this.container.getLayoutTarget(), ret;
289         
290         if (target) {
291             ret = target.getViewSize();
292
293             // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
294             // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
295             // with getViewSize
296             if (Ext.isIE && Ext.isStrict && ret.width == 0){
297                 ret =  target.getStyleSize();
298             }
299
300             ret.width  -= target.getPadding('lr');
301             ret.height -= target.getPadding('tb');
302         }
303         
304         return ret;
305     },
306
307     // private
308     renderItem : function(c) {
309         if(Ext.isString(c.margins)){
310             c.margins = this.parseMargins(c.margins);
311         }else if(!c.margins){
312             c.margins = this.defaultMargins;
313         }
314         Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
315     },
316     
317     /**
318      * @private
319      */
320     destroy: function() {
321         Ext.destroy(this.overflowHandler);
322         
323         Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
324     }
325 });
326
327
328
329 Ext.ns('Ext.layout.boxOverflow');
330
331 <div id="cls-Ext.layout.boxOverflow.None"></div>/**
332  * @class Ext.layout.boxOverflow.None
333  * @extends Object
334  * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
335  * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
336  * for its container.
337  */
338
339 Ext.layout.boxOverflow.None = Ext.extend(Object, {
340     constructor: function(layout, config) {
341         this.layout = layout;
342         
343         Ext.apply(this, config || {});
344     },
345     
346     handleOverflow: Ext.emptyFn,
347     
348     clearOverflow: Ext.emptyFn
349 });
350
351
352 Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;
353 </pre>    
354 </body>
355 </html>