addon-sdk/source/lib/sdk/ui/button/view.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 'use strict';
michael@0 5
michael@0 6 module.metadata = {
michael@0 7 'stability': 'experimental',
michael@0 8 'engines': {
michael@0 9 'Firefox': '> 28'
michael@0 10 }
michael@0 11 };
michael@0 12
michael@0 13 const { Cu } = require('chrome');
michael@0 14 const { on, off, emit } = require('../../event/core');
michael@0 15
michael@0 16 const { data } = require('sdk/self');
michael@0 17
michael@0 18 const { isObject } = require('../../lang/type');
michael@0 19
michael@0 20 const { getMostRecentBrowserWindow } = require('../../window/utils');
michael@0 21 const { ignoreWindow } = require('../../private-browsing/utils');
michael@0 22 const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
michael@0 23 const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
michael@0 24
michael@0 25 const { events: viewEvents } = require('./view/events');
michael@0 26
michael@0 27 const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
michael@0 28
michael@0 29 const views = new Map();
michael@0 30 const customizedWindows = new WeakMap();
michael@0 31
michael@0 32 const buttonListener = {
michael@0 33 onCustomizeStart: window => {
michael@0 34 for (let [id, view] of views) {
michael@0 35 setIcon(id, window, view.icon);
michael@0 36 setLabel(id, window, view.label);
michael@0 37 }
michael@0 38
michael@0 39 customizedWindows.set(window, true);
michael@0 40 },
michael@0 41 onCustomizeEnd: window => {
michael@0 42 customizedWindows.delete(window);
michael@0 43
michael@0 44 for (let [id, ] of views) {
michael@0 45 let placement = CustomizableUI.getPlacementOfWidget(id);
michael@0 46
michael@0 47 if (placement)
michael@0 48 emit(viewEvents, 'data', { type: 'update', target: id, window: window });
michael@0 49 }
michael@0 50 },
michael@0 51 onWidgetAfterDOMChange: (node, nextNode, container) => {
michael@0 52 let { id } = node;
michael@0 53 let view = views.get(id);
michael@0 54 let window = node.ownerDocument.defaultView;
michael@0 55
michael@0 56 if (view) {
michael@0 57 emit(viewEvents, 'data', { type: 'update', target: id, window: window });
michael@0 58 }
michael@0 59 }
michael@0 60 };
michael@0 61
michael@0 62 CustomizableUI.addListener(buttonListener);
michael@0 63
michael@0 64 require('../../system/unload').when( _ =>
michael@0 65 CustomizableUI.removeListener(buttonListener)
michael@0 66 );
michael@0 67
michael@0 68 function getNode(id, window) {
michael@0 69 return !views.has(id) || ignoreWindow(window)
michael@0 70 ? null
michael@0 71 : CustomizableUI.getWidget(id).forWindow(window).node
michael@0 72 };
michael@0 73
michael@0 74 function isInToolbar(id) {
michael@0 75 let placement = CustomizableUI.getPlacementOfWidget(id);
michael@0 76
michael@0 77 return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
michael@0 78 }
michael@0 79
michael@0 80
michael@0 81 function getImage(icon, isInToolbar, pixelRatio) {
michael@0 82 let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
michael@0 83 let bestSize = 0;
michael@0 84 let image = icon;
michael@0 85
michael@0 86 if (isObject(icon)) {
michael@0 87 for (let size of Object.keys(icon)) {
michael@0 88 size = +size;
michael@0 89 let offset = targetSize - size;
michael@0 90
michael@0 91 if (offset === 0) {
michael@0 92 bestSize = size;
michael@0 93 break;
michael@0 94 }
michael@0 95
michael@0 96 let delta = Math.abs(offset) - Math.abs(targetSize - bestSize);
michael@0 97
michael@0 98 if (delta < 0)
michael@0 99 bestSize = size;
michael@0 100 }
michael@0 101
michael@0 102 image = icon[bestSize];
michael@0 103 }
michael@0 104
michael@0 105 if (image.indexOf('./') === 0)
michael@0 106 return data.url(image.substr(2));
michael@0 107
michael@0 108 return image;
michael@0 109 }
michael@0 110
michael@0 111 function nodeFor(id, window=getMostRecentBrowserWindow()) {
michael@0 112 return customizedWindows.has(window) ? null : getNode(id, window);
michael@0 113 };
michael@0 114 exports.nodeFor = nodeFor;
michael@0 115
michael@0 116 function create(options) {
michael@0 117 let { id, label, icon, type } = options;
michael@0 118
michael@0 119 if (views.has(id))
michael@0 120 throw new Error('The ID "' + id + '" seems already used.');
michael@0 121
michael@0 122 CustomizableUI.createWidget({
michael@0 123 id: id,
michael@0 124 type: 'custom',
michael@0 125 removable: true,
michael@0 126 defaultArea: AREA_NAVBAR,
michael@0 127 allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
michael@0 128
michael@0 129 onBuild: function(document) {
michael@0 130 let window = document.defaultView;
michael@0 131
michael@0 132 let node = document.createElementNS(XUL_NS, 'toolbarbutton');
michael@0 133
michael@0 134 let image = getImage(icon, true, window.devicePixelRatio);
michael@0 135
michael@0 136 if (ignoreWindow(window))
michael@0 137 node.style.display = 'none';
michael@0 138
michael@0 139 node.setAttribute('id', this.id);
michael@0 140 node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional');
michael@0 141 node.setAttribute('type', type);
michael@0 142 node.setAttribute('label', label);
michael@0 143 node.setAttribute('tooltiptext', label);
michael@0 144 node.setAttribute('image', image);
michael@0 145 node.setAttribute('sdk-button', 'true');
michael@0 146
michael@0 147 views.set(id, {
michael@0 148 area: this.currentArea,
michael@0 149 icon: icon,
michael@0 150 label: label
michael@0 151 });
michael@0 152
michael@0 153 node.addEventListener('command', function(event) {
michael@0 154 if (views.has(id)) {
michael@0 155 emit(viewEvents, 'data', {
michael@0 156 type: 'click',
michael@0 157 target: id,
michael@0 158 window: event.view,
michael@0 159 checked: node.checked
michael@0 160 });
michael@0 161 }
michael@0 162 });
michael@0 163
michael@0 164 return node;
michael@0 165 }
michael@0 166 });
michael@0 167 };
michael@0 168 exports.create = create;
michael@0 169
michael@0 170 function dispose(id) {
michael@0 171 if (!views.has(id)) return;
michael@0 172
michael@0 173 views.delete(id);
michael@0 174 CustomizableUI.destroyWidget(id);
michael@0 175 }
michael@0 176 exports.dispose = dispose;
michael@0 177
michael@0 178 function setIcon(id, window, icon) {
michael@0 179 let node = getNode(id, window);
michael@0 180
michael@0 181 if (node) {
michael@0 182 icon = customizedWindows.has(window) ? views.get(id).icon : icon;
michael@0 183 let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
michael@0 184
michael@0 185 node.setAttribute('image', image);
michael@0 186 }
michael@0 187 }
michael@0 188 exports.setIcon = setIcon;
michael@0 189
michael@0 190 function setLabel(id, window, label) {
michael@0 191 let node = nodeFor(id, window);
michael@0 192
michael@0 193 if (node) {
michael@0 194 node.setAttribute('label', label);
michael@0 195 node.setAttribute('tooltiptext', label);
michael@0 196 }
michael@0 197 }
michael@0 198 exports.setLabel = setLabel;
michael@0 199
michael@0 200 function setDisabled(id, window, disabled) {
michael@0 201 let node = nodeFor(id, window);
michael@0 202
michael@0 203 if (node)
michael@0 204 node.disabled = disabled;
michael@0 205 }
michael@0 206 exports.setDisabled = setDisabled;
michael@0 207
michael@0 208 function setChecked(id, window, checked) {
michael@0 209 let node = nodeFor(id, window);
michael@0 210
michael@0 211 if (node)
michael@0 212 node.checked = checked;
michael@0 213 }
michael@0 214 exports.setChecked = setChecked;
michael@0 215
michael@0 216 function click(id) {
michael@0 217 let node = nodeFor(id);
michael@0 218
michael@0 219 if (node)
michael@0 220 node.click();
michael@0 221 }
michael@0 222 exports.click = click;

mercurial