summaryrefslogtreecommitdiffstats
path: root/devtools/client/animationinspector/components/rate-selector.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/client/animationinspector/components/rate-selector.js')
-rw-r--r--devtools/client/animationinspector/components/rate-selector.js105
1 files changed, 105 insertions, 0 deletions
diff --git a/devtools/client/animationinspector/components/rate-selector.js b/devtools/client/animationinspector/components/rate-selector.js
new file mode 100644
index 000000000..e46664e6a
--- /dev/null
+++ b/devtools/client/animationinspector/components/rate-selector.js
@@ -0,0 +1,105 @@
+/* -*- 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/. */
+
+"use strict";
+
+const EventEmitter = require("devtools/shared/event-emitter");
+const {createNode} = require("devtools/client/animationinspector/utils");
+const { LocalizationHelper } = require("devtools/shared/l10n");
+const L10N =
+ new LocalizationHelper("devtools/client/locales/animationinspector.properties");
+
+// List of playback rate presets displayed in the timeline toolbar.
+const PLAYBACK_RATES = [.1, .25, .5, 1, 2, 5, 10];
+
+/**
+ * UI component responsible for displaying a playback rate selector UI.
+ * The rendering logic is such that a predefined list of rates is generated.
+ * If *all* animations passed to render share the same rate, then that rate is
+ * selected in the <select> element, otherwise, the empty value is selected.
+ * If the rate that all animations share isn't part of the list of predefined
+ * rates, than that rate is added to the list.
+ */
+function RateSelector() {
+ this.onRateChanged = this.onRateChanged.bind(this);
+ EventEmitter.decorate(this);
+}
+
+exports.RateSelector = RateSelector;
+
+RateSelector.prototype = {
+ init: function (containerEl) {
+ this.selectEl = createNode({
+ parent: containerEl,
+ nodeType: "select",
+ attributes: {
+ "class": "devtools-button",
+ "title": L10N.getStr("timeline.rateSelectorTooltip")
+ }
+ });
+
+ this.selectEl.addEventListener("change", this.onRateChanged);
+ },
+
+ destroy: function () {
+ this.selectEl.removeEventListener("change", this.onRateChanged);
+ this.selectEl.remove();
+ this.selectEl = null;
+ },
+
+ getAnimationsRates: function (animations) {
+ return sortedUnique(animations.map(a => a.state.playbackRate));
+ },
+
+ getAllRates: function (animations) {
+ let animationsRates = this.getAnimationsRates(animations);
+ if (animationsRates.length > 1) {
+ return PLAYBACK_RATES;
+ }
+
+ return sortedUnique(PLAYBACK_RATES.concat(animationsRates));
+ },
+
+ render: function (animations) {
+ let allRates = this.getAnimationsRates(animations);
+ let hasOneRate = allRates.length === 1;
+
+ this.selectEl.innerHTML = "";
+
+ if (!hasOneRate) {
+ // When the animations displayed have mixed playback rates, we can't
+ // select any of the predefined ones, instead, insert an empty rate.
+ createNode({
+ parent: this.selectEl,
+ nodeType: "option",
+ attributes: {value: "", selector: "true"},
+ textContent: "-"
+ });
+ }
+ for (let rate of this.getAllRates(animations)) {
+ let option = createNode({
+ parent: this.selectEl,
+ nodeType: "option",
+ attributes: {value: rate},
+ textContent: L10N.getFormatStr("player.playbackRateLabel", rate)
+ });
+
+ // If there's only one rate and this is the option for it, select it.
+ if (hasOneRate && rate === allRates[0]) {
+ option.setAttribute("selected", "true");
+ }
+ }
+ },
+
+ onRateChanged: function () {
+ let rate = parseFloat(this.selectEl.value);
+ if (!isNaN(rate)) {
+ this.emit("rate-changed", rate);
+ }
+ }
+};
+
+let sortedUnique = arr => [...new Set(arr)].sort((a, b) => a > b);