summaryrefslogtreecommitdiffstats
path: root/toolkit/content/widgets/toolbar.xml
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/content/widgets/toolbar.xml')
-rw-r--r--toolkit/content/widgets/toolbar.xml590
1 files changed, 590 insertions, 0 deletions
diff --git a/toolkit/content/widgets/toolbar.xml b/toolkit/content/widgets/toolbar.xml
new file mode 100644
index 000000000..548504e24
--- /dev/null
+++ b/toolkit/content/widgets/toolbar.xml
@@ -0,0 +1,590 @@
+<?xml version="1.0"?>
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+
+<bindings id="toolbarBindings"
+ xmlns="http://www.mozilla.org/xbl"
+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+ xmlns:xbl="http://www.mozilla.org/xbl">
+
+ <binding id="toolbar-base">
+ <resources>
+ <stylesheet src="chrome://global/skin/toolbar.css"/>
+ </resources>
+ </binding>
+
+ <binding id="toolbox" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
+ <implementation>
+ <field name="palette">
+ null
+ </field>
+
+ <field name="toolbarset">
+ null
+ </field>
+
+ <field name="customToolbarCount">
+ 0
+ </field>
+
+ <field name="externalToolbars">
+ []
+ </field>
+
+ <!-- Set by customizeToolbar.js -->
+ <property name="customizing">
+ <getter><![CDATA[
+ return this.getAttribute("customizing") == "true";
+ ]]></getter>
+ <setter><![CDATA[
+ if (val)
+ this.setAttribute("customizing", "true");
+ else
+ this.removeAttribute("customizing");
+ return val;
+ ]]></setter>
+ </property>
+
+ <constructor>
+ <![CDATA[
+ // Look to see if there is a toolbarset.
+ this.toolbarset = this.firstChild;
+ while (this.toolbarset && this.toolbarset.localName != "toolbarset")
+ this.toolbarset = toolbarset.nextSibling;
+
+ if (this.toolbarset) {
+ // Create each toolbar described by the toolbarset.
+ var index = 0;
+ while (toolbarset.hasAttribute("toolbar"+(++index))) {
+ var toolbarInfo = toolbarset.getAttribute("toolbar"+index);
+ var infoSplit = toolbarInfo.split(":");
+ this.appendCustomToolbar(infoSplit[0], infoSplit[1]);
+ }
+ }
+ ]]>
+ </constructor>
+
+ <method name="appendCustomToolbar">
+ <parameter name="aName"/>
+ <parameter name="aCurrentSet"/>
+ <body>
+ <![CDATA[
+ if (!this.toolbarset)
+ return null;
+ var toolbar = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ "toolbar");
+ toolbar.id = "__customToolbar_" + aName.replace(" ", "_");
+ toolbar.setAttribute("customizable", "true");
+ toolbar.setAttribute("customindex", ++this.customToolbarCount);
+ toolbar.setAttribute("toolbarname", aName);
+ toolbar.setAttribute("currentset", aCurrentSet);
+ toolbar.setAttribute("mode", this.getAttribute("mode"));
+ toolbar.setAttribute("iconsize", this.getAttribute("iconsize"));
+ toolbar.setAttribute("context", this.toolbarset.getAttribute("context"));
+ toolbar.setAttribute("class", "chromeclass-toolbar");
+
+ this.insertBefore(toolbar, this.toolbarset);
+ return toolbar;
+ ]]>
+ </body>
+ </method>
+ </implementation>
+ </binding>
+
+ <binding id="toolbar" role="xul:toolbar"
+ extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
+ <implementation>
+ <property name="toolbarName"
+ onget="return this.getAttribute('toolbarname');"
+ onset="this.setAttribute('toolbarname', val); return val;"/>
+
+ <field name="_toolbox">null</field>
+ <property name="toolbox" readonly="true">
+ <getter><![CDATA[
+ if (this._toolbox)
+ return this._toolbox;
+
+ let toolboxId = this.getAttribute("toolboxid");
+ if (toolboxId) {
+ let toolbox = document.getElementById(toolboxId);
+ if (!toolbox) {
+ let tbName = this.toolbarName;
+ if (tbName)
+ tbName = " (" + tbName + ")";
+ else
+ tbName = "";
+ throw new Error(`toolbar ID ${this.id}${tbName}: toolboxid attribute '${toolboxId}' points to a toolbox that doesn't exist`);
+ }
+
+ if (toolbox.externalToolbars.indexOf(this) == -1)
+ toolbox.externalToolbars.push(this);
+
+ return this._toolbox = toolbox;
+ }
+
+ return this._toolbox = (this.parentNode &&
+ this.parentNode.localName == "toolbox") ?
+ this.parentNode : null;
+ ]]></getter>
+ </property>
+
+ <constructor>
+ <![CDATA[
+ if (document.readyState == "complete") {
+ this._init();
+ } else {
+ // Need to wait until XUL overlays are loaded. See bug 554279.
+ let self = this;
+ document.addEventListener("readystatechange", function (event) {
+ if (document.readyState != "complete")
+ return;
+ document.removeEventListener("readystatechange", arguments.callee, false);
+ self._init();
+ }, false);
+ }
+ ]]>
+ </constructor>
+
+ <method name="_init">
+ <body>
+ <![CDATA[
+ // Searching for the toolbox palette in the toolbar binding because
+ // toolbars are constructed first.
+ var toolbox = this.toolbox;
+ if (!toolbox)
+ return;
+
+ if (!toolbox.palette) {
+ // Look to see if there is a toolbarpalette.
+ var node = toolbox.firstChild;
+ while (node) {
+ if (node.localName == "toolbarpalette")
+ break;
+ node = node.nextSibling;
+ }
+
+ if (!node)
+ return;
+
+ // Hold on to the palette but remove it from the document.
+ toolbox.palette = node;
+ toolbox.removeChild(node);
+ }
+
+ // Build up our contents from the palette.
+ var currentSet = this.getAttribute("currentset");
+ if (!currentSet)
+ currentSet = this.getAttribute("defaultset");
+ if (currentSet)
+ this.currentSet = currentSet;
+ ]]>
+ </body>
+ </method>
+
+ <method name="_idFromNode">
+ <parameter name="aNode"/>
+ <body>
+ <![CDATA[
+ if (aNode.getAttribute("skipintoolbarset") == "true")
+ return "";
+
+ switch (aNode.localName) {
+ case "toolbarseparator":
+ return "separator";
+ case "toolbarspring":
+ return "spring";
+ case "toolbarspacer":
+ return "spacer";
+ default:
+ return aNode.id;
+ }
+ ]]>
+ </body>
+ </method>
+
+ <property name="currentSet">
+ <getter>
+ <![CDATA[
+ var node = this.firstChild;
+ var currentSet = [];
+ while (node) {
+ var id = this._idFromNode(node);
+ if (id) {
+ currentSet.push(id);
+ }
+ node = node.nextSibling;
+ }
+
+ return currentSet.join(",") || "__empty";
+ ]]>
+ </getter>
+
+ <setter>
+ <![CDATA[
+ if (val == this.currentSet)
+ return val;
+
+ var ids = (val == "__empty") ? [] : val.split(",");
+
+ var nodeidx = 0;
+ var paletteItems = { }, added = { };
+
+ var palette = this.toolbox ? this.toolbox.palette : null;
+
+ // build a cache of items in the toolbarpalette
+ var paletteChildren = palette ? palette.childNodes : [];
+ for (let c = 0; c < paletteChildren.length; c++) {
+ let curNode = paletteChildren[c];
+ paletteItems[curNode.id] = curNode;
+ }
+
+ var children = this.childNodes;
+
+ // iterate over the ids to use on the toolbar
+ for (let i = 0; i < ids.length; i++) {
+ let id = ids[i];
+ // iterate over the existing nodes on the toolbar. nodeidx is the
+ // spot where we want to insert items.
+ let found = false;
+ for (let c = nodeidx; c < children.length; c++) {
+ let curNode = children[c];
+ if (this._idFromNode(curNode) == id) {
+ // the node already exists. If c equals nodeidx, we haven't
+ // iterated yet, so the item is already in the right position.
+ // Otherwise, insert it here.
+ if (c != nodeidx) {
+ this.insertBefore(curNode, children[nodeidx]);
+ }
+
+ added[curNode.id] = true;
+ nodeidx++;
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ // move on to the next id
+ continue;
+ }
+
+ // the node isn't already on the toolbar, so add a new one.
+ var nodeToAdd = paletteItems[id] || this._getToolbarItem(id);
+ if (nodeToAdd && !(nodeToAdd.id in added)) {
+ added[nodeToAdd.id] = true;
+ this.insertBefore(nodeToAdd, children[nodeidx] || null);
+ nodeToAdd.setAttribute("removable", "true");
+ nodeidx++;
+ }
+ }
+
+ // remove any leftover removable nodes
+ for (let i = children.length - 1; i >= nodeidx; i--) {
+ let curNode = children[i];
+
+ let curNodeId = this._idFromNode(curNode);
+ // skip over fixed items
+ if (curNodeId && curNode.getAttribute("removable") == "true") {
+ if (palette)
+ palette.appendChild(curNode);
+ else
+ this.removeChild(curNode);
+ }
+ }
+
+ return val;
+ ]]>
+ </setter>
+ </property>
+
+ <field name="_newElementCount">0</field>
+ <method name="_getToolbarItem">
+ <parameter name="aId"/>
+ <body>
+ <![CDATA[
+ const XUL_NS = "http://www.mozilla.org/keymaster/" +
+ "gatekeeper/there.is.only.xul";
+
+ var newItem = null;
+ switch (aId) {
+ // Handle special cases
+ case "separator":
+ case "spring":
+ case "spacer":
+ newItem = document.createElementNS(XUL_NS, "toolbar" + aId);
+ // Due to timers resolution Date.now() can be the same for
+ // elements created in small timeframes. So ids are
+ // differentiated through a unique count suffix.
+ newItem.id = aId + Date.now() + (++this._newElementCount);
+ if (aId == "spring")
+ newItem.flex = 1;
+ break;
+ default:
+ var toolbox = this.toolbox;
+ if (!toolbox)
+ break;
+
+ // look for an item with the same id, as the item may be
+ // in a different toolbar.
+ var item = document.getElementById(aId);
+ if (item && item.parentNode &&
+ item.parentNode.localName == "toolbar" &&
+ item.parentNode.toolbox == toolbox) {
+ newItem = item;
+ break;
+ }
+
+ if (toolbox.palette) {
+ // Attempt to locate an item with a matching ID within
+ // the palette.
+ let paletteItem = this.toolbox.palette.firstChild;
+ while (paletteItem) {
+ if (paletteItem.id == aId) {
+ newItem = paletteItem;
+ break;
+ }
+ paletteItem = paletteItem.nextSibling;
+ }
+ }
+ break;
+ }
+
+ return newItem;
+ ]]>
+ </body>
+ </method>
+
+ <method name="insertItem">
+ <parameter name="aId"/>
+ <parameter name="aBeforeElt"/>
+ <parameter name="aWrapper"/>
+ <body>
+ <![CDATA[
+ var newItem = this._getToolbarItem(aId);
+ if (!newItem)
+ return null;
+
+ var insertItem = newItem;
+ // make sure added items are removable
+ newItem.setAttribute("removable", "true");
+
+ // Wrap the item in another node if so inclined.
+ if (aWrapper) {
+ aWrapper.appendChild(newItem);
+ insertItem = aWrapper;
+ }
+
+ // Insert the palette item into the toolbar.
+ if (aBeforeElt)
+ this.insertBefore(insertItem, aBeforeElt);
+ else
+ this.appendChild(insertItem);
+
+ return newItem;
+ ]]>
+ </body>
+ </method>
+
+ <method name="hasCustomInteractiveItems">
+ <parameter name="aCurrentSet"/>
+ <body><![CDATA[
+ if (aCurrentSet == "__empty")
+ return false;
+
+ var defaultOrNoninteractive = (this.getAttribute("defaultset") || "")
+ .split(",")
+ .concat(["separator", "spacer", "spring"]);
+ return aCurrentSet.split(",").some(function (item) {
+ return defaultOrNoninteractive.indexOf(item) == -1;
+ });
+ ]]></body>
+ </method>
+ </implementation>
+ </binding>
+
+ <binding id="toolbar-menubar-autohide"
+ extends="chrome://global/content/bindings/toolbar.xml#toolbar">
+ <implementation>
+ <constructor>
+ this._setInactive();
+ </constructor>
+ <destructor>
+ this._setActive();
+ </destructor>
+
+ <field name="_inactiveTimeout">null</field>
+
+ <field name="_contextMenuListener"><![CDATA[({
+ toolbar: this,
+ contextMenu: null,
+
+ get active () {
+ return !!this.contextMenu;
+ },
+
+ init: function (event) {
+ var node = event.target;
+ while (node != this.toolbar) {
+ if (node.localName == "menupopup")
+ return;
+ node = node.parentNode;
+ }
+
+ var contextMenuId = this.toolbar.getAttribute("context");
+ if (!contextMenuId)
+ return;
+
+ this.contextMenu = document.getElementById(contextMenuId);
+ if (!this.contextMenu)
+ return;
+
+ this.contextMenu.addEventListener("popupshown", this, false);
+ this.contextMenu.addEventListener("popuphiding", this, false);
+ this.toolbar.addEventListener("mousemove", this, false);
+ },
+ handleEvent: function (event) {
+ switch (event.type) {
+ case "popupshown":
+ this.toolbar.removeEventListener("mousemove", this, false);
+ break;
+ case "popuphiding":
+ case "mousemove":
+ this.toolbar._setInactiveAsync();
+ this.toolbar.removeEventListener("mousemove", this, false);
+ this.contextMenu.removeEventListener("popuphiding", this, false);
+ this.contextMenu.removeEventListener("popupshown", this, false);
+ this.contextMenu = null;
+ break;
+ }
+ }
+ })]]></field>
+
+ <method name="_setInactive">
+ <body><![CDATA[
+ this.setAttribute("inactive", "true");
+ ]]></body>
+ </method>
+
+ <method name="_setInactiveAsync">
+ <body><![CDATA[
+ this._inactiveTimeout = setTimeout(function (self) {
+ if (self.getAttribute("autohide") == "true") {
+ self._inactiveTimeout = null;
+ self._setInactive();
+ }
+ }, 0, this);
+ ]]></body>
+ </method>
+
+ <method name="_setActive">
+ <body><![CDATA[
+ if (this._inactiveTimeout) {
+ clearTimeout(this._inactiveTimeout);
+ this._inactiveTimeout = null;
+ }
+ this.removeAttribute("inactive");
+ ]]></body>
+ </method>
+ </implementation>
+
+ <handlers>
+ <handler event="DOMMenuBarActive" action="this._setActive();"/>
+ <handler event="popupshowing" action="this._setActive();"/>
+ <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
+ <handler event="DOMMenuBarInactive"><![CDATA[
+ if (!this._contextMenuListener.active)
+ this._setInactiveAsync();
+ ]]></handler>
+ </handlers>
+ </binding>
+
+ <binding id="toolbar-drag"
+ extends="chrome://global/content/bindings/toolbar.xml#toolbar">
+ <implementation>
+ <field name="_dragBindingAlive">true</field>
+ <constructor><![CDATA[
+ if (!this._draggableStarted) {
+ this._draggableStarted = true;
+ try {
+ let tmp = {};
+ Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
+ let draggableThis = new tmp.WindowDraggingElement(this);
+ draggableThis.mouseDownCheck = function(e) {
+ // Don't move while customizing.
+ return this._dragBindingAlive &&
+ this.getAttribute("customizing") != "true";
+ };
+ } catch (e) {}
+ }
+ ]]></constructor>
+ </implementation>
+ </binding>
+
+ <binding id="menubar" role="xul:menubar"
+ extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:menubar">
+ <implementation>
+ <field name="_active">false</field>
+ <field name="_statusbar">null</field>
+ <field name="_originalStatusText">null</field>
+ <property name="statusbar" onget="return this.getAttribute('statusbar');"
+ onset="this.setAttribute('statusbar', val); return val;"/>
+ <method name="_updateStatusText">
+ <parameter name="itemText"/>
+ <body>
+ <![CDATA[
+ if (!this._active)
+ return;
+ var newText = itemText ? itemText : this._originalStatusText;
+ if (newText != this._statusbar.label)
+ this._statusbar.label = newText;
+ ]]>
+ </body>
+ </method>
+ </implementation>
+ <handlers>
+ <handler event="DOMMenuBarActive">
+ <![CDATA[
+ if (!this.statusbar) return;
+ this._statusbar = document.getElementById(this.statusbar);
+ if (!this._statusbar)
+ return;
+ this._active = true;
+ this._originalStatusText = this._statusbar.label;
+ ]]>
+ </handler>
+ <handler event="DOMMenuBarInactive">
+ <![CDATA[
+ if (!this._active)
+ return;
+ this._active = false;
+ this._statusbar.label = this._originalStatusText;
+ ]]>
+ </handler>
+ <handler event="DOMMenuItemActive">this._updateStatusText(event.target.statusText);</handler>
+ <handler event="DOMMenuItemInactive">this._updateStatusText("");</handler>
+ </handlers>
+ </binding>
+
+ <binding id="toolbardecoration" role="xul:toolbarseparator" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base">
+ </binding>
+
+ <binding id="toolbarpaletteitem" extends="chrome://global/content/bindings/toolbar.xml#toolbar-base" display="xul:button">
+ <content>
+ <xul:hbox class="toolbarpaletteitem-box" flex="1" xbl:inherits="type,place">
+ <children/>
+ </xul:hbox>
+ </content>
+ </binding>
+
+ <binding id="toolbarpaletteitem-palette" extends="chrome://global/content/bindings/toolbar.xml#toolbarpaletteitem">
+ <content>
+ <xul:hbox class="toolbarpaletteitem-box" xbl:inherits="type,place">
+ <children/>
+ </xul:hbox>
+ <xul:label xbl:inherits="value=title"/>
+ </content>
+ </binding>
+
+</bindings>
+