    /**
     * @class Ext.layout.container.boxOverflow.Menu
     * @extends Ext.layout.container.boxOverflow.None
     * @private
     */
    Ext.define('Ext.layout.container.boxOverflow.Menu', {

        /* Begin Definitions */

        extend: 'Ext.layout.container.boxOverflow.None',
        requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
        alternateClassName: 'Ext.layout.boxOverflow.Menu',

        /* End Definitions */

        /**
         * @cfg {String} afterCtCls
         * CSS class added to the afterCt element. This is the element that holds any special items such as scrollers,
         * which must always be present at the rightmost edge of the Container
         */

        /**
         * @property noItemsMenuText
         * @type String
         * HTML fragment to render into the toolbar overflow menu if there are no items to display
         */
        noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',

        constructor: function(layout) {
            var me = this;

            me.callParent(arguments);

            // Before layout, we need to re-show all items which we may have hidden due to a previous overflow.
            layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);

            me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
            /**
             * @property menuItems
             * @type Array
             * Array of all items that are currently hidden and should go into the dropdown menu
             */
            me.menuItems = [];
        },

        onRemove: function(comp){
            Ext.Array.remove(this.menuItems, comp);
        },

        handleOverflow: function(calculations, targetSize) {
            var me = this,
                layout = me.layout,
                methodName = 'get' + layout.parallelPrefixCap,
                newSize = {},
                posArgs = [null, null];

            me.callParent(arguments);
            this.createMenu(calculations, targetSize);
            newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
            newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();

            // Center the menuTrigger button.
            // TODO: Should we emulate align: 'middle' like this, or should we 'stretchmax' the menuTrigger?
            posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
            me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);

            return { targetSize: newSize };
        },

        /**
         * @private
         * Called by the layout, when it determines that there is no overflow.
         * Also called as an interceptor to the layout's onLayout method to reshow
         * previously hidden overflowing items.
         */
        clearOverflow: function(calculations, targetSize) {
            var me = this,
                newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
                items = me.menuItems,
                i = 0,
                length = items.length,
                item;

            me.hideTrigger();
            for (; i < length; i++) {
                items[i].show();
            }
            items.length = 0;

            return targetSize ? {
                targetSize: {
                    height: targetSize.height,
                    width : newWidth
                }
            } : null;
        },

        /**
         * @private
         */
        showTrigger: function() {
            this.menuTrigger.show();
        },

        /**
         * @private
         */
        hideTrigger: function() {
            if (this.menuTrigger !== undefined) {
                this.menuTrigger.hide();
            }
        },

        /**
         * @private
         * Called before the overflow menu is shown. This constructs the menu's items, caching them for as long as it can.
         */
        beforeMenuShow: function(menu) {
            var me = this,
                items = me.menuItems,
                i = 0,
                len   = items.length,
                item,
                prev;

            var needsSep = function(group, prev){
                return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
            };

            me.clearMenu();
            menu.removeAll();

            for (; i < len; i++) {
                item = items[i];

                // Do not show a separator as a first item
                if (!i && (item instanceof Ext.toolbar.Separator)) {
                    continue;
                }
                if (prev && (needsSep(item, prev) || needsSep(prev, item))) {
                    menu.add('-');
                }

                me.addComponentToMenu(menu, item);
                prev = item;
            }

            // put something so the menu isn't empty if no compatible items found
            if (menu.items.length < 1) {
                menu.add(me.noItemsMenuText);
            }
        },

        /**
         * @private
         * Returns a menu config for a given component. This config is used to create a menu item
         * to be added to the expander menu
         * @param {Ext.Component} component The component to create the config for
         * @param {Boolean} hideOnClick Passed through to the menu item
         */
        createMenuConfig : function(component, hideOnClick) {
            var config = Ext.apply({}, component.initialConfig),
                group  = component.toggleGroup;

            Ext.copyTo(config, component, [
                'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
            ]);

            Ext.apply(config, {
                text       : component.overflowText || component.text,
                hideOnClick: hideOnClick,
                destroyMenu: false
            });

            if (group || component.enableToggle) {
                Ext.apply(config, {
                    group  : group,
                    checked: component.pressed,
                    listeners: {
                        checkchange: function(item, checked){
                            component.toggle(checked);
                        }
                    }
                });
            }

            delete config.ownerCt;
            delete config.xtype;
            delete config.id;
            return config;
        },

        /**
         * @private
         * Adds the given Toolbar item to the given menu. Buttons inside a buttongroup are added individually.
         * @param {Ext.menu.Menu} menu The menu to add to
         * @param {Ext.Component} component The component to add
         */
        addComponentToMenu : function(menu, component) {
            var me = this;
            if (component instanceof Ext.toolbar.Separator) {
                menu.add('-');
            } else if (component.isComponent) {
                if (component.isXType('splitbutton')) {
                    menu.add(me.createMenuConfig(component, true));

                } else if (component.isXType('button')) {
                    menu.add(me.createMenuConfig(component, !component.menu));

                } else if (component.isXType('buttongroup')) {
                    component.items.each(function(item){
                         me.addComponentToMenu(menu, item);
                    });
                } else {
                    menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
                }
            }
        },

        /**
         * @private
         * Deletes the sub-menu of each item in the expander menu. Submenus are created for items such as
         * splitbuttons and buttongroups, where the Toolbar item cannot be represented by a single menu item
         */
        clearMenu : function() {
            var menu = this.moreMenu;
            if (menu && menu.items) {
                menu.items.each(function(item) {
                    if (item.menu) {
                        delete item.menu;
                    }
                });
            }
        },

        /**
         * @private
         * Creates the overflow trigger and menu used when enableOverflow is set to true and the items
         * in the layout are too wide to fit in the space available
         */
        createMenu: function(calculations, targetSize) {
            var me = this,
                layout = me.layout,
                startProp = layout.parallelBefore,
                sizeProp = layout.parallelPrefix,
                available = targetSize[sizeProp],
                boxes = calculations.boxes,
                i = 0,
                len = boxes.length,
                box;

            if (!me.menuTrigger) {
                me.createInnerElements();

                /**
                 * @private
                 * @property menu
                 * @type Ext.menu.Menu
                 * The expand menu - holds items for every item that cannot be shown
                 * because the container is currently not large enough.
                 */
                me.menu = Ext.create('Ext.menu.Menu', {
                    hideMode: 'offsets',
                    listeners: {
                        scope: me,
                        beforeshow: me.beforeMenuShow
                    }
                });

                /**
                 * @private
                 * @property menuTrigger
                 * @type Ext.button.Button
                 * The expand button which triggers the overflow menu to be shown
                 */
                me.menuTrigger = Ext.create('Ext.button.Button', {
                    ownerCt : me.layout.owner, // To enable the Menu to ascertain a valid zIndexManager owner in the same tree
                    iconCls : Ext.baseCSSPrefix + layout.owner.getXType() + '-more-icon',
                    ui      : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
                    menu    : me.menu,
                    getSplitCls: function() { return '';},
                    renderTo: me.afterCt
                });
            }
            me.showTrigger();
            available -= me.afterCt.getWidth();

            // Hide all items which are off the end, and store them to allow them to be restored
            // before each layout operation.
            me.menuItems.length = 0;
            for (; i < len; i++) {
                box = boxes[i];
                if (box[startProp] + box[sizeProp] > available) {
                    me.menuItems.push(box.component);
                    box.component.hide();
                }
            }
        },

        /**
         * @private
         * Creates the beforeCt, innerCt and afterCt elements if they have not already been created
         * @param {Ext.container.Container} container The Container attached to this Layout instance
         * @param {Ext.core.Element} target The target Element
         */
        createInnerElements: function() {
            var me = this,
                target = me.layout.getRenderTarget();

            if (!this.afterCt) {
                target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
                this.afterCt  = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
            }
        },

        /**
         * @private
         */
        destroy: function() {
            Ext.destroy(this.menu, this.menuTrigger);
        }
    });