Bug 1406285 - Part 3: Implement summary graph base. r?gl
MozReview-Commit-ID: KMbUvJPDuNM
--- a/devtools/client/inspector/animation/components/AnimationItem.js
+++ b/devtools/client/inspector/animation/components/AnimationItem.js
@@ -4,50 +4,59 @@
"use strict";
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,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
render() {
const {
animation,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
+ timeScale,
} = this.props;
return dom.li(
{
className: "animation-item"
},
AnimationTarget(
{
animation,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
}
+ ),
+ SummaryGraph(
+ {
+ animation,
+ timeScale,
+ }
)
);
}
}
module.exports = AnimationItem;
--- a/devtools/client/inspector/animation/components/AnimationList.js
+++ b/devtools/client/inspector/animation/components/AnimationList.js
@@ -14,42 +14,45 @@ class AnimationList extends PureComponen
static get propTypes() {
return {
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
emitEventForTest: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
setSelectedNode: PropTypes.func.isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
render() {
const {
animations,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
+ timeScale,
} = this.props;
return dom.ul(
{
className: "animation-list"
},
animations.map(animation =>
AnimationItem(
{
animation,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
+ timeScale,
}
)
)
);
}
}
module.exports = AnimationList;
--- a/devtools/client/inspector/animation/components/AnimationListContainer.js
+++ b/devtools/client/inspector/animation/components/AnimationListContainer.js
@@ -7,16 +7,18 @@
const { createFactory, PureComponent } =
require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const AnimationList = createFactory(require("./AnimationList"));
const AnimationListHeader = createFactory(require("./AnimationListHeader"));
+const TimeScale = require("../utils/timescale");
+
class AnimationListContainer extends PureComponent {
static get propTypes() {
return {
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
emitEventForTest: PropTypes.func.isRequired,
getNodeFromActor: PropTypes.func.isRequired,
onHideBoxModelHighlighter: PropTypes.func.isRequired,
onShowBoxModelHighlighterForNode: PropTypes.func.isRequired,
@@ -28,33 +30,35 @@ class AnimationListContainer extends Pur
const {
animations,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
} = this.props;
+ const timeScale = new TimeScale(animations);
return dom.div(
{
className: "animation-list-container"
},
AnimationListHeader(
{
- animations
+ timeScale,
}
),
AnimationList(
{
animations,
emitEventForTest,
getNodeFromActor,
onHideBoxModelHighlighter,
onShowBoxModelHighlighterForNode,
setSelectedNode,
+ timeScale,
}
)
);
}
}
module.exports = AnimationListContainer;
--- a/devtools/client/inspector/animation/components/AnimationListHeader.js
+++ b/devtools/client/inspector/animation/components/AnimationListHeader.js
@@ -9,29 +9,29 @@ const { createFactory, PureComponent } =
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const AnimationTimelineTickList = createFactory(require("./AnimationTimelineTickList"));
class AnimationListHeader extends PureComponent {
static get propTypes() {
return {
- animations: PropTypes.arrayOf(PropTypes.object).isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
render() {
- const { animations } = this.props;
+ const { timeScale } = this.props;
return dom.div(
{
className: "animation-list-header devtools-toolbar"
},
AnimationTimelineTickList(
{
- animations
+ timeScale
}
)
);
}
}
module.exports = AnimationListHeader;
--- a/devtools/client/inspector/animation/components/AnimationTimelineTickList.js
+++ b/devtools/client/inspector/animation/components/AnimationTimelineTickList.js
@@ -8,27 +8,26 @@ const { createFactory, PureComponent } =
require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const AnimationTimelineTickItem = createFactory(require("./AnimationTimelineTickItem"));
-const TimeScale = require("../utils/timescale");
const { findOptimalTimeInterval } = require("../utils/utils");
// The minimum spacing between 2 time graduation headers in the timeline (px).
const TIME_GRADUATION_MIN_SPACING = 40;
class AnimationTimelineTickList extends PureComponent {
static get propTypes() {
return {
- animations: PropTypes.arrayOf(PropTypes.object).isRequired,
sidebarWidth: PropTypes.number.isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
this.state = {
tickList: [],
@@ -56,18 +55,17 @@ class AnimationTimelineTickList extends
return true;
}
}
return false;
}
updateTickList() {
- const { animations } = this.props;
- const timeScale = new TimeScale(animations);
+ const { timeScale } = this.props;
const tickListEl = ReactDOM.findDOMNode(this);
const width = tickListEl.offsetWidth;
const animationDuration = timeScale.getDuration();
const minTimeInterval = TIME_GRADUATION_MIN_SPACING * animationDuration / width;
const intervalLength = findOptimalTimeInterval(minTimeInterval);
const intervalWidth = intervalLength * width / animationDuration;
const tickCount = width / intervalWidth;
const intervalPositionPercentage = 100 * intervalWidth / width;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/components/graph/SummaryGraph.js
@@ -0,0 +1,41 @@
+/* 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 { 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 SummaryGraphPath = createFactory(require("./SummaryGraphPath"));
+
+class SummaryGraph extends PureComponent {
+ static get propTypes() {
+ return {
+ animation: PropTypes.object.isRequired,
+ timeScale: PropTypes.object.isRequired,
+ };
+ }
+
+ render() {
+ const {
+ animation,
+ timeScale,
+ } = this.props;
+
+ return dom.div(
+ {
+ className: "animation-summary-graph",
+ },
+ SummaryGraphPath(
+ {
+ animation,
+ timeScale,
+ }
+ )
+ );
+ }
+}
+
+module.exports = SummaryGraph;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/components/graph/SummaryGraphPath.js
@@ -0,0 +1,38 @@
+/* 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 { PureComponent } = require("devtools/client/shared/vendor/react");
+const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const dom = require("devtools/client/shared/vendor/react-dom-factories");
+
+class SummaryGraphPath extends PureComponent {
+ static get propTypes() {
+ return {
+ animation: PropTypes.object.isRequired,
+ timeScale: PropTypes.object.isRequired,
+ };
+ }
+
+ render() {
+ const {
+ animation,
+ timeScale,
+ } = this.props;
+
+ const totalDisplayedDuration = animation.state.playbackRate * timeScale.getDuration();
+ const startTime = timeScale.minStartTime;
+
+ return dom.svg(
+ {
+ className: "animation-summary-graph-path",
+ preserveAspectRatio: "none",
+ viewBox: `${ startTime } -1 ${ totalDisplayedDuration } 1`
+ }
+ );
+ }
+}
+
+module.exports = SummaryGraphPath;
new file mode 100644
--- /dev/null
+++ b/devtools/client/inspector/animation/components/graph/moz.build
@@ -0,0 +1,8 @@
+# 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/.
+
+DevToolsModules(
+ 'SummaryGraph.js',
+ 'SummaryGraphPath.js'
+)
--- a/devtools/client/inspector/animation/components/moz.build
+++ b/devtools/client/inspector/animation/components/moz.build
@@ -1,12 +1,16 @@
# 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/.
+DIRS += [
+ 'graph'
+]
+
DevToolsModules(
'AnimationItem.js',
'AnimationList.js',
'AnimationListContainer.js',
'AnimationListHeader.js',
'AnimationTarget.js',
'AnimationTimelineTickItem.js',
'AnimationTimelineTickList.js',
--- a/devtools/client/themes/animation.css
+++ b/devtools/client/themes/animation.css
@@ -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/. */
/* Animation-inspector specific theme variables */
:root {
--animation-even-background-color: rgba(0, 0, 0, 0.05);
--command-pick-image: url(chrome://devtools/skin/images/command-pick.svg);
+ --graph-right-offset: 10px;
--sidebar-width: 200px;
}
:root.theme-dark {
--animation-even-background-color: rgba(255, 255, 255, 0.05);
}
:root.theme-firebug {
@@ -22,19 +23,19 @@
.animation-list-header {
display: flex;
justify-content: flex-end;
padding: 0;
}
/* Animation Timeline Tick List */
.animation-timeline-tick-list {
- margin-right: 10px;
+ margin-right: var(--graph-right-offset);
position: relative;
- width: calc(100% - var(--sidebar-width) - 10px);
+ width: calc(100% - var(--sidebar-width) - var(--graph-right-offset));
}
.animation-timeline-tick-item {
border-left: 0.5px solid rgba(128, 136, 144, .5);
height: 100vh;
position: absolute;
}
@@ -42,16 +43,17 @@
.animation-list {
list-style-type: none;
margin-top: 0;
padding: 0;
}
/* Animation Item */
.animation-item {
+ display: flex;
height: 30px;
}
.animation-item:nth-child(2n+1) {
background-color: var(--animation-even-background-color);
}
/* Animation Target */
@@ -62,16 +64,27 @@
padding-left: 4px;
width: var(--sidebar-width);
}
.animation-target .tag-name {
cursor: default;
}
+/* Summary Graph */
+.animation-summary-graph {
+ height: 100%;
+ width: calc(100% - var(--sidebar-width) - var(--graph-right-offset));
+}
+
+.animation-summary-graph-path {
+ height: 100%;
+ width: 100%;
+}
+
/* No Animation Panel */
.animation-error-message {
overflow: auto;
}
.animation-error-message > p {
white-space: pre;
}