--- a/devtools/client/inspector/animation/actions/animations.js
+++ b/devtools/client/inspector/animation/actions/animations.js
@@ -2,16 +2,17 @@
* 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 {
UPDATE_ANIMATIONS,
UPDATE_ELEMENT_PICKER_ENABLED,
+ UPDATE_SELECTED_ANIMATION,
UPDATE_SIDEBAR_SIZE
} = require("./index");
module.exports = {
/**
* Update the list of animation in the animation inspector.
*/
updateAnimations(animations) {
@@ -27,16 +28,26 @@ module.exports = {
updateElementPickerEnabled(elementPickerEnabled) {
return {
type: UPDATE_ELEMENT_PICKER_ENABLED,
elementPickerEnabled,
};
},
/**
+ * Update selected animation.
+ */
+ updateSelectedAnimation(selectedAnimation) {
+ return {
+ type: UPDATE_SELECTED_ANIMATION,
+ selectedAnimation,
+ };
+ },
+
+ /**
* Update the sidebar size.
*/
updateSidebarSize(sidebarSize) {
return {
type: UPDATE_SIDEBAR_SIZE,
sidebarSize,
};
}
--- a/devtools/client/inspector/animation/actions/index.js
+++ b/devtools/client/inspector/animation/actions/index.js
@@ -9,12 +9,15 @@ const { createEnum } = require("devtools
createEnum([
// Update the list of animation.
"UPDATE_ANIMATIONS",
// Update state of the picker enabled.
"UPDATE_ELEMENT_PICKER_ENABLED",
+ // Update selected animation.
+ "UPDATE_SELECTED_ANIMATION",
+
// Update sidebar size.
"UPDATE_SIDEBAR_SIZE",
], module.exports);
--- a/devtools/client/inspector/animation/animation.js
+++ b/devtools/client/inspector/animation/animation.js
@@ -10,27 +10,29 @@ const { Provider } = require("devtools/c
const EventEmitter = require("devtools/shared/event-emitter");
const App = createFactory(require("./components/App"));
const {
updateAnimations,
updateElementPickerEnabled,
+ updateSelectedAnimation,
updateSidebarSize
} = require("./actions/animations");
const { isAllAnimationEqual } = require("./utils/utils");
class AnimationInspector {
constructor(inspector, win) {
this.inspector = inspector;
this.win = win;
this.getAnimatedPropertyMap = this.getAnimatedPropertyMap.bind(this);
this.getNodeFromActor = this.getNodeFromActor.bind(this);
+ this.selectAnimation = this.selectAnimation.bind(this);
this.simulateAnimation = this.simulateAnimation.bind(this);
this.toggleElementPicker = this.toggleElementPicker.bind(this);
this.update = this.update.bind(this);
this.onElementPickerStarted = this.onElementPickerStarted.bind(this);
this.onElementPickerStopped = this.onElementPickerStopped.bind(this);
this.onSidebarResized = this.onSidebarResized.bind(this);
this.onSidebarSelect = this.onSidebarSelect.bind(this);
@@ -49,16 +51,17 @@ class AnimationInspector {
const {
onHideBoxModelHighlighter,
} = this.inspector.getPanel("boxmodel").getComponentProps();
const {
emit: emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
+ selectAnimation,
simulateAnimation,
toggleElementPicker,
} = this;
const target = this.inspector.target;
this.animationsFront = new AnimationsFront(target.client, target.form);
const provider = createElement(Provider,
@@ -69,16 +72,17 @@ class AnimationInspector {
},
App(
{
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
toggleElementPicker,
}
)
);
this.provider = provider;
@@ -222,16 +226,20 @@ class AnimationInspector {
if (!this.animations || !isAllAnimationEqual(animations, this.animations)) {
this.inspector.store.dispatch(updateAnimations(animations));
this.animations = animations;
}
done();
}
+ selectAnimation(animation) {
+ this.inspector.store.dispatch(updateSelectedAnimation(animation));
+ }
+
onElementPickerStarted() {
this.inspector.store.dispatch(updateElementPickerEnabled(true));
}
onElementPickerStopped() {
this.inspector.store.dispatch(updateElementPickerEnabled(false));
}
--- a/devtools/client/inspector/animation/components/AnimationItem.js
+++ b/devtools/client/inspector/animation/components/AnimationItem.js
@@ -1,69 +1,105 @@
/* 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 { connect } = require("devtools/client/shared/vendor/react-redux");
const { createFactory, PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const AnimationTarget = createFactory(require("./AnimationTarget"));
const SummaryGraph = createFactory(require("./graph/SummaryGraph"));
class AnimationItem extends PureComponent {
static get propTypes() {
return {
animation: PropTypes.object.isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
+ selectAnimation: PropTypes.func.isRequired,
+ selectedAnimation: PropTypes.object.isRequired,
setSelectedNode: PropTypes.func.isRequired,
simulateAnimation: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
+ constructor(props) {
+ super(props);
+
+ this.state = {
+ isSelected: false,
+ };
+ }
+
+ componentWillReceiveProps(nextProps) {
+ const { animation } = this.props;
+ this.setState({
+ isSelected: animation.actorID === nextProps.selectedAnimation.actorID
+ });
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return this.state.isSelected !== nextState.isSelected ||
+ this.props.animation !== nextProps.animation ||
+ this.props.timeScale !== nextProps.timeScale;
+ }
+
render() {
const {
animation,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
timeScale,
} = this.props;
+ const {
+ isSelected,
+ } = this.state;
return dom.li(
{
- className: `animation-item ${ animation.state.type }`
+ className: `animation-item ${ animation.state.type } ` +
+ (isSelected ? "selected" : ""),
},
AnimationTarget(
{
animation,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
}
),
SummaryGraph(
{
animation,
emitEventForTest,
getAnimatedPropertyMap,
+ selectAnimation,
simulateAnimation,
timeScale,
}
)
);
}
}
-module.exports = AnimationItem;
+const mapStateToProps = state => {
+ return {
+ selectedAnimation: state.animations.selectedAnimation,
+ };
+};
+
+module.exports = connect(mapStateToProps)(AnimationItem);
--- a/devtools/client/inspector/animation/components/AnimationList.js
+++ b/devtools/client/inspector/animation/components/AnimationList.js
@@ -14,30 +14,32 @@ class AnimationList extends PureComponen
static get propTypes() {
return {
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
+ selectAnimation: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
simulateAnimation: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
render() {
const {
animations,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
timeScale,
} = this.props;
return dom.ul(
{
className: "animation-list"
@@ -46,16 +48,17 @@ class AnimationList extends PureComponen
AnimationItem(
{
animation,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
timeScale,
}
)
)
);
}
--- a/devtools/client/inspector/animation/components/AnimationListContainer.js
+++ b/devtools/client/inspector/animation/components/AnimationListContainer.js
@@ -18,29 +18,31 @@ class AnimationListContainer extends Pur
static get propTypes() {
return {
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
+ selectAnimation: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
simulateAnimation: PropTypes.func.isRequired,
};
}
render() {
const {
animations,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
} = this.props;
const timeScale = new TimeScale(animations);
return dom.div(
{
className: "animation-list-container"
@@ -53,16 +55,17 @@ class AnimationListContainer extends Pur
AnimationList(
{
animations,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
timeScale,
}
)
);
}
}
--- a/devtools/client/inspector/animation/components/App.js
+++ b/devtools/client/inspector/animation/components/App.js
@@ -18,16 +18,17 @@ class App extends PureComponent {
static get propTypes() {
return {
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
+ selectAnimation: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
simulateAnimation: PropTypes.func.isRequired,
toggleElementPicker: PropTypes.func.isRequired,
};
}
shouldComponentUpdate(nextProps, nextState) {
return this.props.animations.length !== 0 || nextProps.animations.length !== 0;
@@ -36,16 +37,17 @@ class App extends PureComponent {
render() {
const {
animations,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
toggleElementPicker,
} = this.props;
return dom.div(
{
id: "animation-container"
@@ -60,16 +62,17 @@ class App extends PureComponent {
startPanel: AnimationListContainer(
{
animations,
emitEventForTest,
getAnimatedPropertyMap,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
+ selectAnimation,
setSelectedNode,
simulateAnimation,
}
),
vert: false,
})
:
NoAnimationPanel(
--- a/devtools/client/inspector/animation/components/graph/SummaryGraph.js
+++ b/devtools/client/inspector/animation/components/graph/SummaryGraph.js
@@ -16,21 +16,32 @@ const SummaryGraphPath = createFactory(r
const { getFormatStr, getStr, numberWithDecimals } = require("../../utils/l10n");
class SummaryGraph extends PureComponent {
static get propTypes() {
return {
animation: PropTypes.object.isRequired,
emitEventForTest: PropTypes.func.isRequired,
getAnimatedPropertyMap: PropTypes.func.isRequired,
+ selectAnimation: PropTypes.func.isRequired,
simulateAnimation: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
+ constructor(props) {
+ super(props);
+
+ this.onClick = this.onClick.bind(this);
+ }
+
+ onClick() {
+ this.props.selectAnimation(this.props.animation);
+ }
+
getTitleText(state) {
const getTime =
time => getFormatStr("player.timeLabel", numberWithDecimals(time / 1000, 2));
let text = "";
// Adding the name.
text += getFormattedTitle(state);
@@ -130,16 +141,17 @@ class SummaryGraph extends PureComponent
simulateAnimation,
timeScale,
} = this.props;
return dom.div(
{
className: "animation-summary-graph" +
(animation.state.isRunningOnCompositor ? " compositor" : ""),
+ onClick: this.onClick,
title: this.getTitleText(animation.state),
},
SummaryGraphPath(
{
animation,
emitEventForTest,
getAnimatedPropertyMap,
simulateAnimation,
--- a/devtools/client/inspector/animation/reducers/animations.js
+++ b/devtools/client/inspector/animation/reducers/animations.js
@@ -2,22 +2,24 @@
* 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 {
UPDATE_ANIMATIONS,
UPDATE_ELEMENT_PICKER_ENABLED,
+ UPDATE_SELECTED_ANIMATION,
UPDATE_SIDEBAR_SIZE,
} = require("../actions/index");
const INITIAL_STATE = {
animations: [],
elementPickerEnabled: false,
+ selectedAnimation: null,
sidebarSize: {
height: 0,
width: 0,
},
};
const reducers = {
[UPDATE_ANIMATIONS](state, { animations }) {
@@ -27,16 +29,22 @@ const reducers = {
},
[UPDATE_ELEMENT_PICKER_ENABLED](state, { elementPickerEnabled }) {
return Object.assign({}, state, {
elementPickerEnabled
});
},
+ [UPDATE_SELECTED_ANIMATION](state, { selectedAnimation }) {
+ return Object.assign({}, state, {
+ selectedAnimation
+ });
+ },
+
[UPDATE_SIDEBAR_SIZE](state, { sidebarSize }) {
return Object.assign({}, state, {
sidebarSize
});
},
};
module.exports = function (state = INITIAL_STATE, action) {
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -82,16 +82,20 @@
--effect-timing-graph-color: var(--theme-highlight-bluegrey);
}
.animation-item.scriptanimation {
--computed-timing-graph-color: var(--theme-graphs-green);
--effect-timing-graph-color: var(--theme-highlight-green);
}
+.animation-item.selected {
+ background-color: var(--theme-selection-background-hover);
+}
+
/* Animation Target */
.animation-target {
align-items: center;
display: flex;
height: 100%;
padding-left: 4px;
width: var(--sidebar-width);
}