Files
tubestation/browser/devtools/fontinspector/font-inspector.js
Sami Jaktholm ba28755b0a Bug 1158634 - Restore support for editing previews in Font Inspector. r=pbrosset
An input box similar to those in rule and computed views (without the search
symbol) is added to the font-inspector panel which can be used to control the
preview text. The updates are throttled to avoid unnecessary updates while the
text is being edited.

Since the PageStyleActor has allowed clients to define the preview text for a
while now, this feature is also enabled for older targets too.
2015-05-21 19:18:18 +03:00

243 lines
6.4 KiB
JavaScript

/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { utils: Cu } = Components;
const DEFAULT_PREVIEW_TEXT = "Abc";
const PREVIEW_UPDATE_DELAY = 150;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "console",
"resource://gre/modules/devtools/Console.jsm");
function FontInspector(inspector, window)
{
this.inspector = inspector;
this.pageStyle = this.inspector.pageStyle;
this.chromeDoc = window.document;
this.init();
}
FontInspector.prototype = {
init: function() {
this.update = this.update.bind(this);
this.onNewNode = this.onNewNode.bind(this);
this.inspector.selection.on("new-node", this.onNewNode);
this.inspector.sidebar.on("fontinspector-selected", this.onNewNode);
this.showAll = this.showAll.bind(this);
this.showAllButton = this.chromeDoc.getElementById("showall");
this.showAllButton.addEventListener("click", this.showAll);
this.previewTextChanged = this.previewTextChanged.bind(this);
this.previewInput = this.chromeDoc.getElementById("preview-text-input");
this.previewInput.addEventListener("input", this.previewTextChanged);
this.update();
},
/**
* Is the fontinspector visible in the sidebar?
*/
isActive: function() {
return this.inspector.sidebar &&
this.inspector.sidebar.getCurrentTabID() == "fontinspector";
},
/**
* Remove listeners.
*/
destroy: function() {
this.chromeDoc = null;
this.inspector.sidebar.off("fontinspector-selected", this.onNewNode);
this.inspector.selection.off("new-node", this.onNewNode);
this.showAllButton.removeEventListener("click", this.showAll);
this.previewInput.removeEventListener("input", this.previewTextChanged);
if (this._previewUpdateTimeout) {
clearTimeout(this._previewUpdateTimeout);
}
},
/**
* Selection 'new-node' event handler.
*/
onNewNode: function() {
if (this.isActive() &&
this.inspector.selection.isConnected() &&
this.inspector.selection.isElementNode()) {
this.undim();
this.update();
} else {
this.dim();
}
},
/**
* The text to use for previews. Returns either the value user has typed to
* the preview input or DEFAULT_PREVIEW_TEXT if the input is empty or contains
* only whitespace.
*/
getPreviewText: function() {
let inputText = this.previewInput.value.trim();
if (inputText === "") {
return DEFAULT_PREVIEW_TEXT;
}
return inputText;
},
/**
* Preview input 'input' event handler.
*/
previewTextChanged: function() {
if (this._previewUpdateTimeout) {
clearTimeout(this._previewUpdateTimeout);
}
this._previewUpdateTimeout = setTimeout(() => {
this.update(this._lastUpdateShowedAllFonts);
}, PREVIEW_UPDATE_DELAY);
},
/**
* Hide the font list. No node are selected.
*/
dim: function() {
this.chromeDoc.body.classList.add("dim");
this.clear();
},
/**
* Show the font list. A node is selected.
*/
undim: function() {
this.chromeDoc.body.classList.remove("dim");
},
/**
* Clears the font list.
*/
clear: function() {
this.chromeDoc.querySelector("#all-fonts").innerHTML = "";
},
/**
* Retrieve all the font info for the selected node and display it.
*/
update: Task.async(function*(showAllFonts) {
let node = this.inspector.selection.nodeFront;
if (!node ||
!this.isActive() ||
!this.inspector.selection.isConnected() ||
!this.inspector.selection.isElementNode() ||
this.chromeDoc.body.classList.contains("dim")) {
return;
}
this._lastUpdateShowedAllFonts = showAllFonts;
// Assume light theme colors as the default (see also bug 1118179).
let fillStyle = (Services.prefs.getCharPref("devtools.theme") == "dark") ?
"white" : "black";
let options = {
includePreviews: true,
previewText: this.getPreviewText(),
previewFillStyle: fillStyle
};
let fonts = [];
if (showAllFonts) {
fonts = yield this.pageStyle.getAllUsedFontFaces(options)
.then(null, console.error);
} else {
fonts = yield this.pageStyle.getUsedFontFaces(node, options)
.then(null, console.error);
}
if (!fonts || !fonts.length) {
// No fonts to display. Clear the previously shown fonts.
this.clear();
return;
}
for (let font of fonts) {
font.previewUrl = yield font.preview.data.string();
}
// in case we've been destroyed in the meantime
if (!this.chromeDoc) {
return;
}
// Make room for the new fonts.
this.clear();
for (let font of fonts) {
this.render(font);
}
this.inspector.emit("fontinspector-updated");
}),
/**
* Display the information of one font.
*/
render: function(font) {
let s = this.chromeDoc.querySelector("#template > section");
s = s.cloneNode(true);
s.querySelector(".font-name").textContent = font.name;
s.querySelector(".font-css-name").textContent = font.CSSFamilyName;
if (font.URI) {
s.classList.add("is-remote");
} else {
s.classList.add("is-local");
}
let formatElem = s.querySelector(".font-format");
if (font.format) {
formatElem.textContent = font.format;
} else {
formatElem.hidden = true;
}
s.querySelector(".font-url").value = font.URI;
if (font.rule) {
// This is the @font-face{…} code.
let cssText = font.ruleText;
s.classList.add("has-code");
s.querySelector(".font-css-code").textContent = cssText;
}
let preview = s.querySelector(".font-preview");
preview.src = font.previewUrl;
this.chromeDoc.querySelector("#all-fonts").appendChild(s);
},
/**
* Show all fonts for the document (including iframes)
*/
showAll: function() {
this.update(true);
},
};
window.setPanel = function(panel) {
window.fontInspector = new FontInspector(panel, window);
};
window.onunload = function() {
if (window.fontInspector) {
window.fontInspector.destroy();
}
};