1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/content/widgets/toolbar.xml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,583 @@ 1.4 +<?xml version="1.0"?> 1.5 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.6 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.8 + 1.9 + 1.10 +<bindings id="toolbarBindings" 1.11 + xmlns="http://www.mozilla.org/xbl" 1.12 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.13 + xmlns:xbl="http://www.mozilla.org/xbl"> 1.14 + 1.15 + <binding id="toolbar-base"> 1.16 + <resources> 1.17 + <stylesheet src="chrome://global/skin/toolbar.css"/> 1.18 + </resources> 1.19 + </binding> 1.20 + 1.21 + <binding id="toolbox" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base"> 1.22 + <implementation> 1.23 + <field name="palette"> 1.24 + null 1.25 + </field> 1.26 + 1.27 + <field name="toolbarset"> 1.28 + null 1.29 + </field> 1.30 + 1.31 + <field name="customToolbarCount"> 1.32 + 0 1.33 + </field> 1.34 + 1.35 + <field name="externalToolbars"> 1.36 + [] 1.37 + </field> 1.38 + 1.39 + <!-- Set by customizeToolbar.js --> 1.40 + <property name="customizing"> 1.41 + <getter><![CDATA[ 1.42 + return this.getAttribute("customizing") == "true"; 1.43 + ]]></getter> 1.44 + <setter><![CDATA[ 1.45 + if (val) 1.46 + this.setAttribute("customizing", "true"); 1.47 + else 1.48 + this.removeAttribute("customizing"); 1.49 + return val; 1.50 + ]]></setter> 1.51 + </property> 1.52 + 1.53 + <constructor> 1.54 + <![CDATA[ 1.55 + // Look to see if there is a toolbarset. 1.56 + this.toolbarset = this.firstChild; 1.57 + while (this.toolbarset && this.toolbarset.localName != "toolbarset") 1.58 + this.toolbarset = toolbarset.nextSibling; 1.59 + 1.60 + if (this.toolbarset) { 1.61 + // Create each toolbar described by the toolbarset. 1.62 + var index = 0; 1.63 + while (toolbarset.hasAttribute("toolbar"+(++index))) { 1.64 + var toolbarInfo = toolbarset.getAttribute("toolbar"+index); 1.65 + var infoSplit = toolbarInfo.split(":"); 1.66 + this.appendCustomToolbar(infoSplit[0], infoSplit[1]); 1.67 + } 1.68 + } 1.69 + ]]> 1.70 + </constructor> 1.71 + 1.72 + <method name="appendCustomToolbar"> 1.73 + <parameter name="aName"/> 1.74 + <parameter name="aCurrentSet"/> 1.75 + <body> 1.76 + <![CDATA[ 1.77 + if (!this.toolbarset) 1.78 + return null; 1.79 + var toolbar = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", 1.80 + "toolbar"); 1.81 + toolbar.id = "__customToolbar_" + aName.replace(" ", "_"); 1.82 + toolbar.setAttribute("customizable", "true"); 1.83 + toolbar.setAttribute("customindex", ++this.customToolbarCount); 1.84 + toolbar.setAttribute("toolbarname", aName); 1.85 + toolbar.setAttribute("currentset", aCurrentSet); 1.86 + toolbar.setAttribute("mode", this.getAttribute("mode")); 1.87 + toolbar.setAttribute("iconsize", this.getAttribute("iconsize")); 1.88 + toolbar.setAttribute("context", this.toolbarset.getAttribute("context")); 1.89 + toolbar.setAttribute("class", "chromeclass-toolbar"); 1.90 + 1.91 + this.insertBefore(toolbar, this.toolbarset); 1.92 + return toolbar; 1.93 + ]]> 1.94 + </body> 1.95 + </method> 1.96 + </implementation> 1.97 + </binding> 1.98 + 1.99 + <binding id="toolbar" role="xul:toolbar" 1.100 + extends="chrome://global/content/bindings/toolbar.xml#toolbar-base"> 1.101 + <implementation> 1.102 + <property name="toolbarName" 1.103 + onget="return this.getAttribute('toolbarname');" 1.104 + onset="this.setAttribute('toolbarname', val); return val;"/> 1.105 + 1.106 + <field name="_toolbox">null</field> 1.107 + <property name="toolbox" readonly="true"> 1.108 + <getter><![CDATA[ 1.109 + if (this._toolbox) 1.110 + return this._toolbox; 1.111 + 1.112 + let toolboxId = this.getAttribute("toolboxid"); 1.113 + if (toolboxId) { 1.114 + let toolbox = document.getElementById(toolboxId); 1.115 + if (!toolbox) { 1.116 + let tbName = this.toolbarName; 1.117 + if (tbName) 1.118 + tbName = " (" + tbName + ")"; 1.119 + else 1.120 + tbName = ""; 1.121 + throw("toolbar ID " + this.id + tbName + ": toolboxid attribute '" + toolboxId + "' points to a toolbox that doesn't exist"); 1.122 + } 1.123 + 1.124 + if (toolbox.externalToolbars.indexOf(this) == -1) 1.125 + toolbox.externalToolbars.push(this); 1.126 + 1.127 + return this._toolbox = toolbox; 1.128 + } 1.129 + 1.130 + return this._toolbox = (this.parentNode && 1.131 + this.parentNode.localName == "toolbox") ? 1.132 + this.parentNode : null; 1.133 + ]]></getter> 1.134 + </property> 1.135 + 1.136 + <constructor> 1.137 + <![CDATA[ 1.138 + if (document.readyState == "complete") { 1.139 + this._init(); 1.140 + } else { 1.141 + // Need to wait until XUL overlays are loaded. See bug 554279. 1.142 + let self = this; 1.143 + document.addEventListener("readystatechange", function (event) { 1.144 + if (document.readyState != "complete") 1.145 + return; 1.146 + document.removeEventListener("readystatechange", arguments.callee, false); 1.147 + self._init(); 1.148 + }, false); 1.149 + } 1.150 + ]]> 1.151 + </constructor> 1.152 + 1.153 + <method name="_init"> 1.154 + <body> 1.155 + <![CDATA[ 1.156 + // Searching for the toolbox palette in the toolbar binding because 1.157 + // toolbars are constructed first. 1.158 + var toolbox = this.toolbox; 1.159 + if (!toolbox) 1.160 + return; 1.161 + 1.162 + if (!toolbox.palette) { 1.163 + // Look to see if there is a toolbarpalette. 1.164 + var node = toolbox.firstChild; 1.165 + while (node) { 1.166 + if (node.localName == "toolbarpalette") 1.167 + break; 1.168 + node = node.nextSibling; 1.169 + } 1.170 + 1.171 + if (!node) 1.172 + return; 1.173 + 1.174 + // Hold on to the palette but remove it from the document. 1.175 + toolbox.palette = node; 1.176 + toolbox.removeChild(node); 1.177 + } 1.178 + 1.179 + // Build up our contents from the palette. 1.180 + var currentSet = this.getAttribute("currentset"); 1.181 + if (!currentSet) 1.182 + currentSet = this.getAttribute("defaultset"); 1.183 + if (currentSet) 1.184 + this.currentSet = currentSet; 1.185 + ]]> 1.186 + </body> 1.187 + </method> 1.188 + 1.189 + <method name="_idFromNode"> 1.190 + <parameter name="aNode"/> 1.191 + <body> 1.192 + <![CDATA[ 1.193 + if (aNode.getAttribute("skipintoolbarset") == "true") 1.194 + return ""; 1.195 + 1.196 + switch (aNode.localName) { 1.197 + case "toolbarseparator": 1.198 + return "separator"; 1.199 + case "toolbarspring": 1.200 + return "spring"; 1.201 + case "toolbarspacer": 1.202 + return "spacer"; 1.203 + default: 1.204 + return aNode.id; 1.205 + } 1.206 + ]]> 1.207 + </body> 1.208 + </method> 1.209 + 1.210 + <property name="currentSet"> 1.211 + <getter> 1.212 + <![CDATA[ 1.213 + var node = this.firstChild; 1.214 + var currentSet = []; 1.215 + while (node) { 1.216 + var id = this._idFromNode(node); 1.217 + if (id) { 1.218 + currentSet.push(id); 1.219 + } 1.220 + node = node.nextSibling; 1.221 + } 1.222 + 1.223 + return currentSet.join(",") || "__empty"; 1.224 + ]]> 1.225 + </getter> 1.226 + 1.227 + <setter> 1.228 + <![CDATA[ 1.229 + if (val == this.currentSet) 1.230 + return val; 1.231 + 1.232 + var ids = (val == "__empty") ? [] : val.split(","); 1.233 + 1.234 + var nodeidx = 0; 1.235 + var paletteItems = { }, added = { }; 1.236 + 1.237 + var palette = this.toolbox ? this.toolbox.palette : null; 1.238 + 1.239 + // build a cache of items in the toolbarpalette 1.240 + var paletteChildren = palette ? palette.childNodes : []; 1.241 + for (let c = 0; c < paletteChildren.length; c++) { 1.242 + let curNode = paletteChildren[c]; 1.243 + paletteItems[curNode.id] = curNode; 1.244 + } 1.245 + 1.246 + var children = this.childNodes; 1.247 + 1.248 + iter: 1.249 + // iterate over the ids to use on the toolbar 1.250 + for (let i = 0; i < ids.length; i++) { 1.251 + let id = ids[i]; 1.252 + // iterate over the existing nodes on the toolbar. nodeidx is the 1.253 + // spot where we want to insert items. 1.254 + for (let c = nodeidx; c < children.length; c++) { 1.255 + let curNode = children[c]; 1.256 + if (this._idFromNode(curNode) == id) { 1.257 + // the node already exists. If c equals nodeidx, we haven't 1.258 + // iterated yet, so the item is already in the right position. 1.259 + // Otherwise, insert it here. 1.260 + if (c != nodeidx) { 1.261 + this.insertBefore(curNode, children[nodeidx]); 1.262 + } 1.263 + 1.264 + added[curNode.id] = true; 1.265 + nodeidx++; 1.266 + continue iter; // move on to the next id 1.267 + } 1.268 + } 1.269 + 1.270 + // the node isn't already on the toolbar, so add a new one. 1.271 + var nodeToAdd = paletteItems[id] || this._getToolbarItem(id); 1.272 + if (nodeToAdd && !(nodeToAdd.id in added)) { 1.273 + added[nodeToAdd.id] = true; 1.274 + this.insertBefore(nodeToAdd, children[nodeidx] || null); 1.275 + nodeToAdd.setAttribute("removable", "true"); 1.276 + nodeidx++; 1.277 + } 1.278 + } 1.279 + 1.280 + // remove any leftover removable nodes 1.281 + for (let i = children.length - 1; i >= nodeidx; i--) { 1.282 + let curNode = children[i]; 1.283 + 1.284 + let curNodeId = this._idFromNode(curNode); 1.285 + // skip over fixed items 1.286 + if (curNodeId && curNode.getAttribute("removable") == "true") { 1.287 + if (palette) 1.288 + palette.appendChild(curNode); 1.289 + else 1.290 + this.removeChild(curNode); 1.291 + } 1.292 + } 1.293 + 1.294 + return val; 1.295 + ]]> 1.296 + </setter> 1.297 + </property> 1.298 + 1.299 + <field name="_newElementCount">0</field> 1.300 + <method name="_getToolbarItem"> 1.301 + <parameter name="aId"/> 1.302 + <body> 1.303 + <![CDATA[ 1.304 + const XUL_NS = "http://www.mozilla.org/keymaster/" + 1.305 + "gatekeeper/there.is.only.xul"; 1.306 + 1.307 + var newItem = null; 1.308 + switch (aId) { 1.309 + // Handle special cases 1.310 + case "separator": 1.311 + case "spring": 1.312 + case "spacer": 1.313 + newItem = document.createElementNS(XUL_NS, "toolbar" + aId); 1.314 + // Due to timers resolution Date.now() can be the same for 1.315 + // elements created in small timeframes. So ids are 1.316 + // differentiated through a unique count suffix. 1.317 + newItem.id = aId + Date.now() + (++this._newElementCount); 1.318 + if (aId == "spring") 1.319 + newItem.flex = 1; 1.320 + break; 1.321 + default: 1.322 + var toolbox = this.toolbox; 1.323 + if (!toolbox) 1.324 + break; 1.325 + 1.326 + // look for an item with the same id, as the item may be 1.327 + // in a different toolbar. 1.328 + var item = document.getElementById(aId); 1.329 + if (item && item.parentNode && 1.330 + item.parentNode.localName == "toolbar" && 1.331 + item.parentNode.toolbox == toolbox) { 1.332 + newItem = item; 1.333 + break; 1.334 + } 1.335 + 1.336 + if (toolbox.palette) { 1.337 + // Attempt to locate an item with a matching ID within 1.338 + // the palette. 1.339 + let paletteItem = this.toolbox.palette.firstChild; 1.340 + while (paletteItem) { 1.341 + if (paletteItem.id == aId) { 1.342 + newItem = paletteItem; 1.343 + break; 1.344 + } 1.345 + paletteItem = paletteItem.nextSibling; 1.346 + } 1.347 + } 1.348 + break; 1.349 + } 1.350 + 1.351 + return newItem; 1.352 + ]]> 1.353 + </body> 1.354 + </method> 1.355 + 1.356 + <method name="insertItem"> 1.357 + <parameter name="aId"/> 1.358 + <parameter name="aBeforeElt"/> 1.359 + <parameter name="aWrapper"/> 1.360 + <body> 1.361 + <![CDATA[ 1.362 + var newItem = this._getToolbarItem(aId); 1.363 + if (!newItem) 1.364 + return null; 1.365 + 1.366 + var insertItem = newItem; 1.367 + // make sure added items are removable 1.368 + newItem.setAttribute("removable", "true"); 1.369 + 1.370 + // Wrap the item in another node if so inclined. 1.371 + if (aWrapper) { 1.372 + aWrapper.appendChild(newItem); 1.373 + insertItem = aWrapper; 1.374 + } 1.375 + 1.376 + // Insert the palette item into the toolbar. 1.377 + if (aBeforeElt) 1.378 + this.insertBefore(insertItem, aBeforeElt); 1.379 + else 1.380 + this.appendChild(insertItem); 1.381 + 1.382 + return newItem; 1.383 + ]]> 1.384 + </body> 1.385 + </method> 1.386 + 1.387 + <method name="hasCustomInteractiveItems"> 1.388 + <parameter name="aCurrentSet"/> 1.389 + <body><![CDATA[ 1.390 + if (aCurrentSet == "__empty") 1.391 + return false; 1.392 + 1.393 + var defaultOrNoninteractive = (this.getAttribute("defaultset") || "") 1.394 + .split(",") 1.395 + .concat(["separator", "spacer", "spring"]); 1.396 + return aCurrentSet.split(",").some(function (item) { 1.397 + return defaultOrNoninteractive.indexOf(item) == -1; 1.398 + }); 1.399 + ]]></body> 1.400 + </method> 1.401 + </implementation> 1.402 + </binding> 1.403 + 1.404 + <binding id="toolbar-menubar-autohide" 1.405 + extends="chrome://global/content/bindings/toolbar.xml#toolbar"> 1.406 + <implementation> 1.407 + <constructor> 1.408 + this._setInactive(); 1.409 + </constructor> 1.410 + <destructor> 1.411 + this._setActive(); 1.412 + </destructor> 1.413 + 1.414 + <field name="_inactiveTimeout">null</field> 1.415 + 1.416 + <field name="_contextMenuListener"><![CDATA[({ 1.417 + toolbar: this, 1.418 + contextMenu: null, 1.419 + 1.420 + get active () !!this.contextMenu, 1.421 + 1.422 + init: function (event) { 1.423 + var node = event.target; 1.424 + while (node != this.toolbar) { 1.425 + if (node.localName == "menupopup") 1.426 + return; 1.427 + node = node.parentNode; 1.428 + } 1.429 + 1.430 + var contextMenuId = this.toolbar.getAttribute("context"); 1.431 + if (!contextMenuId) 1.432 + return; 1.433 + 1.434 + this.contextMenu = document.getElementById(contextMenuId); 1.435 + if (!this.contextMenu) 1.436 + return; 1.437 + 1.438 + this.contextMenu.addEventListener("popupshown", this, false); 1.439 + this.contextMenu.addEventListener("popuphiding", this, false); 1.440 + this.toolbar.addEventListener("mousemove", this, false); 1.441 + }, 1.442 + handleEvent: function (event) { 1.443 + switch (event.type) { 1.444 + case "popupshown": 1.445 + this.toolbar.removeEventListener("mousemove", this, false); 1.446 + break; 1.447 + case "popuphiding": 1.448 + case "mousemove": 1.449 + this.toolbar._setInactiveAsync(); 1.450 + this.toolbar.removeEventListener("mousemove", this, false); 1.451 + this.contextMenu.removeEventListener("popuphiding", this, false); 1.452 + this.contextMenu.removeEventListener("popupshown", this, false); 1.453 + this.contextMenu = null; 1.454 + break; 1.455 + } 1.456 + } 1.457 + })]]></field> 1.458 + 1.459 + <method name="_setInactive"> 1.460 + <body><![CDATA[ 1.461 + this.setAttribute("inactive", "true"); 1.462 + ]]></body> 1.463 + </method> 1.464 + 1.465 + <method name="_setInactiveAsync"> 1.466 + <body><![CDATA[ 1.467 + this._inactiveTimeout = setTimeout(function (self) { 1.468 + if (self.getAttribute("autohide") == "true") { 1.469 + self._inactiveTimeout = null; 1.470 + self._setInactive(); 1.471 + } 1.472 + }, 0, this); 1.473 + ]]></body> 1.474 + </method> 1.475 + 1.476 + <method name="_setActive"> 1.477 + <body><![CDATA[ 1.478 + if (this._inactiveTimeout) { 1.479 + clearTimeout(this._inactiveTimeout); 1.480 + this._inactiveTimeout = null; 1.481 + } 1.482 + this.removeAttribute("inactive"); 1.483 + ]]></body> 1.484 + </method> 1.485 + </implementation> 1.486 + 1.487 + <handlers> 1.488 + <handler event="DOMMenuBarActive" action="this._setActive();"/> 1.489 + <handler event="popupshowing" action="this._setActive();"/> 1.490 + <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/> 1.491 + <handler event="DOMMenuBarInactive"><![CDATA[ 1.492 + if (!this._contextMenuListener.active) 1.493 + this._setInactiveAsync(); 1.494 + ]]></handler> 1.495 + </handlers> 1.496 + </binding> 1.497 + 1.498 + <binding id="toolbar-drag" 1.499 + extends="chrome://global/content/bindings/toolbar.xml#toolbar"> 1.500 + <implementation> 1.501 + <field name="_dragBindingAlive">true</field> 1.502 + <constructor><![CDATA[ 1.503 + if (!this._draggableStarted) { 1.504 + this._draggableStarted = true; 1.505 + try { 1.506 + let tmp = {}; 1.507 + Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp); 1.508 + let draggableThis = new tmp.WindowDraggingElement(this); 1.509 + draggableThis.mouseDownCheck = function(e) { 1.510 + // Don't move while customizing. 1.511 + return this._dragBindingAlive && 1.512 + this.getAttribute("customizing") != "true"; 1.513 + }; 1.514 + } catch (e) {} 1.515 + } 1.516 + ]]></constructor> 1.517 + </implementation> 1.518 + </binding> 1.519 + 1.520 + <binding id="menubar" role="xul:menubar" 1.521 + extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:menubar"> 1.522 + <implementation> 1.523 + <field name="_active">false</field> 1.524 + <field name="_statusbar">null</field> 1.525 + <field name="_originalStatusText">null</field> 1.526 + <property name="statusbar" onget="return this.getAttribute('statusbar');" 1.527 + onset="this.setAttribute('statusbar', val); return val;"/> 1.528 + <method name="_updateStatusText"> 1.529 + <parameter name="itemText"/> 1.530 + <body> 1.531 + <![CDATA[ 1.532 + if (!this._active) 1.533 + return; 1.534 + var newText = itemText ? itemText : this._originalStatusText; 1.535 + if (newText != this._statusbar.label) 1.536 + this._statusbar.label = newText; 1.537 + ]]> 1.538 + </body> 1.539 + </method> 1.540 + </implementation> 1.541 + <handlers> 1.542 + <handler event="DOMMenuBarActive"> 1.543 + <![CDATA[ 1.544 + if (!this.statusbar) return; 1.545 + this._statusbar = document.getElementById(this.statusbar); 1.546 + if (!this._statusbar) 1.547 + return; 1.548 + this._active = true; 1.549 + this._originalStatusText = this._statusbar.label; 1.550 + ]]> 1.551 + </handler> 1.552 + <handler event="DOMMenuBarInactive"> 1.553 + <![CDATA[ 1.554 + if (!this._active) 1.555 + return; 1.556 + this._active = false; 1.557 + this._statusbar.label = this._originalStatusText; 1.558 + ]]> 1.559 + </handler> 1.560 + <handler event="DOMMenuItemActive">this._updateStatusText(event.target.statusText);</handler> 1.561 + <handler event="DOMMenuItemInactive">this._updateStatusText("");</handler> 1.562 + </handlers> 1.563 + </binding> 1.564 + 1.565 + <binding id="toolbardecoration" role="xul:toolbarseparator" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base"> 1.566 + </binding> 1.567 + 1.568 + <binding id="toolbarpaletteitem" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:button"> 1.569 + <content> 1.570 + <xul:hbox class="toolbarpaletteitem-box" flex="1" xbl:inherits="type,place"> 1.571 + <children/> 1.572 + </xul:hbox> 1.573 + </content> 1.574 + </binding> 1.575 + 1.576 + <binding id="toolbarpaletteitem-palette" extends="chrome://global/content/bindings/toolbar.xml#toolbarpaletteitem"> 1.577 + <content> 1.578 + <xul:hbox class="toolbarpaletteitem-box" xbl:inherits="type,place"> 1.579 + <children/> 1.580 + </xul:hbox> 1.581 + <xul:label xbl:inherits="value=title"/> 1.582 + </content> 1.583 + </binding> 1.584 + 1.585 +</bindings> 1.586 +