Bug 952294 - Let devtools tooltip size be automatically set. r=miker
authorPatrick Brosset <pbrosset@mozilla.com>
Wed, 08 Jan 2014 09:49:12 -0500
changeset 162552 3639d34ce298f116caad59d4c4f34458aced5e23
parent 162551 63d31c0367e9268ef94b185d7eba5e99c46b6d1a
child 162553 ad1a0f74524663aced4da974330a22bee383bfad
push idunknown
push userunknown
push dateunknown
reviewersmiker
bugs952294
milestone29.0a1
Bug 952294 - Let devtools tooltip size be automatically set. r=miker
browser/devtools/inspector/test/browser.ini
browser/devtools/inspector/test/browser_inspector_bug_952294_tooltips_dimensions.js
browser/devtools/shared/widgets/Tooltip.js
--- a/browser/devtools/inspector/test/browser.ini
+++ b/browser/devtools/inspector/test/browser.ini
@@ -41,8 +41,9 @@ support-files =
 [browser_inspector_pseudoClass_menu.js]
 [browser_inspector_pseudoclass_lock.js]
 [browser_inspector_reload.js]
 [browser_inspector_scrolling.js]
 [browser_inspector_select_last_selected.js]
 [browser_inspector_sidebarstate.js]
 [browser_inspector_bug_848731_reset_selection_on_delete.js]
 [browser_inspector_bug_922125_destroy_on_navigate.js]
+[browser_inspector_bug_952294_tooltips_dimensions.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/inspector/test/browser_inspector_bug_952294_tooltips_dimensions.js
@@ -0,0 +1,175 @@
+/* vim: set ts=2 et sw=2 tw=80: */
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let contentDoc;
+let inspector;
+let ruleView;
+let markupView;
+
+const PAGE_CONTENT = [
+  '<style type="text/css">',
+  '  div {',
+  '    width: 300px;height: 300px;border-radius: 50%;',
+  '    transform: skew(45deg);',
+  '    background: red url(chrome://global/skin/icons/warning-64.png);',
+  '  }',
+  '</style>',
+  '<div></div>'
+].join("\n");
+
+function test() {
+  waitForExplicitFinish();
+
+  gBrowser.selectedTab = gBrowser.addTab();
+  gBrowser.selectedBrowser.addEventListener("load", function onload(evt) {
+    gBrowser.selectedBrowser.removeEventListener("load", onload, true);
+    contentDoc = content.document;
+    waitForFocus(createDocument, content);
+  }, true);
+
+  content.location = "data:text/html,tooltip dimension test";
+}
+
+function createDocument() {
+  contentDoc.body.innerHTML = PAGE_CONTENT;
+
+  openInspector(aInspector => {
+    inspector = aInspector;
+    markupView = inspector.markup;
+
+    inspector.sidebar.once("ruleview-ready", function() {
+      ruleView = inspector.sidebar.getWindowForTab("ruleview").ruleview.view;
+      inspector.sidebar.select("ruleview");
+      startTests();
+    });
+  });
+}
+
+function endTests() {
+  contentDoc = inspector = ruleView = markupView = null;
+  gBrowser.removeCurrentTab();
+  finish();
+}
+
+function startTests() {
+  Task.spawn(function() {
+    yield selectDiv();
+    yield testTransformDimension();
+    yield testImageDimension();
+    yield testPickerDimension();
+    endTests();
+  }).then(null, Cu.reportError);
+}
+
+function selectDiv() {
+  let deferred = promise.defer();
+
+  inspector.selection.setNode(contentDoc.querySelector("div"));
+  inspector.once("inspector-updated", () => {
+    deferred.resolve();
+  });
+
+  return deferred.promise;
+}
+
+function testTransformDimension() {
+  let deferred = promise.defer();
+  info("Testing css transform tooltip dimensions");
+
+  let {valueSpan} = getRuleViewProperty("transform");
+  showTooltipOn(ruleView.previewTooltip, valueSpan, () => {
+    let panel = ruleView.previewTooltip.panel;
+
+    // Let's not test for a specific size, but instead let's make sure it's at
+    // least as big as the preview canvas
+    let canvas = panel.querySelector("canvas");
+    let w = canvas.width;
+    let h = canvas.height;
+    let panelRect = panel.getBoundingClientRect();
+
+    ok(panelRect.width >= w, "The panel is wide enough to show the canvas");
+    ok(panelRect.height >= h, "The panel is high enough to show the canvas");
+
+    ruleView.previewTooltip.hide();
+    deferred.resolve();
+  });
+
+  return deferred.promise;
+}
+
+function testImageDimension() {
+  let deferred = promise.defer();
+  info("Testing background-image tooltip dimensions");
+
+  let {valueSpan} = getRuleViewProperty("background");
+  let uriSpan = valueSpan.querySelector(".theme-link");
+
+  showTooltipOn(ruleView.previewTooltip, uriSpan, () => {
+    let panel = ruleView.previewTooltip.panel;
+
+    // Let's not test for a specific size, but instead let's make sure it's at
+    // least as big as the image
+    let imageRect = panel.querySelector("image").getBoundingClientRect();
+    let panelRect = panel.getBoundingClientRect();
+
+    ok(panelRect.width >= imageRect.width,
+      "The panel is wide enough to show the image");
+    ok(panelRect.height >= imageRect.height,
+      "The panel is high enough to show the image");
+
+    ruleView.previewTooltip.hide();
+    deferred.resolve();
+  });
+
+  return deferred.promise;
+}
+
+function testPickerDimension() {
+  let deferred = promise.defer();
+  info("Testing color-picker tooltip dimensions");
+
+  let {valueSpan} = getRuleViewProperty("background");
+  let swatch = valueSpan.querySelector(".ruleview-colorswatch");
+  let cPicker = ruleView.colorPicker;
+
+  cPicker.tooltip.once("shown", () => {
+    // The colorpicker spectrum's iframe has a fixed width height, so let's
+    // make sure the tooltip is at least as big as that
+    let w = cPicker.tooltip.panel.querySelector("iframe").width;
+    let h = cPicker.tooltip.panel.querySelector("iframe").height;
+    let panelRect = cPicker.tooltip.panel.getBoundingClientRect();
+
+    ok(panelRect.width >= w, "The panel is wide enough to show the picker");
+    ok(panelRect.height >= h, "The panel is high enough to show the picker");
+
+    cPicker.hide();
+    deferred.resolve();
+  });
+  swatch.click();
+
+  return deferred.promise;
+}
+
+function showTooltipOn(tooltip, element, cb) {
+  // If there is indeed a show-on-hover on element, the xul panel will be shown
+  tooltip.panel.addEventListener("popupshown", function shown() {
+    tooltip.panel.removeEventListener("popupshown", shown, true);
+    cb();
+  }, true);
+  tooltip._showOnHover(element);
+}
+
+function getRuleViewProperty(name) {
+  let prop = null;
+  [].forEach.call(ruleView.doc.querySelectorAll(".ruleview-property"), property => {
+    let nameSpan = property.querySelector(".ruleview-propertyname");
+    let valueSpan = property.querySelector(".ruleview-propertyvalue");
+
+    if (nameSpan.textContent === name) {
+      prop = {nameSpan: nameSpan, valueSpan: valueSpan};
+    }
+  });
+  return prop;
+}
--- a/browser/devtools/shared/widgets/Tooltip.js
+++ b/browser/devtools/shared/widgets/Tooltip.js
@@ -520,27 +520,25 @@ Tooltip.prototype = {
 
     // Dimension label
     let label = this.doc.createElement("label");
     label.classList.add("devtools-tooltip-caption");
     label.classList.add("theme-comment");
     if (options.naturalWidth && options.naturalHeight) {
       label.textContent = this._getImageDimensionLabel(options.naturalWidth,
         options.naturalHeight);
-      this.setSize(vbox.width, vbox.height);
     } else {
       // If no dimensions were provided, load the image to get them
       label.textContent = l10n.strings.GetStringFromName("previewTooltip.image.brokenImage");
       let imgObj = new this.doc.defaultView.Image();
       imgObj.src = imageUrl;
       imgObj.onload = () => {
         imgObj.onload = null;
         label.textContent = this._getImageDimensionLabel(imgObj.naturalWidth,
           imgObj.naturalHeight);
-        this.setSize(vbox.width, vbox.height);
       }
     }
     vbox.appendChild(label);
 
     this.content = vbox;
   },
 
   _getImageDimensionLabel: (w, h) => w + " x " + h,
@@ -629,21 +627,18 @@ Tooltip.prototype = {
         let origin = styles["transform-origin"].value;
         let width = parseInt(styles["width"].value);
         let height = parseInt(styles["height"].value);
 
         let root = this.doc.createElementNS(XHTML_NS, "div");
         let previewer = new CSSTransformPreviewer(root);
         this.content = root;
         if (!previewer.preview(transform, origin, width, height)) {
-          // If the preview didn't work, reject the promise
           def.reject();
         } else {
-          // Else, make sure the tooltip has the right size and resolve
-          this.setSize(previewer.canvas.width, previewer.canvas.height);
           def.resolve();
         }
       });
     } else {
       def.reject();
     }
 
     return def.promise;