Bug 1189492 - part1: support horizontal collapsing in ViewHelpers togglePane;r=vporof draft
authorJulian Descottes <jdescottes@mozilla.com>
Fri, 26 Feb 2016 00:31:34 +0100
changeset 335357 d2bbd5ba289e7cbee0380d5f380bfd05a667295d
parent 335356 1e55f160b4ae5237c3bd8053acba9ff434c1b609
child 335358 99787aefc89b6d884624173afc66b371a9575b2f
push id11768
push userjdescottes@mozilla.com
push dateMon, 29 Feb 2016 08:33:17 +0000
reviewersvporof
bugs1189492
milestone47.0a1
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);
   --smw-item-top-border: rgba(128,128,128,0.15);
   --smw-item-bottom-border: transparent;
 }
 
 /* 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 */