Bug 1414244 - Part 7 - Remove unused code paths from PanelMultiview.jsm. r=Gijs
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Thu, 23 Nov 2017 15:18:14 +0000
changeset 437878 0ee02ed83f71b4c4d2ed2d142eea26c5ff15081c
parent 437877 5c9a0be10b652de366b5e7b0a0b79f364278454d
child 437879 f6d80e35ce4f704e73c9073b2e56939dcde8c794
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersGijs
bugs1414244
milestone59.0a1
Bug 1414244 - Part 7 - Remove unused code paths from PanelMultiview.jsm. r=Gijs MozReview-Commit-ID: 9cwaAZXqDGO
browser/components/customizableui/CustomizableUI.jsm
browser/components/customizableui/PanelMultiView.jsm
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -1801,21 +1801,17 @@ var CustomizableUIInternal = {
     if (closemenu == "none" || widgetType == "view") {
       return;
     }
 
     if (closemenu == "single") {
       let panel = this._getPanelForNode(target);
       let multiview = panel.querySelector("panelmultiview");
       if (multiview.showingSubView) {
-        if (multiview.instance.panelViews) {
-          multiview.goBack();
-        } else {
-          multiview.showMainView();
-        }
+        multiview.goBack();
         return;
       }
     }
 
     // If we get here, we can actually hide the popup:
     this.hidePanelForNode(aEvent.target);
   },
 
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -224,24 +224,20 @@ this.PanelMultiView = class {
    * @return {panelview} the currently visible subview OR the subview that is
    *                     about to be shown whilst a 'ViewShowing' event is being
    *                     dispatched.
    */
   get current() {
     return this._viewShowing || this._currentSubView;
   }
   get _currentSubView() {
-    return this.panelViews ? this.panelViews.currentView : this.__currentSubView;
+    return this.panelViews.currentView;
   }
   set _currentSubView(panel) {
-    if (this.panelViews)
-      this.panelViews.currentView = panel;
-    else
-      this.__currentSubView = panel;
-    return panel;
+    this.panelViews.currentView = panel;
   }
   /**
    * @return {Promise} showSubView() returns a promise, which is kept here for
    *                   random access.
    */
   get currentShowPromise() {
     return this._currentShowPromise || Promise.resolve();
   }
@@ -258,50 +254,44 @@ this.PanelMultiView = class {
 
   constructor(xulNode, testMode = false) {
     this.node = xulNode;
     // If `testMode` is `true`, the consumer is only interested in accessing the
     // methods of this instance. (E.g. in unit tests.)
     if (testMode)
       return;
 
-    this._currentSubView = this._anchorElement = this._subViewObserver = null;
+    this._currentSubView = this._subViewObserver = null;
     this._mainViewHeight = 0;
     this.__transitioning = this._ignoreMutations = this._showingSubView = false;
 
     const {document, window} = this;
 
     this._viewContainer =
       document.getAnonymousElementByAttribute(this.node, "anonid", "viewContainer");
-    this._mainViewContainer =
-      document.getAnonymousElementByAttribute(this.node, "anonid", "mainViewContainer");
     this._viewStack =
       document.getAnonymousElementByAttribute(this.node, "anonid", "viewStack");
     this._offscreenViewStack =
       document.getAnonymousElementByAttribute(this.node, "anonid", "offscreenViewStack");
 
     XPCOMUtils.defineLazyGetter(this, "_panelViewCache", () => {
       let viewCacheId = this.node.getAttribute("viewCacheId");
       return viewCacheId ? document.getElementById(viewCacheId) : null;
     });
 
     this._panel.addEventListener("popupshowing", this);
     this._panel.addEventListener("popuppositioned", this);
     this._panel.addEventListener("popuphidden", this);
     this._panel.addEventListener("popupshown", this);
-    if (this.panelViews) {
-      let cs = window.getComputedStyle(document.documentElement);
-      // Set CSS-determined attributes now to prevent a layout flush when we do
-      // it when transitioning between panels.
-      this._dir = cs.direction;
-      this.setMainView(this.panelViews.currentView);
-      this.showMainView();
-    } else if (this._mainView) {
-      this.setMainView(this._mainView);
-    }
+    let cs = window.getComputedStyle(document.documentElement);
+    // Set CSS-determined attributes now to prevent a layout flush when we do
+    // it when transitioning between panels.
+    this._dir = cs.direction;
+    this.setMainView(this.panelViews.currentView);
+    this.showMainView();
 
     this._showingSubView = false;
 
     // Proxy these public properties and methods, as used elsewhere by various
     // parts of the browser, to this instance.
     ["_mainView", "ignoreMutations", "showingSubView",
      "_panelViews"].forEach(property => {
       Object.defineProperty(this.node, property, {
@@ -335,29 +325,26 @@ this.PanelMultiView = class {
       this.hideAllViewsExcept(null);
     let mainView = this._mainView;
     if (mainView) {
       if (this._panelViewCache)
         this._panelViewCache.appendChild(mainView);
       mainView.removeAttribute("mainview");
     }
 
-    if (this.panelViews) {
-      this._moveOutKids(this._viewStack);
-      this.panelViews.clear();
-    }
+    this._moveOutKids(this._viewStack);
+    this.panelViews.clear();
     this._panel.removeEventListener("mousemove", this);
     this._panel.removeEventListener("popupshowing", this);
     this._panel.removeEventListener("popuppositioned", this);
     this._panel.removeEventListener("popupshown", this);
     this._panel.removeEventListener("popuphidden", this);
     this.window.removeEventListener("keydown", this);
-    this.node = this._viewContainer = this._mainViewContainer =
-      this._viewStack = this.__dwu = this._panelViewCache =
-        this._transitionDetails = null;
+    this.node = this._viewContainer = this._viewStack = this.__dwu =
+      this._panelViewCache = this._transitionDetails = null;
   }
 
   /**
    * Remove any child subviews into the panelViewCache, to ensure
    * they remain usable even if this panelmultiview instance is removed
    * from the DOM.
    * @param viewNodeContainer the container from which to remove subviews
    */
@@ -371,21 +358,19 @@ this.PanelMultiView = class {
     for (let subview of subviews) {
       // XBL lists the 'children' XBL element explicitly. :-(
       if (subview.nodeName != "children")
         this._panelViewCache.appendChild(subview);
     }
   }
 
   _placeSubView(viewNode) {
-    if (this.panelViews) {
-      this._viewStack.appendChild(viewNode);
-      if (!this.panelViews.includes(viewNode))
-        this.panelViews.push(viewNode);
-    }
+    this._viewStack.appendChild(viewNode);
+    if (!this.panelViews.includes(viewNode))
+      this.panelViews.push(viewNode);
   }
 
   goBack(target) {
     let [current, previous] = this.panelViews.back();
     return this.showSubView(current, target, previous);
   }
 
   /**
@@ -403,46 +388,29 @@ this.PanelMultiView = class {
     if (!aNewMainView)
       return;
 
     if (this._mainView) {
       this._mainView.removeAttribute("mainview");
     }
     this._mainViewId = aNewMainView.id;
     aNewMainView.setAttribute("mainview", "true");
-    if (this.panelViews) {
-      // If the new main view is not yet in the zeroth position, make sure it's
-      // inserted there.
-      if (aNewMainView.parentNode != this._viewStack && this._viewStack.firstChild != aNewMainView) {
-        this._viewStack.insertBefore(aNewMainView, this._viewStack.firstChild);
-      }
-    } else {
-      this._mainViewContainer.appendChild(aNewMainView);
+    // If the new main view is not yet in the zeroth position, make sure it's
+    // inserted there.
+    if (aNewMainView.parentNode != this._viewStack &&
+        this._viewStack.firstChild != aNewMainView) {
+      this._viewStack.insertBefore(aNewMainView, this._viewStack.firstChild);
     }
   }
 
   showMainView() {
     if (!this._mainViewId)
       return Promise.resolve();
 
-    if (this.panelViews)
-      return this.showSubView(this._mainView);
-
-    if (this.showingSubView) {
-      let viewNode = this._currentSubView;
-      this._dispatchViewEvent(viewNode, "ViewHiding");
-      this._transitionHeight(() => {
-        viewNode.removeAttribute("current");
-        this._currentSubView = null;
-        this._showingSubView = false;
-      });
-    }
-
-    this._shiftMainView();
-    return Promise.resolve();
+    return this.showSubView(this._mainView);
   }
 
   /**
    * Ensures that all the panelviews, that are currently part of this instance,
    * are hidden, except one specifically.
    *
    * @param {panelview} [theOne] The panelview DOM node to ensure is visible.
    *                             Optional.
@@ -489,54 +457,49 @@ this.PanelMultiView = class {
       let reverse = !!aPreviousView;
       let previousViewNode = aPreviousView || this._currentSubView;
       // If the panelview to show is the same as the previous one, the 'ViewShowing'
       // event has already been dispatched. Don't do it twice.
       let showingSameView = viewNode == previousViewNode;
       let playTransition = (!!previousViewNode && !showingSameView && this._panel.state == "open");
       let isMainView = viewNode.id == this._mainViewId;
 
-      let dwu, previousRect;
-      if (playTransition || this.panelViews) {
-        dwu = this._dwu;
-        previousRect = previousViewNode.__lastKnownBoundingRect =
+      let dwu = this._dwu;
+      let previousRect = previousViewNode.__lastKnownBoundingRect =
           dwu.getBoundsWithoutFlushing(previousViewNode);
-        if (this.panelViews) {
-          // Cache the measures that have the same caching lifetime as the width
-          // or height of the main view, i.e. whilst the panel is shown and/ or
-          // visible.
-          if (!this._mainViewWidth) {
-            this._mainViewWidth = previousRect.width;
-            let top = dwu.getBoundsWithoutFlushing(previousViewNode.firstChild || previousViewNode).top;
-            let bottom = dwu.getBoundsWithoutFlushing(previousViewNode.lastChild || previousViewNode).bottom;
-            this._viewVerticalPadding = previousRect.height - (bottom - top);
-          }
-          if (!this._mainViewHeight) {
-            this._mainViewHeight = previousRect.height;
-            this._viewContainer.style.minHeight = this._mainViewHeight + "px";
-          }
-        }
+      // Cache the measures that have the same caching lifetime as the width
+      // or height of the main view, i.e. whilst the panel is shown and/ or
+      // visible.
+      if (!this._mainViewWidth) {
+        this._mainViewWidth = previousRect.width;
+        let top = dwu.getBoundsWithoutFlushing(previousViewNode.firstChild || previousViewNode).top;
+        let bottom = dwu.getBoundsWithoutFlushing(previousViewNode.lastChild || previousViewNode).bottom;
+        this._viewVerticalPadding = previousRect.height - (bottom - top);
+      }
+      if (!this._mainViewHeight) {
+        this._mainViewHeight = previousRect.height;
+        this._viewContainer.style.minHeight = this._mainViewHeight + "px";
       }
 
       this._viewShowing = viewNode;
       // Because the 'mainview' attribute may be out-of-sync, due to view node
       // reparenting in combination with ephemeral PanelMultiView instances,
       // this is the best place to correct it (just before showing).
       if (isMainView)
         viewNode.setAttribute("mainview", true);
       else
         viewNode.removeAttribute("mainview");
 
       // Make sure that new panels always have a title set.
-      if (this.panelViews && aAnchor) {
+      if (aAnchor) {
         if (!viewNode.hasAttribute("title"))
           viewNode.setAttribute("title", aAnchor.getAttribute("label"));
         viewNode.classList.add("PanelUI-subView");
       }
-      if (this.panelViews && !isMainView && this._mainViewWidth)
+      if (!isMainView && this._mainViewWidth)
         viewNode.style.maxWidth = viewNode.style.minWidth = this._mainViewWidth + "px";
 
       if (!showingSameView || !viewNode.hasAttribute("current")) {
         // Emit the ViewShowing event so that the widget definition has a chance
         // to lazily populate the subview with things or perhaps even cancel this
         // whole operation.
         let detail = {
           blockers: new Set(),
@@ -556,37 +519,24 @@ this.PanelMultiView = class {
         }
 
         if (cancel) {
           this._viewShowing = null;
           return;
         }
       }
 
-      // Now we have to transition the panel.
-      if (this.panelViews) {
-        // If we've got an older transition still running, make sure to clean it up.
-        await this._cleanupTransitionPhase();
-        if (playTransition) {
-          await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
-          this._updateKeyboardFocus(viewNode);
-        } else {
-          this.hideAllViewsExcept(viewNode);
-        }
+      // Now we have to transition the panel. If we've got an older transition
+      // still running, make sure to clean it up.
+      await this._cleanupTransitionPhase();
+      if (playTransition) {
+        await this._transitionViews(previousViewNode, viewNode, reverse, previousRect, aAnchor);
+        this._updateKeyboardFocus(viewNode);
       } else {
-        this._currentSubView = viewNode;
-        this._transitionHeight(() => {
-          viewNode.setAttribute("current", true);
-          this._showingSubView = viewNode.id != this._mainViewId;
-          // Now that the subview is visible, we can check the height of the
-          // description elements it contains.
-          this.descriptionHeightWorkaround(viewNode);
-          this._dispatchViewEvent(viewNode, "ViewShown");
-        });
-        this._shiftMainView(aAnchor);
+        this.hideAllViewsExcept(viewNode);
       }
     })().catch(e => Cu.reportError(e));
     return this._currentShowPromise;
   }
 
   /**
    * Apply a transition to 'slide' from the currently active view to the next
    * one.
@@ -869,119 +819,16 @@ this.PanelMultiView = class {
     // due to small rounding errors. So, we just use a value that makes
     // sense for all platforms. If the arrow visuals change significantly,
     // this value will be easy to adjust.
     const EXTRA_MARGIN_PX = 20;
     maxHeight -= EXTRA_MARGIN_PX;
     return maxHeight;
   }
 
-  /**
-   * Applies the height transition for which <panelmultiview> is designed.
-   *
-   * The height transition involves two elements, the viewContainer and its only
-   * immediate child the viewStack. In order for this to work correctly, the
-   * viewContainer must have "overflow: hidden;" and the two elements must have
-   * no margins or padding. This means that the height of the viewStack is never
-   * limited by the viewContainer, but when the height of the container is not
-   * constrained it matches the height of the viewStack.
-   *
-   * @param changeFn
-   *        This synchronous function is called to make the DOM changes
-   *        that will result in a new height of the viewStack.
-   */
-  _transitionHeight(changeFn) {
-    if (this._panel.state != "open") {
-      changeFn();
-      return;
-    }
-
-    // Lock the dimensions of the window that hosts the popup panel. This
-    // in turn constrains the height of the viewContainer.
-    let rect = this._panel.popupBoxObject.getOuterScreenRect();
-    this._panel.setAttribute("width", rect.width);
-    this._panel.setAttribute("height", rect.height);
-
-    // Read the current height of the viewStack. If we are in the middle
-    // of a transition, this is the actual height of the element at this
-    // point in time.
-    let oldHeight = this._dwu.getBoundsWithoutFlushing(this._viewStack).height;
-
-    // Make the necessary DOM changes, and remove the "height" property of the
-    // viewStack to ensure that we read its final value even if we are in the
-    // middle of a transition. To avoid flickering, we have to prevent the panel
-    // from being painted in this temporary state, which requires a synchronous
-    // layout when reading the new height.
-    this._viewStack.style.removeProperty("height");
-    changeFn();
-    let newHeight = this._viewStack.getBoundingClientRect().height;
-
-    // Now we can allow the popup panel to resize again. This must occur
-    // in the same tick as the code below, but we can do this before
-    // setting the starting height in case the transition is not needed.
-    this._panel.removeAttribute("width");
-    this._panel.removeAttribute("height");
-
-    if (oldHeight != newHeight) {
-      // Height transitions can only occur between two numeric values, and
-      // cannot start if the height is not set. In case a transition is
-      // needed, we have to set the height to the old value, then force a
-      // synchronous layout so the panel won't resize unexpectedly.
-      this._viewStack.style.height = oldHeight + "px";
-      this._viewStack.getBoundingClientRect().height;
-
-      // We can now set the new height to start the transition, but
-      // before doing that we set up a listener to reset the height to
-      // "auto" at the end, so that DOM changes made after the
-      // transition ends are still reflected by the height of the panel.
-      let onTransitionEnd = event => {
-        if (event.target != this._viewStack) {
-          return;
-        }
-        this._viewStack.removeEventListener("transitionend", onTransitionEnd);
-        this._viewStack.style.removeProperty("height");
-      };
-      this._viewStack.addEventListener("transitionend", onTransitionEnd);
-      this._viewStack.style.height = newHeight + "px";
-    }
-  }
-
-  _shiftMainView(aAnchor) {
-    if (aAnchor) {
-      // We need to find the edge of the anchor, relative to the main panel.
-      // Then we need to add half the width of the anchor. This is the target
-      // that we need to transition to.
-      let anchorRect = aAnchor.getBoundingClientRect();
-      let mainViewRect = this._mainViewContainer.getBoundingClientRect();
-      let center = aAnchor.clientWidth / 2;
-      let direction = aAnchor.ownerGlobal.getComputedStyle(aAnchor).direction;
-      let edge;
-      if (direction == "ltr") {
-        edge = anchorRect.left - mainViewRect.left;
-      } else {
-        edge = mainViewRect.right - anchorRect.right;
-      }
-
-      // If the anchor is an element on the far end of the mainView we
-      // don't want to shift the mainView too far, we would reveal empty
-      // space otherwise.
-      let maxShift = mainViewRect.width - 38;
-      let target = Math.min(maxShift, edge + center);
-
-      let neg = direction == "ltr" ? "-" : "";
-      this._mainViewContainer.style.transform = `translateX(${neg}${target}px)`;
-      aAnchor.setAttribute("panel-multiview-anchor", true);
-    } else {
-      this._mainViewContainer.style.transform = "";
-      if (this.anchorElement)
-        this.anchorElement.removeAttribute("panel-multiview-anchor");
-    }
-    this.anchorElement = aAnchor;
-  }
-
   handleEvent(aEvent) {
     if (aEvent.type.startsWith("popup") && aEvent.target != this._panel) {
       // Shouldn't act on e.g. context menus being shown from within the panel.
       return;
     }
     switch (aEvent.type) {
       case "keydown":
         this._keyNavigation(aEvent);
@@ -1020,37 +867,35 @@ this.PanelMultiView = class {
         break;
       case "popuphidden": {
         // WebExtensions consumers can hide the popup from viewshowing, or
         // mid-transition, which disrupts our state:
         this._viewShowing = null;
         this._transitioning = false;
         this.node.removeAttribute("panelopen");
         this.showMainView();
-        if (this.panelViews) {
-          for (let panelView of this._viewStack.children) {
-            if (panelView.nodeName != "children") {
-              panelView.__lastKnownBoundingRect = null;
-              panelView.style.removeProperty("min-width");
-              panelView.style.removeProperty("max-width");
-            }
+        for (let panelView of this._viewStack.children) {
+          if (panelView.nodeName != "children") {
+            panelView.__lastKnownBoundingRect = null;
+            panelView.style.removeProperty("min-width");
+            panelView.style.removeProperty("max-width");
           }
-          this.window.removeEventListener("keydown", this);
-          this._panel.removeEventListener("mousemove", this);
-          this._resetKeyNavigation();
+        }
+        this.window.removeEventListener("keydown", this);
+        this._panel.removeEventListener("mousemove", this);
+        this._resetKeyNavigation();
 
-          // Clear the main view size caches. The dimensions could be different
-          // when the popup is opened again, e.g. through touch mode sizing.
-          this._mainViewHeight = 0;
-          this._mainViewWidth = 0;
-          this._viewContainer.style.removeProperty("min-height");
-          this._viewStack.style.removeProperty("max-height");
-          this._viewContainer.style.removeProperty("min-width");
-          this._viewContainer.style.removeProperty("max-width");
-        }
+        // Clear the main view size caches. The dimensions could be different
+        // when the popup is opened again, e.g. through touch mode sizing.
+        this._mainViewHeight = 0;
+        this._mainViewWidth = 0;
+        this._viewContainer.style.removeProperty("min-height");
+        this._viewStack.style.removeProperty("max-height");
+        this._viewContainer.style.removeProperty("min-width");
+        this._viewContainer.style.removeProperty("max-width");
 
         this._dispatchViewEvent(this.node, "PanelMultiViewHidden");
         break;
       }
     }
   }
 
   /**