mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-08 16:58:38 +09:00
Move Add-on SDK source to toolkit/jetpack
This commit is contained in:
parent
0a03067ee3
commit
23b67db438
993 changed files with 484 additions and 100663 deletions
|
|
@ -1,243 +0,0 @@
|
|||
/* 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';
|
||||
|
||||
module.metadata = {
|
||||
'stability': 'experimental',
|
||||
'engines': {
|
||||
'Firefox': '> 28'
|
||||
}
|
||||
};
|
||||
|
||||
const { Cu } = require('chrome');
|
||||
const { on, off, emit } = require('../../event/core');
|
||||
|
||||
const { data } = require('sdk/self');
|
||||
|
||||
const { isObject, isNil } = require('../../lang/type');
|
||||
|
||||
const { getMostRecentBrowserWindow } = require('../../window/utils');
|
||||
const { ignoreWindow } = require('../../private-browsing/utils');
|
||||
const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
|
||||
const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
|
||||
|
||||
const { events: viewEvents } = require('./view/events');
|
||||
|
||||
const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
|
||||
|
||||
const views = new Map();
|
||||
const customizedWindows = new WeakMap();
|
||||
|
||||
const buttonListener = {
|
||||
onCustomizeStart: window => {
|
||||
for (let [id, view] of views) {
|
||||
setIcon(id, window, view.icon);
|
||||
setLabel(id, window, view.label);
|
||||
}
|
||||
|
||||
customizedWindows.set(window, true);
|
||||
},
|
||||
onCustomizeEnd: window => {
|
||||
customizedWindows.delete(window);
|
||||
|
||||
for (let [id, ] of views) {
|
||||
let placement = CustomizableUI.getPlacementOfWidget(id);
|
||||
|
||||
if (placement)
|
||||
emit(viewEvents, 'data', { type: 'update', target: id, window: window });
|
||||
}
|
||||
},
|
||||
onWidgetAfterDOMChange: (node, nextNode, container) => {
|
||||
let { id } = node;
|
||||
let view = views.get(id);
|
||||
let window = node.ownerDocument.defaultView;
|
||||
|
||||
if (view) {
|
||||
emit(viewEvents, 'data', { type: 'update', target: id, window: window });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
CustomizableUI.addListener(buttonListener);
|
||||
|
||||
require('../../system/unload').when( _ =>
|
||||
CustomizableUI.removeListener(buttonListener)
|
||||
);
|
||||
|
||||
function getNode(id, window) {
|
||||
return !views.has(id) || ignoreWindow(window)
|
||||
? null
|
||||
: CustomizableUI.getWidget(id).forWindow(window).node
|
||||
};
|
||||
|
||||
function isInToolbar(id) {
|
||||
let placement = CustomizableUI.getPlacementOfWidget(id);
|
||||
|
||||
return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
|
||||
}
|
||||
|
||||
|
||||
function getImage(icon, isInToolbar, pixelRatio) {
|
||||
let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
|
||||
let bestSize = 0;
|
||||
let image = icon;
|
||||
|
||||
if (isObject(icon)) {
|
||||
for (let size of Object.keys(icon)) {
|
||||
size = +size;
|
||||
let offset = targetSize - size;
|
||||
|
||||
if (offset === 0) {
|
||||
bestSize = size;
|
||||
break;
|
||||
}
|
||||
|
||||
let delta = Math.abs(offset) - Math.abs(targetSize - bestSize);
|
||||
|
||||
if (delta < 0)
|
||||
bestSize = size;
|
||||
}
|
||||
|
||||
image = icon[bestSize];
|
||||
}
|
||||
|
||||
if (image.indexOf('./') === 0)
|
||||
return data.url(image.substr(2));
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
function nodeFor(id, window=getMostRecentBrowserWindow()) {
|
||||
return customizedWindows.has(window) ? null : getNode(id, window);
|
||||
};
|
||||
exports.nodeFor = nodeFor;
|
||||
|
||||
function create(options) {
|
||||
let { id, label, icon, type, badge } = options;
|
||||
|
||||
if (views.has(id))
|
||||
throw new Error('The ID "' + id + '" seems already used.');
|
||||
|
||||
CustomizableUI.createWidget({
|
||||
id: id,
|
||||
type: 'custom',
|
||||
removable: true,
|
||||
defaultArea: AREA_NAVBAR,
|
||||
allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
|
||||
|
||||
onBuild: function(document) {
|
||||
let window = document.defaultView;
|
||||
|
||||
let node = document.createElementNS(XUL_NS, 'toolbarbutton');
|
||||
|
||||
let image = getImage(icon, true, window.devicePixelRatio);
|
||||
|
||||
if (ignoreWindow(window))
|
||||
node.style.display = 'none';
|
||||
|
||||
node.setAttribute('id', this.id);
|
||||
node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional badged-button');
|
||||
node.setAttribute('type', type);
|
||||
node.setAttribute('label', label);
|
||||
node.setAttribute('tooltiptext', label);
|
||||
node.setAttribute('image', image);
|
||||
node.setAttribute('constrain-size', 'true');
|
||||
|
||||
views.set(id, {
|
||||
area: this.currentArea,
|
||||
icon: icon,
|
||||
label: label
|
||||
});
|
||||
|
||||
node.addEventListener('command', function(event) {
|
||||
if (views.has(id)) {
|
||||
emit(viewEvents, 'data', {
|
||||
type: 'click',
|
||||
target: id,
|
||||
window: event.view,
|
||||
checked: node.checked
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return node;
|
||||
}
|
||||
});
|
||||
};
|
||||
exports.create = create;
|
||||
|
||||
function dispose(id) {
|
||||
if (!views.has(id)) return;
|
||||
|
||||
views.delete(id);
|
||||
CustomizableUI.destroyWidget(id);
|
||||
}
|
||||
exports.dispose = dispose;
|
||||
|
||||
function setIcon(id, window, icon) {
|
||||
let node = getNode(id, window);
|
||||
|
||||
if (node) {
|
||||
icon = customizedWindows.has(window) ? views.get(id).icon : icon;
|
||||
let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
|
||||
|
||||
node.setAttribute('image', image);
|
||||
}
|
||||
}
|
||||
exports.setIcon = setIcon;
|
||||
|
||||
function setLabel(id, window, label) {
|
||||
let node = nodeFor(id, window);
|
||||
|
||||
if (node) {
|
||||
node.setAttribute('label', label);
|
||||
node.setAttribute('tooltiptext', label);
|
||||
}
|
||||
}
|
||||
exports.setLabel = setLabel;
|
||||
|
||||
function setDisabled(id, window, disabled) {
|
||||
let node = nodeFor(id, window);
|
||||
|
||||
if (node)
|
||||
node.disabled = disabled;
|
||||
}
|
||||
exports.setDisabled = setDisabled;
|
||||
|
||||
function setChecked(id, window, checked) {
|
||||
let node = nodeFor(id, window);
|
||||
|
||||
if (node)
|
||||
node.checked = checked;
|
||||
}
|
||||
exports.setChecked = setChecked;
|
||||
|
||||
function setBadge(id, window, badge, color) {
|
||||
let node = nodeFor(id, window);
|
||||
|
||||
if (node) {
|
||||
// `Array.from` is needed to handle unicode symbol properly:
|
||||
// '𝐀𝐁'.length is 4 where Array.from('𝐀𝐁').length is 2
|
||||
let text = isNil(badge)
|
||||
? ''
|
||||
: Array.from(String(badge)).slice(0, 4).join('');
|
||||
|
||||
node.setAttribute('badge', text);
|
||||
|
||||
let badgeNode = node.ownerDocument.getAnonymousElementByAttribute(node,
|
||||
'class', 'toolbarbutton-badge');
|
||||
|
||||
if (badgeNode)
|
||||
badgeNode.style.backgroundColor = isNil(color) ? '' : color;
|
||||
}
|
||||
}
|
||||
exports.setBadge = setBadge;
|
||||
|
||||
function click(id) {
|
||||
let node = nodeFor(id);
|
||||
|
||||
if (node)
|
||||
node.click();
|
||||
}
|
||||
exports.click = click;
|
||||
Loading…
Add table
Add a link
Reference in a new issue