Files
tubestation/devtools/client/animationinspector/animation-panel.js
J. Ryan Stinnett 2dada8f365 Bug 912121 - Rewrite require / import to match source tree. rs=devtools
In a following patch, all DevTools moz.build files will use DevToolsModules to
install JS modules at a path that corresponds directly to their source tree
location.  Here we rewrite all require and import calls to match the new
location that these files are installed to.
2015-09-21 12:04:18 -05:00

223 lines
7.2 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* 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/. */
/* globals AnimationsController, document, performance, promise,
gToolbox, gInspector, requestAnimationFrame, cancelAnimationFrame, L10N */
"use strict";
const {AnimationsTimeline} = require("devtools/client/animationinspector/components");
/**
* The main animations panel UI.
*/
var AnimationsPanel = {
UI_UPDATED_EVENT: "ui-updated",
PANEL_INITIALIZED: "panel-initialized",
initialize: Task.async(function*() {
if (AnimationsController.destroyed) {
console.warn("Could not initialize the animation-panel, controller " +
"was destroyed");
return;
}
if (this.initialized) {
yield this.initialized.promise;
return;
}
this.initialized = promise.defer();
this.playersEl = document.querySelector("#players");
this.errorMessageEl = document.querySelector("#error-message");
this.pickerButtonEl = document.querySelector("#element-picker");
this.toggleAllButtonEl = document.querySelector("#toggle-all");
this.playTimelineButtonEl = document.querySelector("#pause-resume-timeline");
// If the server doesn't support toggling all animations at once, hide the
// whole global toolbar.
if (!AnimationsController.traits.hasToggleAll) {
document.querySelector("#global-toolbar").style.display = "none";
}
// Binding functions that need to be called in scope.
for (let functionName of ["onPickerStarted", "onPickerStopped",
"refreshAnimations", "toggleAll", "onTabNavigated",
"onTimelineDataChanged", "playPauseTimeline"]) {
this[functionName] = this[functionName].bind(this);
}
let hUtils = gToolbox.highlighterUtils;
this.togglePicker = hUtils.togglePicker.bind(hUtils);
this.animationsTimelineComponent = new AnimationsTimeline(gInspector);
this.animationsTimelineComponent.init(this.playersEl);
this.startListeners();
yield this.refreshAnimations();
this.initialized.resolve();
this.emit(this.PANEL_INITIALIZED);
}),
destroy: Task.async(function*() {
if (!this.initialized) {
return;
}
if (this.destroyed) {
yield this.destroyed.promise;
return;
}
this.destroyed = promise.defer();
this.stopListeners();
this.animationsTimelineComponent.destroy();
this.animationsTimelineComponent = null;
yield this.destroyPlayerWidgets();
this.playersEl = this.errorMessageEl = null;
this.toggleAllButtonEl = this.pickerButtonEl = null;
this.playTimelineButtonEl = null;
this.destroyed.resolve();
}),
startListeners: function() {
AnimationsController.on(AnimationsController.PLAYERS_UPDATED_EVENT,
this.refreshAnimations);
this.pickerButtonEl.addEventListener("click", this.togglePicker);
gToolbox.on("picker-started", this.onPickerStarted);
gToolbox.on("picker-stopped", this.onPickerStopped);
this.toggleAllButtonEl.addEventListener("click", this.toggleAll);
this.playTimelineButtonEl.addEventListener("click", this.playPauseTimeline);
gToolbox.target.on("navigate", this.onTabNavigated);
this.animationsTimelineComponent.on("timeline-data-changed",
this.onTimelineDataChanged);
},
stopListeners: function() {
AnimationsController.off(AnimationsController.PLAYERS_UPDATED_EVENT,
this.refreshAnimations);
this.pickerButtonEl.removeEventListener("click", this.togglePicker);
gToolbox.off("picker-started", this.onPickerStarted);
gToolbox.off("picker-stopped", this.onPickerStopped);
this.toggleAllButtonEl.removeEventListener("click", this.toggleAll);
this.playTimelineButtonEl.removeEventListener("click", this.playPauseTimeline);
gToolbox.target.off("navigate", this.onTabNavigated);
this.animationsTimelineComponent.off("timeline-data-changed",
this.onTimelineDataChanged);
},
togglePlayers: function(isVisible) {
if (isVisible) {
document.body.removeAttribute("empty");
document.body.setAttribute("timeline", "true");
} else {
document.body.setAttribute("empty", "true");
document.body.removeAttribute("timeline");
}
},
onPickerStarted: function() {
this.pickerButtonEl.setAttribute("checked", "true");
},
onPickerStopped: function() {
this.pickerButtonEl.removeAttribute("checked");
},
toggleAll: Task.async(function*() {
this.toggleAllButtonEl.classList.toggle("paused");
yield AnimationsController.toggleAll();
}),
/**
* Depending on the state of the timeline either pause or play the animations
* displayed in it.
* If the animations are finished, this will play them from the start again.
* If the animations are playing, this will pause them.
* If the animations are paused, this will resume them.
*/
playPauseTimeline: Task.async(function*() {
yield AnimationsController.toggleCurrentAnimations(this.timelineData.isMoving);
// Now that the playState have been changed make sure the player (the
// fronts) are up to date, and then refresh the UI.
for (let player of AnimationsController.animationPlayers) {
yield player.refreshState();
}
yield this.refreshAnimations();
}),
onTabNavigated: function() {
this.toggleAllButtonEl.classList.remove("paused");
},
onTimelineDataChanged: function(e, data) {
this.timelineData = data;
let {isPaused, isMoving, time} = data;
this.playTimelineButtonEl.classList.toggle("paused", !isMoving);
// Pause all animations and set their currentTimes (but only do this after
// the previous currentTime setting is done, as this gets called many times
// when users drag the scrubber with the mouse, and we want the server-side
// requests to be sequenced).
if (isPaused && !this.setCurrentTimeAllPromise) {
this.setCurrentTimeAllPromise =
AnimationsController.setCurrentTimeAll(time, true)
.catch(error => console.error(error))
.then(() => this.setCurrentTimeAllPromise = null);
}
},
refreshAnimations: Task.async(function*() {
let done = gInspector.updating("animationspanel");
// Empty the whole panel first.
this.togglePlayers(true);
yield this.destroyPlayerWidgets();
// Re-render the timeline component.
this.animationsTimelineComponent.render(
AnimationsController.animationPlayers,
AnimationsController.documentCurrentTime);
// If there are no players to show, show the error message instead and
// return.
if (!AnimationsController.animationPlayers.length) {
this.togglePlayers(false);
this.emit(this.UI_UPDATED_EVENT);
done();
return;
}
this.emit(this.UI_UPDATED_EVENT);
done();
}),
destroyPlayerWidgets: Task.async(function*() {
if (!this.playerWidgets) {
return;
}
let destroyers = this.playerWidgets.map(widget => widget.destroy());
yield promise.all(destroyers);
this.playerWidgets = null;
this.playersEl.innerHTML = "";
})
};
EventEmitter.decorate(AnimationsPanel);