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: Fixed unintentional code duplication Created Nov. 22, 2013, 5:11 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 getToolbox(/**Window*/ window, /**Widget*/ widget) /**Element*/
27 {
28 if (!("defaultArea" in widget) || !widget.defaultArea)
29 return null;
30
31 let {UI} = require("ui");
32 let toolbar = UI.findElement(window, widget.defaultArea);
33 if (!toolbar)
34 return null;
35
36 let toolbox = toolbar.toolbox;
37 if (toolbox && ("palette" in toolbox) && toolbox.palette)
38 return toolbox;
39 else
40 return null;
41 }
42
43 function getToolbar(/**Element*/ element) /**Element*/
44 {
45 for (let parent = element.parentNode; parent; parent = parent.parentNode)
46 if (parent.localName == "toolbar")
47 return parent;
48 return null;
49 }
50
51 function getPaletteItem(/**Element*/ toolbox, /**String*/ id) /**Element*/
52 {
53 for (let child of toolbox.palette.children)
54 if (child.id == id)
55 return child;
56
57 return null;
58 }
59
60 function restoreWidget(/**Element*/ toolbox, /**Widget*/ widget)
61 {
62 // Create node
63 let node = toolbox.ownerDocument.createElement("toolbarbutton");
64 node.setAttribute("id", widget.id);
65 if (typeof widget.onClick == "function")
66 node.addEventListener("click", widget.onClick, false);
67 if (typeof widget.onCommand == "function")
68 node.addEventListener("command", widget.onCommand, false);
69 if (typeof widget.onCreated == "function")
70 widget.onCreated(node);
71
72 // Insert into the palette first
73 toolbox.palette.insertBefore(node, toolbox.palette.firstChild);
74
75 // Now find out where we should put it
76 let position = toolbox.getAttribute(widget.positionAttribute);
77 if (!/^\S*,\S*,\S*$/.test(position))
78 position = null;
79
80 if (position == null)
81 {
82 // No explicitly saved position but maybe we can find it in a currentset
83 // attribute somewhere.
84 let toolbars = toolbox.externalToolbars.slice();
85 for (let child of toolbox.children)
86 if (child.localName == "toolbar")
87 toolbars.push(child);
88 for (let toolbar of toolbars)
89 {
90 let currentSet = toolbar.getAttribute("currentset");
91 if (currentSet)
92 {
93 let items = currentSet.split(",");
94 let index = items.indexOf(widget.id);
95 if (index >= 0)
96 {
97 let before = (index + 1 < items.length ? items[index + 1] : "");
98 position = "visible," + toolbar.id + "," + before;
99 toolbox.setAttribute(widget.positionAttribute, position);
100 toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute);
101 break;
102 }
103 }
104 }
105 }
106
107 showWidget(toolbox, widget, position);
108 }
109
110 function showWidget(/**Element*/ toolbox, /**Widget*/ widget, /**String*/ positi on)
111 {
112 let visible = "visible", parent = null, before = null;
113 if (position)
114 {
115 [visible, parent, before] = position.split(",", 3);
116 parent = toolbox.ownerDocument.getElementById(parent);
117 if (before == "")
118 before = null;
119 else
120 before = toolbox.ownerDocument.getElementById(before);
121 if (before && before.parentNode != parent)
122 before = null;
123 }
124
125 if (visible == "visible" && !parent)
126 {
127 let insertionPoint = {
128 parent: widget.defaultArea
129 };
130 if (typeof widget.defaultBefore != "undefined")
131 insertionPoint.before = widget.defaultBefore;
132 if (typeof widget.defaultAfter != "undefined")
133 insertionPoint.after = widget.defaultAfter;
134
135 let {UI} = require("ui");
136 [parent, before] = UI.resolveInsertionPoint(toolbox.ownerDocument.defaultVie w, insertionPoint);
137 }
138
139 if (parent && parent.localName != "toolbar")
140 parent = null;
141
142 if (visible != "visible")
143 {
144 // Move to palette if the item is currently visible
145 let node = toolbox.ownerDocument.getElementById(widget.id);
146 if (node)
147 toolbox.palette.appendChild(node);
148 }
149 else if (parent)
150 {
151 // Add the item to the toolbar
152 let items = parent.currentSet.split(",");
153 let index = (before ? items.indexOf(before.id) : -1);
154 if (index < 0)
155 before = null;
156 parent.insertItem(widget.id, before, null, false);
157 }
158
159 saveState(toolbox, widget);
160 }
161
162 function removeWidget(/**Window*/ window, /**Widget*/ widget)
163 {
164 let element = window.document.getElementById(widget.id);
165 if (element)
166 element.parentNode.removeChild(element);
167
168 let toolbox = getToolbox(window, widget);
169 if (toolbox)
170 {
171 let paletteItem = getPaletteItem(toolbox, widget.id);
172 if (paletteItem)
173 paletteItem.parentNode.removeChild(paletteItem);
174 }
175 }
176
177 function onToolbarCustomization(/**Event*/ event)
178 {
179 let toolbox = event.currentTarget;
180 for (let [id, widget] of widgets)
181 saveState(toolbox, widget);
182 }
183
184 function saveState(/**Element*/ toolbox, /**Widget*/ widget)
185 {
186 let node = toolbox.ownerDocument.getElementById(widget.id);
187
188 let position = toolbox.getAttribute(widget.positionAttribute) || "hidden,,";
189 if (node)
190 {
191 if (typeof widget.onCreated == "function")
192 widget.onCreated(node);
193
194 let toolbar = getToolbar(node);
195 position = "visible," + toolbar.id + "," + (node.nextSibling ? node.nextSibl ing.id : "");
196 }
197 else
198 position = position.replace(/^visible,/, "hidden,")
199
200 toolbox.setAttribute(widget.positionAttribute, position);
201 toolbox.ownerDocument.persist(toolbox.id, widget.positionAttribute);
202 }
203
204 let CustomizableUI = exports.CustomizableUI =
205 {
206 createWidget: function(widget)
207 {
208 if (typeof widget.id == "undefined" ||
209 typeof widget.defaultArea == "undefined" ||
210 typeof widget.positionAttribute == "undefined")
211 {
212 throw new Error("Unexpected: required property missing from the widget dat a");
213 }
214 widgets.set(widget.id, widget);
215
216 // Show widget in any existing windows
217 let {UI} = require("ui");
218 for (let window of UI.applicationWindows)
219 {
220 let toolbox = getToolbox(window, widget);
221 if (toolbox)
222 {
223 toolbox.addEventListener("aftercustomization", onToolbarCustomization, f alse);
224 restoreWidget(toolbox, widget);
225 }
226 }
227 },
228
229 destroyWidget: function(id)
230 {
231 // Don't do anything here. This function is called on shutdown,
232 // removeFromWindow will take care of cleaning up already.
233 },
234
235 getPlacementOfWidget: function(id)
236 {
237 let {UI} = require("ui");
238 let window = UI.currentWindow;
239 if (!window)
240 return null;
241
242 let widget = window.document.getElementById(id);
243 if (!widget)
244 return null;
245
246 let toolbar = getToolbar(widget);
247 if (!toolbar)
248 return null;
249
250 let items = toolbar.currentSet.split(",");
251 let index = items.indexOf(id);
252 if (index < 0)
253 return null;
254 else
255 return {area: toolbar.id, placement: index};
256 },
257
258 addWidgetToArea: function(id, area, position)
259 {
260 let {UI} = require("ui");
261 let widget = widgets.get(id);
262 for (let window of UI.applicationWindows)
263 {
264 let toolbox = getToolbox(window, widget);
265 if (!toolbox)
266 continue;
267
268 let position = toolbox.getAttribute(widget.positionAttribute);
269 if (position)
270 position = position.replace(/^hidden,/, "visible,");
271 showWidget(toolbox, widget, position);
272 }
273 },
274
275 removeWidgetFromArea: function(id)
276 {
277 let {UI} = require("ui");
278 let widget = widgets.get(id);
279 for (let window of UI.applicationWindows)
280 {
281 let toolbox = getToolbox(window, widget);
282 if (!toolbox)
283 continue;
284
285 let position = toolbox.getAttribute(widget.positionAttribute);
286 if (position)
287 position = position.replace(/^visible,/, "hidden,");
288 else
289 position = "hidden,,";
290 showWidget(toolbox, widget, position);
291 }
292 }
293 };
294
295 let {WindowObserver} = require("windowObserver");
296 new WindowObserver({
297 applyToWindow: function(window)
298 {
299 let {isKnownWindow} = require("appSupport");
300 if (!isKnownWindow(window))
301 return;
302
303 for (let [id, widget] of widgets)
304 {
305 let toolbox = getToolbox(window, widget);
306 if (toolbox)
307 {
308 toolbox.addEventListener("aftercustomization", onToolbarCustomization, f alse);
309
310 // Restore widget asynchronously to allow the stylesheet to load
311 Utils.runAsync(restoreWidget.bind(null, toolbox, widget));
312 }
313 }
314 },
315
316 removeFromWindow: function(window)
317 {
318 let {isKnownWindow} = require("appSupport");
319 if (!isKnownWindow(window))
320 return;
321
322 for (let [id, widget] of widgets)
323 {
324 let toolbox = getToolbox(window, widget);
325 if (toolbox)
326 toolbox.removeEventListener("aftercustomization", onToolbarCustomization , false);
327
328 removeWidget(window, widget);
329 }
330 }
331 });
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