browser/components/customizableui/content/toolbar.xml

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/components/customizableui/content/toolbar.xml	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,615 @@
     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 +<bindings id="browserToolbarBindings"
    1.10 +          xmlns="http://www.mozilla.org/xbl"
    1.11 +          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    1.12 +          xmlns:xbl="http://www.mozilla.org/xbl">
    1.13 +
    1.14 +  <binding id="toolbar" role="xul:toolbar">
    1.15 +    <resources>
    1.16 +      <stylesheet src="chrome://global/skin/toolbar.css"/>
    1.17 +    </resources>
    1.18 +    <implementation>
    1.19 +      <field name="overflowedDuringConstruction">null</field>
    1.20 +
    1.21 +      <constructor><![CDATA[
    1.22 +          let scope = {};
    1.23 +          Cu.import("resource:///modules/CustomizableUI.jsm", scope);
    1.24 +          // Add an early overflow event listener that will mark if the
    1.25 +          // toolbar overflowed during construction.
    1.26 +          if (scope.CustomizableUI.isAreaOverflowable(this.id)) {
    1.27 +            this.addEventListener("overflow", this);
    1.28 +            this.addEventListener("underflow", this);
    1.29 +          }
    1.30 +
    1.31 +          if (document.readyState == "complete") {
    1.32 +            this._init();
    1.33 +          } else {
    1.34 +            // Need to wait until XUL overlays are loaded. See bug 554279.
    1.35 +            let self = this;
    1.36 +            document.addEventListener("readystatechange", function onReadyStateChange() {
    1.37 +              if (document.readyState != "complete")
    1.38 +                return;
    1.39 +              document.removeEventListener("readystatechange", onReadyStateChange, false);
    1.40 +              self._init();
    1.41 +            }, false);
    1.42 +          }
    1.43 +      ]]></constructor>
    1.44 +
    1.45 +      <method name="_init">
    1.46 +        <body><![CDATA[
    1.47 +          let scope = {};
    1.48 +          Cu.import("resource:///modules/CustomizableUI.jsm", scope);
    1.49 +          let CustomizableUI = scope.CustomizableUI;
    1.50 +
    1.51 +          // Bug 989289: Forcibly set the now unsupported "mode" and "iconsize"
    1.52 +          // attributes, just in case they accidentally get restored from
    1.53 +          // persistence from a user that's been upgrading and downgrading.
    1.54 +          if (CustomizableUI.isBuiltinToolbar(this.id)) {
    1.55 +            const kAttributes = new Map([["mode", "icons"], ["iconsize", "small"]]);
    1.56 +            for (let [attribute, value] of kAttributes) {
    1.57 +              if (this.getAttribute(attribute) != value) {
    1.58 +                this.setAttribute(attribute, value);
    1.59 +                document.persist(this.id, attribute);
    1.60 +              }
    1.61 +              if (this.toolbox) {
    1.62 +                if (this.toolbox.getAttribute(attribute) != value) {
    1.63 +                  this.toolbox.setAttribute(attribute, value);
    1.64 +                  document.persist(this.toolbox.id, attribute);
    1.65 +                }
    1.66 +              }
    1.67 +            }
    1.68 +          }
    1.69 +
    1.70 +          // Searching for the toolbox palette in the toolbar binding because
    1.71 +          // toolbars are constructed first.
    1.72 +          let toolbox = this.toolbox;
    1.73 +          if (toolbox && !toolbox.palette) {
    1.74 +            for (let node of toolbox.children) {
    1.75 +              if (node.localName == "toolbarpalette") {
    1.76 +                // Hold on to the palette but remove it from the document.
    1.77 +                toolbox.palette = node;
    1.78 +                toolbox.removeChild(node);
    1.79 +                break;
    1.80 +              }
    1.81 +            }
    1.82 +          }
    1.83 +
    1.84 +          // pass the current set of children for comparison with placements:
    1.85 +          let children = [node.id for (node of this.childNodes)
    1.86 +                          if (node.getAttribute("skipintoolbarset") != "true" && node.id)];
    1.87 +          CustomizableUI.registerToolbarNode(this, children);
    1.88 +        ]]></body>
    1.89 +      </method>
    1.90 +
    1.91 +      <method name="handleEvent">
    1.92 +        <parameter name="aEvent"/>
    1.93 +        <body><![CDATA[
    1.94 +          if (aEvent.type == "overflow" && aEvent.detail > 0) {
    1.95 +            if (this.overflowable && this.overflowable.initialized) {
    1.96 +              this.overflowable.onOverflow(aEvent);
    1.97 +            } else {
    1.98 +              this.overflowedDuringConstruction = aEvent;
    1.99 +            }
   1.100 +          } else if (aEvent.type == "underflow" && aEvent.detail > 0) {
   1.101 +            this.overflowedDuringConstruction = null;
   1.102 +          }
   1.103 +        ]]></body>
   1.104 +      </method>
   1.105 +
   1.106 +      <method name="insertItem">
   1.107 +        <parameter name="aId"/>
   1.108 +        <parameter name="aBeforeElt"/>
   1.109 +        <parameter name="aWrapper"/>
   1.110 +        <body><![CDATA[
   1.111 +          if (aWrapper) {
   1.112 +            Cu.reportError("Can't insert " + aId + ": using insertItem " +
   1.113 +                           "no longer supports wrapper elements.");
   1.114 +            return null;
   1.115 +          }
   1.116 +
   1.117 +          // Hack, the customizable UI code makes this be the last position
   1.118 +          let pos = null;
   1.119 +          if (aBeforeElt) {
   1.120 +            let beforeInfo = CustomizableUI.getPlacementOfWidget(aBeforeElt.id);
   1.121 +            if (beforeInfo.area != this.id) {
   1.122 +              Cu.reportError("Can't insert " + aId + " before " +
   1.123 +                             aBeforeElt.id + " which isn't in this area (" +
   1.124 +                             this.id + ").");
   1.125 +              return null;
   1.126 +            }
   1.127 +            pos = beforeInfo.position;
   1.128 +          }
   1.129 +
   1.130 +          CustomizableUI.addWidgetToArea(aId, this.id, pos);
   1.131 +          return this.ownerDocument.getElementById(aId);
   1.132 +        ]]></body>
   1.133 +      </method>
   1.134 +
   1.135 +      <property name="toolbarName"
   1.136 +                onget="return this.getAttribute('toolbarname');"
   1.137 +                onset="this.setAttribute('toolbarname', val); return val;"/>
   1.138 +
   1.139 +      <property name="customizationTarget" readonly="true">
   1.140 +        <getter><![CDATA[
   1.141 +          if (this._customizationTarget)
   1.142 +            return this._customizationTarget;
   1.143 +
   1.144 +          let id = this.getAttribute("customizationtarget");
   1.145 +          if (id)
   1.146 +            this._customizationTarget = document.getElementById(id);
   1.147 +
   1.148 +          if (this._customizationTarget)
   1.149 +            this._customizationTarget.insertItem = this.insertItem.bind(this);
   1.150 +          else
   1.151 +            this._customizationTarget = this;
   1.152 +
   1.153 +          return this._customizationTarget;
   1.154 +        ]]></getter>
   1.155 +      </property>
   1.156 +
   1.157 +      <property name="toolbox" readonly="true">
   1.158 +        <getter><![CDATA[
   1.159 +          if (this._toolbox)
   1.160 +            return this._toolbox;
   1.161 +
   1.162 +          let toolboxId = this.getAttribute("toolboxid");
   1.163 +          if (toolboxId) {
   1.164 +            let toolbox = document.getElementById(toolboxId);
   1.165 +            if (toolbox) {
   1.166 +              if (toolbox.externalToolbars.indexOf(this) == -1)
   1.167 +                toolbox.externalToolbars.push(this);
   1.168 +
   1.169 +              this._toolbox = toolbox;
   1.170 +            }
   1.171 +          }
   1.172 +
   1.173 +          if (!this._toolbox && this.parentNode &&
   1.174 +              this.parentNode.localName == "toolbox") {
   1.175 +            this._toolbox = this.parentNode;
   1.176 +          }
   1.177 +
   1.178 +          return this._toolbox;
   1.179 +        ]]></getter>
   1.180 +      </property>
   1.181 +
   1.182 +      <property name="currentSet">
   1.183 +        <getter><![CDATA[
   1.184 +          let currentWidgets = new Set();
   1.185 +          for (let node of this.customizationTarget.children) {
   1.186 +            let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
   1.187 +            if (realNode.getAttribute("skipintoolbarset") != "true") {
   1.188 +              currentWidgets.add(realNode.id);
   1.189 +            }
   1.190 +          }
   1.191 +          if (this.getAttribute("overflowing") == "true") {
   1.192 +            let overflowTarget = this.getAttribute("overflowtarget");
   1.193 +            let overflowList = this.ownerDocument.getElementById(overflowTarget);
   1.194 +            for (let node of overflowList.children) {
   1.195 +              let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node;
   1.196 +              if (realNode.getAttribute("skipintoolbarset") != "true") {
   1.197 +                currentWidgets.add(realNode.id);
   1.198 +              }
   1.199 +            }
   1.200 +          }
   1.201 +          let orderedPlacements = CustomizableUI.getWidgetIdsInArea(this.id);
   1.202 +          return orderedPlacements.filter((x) => currentWidgets.has(x)).join(',');
   1.203 +        ]]></getter>
   1.204 +        <setter><![CDATA[
   1.205 +          // Get list of new and old ids:
   1.206 +          let newVal = (val || '').split(',').filter(x => x);
   1.207 +          let oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
   1.208 +
   1.209 +          // Get a list of items only in the new list
   1.210 +          let newIds = [id for (id of newVal) if (oldIds.indexOf(id) == -1)];
   1.211 +          CustomizableUI.beginBatchUpdate();
   1.212 +          try {
   1.213 +            for (let newId of newIds) {
   1.214 +              oldIds = CustomizableUI.getWidgetIdsInArea(this.id);
   1.215 +              let nextId = newId;
   1.216 +              let pos;
   1.217 +              do {
   1.218 +                // Get the next item
   1.219 +                nextId = newVal[newVal.indexOf(nextId) + 1];
   1.220 +                // Figure out where it is in the old list
   1.221 +                pos = oldIds.indexOf(nextId);
   1.222 +                // If it's not in the old list, repeat:
   1.223 +              } while (pos == -1 && nextId);
   1.224 +              if (pos == -1) {
   1.225 +                pos = null; // We didn't find anything, insert at the end
   1.226 +              }
   1.227 +              CustomizableUI.addWidgetToArea(newId, this.id, pos);
   1.228 +            }
   1.229 +
   1.230 +            let currentIds = this.currentSet.split(',');
   1.231 +            let removedIds = [id for (id of currentIds) if (newIds.indexOf(id) == -1 && newVal.indexOf(id) == -1)];
   1.232 +            for (let removedId of removedIds) {
   1.233 +              CustomizableUI.removeWidgetFromArea(removedId);
   1.234 +            }
   1.235 +          } finally {
   1.236 +            CustomizableUI.endBatchUpdate();
   1.237 +          }
   1.238 +        ]]></setter>
   1.239 +      </property>
   1.240 +
   1.241 +
   1.242 +    </implementation>
   1.243 +  </binding>
   1.244 +
   1.245 +  <binding id="toolbar-menubar-stub">
   1.246 +    <implementation>
   1.247 +      <property name="toolbox" readonly="true">
   1.248 +        <getter><![CDATA[
   1.249 +          if (this._toolbox)
   1.250 +            return this._toolbox;
   1.251 +
   1.252 +          if (this.parentNode && this.parentNode.localName == "toolbox") {
   1.253 +            this._toolbox = this.parentNode;
   1.254 +          }
   1.255 +
   1.256 +          return this._toolbox;
   1.257 +        ]]></getter>
   1.258 +      </property>
   1.259 +      <property name="currentSet" readonly="true">
   1.260 +        <getter><![CDATA[
   1.261 +          return this.getAttribute("defaultset");
   1.262 +        ]]></getter>
   1.263 +      </property>
   1.264 +      <method name="insertItem">
   1.265 +        <body><![CDATA[
   1.266 +          return null;
   1.267 +        ]]></body>
   1.268 +      </method>
   1.269 +    </implementation>
   1.270 +  </binding>
   1.271 +
   1.272 +  <!-- The toolbar-menubar-autohide and toolbar-drag bindings are almost
   1.273 +       verbatim copies of their toolkit counterparts - they just inherit from
   1.274 +       the customizableui's toolbar binding instead of toolkit's. We're currently
   1.275 +       OK with the maintainance burden of having two copies of a binding, since
   1.276 +       the long term goal is to move the customization framework into toolkit. -->
   1.277 +
   1.278 +  <binding id="toolbar-menubar-autohide"
   1.279 +           extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
   1.280 +    <implementation>
   1.281 +      <constructor>
   1.282 +        this._setInactive();
   1.283 +      </constructor>
   1.284 +      <destructor>
   1.285 +        this._setActive();
   1.286 +      </destructor>
   1.287 +
   1.288 +      <field name="_inactiveTimeout">null</field>
   1.289 +
   1.290 +      <field name="_contextMenuListener"><![CDATA[({
   1.291 +        toolbar: this,
   1.292 +        contextMenu: null,
   1.293 +
   1.294 +        get active () !!this.contextMenu,
   1.295 +
   1.296 +        init: function (event) {
   1.297 +          let node = event.target;
   1.298 +          while (node != this.toolbar) {
   1.299 +            if (node.localName == "menupopup")
   1.300 +              return;
   1.301 +            node = node.parentNode;
   1.302 +          }
   1.303 +
   1.304 +          let contextMenuId = this.toolbar.getAttribute("context");
   1.305 +          if (!contextMenuId)
   1.306 +            return;
   1.307 +
   1.308 +          this.contextMenu = document.getElementById(contextMenuId);
   1.309 +          if (!this.contextMenu)
   1.310 +            return;
   1.311 +
   1.312 +          this.contextMenu.addEventListener("popupshown", this, false);
   1.313 +          this.contextMenu.addEventListener("popuphiding", this, false);
   1.314 +          this.toolbar.addEventListener("mousemove", this, false);
   1.315 +        },
   1.316 +        handleEvent: function (event) {
   1.317 +          switch (event.type) {
   1.318 +            case "popupshown":
   1.319 +              this.toolbar.removeEventListener("mousemove", this, false);
   1.320 +              break;
   1.321 +            case "popuphiding":
   1.322 +            case "mousemove":
   1.323 +              this.toolbar._setInactiveAsync();
   1.324 +              this.toolbar.removeEventListener("mousemove", this, false);
   1.325 +              this.contextMenu.removeEventListener("popuphiding", this, false);
   1.326 +              this.contextMenu.removeEventListener("popupshown", this, false);
   1.327 +              this.contextMenu = null;
   1.328 +              break;
   1.329 +          }
   1.330 +        }
   1.331 +      })]]></field>
   1.332 +
   1.333 +      <method name="_setInactive">
   1.334 +        <body><![CDATA[
   1.335 +          this.setAttribute("inactive", "true");
   1.336 +        ]]></body>
   1.337 +      </method>
   1.338 +
   1.339 +      <method name="_setInactiveAsync">
   1.340 +        <body><![CDATA[
   1.341 +          this._inactiveTimeout = setTimeout(function (self) {
   1.342 +            if (self.getAttribute("autohide") == "true") {
   1.343 +              self._inactiveTimeout = null;
   1.344 +              self._setInactive();
   1.345 +            }
   1.346 +          }, 0, this);
   1.347 +        ]]></body>
   1.348 +      </method>
   1.349 +
   1.350 +      <method name="_setActive">
   1.351 +        <body><![CDATA[
   1.352 +          if (this._inactiveTimeout) {
   1.353 +            clearTimeout(this._inactiveTimeout);
   1.354 +            this._inactiveTimeout = null;
   1.355 +          }
   1.356 +          this.removeAttribute("inactive");
   1.357 +        ]]></body>
   1.358 +      </method>
   1.359 +    </implementation>
   1.360 +
   1.361 +    <handlers>
   1.362 +      <handler event="DOMMenuBarActive"     action="this._setActive();"/>
   1.363 +      <handler event="popupshowing"         action="this._setActive();"/>
   1.364 +      <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/>
   1.365 +      <handler event="DOMMenuBarInactive"><![CDATA[
   1.366 +        if (!this._contextMenuListener.active)
   1.367 +          this._setInactiveAsync();
   1.368 +      ]]></handler>
   1.369 +    </handlers>
   1.370 +  </binding>
   1.371 +
   1.372 +  <binding id="toolbar-drag"
   1.373 +           extends="chrome://browser/content/customizableui/toolbar.xml#toolbar">
   1.374 +    <implementation>
   1.375 +      <field name="_dragBindingAlive">true</field>
   1.376 +      <constructor><![CDATA[
   1.377 +        if (!this._draggableStarted) {
   1.378 +          this._draggableStarted = true;
   1.379 +          try {
   1.380 +            let tmp = {};
   1.381 +            Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp);
   1.382 +            let draggableThis = new tmp.WindowDraggingElement(this);
   1.383 +            draggableThis.mouseDownCheck = function(e) {
   1.384 +              return this._dragBindingAlive;
   1.385 +            };
   1.386 +          } catch (e) {}
   1.387 +        }
   1.388 +      ]]></constructor>
   1.389 +    </implementation>
   1.390 +  </binding>
   1.391 +
   1.392 +
   1.393 +<!-- This is a peculiar binding. It is here to deal with overlayed/inserted add-on content,
   1.394 +      and immediately direct such content elsewhere. -->
   1.395 +  <binding id="addonbar-delegating">
   1.396 +    <implementation>
   1.397 +      <constructor><![CDATA[
   1.398 +          // Reading these immediately so nobody messes with them anymore:
   1.399 +          this._delegatingToolbar = this.getAttribute("toolbar-delegate");
   1.400 +          this._wasCollapsed = this.getAttribute("collapsed") == "true";
   1.401 +          // Leaving those in here to unbreak some code:
   1.402 +          if (document.readyState == "complete") {
   1.403 +            this._init();
   1.404 +          } else {
   1.405 +            // Need to wait until XUL overlays are loaded. See bug 554279.
   1.406 +            let self = this;
   1.407 +            document.addEventListener("readystatechange", function onReadyStateChange() {
   1.408 +              if (document.readyState != "complete")
   1.409 +                return;
   1.410 +              document.removeEventListener("readystatechange", onReadyStateChange, false);
   1.411 +              self._init();
   1.412 +            }, false);
   1.413 +          }
   1.414 +      ]]></constructor>
   1.415 +
   1.416 +      <method name="_init">
   1.417 +        <body><![CDATA[
   1.418 +          // Searching for the toolbox palette in the toolbar binding because
   1.419 +          // toolbars are constructed first.
   1.420 +          let toolbox = this.toolbox;
   1.421 +          if (toolbox && !toolbox.palette) {
   1.422 +            for (let node of toolbox.children) {
   1.423 +              if (node.localName == "toolbarpalette") {
   1.424 +                // Hold on to the palette but remove it from the document.
   1.425 +                toolbox.palette = node;
   1.426 +                toolbox.removeChild(node);
   1.427 +              }
   1.428 +            }
   1.429 +          }
   1.430 +
   1.431 +          // pass the current set of children for comparison with placements:
   1.432 +          let children = [];
   1.433 +          for (let node of this.childNodes) {
   1.434 +            if (node.getAttribute("skipintoolbarset") != "true" && node.id) {
   1.435 +              // Force everything to be removable so that buildArea can chuck stuff
   1.436 +              // out if the user has customized things / we've been here before:
   1.437 +              if (!this._whiteListed.has(node.id)) {
   1.438 +                node.setAttribute("removable", "true");
   1.439 +              }
   1.440 +              children.push(node);
   1.441 +            }
   1.442 +          }
   1.443 +          CustomizableUI.registerToolbarNode(this, children);
   1.444 +          let existingMigratedItems = (this.getAttribute("migratedset") || "").split(',');
   1.445 +          for (let migratedItem of existingMigratedItems.filter((x) => !!x)) {
   1.446 +            this._currentSetMigrated.add(migratedItem);
   1.447 +          }
   1.448 +          this.evictNodes();
   1.449 +          // We can't easily use |this| or strong bindings for the observer fn here
   1.450 +          // because that creates leaky circular references when the node goes away,
   1.451 +          // and XBL destructors are unreliable.
   1.452 +          let mutationObserver = new MutationObserver(function(mutations) {
   1.453 +            if (!mutations.length) {
   1.454 +              return;
   1.455 +            }
   1.456 +            let toolbar = mutations[0].target;
   1.457 +            // Can't use our own attribute because we might not have one if we're set to
   1.458 +            // collapsed
   1.459 +            let areCustomizing = toolbar.ownerDocument.documentElement.getAttribute("customizing");
   1.460 +            if (!toolbar._isModifying && !areCustomizing) {
   1.461 +              toolbar.evictNodes();
   1.462 +            }
   1.463 +          });
   1.464 +          mutationObserver.observe(this, {childList: true});
   1.465 +        ]]></body>
   1.466 +      </method>
   1.467 +      <method name="evictNodes">
   1.468 +        <body><![CDATA[
   1.469 +          this._isModifying = true;
   1.470 +          let i = this.childNodes.length;
   1.471 +          while (i--) {
   1.472 +            let node = this.childNodes[i];
   1.473 +            if (this.childNodes[i].id) {
   1.474 +              this.evictNode(this.childNodes[i]);
   1.475 +            } else {
   1.476 +              node.remove();
   1.477 +            }
   1.478 +          }
   1.479 +          this._isModifying = false;
   1.480 +          this._updateMigratedSet();
   1.481 +        ]]></body>
   1.482 +      </method>
   1.483 +      <method name="evictNode">
   1.484 +        <parameter name="aNode"/>
   1.485 +        <body>
   1.486 +        <![CDATA[
   1.487 +          if (this._whiteListed.has(aNode.id) || CustomizableUI.isSpecialWidget(aNode.id)) {
   1.488 +            return;
   1.489 +          }
   1.490 +          const kItemMaxWidth = 100;
   1.491 +          let oldParent = aNode.parentNode;
   1.492 +          aNode.setAttribute("removable", "true");
   1.493 +          this._currentSetMigrated.add(aNode.id);
   1.494 +
   1.495 +          let movedOut = false;
   1.496 +          if (!this._wasCollapsed) {
   1.497 +            try {
   1.498 +              let nodeWidth = aNode.getBoundingClientRect().width;
   1.499 +              if (nodeWidth == 0 || nodeWidth > kItemMaxWidth) {
   1.500 +                throw new Error(aNode.id + " is too big (" + nodeWidth +
   1.501 +                                "px wide), moving to the palette");
   1.502 +              }
   1.503 +              CustomizableUI.addWidgetToArea(aNode.id, this._delegatingToolbar);
   1.504 +              movedOut = true;
   1.505 +            } catch (ex) {
   1.506 +              // This will throw if the node is too big, or can't be moved there for
   1.507 +              // some reason. Report this:
   1.508 +              Cu.reportError(ex);
   1.509 +            }
   1.510 +          }
   1.511 +
   1.512 +          /* We won't have moved the widget if either the add-on bar was collapsed,
   1.513 +           * or if it was too wide to be inserted into the navbar. */
   1.514 +          if (!movedOut) {
   1.515 +            try {
   1.516 +              CustomizableUI.removeWidgetFromArea(aNode.id);
   1.517 +            } catch (ex) {
   1.518 +              Cu.reportError(ex);
   1.519 +              aNode.remove();
   1.520 +            }
   1.521 +          }
   1.522 +
   1.523 +          // Surprise: addWidgetToArea(palette) will get you nothing if the palette
   1.524 +          // is not constructed yet. Fix:
   1.525 +          if (aNode.parentNode == oldParent) {
   1.526 +            let palette = this.toolbox.palette;
   1.527 +            if (palette && oldParent != palette) {
   1.528 +              palette.appendChild(aNode);
   1.529 +            }
   1.530 +          }
   1.531 +        ]]></body>
   1.532 +      </method>
   1.533 +      <method name="insertItem">
   1.534 +        <parameter name="aId"/>
   1.535 +        <parameter name="aBeforeElt"/>
   1.536 +        <parameter name="aWrapper"/>
   1.537 +        <body><![CDATA[
   1.538 +          if (aWrapper) {
   1.539 +            Cu.reportError("Can't insert " + aId + ": using insertItem " +
   1.540 +                           "no longer supports wrapper elements.");
   1.541 +            return null;
   1.542 +          }
   1.543 +
   1.544 +          let widget = CustomizableUI.getWidget(aId);
   1.545 +          widget = widget && widget.forWindow(window);
   1.546 +          let node = widget && widget.node;
   1.547 +          if (!node) {
   1.548 +            return null;
   1.549 +          }
   1.550 +
   1.551 +          this._isModifying = true;
   1.552 +          // Temporarily add it here so it can have a width, then ditch it:
   1.553 +          this.appendChild(node);
   1.554 +          this.evictNode(node);
   1.555 +          this._isModifying = false;
   1.556 +          this._updateMigratedSet();
   1.557 +          // We will now have moved stuff around; kick off some events
   1.558 +          // so add-ons know we've just moved their stuff:
   1.559 +          // XXXgijs: only in this window. It's hard to know for sure what's the right
   1.560 +          // thing to do here - typically insertItem is used on each window, so
   1.561 +          // this seems to make the most sense, even if some of the effects of
   1.562 +          // evictNode might affect multiple windows.
   1.563 +          CustomizableUI.dispatchToolboxEvent("customizationchange", {}, window);
   1.564 +          CustomizableUI.dispatchToolboxEvent("aftercustomization", {}, window);
   1.565 +          return node;
   1.566 +        ]]></body>
   1.567 +      </method>
   1.568 +      <method name="getMigratedItems">
   1.569 +        <body><![CDATA[
   1.570 +          return [... this._currentSetMigrated];
   1.571 +        ]]></body>
   1.572 +      </method>
   1.573 +      <method name="_updateMigratedSet">
   1.574 +        <body><![CDATA[
   1.575 +          let newMigratedItems = this.getMigratedItems().join(',');
   1.576 +          if (this.getAttribute("migratedset") != newMigratedItems) {
   1.577 +            this.setAttribute("migratedset", newMigratedItems);
   1.578 +            this.ownerDocument.persist(this.id, "migratedset");
   1.579 +          }
   1.580 +        ]]></body>
   1.581 +      </method>
   1.582 +      <property name="customizationTarget" readonly="true">
   1.583 +        <getter><![CDATA[
   1.584 +          return this;
   1.585 +        ]]></getter>
   1.586 +      </property>
   1.587 +      <property name="currentSet">
   1.588 +        <getter><![CDATA[
   1.589 +          return [node.id for (node of this.children)].join(',');
   1.590 +        ]]></getter>
   1.591 +        <setter><![CDATA[
   1.592 +          let v = val.split(',');
   1.593 +          let newButtons = v.filter(x => x && (!this._whiteListed.has(x) &&
   1.594 +                                               !CustomizableUI.isSpecialWidget(x) &&
   1.595 +                                               !this._currentSetMigrated.has(x)));
   1.596 +          for (let newButton of newButtons) {
   1.597 +            this._currentSetMigrated.add(newButton);
   1.598 +            this.insertItem(newButton);
   1.599 +          }
   1.600 +          this._updateMigratedSet();
   1.601 +        ]]></setter>
   1.602 +      </property>
   1.603 +      <property name="toolbox" readonly="true">
   1.604 +        <getter><![CDATA[
   1.605 +          if (!this._toolbox && this.parentNode &&
   1.606 +              this.parentNode.localName == "toolbox") {
   1.607 +            this._toolbox = this.parentNode;
   1.608 +          }
   1.609 +
   1.610 +          return this._toolbox;
   1.611 +        ]]></getter>
   1.612 +      </property>
   1.613 +      <field name="_whiteListed" readonly="true">new Set(["addonbar-closebutton", "status-bar"])</field>
   1.614 +      <field name="_isModifying">false</field>
   1.615 +      <field name="_currentSetMigrated">new Set()</field>
   1.616 +    </implementation>
   1.617 +  </binding>
   1.618 +</bindings>

mercurial