Bug 1276876 - ruleview: migrate font&image preview tooltips to HTMLTooltips;r=tromey

Migrate the previewTooltip used in the ruleview (& computedview) to use a
HTMLTooltip instance.

Helper methods from Tooltip.js have been removed, migrated to HTML and are
now in style-inspector-overlays.js (not used by any other client). Tests
have been updated to be compatible with HTML Image preview tooltips.

The behavior should be the same as before, so no new test has been added.

MozReview-Commit-ID: HuFatuPi5VM

--HG--
extra : rebase_source : cc0f0af816c9d2a276f595120210e1e5f0197039
extra : amend_source : a6390ffac7dff0325a96be6f884b344db621b439
This commit is contained in:
Julian Descottes 2016-06-01 17:07:09 +02:00
parent 9dbe902fe1
commit 8e32fa1b37
9 changed files with 99 additions and 83 deletions

View File

@ -43,7 +43,8 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
});
let spectrum = yield picker.spectrum;
let onModifications = ruleView.once("ruleview-changed");
let onModifications = waitForNEvents(ruleView, "ruleview-changed", 2);
let onHidden = picker.tooltip.once("hidden");
EventUtils.sendKey("RETURN", spectrum.element.ownerDocument.defaultView);
yield onHidden;
@ -53,8 +54,7 @@ function* testColorChangeIsntRevertedWhenOtherTooltipIsShown(ruleView) {
let value = getRuleViewProperty(ruleView, "body", "background").valueSpan;
let url = value.querySelector(".theme-link");
onShown = ruleView.tooltips.previewTooltip.once("shown");
let anchor = yield isHoverTooltipTarget(ruleView.tooltips.previewTooltip,
url);
let anchor = yield isHoverTooltipTarget(ruleView.tooltips.previewTooltip, url);
ruleView.tooltips.previewTooltip.show(anchor);
yield onShown;

View File

@ -12,8 +12,14 @@
// - in-content highlighters that appear when hovering over property values
// - etc.
const {getTheme} = require("devtools/client/shared/theme");
const {HTMLTooltip} = require("devtools/client/shared/widgets/HTMLTooltip");
const {
getImageDimensions,
setImageTooltip,
setBrokenImageTooltip,
} = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper");
const {
Tooltip,
SwatchColorPickerTooltip,
SwatchCubicBezierTooltip,
CssDocsTooltip,
@ -273,7 +279,9 @@ TooltipsOverlay.prototype = {
let panelDoc = this.view.inspector.panelDoc;
// Image, fonts, ... preview tooltip
this.previewTooltip = new Tooltip(panelDoc);
this.previewTooltip = new HTMLTooltip(this.view.inspector.toolbox, {
type: "arrow"
});
this.previewTooltip.startTogglingOnHover(this.view.element,
this._onPreviewTooltipTargetHover.bind(this));
@ -395,23 +403,85 @@ TooltipsOverlay.prototype = {
let inspector = this.view.inspector;
if (type === TOOLTIP_IMAGE_TYPE) {
let dim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE);
// nodeInfo contains an absolute uri
let uri = nodeInfo.value.url;
yield this.previewTooltip.setRelativeImageContent(uri,
inspector.inspector, dim);
try {
yield this._setImagePreviewTooltip(nodeInfo.value.url);
} catch (e) {
yield setBrokenImageTooltip(this.previewTooltip, this.view.inspector.panelDoc);
}
return true;
}
if (type === TOOLTIP_FONTFAMILY_TYPE) {
yield this.previewTooltip.setFontFamilyContent(nodeInfo.value.value,
inspector.selection.nodeFront);
let font = nodeInfo.value.value;
let nodeFront = inspector.selection.nodeFront;
yield this._setFontPreviewTooltip(font, nodeFront);
return true;
}
return false;
}),
/**
* Set the content of the preview tooltip to display an image preview. The image URL can
* be relative, a call will be made to the debuggee to retrieve the image content as an
* imageData URI.
*
* @param {String} imageUrl
* The image url value (may be relative or absolute).
* @return {Promise} A promise that resolves when the preview tooltip content is ready
*/
_setImagePreviewTooltip: Task.async(function* (imageUrl) {
let doc = this.view.inspector.panelDoc;
let maxDim = Services.prefs.getIntPref(PREF_IMAGE_TOOLTIP_SIZE);
let naturalWidth, naturalHeight;
if (imageUrl.startsWith("data:")) {
// If the imageUrl already is a data-url, save ourselves a round-trip
let size = yield getImageDimensions(doc, imageUrl);
naturalWidth = size.naturalWidth;
naturalHeight = size.naturalHeight;
} else {
let inspectorFront = this.view.inspector.inspector;
let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl, maxDim);
imageUrl = yield data.string();
naturalWidth = size.naturalWidth;
naturalHeight = size.naturalHeight;
}
yield setImageTooltip(this.previewTooltip, doc, imageUrl,
{maxDim, naturalWidth, naturalHeight});
}),
/**
* Set the content of the preview tooltip to display a font family preview.
*
* @param {String} font
* The font family value.
* @param {object} nodeFront
* The NodeActor that will used to retrieve the dataURL for the font
* family tooltip contents.
* @return {Promise} A promise that resolves when the preview tooltip content is ready
*/
_setFontPreviewTooltip: Task.async(function* (font, nodeFront) {
if (!font || !nodeFront || typeof nodeFront.getFontFamilyDataURL !== "function") {
throw new Error("Unable to create font preview tooltip content.");
}
font = font.replace(/"/g, "'");
font = font.replace("!important", "");
font = font.trim();
let fillStyle = getTheme() === "light" ? "black" : "white";
let {data, size: maxDim} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
let imageUrl = yield data.string();
let doc = this.view.inspector.panelDoc;
let {naturalWidth, naturalHeight} = yield getImageDimensions(doc, imageUrl);
yield setImageTooltip(this.previewTooltip, doc, imageUrl,
{hideDimensionLabel: true, maxDim, naturalWidth, naturalHeight});
}),
_onNewSelection: function () {
if (this.previewTooltip) {
this.previewTooltip.hide();

View File

@ -65,7 +65,7 @@ function* testBodyRuleView(view) {
yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src")
.indexOf("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHe") !== -1,
@ -81,7 +81,7 @@ function* testDivRuleView(view) {
yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"),
"Tooltip contains a data-uri image as expected");
@ -117,7 +117,7 @@ function* testComputedView(view) {
yield assertHoverTooltipOn(view.tooltips.previewTooltip, uriSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"),

View File

@ -7,6 +7,7 @@
// Test that if a tooltip is visible when a new selection is made, it closes
const TEST_URI = "<div class='one'>el 1</div><div class='two'>el 2</div>";
const XHTML_NS = "http://www.w3.org/1999/xhtml";
add_task(function* () {
yield addTab("data:text/html;charset=utf-8," + encodeURIComponent(TEST_URI));
@ -25,7 +26,9 @@ function* testRuleView(ruleView, inspector) {
info("Showing the tooltip");
let tooltip = ruleView.tooltips.previewTooltip;
tooltip.setTextContent({messages: ["rule-view tooltip"]});
let tooltipContent = ruleView.styleDocument.createElementNS(XHTML_NS, "div");
yield tooltip.setContent(tooltipContent, 100, 30);
// Stop listening for mouse movements because it's not needed for this test,
// and causes intermittent failures on Linux. When this test runs in the suite
// sometimes a mouseleave event is dispatched at the start, which causes the
@ -48,7 +51,8 @@ function* testComputedView(computedView, inspector) {
info("Showing the tooltip");
let tooltip = computedView.tooltips.previewTooltip;
tooltip.setTextContent({messages: ["computed-view tooltip"]});
let tooltipContent = computedView.styleDocument.createElementNS(XHTML_NS, "div");
yield tooltip.setContent(tooltipContent, 100, 30);
// Stop listening for mouse movements because it's not needed for this test,
// and causes intermittent failures on Linux. When this test runs in the suite
// sometimes a mouseleave event is dispatched at the start, which causes the

View File

@ -51,7 +51,7 @@ function* testRuleView(ruleView, nodeFront) {
// And verify that the tooltip gets shown on this property
yield assertHoverTooltipOn(tooltip, valueSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"),
"Tooltip contains a data-uri image as expected");
@ -70,7 +70,7 @@ function* testComputedView(computedView, nodeFront) {
yield assertHoverTooltipOn(tooltip, valueSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"),
"Tooltip contains a data-uri image as expected");
@ -97,7 +97,7 @@ function* testExpandedComputedViewProperty(computedView, nodeFront) {
yield assertHoverTooltipOn(tooltip, valueSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src").startsWith("data:"),
"Tooltip contains a data-uri image as expected");

View File

@ -45,7 +45,7 @@ function* testComputedViewUrls(inspector) {
*/
function* performChecks(view, propertyValue) {
function checkTooltip(panel, imageSrc) {
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
is(images[0].getAttribute("src"), imageSrc, "The image URL is correct");
}

View File

@ -47,7 +47,7 @@ function* testRuleView(ruleView, nodeFront) {
// And verify that the tooltip gets shown on this property
yield assertHoverTooltipOn(tooltip, valueSpan);
let images = panel.getElementsByTagName("image");
let images = panel.getElementsByTagName("img");
is(images.length, 1, "Tooltip contains an image");
ok(images[0].getAttribute("src")
.startsWith("data:"), "Tooltip contains a data-uri image as expected");

View File

@ -39,12 +39,12 @@ function* testImageDimension(ruleView) {
info("Showing the tooltip");
let onShown = tooltip.once("shown");
tooltip.show();
tooltip.show(uriSpan);
yield onShown;
// 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 imageRect = panel.querySelector("img").getBoundingClientRect();
let panelRect = panel.getBoundingClientRect();
ok(panelRect.width >= imageRect.width,

View File

@ -18,7 +18,6 @@ const Heritage = require("sdk/core/heritage");
const {Eyedropper} = require("devtools/client/eyedropper/eyedropper");
const Editor = require("devtools/client/sourceeditor/editor");
const Services = require("Services");
const {Task} = require("devtools/shared/task");
loader.lazyRequireGetter(this, "beautify", "devtools/shared/jsbeautify/beautify");
loader.lazyRequireGetter(this, "setNamedTimeout", "devtools/client/shared/widgets/view-helpers", true);
@ -520,31 +519,6 @@ Tooltip.prototype = {
this.panel.setAttribute("clamped-dimensions", "");
},
/**
* Uses the provided inspectorFront's getImageDataFromURL method to resolve
* the relative URL on the server-side, in the page context, and then sets the
* tooltip content with the resulting image just like |setImageContent| does.
* @return a promise that resolves when the image is shown in the tooltip or
* resolves when the broken image tooltip content is ready, but never rejects.
*/
setRelativeImageContent: Task.async(function* (imageUrl, inspectorFront,
maxDim) {
if (imageUrl.startsWith("data:")) {
// If the imageUrl already is a data-url, save ourselves a round-trip
this.setImageContent(imageUrl, {maxDim: maxDim});
} else if (inspectorFront) {
try {
let {data, size} = yield inspectorFront.getImageDataFromURL(imageUrl,
maxDim);
size.maxDim = maxDim;
let str = yield data.string();
this.setImageContent(str, size);
} catch (e) {
this.setBrokenImageContent();
}
}
}),
/**
* Fill the tooltip with a message explaining the the image is missing
*/
@ -560,7 +534,7 @@ Tooltip.prototype = {
* Fill the tooltip with an image and add the image dimension at the bottom.
*
* Only use this for absolute URLs that can be queried from the devtools
* client-side. For relative URLs, use |setRelativeImageContent|.
* client-side.
*
* @param {string} imageUrl
* The url to load the image from
@ -768,38 +742,6 @@ Tooltip.prototype = {
}
},
/**
* Set the content of the tooltip to display a font family preview.
* This is based on Lea Verou's Dablet.
* See https://github.com/LeaVerou/dabblet
* for more info.
* @param {String} font The font family value.
* @param {object} nodeFront
* The NodeActor that will used to retrieve the dataURL for the font
* family tooltip contents.
* @return A promise that resolves when the font tooltip content is ready, or
* rejects if no font is provided
*/
setFontFamilyContent: Task.async(function* (font, nodeFront) {
if (!font || !nodeFront) {
throw new Error("Missing font");
}
if (typeof nodeFront.getFontFamilyDataURL === "function") {
font = font.replace(/"/g, "'");
font = font.replace("!important", "");
font = font.trim();
let fillStyle =
(Services.prefs.getCharPref("devtools.theme") === "light") ?
"black" : "white";
let {data, size} = yield nodeFront.getFontFamilyDataURL(font, fillStyle);
let str = yield data.string();
this.setImageContent(str, { hideDimensionLabel: true, maxDim: size });
}
}),
/**
* Set the content of this tooltip to the MDN docs widget.
*