Bug 1468475 - Part 2. Display the zero graduation. r?daisuke
This patch will ensure that displaying the zero graduation into the timeline by
using shift the graduation with zeroBaseTime. If we shifted all of the
graduations, the graph might not have the first graduation. So this patch will
add the first graduation intentionally in this case.
Furthermore, this patch will not display negative divisions excepting the first
graduation.
MozReview-Commit-ID: 3zkPH8RuCoj
--- a/devtools/client/inspector/animation/components/AnimationListContainer.js
+++ b/devtools/client/inspector/animation/components/AnimationListContainer.js
@@ -64,25 +64,40 @@ class AnimationListContainer extends Pur
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 = parseInt(width / intervalWidth, 10);
const isAllDurationInfinity =
- animations.every(animation => animation.state.duration === Infinity);
+ animations.every(animation => animation.state.duration === Infinity);
+ const zeroBasePosition =
+ width * (timeScale.zeroPositionTime / animationDuration);
+ const shiftWidth = zeroBasePosition % intervalWidth;
const ticks = [];
+ // Need to press first graduation since position will be shifted.
+ if (zeroBasePosition !== 0) {
+ const position = 0;
+ const label = timeScale.formatTime(timeScale.distanceToRelativeTime(0));
+ ticks.push({ position, label });
+ }
+
for (let i = 0; i <= tickCount; i++) {
- const position = i * intervalWidth * 100 / width;
- const label = isAllDurationInfinity && i === tickCount
- ? getStr("player.infiniteTimeLabel")
- : timeScale.formatTime(timeScale.distanceToRelativeTime(position));
+ const position = ((i * intervalWidth) + shiftWidth) * 100 / width;
+ let distance = timeScale.distanceToRelativeTime(position);
+ let label = "";
+ // Press the graduation only if positive time.
+ if (distance >= 0) {
+ label = isAllDurationInfinity && i === tickCount
+ ? getStr("player.infiniteTimeLabel")
+ : timeScale.formatTime(distance);
+ }
ticks.push({ position, label });
}
this.setState({ ticks });
}
render() {
const {
--- a/devtools/client/inspector/animation/components/AnimationToolbar.js
+++ b/devtools/client/inspector/animation/components/AnimationToolbar.js
@@ -17,27 +17,29 @@ class AnimationToolbar extends PureCompo
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
animations: PropTypes.arrayOf(PropTypes.object).isRequired,
removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
rewindAnimationsCurrentTime: PropTypes.func.isRequired,
setAnimationsPlaybackRate: PropTypes.func.isRequired,
setAnimationsPlayState: PropTypes.func.isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
render() {
const {
addAnimationsCurrentTimeListener,
animations,
removeAnimationsCurrentTimeListener,
rewindAnimationsCurrentTime,
setAnimationsPlaybackRate,
setAnimationsPlayState,
+ timeScale,
} = this.props;
return dom.div(
{
className: "animation-toolbar devtools-toolbar",
},
RewindButton(
{
@@ -55,15 +57,16 @@ class AnimationToolbar extends PureCompo
animations,
setAnimationsPlaybackRate,
}
),
CurrentTimeLabel(
{
addAnimationsCurrentTimeListener,
removeAnimationsCurrentTimeListener,
+ timeScale,
}
)
);
}
}
module.exports = AnimationToolbar;
--- a/devtools/client/inspector/animation/components/App.js
+++ b/devtools/client/inspector/animation/components/App.js
@@ -89,16 +89,17 @@ class App extends Component {
AnimationToolbar(
{
addAnimationsCurrentTimeListener,
animations,
removeAnimationsCurrentTimeListener,
rewindAnimationsCurrentTime,
setAnimationsPlaybackRate,
setAnimationsPlayState,
+ timeScale,
}
),
SplitBox({
className: "animation-container-splitter",
endPanel: AnimationDetailContainer(
{
addAnimationsCurrentTimeListener,
emitEventForTest,
--- a/devtools/client/inspector/animation/components/CurrentTimeLabel.js
+++ b/devtools/client/inspector/animation/components/CurrentTimeLabel.js
@@ -8,16 +8,17 @@ const { PureComponent } = require("devto
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
class CurrentTimeLabel extends PureComponent {
static get propTypes() {
return {
addAnimationsCurrentTimeListener: PropTypes.func.isRequired,
removeAnimationsCurrentTimeListener: PropTypes.func.isRequired,
+ timeScale: PropTypes.object.isRequired,
};
}
constructor(props) {
super(props);
const { addAnimationsCurrentTimeListener } = props;
this.onCurrentTimeUpdated = this.onCurrentTimeUpdated.bind(this);
@@ -34,50 +35,52 @@ class CurrentTimeLabel extends PureCompo
removeAnimationsCurrentTimeListener(this.onCurrentTimeUpdated);
}
onCurrentTimeUpdated(currentTime) {
this.setState({ currentTime });
}
render() {
+ const { timeScale } = this.props;
const { currentTime } = this.state;
return dom.label(
{
className: "current-time-label",
},
- formatStopwatchTime(currentTime)
+ formatStopwatchTime(currentTime - timeScale.zeroPositionTime)
);
}
}
/**
* Format a timestamp (in ms) as a mm:ss.mmm string.
*
* @param {Number} time
* @return {String}
*/
function formatStopwatchTime(time) {
// Format falsy values as 0
if (!time) {
return "00:00.000";
}
- let milliseconds = parseInt(time % 1000, 10);
- let seconds = parseInt((time / 1000) % 60, 10);
- let minutes = parseInt((time / (1000 * 60)), 10);
+ const sign = time < 0 ? "-" : "";
+ let milliseconds = parseInt(Math.abs(time % 1000), 10);
+ let seconds = parseInt(Math.abs((time / 1000)) % 60, 10);
+ let minutes = parseInt(Math.abs((time / (1000 * 60))), 10);
const pad = (nb, max) => {
if (nb < max) {
return new Array((max + "").length - (nb + "").length + 1).join("0") + nb;
}
return nb;
};
minutes = pad(minutes, 10);
seconds = pad(seconds, 10);
milliseconds = pad(milliseconds, 100);
- return `${minutes}:${seconds}.${milliseconds}`;
+ return `${sign}${minutes}:${seconds}.${milliseconds}`;
}
module.exports = CurrentTimeLabel;
--- a/devtools/client/inspector/animation/test/browser_animation_animation-timeline-tick.js
+++ b/devtools/client/inspector/animation/test/browser_animation_animation-timeline-tick.js
@@ -49,30 +49,41 @@ function assertTickLabels(timeScale, lis
const timelineTickListEl = listContainerEl.querySelector(".tick-labels");
ok(timelineTickListEl,
"The animation timeline tick list element should be in header");
const width = timelineTickListEl.offsetWidth;
const animationDuration = timeScale.getDuration();
const minTimeInterval = TIME_GRADUATION_MIN_SPACING * animationDuration / width;
const interval = findOptimalTimeInterval(minTimeInterval);
- const expectedTickItem = Math.ceil(animationDuration / interval);
+ const shiftWidth = timeScale.zeroPositionTime % interval;
+ const expectedTickItem = Math.ceil(animationDuration / interval) +
+ (shiftWidth !== 0 ? 1 : 0);
const timelineTickItemEls = timelineTickListEl.querySelectorAll(".tick-label");
is(timelineTickItemEls.length, expectedTickItem,
"The expected number of timeline ticks were found");
info("Make sure graduations are evenly distributed and show the right times");
for (const [index, tickEl] of timelineTickItemEls.entries()) {
const left = parseFloat(tickEl.style.marginInlineStart);
- const expectedPos = index * interval * 100 / animationDuration;
+ let expectedPos = (((index - 1) * interval + shiftWidth) / animationDuration) * 100;
+ if (shiftWidth !== 0 && index === 0) {
+ expectedPos = 0;
+ }
is(Math.round(left), Math.round(expectedPos),
`Graduation ${ index } is positioned correctly`);
// Note that the distancetoRelativeTime and formatTime functions are tested
// separately in xpcshell test test_timeScale.js, so we assume that they
// work here.
- const formattedTime =
+ let formattedTime =
timeScale.formatTime(timeScale.distanceToRelativeTime(expectedPos, width));
+
+ // If label area is narrow due to shift the graph of negative-delay,
+ // label will not be displayed.
+ if (shiftWidth < interval / 2 && index === 0) {
+ formattedTime = "";
+ }
is(tickEl.textContent, formattedTime,
`Graduation ${ index } has the right text content`);
}
}