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
--- 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>