X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/6746dc89c47ed01b165cc1152533605f97eb8e8d..HEAD:/docs/source/Manager3.html diff --git a/docs/source/Manager3.html b/docs/source/Manager3.html index 24a69a73..bc878f2f 100644 --- a/docs/source/Manager3.html +++ b/docs/source/Manager3.html @@ -3,8 +3,8 @@
/** - * @class Ext.state.Manager - * This is the global state manager. By default all components that are "state aware" check this class - * for state information if you don't pass them a custom state provider. In order for this class - * to be useful, it must be initialized with a provider when your application initializes. Example usage: - <pre><code> -// in your initialization function -init : function(){ - Ext.state.Manager.setProvider(new Ext.state.CookieProvider()); - var win = new Window(...); - win.restoreState(); -} - </code></pre> - * This class passes on calls from components to the underlying {@link Ext.state.Provider} so that - * there is a common interface that can be used without needing to refer to a specific provider instance - * in every component. +/** + * @class Ext.fx.Manager + * Animation Manager which keeps track of all current animations and manages them on a frame by frame basis. + * @private * @singleton - * @docauthor Evan Trimboli <evan@sencha.com> */ -Ext.define('Ext.state.Manager', { + +Ext.define('Ext.fx.Manager', { + + /* Begin Definitions */ + singleton: true, - requires: ['Ext.state.Provider'], + + requires: ['Ext.util.MixedCollection', + 'Ext.fx.target.Element', + 'Ext.fx.target.CompositeElement', + 'Ext.fx.target.Sprite', + 'Ext.fx.target.CompositeSprite', + 'Ext.fx.target.Component'], + + mixins: { + queue: 'Ext.fx.Queue' + }, + + /* End Definitions */ + constructor: function() { - this.provider = Ext.create('Ext.state.Provider'); + this.items = Ext.create('Ext.util.MixedCollection'); + this.mixins.queue.constructor.call(this); + + // this.requestAnimFrame = (function() { + // var raf = window.requestAnimationFrame || + // window.webkitRequestAnimationFrame || + // window.mozRequestAnimationFrame || + // window.oRequestAnimationFrame || + // window.msRequestAnimationFrame; + // if (raf) { + // return function(callback, element) { + // raf(callback); + // }; + // } + // else { + // return function(callback, element) { + // window.setTimeout(callback, Ext.fx.Manager.interval); + // }; + // } + // })(); }, - - - /** - * Configures the default state provider for your application - * @param {Provider} stateProvider The state provider to set + + /** + * @cfg {Number} interval Default interval in miliseconds to calculate each frame. Defaults to 16ms (~60fps) + */ + interval: 16, + + /** + * @cfg {Boolean} forceJS Turn off to not use CSS3 transitions when they are available */ - setProvider : function(stateProvider){ - this.provider = stateProvider; + forceJS: true, + + // @private Target factory + createTarget: function(target) { + var me = this, + useCSS3 = !me.forceJS && Ext.supports.Transitions, + targetObj; + + me.useCSS3 = useCSS3; + + // dom id + if (Ext.isString(target)) { + target = Ext.get(target); + } + // dom element + if (target && target.tagName) { + target = Ext.get(target); + targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target); + me.targets.add(targetObj); + return targetObj; + } + if (Ext.isObject(target)) { + // Element + if (target.dom) { + targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target); + } + // Element Composite + else if (target.isComposite) { + targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target); + } + // Draw Sprite + else if (target.isSprite) { + targetObj = Ext.create('Ext.fx.target.Sprite', target); + } + // Draw Sprite Composite + else if (target.isCompositeSprite) { + targetObj = Ext.create('Ext.fx.target.CompositeSprite', target); + } + // Component + else if (target.isComponent) { + targetObj = Ext.create('Ext.fx.target.Component', target); + } + else if (target.isAnimTarget) { + return target; + } + else { + return null; + } + me.targets.add(targetObj); + return targetObj; + } + else { + return null; + } }, - /** - * Returns the current value for a key - * @param {String} name The key name - * @param {Mixed} defaultValue The default value to return if the key lookup does not match - * @return {Mixed} The state data + /** + * Add an Anim to the manager. This is done automatically when an Anim instance is created. + * @param {Ext.fx.Anim} anim */ - get : function(key, defaultValue){ - return this.provider.get(key, defaultValue); + addAnim: function(anim) { + var items = this.items, + task = this.task; + // var me = this, + // items = me.items, + // cb = function() { + // if (items.length) { + // me.task = true; + // me.runner(); + // me.requestAnimFrame(cb); + // } + // else { + // me.task = false; + // } + // }; + + items.add(anim); + + // Start the timer if not already running + if (!task && items.length) { + task = this.task = { + run: this.runner, + interval: this.interval, + scope: this + }; + Ext.TaskManager.start(task); + } + + // //Start the timer if not already running + // if (!me.task && items.length) { + // me.requestAnimFrame(cb); + // } }, - /** - * Sets the value for a key - * @param {String} name The key name - * @param {Mixed} value The state data + /** + * Remove an Anim from the manager. This is done automatically when an Anim ends. + * @param {Ext.fx.Anim} anim */ - set : function(key, value){ - this.provider.set(key, value); + removeAnim: function(anim) { + // this.items.remove(anim); + var items = this.items, + task = this.task; + items.remove(anim); + // Stop the timer if there are no more managed Anims + if (task && !items.length) { + Ext.TaskManager.stop(task); + delete this.task; + } }, - /** - * Clears a value from the state - * @param {String} name The key name + /** + * @private + * Filter function to determine which animations need to be started */ - clear : function(key){ - this.provider.clear(key); + startingFilter: function(o) { + return o.paused === false && o.running === false && o.iterations > 0; + }, + + /** + * @private + * Filter function to determine which animations are still running + */ + runningFilter: function(o) { + return o.paused === false && o.running === true && o.isAnimator !== true; + }, + + /** + * @private + * Runner function being called each frame + */ + runner: function() { + var me = this, + items = me.items; + + me.targetData = {}; + me.targetArr = {}; + + // Single timestamp for all animations this interval + me.timestamp = new Date(); + + // Start any items not current running + items.filterBy(me.startingFilter).each(me.startAnim, me); + + // Build the new attributes to be applied for all targets in this frame + items.filterBy(me.runningFilter).each(me.runAnim, me); + + // Apply all the pending changes to their targets + me.applyPendingAttrs(); + }, + + /** + * @private + * Start the individual animation (initialization) + */ + startAnim: function(anim) { + anim.start(this.timestamp); + }, + + /** + * @private + * Run the individual animation for this frame + */ + runAnim: function(anim) { + if (!anim) { + return; + } + var me = this, + targetId = anim.target.getId(), + useCSS3 = me.useCSS3 && anim.target.type == 'element', + elapsedTime = me.timestamp - anim.startTime, + target, o; + + this.collectTargetData(anim, elapsedTime, useCSS3); + + // For CSS3 animation, we need to immediately set the first frame's attributes without any transition + // to get a good initial state, then add the transition properties and set the final attributes. + if (useCSS3) { + // Flush the collected attributes, without transition + anim.target.setAttr(me.targetData[targetId], true); + + // Add the end frame data + me.targetData[targetId] = []; + me.collectTargetData(anim, anim.duration, useCSS3); + + // Pause the animation so runAnim doesn't keep getting called + anim.paused = true; + + target = anim.target.target; + // We only want to attach an event on the last element in a composite + if (anim.target.isComposite) { + target = anim.target.target.last(); + } + + // Listen for the transitionend event + o = {}; + o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame; + o.scope = anim; + o.single = true; + target.on(o); + } + // For JS animation, trigger the lastFrame handler if this is the final frame + else if (elapsedTime >= anim.duration) { + me.applyPendingAttrs(true); + delete me.targetData[targetId]; + delete me.targetArr[targetId]; + anim.lastFrame(); + } + }, + + /** + * Collect target attributes for the given Anim object at the given timestamp + * @param {Ext.fx.Anim} anim The Anim instance + * @param {Number} timestamp Time after the anim's start time + */ + collectTargetData: function(anim, elapsedTime, useCSS3) { + var targetId = anim.target.getId(), + targetData = this.targetData[targetId], + data; + + if (!targetData) { + targetData = this.targetData[targetId] = []; + this.targetArr[targetId] = anim.target; + } + + data = { + duration: anim.duration, + easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing, + attrs: {} + }; + Ext.apply(data.attrs, anim.runAnim(elapsedTime)); + targetData.push(data); }, - /** - * Gets the currently configured state provider - * @return {Provider} The state provider + /** + * @private + * Apply all pending attribute changes to their targets */ - getProvider : function(){ - return this.provider; + applyPendingAttrs: function(isLastFrame) { + var targetData = this.targetData, + targetArr = this.targetArr, + targetId; + for (targetId in targetData) { + if (targetData.hasOwnProperty(targetId)) { + targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame); + } + } } -});+}); +