Bug 877351 - Network Panel is broken on RTL UI, r=rcampbell, a=lsblakk
authorVictor Porof <vporof@mozilla.com>
Sun, 02 Jun 2013 19:39:02 +0300
changeset 142857 b137eb36e1e751472ea0280e9bd5d2569b142a0f
parent 142856 9eeb7511a90660171a7c705dbd109b8f829cc3d4
child 142858 58bef88a459c30fe6972be32ff88d201607d6a99
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrcampbell, lsblakk
bugs877351
milestone23.0a2
Bug 877351 - Network Panel is broken on RTL UI, r=rcampbell, a=lsblakk
browser/devtools/netmonitor/netmonitor-controller.js
browser/devtools/netmonitor/netmonitor-view.js
browser/devtools/netmonitor/netmonitor.css
browser/themes/linux/devtools/netmonitor.css
browser/themes/osx/devtools/netmonitor.css
browser/themes/windows/devtools/netmonitor.css
--- a/browser/devtools/netmonitor/netmonitor-controller.js
+++ b/browser/devtools/netmonitor/netmonitor-controller.js
@@ -515,16 +515,24 @@ let L10N = new ViewHelpers.L10N(NET_STRI
  * Shortcuts for accessing various network monitor preferences.
  */
 let Prefs = new ViewHelpers.Prefs("devtools.netmonitor", {
   networkDetailsWidth: ["Int", "panes-network-details-width"],
   networkDetailsHeight: ["Int", "panes-network-details-height"]
 });
 
 /**
+ * Returns true if this is document is in RTL mode.
+ * @return boolean
+ */
+XPCOMUtils.defineLazyGetter(window, "isRTL", function() {
+  return window.getComputedStyle(document.documentElement, null).direction == "rtl";
+});
+
+/**
  * Convenient way of emitting events from the panel window.
  */
 EventEmitter.decorate(this);
 
 /**
  * Preliminary setup for the NetMonitorController object.
  */
 NetMonitorController.TargetEventsHandler = new TargetEventsHandler();
--- a/browser/devtools/netmonitor/netmonitor-view.js
+++ b/browser/devtools/netmonitor/netmonitor-view.js
@@ -746,32 +746,33 @@ create({ constructor: RequestsMenuView, 
 
     // Apply CSS transforms to each waterfall in this container totalTime
     // accurately translate and resize as needed.
     for (let [, { target, attachment }] of this._cache) {
       let timingsNode = $(".requests-menu-timings", target);
       let startCapNode = $(".requests-menu-timings-cap.start", target);
       let endCapNode = $(".requests-menu-timings-cap.end", target);
       let totalNode = $(".requests-menu-timings-total", target);
+      let direction = window.isRTL ? -1 : 1;
 
       // Render the timing information at a specific horizontal translation
       // based on the delta to the first monitored event network.
-      let translateX = "translateX(" + attachment.startedDeltaMillis + "px)";
+      let translateX = "translateX(" + (direction * attachment.startedDeltaMillis) + "px)";
 
       // Based on the total time passed until the last request, rescale
       // all the waterfalls to a reasonable size.
       let scaleX = "scaleX(" + scale + ")";
 
       // Certain nodes should not be scaled, even if they're children of
       // another scaled node. In this case, apply a reversed transformation.
       let revScaleX = "scaleX(" + (1 / scale) + ")";
 
       timingsNode.style.transform = scaleX + " " + translateX;
-      startCapNode.style.transform = revScaleX + " translateX(0.5px)";
-      endCapNode.style.transform = revScaleX + " translateX(-0.5px)";
+      startCapNode.style.transform = revScaleX + " translateX(" + (direction * 0.5) + "px)";
+      endCapNode.style.transform = revScaleX + " translateX(" + (direction * -0.5) + "px)";
       totalNode.style.transform = revScaleX;
     }
   },
 
   /**
    * Creates the labels displayed on the waterfall header in this container.
    *
    * @param number aScale
@@ -796,20 +797,21 @@ create({ constructor: RequestsMenuView, 
       if (scaledStep < REQUESTS_WATERFALL_HEADER_TICKS_SPACING_MIN) {
         timingStep <<= 1;
         continue;
       }
       optimalTickIntervalFound = true;
 
       // Insert one label for each division on the current scale.
       let fragment = document.createDocumentFragment();
+      let direction = window.isRTL ? -1 : 1;
 
       for (let x = 0; x < availableWidth; x += scaledStep) {
         let divisionMS = (x / aScale).toFixed(0);
-        let translateX = "translateX(" + (x | 0) + "px)";
+        let translateX = "translateX(" + ((direction * x) | 0) + "px)";
 
         let node = document.createElement("label");
         let text = L10N.getFormatStr("networkMenu.divisionMS", divisionMS);
         node.className = "plain requests-menu-timings-division";
         node.style.transform = translateX;
 
         node.setAttribute("value", text);
         fragment.appendChild(node);
@@ -857,17 +859,18 @@ create({ constructor: RequestsMenuView, 
         continue;
       }
       optimalTickIntervalFound = true;
 
       // Insert one pixel for each division on each scale.
       for (let i = 1; i <= REQUESTS_WATERFALL_BACKGROUND_TICKS_SCALES; i++) {
         let increment = scaledStep * Math.pow(2, i);
         for (let x = 0; x < canvasWidth; x += increment) {
-          data32[x | 0] = (alphaComponent << 24) | (255 << 16) | (255 <<  8) | 255;
+          let position = (window.isRTL ? canvasWidth - x : x) | 0;
+          data32[position] = (alphaComponent << 24) | (255 << 16) | (255 << 8) | 255;
         }
         alphaComponent += REQUESTS_WATERFALL_BACKGROUND_TICKS_OPACITY_ADD;
       }
     }
 
     // Flush the image data and cache the waterfall background.
     pixelArray.set(buf8);
     ctx.putImageData(imageData, 0, 0);
@@ -883,16 +886,19 @@ create({ constructor: RequestsMenuView, 
       waterfallNode.style.backgroundImage = this._cachedWaterfallBackground;
     }
   },
 
   /**
    * Hides the overflowing columns in the requests table.
    */
   _hideOverflowingColumns: function NVRM__hideOverflowingColumns() {
+    if (window.isRTL) {
+      return;
+    }
     let table = $("#network-table");
     let toolbar = $("#requests-menu-toolbar");
     let columns = [
       ["#requests-menu-waterfall-header-box", "waterfall-overflows"],
       ["#requests-menu-size-header-box", "size-overflows"],
       ["#requests-menu-type-header-box", "type-overflows"],
       ["#requests-menu-domain-header-box", "domain-overflows"]
     ];
@@ -979,17 +985,21 @@ create({ constructor: RequestsMenuView, 
    * @return number
    */
   get _waterfallWidth() {
     if (this._cachedWaterfallWidth == 0) {
       let container = $("#requests-menu-toolbar");
       let waterfall = $("#requests-menu-waterfall-header-box");
       let containerBounds = container.getBoundingClientRect();
       let waterfallBounds = waterfall.getBoundingClientRect();
-      this._cachedWaterfallWidth = containerBounds.width - waterfallBounds.left;
+      if (!window.isRTL) {
+        this._cachedWaterfallWidth = containerBounds.width - waterfallBounds.left;
+      } else {
+        this._cachedWaterfallWidth = waterfallBounds.right;
+      }
     }
     return this._cachedWaterfallWidth;
   },
 
   _cache: null,
   _canvas: null,
   _ctx: null,
   _cachedWaterfallWidth: 0,
--- a/browser/devtools/netmonitor/netmonitor.css
+++ b/browser/devtools/netmonitor/netmonitor.css
@@ -1,13 +1,17 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* 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/. */
 
+#toolbar-labels {
+  overflow: hidden;
+}
+
 #details-pane-toggle[disabled] {
   visibility: hidden;
 }
 
 #response-content-image-box {
   overflow: auto;
 }
 
--- a/browser/themes/linux/devtools/netmonitor.css
+++ b/browser/themes/linux/devtools/netmonitor.css
@@ -29,22 +29,28 @@
 .requests-menu-header {
   text-align: center;
 }
 
 .requests-menu-subitem {
   padding: 4px;
 }
 
-.requests-menu-header:not(:last-child),
-.requests-menu-subitem:not(:last-child) {
+.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
   -moz-border-end: 1px solid hsla(210,8%,5%,.25);
   box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
 }
 
+.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
+  -moz-border-end: 1px solid hsla(210,8%,5%,.25);
+  box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
+}
+
 .requests-menu-header-button {
   -moz-appearance: none;
   background: none;
   min-width: 12px;
   min-height: 31px; /* Remaining 1px comes from border of the button. */
   margin: 0;
   border: none;
   padding: 2px 0px;
@@ -169,63 +175,101 @@ box.requests-menu-status[code^="5"] {
 }
 
 .requests-menu-timings-division {
   width: 100px;
   padding-top: 2px;
   -moz-padding-start: 4px;
   -moz-border-start: 1px dotted #999;
   font-size: 75%;
-  text-align: left;
   pointer-events: none;
 }
 
 .requests-menu-timings-division:not(:first-child) {
   -moz-margin-start: -100px !important; /* Don't affect layout. */
 }
 
+.requests-menu-timings-division:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-division:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 /* Network requests table: waterfall items */
 
 .requests-menu-subitem.requests-menu-waterfall {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
   background-repeat: repeat-y; /* Background created on a <canvas> in js. */
   margin-top: -1px; /* Compensate borders. */
   margin-bottom: -1px;
 }
 
-.requests-menu-timings {
+.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
+  background-position: right center;
+}
+
+.requests-menu-timings:-moz-locale-dir(ltr) {
   transform-origin: left center;
 }
 
+.requests-menu-timings:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 .requests-menu-timings-total {
   -moz-padding-start: 8px;
   font-size: 85%;
   font-weight: 600;
-  transform-origin: left center;
 }
 
 .requests-menu-timings-cap {
   width: 4px;
   height: 10px;
   border: 1px solid #fff;
 }
 
 .requests-menu-timings-cap.start {
   -moz-border-end: none;
+}
+
+.requests-menu-timings-cap.end {
+  -moz-border-start: none;
+}
+
+.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
   border-radius: 4px 0 0 4px;
   transform-origin: right center;
 }
 
-.requests-menu-timings-cap.end {
-  -moz-border-start: none;
+.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
   border-radius: 0 4px 4px 0;
   transform-origin: left center;
 }
 
+.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
+  border-radius: 0 4px 4px 0;
+  transform-origin: left center;
+}
+
+.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
+  border-radius: 4px 0 0 4px;
+  transform-origin: right center;
+}
+
 .requests-menu-timings-box {
   height: 10px;
   border-top: 1px solid #fff;
   border-bottom: 1px solid #fff;
 }
 
 .requests-menu-timings-box.blocked,
 .requests-menu-timings-cap.blocked {
--- a/browser/themes/osx/devtools/netmonitor.css
+++ b/browser/themes/osx/devtools/netmonitor.css
@@ -29,22 +29,28 @@
 .requests-menu-header {
   text-align: center;
 }
 
 .requests-menu-subitem {
   padding: 4px;
 }
 
-.requests-menu-header:not(:last-child),
-.requests-menu-subitem:not(:last-child) {
+.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
   -moz-border-end: 1px solid hsla(210,8%,5%,.25);
   box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
 }
 
+.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
+  -moz-border-end: 1px solid hsla(210,8%,5%,.25);
+  box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
+}
+
 .requests-menu-header-button {
   -moz-appearance: none;
   background: none;
   min-width: 1em;
   min-height: 31px; /* Remaining 1px comes from border of the button. */
   margin: 0;
   border: none;
   padding: 2px 0px;
@@ -169,63 +175,101 @@ box.requests-menu-status[code^="5"] {
 }
 
 .requests-menu-timings-division {
   width: 100px;
   padding-top: 2px;
   -moz-padding-start: 4px;
   -moz-border-start: 1px dotted #999;
   font-size: 75%;
-  text-align: left;
   pointer-events: none;
 }
 
 .requests-menu-timings-division:not(:first-child) {
   -moz-margin-start: -100px !important; /* Don't affect layout. */
 }
 
+.requests-menu-timings-division:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-division:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 /* Network requests table: waterfall items */
 
 .requests-menu-subitem.requests-menu-waterfall {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
   background-repeat: repeat-y; /* Background created on a <canvas> in js. */
   margin-top: -1px; /* Compensate borders. */
   margin-bottom: -1px;
 }
 
-.requests-menu-timings {
+.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
+  background-position: right center;
+}
+
+.requests-menu-timings:-moz-locale-dir(ltr) {
   transform-origin: left center;
 }
 
+.requests-menu-timings:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 .requests-menu-timings-total {
   -moz-padding-start: 8px;
   font-size: 85%;
   font-weight: 600;
-  transform-origin: left center;
 }
 
 .requests-menu-timings-cap {
   width: 4px;
   height: 10px;
   border: 1px solid #fff;
 }
 
 .requests-menu-timings-cap.start {
   -moz-border-end: none;
+}
+
+.requests-menu-timings-cap.end {
+  -moz-border-start: none;
+}
+
+.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
   border-radius: 4px 0 0 4px;
   transform-origin: right center;
 }
 
-.requests-menu-timings-cap.end {
-  -moz-border-start: none;
+.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
   border-radius: 0 4px 4px 0;
   transform-origin: left center;
 }
 
+.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
+  border-radius: 0 4px 4px 0;
+  transform-origin: left center;
+}
+
+.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
+  border-radius: 4px 0 0 4px;
+  transform-origin: right center;
+}
+
 .requests-menu-timings-box {
   height: 10px;
   border-top: 1px solid #fff;
   border-bottom: 1px solid #fff;
 }
 
 .requests-menu-timings-box.blocked,
 .requests-menu-timings-cap.blocked {
--- a/browser/themes/windows/devtools/netmonitor.css
+++ b/browser/themes/windows/devtools/netmonitor.css
@@ -29,22 +29,28 @@
 .requests-menu-header {
   text-align: center;
 }
 
 .requests-menu-subitem {
   padding: 4px;
 }
 
-.requests-menu-header:not(:last-child),
-.requests-menu-subitem:not(:last-child) {
+.requests-menu-header:not(:last-child):-moz-locale-dir(ltr),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(ltr) {
   -moz-border-end: 1px solid hsla(210,8%,5%,.25);
   box-shadow: 1px 0 0 hsla(210,16%,76%,.1);
 }
 
+.requests-menu-header:not(:last-child):-moz-locale-dir(rtl),
+.requests-menu-subitem:not(:last-child):-moz-locale-dir(rtl) {
+  -moz-border-end: 1px solid hsla(210,8%,5%,.25);
+  box-shadow: -1px 0 0 hsla(210,16%,76%,.1);
+}
+
 .requests-menu-header-button {
   -moz-appearance: none;
   background: none;
   min-width: 10px;
   min-height: 32px; /* Remaining 1px comes from border of the button. */
   margin: 0;
   border: none;
   padding: 2px 0px;
@@ -169,63 +175,101 @@ box.requests-menu-status[code^="5"] {
 }
 
 .requests-menu-timings-division {
   width: 100px;
   padding-top: 1px;
   -moz-padding-start: 4px;
   -moz-border-start: 1px dotted #999;
   font-size: 90%;
-  text-align: left;
   pointer-events: none;
 }
 
 .requests-menu-timings-division:not(:first-child) {
   -moz-margin-start: -100px !important; /* Don't affect layout. */
 }
 
+.requests-menu-timings-division:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-division:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 /* Network requests table: waterfall items */
 
 .requests-menu-subitem.requests-menu-waterfall {
   -moz-padding-start: 4px;
   -moz-padding-end: 4px;
   background-repeat: repeat-y; /* Background created on a <canvas> in js. */
   margin-top: -1px; /* Compensate borders. */
   margin-bottom: -1px;
 }
 
-.requests-menu-timings {
+.requests-menu-subitem.requests-menu-waterfall:-moz-locale-dir(rtl) {
+  background-position: right center;
+}
+
+.requests-menu-timings:-moz-locale-dir(ltr) {
   transform-origin: left center;
 }
 
+.requests-menu-timings:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(ltr) {
+  transform-origin: left center;
+}
+
+.requests-menu-timings-total:-moz-locale-dir(rtl) {
+  transform-origin: right center;
+}
+
 .requests-menu-timings-total {
   -moz-padding-start: 8px;
   font-size: 85%;
   font-weight: 600;
-  transform-origin: left center;
 }
 
 .requests-menu-timings-cap {
   width: 4px;
   height: 10px;
   border: 1px solid #fff;
 }
 
 .requests-menu-timings-cap.start {
   -moz-border-end: none;
+}
+
+.requests-menu-timings-cap.end {
+  -moz-border-start: none;
+}
+
+.requests-menu-timings-cap.start:-moz-locale-dir(ltr) {
   border-radius: 4px 0 0 4px;
   transform-origin: right center;
 }
 
-.requests-menu-timings-cap.end {
-  -moz-border-start: none;
+.requests-menu-timings-cap.start:-moz-locale-dir(rtl) {
   border-radius: 0 4px 4px 0;
   transform-origin: left center;
 }
 
+.requests-menu-timings-cap.end:-moz-locale-dir(ltr) {
+  border-radius: 0 4px 4px 0;
+  transform-origin: left center;
+}
+
+.requests-menu-timings-cap.end:-moz-locale-dir(rtl) {
+  border-radius: 4px 0 0 4px;
+  transform-origin: right center;
+}
+
 .requests-menu-timings-box {
   height: 10px;
   border-top: 1px solid #fff;
   border-bottom: 1px solid #fff;
 }
 
 .requests-menu-timings-box.blocked,
 .requests-menu-timings-cap.blocked {