Bug 1189492 - part1: support horizontal collapsing in ViewHelpers togglePane;r=vporof
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 26 Feb 2016 00:31:34 +0100
changeset 322365 4245d4c579beb4be51281240b8cef73cdccb0400
parent 322364 57774ff596857a1567ff5e40ce44cbbe2ec8308a
child 322366 e3ca5d7c28a95c3ee27a8109a0522f224e17ace3
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvporof
bugs1189492
milestone47.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 1189492 - part1: support horizontal collapsing in ViewHelpers togglePane;r=vporof MozReview-Commit-ID: 1Hj8vrZhKKq
devtools/client/inspector/inspector-panel.js
devtools/client/shared/widgets/ViewHelpers.jsm
devtools/client/themes/widgets.css
--- a/devtools/client/inspector/inspector-panel.js
+++ b/devtools/client/inspector/inspector-panel.js
@@ -990,20 +990,26 @@ InspectorPanel.prototype = {
    * When the pane toggle button is clicked, toggle the pane, change the button
    * state and tooltip.
    */
   onPaneToggleButtonClicked: function(e) {
     let sidePane = this.panelDoc.querySelector("#inspector-sidebar");
     let button = this._paneToggleButton;
     let isVisible = !button.hasAttribute("pane-collapsed");
 
-    // Make sure the sidebar has a width attribute before collapsing because
-    // ViewHelpers needs it.
-    if (isVisible && !sidePane.hasAttribute("width")) {
-      sidePane.setAttribute("width", sidePane.getBoundingClientRect().width);
+    // Make sure the sidebar has width and height attributes before collapsing
+    // because ViewHelpers needs it.
+    if (isVisible) {
+      let rect = sidePane.getBoundingClientRect();
+      if (!sidePane.hasAttribute("width")) {
+        sidePane.setAttribute("width", rect.width);
+      }
+      // always refresh the height attribute before collapsing, it could have
+      // been modified by resizing the container.
+      sidePane.setAttribute("height", rect.height);
     }
 
     ViewHelpers.togglePane({
       visible: !isVisible,
       animated: true,
       delayed: true
     }, sidePane);
 
--- a/devtools/client/shared/widgets/ViewHelpers.jsm
+++ b/devtools/client/shared/widgets/ViewHelpers.jsm
@@ -220,17 +220,18 @@ this.ViewHelpers = {
       case e.DOM_VK_HOME:
       case e.DOM_VK_END:
         e.preventDefault();
         e.stopPropagation();
     }
   },
 
   /**
-   * Sets a side pane hidden or visible.
+   * Sets a toggled pane hidden or visible. The pane can either be displayed on
+   * the side (right or left depending on the locale) or at the bottom.
    *
    * @param object aFlags
    *        An object containing some of the following properties:
    *        - visible: true if the pane should be shown, false to hide
    *        - animated: true to display an animation on toggle
    *        - delayed: true to wait a few cycles before toggle
    *        - callback: a function to invoke when the toggle finishes
    * @param nsIDOMNode aPane
@@ -241,58 +242,64 @@ this.ViewHelpers = {
     if (!aPane) {
       return;
     }
 
     // Hiding is always handled via margins, not the hidden attribute.
     aPane.removeAttribute("hidden");
 
     // Add a class to the pane to handle min-widths, margins and animations.
-    if (!aPane.classList.contains("generic-toggled-side-pane")) {
-      aPane.classList.add("generic-toggled-side-pane");
-    }
+    aPane.classList.add("generic-toggled-pane");
 
     // Avoid useless toggles.
     if (aFlags.visible == !aPane.hasAttribute("pane-collapsed")) {
       if (aFlags.callback) aFlags.callback();
       return;
     }
 
     // The "animated" attributes enables animated toggles (slide in-out).
     if (aFlags.animated) {
       aPane.setAttribute("animated", "");
     } else {
       aPane.removeAttribute("animated");
     }
 
     // Computes and sets the pane margins in order to hide or show it.
     let doToggle = () => {
+      // Negative margins are applied to "right" and "left" to support RTL and
+      // LTR directions, as well as to "bottom" to support vertical layouts.
+      // Unnecessary negative margins are forced to 0 via CSS in widgets.css.
       if (aFlags.visible) {
         aPane.style.marginLeft = "0";
         aPane.style.marginRight = "0";
+        aPane.style.marginBottom = "0";
         aPane.removeAttribute("pane-collapsed");
       } else {
-        let margin = ~~(aPane.getAttribute("width")) + 1;
-        aPane.style.marginLeft = -margin + "px";
-        aPane.style.marginRight = -margin + "px";
+        let width = Math.floor(aPane.getAttribute("width")) + 1;
+        let height = Math.floor(aPane.getAttribute("height")) + 1;
+        aPane.style.marginLeft = -width + "px";
+        aPane.style.marginRight = -width + "px";
+        aPane.style.marginBottom = -height + "px";
         aPane.setAttribute("pane-collapsed", "");
       }
 
-      // Invoke the callback when the transition ended.
+      // Wait for the animation to end before calling afterToggle()
       if (aFlags.animated) {
         aPane.addEventListener("transitionend", function onEvent() {
           aPane.removeEventListener("transitionend", onEvent, false);
+          // Prevent unwanted transitions: if the panel is hidden and the layout
+          // changes margins will be updated and the panel will pop out.
+          aPane.removeAttribute("animated");
           if (aFlags.callback) aFlags.callback();
         }, false);
-      }
-      // Invoke the callback immediately since there's no transition.
-      else {
+      } else {
+        // Invoke the callback immediately since there's no transition.
         if (aFlags.callback) aFlags.callback();
       }
-    }
+    };
 
     // Sometimes it's useful delaying the toggle a few ticks to ensure
     // a smoother slide in-out animation.
     if (aFlags.delayed) {
       aPane.ownerDocument.defaultView.setTimeout(doToggle, PANE_APPEARANCE_DELAY);
     } else {
       doToggle();
     }
--- a/devtools/client/themes/widgets.css
+++ b/devtools/client/themes/widgets.css
@@ -13,24 +13,24 @@
   --table-splitter-color: rgba(0,0,0,0.15);
   --table-zebra-background: rgba(0,0,0,0.05);
   --sidemenu-selected-arrow: url(images/itemArrow-ltr.svg);
   --sidemenu-selected-arrow-rtl: url(images/itemArrow-rtl.svg);
 }
 
 /* Generic pane helpers */
 
-.generic-toggled-side-pane {
+.generic-toggled-pane {
   -moz-margin-start: 0 !important;
   /* Unfortunately, transitions don't work properly with locale-aware properties,
      so both the left and right margins are set via js, while the start margin
      is always overridden here. */
 }
 
-.generic-toggled-side-pane[animated] {
+.generic-toggled-pane[animated] {
   transition: margin 0.25s ease-in-out;
 }
 
 /* Responsive container */
 
 .devtools-responsive-container {
   -moz-box-orient: horizontal;
 }
@@ -40,16 +40,27 @@
 }
 
 .devtools-main-content,
 .devtools-sidebar-tabs {
   /* Prevent some children that should be hidden from remaining visible as this is shrunk (Bug 971959) */
   position: relative;
 }
 
+@media (min-width: 701px) {
+  .devtools-responsive-container .generic-toggled-pane {
+    /* To hide generic-toggled-pane, negative margins are applied dynamically.
+     * In the default horizontal layout, the pane is on the side and should be
+     * hidden using negative -moz-margin-end only.
+     */
+    margin-top: 0 !important;
+    margin-bottom: 0 !important;
+  }
+}
+
 @media (max-width: 700px) {
   .devtools-responsive-container {
     -moz-box-orient: vertical;
   }
 
   .devtools-responsive-container > .devtools-side-splitter {
     /* This is a normally vertical splitter, but we have turned it horizontal
        due to the smaller resolution */
@@ -68,16 +79,24 @@
     /* In some edge case the cursor is not changed to n-resize */
     cursor: n-resize;
   }
 
   .devtools-responsive-container > .devtools-sidebar-tabs {
     min-height: 35vh;
     max-height: 75vh;
   }
+
+  .devtools-responsive-container .generic-toggled-pane {
+    /* To hide generic-toggled-pane, negative margins are applied dynamically.
+     * If a vertical layout, the pane is on the bottom and should be hidden
+     * using negative bottom margin only.
+     */
+    -moz-margin-end: 0 !important;
+  }
 }
 
 /* BreacrumbsWidget */
 
 .breadcrumbs-widget-container {
   -moz-margin-end: 3px;
   max-height: 24px; /* Set max-height for proper sizing on linux */
   height: 24px; /* Set height to prevent starting small waiting for content */