    /*!
     * Ext JS Library 3.3.0
     * Copyright(c) 2006-2010 Ext JS, Inc.
     * licensing@extjs.com
     * http://www.extjs.com/license
     */
    /**
     * @class Ext.layout.BoxLayout
     * @extends Ext.layout.ContainerLayout
     * Base Class for HBoxLayout and VBoxLayout Classes. Generally it should not need to be used directly.
     */
    Ext.layout.BoxLayout = Ext.extend(Ext.layout.ContainerLayout, {
        /**
         * @cfg {Object} defaultMargins
         * If the individual contained items do not have a margins
         * property specified, the default margins from this property will be
         * applied to each item.
         *
    This property may be specified as an object containing margins
         * to apply in the format:
    {
        top: (top margin),
        right: (right margin),
        bottom: (bottom margin),
        left: (left margin)
    }
         * This property may also be specified as a string containing
         * space-separated, numeric margin values. The order of the sides associated
         * with each value matches the way CSS processes margin values:
         *
         * If there is only one value, it applies to all sides.
         * If there are two values, the top and bottom borders are set to the
         * first value and the right and left are set to the second.
         * If there are three values, the top is set to the first value, the left
         * and right are set to the second, and the bottom is set to the third.
         * If there are four values, they apply to the top, right, bottom, and
         * left, respectively.
         *
         * Defaults to:
         * {top:0, right:0, bottom:0, left:0}
         *
         */
        defaultMargins : {left:0,top:0,right:0,bottom:0},
        /**
         * @cfg {String} padding
         * Sets the padding to be applied to all child items managed by this layout.
         * This property must be specified as a string containing
         * space-separated, numeric padding values. The order of the sides associated
         * with each value matches the way CSS processes padding values:
         *
         * If there is only one value, it applies to all sides.
         * If there are two values, the top and bottom borders are set to the
         * first value and the right and left are set to the second.
         * If there are three values, the top is set to the first value, the left
         * and right are set to the second, and the bottom is set to the third.
         * If there are four values, they apply to the top, right, bottom, and
         * left, respectively.
         *
         * Defaults to: "0"
         */
        padding : '0',
        // documented in subclasses
        pack : 'start',

        // private
        monitorResize : true,
        type: 'box',
        scrollOffset : 0,
        extraCls : 'x-box-item',
        targetCls : 'x-box-layout-ct',
        innerCls : 'x-box-inner',

        constructor : function(config){
            Ext.layout.BoxLayout.superclass.constructor.call(this, config);

            if (Ext.isString(this.defaultMargins)) {
                this.defaultMargins = this.parseMargins(this.defaultMargins);
            }

            var handler = this.overflowHandler;

            if (typeof handler == 'string') {
                handler = {
                    type: handler
                };
            }

            var handlerType = 'none';
            if (handler && handler.type != undefined) {
                handlerType = handler.type;
            }

            var constructor = Ext.layout.boxOverflow[handlerType];
            if (constructor[this.type]) {
                constructor = constructor[this.type];
            }

            this.overflowHandler = new constructor(this, handler);
        },

        /**
         * @private
         * Runs the child box calculations and caches them in childBoxCache. Subclasses can used these cached values
         * when laying out
         */
        onLayout: function(container, target) {
            Ext.layout.BoxLayout.superclass.onLayout.call(this, container, target);

            var tSize = this.getLayoutTargetSize(),
                items = this.getVisibleItems(container),
                calcs = this.calculateChildBoxes(items, tSize),
                boxes = calcs.boxes,
                meta  = calcs.meta;

            //invoke the overflow handler, if one is configured
            if (tSize.width > 0) {
                var handler = this.overflowHandler,
                    method  = meta.tooNarrow ? 'handleOverflow' : 'clearOverflow';

                var results = handler[method](calcs, tSize);

                if (results) {
                    if (results.targetSize) {
                        tSize = results.targetSize;
                    }

                    if (results.recalculate) {
                        items = this.getVisibleItems(container);
                        calcs = this.calculateChildBoxes(items, tSize);
                        boxes = calcs.boxes;
                    }
                }
            }

            /**
             * @private
             * @property layoutTargetLastSize
             * @type Object
             * Private cache of the last measured size of the layout target. This should never be used except by
             * BoxLayout subclasses during their onLayout run.
             */
            this.layoutTargetLastSize = tSize;

            /**
             * @private
             * @property childBoxCache
             * @type Array
             * Array of the last calculated height, width, top and left positions of each visible rendered component
             * within the Box layout.
             */
            this.childBoxCache = calcs;

            this.updateInnerCtSize(tSize, calcs);
            this.updateChildBoxes(boxes);

            // Putting a box layout into an overflowed container is NOT correct and will make a second layout pass necessary.
            this.handleTargetOverflow(tSize, container, target);
        },

        /**
         * Resizes and repositions each child component
         * @param {Array} boxes The box measurements
         */
        updateChildBoxes: function(boxes) {
            for (var i = 0, length = boxes.length; i < length; i++) {
                var box  = boxes[i],
                    comp = box.component;

                if (box.dirtySize) {
                    comp.setSize(box.width, box.height);
                }
                // Don't set positions to NaN
                if (isNaN(box.left) || isNaN(box.top)) {
                    continue;
                }

                comp.setPosition(box.left, box.top);
            }
        },

        /**
         * @private
         * Called by onRender just before the child components are sized and positioned. This resizes the innerCt
         * to make sure all child items fit within it. We call this before sizing the children because if our child
         * items are larger than the previous innerCt size the browser will insert scrollbars and then remove them
         * again immediately afterwards, giving a performance hit.
         * Subclasses should provide an implementation.
         * @param {Object} currentSize The current height and width of the innerCt
         * @param {Array} calculations The new box calculations of all items to be laid out
         */
        updateInnerCtSize: function(tSize, calcs) {
            var align   = this.align,
                padding = this.padding,
                width   = tSize.width,
                height  = tSize.height;

            if (this.type == 'hbox') {
                var innerCtWidth  = width,
                    innerCtHeight = calcs.meta.maxHeight + padding.top + padding.bottom;

                if (align == 'stretch') {
                    innerCtHeight = height;
                } else if (align == 'middle') {
                    innerCtHeight = Math.max(height, innerCtHeight);
                }
            } else {
                var innerCtHeight = height,
                    innerCtWidth  = calcs.meta.maxWidth + padding.left + padding.right;

                if (align == 'stretch') {
                    innerCtWidth = width;
                } else if (align == 'center') {
                    innerCtWidth = Math.max(width, innerCtWidth);
                }
            }

            this.innerCt.setSize(innerCtWidth || undefined, innerCtHeight || undefined);
        },

        /**
         * @private
         * This should be called after onLayout of any BoxLayout subclass. If the target's overflow is not set to 'hidden',
         * we need to lay out a second time because the scrollbars may have modified the height and width of the layout
         * target. Having a Box layout inside such a target is therefore not recommended.
         * @param {Object} previousTargetSize The size and height of the layout target before we just laid out
         * @param {Ext.Container} container The container
         * @param {Ext.Element} target The target element
         */
        handleTargetOverflow: function(previousTargetSize, container, target) {
            var overflow = target.getStyle('overflow');

            if (overflow && overflow != 'hidden' &&!this.adjustmentPass) {
                var newTargetSize = this.getLayoutTargetSize();
                if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height){
                    this.adjustmentPass = true;
                    this.onLayout(container, target);
                }
            }

            delete this.adjustmentPass;
        },

        // private
        isValidParent : function(c, target) {
            return this.innerCt && c.getPositionEl().dom.parentNode == this.innerCt.dom;
        },

        /**
         * @private
         * Returns all items that are both rendered and visible
         * @return {Array} All matching items
         */
        getVisibleItems: function(ct) {
            var ct  = ct || this.container,
                t   = ct.getLayoutTarget(),
                cti = ct.items.items,
                len = cti.length,

                i, c, items = [];

            for (i = 0; i < len; i++) {
                if((c = cti[i]).rendered && this.isValidParent(c, t) && c.hidden !== true  && c.collapsed !== true && c.shouldLayout !== false){
                    items.push(c);
                }
            }

            return items;
        },

        // private
        renderAll : function(ct, target) {
            if (!this.innerCt) {
                // the innerCt prevents wrapping and shuffling while the container is resizing
                this.innerCt = target.createChild({cls:this.innerCls});
                this.padding = this.parseMargins(this.padding);
            }
            Ext.layout.BoxLayout.superclass.renderAll.call(this, ct, this.innerCt);
        },

        getLayoutTargetSize : function() {
            var target = this.container.getLayoutTarget(), ret;

            if (target) {
                ret = target.getViewSize();

                // IE in strict mode will return a width of 0 on the 1st pass of getViewSize.
                // Use getStyleSize to verify the 0 width, the adjustment pass will then work properly
                // with getViewSize
                if (Ext.isIE && Ext.isStrict && ret.width == 0){
                    ret =  target.getStyleSize();
                }

                ret.width  -= target.getPadding('lr');
                ret.height -= target.getPadding('tb');
            }

            return ret;
        },

        // private
        renderItem : function(c) {
            if(Ext.isString(c.margins)){
                c.margins = this.parseMargins(c.margins);
            }else if(!c.margins){
                c.margins = this.defaultMargins;
            }
            Ext.layout.BoxLayout.superclass.renderItem.apply(this, arguments);
        },

        /**
         * @private
         */
        destroy: function() {
            Ext.destroy(this.overflowHandler);

            Ext.layout.BoxLayout.superclass.destroy.apply(this, arguments);
        }
    });

    Ext.ns('Ext.layout.boxOverflow');

    /**
     * @class Ext.layout.boxOverflow.None
     * @extends Object
     * Base class for Box Layout overflow handlers. These specialized classes are invoked when a Box Layout
     * (either an HBox or a VBox) has child items that are either too wide (for HBox) or too tall (for VBox)
     * for its container.
     */

    Ext.layout.boxOverflow.None = Ext.extend(Object, {
        constructor: function(layout, config) {
            this.layout = layout;

            Ext.apply(this, config || {});
        },

        handleOverflow: Ext.emptyFn,

        clearOverflow: Ext.emptyFn
    });

    Ext.layout.boxOverflow.none = Ext.layout.boxOverflow.None;