diff options
Diffstat (limited to 'devtools/shared/fronts/animation.js')
-rw-r--r-- | devtools/shared/fronts/animation.js | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/devtools/shared/fronts/animation.js b/devtools/shared/fronts/animation.js new file mode 100644 index 000000000..01c9f0bfa --- /dev/null +++ b/devtools/shared/fronts/animation.js @@ -0,0 +1,140 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +"use strict"; + +const { + Front, + FrontClassWithSpec, + custom, + preEvent +} = require("devtools/shared/protocol"); +const { + animationPlayerSpec, + animationsSpec +} = require("devtools/shared/specs/animation"); +const { Task } = require("devtools/shared/task"); + +const AnimationPlayerFront = FrontClassWithSpec(animationPlayerSpec, { + initialize: function (conn, form, detail, ctx) { + Front.prototype.initialize.call(this, conn, form, detail, ctx); + + this.state = {}; + }, + + form: function (form, detail) { + if (detail === "actorid") { + this.actorID = form; + return; + } + this._form = form; + this.state = this.initialState; + }, + + destroy: function () { + Front.prototype.destroy.call(this); + }, + + /** + * If the AnimationsActor was given a reference to the WalkerActor previously + * then calling this getter will return the animation target NodeFront. + */ + get animationTargetNodeFront() { + if (!this._form.animationTargetNodeActorID) { + return null; + } + + return this.conn.getActor(this._form.animationTargetNodeActorID); + }, + + /** + * Getter for the initial state of the player. Up to date states can be + * retrieved by calling the getCurrentState method. + */ + get initialState() { + return { + type: this._form.type, + startTime: this._form.startTime, + previousStartTime: this._form.previousStartTime, + currentTime: this._form.currentTime, + playState: this._form.playState, + playbackRate: this._form.playbackRate, + name: this._form.name, + duration: this._form.duration, + delay: this._form.delay, + endDelay: this._form.endDelay, + iterationCount: this._form.iterationCount, + iterationStart: this._form.iterationStart, + easing: this._form.easing, + fill: this._form.fill, + direction: this._form.direction, + isRunningOnCompositor: this._form.isRunningOnCompositor, + propertyState: this._form.propertyState, + documentCurrentTime: this._form.documentCurrentTime + }; + }, + + /** + * Executed when the AnimationPlayerActor emits a "changed" event. Used to + * update the local knowledge of the state. + */ + onChanged: preEvent("changed", function (partialState) { + let {state} = this.reconstructState(partialState); + this.state = state; + }), + + /** + * Refresh the current state of this animation on the client from information + * found on the server. Doesn't return anything, just stores the new state. + */ + refreshState: Task.async(function* () { + let data = yield this.getCurrentState(); + if (this.currentStateHasChanged) { + this.state = data; + } + }), + + /** + * getCurrentState interceptor re-constructs incomplete states since the actor + * only sends the values that have changed. + */ + getCurrentState: custom(function () { + this.currentStateHasChanged = false; + return this._getCurrentState().then(partialData => { + let {state, hasChanged} = this.reconstructState(partialData); + this.currentStateHasChanged = hasChanged; + return state; + }); + }, { + impl: "_getCurrentState" + }), + + reconstructState: function (data) { + let hasChanged = false; + + for (let key in this.state) { + if (typeof data[key] === "undefined") { + data[key] = this.state[key]; + } else if (data[key] !== this.state[key]) { + hasChanged = true; + } + } + + return {state: data, hasChanged}; + } +}); + +exports.AnimationPlayerFront = AnimationPlayerFront; + +const AnimationsFront = FrontClassWithSpec(animationsSpec, { + initialize: function (client, {animationsActor}) { + Front.prototype.initialize.call(this, client, {actor: animationsActor}); + this.manage(this); + }, + + destroy: function () { + Front.prototype.destroy.call(this); + } +}); + +exports.AnimationsFront = AnimationsFront; |