Bug 931092 - refactor insertion code so we can update individual nodes, r=mconley
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 31 Oct 2013 23:20:42 +0100
changeset 164979 2666f7e02336e5f99096aea9f1ccb3cb8da19cd1
parent 164978 9704aedc2a5c3334aa62af5443c9d61eab0c7d90
child 164980 f0305288f605cc310437223ba3a8e1efb74c65f6
push id4703
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 20:24:19 +0000
treeherdermozilla-aurora@20af7fbd96c1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconley
bugs931092
milestone28.0a1
Bug 931092 - refactor insertion code so we can update individual nodes, r=mconley
browser/components/customizableui/src/CustomizableUI.jsm
--- a/browser/components/customizableui/src/CustomizableUI.jsm
+++ b/browser/components/customizableui/src/CustomizableUI.jsm
@@ -710,54 +710,58 @@ let CustomizableUIInternal = {
             " when moving a widget.");
       return;
     }
 
     let nextNodeId = placements[aPosition + 1];
     // Go through each of the nodes associated with this area and move the
     // widget to the requested location.
     for (let areaNode of areaNodes) {
-      let window = areaNode.ownerDocument.defaultView;
-      let showInPrivateBrowsing = gPalette.has(aWidgetId)
-                                ? gPalette.get(aWidgetId).showInPrivateBrowsing
-                                : true;
-
-      if (!showInPrivateBrowsing &&
-          PrivateBrowsingUtils.isWindowPrivate(window)) {
-        continue;
-      }
-
-      let [, widgetNode] = this.getWidgetNode(aWidgetId, window);
-      if (!widgetNode) {
-        ERROR("Widget '" + aWidgetId + "' not found, unable to move");
-        continue;
-      }
-
-      if (isNew) {
-        this.ensureButtonContextMenu(widgetNode, aArea == CustomizableUI.AREA_PANEL);
-        if (widgetNode.localName == "toolbarbutton" && aArea == CustomizableUI.AREA_PANEL) {
-          widgetNode.setAttribute("tabindex", "0");
-          if (!widgetNode.hasAttribute("type")) {
-            widgetNode.setAttribute("type", "wrap");
-          }
-        }
-      }
-
-      let container = areaNode.customizationTarget;
-      let [insertionContainer, nextNode] = this.findInsertionPoints(widgetNode, nextNodeId, areaNode, aArea);
-      this.insertWidgetBefore(widgetNode, nextNode, insertionContainer, aArea);
-
-      if (gAreas.get(aArea).get("type") == CustomizableUI.TYPE_TOOLBAR) {
-        areaNode.setAttribute("currentset", areaNode.currentSet);
-      }
+      this.insertNodeInWindow(aWidgetId, areaNode, nextNodeId, isNew);
     }
   },
 
-  findInsertionPoints: function(aNode, aNextNodeId, aAreaNode, aArea) {
-    let props = gAreas.get(aArea);
+  insertNodeInWindow: function(aWidgetId, aAreaNode, aNextNodeId, isNew) {
+    let window = aAreaNode.ownerDocument.defaultView;
+    let showInPrivateBrowsing = gPalette.has(aWidgetId)
+                              ? gPalette.get(aWidgetId).showInPrivateBrowsing
+                              : true;
+
+    if (!showInPrivateBrowsing && PrivateBrowsingUtils.isWindowPrivate(window)) {
+      return;
+    }
+
+    let [, widgetNode] = this.getWidgetNode(aWidgetId, window);
+    if (!widgetNode) {
+      ERROR("Widget '" + aWidgetId + "' not found, unable to move");
+      return;
+    }
+
+    let areaId = aAreaNode.id;
+    if (isNew) {
+      this.ensureButtonContextMenu(widgetNode, areaId == CustomizableUI.AREA_PANEL);
+      if (widgetNode.localName == "toolbarbutton" && areaId == CustomizableUI.AREA_PANEL) {
+        widgetNode.setAttribute("tabindex", "0");
+        if (!widgetNode.hasAttribute("type")) {
+          widgetNode.setAttribute("type", "wrap");
+        }
+      }
+    }
+
+    let container = aAreaNode.customizationTarget;
+    let [insertionContainer, nextNode] = this.findInsertionPoints(widgetNode, aNextNodeId, aAreaNode);
+    this.insertWidgetBefore(widgetNode, nextNode, insertionContainer, areaId);
+
+    if (gAreas.get(areaId).get("type") == CustomizableUI.TYPE_TOOLBAR) {
+      aAreaNode.setAttribute("currentset", aAreaNode.currentSet);
+    }
+  },
+
+  findInsertionPoints: function(aNode, aNextNodeId, aAreaNode) {
+    let props = gAreas.get(aAreaNode.id);
     if (props.get("type") == CustomizableUI.TYPE_TOOLBAR && props.get("overflowable") &&
         aAreaNode.getAttribute("overflowing") == "true") {
       return aAreaNode.overflowable.getOverflowedInsertionPoints(aNode, aNextNodeId);
     }
     let nextNode = null;
     if (aNextNodeId) {
       nextNode = aAreaNode.customizationTarget.querySelector(idToSelector(aNextNodeId));
     }
@@ -1841,16 +1845,40 @@ let CustomizableUIInternal = {
     let placement = this.getPlacementOfWidget(aWidgetId);
     if (placement && placement.area != aArea &&
         !this.isWidgetRemovable(aWidgetId)) {
       return false;
     }
     return true;
   },
 
+  ensureWidgetPlacedInWindow: function(aWidgetId, aWindow) {
+    let placement = this.getPlacementOfWidget(aWidgetId);
+    if (!placement) {
+      return false;
+    }
+    let areaNodes = gBuildAreas.get(placement.area);
+    if (!areaNodes) {
+      return false;
+    }
+    let container = [...areaNodes].filter((n) => n.ownerDocument.defaultView == aWindow);
+    if (!container.length) {
+      return false;
+    }
+    let existingNode = container[0].querySelector(idToSelector(aWidgetId));
+    if (existingNode) {
+      return true;
+    }
+
+    let placementAry = gPlacements.get(placement.area);
+    let nextNodeId = placementAry[placement.position + 1];
+    this.insertNodeInWindow(aWidgetId, container[0], nextNodeId, true);
+    return true;
+  },
+
   get inDefaultState() {
     for (let [areaId, props] of gAreas) {
       let defaultPlacements = props.get("defaultPlacements");
       // Areas without default placements (like legacy ones?) get skipped
       if (!defaultPlacements) {
         continue;
       }
 
@@ -1941,16 +1969,19 @@ this.CustomizableUI = {
     CustomizableUIInternal.addWidgetToArea(aWidgetId, aArea, aPosition);
   },
   removeWidgetFromArea: function(aWidgetId) {
     CustomizableUIInternal.removeWidgetFromArea(aWidgetId);
   },
   moveWidgetWithinArea: function(aWidgetId, aPosition) {
     CustomizableUIInternal.moveWidgetWithinArea(aWidgetId, aPosition);
   },
+  ensureWidgetPlacedInWindow: function(aWidgetId, aWindow) {
+    return CustomizableUIInternal.ensureWidgetPlacedInWindow(aWidgetId, aWindow);
+  },
   beginBatchUpdate: function() {
     CustomizableUIInternal.beginBatchUpdate();
   },
   endBatchUpdate: function(aForceDirty) {
     CustomizableUIInternal.endBatchUpdate(aForceDirty);
   },
   createWidget: function(aProperties) {
     return CustomizableUIInternal.wrapWidget(