Bug 1639925 - implement 'wrap' support in toolbarbuttons on a single element instead of 2, r=bgrins
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Wed, 27 May 2020 23:01:15 +0000
changeset 532628 983a55f50d600f5055cce1c990c56c607d3d3e3a
parent 532627 095ff1c0aa57ad554330a41fb6ff10f1f96354ec
child 532629 38dea55d2978cfe2d15b76734747b049705fb1bb
push id37457
push usernerli@mozilla.com
push dateThu, 28 May 2020 15:51:15 +0000
treeherdermozilla-central@272e3c98d002 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbgrins
bugs1639925
milestone78.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1639925 - implement 'wrap' support in toolbarbuttons on a single element instead of 2, r=bgrins This unifies toolbarbutton-text and toolbarbutton-multiline-text. We now always use toolbarbutton-text for the button's text, but can either use textContent or the value attribute, depending on the value of the wrap attribute. This reduces DOM size and consumer complexity, at the cost of adding some logic to toolbarbutton.js itself. Differential Revision: https://phabricator.services.mozilla.com/D76383
browser/themes/shared/customizableui/panelUI.inc.css
toolkit/content/widgets/toolbarbutton.js
toolkit/content/xul.css
xpcom/ds/StaticAtoms.py
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -360,17 +360,17 @@ panelview {
   }
 }
 
 panelview[id^=PanelUI-webext-] {
   overflow: hidden;
 }
 
 panelview:not([mainview]) .toolbarbutton-text,
-.cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text,
+.cui-widget-panel .toolbarbutton-text,
 #overflowMenu-customize-button > .toolbarbutton-text {
   text-align: start;
   display: -moz-box;
 }
 
 .cui-widget-panel,
 .cui-widget-panel::part(arrowcontent) {
   --arrowpanel-padding: 4px 0;
@@ -1016,17 +1016,16 @@ panelmultiview[mainViewId="PanelUI-fxa"]
 :root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover {
   background-color: @appmenuWarningBackgroundColorHoverBrightText@;
 }
 
 :root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):active {
   background-color: @appmenuWarningBackgroundColorActiveBrightText@;
 }
 
-#customization-palette .toolbarbutton-multiline-text,
 #customization-palette .toolbarbutton-text {
   display: none;
 }
 
 .subview-subheader,
 panelview .toolbarbutton-1,
 .subviewbutton,
 .widget-overflow-list .toolbarbutton-1 {
@@ -1079,22 +1078,16 @@ panelview .toolbarbutton-1,
 .subviewbutton[image] > .toolbarbutton-text,
 .subviewbutton[targetURI] > .toolbarbutton-text,
 .subviewbutton.restoreallitem > .toolbarbutton-text,
 .subviewbutton.bookmark-item > .toolbarbutton-text,
 .subviewbutton[checked="true"] > .toolbarbutton-text {
   padding-inline-start: 8px; /* See '.subviewbutton-iconic > .toolbarbutton-text' rule above. */
 }
 
-.panel-banner-item > .toolbarbutton-multiline-text {
-  margin: 0;
-  padding: 0;
-  padding-inline-start: 8px; /* See '.subviewbutton-iconic > .toolbarbutton-text' rule above. */
-}
-
 .subviewbutton-iconic > .toolbarbutton-icon {
   width: 16px;
   height: 16px;
   -moz-context-properties: fill;
   fill: currentColor;
 }
 
 /* We don't always display: none this item, and if it has forced width (like above)
@@ -1741,17 +1734,17 @@ toolbarpaletteitem[place="menu-panel"] >
   padding: 8px;
 }
 
 .subviewbutton-back:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
 }
 
 .subviewbutton-back > .toolbarbutton-text {
-  /* !important to override .cui-widget-panel toolbarbutton:not([wrap]) > .toolbarbutton-text
+  /* !important to override .cui-widget-panel .toolbarbutton-text
    * selector further down. */
   display: none !important;
 }
 
 .subviewbutton.download {
   -moz-box-align: start;
   min-height: 48px;
   padding-inline-start: 8px;
--- a/toolkit/content/widgets/toolbarbutton.js
+++ b/toolkit/content/widgets/toolbarbutton.js
@@ -27,49 +27,48 @@
         el.render();
       }
     },
     { capture: true }
   );
 
   class MozToolbarbutton extends MozElements.ButtonBase {
     static get inheritedAttributes() {
+      // Note: if you remove 'wrap' or 'label' from the inherited attributes,
+      // you'll need to add them to observedAttributes.
       return {
         ".toolbarbutton-icon":
           "validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal",
-        ".toolbarbutton-text": "value=label,accesskey,crop,dragover-top,wrap",
-        ".toolbarbutton-multiline-text": "text=label,accesskey,wrap",
+        ".toolbarbutton-text": "accesskey,crop,dragover-top,wrap",
         ".toolbarbutton-menu-dropmarker": "disabled,label",
 
         ".toolbarbutton-badge": "text=badge,style=badgeStyle",
       };
     }
 
     static get fragment() {
       let frag = document.importNode(
         MozXULElement.parseXULToFragment(`
         <image class="toolbarbutton-icon"></image>
         <label class="toolbarbutton-text" crop="right" flex="1"></label>
-        <label class="toolbarbutton-multiline-text" flex="1"></label>
         `),
         true
       );
       Object.defineProperty(this, "fragment", { value: frag });
       return frag;
     }
 
     static get badgedFragment() {
       let frag = document.importNode(
         MozXULElement.parseXULToFragment(`
         <stack class="toolbarbutton-badge-stack">
           <image class="toolbarbutton-icon"/>
           <html:label class="toolbarbutton-badge"/>
         </stack>
         <label class="toolbarbutton-text" crop="right" flex="1"/>
-        <label class="toolbarbutton-multiline-text" flex="1"/>
         `),
         true
       );
       Object.defineProperty(this, "badgedFragment", { value: frag });
       return frag;
     }
 
     static get dropmarkerFragment() {
@@ -82,16 +81,52 @@
       Object.defineProperty(this, "dropmarkerFragment", { value: frag });
       return frag;
     }
 
     get _hasRendered() {
       return this.querySelector(":scope > .toolbarbutton-text") != null;
     }
 
+    get _textNode() {
+      let node = this.getElementForAttrInheritance(".toolbarbutton-text");
+      if (node) {
+        Object.defineProperty(this, "_textNode", { value: node });
+      }
+      return node;
+    }
+
+    _setLabel() {
+      let label = this.getAttribute("label") || "";
+      let hasLabel = this.hasAttribute("label");
+      if (this.getAttribute("wrap") == "true") {
+        this._textNode.removeAttribute("value");
+        this._textNode.textContent = label;
+      } else {
+        this._textNode.textContent = "";
+        if (hasLabel) {
+          this._textNode.setAttribute("value", label);
+        } else {
+          this._textNode.removeAttribute("value");
+        }
+      }
+    }
+
+    attributeChangedCallback(name, oldValue, newValue) {
+      if (oldValue === newValue || !this.initializedAttributeInheritance) {
+        return;
+      }
+      // Deal with single/multiline label inheritance:
+      if (name == "label" || name == "wrap") {
+        this._setLabel();
+      }
+      // The normal implementation will deal with everything else.
+      super.attributeChangedCallback(name, oldValue, newValue);
+    }
+
     connectedCallback() {
       if (this.delayConnectedCallback()) {
         return;
       }
 
       // Defer creating DOM elements for content inside popups.
       // These will be added in the popupshown handler above.
       let panel = this.closest("panel");
@@ -152,32 +187,36 @@
         // XBL toolbarbutton explicitly places any <box> children
         // right before the menu marker.
         for (let child of moveChildren) {
           this.insertBefore(child, this.lastChild);
         }
       }
 
       this.initializeAttributeInheritance();
+      this._setLabel();
     }
 
     get icon() {
       return this.querySelector(".toolbarbutton-icon");
     }
 
     get badgeLabel() {
       return this.querySelector(".toolbarbutton-badge");
     }
 
     get badgeStack() {
       return this.querySelector(".toolbarbutton-badge-stack");
     }
 
     get multilineLabel() {
-      return this.querySelector(".toolbarbutton-multiline-text");
+      if (this.getAttribute("wrap") == "true") {
+        return this._textNode;
+      }
+      return null;
     }
 
     get dropmarker() {
       return this.querySelector(".toolbarbutton-menu-dropmarker");
     }
 
     get menupopup() {
       return this.querySelector("menupopup");
--- a/toolkit/content/xul.css
+++ b/toolkit/content/xul.css
@@ -113,20 +113,17 @@ label.text-link, label[onclick] {
 label html|span.accesskey {
   text-decoration: underline;
   text-decoration-skip-ink: none;
 }
 
 /********** toolbarbutton **********/
 
 toolbar[mode="icons"] .toolbarbutton-text,
-toolbar[mode="icons"] .toolbarbutton-multiline-text,
 toolbar[mode="text"] .toolbarbutton-icon,
-.toolbarbutton-multiline-text:not([wrap="true"]),
-.toolbarbutton-text[wrap="true"],
 html|label.toolbarbutton-badge:empty {
   display: none;
 }
 
 /******** browser, editor, iframe ********/
 
 browser,
 editor,
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -1194,17 +1194,16 @@ STATIC_ATOMS = [
     Atom("time", "time"),
     Atom("title", "title"),
     Atom("titlebar", "titlebar"),
     Atom("titletip", "titletip"),
     Atom("token", "token"),
     Atom("tokenize", "tokenize"),
     Atom("toolbar", "toolbar"),
     Atom("toolbarbutton", "toolbarbutton"),
-    Atom("toolbarbuttonMultilineText", "toolbarbutton-multiline-text"),
     Atom("toolbaritem", "toolbaritem"),
     Atom("toolbarpaletteitem", "toolbarpaletteitem"),
     Atom("toolbox", "toolbox"),
     Atom("tooltip", "tooltip"),
     Atom("tooltiptext", "tooltiptext"),
     Atom("top", "top"),
     Atom("topleft", "topleft"),
     Atom("topmargin", "topmargin"),