Bug 606565 - Create an Android-style app menu [r=mfinkle]
authorMatt Brubeck <mbrubeck@mozilla.com>
Tue, 09 Nov 2010 13:42:16 -0800
changeset 66978 d0b2620a6498c152b44cc46969ebb23e4c3239ff
parent 66977 5a92210647c43a3db7cd14cb7d9edbd499de011c
child 66979 e7ff11aae715ee7ac5b9d55f77ec0cdc7c2a1954
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)
reviewersmfinkle
bugs606565
Bug 606565 - Create an Android-style app menu [r=mfinkle]
mobile/chrome/content/browser-ui.js
mobile/chrome/content/browser.js
mobile/chrome/content/browser.xul
mobile/locales/en-US/chrome/browser.dtd
mobile/themes/core/browser.css
mobile/themes/core/images/addons-default-64.png
--- a/mobile/chrome/content/browser-ui.js
+++ b/mobile/chrome/content/browser-ui.js
@@ -1056,17 +1056,17 @@ var BrowserUI = {
         break;
       case "cmd_quit":
         goQuitApplication();
         break;
       case "cmd_close":
         this._closeOrQuit();
         break;
       case "cmd_menu":
-        getIdentityHandler().toggle();
+        AppMenu.toggle();
         break;
       case "cmd_newTab":
         this.newTab();
         break;
       case "cmd_closeTab":
         this.closeTab();
         break;
       case "cmd_undoCloseTab":
@@ -2828,8 +2828,34 @@ var FullScreenVideo = {
     let pos = this.browser.transformClientToBrowser(aX, aY);
     this.browser.messageManager.sendAsyncMessage(aName, {
       x: pos.x,
       y: pos.y,
       messageId: null
     });
   }
 };
+
+var AppMenu = {
+  get panel() {
+    delete this.panel;
+    return this.panel = document.getElementById("appmenu");
+  },
+
+  show: function show() {
+    if (BrowserUI.activePanel || BrowserUI.isPanelVisible())
+      return;
+    this.panel.setAttribute("count", this.panel.childNodes.length);
+    this.panel.collapsed = false;
+    BrowserUI.lockToolbar();
+    BrowserUI.pushPopup(this, [this.panel, Elements.toolbarContainer]);
+  },
+
+  hide: function hide() {
+    this.panel.collapsed = true;
+    BrowserUI.unlockToolbar();
+    BrowserUI.popPopup(this);
+  },
+
+  toggle: function toggle() {
+    this.panel.collapsed ? this.show() : this.hide();
+  }
+};
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -88,17 +88,17 @@ function onDebugKeyPress(ev) {
   const e = 69;
   const f = 70;  // force GC
   const g = 71;
   const h = 72;
   const i = 73;
   const j = 74;
   const k = 75;
   const l = 76;
-  const m = 77;
+  const m = 77; // Android menu
   const n = 78;
   const o = 79;
   const p = 80;  // fake pinch zoom
   const q = 81;  // toggle orientation
   const r = 82;
   const s = 83; // swipe down
   const t = 84;
   const u = 85;
@@ -127,16 +127,19 @@ function onDebugKeyPress(ev) {
     break;
   case a:
     doSwipe(Ci.nsIDOMSimpleGestureEvent.DIRECTION_LEFT);
     break;
   case f:
     MemoryObserver.observe();
     dump("Forced a GC\n");
     break;
+  case m:
+    CommandUpdater.doCommand("cmd_menu");
+    break;
 #ifndef MOZ_PLATFORM_MAEMO
   case p:
     function dispatchMagnifyEvent(aName, aDelta) {
       let e = document.createEvent("SimpleGestureEvent");
       e.initSimpleGestureEvent("MozMagnifyGesture"+aName, true, true, window, null,
                                0, 0, 0, 0, false, false, false, false, 0, null, 0, aDelta);
       document.getElementById("inputhandler-overlay").dispatchEvent(e);
     }
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -600,13 +600,32 @@
     <hbox id="alerts-container" hidden="true" align="start" class="dialog-dark" bottom="0" right="0"
           onclick="AlertsHelper.click(event);">
       <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" collapsed="true" align="stretch" oncommand="AppMenu.hide();">
+      <toolbarbutton class="appmenu-button"
+        label="&appMenu.siteOptions;"
+        image="chrome://browser/skin/images/settings-default-64.png"
+        oncommand="getIdentityHandler().show(); event.stopPropagation();"/>
+      <toolbarbutton class="appmenu-button"
+        label="&prefsHeader.label;"
+        image="chrome://browser/skin/images/preferences-default-64.png"
+        oncommand="BrowserUI.showPanel('prefs-container');"/>
+      <toolbarbutton class="appmenu-button"
+        label="&addonsHeader.label;"
+        image="chrome://browser/skin/images/addons-default-64.png"
+        oncommand="BrowserUI.showPanel('addons-container');"/>
+      <toolbarbutton class="appmenu-button"
+        label="&downloadsHeader.label;"
+        image="chrome://browser/skin/images/downloads-default-64.png"
+        oncommand="BrowserUI.showPanel('downloads-container');"/>
+    </hbox>
   </stack>
 
   <tooltip default="true" id="default-tooltip"/>
 
 </window>
--- a/mobile/locales/en-US/chrome/browser.dtd
+++ b/mobile/locales/en-US/chrome/browser.dtd
@@ -102,9 +102,11 @@
 
 <!ENTITY pageactions.saveas.pdf      "Save As PDF">
 <!ENTITY pageactions.share.page      "Share Page">
 <!ENTITY pageactions.password.forget "Forget Password">
 <!ENTITY pageactions.reset           "Clear Site Preferences">
 <!ENTITY pageactions.findInPage      "Find In Page">
 <!ENTITY pageactions.search.addNew   "Add Search Engine">
 
-<!ENTITY selectHelper.emptytext      "Filter List">
\ No newline at end of file
+<!ENTITY selectHelper.emptytext      "Filter List">
+
+<!ENTITY appMenu.siteOptions         "Site Options">
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -920,17 +920,17 @@ documenttab[reload="true"] > stack > .do
   list-style-image: url("images/newtab-default-64.png");
   height: 82px;
 }
 
 /* bookmark editor   ------------------------------------------------------- */
 #bookmark-container {
   padding: 8px; /* core spacing */
   background: rgb(94,97,102);
-  -moz-box-shadow: black 0 2px 2px;
+  box-shadow: black 0 2px 2px;
 }
 
 #bookmark-form {
   padding: 8px; /* core spacing */
 }
 
 #bookmark-form .bookmark-controls {
   display: none;
@@ -1466,8 +1466,57 @@ pageaction:not([image]) > hbox >.pageact
 }
 
 /* full-screen video ------------------------------------------------------- */
 .full-screen {
   position: absolute;
   z-index: 500;
 }
 
+/* Android menu ------------------------------------------------------------ */
+#appmenu {
+  background: rgba(255,255,255,0.95);
+  box-shadow: 0 6px 10px 6px black;
+  border-style: solid;
+  border-color: #6d6d6d;
+  border-width: 3px 3px 0 3px;
+}
+
+.appmenu-button {
+  -moz-box-flex: 1;
+  -moz-box-orient: vertical;
+  border-style: solid;
+  border-color: #d8d8d8 !important;
+  border-width: 0 1px 1px 0;
+  height: 99px;
+  width: 0;
+}
+
+.appmenu-button:hover:active {
+  background: #f78c00;
+  box-shadow: inset 1px 2px 5px #333;
+}
+
+#appmenu > .appmenu-button .toolbarbutton-text {
+  display: block !important;
+  font-size: 22px !important;
+}
+
+@media (max-width: 499px) {
+  #appmenu[count="4"],
+  #appmenu[count="5"],
+  #appmenu[count="6"] {
+    height: 200px;
+    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="6"] > .appmenu-button {
+    width: 33%;
+  }
+}
index 229149c1d69c954cc63858b7485968b7bf5b851e..0e5d2d61d2be762f94cea282340705b5f3fead37
GIT binary patch
literal 1048
zc$@(k1n2vSP)<h;3K|Lk000e1NJLTq002M$002M;1ONa40ARUQ00001b5ch_0Itp)
z=>Px&(n&-?RA}Dqm|tjHRUF4Z=O(#Hmi}4mY&zQ2b<So5+hDOw!8jGBB6A>vJq)UX
zu<7u@R~dpYiXgrU^Qr!0_~xLF!9)dzq7_`af?Ky48yH({o3u^;+}zxIj}L1!A-QRC
zo3se`dtdJP{m!}Pdw%EqzUQ0^E?l^9;ljl>L)6|RI?N;g7JiS9Z;pVs=I&38M1~{z
z()a;}xEP<_vVcWTef7C4!uWTCuW#myN^P}G-;2kJO^-f(Uu&d&iwHESW?(j0Y)dlO
z>*?Pj0?QstozZ3sEVHEeZ7x0SWHCFL0)cYjTeHAma(--9zq8_;fTyO~zWK!M-3J2w
zU3tT$UqAZk#usGBHYg3FMG?AXYML<Ag3i>eFg$C4+<x(24B}SZ2t-d7mmd_SYUn~1
z%!%}5`(N_t6xgD~KdDR3cX|g-O9vP@-RZ5%BFy-V9ZrZFJ2Jky5HP$}zzG2>VALl9
zQjw05OA4tpN(UN%Z6~n7Y~`~{$0WFY1X3h{c6w^tx?AakjSegu5V(@xh8A^=a2U1v
z?oaLs9oi!#Lum0&HyMFz6Yq|}iNSqGs!Q;PUh!t%7#bN-gYa7FgR}D0iBTtK!sfoW
z@=CCL<?hY>$G(3v+`4i1(|>tPA@A=}*B4DD{nR^GKQ0vOY9nAxol|xqkX9BQgtfXL
zt02&`w|D_JwHd)C|FTv)0VC|&`MeZDnm2A<LJ_%OKss9KmTIq!l?dcIp84<zfLjlo
zZL@q&cI*mU4%Nn98!Hg#RHPDn4j{(Cf!T$}4ple)s{nM<wqE`lDeOhvTWL3J3+6{0
zIT!(|8^5)FSk2Ia$r4LWb-?gis@<5=<bVJzWqdEc4{+v4WH1fDFF%5AIUpbvDasSL
zO?v&UgN`!(KfmtieUIbGhx;@wKK0G@)I}_ZLR7w8im8e8B6Nm>eY;Af#bWL5B-hT(
zdnQ0nCNGo5*yLtZj335EC+@wSiS3P*5HOUKl_iw8fQlqXh9z=!B`_LKp4T<#9+>Po
z8Y>N(vcfWJgzzKLSS4#e1<FPQ$~|un_a0`RbZFlT1Et>e8_OCC%rVCzTBY=H6oI49
zUY;Z@nh$pmMx}kzoPFS{CXleP2SZ8-X^2Fl4<su#c3n06kn^oHl7Mc(XJ3~0{V|iC
zhRK=oe!Ye*qtbaG#O|)g%e$7YXA;od+Y%`wQ$KTum3k2H(?*NU{dtuX&`#;y$z+Li
z^|xhF@yPDSUzUJGM*{+=C0{VfR?7R@e$xqrO$`fq?}vqrbhvQg!i9_f5B>pw(wgSX
SG6t3a0000<MNUMnLSTX?EA?vt