Bug 1174060 - 2 - Display negative delays like normal delays; r=bgrins
authorPatrick Brosset <pbrosset@mozilla.com>
Fri, 04 Sep 2015 17:43:41 +0200
changeset 261284 688b108cdfe0cdf4efb333ee2ea0241a2a29bc32
parent 261283 10a7429d7ed573890a4618e173fbdfb06372dc76
child 261285 ba641c7faa1279afc43ec3bb62d1f68ccc6db7a6
push id64705
push usercbook@mozilla.com
push dateTue, 08 Sep 2015 14:02:43 +0000
treeherdermozilla-inbound@7fa38a962661 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1174060
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1174060 - 2 - Display negative delays like normal delays; r=bgrins This ensure animations with negative delays are fully displayed in the animation-inspector panel, and that negative and positive delays look the same.
browser/devtools/animationinspector/components.js
browser/devtools/animationinspector/test/browser_animation_timeline_takes_rate_into_account.js
browser/themes/shared/devtools/animationinspector.css
--- a/browser/devtools/animationinspector/components.js
+++ b/browser/devtools/animationinspector/components.js
@@ -562,17 +562,22 @@ let TimeScale = {
 
   /**
    * Add a new animation to time scale.
    * @param {Object} state A PlayerFront.state object.
    */
   addAnimation: function(state) {
     let {startTime, delay, duration, iterationCount, playbackRate} = state;
 
-    this.minStartTime = Math.min(this.minStartTime, startTime);
+    // Negative-delayed animations have their startTimes set such that we would
+    // be displaying the delay outside the time window if we didn't take it into
+    // account here.
+    let relevantDelay = delay < 0 ? delay / playbackRate : 0;
+
+    this.minStartTime = Math.min(this.minStartTime, startTime + relevantDelay);
     let length = (delay / playbackRate) +
                  ((duration / playbackRate) *
                   (!iterationCount ? 1 : iterationCount));
     this.maxEndTime = Math.max(this.maxEndTime, startTime + length);
   },
 
   /**
    * Reset the current time scale.
@@ -948,31 +953,39 @@ AnimationsTimeline.prototype = {
         // repeating linear-gradient.
         "style": `left:${x}px;
                   width:${w * (count || 1)}px;
                   background-size:${Math.max(w, 2)}px 100%;`
       }
     });
 
     // The animation name is displayed over the iterations.
+    // Note that in case of negative delay, we push the name towards the right
+    // so the delay can be shown.
     createNode({
       parent: iterations,
       attributes: {
         "class": "name",
-        "title": this.getAnimationTooltipText(state)
+        "title": this.getAnimationTooltipText(state),
+        "style": delay < 0
+                 ? "margin-left:" +
+                   TimeScale.durationToDistance(Math.abs(delay), width) + "px"
+                 : ""
       },
       textContent: state.name
     });
 
     // Delay.
     if (delay) {
-      let w = TimeScale.durationToDistance(delay / rate, width);
+      // Negative delays need to start at 0.
+      let x = TimeScale.durationToDistance((delay < 0 ? 0 : delay) / rate, width);
+      let w = TimeScale.durationToDistance(Math.abs(delay) / rate, width);
       createNode({
         parent: iterations,
         attributes: {
           "class": "delay",
-          "style": `left:-${w}px;
+          "style": `left:-${x}px;
                     width:${w}px;`
         }
       });
     }
   }
 };
--- a/browser/devtools/animationinspector/test/browser_animation_timeline_takes_rate_into_account.js
+++ b/browser/devtools/animationinspector/test/browser_animation_timeline_takes_rate_into_account.js
@@ -17,23 +17,28 @@ add_task(function*() {
   let {panel} = yield openAnimationInspectorNewUI();
   yield waitForAllAnimationTargets(panel);
 
   let timelineEl = panel.animationsTimelineComponent.rootWrapperEl;
 
   let timeBlocks = timelineEl.querySelectorAll(".time-block");
   is(timeBlocks.length, 2, "2 animations are displayed");
 
-  info("The first animation has its rate to 1, let's measure it");
+  info("The first animation has its rate set to 1, let's measure it");
 
   let el = timeBlocks[0];
-  let duration = el.querySelector(".iterations").getBoundingClientRect().width;
-  let delay = el.querySelector(".delay").getBoundingClientRect().width;
+  let duration = parseInt(el.querySelector(".iterations").style.width, 10);
+  let delay = parseInt(el.querySelector(".delay").style.width, 10);
 
   info("The second animation has its rate set to 2, so should be shorter");
 
   let el2 = timeBlocks[1];
-  let duration2 = el2.querySelector(".iterations").getBoundingClientRect().width;
-  let delay2 = el2.querySelector(".delay").getBoundingClientRect().width;
+  let duration2 = parseInt(el2.querySelector(".iterations").style.width, 10);
+  let delay2 = parseInt(el2.querySelector(".delay").style.width, 10);
 
-  is(duration, 2 * duration2, "The duration width is correct");
-  is(delay, 2 * delay2, "The delay width is correct");
+  // The width are calculated by the animation-inspector dynamically depending
+  // on the size of the panel, and therefore depends on the test machine/OS.
+  // Let's not try to be too precise here and compare numbers.
+  let durationDelta = (2 * duration2) - duration;
+  ok(durationDelta <= 1, "The duration width is correct");
+  let delayDelta = (2 * delay2) - delay;
+  ok(delayDelta <= 1, "The delay width is correct");
 });
--- a/browser/themes/shared/devtools/animationinspector.css
+++ b/browser/themes/shared/devtools/animationinspector.css
@@ -282,35 +282,26 @@ body {
   white-space: nowrap;
   line-height: 150%;
   padding: 0 2px;
 }
 
 .animation-timeline .animation .delay {
   position: absolute;
   top: 0;
+  /* Make sure the delay covers up the animation border */
+  transform: translate(-1px, -1px);
   height: 100%;
-  background-image: linear-gradient(to bottom,
-                                    transparent,
-                                    transparent 9px,
-                                    var(--timelime-border-color) 9px,
-                                    var(--timelime-border-color) 11px,
-                                    transparent 11px,
-                                    transparent);
-}
-
-.animation-timeline .animation .delay::before {
-  position: absolute;
-  content: "";
-  left: 0;
-  width: 2px;
-  height: 8px;
-  top: 50%;
-  margin-top: -4px;
-  background: var(--timelime-border-color);
+  background-image: repeating-linear-gradient(45deg,
+                                              transparent,
+                                              transparent 1px,
+                                              var(--theme-selection-color) 1px,
+                                              var(--theme-selection-color) 4px);
+  background-color: var(--timelime-border-color);
+  border: 1px solid var(--timelime-border-color);
 }
 
 /* Animation target node gutter, contains a preview of the dom node */
 
 .animation-target {
   background-color: var(--theme-toolbar-background);
   padding: 1px 4px;
   box-sizing: border-box;