    /**
     * @class Ext.layout.container.CheckboxGroup
     * @extends Ext.layout.container.Container
     * <p>This layout implements the column arrangement for {@link Ext.form.CheckboxGroup} and {@link Ext.form.RadioGroup}.
     * It groups the component's sub-items into columns based on the component's
     * {@link Ext.form.CheckboxGroup#columns columns} and {@link Ext.form.CheckboxGroup#vertical} config properties.</p>
     *
     */
    Ext.define('Ext.layout.container.CheckboxGroup', {
        extend: 'Ext.layout.container.Container',
        alias: ['layout.checkboxgroup'],

        onLayout: function() {
            var numCols = this.getColCount(),
                shadowCt = this.getShadowCt(),
                owner = this.owner,
                items = owner.items,
                shadowItems = shadowCt.items,
                numItems = items.length,
                colIndex = 0,
                i, numRows;

            // Distribute the items into the appropriate column containers. We add directly to the
            // containers' items collection rather than calling container.add(), because we need the
            // checkboxes to maintain their original ownerCt. The distribution is done on each layout
            // in case items have been added, removed, or reordered.

            shadowItems.each(function(col) {
                col.items.clear();
            });

            // If columns="auto", then the number of required columns may change as checkboxes are added/removed
            // from the CheckboxGroup; adjust to match.
            while (shadowItems.length > numCols) {
                shadowCt.remove(shadowItems.last());
            }
            while (shadowItems.length < numCols) {
                shadowCt.add({
                    xtype: 'container',
                    cls: owner.groupCls,
                    flex: 1
                });
            }

            if (owner.vertical) {
                numRows = Math.ceil(numItems / numCols);
                for (i = 0; i < numItems; i++) {
                    if (i > 0 && i % numRows === 0) {
                        colIndex++;
                    }
                    shadowItems.getAt(colIndex).items.add(items.getAt(i));
                }
            } else {
                for (i = 0; i < numItems; i++) {
                    colIndex = i % numCols;
                    shadowItems.getAt(colIndex).items.add(items.getAt(i));
                }
            }

            if (!shadowCt.rendered) {
                shadowCt.render(this.getRenderTarget());
            } else {
                // Ensure all items are rendered in the correct place in the correct column - this won't
                // get done by the column containers themselves if their dimensions are not changing.
                shadowItems.each(function(col) {
                    var layout = col.getLayout();
                    layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
                });
            }

            shadowCt.doComponentLayout();
        },

        // We don't want to render any items to the owner directly, that gets handled by each column's own layout
        renderItems: Ext.emptyFn,

        /**
         * @private
         * Creates and returns the shadow hbox container that will be used to arrange the owner's items
         * into columns.
         */
        getShadowCt: function() {
            var me = this,
                shadowCt = me.shadowCt,
                owner, items, item, columns, columnsIsArray, numCols, i;

            if (!shadowCt) {
                // Create the column containers based on the owner's 'columns' config
                owner = me.owner;
                columns = owner.columns;
                columnsIsArray = Ext.isArray(columns);
                numCols = me.getColCount();
                items = [];
                for(i = 0; i < numCols; i++) {
                    item = {
                        xtype: 'container',
                        cls: owner.groupCls
                    };
                    if (columnsIsArray) {
                        // Array can contain mixture of whole numbers, used as fixed pixel widths, and fractional
                        // numbers, used as relative flex values.
                        if (columns[i] < 1) {
                            item.flex = columns[i];
                        } else {
                            item.width = columns[i];
                        }
                    }
                    else {
                        // All columns the same width
                        item.flex = 1;
                    }
                    items.push(item);
                }

                // Create the shadow container; delay rendering until after items are added to the columns
                shadowCt = me.shadowCt = Ext.createWidget('container', {
                    layout: 'hbox',
                    items: items,
                    ownerCt: owner
                });
            }

            return shadowCt;
        },

        /**
         * @private Get the number of columns in the checkbox group
         */
        getColCount: function() {
            var owner = this.owner,
                colsCfg = owner.columns;
            return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
        }

    });