toolkit/content/widgets/toolbar.xml

branch
TOR_BUG_3246
changeset 7
129ffea94266
equal deleted inserted replaced
-1:000000000000 0:954037b84ed4
1 <?xml version="1.0"?>
2 <!-- This Source Code Form is subject to the terms of the Mozilla Public
3 - License, v. 2.0. If a copy of the MPL was not distributed with this
4 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
5
6
7 <bindings id="toolbarBindings"
8 xmlns="http://www.mozilla.org/xbl"
9 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
10 xmlns:xbl="http://www.mozilla.org/xbl">
11
12 <binding id="toolbar-base">
13 <resources>
14 <stylesheet src="chrome://global/skin/toolbar.css"/>
15 </resources>
16 </binding>
17
18 <binding id="toolbox" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
19 <implementation>
20 <field name="palette">
21 null
22 </field>
23
24 <field name="toolbarset">
25 null
26 </field>
27
28 <field name="customToolbarCount">
29 0
30 </field>
31
32 <field name="externalToolbars">
33 []
34 </field>
35
36 <!-- Set by customizeToolbar.js -->
37 <property name="customizing">
38 <getter><![CDATA[
39 return this.getAttribute("customizing") == "true";
40 ]]></getter>
41 <setter><![CDATA[
42 if (val)
43 this.setAttribute("customizing", "true");
44 else
45 this.removeAttribute("customizing");
46 return val;
47 ]]></setter>
48 </property>
49
50 <constructor>
51 <![CDATA[
52 // Look to see if there is a toolbarset.
53 this.toolbarset = this.firstChild;
54 while (this.toolbarset && this.toolbarset.localName != "toolbarset")
55 this.toolbarset = toolbarset.nextSibling;
56
57 if (this.toolbarset) {
58 // Create each toolbar described by the toolbarset.
59 var index = 0;
60 while (toolbarset.hasAttribute("toolbar"+(++index))) {
61 var toolbarInfo = toolbarset.getAttribute("toolbar"+index);
62 var infoSplit = toolbarInfo.split(":");
63 this.appendCustomToolbar(infoSplit[0], infoSplit[1]);
64 }
65 }
66 ]]>
67 </constructor>
68
69 <method name="appendCustomToolbar">
70 <parameter name="aName"/>
71 <parameter name="aCurrentSet"/>
72 <body>
73 <![CDATA[
74 if (!this.toolbarset)
75 return null;
76 var toolbar = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
77 "toolbar");
78 toolbar.id = "__customToolbar_" + aName.replace(" ", "_");
79 toolbar.setAttribute("customizable", "true");
80 toolbar.setAttribute("customindex", ++this.customToolbarCount);
81 toolbar.setAttribute("toolbarname", aName);
82 toolbar.setAttribute("currentset", aCurrentSet);
83 toolbar.setAttribute("mode", this.getAttribute("mode"));
84 toolbar.setAttribute("iconsize", this.getAttribute("iconsize"));
85 toolbar.setAttribute("context", this.toolbarset.getAttribute("context"));
86 toolbar.setAttribute("class", "chromeclass-toolbar");
87
88 this.insertBefore(toolbar, this.toolbarset);
89 return toolbar;
90 ]]>
91 </body>
92 </method>
93 </implementation>
94 </binding>
95
96 <binding id="toolbar" role="xul:toolbar"
97 extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
98 <implementation>
99 <property name="toolbarName"
100 onget="return this.getAttribute('toolbarname');"
101 onset="this.setAttribute('toolbarname', val); return val;"/>
102
103 <field name="_toolbox">null</field>
104 <property name="toolbox" readonly="true">
105 <getter><![CDATA[
106 if (this._toolbox)
107 return this._toolbox;
108
109 let toolboxId = this.getAttribute("toolboxid");
110 if (toolboxId) {
111 let toolbox = document.getElementById(toolboxId);
112 if (!toolbox) {
113 let tbName = this.toolbarName;
114 if (tbName)
115 tbName = " (" + tbName + ")";
116 else
117 tbName = "";
118 throw("toolbar ID " + this.id + tbName + ": toolboxid attribute '" + toolboxId + "' points to a toolbox that doesn't exist");
119 }
120
121 if (toolbox.externalToolbars.indexOf(this) == -1)
122 toolbox.externalToolbars.push(this);
123
124 return this._toolbox = toolbox;
125 }
126
127 return this._toolbox = (this.parentNode &&
128 this.parentNode.localName == "toolbox") ?
129 this.parentNode : null;
130 ]]></getter>
131 </property>
132
133 <constructor>
134 <![CDATA[
135 if (document.readyState == "complete") {
136 this._init();
137 } else {
138 // Need to wait until XUL overlays are loaded. See bug 554279.
139 let self = this;
140 document.addEventListener("readystatechange", function (event) {
141 if (document.readyState != "complete")
142 return;
143 document.removeEventListener("readystatechange", arguments.callee, false);
144 self._init();
145 }, false);
146 }
147 ]]>
148 </constructor>
149
150 <method name="_init">
151 <body>
152 <![CDATA[
153 // Searching for the toolbox palette in the toolbar binding because
154 // toolbars are constructed first.
155 var toolbox = this.toolbox;
156 if (!toolbox)
157 return;
158
159 if (!toolbox.palette) {
160 // Look to see if there is a toolbarpalette.
161 var node = toolbox.firstChild;
162 while (node) {
163 if (node.localName == "toolbarpalette")
164 break;
165 node = node.nextSibling;
166 }
167
168 if (!node)
169 return;
170
171 // Hold on to the palette but remove it from the document.
172 toolbox.palette = node;
173 toolbox.removeChild(node);
174 }
175
176 // Build up our contents from the palette.
177 var currentSet = this.getAttribute("currentset");
178 if (!currentSet)
179 currentSet = this.getAttribute("defaultset");
180 if (currentSet)
181 this.currentSet = currentSet;
182 ]]>
183 </body>
184 </method>
185
186 <method name="_idFromNode">
187 <parameter name="aNode"/>
188 <body>
189 <![CDATA[
190 if (aNode.getAttribute("skipintoolbarset") == "true")
191 return "";
192
193 switch (aNode.localName) {
194 case "toolbarseparator":
195 return "separator";
196 case "toolbarspring":
197 return "spring";
198 case "toolbarspacer":
199 return "spacer";
200 default:
201 return aNode.id;
202 }
203 ]]>
204 </body>
205 </method>
206
207 <property name="currentSet">
208 <getter>
209 <![CDATA[
210 var node = this.firstChild;
211 var currentSet = [];
212 while (node) {
213 var id = this._idFromNode(node);
214 if (id) {
215 currentSet.push(id);
216 }
217 node = node.nextSibling;
218 }
219
220 return currentSet.join(",") || "__empty";
221 ]]>
222 </getter>
223
224 <setter>
225 <![CDATA[
226 if (val == this.currentSet)
227 return val;
228
229 var ids = (val == "__empty") ? [] : val.split(",");
230
231 var nodeidx = 0;
232 var paletteItems = { }, added = { };
233
234 var palette = this.toolbox ? this.toolbox.palette : null;
235
236 // build a cache of items in the toolbarpalette
237 var paletteChildren = palette ? palette.childNodes : [];
238 for (let c = 0; c < paletteChildren.length; c++) {
239 let curNode = paletteChildren[c];
240 paletteItems[curNode.id] = curNode;
241 }
242
243 var children = this.childNodes;
244
245 iter:
246 // iterate over the ids to use on the toolbar
247 for (let i = 0; i < ids.length; i++) {
248 let id = ids[i];
249 // iterate over the existing nodes on the toolbar. nodeidx is the
250 // spot where we want to insert items.
251 for (let c = nodeidx; c < children.length; c++) {
252 let curNode = children[c];
253 if (this._idFromNode(curNode) == id) {
254 // the node already exists. If c equals nodeidx, we haven't
255 // iterated yet, so the item is already in the right position.
256 // Otherwise, insert it here.
257 if (c != nodeidx) {
258 this.insertBefore(curNode, children[nodeidx]);
259 }
260
261 added[curNode.id] = true;
262 nodeidx++;
263 continue iter; // move on to the next id
264 }
265 }
266
267 // the node isn't already on the toolbar, so add a new one.
268 var nodeToAdd = paletteItems[id] || this._getToolbarItem(id);
269 if (nodeToAdd && !(nodeToAdd.id in added)) {
270 added[nodeToAdd.id] = true;
271 this.insertBefore(nodeToAdd, children[nodeidx] || null);
272 nodeToAdd.setAttribute("removable", "true");
273 nodeidx++;
274 }
275 }
276
277 // remove any leftover removable nodes
278 for (let i = children.length - 1; i >= nodeidx; i--) {
279 let curNode = children[i];
280
281 let curNodeId = this._idFromNode(curNode);
282 // skip over fixed items
283 if (curNodeId && curNode.getAttribute("removable") == "true") {
284 if (palette)
285 palette.appendChild(curNode);
286 else
287 this.removeChild(curNode);
288 }
289 }
290
291 return val;
292 ]]>
293 </setter>
294 </property>
295
296 <field name="_newElementCount">0</field>
297 <method name="_getToolbarItem">
298 <parameter name="aId"/>
299 <body>
300 <![CDATA[
301 const XUL_NS = "http://www.mozilla.org/keymaster/" +
302 "gatekeeper/there.is.only.xul";
303
304 var newItem = null;
305 switch (aId) {
306 // Handle special cases
307 case "separator":
308 case "spring":
309 case "spacer":
310 newItem = document.createElementNS(XUL_NS, "toolbar" + aId);
311 // Due to timers resolution Date.now() can be the same for
312 // elements created in small timeframes. So ids are
313 // differentiated through a unique count suffix.
314 newItem.id = aId + Date.now() + (++this._newElementCount);
315 if (aId == "spring")
316 newItem.flex = 1;
317 break;
318 default:
319 var toolbox = this.toolbox;
320 if (!toolbox)
321 break;
322
323 // look for an item with the same id, as the item may be
324 // in a different toolbar.
325 var item = document.getElementById(aId);
326 if (item && item.parentNode &&
327 item.parentNode.localName == "toolbar" &&
328 item.parentNode.toolbox == toolbox) {
329 newItem = item;
330 break;
331 }
332
333 if (toolbox.palette) {
334 // Attempt to locate an item with a matching ID within
335 // the palette.
336 let paletteItem = this.toolbox.palette.firstChild;
337 while (paletteItem) {
338 if (paletteItem.id == aId) {
339 newItem = paletteItem;
340 break;
341 }
342 paletteItem = paletteItem.nextSibling;
343 }
344 }
345 break;
346 }
347
348 return newItem;
349 ]]>
350 </body>
351 </method>
352
353 <method name="insertItem">
354 <parameter name="aId"/>
355 <parameter name="aBeforeElt"/>
356 <parameter name="aWrapper"/>
357 <body>
358 <![CDATA[
359 var newItem = this._getToolbarItem(aId);
360 if (!newItem)
361 return null;
362
363 var insertItem = newItem;
364 // make sure added items are removable
365 newItem.setAttribute("removable", "true");
366
367 // Wrap the item in another node if so inclined.
368 if (aWrapper) {
369 aWrapper.appendChild(newItem);
370 insertItem = aWrapper;
371 }
372
373 // Insert the palette item into the toolbar.
374 if (aBeforeElt)
375 this.insertBefore(insertItem, aBeforeElt);
376 else
377 this.appendChild(insertItem);
378
379 return newItem;
380 ]]>
381 </body>
382 </method>
383
384 <method name="hasCustomInteractiveItems">
385 <parameter name="aCurrentSet"/>
386 <body><![CDATA[
387 if (aCurrentSet == "__empty")
388 return false;
389
390 var defaultOrNoninteractive = (this.getAttribute("defaultset") || "")
391 .split(",")
392 .concat(["separator", "spacer", "spring"]);
393 return aCurrentSet.split(",").some(function (item) {
394 return defaultOrNoninteractive.indexOf(item) == -1;
395 });
396 ]]></body>
397 </method>
398 </implementation>
399 </binding>
400
401 <binding id="toolbar-menubar-autohide"
402 extends="chrome://global/content/bindings/toolbar.xml#toolbar">
403 <implementation>
404 <constructor>
405 this._setInactive();
406 </constructor>
407 <destructor>
408 this._setActive();
409 </destructor>
410
411 <field name="_inactiveTimeout">null</field>
412
413 <field name="_contextMenuListener"><![CDATA[({
414 toolbar: this,
415 contextMenu: null,
416
417 get active () !!this.contextMenu,
418
419 init: function (event) {
420 var node = event.target;
421 while (node != this.toolbar) {
422 if (node.localName == "menupopup")
423 return;
424 node = node.parentNode;
425 }
426
427 var contextMenuId = this.toolbar.getAttribute("context");
428 if (!contextMenuId)
429 return;
430
431 this.contextMenu = document.getElementById(contextMenuId);
432 if (!this.contextMenu)
433 return;
434
435 this.contextMenu.addEventListener("popupshown", this, false);
436 this.contextMenu.addEventListener("popuphiding", this, false);
437 this.toolbar.addEventListener("mousemove", this, false);
438 },
439 handleEvent: function (event) {
440 switch (event.type) {
441 case "popupshown":
442 this.toolbar.removeEventListener("mousemove", this, false);
443 break;
444 case "popuphiding":
445 case "mousemove":
446 this.toolbar._setInactiveAsync();
447 this.toolbar.removeEventListener("mousemove", this, false);
448 this.contextMenu.removeEventListener("popuphiding", this, false);
449 this.contextMenu.removeEventListener("popupshown", this, false);
450 this.contextMenu = null;
451 break;
452 }
453 }
454 })]]></field>
455
456 <method name="_setInactive">
457 <body><![CDATA[
458 this.setAttribute("inactive", "true");
459 ]]></body>
460 </method>
461
462 <method name="_setInactiveAsync">
463 <body><![CDATA[
464 this._inactiveTimeout = setTimeout(function (self) {
465 if (self.getAttribute("autohide") == "true") {
466 self._inactiveTimeout = null;
467 self._setInactive();
468 }
469 }, 0, this);
470 ]]></body>
471 </method>
472
473 <method name="_setActive">
474 <body><![CDATA[
475 if (this._inactiveTimeout) {
476 clearTimeout(this._inactiveTimeout);
477 this._inactiveTimeout = null;
478 }
479 this.removeAttribute("inactive");
480 ]]></body>
481 </method>
482 </implementation>
483
484 <handlers>
485 <handler event="DOMMenuBarActive" action="this._setActive();"/>
486 <handler event="popupshowing" action="this._setActive();"/>
487 <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
488 <handler event="DOMMenuBarInactive"><![CDATA[
489 if (!this._contextMenuListener.active)
490 this._setInactiveAsync();
491 ]]></handler>
492 </handlers>
493 </binding>
494
495 <binding id="toolbar-drag"
496 extends="chrome://global/content/bindings/toolbar.xml#toolbar">
497 <implementation>
498 <field name="_dragBindingAlive">true</field>
499 <constructor><![CDATA[
500 if (!this._draggableStarted) {
501 this._draggableStarted = true;
502 try {
503 let tmp = {};
504 Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
505 let draggableThis = new tmp.WindowDraggingElement(this);
506 draggableThis.mouseDownCheck = function(e) {
507 // Don't move while customizing.
508 return this._dragBindingAlive &&
509 this.getAttribute("customizing") != "true";
510 };
511 } catch (e) {}
512 }
513 ]]></constructor>
514 </implementation>
515 </binding>
516
517 <binding id="menubar" role="xul:menubar"
518 extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:menubar">
519 <implementation>
520 <field name="_active">false</field>
521 <field name="_statusbar">null</field>
522 <field name="_originalStatusText">null</field>
523 <property name="statusbar" onget="return this.getAttribute('statusbar');"
524 onset="this.setAttribute('statusbar', val); return val;"/>
525 <method name="_updateStatusText">
526 <parameter name="itemText"/>
527 <body>
528 <![CDATA[
529 if (!this._active)
530 return;
531 var newText = itemText ? itemText : this._originalStatusText;
532 if (newText != this._statusbar.label)
533 this._statusbar.label = newText;
534 ]]>
535 </body>
536 </method>
537 </implementation>
538 <handlers>
539 <handler event="DOMMenuBarActive">
540 <![CDATA[
541 if (!this.statusbar) return;
542 this._statusbar = document.getElementById(this.statusbar);
543 if (!this._statusbar)
544 return;
545 this._active = true;
546 this._originalStatusText = this._statusbar.label;
547 ]]>
548 </handler>
549 <handler event="DOMMenuBarInactive">
550 <![CDATA[
551 if (!this._active)
552 return;
553 this._active = false;
554 this._statusbar.label = this._originalStatusText;
555 ]]>
556 </handler>
557 <handler event="DOMMenuItemActive">this._updateStatusText(event.target.statusText);</handler>
558 <handler event="DOMMenuItemInactive">this._updateStatusText("");</handler>
559 </handlers>
560 </binding>
561
562 <binding id="toolbardecoration" role="xul:toolbarseparator" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
563 </binding>
564
565 <binding id="toolbarpaletteitem" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:button">
566 <content>
567 <xul:hbox class="toolbarpaletteitem-box" flex="1" xbl:inherits="type,place">
568 <children/>
569 </xul:hbox>
570 </content>
571 </binding>
572
573 <binding id="toolbarpaletteitem-palette" extends="chrome://global/content/bindings/toolbar.xml#toolbarpaletteitem">
574 <content>
575 <xul:hbox class="toolbarpaletteitem-box" xbl:inherits="type,place">
576 <children/>
577 </xul:hbox>
578 <xul:label xbl:inherits="value=title"/>
579 </content>
580 </binding>
581
582 </bindings>
583

mercurial