Bug 1456828 - Part 2: Apply ProgressInspectionPanel to animations. r=gl

MozReview-Commit-ID: 7It2CibH3oa

--HG--
extra : rebase_source : a1e0cce1f9c0af731cb0e6d29c70e9ce20e4d5ea
This commit is contained in:
Daisuke Akatsuka 2018-06-15 13:38:27 +09:00
Родитель 976f361b5c
Коммит bb01d0ac70
7 изменённых файлов: 101 добавлений и 301 удалений

Просмотреть файл

@ -6,11 +6,20 @@
const { createFactory, PureComponent } =
require("devtools/client/shared/vendor/react");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const { connect } = require("devtools/client/shared/vendor/react-redux");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const AnimationList = createFactory(require("./AnimationList"));
const AnimationListHeader = createFactory(require("./AnimationListHeader"));
const CurrentTimeScrubberController =
createFactory(require("./CurrentTimeScrubberController"));
const ProgressInspectionPanel = createFactory(require("./ProgressInspectionPanel"));
const { findOptimalTimeInterval } = require("../utils/utils");
// The minimum spacing between 2 time graduation headers in the timeline (px).
const TIME_GRADUATION_MIN_SPACING = 40;
class AnimationListContainer extends PureComponent {
static get propTypes() {
@ -32,6 +41,44 @@ class AnimationListContainer extends PureComponent {
};
}
constructor(props) {
super(props);
this.state = {
// tick labels and lines on the progress inspection panel
ticks: [],
};
}
componentDidMount() {
this.updateState(this.props);
}
componentWillReceiveProps(nextProps) {
this.updateState(nextProps);
}
updateState(props) {
const { timeScale } = props;
const tickLinesEl = ReactDOM.findDOMNode(this).querySelector(".tick-lines");
const width = tickLinesEl.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 ticks = [];
for (let i = 0; i <= tickCount; i++) {
const position = i * intervalWidth * 100 / width;
const label = timeScale.formatTime(timeScale.distanceToRelativeTime(position));
ticks.push({ position, label });
}
this.setState({ ticks });
}
render() {
const {
addAnimationsCurrentTimeListener,
@ -49,12 +96,15 @@ class AnimationListContainer extends PureComponent {
simulateAnimation,
timeScale,
} = this.props;
const { ticks } = this.state;
return dom.div(
{
className: "animation-list-container"
},
AnimationListHeader(
ProgressInspectionPanel(
{
indicator: CurrentTimeScrubberController(
{
addAnimationsCurrentTimeListener,
removeAnimationsCurrentTimeListener,
@ -62,7 +112,7 @@ class AnimationListContainer extends PureComponent {
timeScale,
}
),
AnimationList(
list: AnimationList(
{
animations,
emitEventForTest,
@ -76,9 +126,18 @@ class AnimationListContainer extends PureComponent {
simulateAnimation,
timeScale,
}
),
ticks,
}
)
);
}
}
module.exports = AnimationListContainer;
const mapStateToProps = state => {
return {
sidebarWidth: state.animations.sidebarSize ? state.animations.sidebarSize.width : 0
};
};
module.exports = connect(mapStateToProps)(AnimationListContainer);

Просмотреть файл

@ -1,60 +0,0 @@
/* 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 PropTypes = require("devtools/client/shared/vendor/react-prop-types");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const AnimationTimelineTickList = createFactory(require("./AnimationTimelineTickList"));
const CurrentTimeScrubberController =
createFactory(require("./CurrentTimeScrubberController"));
class AnimationListHeader extends PureComponent {
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
setAnimationsCurrentTime: PropTypes.func.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
render() {
const {
addAnimationsCurrentTimeListener,
removeAnimationsCurrentTimeListener,
setAnimationsCurrentTime,
timeScale,
} = this.props;
return dom.div(
{
className: "animation-list-header"
},
dom.div(
{
className: "devtools-toolbar"
}
),
AnimationTimelineTickList(
{
timeScale
}
),
CurrentTimeScrubberController(
{
addAnimationsCurrentTimeListener,
removeAnimationsCurrentTimeListener,
setAnimationsCurrentTime,
timeScale,
}
)
);
}
}
module.exports = AnimationListHeader;

Просмотреть файл

@ -1,32 +0,0 @@
/* 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 AnimationTimeTickItem extends PureComponent {
static get propTypes() {
return {
position: PropTypes.number.isRequired,
timeTickLabel: PropTypes.string.isRequired,
};
}
render() {
const { position, timeTickLabel } = this.props;
return dom.div(
{
className: "animation-timeline-tick-item",
style: { left: `${ position }%` }
},
timeTickLabel
);
}
}
module.exports = AnimationTimeTickItem;

Просмотреть файл

@ -1,101 +0,0 @@
/* 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 { Component, createFactory } = 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 { 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 Component {
static get propTypes() {
return {
sidebarWidth: PropTypes.number.isRequired,
timeScale: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
this.state = {
tickList: [],
};
}
componentDidMount() {
this.updateTickList(this.props);
}
componentWillReceiveProps(nextProps) {
this.updateTickList(nextProps);
}
shouldComponentUpdate(nextProps, nextState) {
if (this.state.tickList.length !== nextState.tickList.length) {
return true;
}
for (let i = 0; i < this.state.tickList.length; i++) {
const currentTickItem = this.state.tickList[i];
const nextTickItem = nextState.tickList[i];
if (currentTickItem.timeTickLabel !== nextTickItem.timeTickLabel) {
return true;
}
}
return false;
}
updateTickList(props) {
const { timeScale } = 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;
const tickList = [];
for (let i = 0; i <= tickCount; i++) {
const position = i * intervalPositionPercentage;
const timeTickLabel =
timeScale.formatTime(timeScale.distanceToRelativeTime(position));
tickList.push({ position, timeTickLabel });
}
this.setState({ tickList });
}
render() {
const { tickList } = this.state;
return dom.div(
{
className: "animation-timeline-tick-list"
},
tickList.map(tickItem => AnimationTimelineTickItem(tickItem))
);
}
}
const mapStateToProps = state => {
return {
sidebarWidth: state.animations.sidebarSize ? state.animations.sidebarSize.width : 0
};
};
module.exports = connect(mapStateToProps)(AnimationTimelineTickList);

Просмотреть файл

@ -18,10 +18,7 @@ DevToolsModules(
'AnimationItem.js',
'AnimationList.js',
'AnimationListContainer.js',
'AnimationListHeader.js',
'AnimationTarget.js',
'AnimationTimelineTickItem.js',
'AnimationTimelineTickList.js',
'AnimationToolbar.js',
'App.js',
'CurrentTimeLabel.js',

Просмотреть файл

@ -5,8 +5,8 @@
// Test for following timeline tick items.
// * animation list header elements existence
// * timeline tick item elements existence
// * count and label of timeline tick elements changing by the sidebar width
// * tick labels elements existence
// * count and text of tick label elements changing by the sidebar width
const TimeScale = require("devtools/client/inspector/animation/utils/timescale");
const { findOptimalTimeInterval } =
@ -29,27 +29,24 @@ add_task(async function() {
ok(listHeaderEl, "The header element should be in animation list container element");
info("Checking time tick item elements existence");
assertTimelineTickItems(timeScale, listContainerEl);
const timelineTickItemLength =
listContainerEl.querySelectorAll(".animation-timeline-tick-item").length;
assertTickLabels(timeScale, listContainerEl);
const timelineTickItemLength = listContainerEl.querySelectorAll(".tick-label").length;
info("Checking timeline tick item elements after enlarge sidebar width");
await setSidebarWidth("100%", inspector);
assertTimelineTickItems(timeScale, listContainerEl);
ok(timelineTickItemLength <
listContainerEl.querySelectorAll(".animation-timeline-tick-item").length,
assertTickLabels(timeScale, listContainerEl);
ok(timelineTickItemLength < listContainerEl.querySelectorAll(".tick-label").length,
"The timeline tick item elements should increase");
});
/**
* Assert timeline tick item's position and label.
* Assert tick label's position and label.
*
* @param {TimeScale} - timeScale
* @param {Element} - listContainerEl
*/
function assertTimelineTickItems(timeScale, listContainerEl) {
const timelineTickListEl =
listContainerEl.querySelector(".animation-timeline-tick-list");
function assertTickLabels(timeScale, listContainerEl) {
const timelineTickListEl = listContainerEl.querySelector(".tick-labels");
ok(timelineTickListEl,
"The animation timeline tick list element should be in header");
@ -59,8 +56,7 @@ function assertTimelineTickItems(timeScale, listContainerEl) {
const interval = findOptimalTimeInterval(minTimeInterval);
const expectedTickItem = Math.ceil(animationDuration / interval);
const timelineTickItemEls =
timelineTickListEl.querySelectorAll(".animation-timeline-tick-item");
const timelineTickItemEls = timelineTickListEl.querySelectorAll(".tick-label");
is(timelineTickItemEls.length, expectedTickItem,
"The expected number of timeline ticks were found");

Просмотреть файл

@ -12,6 +12,7 @@
--fill-color-cssanimation: var(--theme-contrast-background);
--fill-color-csstransition: var(--theme-highlight-blue);
--fill-color-scriptanimation: var(--theme-graphs-green);
--graph-height: 30px;
--graph-right-offset: 10px;
--keyframe-marker-shadow-color: #c4c4c4;
--pause-image: url(chrome://devtools/skin/images/pause.svg);
@ -88,10 +89,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
/* Animation List Container */
.animation-list-container {
height: 100%;
overflow-y: auto;
overflow-x: hidden;
position: relative;
overflow: hidden;
width: 100%;
-moz-user-select: none;
}
@ -100,50 +98,10 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
cursor: col-resize;
}
/* Animation List Header */
.animation-list-header {
display: grid;
grid-template-columns: var(--sidebar-width) calc(100% - var(--sidebar-width) - var(--graph-right-offset)) var(--graph-right-offset);
line-height: var(--devtools-toolbar-height);
min-height: 100%;
padding: 0;
pointer-events: none;
position: sticky;
top: 0;
z-index: 2;
}
.animation-list-header .devtools-toolbar {
position: absolute;
width: 100%;
}
/* Animation Timeline Tick List */
.animation-timeline-tick-list {
grid-column: 2/3;
height: 100%;
position: relative;
}
.animation-timeline-tick-item {
height: 100%;
position: absolute;
}
.animation-timeline-tick-item::before {
border-left: var(--tick-line-style);
content: "";
height: 100%;
position: absolute;
}
/* Current Time Scrubber */
.current-time-scrubber-controller {
grid-column: 2 / 3;
height: 100%;
padding: 0;
position: absolute;
width: 100%;
z-index: 2;
}
.current-time-scrubber-controller::before {
@ -163,7 +121,6 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
pointer-events: auto;
position: absolute;
width: 12px;
z-index: 1;
}
.current-time-scrubber::before {
@ -186,22 +143,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
width: 0;
}
/* Animation List */
.animation-list {
list-style-type: none;
margin: 0;
padding: 0;
position: absolute;
top: var(--devtools-toolbar-height);
width: 100%;
}
/* Animation Item */
.animation-item {
display: flex;
height: 30px;
}
.animation-item:nth-child(2n+1) {
background-color: var(--animation-even-background-color);
}
@ -229,9 +171,9 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
.animation-target {
align-items: center;
display: flex;
height: 100%;
grid-column: 1 / 2;
height: var(--graph-height);
padding-left: 4px;
width: var(--sidebar-width);
}
/* Reps component */
@ -259,10 +201,10 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
/* Summary Graph */
.animation-summary-graph {
cursor: pointer;
height: 100%;
grid-column: 2 / 3;
height: var(--graph-height);
padding-top: 5px;
position: relative;
width: calc(100% - var(--sidebar-width) - var(--graph-right-offset));
}
.animation-summary-graph.compositor::after {
@ -277,7 +219,6 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
top: 5px;
width: 15px;
-moz-context-properties: fill;
z-index: 1;
}
.animation-summary-graph-path {
@ -382,7 +323,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
height: 100%;
overflow: hidden;
width: 100%;
z-index: 1;
z-index: 2;
}
.animation-detail-header {
@ -527,7 +468,7 @@ select.playback-rate-selector.devtools-button:not(:empty):not(:disabled):not(.ch
/* Animated Property Item */
.animated-property-item {
display: flex;
height: 30px;
height: var(--graph-height);
}
.animated-property-item:nth-child(2n+1) {