123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- <!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-Anchor'>/**
- </span> * This is a layout that enables anchoring of contained elements relative to the container's dimensions.
- * If the container is resized, all anchored items are automatically rerendered according to their
- * `{@link #anchor}` rules.
- *
- * This class is intended to be extended or created via the {@link Ext.container.AbstractContainer#layout layout}: 'anchor'
- * config, and should generally not need to be created directly via the new keyword.
- *
- * AnchorLayout does not have any direct config options (other than inherited ones). By default,
- * AnchorLayout will calculate anchor measurements based on the size of the container itself. However, the
- * container using the AnchorLayout can supply an anchoring-specific config property of `anchorSize`.
- *
- * If anchorSize is specifed, the layout will use it as a virtual container for the purposes of calculating
- * anchor measurements based on it instead, allowing the container to be sized independently of the anchoring
- * logic if necessary.
- *
- * @example
- * Ext.create('Ext.Panel', {
- * width: 500,
- * height: 400,
- * title: "AnchorLayout Panel",
- * layout: 'anchor',
- * renderTo: Ext.getBody(),
- * items: [
- * {
- * xtype: 'panel',
- * title: '75% Width and 20% Height',
- * anchor: '75% 20%'
- * },
- * {
- * xtype: 'panel',
- * title: 'Offset -300 Width & -200 Height',
- * anchor: '-300 -200'
- * },
- * {
- * xtype: 'panel',
- * title: 'Mixed Offset and Percent',
- * anchor: '-250 20%'
- * }
- * ]
- * });
- */
- Ext.define('Ext.layout.container.Anchor', {
- /* Begin Definitions */
- alias: 'layout.anchor',
- extend: 'Ext.layout.container.Container',
- alternateClassName: 'Ext.layout.AnchorLayout',
- /* End Definitions */
- type: 'anchor',
- manageOverflow: 2,
- renderTpl: [
- '{%this.renderBody(out,values);this.renderPadder(out,values)%}'
- ],
- <span id='Ext-layout-container-Anchor-cfg-anchor'> /**
- </span> * @cfg {String} anchor
- *
- * This configuation option is to be applied to **child `items`** of a container managed by
- * this layout (ie. configured with `layout:'anchor'`).
- *
- * This value is what tells the layout how an item should be anchored to the container. `items`
- * added to an AnchorLayout accept an anchoring-specific config property of **anchor** which is a string
- * containing two values: the horizontal anchor value and the vertical anchor value (for example, '100% 50%').
- * The following types of anchor values are supported:
- *
- * - **Percentage** : Any value between 1 and 100, expressed as a percentage.
- *
- * The first anchor is the percentage width that the item should take up within the container, and the
- * second is the percentage height. For example:
- *
- * // two values specified
- * anchor: '100% 50%' // render item complete width of the container and
- * // 1/2 height of the container
- * // one value specified
- * anchor: '100%' // the width value; the height will default to auto
- *
- * - **Offsets** : Any positive or negative integer value.
- *
- * This is a raw adjustment where the first anchor is the offset from the right edge of the container,
- * and the second is the offset from the bottom edge. For example:
- *
- * // two values specified
- * anchor: '-50 -100' // render item the complete width of the container
- * // minus 50 pixels and
- * // the complete height minus 100 pixels.
- * // one value specified
- * anchor: '-50' // anchor value is assumed to be the right offset value
- * // bottom offset will default to 0
- *
- * - **Sides** : Valid values are `right` (or `r`) and `bottom` (or `b`).
- *
- * Either the container must have a fixed size or an anchorSize config value defined at render time in
- * order for these to have any effect.
- *
- * - **Mixed** :
- *
- * Anchor values can also be mixed as needed. For example, to render the width offset from the container
- * right edge by 50 pixels and 75% of the container's height use:
- *
- * anchor: '-50 75%'
- */
- <span id='Ext-layout-container-Anchor-cfg-defaultAnchor'> /**
- </span> * @cfg {String} defaultAnchor
- * Default anchor for all child **container** items applied if no anchor or specific width is set on the child item.
- */
- defaultAnchor: '100%',
- parseAnchorRE: /^(r|right|b|bottom)$/i,
- beginLayout: function (ownerContext) {
- var me = this,
- dimensions = 0,
- anchorSpec, childContext, childItems, i, length, target;
- me.callParent(arguments);
- childItems = ownerContext.childItems; // populated by callParent
- length = childItems.length;
- for (i = 0; i < length; ++i) {
- childContext = childItems[i];
- anchorSpec = childContext.target.anchorSpec;
- if (anchorSpec) {
- if (childContext.widthModel.calculated && anchorSpec.right) {
- dimensions |= 1;
- }
- if (childContext.heightModel.calculated && anchorSpec.bottom) {
- dimensions |= 2;
- }
- if (dimensions == 3) { // if (both dimensions in play)
- break;
- }
- }
- }
- ownerContext.anchorDimensions = dimensions;
- // Work around WebKit RightMargin bug. We're going to inline-block all the children
- // only ONCE and remove it when we're done
- if (!Ext.supports.RightMargin && !me.rightMarginCleanerFn) {
- target = ownerContext.targetContext.el; // targetContext is added by superclass
- me.rightMarginCleanerFn = Ext.Element.getRightMarginFixCleaner(target);
- target.addCls(Ext.baseCSSPrefix + 'inline-children');
- }
- //<debug>
- me.sanityCheck(ownerContext);
- //</debug>
- },
- calculate: function (ownerContext) {
- var me = this,
- containerSize = me.getContainerSize(ownerContext);
- if (ownerContext.anchorDimensions !== ownerContext.state.calculatedAnchors) {
- me.calculateAnchors(ownerContext, containerSize);
- }
- if (ownerContext.hasDomProp('containerChildrenDone')) {
- // Once the child layouts are done we can determine the content sizes...
- if (!containerSize.gotAll) {
- me.done = false;
- }
- me.calculateContentSize(ownerContext, ownerContext.anchorDimensions);
- if (me.done) {
- me.calculateOverflow(ownerContext, containerSize, ownerContext.anchorDimensions);
- return;
- }
- }
- me.done = false;
- },
- calculateAnchors: function (ownerContext, containerSize) {
- var me = this,
- childItems = ownerContext.childItems,
- length = childItems.length,
- gotHeight = containerSize.gotHeight,
- gotWidth = containerSize.gotWidth,
- ownerHeight = containerSize.height,
- ownerWidth = containerSize.width,
- state = ownerContext.state,
- calculatedAnchors = (gotWidth ? 1 : 0) | (gotHeight ? 2 : 0),
- anchorSpec, childContext, childMargins, height, i, width;
- state.calculatedAnchors = (state.calculatedAnchors || 0) | calculatedAnchors;
- for (i = 0; i < length; i++) {
- childContext = childItems[i];
- childMargins = childContext.getMarginInfo();
- anchorSpec = childContext.target.anchorSpec;
- // Check widthModel in case "defaults" has applied an anchor to a component
- // that also has width (which must win). If we did not make this check in this
- // way, we would attempt to calculate a width where it had been configured.
- //
- if (gotWidth && childContext.widthModel.calculated) {
- width = anchorSpec.right(ownerWidth) - childMargins.width;
- width = me.adjustWidthAnchor(width, childContext);
- childContext.setWidth(width);
- }
- // Repeat for height
- if (gotHeight && childContext.heightModel.calculated) {
- height = anchorSpec.bottom(ownerHeight) - childMargins.height;
- height = me.adjustHeightAnchor(height, childContext);
- childContext.setHeight(height);
- }
- }
- },
- finishedLayout: function (ownerContext) {
- var cleanerFn = this.rightMarginCleanerFn;
- if (cleanerFn) {
- delete this.rightMarginCleanerFn;
- ownerContext.targetContext.el.removeCls(Ext.baseCSSPrefix + 'inline-children');
- cleanerFn();
- }
- },
- //<debug>
- sanityCheck: function (ownerContext) {
- var shrinkWrapWidth = ownerContext.widthModel.shrinkWrap,
- shrinkWrapHeight = ownerContext.heightModel.shrinkWrap,
- children = ownerContext.childItems,
- anchorSpec, comp, childContext,
- i, length;
- for (i = 0, length = children.length; i < length; ++i) {
- childContext = children[i];
- comp = childContext.target;
- anchorSpec = comp.anchorSpec;
- if (anchorSpec) {
- if (childContext.widthModel.calculated && anchorSpec.right) {
- if (shrinkWrapWidth) {
- Ext.log({
- level: 'warn',
- msg: 'Right anchor on '+comp.id+' in shrinkWrap width container'
- });
- }
- }
- if (childContext.heightModel.calculated && anchorSpec.bottom) {
- if (shrinkWrapHeight) {
- Ext.log({
- level: 'warn',
- msg: 'Bottom anchor on '+comp.id+' in shrinkWrap height container'
- });
- }
- }
- }
- }
- },
- //</debug>
- // private
- anchorFactory: {
- offset: function (delta) {
- return function(v) {
- return v + delta;
- };
- },
- ratio: function (ratio) {
- return function(v) {
- return Math.floor(v * ratio);
- };
- },
- standard: function (diff) {
- return function(v) {
- return v - diff;
- };
- }
- },
- parseAnchor: function(a, start, cstart) {
- if (a && a != 'none') {
- var factory = this.anchorFactory,
- delta;
- if (this.parseAnchorRE.test(a)) {
- return factory.standard(cstart - start);
- }
- if (a.indexOf('%') != -1) {
- return factory.ratio(parseFloat(a.replace('%', '')) * 0.01);
- }
- delta = parseInt(a, 10);
- if (!isNaN(delta)) {
- return factory.offset(delta);
- }
- }
- return null;
- },
- // private
- adjustWidthAnchor: function(value, childContext) {
- return value;
- },
- // private
- adjustHeightAnchor: function(value, childContext) {
- return value;
- },
- configureItem: function(item) {
- var me = this,
- owner = me.owner,
- anchor= item.anchor,
- anchorsArray,
- anchorWidth,
- anchorHeight;
- me.callParent(arguments);
- if (!item.anchor && item.items && !Ext.isNumber(item.width) && !(Ext.isIE6 && Ext.isStrict)) {
- item.anchor = anchor = me.defaultAnchor;
- }
- <span id='Ext-container-Container-cfg-anchorSize'> /**
- </span> * @cfg {Number/Object} anchorSize
- * Defines the anchoring size of container.
- * Either a number to define the width of the container or an object with `width` and `height` fields.
- * @member Ext.container.Container
- */
- if (owner.anchorSize) {
- if (typeof owner.anchorSize == 'number') {
- anchorWidth = owner.anchorSize;
- } else {
- anchorWidth = owner.anchorSize.width;
- anchorHeight = owner.anchorSize.height;
- }
- } else {
- anchorWidth = owner.initialConfig.width;
- anchorHeight = owner.initialConfig.height;
- }
- if (anchor) {
- // cache all anchor values
- anchorsArray = anchor.split(' ');
- item.anchorSpec = {
- right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth),
- bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight)
- };
- }
- },
- sizePolicy: {
- '': {
- setsWidth: 0,
- setsHeight: 0
- },
- b: {
- setsWidth: 0,
- setsHeight: 1
- },
- r: {
- '': {
- setsWidth: 1,
- setsHeight: 0
- },
- b: {
- setsWidth: 1,
- setsHeight: 1
- }
- }
- },
- getItemSizePolicy: function (item) {
- var anchorSpec = item.anchorSpec,
- key = '',
- policy = this.sizePolicy,
- sizeModel;
- if (anchorSpec) {
- sizeModel = this.owner.getSizeModel();
- if (anchorSpec.right && !sizeModel.width.shrinkWrap) {
- policy = policy.r;
- }
- if (anchorSpec.bottom && !sizeModel.height.shrinkWrap) {
- key = 'b';
- }
- }
- return policy[key];
- }
- });
- </pre>
- </body>
- </html>
|