Bug 612900 - Cannot pan list of search engines when list is longer than viewable screen [r=mfinkle]
authorVivien Nicolas <21@vingtetun.org>
Thu, 09 Dec 2010 10:08:14 -0500
changeset 67085 ee4f128c02c88aed6b209ff85e27a0a6d5d8a908
parent 67084 6d02cd1d0496f358f0f8bdc5af7fd94daffc3af2
child 67086 954dd263e56486e0247a1aa3d97b1cf7b5b40983
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
bugs612900
Bug 612900 - Cannot pan list of search engines when list is longer than viewable screen [r=mfinkle]
mobile/chrome/content/bindings/arrowbox.xml
mobile/chrome/content/browser.js
mobile/chrome/content/browser.xul
mobile/themes/core/browser.css
--- a/mobile/chrome/content/bindings/arrowbox.xml
+++ b/mobile/chrome/content/bindings/arrowbox.xml
@@ -38,44 +38,78 @@
 
 <bindings
     xmlns="http://www.mozilla.org/xbl"
     xmlns:xbl="http://www.mozilla.org/xbl"
     xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <binding id="arrowbox" extends="xul:box">
     <content orient="vertical">
-      <xul:box anonid="container" class="panel-arrowcontainer">
+      <xul:box anonid="container" class="panel-arrowcontainer" flex="1">
         <xul:box anonid="arrowbox" class="panel-arrowbox" dir="ltr">
           <xul:image anonid="arrow" class="panel-arrow"/>
         </xul:box>
-        <xul:box class="panel-arrowcontent" flex="1">
+        <xul:scrollbox anonid="arrowcontent" class="panel-arrowcontent" flex="1">
           <xul:box class="panel-inner-arrowcontent" xbl:inherits="align,dir,orient,pack,flex">
             <children/>
           </xul:box>
-        </xul:box>
+        </xul:scrollbox>
       </xul:box>
     </content>
-    <implementation>
-      <field name="_fadeTimer"/>
+    <implementation implements="nsIDOMEventListener">
+      <constructor>
+        <![CDATA[
+          window.addEventListener("resize", this._eventHandler, false);
+        ]]>
+      </constructor>
+
+      <desctructor>
+        <![CDATA[
+          window.removeEventListener("resize", this._eventHandler, false);
+        ]]>
+      </desctructor>
+
+      <property name="scrollBoxObject" readonly="true">
+        <getter><![CDATA[
+          let content = document.getAnonymousElementByAttribute(this, "anonid", "arrowcontent");
+          if (content.style.overflow == "hidden")
+            return content.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
+
+          return null;
+        ]]></getter>
+      </property>
 
       <property name="offset" onget="return parseInt(this.getAttribute('offset')) || 0;"
                               onset="this.setAttribute('offset', val); return val;"/>
 
+      <field name="anchorNode">null</field>
       <method name="anchorTo">
          <parameter name="aAnchorNode"/>
          <body>
             <![CDATA[
+              if (!aAnchorNode) {
+                this.arrow.hidden = true;
+                return;
+              }
+
+              this.anchorNode = aAnchorNode;
               let container = document.getAnonymousElementByAttribute(this, "anonid", "container");
+              let content = document.getAnonymousElementByAttribute(this, "anonid", "arrowcontent");
               let arrowbox = document.getAnonymousElementByAttribute(this, "anonid", "arrowbox");
               let arrow = document.getAnonymousElementByAttribute(this, "anonid", "arrow");
 
-              if (!aAnchorNode) {
-                arrow.hidden = true;
-                return;
+              // If the content of the arrowbox if taller than the available
+              // screen space, force a maximum height
+              this.style.minHeight = "";
+              content.style.overflow = "visible";
+              const kBottomMargin = 64;
+              let contentRect = content.firstChild.getBoundingClientRect();
+              if ((contentRect.height + contentRect.top + kBottomMargin) > window.innerHeight) {
+                content.style.overflow = "hidden";
+                this.style.minHeight = (window.innerHeight - parseInt(this.top) - kBottomMargin) + "px";
               }
 
               let anchorRect = aAnchorNode.getBoundingClientRect();
               let popupRect = this.getBoundingClientRect();
               let offset = this.offset;
 
               let horizPos = (Math.round(popupRect.right) <= Math.round(anchorRect.left + offset)) ? -1 :
                              (Math.round(popupRect.left) >= Math.round(anchorRect.right - offset)) ? 1 : 0;
@@ -115,11 +149,30 @@
               } else {
                 hideArrow = true;
               }
               arrow.hidden = hideArrow;
               arrow.setAttribute("side", anchorClass);
             ]]>
          </body>
       </method>
+
+      <field name="_eventHandler"><![CDATA[
+        ({
+          self: this,
+          handleEvent: function handleEvent(aEvent) {
+            // We need to reset the margins because the previous values could
+            // cause the arrowbox to size incorrectly.
+            let self = this.self;
+            switch (aEvent.type) {
+              case "resize":
+                let arrowbox = document.getAnonymousElementByAttribute(self, "anonid", "arrowbox");
+                arrowbox.style.marginLeft = "0px";
+                arrowbox.style.marginTop = "0px";
+                self.anchorTo(self.anchorNode);
+                break;
+            }
+          }
+        })
+      ]]></field>
     </implementation>
   </binding>
 </bindings>
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1292,45 +1292,40 @@ const BrowserSearch = {
     let list = this._list;
     while (list.lastChild)
       list.removeChild(list.lastChild);
 
     this.engines.forEach(function(aEngine) {
       let button = document.createElement("button");
       button.className = "prompt-button";
       button.setAttribute("label", aEngine.name);
+      button.setAttribute("crop", "end");
       button.setAttribute("pack", "start");
       button.setAttribute("image", aEngine.iconURI ? aEngine.iconURI.spec : null);
       button.onclick = function() {
         popup.hidden = true;
         BrowserUI.doOpenSearch(aEngine.name);
       }
       list.appendChild(button);
     });
 
     popup.hidden = false;
     popup.top = BrowserUI.toolbarH - popup.offset;
     popup.anchorTo(document.getElementById("tool-search"));
 
     document.getElementById("urlbar-icons").setAttribute("open", "true");
-    window.addEventListener("resize", this, true);
     BrowserUI.pushPopup(this, [popup, this._button]);
   },
 
   hide: function bs_hide() {
     this._popup.hidden = true;
     document.getElementById("urlbar-icons").removeAttribute("open");
-    window.removeEventListener("resize", this, true);
     BrowserUI.popPopup(this);
   },
 
-  handleEvent: function handleEvent(aEvent) {
-    this._popup.anchorTo(document.getElementById("tool-search"));
-  },
-
   observe: function bs_observe(aSubject, aTopic, aData) {
     if (aTopic != "browser-search-engine-modified")
       return;
 
     switch (aData) {
       case "engine-added":
       case "engine-removed":
         // force a rebuild of the prefs list, if needed
--- a/mobile/chrome/content/browser.xul
+++ b/mobile/chrome/content/browser.xul
@@ -562,18 +562,18 @@
             <separator/>
             <button oncommand="WeaveGlue.close(); WeaveGlue.connect();">&sync.setup.connect;</button>
           </hbox>
         </vbox>
       </scrollbox>
     </vbox>
 #endif
 
-    <arrowbox id="search-engines-popup" hidden="true" class="window-width" offset="18">
-      <hbox id="search-engines-list" class="prompt-buttons window-width"/>
+    <arrowbox id="search-engines-popup" hidden="true" offset="18" flex="1">
+      <hbox id="search-engines-list" class="prompt-buttons" flex="1"/>
     </arrowbox>
 
     <vbox id="newtab-popup" hidden="true" class="dialog-dark" onclick="NewTabPopup.selectTab()" align="center" left="21">
       <label/>
     </vbox>
 
     <!-- options dialog for select form field -->
     <vbox id="select-container" hidden="true" pack="center">
--- a/mobile/themes/core/browser.css
+++ b/mobile/themes/core/browser.css
@@ -1159,16 +1159,21 @@ pageaction:not([image]) > hbox >.pageact
   font-size: 18px;
   padding: 4px;
 }
 
 #context-hint[value=""] {
   visibility: collapse;
 }
 
+/* Needed for the crop attribute to have an effect */
+#search-engines-list > .prompt-button > .button-box > .button-text {
+  -moz-box-flex: 1;
+}
+
 #search-engines-list > .prompt-button > .button-box > .button-icon {
   width: 32px;
   height: 32px;
 }
 
 /* Preferences window   ---------------------------------------------------- */
 .setting {
   padding-left: 10px;