Bug 1354127 - Add a 'More' toolbar button to the Photon app menu. r?Gijs draft
authorMike de Boer <mdeboer@mozilla.com>
Thu, 11 May 2017 16:23:16 -0400
changeset 576541 5c3f13bf81adf903f0e7664224e5a6f68ff34986
parent 576334 3b96f277325747fe668ca8cd896d2f581238e4ee
child 576989 62d34eab52160caf66331ac0b6825fdc1a643283
child 576994 cdb9e056ac14e4189179b6576439dd476b93b56b
push id58398
push usermdeboer@mozilla.com
push dateThu, 11 May 2017 20:26:05 +0000
reviewersGijs
bugs1354127
milestone55.0a1
Bug 1354127 - Add a 'More' toolbar button to the Photon app menu. r?Gijs This also improves the styling of checkbox buttons inside the menu and improves support for adopting panelviews into the app menu from another area properly. MozReview-Commit-ID: 1I9CeBx3zrz
browser/components/customizableui/CustomizableWidgets.jsm
browser/components/customizableui/PanelMultiView.jsm
browser/components/customizableui/content/panelUI.inc.xul
browser/components/customizableui/content/panelUI.js
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/shared/customizableui/panelUI.inc.css
browser/themes/shared/jar.inc.mn
browser/themes/shared/menu-icons/check.svg
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -1069,16 +1069,19 @@ const CustomizableWidgets = [
           if (aWidgetId != this.id || aDoc != document)
             return;
 
           CustomizableUI.removeListener(listener);
           getPanel().removeEventListener("popupshowing", updateButton);
         }
       };
       CustomizableUI.addListener(listener);
+      this.onInit();
+    },
+    onInit() {
       if (!this.charsetInfo) {
         this.charsetInfo = CharsetMenu.getData();
       }
     }
   }, {
     id: "email-link-button",
     tooltiptext: "email-link-button.tooltiptext3",
     onCommand(aEvent) {
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -3,16 +3,20 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 this.EXPORTED_SYMBOLS = ["PanelMultiView"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableWidgets",
+  "resource:///modules/CustomizableWidgets.jsm");
+
 /**
  * Simple implementation of the sliding window pattern; panels are added to a
  * linked list, in-order, and the currently shown panel is remembered using a
  * marker. The marker shifts as navigation between panels is continued, where
  * the panel at index 0 is always the starting point:
  *           ┌────┬────┬────┬────┐
  *           │▓▓▓▓│    │    │    │ Start
  *           └────┴────┴────┴────┘
@@ -349,17 +353,17 @@ this.PanelMultiView = class {
 
         this.node.setAttribute("viewtype", "main");
       }
 
       this._shiftMainView();
     }
   }
 
-  showSubView(aViewId, aAnchor, aPreviousView) {
+  showSubView(aViewId, aAnchor, aPreviousView, aAdopted = false) {
     const {document, window} = this;
     return window.Task.spawn(function*() {
       // Support passing in the node directly.
       let viewNode = typeof aViewId == "string" ? this.node.querySelector("#" + aViewId) : aViewId;
       if (!viewNode) {
         viewNode = document.getElementById(aViewId);
         if (viewNode) {
           if (this.panelViews) {
@@ -378,27 +382,40 @@ this.PanelMultiView = class {
       let playTransition = (!!previousViewNode && previousViewNode != viewNode);
 
       let dwu, previousRect;
       if (playTransition) {
         dwu = this._dwu;
         previousRect = previousViewNode.__lastKnownBoundingRect =
           dwu.getBoundsWithoutFlushing(previousViewNode);
       }
-      viewNode.setAttribute("current", true);
 
       // Emit the ViewShowing event so that the widget definition has a chance
       // to lazily populate the subview with things.
       let detail = {
         blockers: new Set(),
         addBlocker(aPromise) {
           this.blockers.add(aPromise);
         },
       };
 
+      // Make sure that new panels always have a title set.
+      if (this.panelViews && aAdopted && aAnchor) {
+        if (aAnchor && !viewNode.hasAttribute("title"))
+          viewNode.setAttribute("title", aAnchor.getAttribute("label"));
+        viewNode.classList.add("PanelUI-subView");
+        let custWidget = CustomizableWidgets.find(widget => widget.viewId == viewNode.id);
+        if (custWidget) {
+          if (custWidget.onInit)
+            custWidget.onInit(aAnchor);
+          custWidget.onViewShowing({ target: aAnchor, detail });
+        }
+      }
+      viewNode.setAttribute("current", true);
+
       let evt = new window.CustomEvent("ViewShowing", { bubbles: true, cancelable: true, detail });
       viewNode.dispatchEvent(evt);
 
       let cancel = evt.defaultPrevented;
       if (detail.blockers.size) {
         try {
           let results = yield window.Promise.all(detail.blockers);
           cancel = cancel || results.some(val => val === false);
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -493,17 +493,17 @@
        class="cui-widget-panel"
        role="group"
        type="arrow"
        hidden="true"
        flip="slide"
        position="bottomcenter topright"
        noautofocus="true">
   <photonpanelmultiview id="appMenu-multiView" mainViewId="appMenu-mainView">
-    <panelview id="appMenu-mainView" class="cui-widget-panelview PanelUI-subView">
+    <panelview id="appMenu-mainView" class="PanelUI-subView">
       <vbox class="panel-subview-body">
         <vbox id="appMenu-addon-banners"/>
         <toolbarbutton class="panel-banner-item"
                        label-update-available="&updateAvailable.panelUI.label;"
                        label-update-manual="&updateManual.panelUI.label;"
                        label-update-restart="&updateRestart.panelUI.label;"
                        oncommand="PanelUI._onBannerItemSelected(event)"
                        wrap="true"
@@ -570,12 +570,33 @@
 #endif
                        oncommand="openPreferences()"
                        />
         <toolbarbutton id="appMenu-customize-button"
                        class="subviewbutton subviewbutton-iconic"
                        label="&viewCustomizeToolbar.label;"
                        command="cmd_CustomizeToolbars"
                        />
+        <toolbarseparator/>
+        <toolbarbutton id="appMenu-more-button"
+                       class="subviewbutton subviewbutton-nav"
+                       label="&moreMenu.label;"
+                       closemenu="none"
+                       oncommand="PanelUI.showSubView('appMenu-moreView', this)"/>
+      </vbox>
+    </panelview>
+    <panelview id="appMenu-moreView" title="&moreMenu.label;" class="PanelUI-subView">
+      <vbox class="panel-subview-body">
+        <toolbarbutton id="appMenu-characterencoding-button"
+                       class="subviewbutton subviewbutton-nav"
+                       label="&charsetMenu2.label;"
+                       closemenu="none"
+                       oncommand="PanelUI.showSubView('PanelUI-characterEncodingView', this, null, true)"/>
+        <toolbarbutton id="appMenu-workoffline-button"
+                       class="subviewbutton"
+                       label="&goOfflineCmd.label;"
+                       type="checkbox"
+                       observes="workOfflineMenuitemState"
+                       oncommand="BrowserOffline.toggleOfflineStatus();"/>
       </vbox>
     </panelview>
   </photonpanelmultiview>
 </panel>
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -477,32 +477,32 @@ const PanelUI = {
 
   /**
    * Shows a subview in the panel with a given ID.
    *
    * @param aViewId the ID of the subview to show.
    * @param aAnchor the element that spawned the subview.
    * @param aPlacementArea the CustomizableUI area that aAnchor is in.
    */
-  showSubView: Task.async(function*(aViewId, aAnchor, aPlacementArea) {
+  showSubView: Task.async(function*(aViewId, aAnchor, aPlacementArea, aAdopted = false) {
     this._ensureEventListenersAdded();
     let viewNode = document.getElementById(aViewId);
     if (!viewNode) {
       Cu.reportError("Could not show panel subview with id: " + aViewId);
       return;
     }
 
     if (!aAnchor) {
       Cu.reportError("Expected an anchor when opening subview with id: " + aViewId);
       return;
     }
 
     let container = aAnchor.closest("panelmultiview,photonpanelmultiview");
     if (container) {
-      container.showSubView(aViewId, aAnchor);
+      container.showSubView(aViewId, aAnchor, null, aAdopted);
     } else if (!aAnchor.open) {
       aAnchor.open = true;
 
       let tempPanel = document.createElement("panel");
       tempPanel.setAttribute("type", "arrow");
       tempPanel.setAttribute("id", "customizationui-widget-panel");
       tempPanel.setAttribute("class", "cui-widget-panel");
       tempPanel.setAttribute("viewId", aViewId);
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -393,16 +393,18 @@ These should match what Safari and other
 <!ENTITY customizeMenu.moveToPanel.accesskey "o">
 <!ENTITY customizeMenu.removeFromToolbar.label "Remove from Toolbar">
 <!ENTITY customizeMenu.removeFromToolbar.accesskey "R">
 <!ENTITY customizeMenu.removeFromMenu.label "Remove from Menu">
 <!ENTITY customizeMenu.removeFromMenu.accesskey "R">
 <!ENTITY customizeMenu.addMoreItems.label "Add More Items…">
 <!ENTITY customizeMenu.addMoreItems.accesskey "A">
 
+<!ENTITY moreMenu.label "More">
+
 <!ENTITY openCmd.commandkey           "l">
 <!ENTITY urlbar.placeholder2          "Search or enter address">
 <!ENTITY urlbar.accesskey             "d">
 <!-- LOCALIZATION NOTE (urlbar.extension.label): Used to indicate that a selected autocomplete entry is provided by an extension. -->
 <!ENTITY urlbar.extension.label       "Extension:">
 <!ENTITY urlbar.switchToTab.label     "Switch to tab:">
 
 <!ENTITY urlbar.searchSuggestionsNotification.question "Would you like to improve your search experience with suggestions?">
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -218,17 +218,18 @@ panelmultiview[nosubviews=true] > .panel
 
 .panel-subview-header {
   margin: -4px -4px 4px;
   border-bottom: 1px solid var(--panel-separator-color);
   color: GrayText;
   font-variant: small-caps;
 }
 
-.cui-widget-panelview .panel-subview-header {
+.cui-widget-panelview .panel-subview-header,
+photonpanelmultiview .panel-subview-header {
   display: none;
 }
 
 .cui-widget-panelview .subviewbutton.panel-subview-footer {
   margin: 4px 0 0;
   -moz-box-pack: center;
 }
 
@@ -328,16 +329,21 @@ panelview:not([mainview]) .toolbarbutton
 #appMenu-popup > .panel-arrowcontainer > .panel-arrowcontent {
   padding: 0;
   margin: 0;
   border-radius: 0;
 }
 
 photonpanelmultiview panelview {
   background: var(--arrowpanel-background);
+  padding: 6px 0;
+}
+
+photonpanelmultiview panelview[title] {
+  padding-top: 0;
 }
 
 photonpanelmultiview .panel-subview-body {
   /*XXXmikedeboer this flex is unnecessary, so I unset it for our case. It might
                   break other panels, though, so I refrain from removing it above. */
   -moz-box-flex: unset;
 }
 
@@ -1119,16 +1125,17 @@ panelview:not([mainView]) .subviewbutton
   float: right;
 }
 
 .PanelUI-subView .subviewbutton-nav:-moz-locale-dir(ltr)::after {
   transform: scaleX(-1);
 }
 
 .PanelUI-subView.cui-widget-panelview .subviewbutton[shortcut]::after,
+photonpanelmultiview .PanelUI-subView .subviewbutton[shortcut]::after,
 .PanelUI-subView .subviewbutton-nav::after {
   margin-inline-start: 10px;
 }
 
 /* This is a <label> but it should fit in with the menu font- and colorwise. */
 #PanelUI-characterEncodingView-autodetect-label {
   font: menu;
   color: inherit;
@@ -1136,36 +1143,48 @@ panelview:not([mainView]) .subviewbutton
 
 .cui-widget-panelview .subviewbutton:not(.panel-subview-footer) {
   margin-left: 4px;
   margin-right: 4px;
 }
 
 /* START photon adjustments */
 
-photonpanelmultiview .cui-widget-panelview .subviewbutton:not(.panel-subview-footer) {
+photonpanelmultiview .PanelUI-subView .subviewbutton:not(.panel-subview-footer) {
   border-radius: 0;
   border-width: 0;
   margin-left: 0;
   margin-right: 0;
   padding: 4px 12px;
 }
 
-photonpanelmultiview .subviewbutton-iconic:not(.subviewbutton-back) > .toolbarbutton-text {
+photonpanelmultiview .subviewbutton-iconic:not(.subviewbutton-back) > .toolbarbutton-text,
+photonpanelmultiview .subviewbutton[checked="true"] > .toolbarbutton-text {
   padding-inline-start: 8px; /* See '.subviewbutton-iconic > .toolbarbutton-text' rule above. */
 }
 
-photonpanelmultiview .subviewbutton:not(.subviewbutton-iconic) > .toolbarbutton-text {
+photonpanelmultiview .subviewbutton:not(.subviewbutton-iconic):not([checked="true"]) > .toolbarbutton-text {
   padding-inline-start: 24px; /* This is 16px for the icon + 8px for the padding as defined above. */
 }
 
-photonpanelmultiview .cui-widget-panelview .panel-subview-footer {
+photonpanelmultiview .PanelUI-subView .panel-subview-footer {
   font-size: 1.2rem;
 }
 
+photonpanelmultiview .subviewbutton[checked="true"] {
+  background: none;
+  list-style-image: url(chrome://browser/skin/menu-icons/check.svg);
+  -moz-context-properties: fill;
+}
+
+photonpanelmultiview .subviewbutton > .menu-iconic-left {
+  -moz-appearance: none;
+  margin-inline-end: 0;
+}
+
 /* END photon adjustments */
 
 panelview .toolbarbutton-1,
 .widget-overflow-list > .toolbarbutton-1:not(:first-child),
 .widget-overflow-list > toolbaritem:not(:first-child) {
   margin-top: 6px;
 }
 
@@ -1857,33 +1876,35 @@ menuitem[checked="true"].subviewbutton >
 .subviewbutton-iconic > .toolbarbutton-text {
   padding-inline-start: 5px;
 }
 
 /* START photon adjustments */
 
 .panel-header {
   align-items: center;
+  border-bottom: 1px solid var(--panel-separator-color);
   display: flex;
   flex: 1 auto;
   height: 40px; /* fixed item height to prevent flex sizing; height + 2*4px padding */
+  margin-bottom: 6px;
   padding: 4px;
 }
 
 .panel-header > label {
   flex: auto;
   font-size: 13px;
   font-weight: 500;
   margin: 0;
   /* Add the size of the back button to center properly. */
   margin-inline-end: 32px;
   text-align: center;
 }
 
-photonpanelmultiview .cui-widget-panelview .panel-header > .subviewbutton-back {
+photonpanelmultiview .PanelUI-subView .panel-header > .subviewbutton-back {
   -moz-context-properties: fill;
   fill: var(--arrowpanel-color);
   list-style-image: url(chrome://browser/skin/menu-icons/back.svg);
   padding: 8px;
 }
 
 .panel-header > .subviewbutton-back:-moz-locale-dir(rtl) {
   transform: scaleX(-1);
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -186,14 +186,15 @@
   skin/classic/browser/compacttheme/loading-inverted@2x.png (../shared/compacttheme/loading-inverted@2x.png)
   skin/classic/browser/compacttheme/urlbar-history-dropmarker.svg (../shared/compacttheme/urlbar-history-dropmarker.svg)
   skin/classic/browser/urlbar-star.svg                         (../shared/urlbar-star.svg)
   skin/classic/browser/urlbar-tab.svg                          (../shared/urlbar-tab.svg)
   skin/classic/browser/page-action.svg                         (../shared/page-action.svg)
   skin/classic/browser/menu-icons/back.svg                     (../shared/menu-icons/back.svg)
   skin/classic/browser/menu-icons/back-small.svg               (../shared/menu-icons/back-small.svg)
   skin/classic/browser/menu-icons/addons.svg                   (../shared/menu-icons/addons.svg)
+  skin/classic/browser/menu-icons/check.svg                    (../shared/menu-icons/check.svg)
   skin/classic/browser/menu-icons/customize.svg                (../shared/menu-icons/customize.svg)
   skin/classic/browser/menu-icons/library.svg                  (../shared/menu-icons/library.svg)
   skin/classic/browser/menu-icons/new-window.svg               (../shared/menu-icons/new-window.svg)
   skin/classic/browser/menu-icons/print.svg                    (../shared/menu-icons/print.svg)
   skin/classic/browser/menu-icons/private-window.svg           (../shared/menu-icons/private-window.svg)
   skin/classic/browser/menu-icons/settings.svg                 (../shared/menu-icons/settings.svg)
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/menu-icons/check.svg
@@ -0,0 +1,6 @@
+<!-- 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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
+  <path fill="context-fill" d="M6 14a1 1 0 0 1-.707-.293l-3-3a1 1 0 0 1 1.414-1.414l2.157 2.157 6.316-9.023a1 1 0 0 1 1.639 1.146l-7 10a1 1 0 0 1-.732.427A.863.863 0 0 1 6 14z"/>
+</svg>