Bug 1284461 - HTMLTooltip: use variable height only if height==Infinity;r=bgrins draft
authorJulian Descottes <jdescottes@mozilla.com>
Tue, 05 Jul 2016 14:35:15 +0200
changeset 386173 2a120b3551123275504cda8863a377fc30a403ad
parent 386172 561aa3265fa3595cbac2a1c52ee429a82e8bf3e0
child 525050 ef7e9ae561004f015ea0963bbd269e00efce844d
push id22639
push userjdescottes@mozilla.com
push dateMon, 11 Jul 2016 09:37:59 +0000
reviewersbgrins
bugs1284461
milestone50.0a1
Bug 1284461 - HTMLTooltip: use variable height only if height==Infinity;r=bgrins MozReview-Commit-ID: LTraHLeEEp4
devtools/client/shared/test/browser_html_tooltip_variable-height.js
devtools/client/shared/widgets/HTMLTooltip.js
devtools/client/themes/tooltips.css
--- a/devtools/client/shared/test/browser_html_tooltip_variable-height.js
+++ b/devtools/client/shared/test/browser_html_tooltip_variable-height.js
@@ -17,47 +17,35 @@ const TEST_URI = `data:text/xml;charset=
     <vbox flex="1">
       <hbox id="box1" flex="1">test1</hbox>
       <hbox id="box2" flex="1">test2</hbox>
       <hbox id="box3" flex="1">test3</hbox>
       <hbox id="box4" flex="1">test4</hbox>
     </vbox>
   </window>`;
 
-const CONTAINER_HEIGHT = 200;
+const CONTAINER_HEIGHT = 300;
 const CONTAINER_WIDTH = 200;
 const TOOLTIP_HEIGHT = 50;
 
 const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
 loadHelperScript("helper_html_tooltip.js");
 
-let useXulWrapper;
-
 add_task(function* () {
   // Force the toolbox to be 400px tall => 50px for each box.
   yield pushPref("devtools.toolbox.footer.height", 400);
 
   yield addTab("about:blank");
   let [,, doc] = yield createHost("bottom", TEST_URI);
 
-  info("Run tests for a Tooltip without using a XUL panel");
-  useXulWrapper = false;
-  yield runTests(doc);
-
-  info("Run tests for a Tooltip with a XUL panel");
-  useXulWrapper = true;
-  yield runTests(doc);
-});
-
-function* runTests(doc) {
-  let tooltip = new HTMLTooltip({doc}, {useXulWrapper});
+  let tooltip = new HTMLTooltip({doc}, {useXulWrapper: false});
   info("Set tooltip content 50px tall, but request a container 200px tall");
   let tooltipContent = doc.createElementNS(HTML_NS, "div");
   tooltipContent.style.cssText = "height: " + TOOLTIP_HEIGHT + "px; background: red;";
-  tooltip.setContent(tooltipContent, {width: CONTAINER_WIDTH, height: CONTAINER_HEIGHT});
+  tooltip.setContent(tooltipContent, {width: CONTAINER_WIDTH, height: Infinity});
 
   info("Show the tooltip and check the container and panel height.");
   yield showTooltip(tooltip, doc.getElementById("box1"));
 
   let containerRect = tooltip.container.getBoundingClientRect();
   let panelRect = tooltip.panel.getBoundingClientRect();
   is(containerRect.height, CONTAINER_HEIGHT,
     "Tooltip container has the expected height.");
@@ -73,16 +61,15 @@ function* runTests(doc) {
   tooltipContent.style.height = (2 * CONTAINER_HEIGHT) + "px";
 
   info("Click at the same coordinates as earlier, this time it should hit the tooltip.");
   let onPanelClick = once(tooltip.panel, "click");
   EventUtils.synthesizeMouse(tooltip.container, 100, 100, {}, doc.defaultView);
   yield onPanelClick;
   is(tooltip.isVisible(), true, "Tooltip is still visible");
 
-  info("Click below the tooltip container, the tooltip should be closed.");
+  info("Click above the tooltip container, the tooltip should be closed.");
   onHidden = once(tooltip, "hidden");
-  EventUtils.synthesizeMouse(tooltip.container, 100, CONTAINER_HEIGHT + 10,
-    {}, doc.defaultView);
+  EventUtils.synthesizeMouse(tooltip.container, 100, -10, {}, doc.defaultView);
   yield onHidden;
 
   tooltip.destroy();
-}
+});
--- a/devtools/client/shared/widgets/HTMLTooltip.js
+++ b/devtools/client/shared/widgets/HTMLTooltip.js
@@ -280,19 +280,18 @@ HTMLTooltip.prototype = {
    * specified here.
    *
    * @param {Element} content
    *        The tooltip content, should be a HTML element.
    * @param {Object}
    *        - {Number} width: preferred width for the tooltip container. If not specified
    *          the tooltip container will be measured before being displayed, and the
    *          measured width will be used as preferred width.
-   *        - {Number} height: optional, preferred height for the tooltip container. This
-   *          parameter acts as a max-height for the tooltip content. If not specified,
-   *          the tooltip will be able to use all the height available.
+   *        - {Number} height: optional, preferred height for the tooltip container. If
+   *          not specified, the tooltip will be able to use all the height available.
    */
   setContent: function (content, {width = "auto", height = Infinity} = {}) {
     this.preferredWidth = width;
     this.preferredHeight = height;
 
     this.panel.innerHTML = "";
     this.panel.appendChild(content);
   },
@@ -327,16 +326,22 @@ HTMLTooltip.prototype = {
     let {top, height, computedPosition} =
       calculateVerticalPosition(anchorRect, viewportRect, preferredHeight, position, y);
 
     this._position = computedPosition;
     // Apply height before measuring the content width (if width="auto").
     let isTop = computedPosition === POSITION.TOP;
     this.container.classList.toggle("tooltip-top", isTop);
     this.container.classList.toggle("tooltip-bottom", !isTop);
+
+    // If the preferred height is set to Infinity, the tooltip container should grow based
+    // on its content's height and use as much height as possible.
+    this.container.classList.toggle("tooltip-flexible-height",
+      this.preferredHeight === Infinity);
+
     this.container.style.height = height + "px";
 
     let preferredWidth;
     if (this.preferredWidth === "auto") {
       preferredWidth = this._measureContainerWidth();
     } else {
       let themeWidth = 2 * EXTRA_BORDER[this.type];
       preferredWidth = this.preferredWidth + themeWidth;
--- a/devtools/client/themes/tooltips.css
+++ b/devtools/client/themes/tooltips.css
@@ -126,37 +126,49 @@
 
 .tooltip-bottom {
   flex-direction: column-reverse;
 }
 
 .tooltip-panel{
   background-color: var(--theme-tooltip-background);
   pointer-events: all;
+  flex-grow: 1;
 }
 
 .tooltip-visible {
   display: flex;
 }
 
 .tooltip-hidden {
   display: flex;
   visibility: hidden;
 }
 
+/* Tooltip : flexible height styles */
+
+.tooltip-flexible-height .tooltip-panel {
+  /* In flexible mode the tooltip panel should only grow according to its content. */
+  flex-grow: 0;
+}
+
+.tooltip-flexible-height .tooltip-filler {
+  /* In flexible mode the filler should grow as much as possible. */
+  flex-grow: 1;
+}
+
 /* Tooltip : arrow style */
 
 .tooltip-xul-wrapper .tooltip-container {
   /* When displayed in a XUL panel the drop shadow would be abruptly cut by the panel */
   filter: none;
 }
 
 .tooltip-container[type="arrow"] > .tooltip-panel {
   position: relative;
-  flex-grow: 0;
   min-height: 10px;
   box-sizing: border-box;
   width: 100%;
 
   border: 3px solid var(--theme-tooltip-border);
   border-radius: 5px;
 }
 
@@ -175,20 +187,16 @@
   overflow: hidden;
   flex-shrink: 0;
 }
 
 .tooltip-arrow:-moz-locale-dir(rtl) {
   align-self: flex-end;
 }
 
-.tooltip-filler {
-  flex: 1;
-}
-
 .tooltip-top .tooltip-arrow {
   margin-top: -3px;
 }
 
 .tooltip-bottom .tooltip-arrow {
   margin-bottom: -3px;
 }