The only purpose of these bindings was to insert a stylesheet, which has been moved to be included in toolkit/content/components.css. MozReview-Commit-ID: 23jqkIrbVvi
352 lines
12 KiB
XML
352 lines
12 KiB
XML
<?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="browserToolbarBindings"
|
|
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">
|
|
<implementation>
|
|
<field name="overflowedDuringConstruction">null</field>
|
|
|
|
<constructor><![CDATA[
|
|
let scope = {};
|
|
ChromeUtils.import("resource:///modules/CustomizableUI.jsm", scope);
|
|
let CustomizableUI = scope.CustomizableUI;
|
|
// Add an early overflow event listener that will mark if the
|
|
// toolbar overflowed during construction.
|
|
if (CustomizableUI.isAreaOverflowable(this.id)) {
|
|
this.addEventListener("overflow", this);
|
|
this.addEventListener("underflow", this);
|
|
}
|
|
|
|
// Searching for the toolbox palette in the toolbar binding because
|
|
// toolbars are constructed first.
|
|
let toolbox = this.toolbox;
|
|
if (toolbox && !toolbox.palette) {
|
|
for (let node of toolbox.children) {
|
|
if (node.localName == "toolbarpalette") {
|
|
// Hold on to the palette but remove it from the document.
|
|
toolbox.palette = node;
|
|
toolbox.removeChild(node);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// pass the current set of children for comparison with placements:
|
|
let children = Array.from(this.childNodes)
|
|
.filter(node => node.getAttribute("skipintoolbarset") != "true" && node.id)
|
|
.map(node => node.id);
|
|
CustomizableUI.registerToolbarNode(this, children);
|
|
]]></constructor>
|
|
|
|
<method name="handleEvent">
|
|
<parameter name="aEvent"/>
|
|
<body><![CDATA[
|
|
// Ignore overflow/underflow events from from nodes inside the toolbar.
|
|
if (aEvent.target != this.customizationTarget) {
|
|
return;
|
|
}
|
|
|
|
if (aEvent.type == "overflow" && aEvent.detail > 0) {
|
|
if (this.overflowable && this.overflowable.initialized) {
|
|
this.overflowable.onOverflow(aEvent);
|
|
} else {
|
|
this.overflowedDuringConstruction = aEvent;
|
|
}
|
|
} else if (aEvent.type == "underflow" && aEvent.detail > 0) {
|
|
this.overflowedDuringConstruction = null;
|
|
}
|
|
]]></body>
|
|
</method>
|
|
|
|
<method name="insertItem">
|
|
<parameter name="aId"/>
|
|
<parameter name="aBeforeElt"/>
|
|
<parameter name="aWrapper"/>
|
|
<body><![CDATA[
|
|
if (aWrapper) {
|
|
Cu.reportError("Can't insert " + aId + ": using insertItem " +
|
|
"no longer supports wrapper elements.");
|
|
return null;
|
|
}
|
|
|
|
// Hack, the customizable UI code makes this be the last position
|
|
let pos = null;
|
|
if (aBeforeElt) {
|
|
let beforeInfo = CustomizableUI.getPlacementOfWidget(aBeforeElt.id);
|
|
if (beforeInfo.area != this.id) {
|
|
Cu.reportError("Can't insert " + aId + " before " +
|
|
aBeforeElt.id + " which isn't in this area (" +
|
|
this.id + ").");
|
|
return null;
|
|
}
|
|
pos = beforeInfo.position;
|
|
}
|
|
|
|
CustomizableUI.addWidgetToArea(aId, this.id, pos);
|
|
return this.ownerDocument.getElementById(aId);
|
|
]]></body>
|
|
</method>
|
|
|
|
<property name="toolbarName"
|
|
onget="return this.getAttribute('toolbarname');"
|
|
onset="this.setAttribute('toolbarname', val); return val;"/>
|
|
|
|
<property name="customizationTarget" readonly="true">
|
|
<getter><![CDATA[
|
|
if (this._customizationTarget)
|
|
return this._customizationTarget;
|
|
|
|
let id = this.getAttribute("customizationtarget");
|
|
if (id)
|
|
this._customizationTarget = document.getElementById(id);
|
|
|
|
if (this._customizationTarget)
|
|
this._customizationTarget.insertItem = this.insertItem.bind(this);
|
|
else
|
|
this._customizationTarget = this;
|
|
|
|
return this._customizationTarget;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<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) {
|
|
this._toolbox = toolbox;
|
|
}
|
|
}
|
|
|
|
if (!this._toolbox && this.parentNode &&
|
|
this.parentNode.localName == "toolbox") {
|
|
this._toolbox = this.parentNode;
|
|
}
|
|
|
|
return this._toolbox;
|
|
]]></getter>
|
|
</property>
|
|
|
|
<property name="currentSet">
|
|
<getter><![CDATA[
|
|
let currentWidgets = new Set();
|
|
for (let node of this.customizationTarget.children) {
|
|
let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
|
|
if (realNode.getAttribute("skipintoolbarset") != "true") {
|
|
currentWidgets.add(realNode.id);
|
|
}
|
|
}
|
|
if (this.getAttribute("overflowing") == "true") {
|
|
let overflowTarget = this.getAttribute("overflowtarget");
|
|
let overflowList = this.ownerDocument.getElementById(overflowTarget);
|
|
for (let node of overflowList.children) {
|
|
let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
|
|
if (realNode.getAttribute("skipintoolbarset") != "true") {
|
|
currentWidgets.add(realNode.id);
|
|
}
|
|
}
|
|
}
|
|
let orderedPlacements = CustomizableUI.getWidgetIdsInArea(this.id);
|
|
return orderedPlacements.filter(w => currentWidgets.has(w)).join(",");
|
|
]]></getter>
|
|
<setter><![CDATA[
|
|
// Get list of new and old ids:
|
|
let newVal = (val || "").split(",").filter(x => x);
|
|
let oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
|
|
|
|
// Get a list of items only in the new list
|
|
let newIds = newVal.filter(id => !oldIds.includes(id));
|
|
CustomizableUI.beginBatchUpdate();
|
|
try {
|
|
for (let newId of newIds) {
|
|
oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
|
|
let nextId = newId;
|
|
let pos;
|
|
do {
|
|
// Get the next item
|
|
nextId = newVal[newVal.indexOf(nextId) + 1];
|
|
// Figure out where it is in the old list
|
|
pos = oldIds.indexOf(nextId);
|
|
// If it's not in the old list, repeat:
|
|
} while (pos == -1 && nextId);
|
|
if (pos == -1) {
|
|
pos = null; // We didn't find anything, insert at the end
|
|
}
|
|
CustomizableUI.addWidgetToArea(newId, this.id, pos);
|
|
}
|
|
|
|
let currentIds = this.currentSet.split(",");
|
|
let removedIds = currentIds.filter(id => !newIds.includes(id) && !newVal.includes(id));
|
|
for (let removedId of removedIds) {
|
|
CustomizableUI.removeWidgetFromArea(removedId);
|
|
}
|
|
} finally {
|
|
CustomizableUI.endBatchUpdate();
|
|
}
|
|
]]></setter>
|
|
</property>
|
|
|
|
|
|
</implementation>
|
|
</binding>
|
|
|
|
<binding id="toolbar-menubar-stub">
|
|
<implementation>
|
|
<property name="toolbox" readonly="true">
|
|
<getter><![CDATA[
|
|
if (this._toolbox)
|
|
return this._toolbox;
|
|
|
|
if (this.parentNode && this.parentNode.localName == "toolbox") {
|
|
this._toolbox = this.parentNode;
|
|
}
|
|
|
|
return this._toolbox;
|
|
]]></getter>
|
|
</property>
|
|
<property name="currentSet" readonly="true">
|
|
<getter><![CDATA[
|
|
return this.getAttribute("defaultset");
|
|
]]></getter>
|
|
</property>
|
|
<method name="insertItem">
|
|
<body><![CDATA[
|
|
return null;
|
|
]]></body>
|
|
</method>
|
|
</implementation>
|
|
</binding>
|
|
|
|
<!-- The toolbar-menubar-autohide and toolbar-drag bindings are almost
|
|
verbatim copies of their toolkit counterparts - they just inherit from
|
|
the customizableui's toolbar binding instead of toolkit's. We're currently
|
|
OK with the maintainance burden of having two copies of a binding, since
|
|
the long term goal is to move the customization framework into toolkit. -->
|
|
|
|
<binding id="toolbar-menubar-autohide"
|
|
extends="chrome://browser/content/customizableui/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(event) {
|
|
let node = event.target;
|
|
while (node != this.toolbar) {
|
|
if (node.localName == "menupopup")
|
|
return;
|
|
node = node.parentNode;
|
|
}
|
|
|
|
let contextMenuId = this.toolbar.getAttribute("context");
|
|
if (!contextMenuId)
|
|
return;
|
|
|
|
this.contextMenu = document.getElementById(contextMenuId);
|
|
if (!this.contextMenu)
|
|
return;
|
|
|
|
this.contextMenu.addEventListener("popupshown", this);
|
|
this.contextMenu.addEventListener("popuphiding", this);
|
|
this.toolbar.addEventListener("mousemove", this);
|
|
},
|
|
handleEvent(event) {
|
|
switch (event.type) {
|
|
case "popupshown":
|
|
this.toolbar.removeEventListener("mousemove", this);
|
|
break;
|
|
case "popuphiding":
|
|
case "mousemove":
|
|
this.toolbar._setInactiveAsync();
|
|
this.toolbar.removeEventListener("mousemove", this);
|
|
this.contextMenu.removeEventListener("popuphiding", this);
|
|
this.contextMenu.removeEventListener("popupshown", this);
|
|
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://browser/content/customizableui/toolbar.xml#toolbar">
|
|
<implementation>
|
|
<field name="_dragBindingAlive">true</field>
|
|
<constructor><![CDATA[
|
|
if (!this._draggableStarted) {
|
|
this._draggableStarted = true;
|
|
try {
|
|
let tmp = {};
|
|
ChromeUtils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
|
|
let draggableThis = new tmp.WindowDraggingElement(this);
|
|
draggableThis.mouseDownCheck = function(e) {
|
|
return this._dragBindingAlive;
|
|
};
|
|
} catch (e) {}
|
|
}
|
|
]]></constructor>
|
|
</implementation>
|
|
</binding>
|
|
</bindings>
|