Bug 610784 - Handle overflow in the Android menu r=mbrubeck,mfinkle
authorWes Johnston <wjohnston@mozilla.com>
Fri, 08 Apr 2011 10:52:07 -0700
changeset 67621 c93094805140ebc2145c45b6d6bbc7968d1940a6
parent 67620 52adbe0156659241e842e7fc70f029da7bf8fd59
child 67622 ecb9212d635ff9672a3b9e53d95ee868482f9c89
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck, mfinkle
bugs610784
milestone2.2a1pre
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 610784 - Handle overflow in the Android menu r=mbrubeck,mfinkle
mobile/chrome/content/AppMenu.js
mobile/chrome/content/browser.xul
mobile/locales/en-US/chrome/browser.properties
mobile/themes/core/browser.css
mobile/themes/core/images/appmenu-more-hdpi.png
mobile/themes/core/jar.mn
--- a/mobile/chrome/content/AppMenu.js
+++ b/mobile/chrome/content/AppMenu.js
@@ -1,35 +1,103 @@
 var AppMenu = {
   get panel() {
     delete this.panel;
     return this.panel = document.getElementById("appmenu");
   },
 
+  shouldShow: function appmenu_shouldShow(aElement) {
+    return !aElement.hidden;
+  },
+
+  overflowMenu : [],
+
   show: function show() {
     if (BrowserUI.activePanel || BrowserUI.isPanelVisible())
       return;
-    this.panel.setAttribute("count", this.panel.childNodes.length);
+
+    let shown = 0;
+    let lastShown = null;
+    this.overflowMenu = [];
+    let childrenCount = this.panel.childElementCount;
+    for (let i = 0; i < childrenCount; i++) {
+      if (this.shouldShow(this.panel.children[i])) {
+        if (shown == 6 && this.overflowMenu.length == 0) {
+          // if we are trying to show more than 6 elements fall back to showing a more button
+          lastShown.removeAttribute("show");
+          this.overflowMenu.push(lastShown);
+          this.panel.appendChild(this.createMoreButton());
+        }
+        if (this.overflowMenu.length > 0) {
+          this.overflowMenu.push(this.panel.children[i]);
+        } else {
+          lastShown = this.panel.children[i];
+          lastShown.setAttribute("show", shown);
+          shown++;
+        }
+      }
+    }
+
+    this.panel.setAttribute("count", shown);
     this.panel.hidden = false;
 
     addEventListener("keypress", this, true);
 
     BrowserUI.lockToolbar();
     BrowserUI.pushPopup(this, [this.panel, Elements.toolbarContainer]);
   },
 
   hide: function hide() {
     this.panel.hidden = true;
+    let moreButton = document.getElementById("appmenu-more-button");
+    if (moreButton)
+      moreButton.parentNode.removeChild(moreButton);
+
+    for (let i = 0; i < this.panel.childElementCount; i++) {
+      if (this.panel.children[i].hasAttribute("show"))
+        this.panel.children[i].removeAttribute("show");
+    }
 
     removeEventListener("keypress", this, true);
 
     BrowserUI.unlockToolbar();
     BrowserUI.popPopup(this);
   },
 
   toggle: function toggle() {
     this.panel.hidden ? this.show() : this.hide();
   },
 
   handleEvent: function handleEvent(aEvent) {
     this.hide();
+  },
+
+  showAsList: function showAsList() {
+    // allow menu to hide to remove the more button before we show the menulist
+    setTimeout((function() {
+      this.menu.menupopup.children = this.overflowMenu;
+      MenuListHelperUI.show(this.menu);
+    }).bind(this), 0)
+  },
+
+  menu : {
+    id: "appmenu-menulist",
+    dispatchEvent: function(aEvent) {
+      let menuitem = AppMenu.overflowMenu[this.selectedIndex];
+      if (menuitem)
+        menuitem.click();
+    },
+    menupopup: {
+      hasAttribute: function(aAttr) { return false; }
+    },
+    selectedIndex: -1
+  },
+
+  createMoreButton: function() {
+    let button = document.createElement("toolbarbutton");
+    button.setAttribute("id", "appmenu-more-button");
+    button.setAttribute("class", "appmenu-button");
+    button.setAttribute("label", Strings.browser.GetStringFromName("appMenu.more"));
+    button.setAttribute("show", 6);
+    button.setAttribute("oncommand", "AppMenu.showAsList();");
+    return button;
   }
 };
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -669,28 +669,24 @@
       <image id="alerts-image"/>
       <vbox flex="1">
         <label id="alerts-title" value=""/>
         <description id="alerts-text" flex="1"/>
       </vbox>
     </hbox>
 
     <hbox id="appmenu" bottom="0" hidden="true" align="stretch" oncommand="AppMenu.hide();">
-      <toolbarbutton class="appmenu-button"
+      <toolbarbutton class="appmenu-site-button appmenu-button"
         label="&appMenu.siteOptions;"
-        image="chrome://browser/skin/images/appmenu-site-hdpi.png"
         oncommand="getIdentityHandler().show(); event.stopPropagation();"/>
-      <toolbarbutton class="appmenu-button"
+      <toolbarbutton class="appmenu-preferences-button appmenu-button"
         label="&prefsHeader.label;"
-        image="chrome://browser/skin/images/appmenu-preferences-hdpi.png"
         oncommand="BrowserUI.showPanel('prefs-container');"/>
-      <toolbarbutton class="appmenu-button"
+      <toolbarbutton class="appmenu-addons-button appmenu-button"
         label="&addonsHeader.label;"
-        image="chrome://browser/skin/images/appmenu-addons-hdpi.png"
         oncommand="BrowserUI.showPanel('addons-container');"/>
-      <toolbarbutton class="appmenu-button"
+      <toolbarbutton class="appmenu-downloads-button appmenu-button"
         label="&downloadsHeader.label;"
-        image="chrome://browser/skin/images/appmenu-downloads-hdpi.png"
         oncommand="BrowserUI.showPanel('downloads-container');"/>
     </hbox>
   </stack>
 
 </window>
--- a/mobile/locales/en-US/chrome/browser.properties
+++ b/mobile/locales/en-US/chrome/browser.properties
@@ -218,8 +218,11 @@ clearPrivateData.message=Delete your bro
 # setting, the "Character Encoding" menu must be enabled via Preferences.
 # This is not a string to translate. If users frequently use the "Character Encoding"
 # menu, set this to "true". Otherwise, you can leave it as "false".
 browser.menu.showCharacterEncoding=false
 
 # LOCALIZATION NOTE (intl.charsetmenu.browser.static): Set to a series of comma separated
 # values for charsets that the user can select from in the Character Encoding menu.
 intl.charsetmenu.browser.static=iso-8859-1,utf-8,x-gbk,big5,iso-2022-jp,shift_jis,euc-jp
+
+#Application Menu
+appMenu.more=More
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -1322,57 +1322,87 @@ pageaction:not([image]) > hbox >.pageact
 #appmenu {
   background: rgba(255,255,255,0.95);
   box-shadow: 0 @shadow_width_large@ @shadow_width_xlarge@ @shadow_width_large@ black;
   border-style: solid;
   border-color: #6d6d6d;
   border-width: @border_width_large@ @border_width_large@ 0 @border_width_large@;
 }
 
-.appmenu-button {
+#appmenu > .appmenu-button {
   -moz-box-flex: 1;
   -moz-box-orient: vertical;
   border-style: solid;
   border-color: #d8d8d8 !important;
   border-width: 0 @border_width_tiny@ @border_width_tiny@ 0;
   height: @appmenu_button_height@;
   width: 0;
+  display: none;
 }
 
-.appmenu-button:hover:active {
+#appmenu > .appmenu-button[show] {
+  display: inline-block;
+}
+
+#appmenu > .appmenu-button:hover:active {
   background-image: url("chrome://browser/skin/images/appmenu-active-hdpi.png");
   background-size: 100% 100%;
 }
 
 #appmenu > .appmenu-button .toolbarbutton-text {
   display: block !important;
   font-size: @font_snormal@ !important;
 }
 
 #appmenu > .appmenu-button .toolbarbutton-icon {
   margin-top: @margin_normal@ !important;
   margin-bottom: @margin_small@ !important;
 }
 
+richlistitem.appmenu-site-button > image,
+.appmenu-site-button {
+  list-style-image: url("chrome://browser/skin/images/appmenu-site-hdpi.png");
+}
+
+richlistitem.appmenu-addons-button > image,
+.appmenu-addons-button {
+  list-style-image: url("chrome://browser/skin/images/appmenu-addons-hdpi.png");
+}
+
+richlistitem.appmenu-preferences-button > image,
+.appmenu-preferences-button {
+  list-style-image: url("chrome://browser/skin/images/appmenu-preferences-hdpi.png");
+}
+
+richlistitem.appmenu-downloads-button > image,
+.appmenu-downloads-button {
+  list-style-image: url("chrome://browser/skin/images/appmenu-downloads-hdpi.png");
+}
+
+#appmenu-more-button {
+  list-style-image: url("chrome://browser/skin/images/appmenu-site-hdpi.png");
+  display: none;
+}
+
 @media (@orientation@: portrait) {
   #appmenu:not([hidden])[count="4"],
   #appmenu:not([hidden])[count="5"],
   #appmenu:not([hidden])[count="6"] {
     height: @appmenu_portrait_height@;
     display: inline-block;
   }
 
   #appmenu[count="4"] > .appmenu-button,
   #appmenu[count="5"] > .appmenu-button {
     width: 50%;
   }
-
-  #appmenu[count="5"] > .appmenu-button:nth-child(3),
-  #appmenu[count="5"] > .appmenu-button:nth-child(4),
-  #appmenu[count="5"] > .appmenu-button:nth-child(5),
+ 
+  #appmenu[count="5"] > .appmenu-button[show="2"],
+  #appmenu[count="5"] > .appmenu-button[show="3"],
+  #appmenu[count="5"] > .appmenu-button[show="4"],
   #appmenu[count="6"] > .appmenu-button {
     width: 33.33%;
   }
 }
 
 /* Sync setup ------------------------------------------------------------- */
 #syncsetup-container {
   background-color: rgba(0,0,0,.6);
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..052f8f2fd893c771f173454ca378f98d95f1c5b6
GIT binary patch
literal 3515
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
Qua*FH<$FqHidNzO1ICeUP5=M^
--- a/mobile/themes/core/jar.mn
+++ b/mobile/themes/core/jar.mn
@@ -15,16 +15,17 @@ chrome.jar:
 * skin/platform.css                         (platform.css)
   skin/touchcontrols.css                    (touchcontrols.css)
 % override chrome://global/skin/about.css chrome://browser/skin/about.css
 % override chrome://global/skin/media/videocontrols.css chrome://browser/skin/touchcontrols.css
 
   skin/images/appmenu-addons-hdpi.png       (images/appmenu-addons-hdpi.png)
   skin/images/appmenu-active-hdpi.png       (images/appmenu-active-hdpi.png)
   skin/images/appmenu-downloads-hdpi.png    (images/appmenu-downloads-hdpi.png)
+  skin/images/appmenu-more-hdpi.png         (images/appmenu-more-hdpi.png)
   skin/images/appmenu-preferences-hdpi.png  (images/appmenu-preferences-hdpi.png)
   skin/images/appmenu-site-hdpi.png         (images/appmenu-site-hdpi.png)
   skin/images/aboutBackground.jpg           (images/aboutBackground.jpg)
   skin/images/button-bg.png                 (images/button-bg.png)
   skin/images/textbox-bg.png                (images/textbox-bg.png)
   skin/images/browseaddons-bg.jpg           (images/browseaddons-bg.jpg)
   skin/images/addons-32.png                 (images/addons-32.png)
   skin/images/arrowleft-16.png              (images/arrowleft-16.png)