Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/customizableUI.js

Issue 5741004535627776: Fix toolbar icon customization in Australis (Closed)
Patch Set: Created Nov. 22, 2013, 5:06 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/appSupport.js ('k') | lib/ui.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2013 Eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /**
19 * @fileOverview This emulates a subset of the CustomizableUI API from Firefox 2 8.
20 */
21
22 let {Utils} = require("utils");
23
24 let widgets = Map();
25
26 function findElement(/**Window*/ window, /**String|String[]*/ id) /**Element*/
27 {
28 if (id instanceof Array)
29 {
30 for (let candidate of id)
31 {
32 let result = window.document.getElementById(candidate);
33 if (result)
34 return result;
35 }
36 return null;
37 }
38 else
39 return window.document.getElementById(id);
40 }
41
42 function getToolbox(/**Window*/ window, /**Widget*/ widget) /**Element*/
43 {
44 if (!("defaultArea" in widget) || !widget.defaultArea)
45 return null;
46
47 let toolbar = findElement(window, widget.defaultArea);
48 if (!toolbar)
49 return null;
50
51 let toolbox = toolbar.toolbox;
52 if (toolbox && ("palette" in toolbox) && toolbox.palette)
53 return toolbox;
54 else
55 return null;
56 }
57
58 function getToolbar(/**Element*/ element) /**Element*/
59 {
60 for (let parent = element.parentNode; parent; parent = parent.parentNode)
61 if (parent.localName == "toolbar")
62 return parent;
63 return null;
64 }
65
66 function getPaletteItem(/**Element*/ toolbox, /**String*/ id) /**Element*/
67 {
68 for (let child of toolbox.palette.children)
69 if (child.id == id)
70 return child;
71
72 return null;
73 }
74
75 function restoreWidget(/**Element*/ toolbox, /**Widget*/ widget)
76 {
77 // Create node
78 let node = toolbox.ownerDocument.createElement("toolbarbutton");
79 node.setAttribute("id", widget.id);
80 if (typeof widget.onClick == "function")
81 node.addEventListener("click", widget.onClick, false);
82 if (typeof widget.onCommand == "function")
83 node.addEventListener("command", widget.onCommand, false);
84 if (typeof widget.onCreated == "function")
85 widget.onCreated(node);
86
87 // Insert into the palette first
88 toolbox.palette.insertBefore(node, toolbox.palette.firstChild);
89
90 // Now find out where we should put it
91 let position = toolbox.getAttribute(widget.positionAttribute);
92 if (!/^\S*,\S*,\S*$/.test(position))
93 position = null;
94
95 if (position == null)
96 {
97 // No explicitly saved position but maybe we can find it in a currentset
98 // attribute somewhere.
99 let toolbars = toolbox.externalToolbars.slice();
100 for (let child of toolbox.children)
101 if (child.localName == "toolbar")
102 toolbars.push(child);
103 for (let toolbar of toolbars)
104 {
105 let currentSet = toolbar.getAttribute("currentset");
106 if (currentSet)
107 {
108 let items = currentSet.split(",");
109 let index = items.indexOf(widget.id);
110 if (index >= 0)
111 {
112 let before = (index + 1 < items.length ? items[index + 1] : "");
113 position = "visible," + toolbar.id + "," + before;
114 toolbox.setAttribute(widget.positionAttribute, position);
115 toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute);
116 break;
117 }
118 }
119 }
120 }
121
122 showWidget(toolbox, widget, position);
123 }
124
125 function showWidget(/**Element*/ toolbox, /**Widget*/ widget, /**String*/ positi on)
126 {
127 let visible = "visible", parent = null, before = null;
128 if (position)
129 {
130 [visible, parent, before] = position.split(",", 3);
131 parent = toolbox.ownerDocument.getElementById(parent);
132 if (before == "")
133 before = null;
134 else
135 before = toolbox.ownerDocument.getElementById(before);
136 if (before && before.parentNode != parent)
137 before = null;
138 }
139
140 if (visible == "visible" && !parent)
141 {
142 let insertionPoint = {
143 parent: widget.defaultArea
144 };
145 if (typeof widget.defaultBefore != "undefined")
146 insertionPoint.before = widget.defaultBefore;
147 if (typeof widget.defaultAfter != "undefined")
148 insertionPoint.after = widget.defaultAfter;
149
150 let {UI} = require("ui");
151 [parent, before] = UI.resolveInsertionPoint(toolbox.ownerDocument.defaultVie w, insertionPoint);
152 }
153
154 if (parent && parent.localName != "toolbar")
155 parent = null;
156
157 if (visible != "visible")
158 {
159 // Move to palette if the item is currently visible
160 let node = toolbox.ownerDocument.getElementById(widget.id);
161 if (node)
162 toolbox.palette.appendChild(node);
163 }
164 else if (parent)
165 {
166 // Add the item to the toolbar
167 let items = parent.currentSet.split(",");
168 let index = (before ? items.indexOf(before.id) : -1);
169 if (index < 0)
170 before = null;
171 parent.insertItem(widget.id, before, null, false);
172 }
173
174 saveState(toolbox, widget);
175 }
176
177 function removeWidget(/**Window*/ window, /**Widget*/ widget)
178 {
179 let element = window.document.getElementById(widget.id);
180 if (element)
181 element.parentNode.removeChild(element);
182
183 let toolbox = getToolbox(window, widget);
184 if (toolbox)
185 {
186 let paletteItem = getPaletteItem(toolbox, widget.id);
187 if (paletteItem)
188 paletteItem.parentNode.removeChild(paletteItem);
189 }
190 }
191
192 function onToolbarCustomization(/**Event*/ event)
193 {
194 let toolbox = event.currentTarget;
195 for (let [id, widget] of widgets)
196 saveState(toolbox, widget);
197 }
198
199 function saveState(/**Element*/ toolbox, /**Widget*/ widget)
200 {
201 let node = toolbox.ownerDocument.getElementById(widget.id);
202
203 let position = toolbox.getAttribute(widget.positionAttribute) || "hidden,,";
204 if (node)
205 {
206 if (typeof widget.onCreated == "function")
207 widget.onCreated(node);
208
209 let toolbar = getToolbar(node);
210 position = "visible," + toolbar.id + "," + (node.nextSibling ? node.nextSibl ing.id : "");
211 }
212 else
213 position = position.replace(/^visible,/, "hidden,")
214
215 toolbox.setAttribute(widget.positionAttribute, position);
216 toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute);
217 }
218
219 let CustomizableUI = exports.CustomizableUI =
220 {
221 createWidget: function(widget)
222 {
223 if (typeof widget.id == "undefined" ||
224 typeof widget.defaultArea == "undefined" ||
225 typeof widget.positionAttribute == "undefined")
226 {
227 throw new Error("Unexpected: required property missing from the widget dat a");
228 }
229 widgets.set(widget.id, widget);
230
231 // Show widget in any existing windows
232 let {UI} = require("ui");
233 for (let window of UI.applicationWindows)
234 {
235 let toolbox = getToolbox(window, widget);
236 if (toolbox)
237 {
238 toolbox.addEventListener("aftercustomization", onToolbarCustomization, f alse);
239 restoreWidget(toolbox, widget);
240 }
241 }
242 },
243
244 destroyWidget: function(id)
245 {
246 // Don't do anything here. This function is called on shutdown,
247 // removeFromWindow will take care of cleaning up already.
248 },
249
250 getPlacementOfWidget: function(id)
251 {
252 let {UI} = require("ui");
253 let window = UI.currentWindow;
254 if (!window)
255 return null;
256
257 let widget = window.document.getElementById(id);
258 if (!widget)
259 return null;
260
261 let toolbar = getToolbar(widget);
262 if (!toolbar)
263 return null;
264
265 let items = toolbar.currentSet.split(",");
266 let index = items.indexOf(id);
267 if (index < 0)
268 return null;
269 else
270 return {area: toolbar.id, placement: index};
271 },
272
273 addWidgetToArea: function(id, area, position)
274 {
275 let {UI} = require("ui");
276 let widget = widgets.get(id);
277 for (let window of UI.applicationWindows)
278 {
279 let toolbox = getToolbox(window, widget);
280 if (!toolbox)
281 continue;
282
283 let position = toolbox.getAttribute(widget.positionAttribute);
284 if (position)
285 position = position.replace(/^hidden,/, "visible,");
286 showWidget(toolbox, widget, position);
287 }
288 },
289
290 removeWidgetFromArea: function(id)
291 {
292 let {UI} = require("ui");
293 let widget = widgets.get(id);
294 for (let window of UI.applicationWindows)
295 {
296 let toolbox = getToolbox(window, widget);
297 if (!toolbox)
298 continue;
299
300 let position = toolbox.getAttribute(widget.positionAttribute);
301 if (position)
302 position = position.replace(/^visible,/, "hidden,");
303 else
304 position = "hidden,,";
305 showWidget(toolbox, widget, position);
306 }
307 }
308 };
309
310 let {WindowObserver} = require("windowObserver");
311 new WindowObserver({
312 applyToWindow: function(window)
313 {
314 let {isKnownWindow} = require("appSupport");
315 if (!isKnownWindow(window))
316 return;
317
318 for (let [id, widget] of widgets)
319 {
320 let toolbox = getToolbox(window, widget);
321 if (toolbox)
322 {
323 toolbox.addEventListener("aftercustomization", onToolbarCustomization, f alse);
324
325 // Restore widget asynchronously to allow the stylesheet to load
326 Utils.runAsync(restoreWidget.bind(null, toolbox, widget));
327 }
328 }
329 },
330
331 removeFromWindow: function(window)
332 {
333 let {isKnownWindow} = require("appSupport");
334 if (!isKnownWindow(window))
335 return;
336
337 for (let [id, widget] of widgets)
338 {
339 let toolbox = getToolbox(window, widget);
340 if (toolbox)
341 toolbox.removeEventListener("aftercustomization", onToolbarCustomization , false);
342
343 removeWidget(window, widget);
344 }
345 }
346 });
OLDNEW
« no previous file with comments | « lib/appSupport.js ('k') | lib/ui.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld