<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>The source code</title> <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" /> <script type="text/javascript" src="../resources/prettify/prettify.js"></script> <style type="text/css"> .highlight { display: block; background-color: #ddd; } </style> <script type="text/javascript"> function highlight() { document.getElementById(location.hash.replace(/#/, "")).className = "highlight"; } </script> </head> <body onload="prettyPrint(); highlight();"> <pre class="prettyprint lang-js"><span id='Ext-layout-container-Column'>/** </span> * This is the layout style of choice for creating structural layouts in a multi-column format where the width of each * column can be specified as a percentage or fixed width, but the height is allowed to vary based on the content. This * class is intended to be extended or created via the layout:'column' {@link Ext.container.Container#layout} config, * and should generally not need to be created directly via the new keyword. * * ColumnLayout does not have any direct config options (other than inherited ones), but it does support a specific * config property of `columnWidth` that can be included in the config of any panel added to it. The layout will use * the columnWidth (if present) or width of each panel during layout to determine how to size each panel. If width or * columnWidth is not specified for a given panel, its width will default to the panel's width (or auto). * * The width property is always evaluated as pixels, and must be a number greater than or equal to 1. The columnWidth * property is always evaluated as a percentage, and must be a decimal value greater than 0 and less than 1 (e.g., .25). * * The basic rules for specifying column widths are pretty simple. The logic makes two passes through the set of * contained panels. During the first layout pass, all panels that either have a fixed width or none specified (auto) * are skipped, but their widths are subtracted from the overall container width. * * During the second pass, all panels with columnWidths are assigned pixel widths in proportion to their percentages * based on the total **remaining** container width. In other words, percentage width panels are designed to fill * the space left over by all the fixed-width and/or auto-width panels. Because of this, while you can specify any * number of columns with different percentages, the columnWidths must always add up to 1 (or 100%) when added * together, otherwise your layout may not render as expected. * * @example * // All columns are percentages -- they must add up to 1 * Ext.create('Ext.panel.Panel', { * title: 'Column Layout - Percentage Only', * width: 350, * height: 250, * layout:'column', * items: [{ * title: 'Column 1', * columnWidth: 0.25 * },{ * title: 'Column 2', * columnWidth: 0.55 * },{ * title: 'Column 3', * columnWidth: 0.20 * }], * renderTo: Ext.getBody() * }); * * // Mix of width and columnWidth -- all columnWidth values must add up * // to 1. The first column will take up exactly 120px, and the last two * // columns will fill the remaining container width. * * Ext.create('Ext.Panel', { * title: 'Column Layout - Mixed', * width: 350, * height: 250, * layout:'column', * items: [{ * title: 'Column 1', * width: 120 * },{ * title: 'Column 2', * columnWidth: 0.7 * },{ * title: 'Column 3', * columnWidth: 0.3 * }], * renderTo: Ext.getBody() * }); */ Ext.define('Ext.layout.container.Column', { extend: 'Ext.layout.container.Container', alias: ['layout.column'], alternateClassName: 'Ext.layout.ColumnLayout', type: 'column', itemCls: Ext.baseCSSPrefix + 'column', targetCls: Ext.baseCSSPrefix + 'column-layout-ct', // Columns with a columnWidth have their width managed. columnWidthSizePolicy: { setsWidth: 1, setsHeight: 0 }, childEls: [ 'innerCt' ], manageOverflow: 2, renderTpl: [ '<div id="{ownerId}-innerCt" class="',Ext.baseCSSPrefix,'column-inner">', '{%this.renderBody(out,values)%}', '<div class="',Ext.baseCSSPrefix,'clear"></div>', '</div>', '{%this.renderPadder(out,values)%}' ], getItemSizePolicy: function (item) { if (item.columnWidth) { return this.columnWidthSizePolicy; } return this.autoSizePolicy; }, beginLayout: function() { this.callParent(arguments); this.innerCt.dom.style.width = ''; }, calculate: function (ownerContext) { var me = this, containerSize = me.getContainerSize(ownerContext), state = ownerContext.state; if (state.calculatedColumns || (state.calculatedColumns = me.calculateColumns(ownerContext))) { if (me.calculateHeights(ownerContext)) { me.calculateOverflow(ownerContext, containerSize); return; } } me.done = false; }, calculateColumns: function (ownerContext) { var me = this, containerSize = me.getContainerSize(ownerContext), innerCtContext = ownerContext.getEl('innerCt', me), items = ownerContext.childItems, len = items.length, contentWidth = 0, blocked, availableWidth, i, itemContext, itemMarginWidth, itemWidth; // Can never decide upon necessity of vertical scrollbar (and therefore, narrower // content width) until the component layout has published a height for the target // element. if (!ownerContext.heightModel.shrinkWrap && !ownerContext.targetContext.hasProp('height')) { return false; } // No parallel measurement, cannot lay out boxes. if (!containerSize.gotWidth) { //\\ TODO: Deal with target padding width ownerContext.targetContext.block(me, 'width'); blocked = true; } else { availableWidth = containerSize.width; innerCtContext.setWidth(availableWidth); } // we need the widths of the columns we don't manage to proceed so we block on them // if they are not ready... for (i = 0; i < len; ++i) { itemContext = items[i]; // this is needed below for non-calculated columns, but is also needed in the // next loop for calculated columns... this way we only call getMarginInfo in // this loop and use the marginInfo property in the next... itemMarginWidth = itemContext.getMarginInfo().width; if (!itemContext.widthModel.calculated) { itemWidth = itemContext.getProp('width'); if (typeof itemWidth != 'number') { itemContext.block(me, 'width'); blocked = true; } contentWidth += itemWidth + itemMarginWidth; } } if (!blocked) { availableWidth = (availableWidth < contentWidth) ? 0 : availableWidth - contentWidth; for (i = 0; i < len; ++i) { itemContext = items[i]; if (itemContext.widthModel.calculated) { itemMarginWidth = itemContext.marginInfo.width; // always set by above loop itemWidth = itemContext.target.columnWidth; itemWidth = Math.floor(itemWidth * availableWidth) - itemMarginWidth; itemWidth = itemContext.setWidth(itemWidth); // constrains to min/maxWidth contentWidth += itemWidth + itemMarginWidth; } } ownerContext.setContentWidth(contentWidth); } // we registered all the values that block this calculation, so abort now if blocked... return !blocked; }, calculateHeights: function (ownerContext) { var me = this, items = ownerContext.childItems, len = items.length, blocked, i, itemContext; // in order for innerCt to have the proper height, all the items must have height // correct in the DOM... blocked = false; for (i = 0; i < len; ++i) { itemContext = items[i]; if (!itemContext.hasDomProp('height')) { itemContext.domBlock(me, 'height'); blocked = true; } } if (!blocked) { ownerContext.setContentHeight(me.innerCt.getHeight() + ownerContext.targetContext.getPaddingInfo().height); } return !blocked; }, finishedLayout: function (ownerContext) { var bc = ownerContext.bodyContext; // Owner may not have a body - this seems to only be needed for Panels. if (bc && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) { // Fix for https://sencha.jira.com/browse/EXTJSIV-4979 bc.el.repaint(); } this.callParent(arguments); }, getRenderTarget : function() { return this.innerCt; } }); </pre> </body> </html>