/** * The class is the default component layout for {@link Ext.Component} when no explicit * `{@link Ext.Component#componentLayout componentLayout}` is configured. * * This class uses template methods to perform the individual aspects of measurement, * calculation and publication of results. The methods called depend on the component's * {@link Ext.Component#getSizeModel size model}. * * ## configured / calculated * * In either of these size models, the dimension of the outer element is of a known size. * The size is found in the `ownerContext` (the {@link Ext.layout.ContextItem} for the owner * component) as either "width" or "height". This value, if available, is passed to the * `publishInnerWidth` or `publishInnerHeight` method, respectively. * * ## shrinkWrap * * When a dimension uses the `shrinkWrap` size model, that means the content is measured, * then the outer (owner) size is calculated and published. * * For example, for a shrinkWrap width, the following sequence of calls are made: * * - `Ext.layout.component.Component#measureContentWidth` * - `publishOwnerWidth` * - `calculateOwnerWidthFromContentWidth` * - `publishInnerWidth` (in the event of hitting a min/maxWidth constraint) * * ## natural * * When a dimension uses the `natural` size model, the measurement is made on the outer * (owner) element. This size is then used to determine the content area in much the same * way as if the outer element had a `configured` or `calculated` size model. * * - `Ext.layout.component.Component#measureOwnerWidth` * - `publishInnerWidth` * * @protected */Ext.define('Ext.layout.component.Auto', { /* Begin Definitions */ alias: 'layout.autocomponent', extend: 'Ext.layout.component.Component', /* End Definitions */ type: 'autocomponent', /** * @cfg {Boolean} [setHeightInDom=false] * @protected * When publishing height of an auto Component, it is usually not written to the DOM. * Setting this to `true` overrides this behaviour. */ setHeightInDom: false, /** * @cfg {Boolean} [setWidthInDom=false] * @protected * When publishing width of an auto Component, it is usually not written to the DOM. * Setting this to `true` overrides this behaviour. */ setWidthInDom: false, waitForOuterHeightInDom: false, waitForOuterWidthInDom: false, beginLayoutCycle: function(ownerContext, firstCycle) { var me = this, lastWidthModel = me.lastWidthModel, lastHeightModel = me.lastHeightModel, el = me.owner.el; me.callParent(arguments); if (lastWidthModel && lastWidthModel.fixed && ownerContext.widthModel.shrinkWrap) { el.setWidth(null); } if (lastHeightModel && lastHeightModel.fixed && ownerContext.heightModel.shrinkWrap) { el.setHeight(null); } }, calculate: function(ownerContext) { var me = this, measurement = me.measureAutoDimensions(ownerContext), heightModel = ownerContext.heightModel, widthModel = ownerContext.widthModel, width, height; // It is generally important to process widths before heights, since widths can // often effect heights... if (measurement.gotWidth) { if (widthModel.shrinkWrap) { me.publishOwnerWidth(ownerContext, measurement.contentWidth); } else if (me.publishInnerWidth) { me.publishInnerWidth(ownerContext, measurement.width); } } else if (!widthModel.auto && me.publishInnerWidth) { width = me.waitForOuterWidthInDom ? ownerContext.getDomProp('width') : ownerContext.getProp('width'); if (width === undefined) { me.done = false; } else { me.publishInnerWidth(ownerContext, width); } } if (measurement.gotHeight) { if (heightModel.shrinkWrap) { me.publishOwnerHeight(ownerContext, measurement.contentHeight); } else if (me.publishInnerHeight) { me.publishInnerHeight(ownerContext, measurement.height); } } else if (!heightModel.auto && me.publishInnerHeight) { height = me.waitForOuterHeightInDom ? ownerContext.getDomProp('height') : ownerContext.getProp('height'); if (height === undefined) { me.done = false; } else { me.publishInnerHeight(ownerContext, height); } } if (!measurement.gotAll) { me.done = false; } }, calculateOwnerHeightFromContentHeight: function(ownerContext, contentHeight) { return contentHeight + ownerContext.getFrameInfo().height; }, calculateOwnerWidthFromContentWidth: function(ownerContext, contentWidth) { return contentWidth + ownerContext.getFrameInfo().width; }, publishOwnerHeight: function(ownerContext, contentHeight) { var me = this, owner = me.owner, height = me.calculateOwnerHeightFromContentHeight(ownerContext, contentHeight), constrainedHeight, dirty, heightModel; if (isNaN(height)) { me.done = false; } else { constrainedHeight = Ext.Number.constrain(height, owner.minHeight, owner.maxHeight); if (constrainedHeight === height) { dirty = me.setHeightInDom; } else { heightModel = me.sizeModels[ (constrainedHeight < height) ? 'constrainedMax' : 'constrainedMin']; height = constrainedHeight; if (ownerContext.heightModel.calculatedFromShrinkWrap) { // Don't bother to invalidate since that will come soon... but we need // to signal our ownerLayout that we need an invalidate to actually // make good on the determined (constrained) size! ownerContext.heightModel = heightModel; } else { ownerContext.invalidate({ heightModel: heightModel }); } } ownerContext.setHeight(height, dirty); } }, publishOwnerWidth: function(ownerContext, contentWidth) { var me = this, owner = me.owner, width = me.calculateOwnerWidthFromContentWidth(ownerContext, contentWidth), constrainedWidth, dirty, widthModel; if (isNaN(width)) { me.done = false; } else { constrainedWidth = Ext.Number.constrain(width, owner.minWidth, owner.maxWidth); if (constrainedWidth === width) { dirty = me.setWidthInDom; } else { widthModel = me.sizeModels[ (constrainedWidth < width) ? 'constrainedMax' : 'constrainedMin']; width = constrainedWidth; if (ownerContext.widthModel.calculatedFromShrinkWrap) { // Don't bother to invalidate since that will come soon... but we need // to signal our ownerLayout that we need an invalidate to actually // make good on the determined (constrained) size! ownerContext.widthModel = widthModel; } else { ownerContext.invalidate({ widthModel: widthModel }); } } ownerContext.setWidth(width, dirty); } }});