changeset 348:b8fbfd7ecfdf

put the main menupopup into the main Firefox popupset and share it with the toolbar and statusbar buttons via the popup attribute for better robustness; add customizable toolbar buttons for the three views
author alta88 <alta88@gmail.com>
date Mon, 27 Oct 2008 17:07:35 -0700
parents d95334ac5edc
children f95f6f24516f
files content/browser.css content/browser.js content/browser.xul content/icons/table_multiple.png locale/en-US/browser.dtd
diffstat 5 files changed, 277 insertions(+), 180 deletions(-) [+]
line wrap: on
line diff
--- a/content/browser.css	Fri Oct 24 16:48:59 2008 -0700
+++ b/content/browser.css	Mon Oct 27 17:07:35 2008 -0700
@@ -35,14 +35,32 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
+#snowlMenu,
+#snowlToolbarButton,
+#snowlStatusbarButton,
+tab[snowl] > image {
+  list-style-image: url("chrome://snowl/content/icons/snowl-16.png");
+}
+
 #snowlToolbarButton {
-  list-style-image: url("chrome://snowl/content/icons/snowl-16.png");
 /* temporary til bug 355143 */
   -moz-binding: url("chrome://global/content/bindings/toolbarbutton.xml#menu-vertical");
 }
 
+#snowlToggleListButton {
+  list-style-image: url("chrome://snowl/content/icons/layout.png");
+}
+
+#snowlToggleStreamButton {
+  list-style-image: url("chrome://snowl/content/icons/application_tile_horizontal.png");
+}
+
+#snowlToggleRiverButton {
+  list-style-image: url("chrome://snowl/content/icons/table_multiple.png");
+}
+
 #snowlToggleHeaderButton[snowlHeader="none"] {
-  list-style-image: url("chrome://snowl/content/icons/application_split.png")
+  list-style-image: url("chrome://snowl/content/icons/application_split.png");
 }
 
 #snowlToggleHeaderButton[snowlHeader="brief"] {
@@ -57,15 +75,6 @@
   opacity: .3;
 }
 
-/* For correct orientation; type=menu cannot be vertical unless in customize.. */
-#palette-box toolbarbutton.snowlToolbarMenuButton {
-  -moz-box-orient: vertical;
-}
-
 tab[snowl] {
   background: white;
 }
-
-tab[snowl] > image {
-  list-style-image: url("chrome://snowl/content/icons/snowl-16.png");
-}
--- a/content/browser.js	Fri Oct 24 16:48:59 2008 -0700
+++ b/content/browser.js	Mon Oct 27 17:07:35 2008 -0700
@@ -87,63 +87,48 @@
 
   },
 
-  _snowlRiverTab: function() {
-    // Could be null if none else a reference to the tab
-    let gBrowser = document.getElementById("content");
-    let snowlTab = null;
-    let snowlTabOpen = false;
-    
-    for (let index = 0; index < gBrowser.mTabs.length && !snowlTabOpen; index++) {
-      // Get the next tab
-      let currentTab = gBrowser.mTabs[index];
-      if (currentTab.hasAttribute("snowl")) {
-        snowlTabOpen = true;
-        snowlTab = currentTab;
-      }
-    }
-    return snowlTab;
-  },
 
   //**************************************************************************//
-  // Menu Popup Sharing
-
-  // The menu popup through which users can access Snowl commands is accessible
-  // from both a menu item in the Tools menu and a statusbar button.  This code
-  // shares the same popup between those two elements so we don't have to
-  // duplicate the popup code.
+  // Menu Popups
 
-  onStatusbarButtonMouseDown: function(event) {
-    let menuPopup = document.getElementById('snowlMenuPopup');
-    let statusbarButton = document.getElementById("snowlStatusbarButton");
-    let toolbarButton = document.getElementById("snowlToolbarButton");
-
-    // If the menu popup isn't on the statusbar or toolbar button, then move it
-    // onto the button so the popup appears when the user clicks the button.
-    // We'll move the popup back to the Tools > Snowl menu when the popup hides.
-    if (event.target.id == "snowlToolbarButton" &&
-        menuPopup.parentNode != toolbarButton)
-      toolbarButton.appendChild(menuPopup);
-    if (event.target.id == "snowlStatusbarButton" &&
-        menuPopup.parentNode != statusbarButton)
-      statusbarButton.appendChild(menuPopup);
+  onToolsMenuPopupShowing: function(event) {
+    // Reuse popup
+    let popup = document.getElementById("snowlMenuPopup");
+    let element = document.getElementById("snowlMenu");
+    document.popupNode = element;
+    popup.hidden = false;
+    popup.openPopup(element, "end_before", -3);
   },
 
-  onPopupShowing: function(event) {
+  onToolsMenuPopupHiding: function(event) {
+    // Hide it manually, no idea why .hidePopup doesn't work..
+    let popup = document.getElementById("snowlMenuPopup");
+    //popup.hidePopup();
+    popup.hidden = true;
+  },
+
+  onSnowlMenuPopupShowing: function(event) {
     // River view menuitem checkstate is off if its tab is not selected+focused
     let rivermenuitem = document.getElementById("viewSnowlRiver");
     let isRiverTab = gBrowser.selectedTab.hasAttribute("snowl");
     rivermenuitem.setAttribute("checked", isRiverTab);
 
-    // Header checked state
-    let menuitems = document.getElementsByAttribute("name", "snowlHeaderMenuitemGroup");
-    let selectedIndex = this._prefs.get("message.headerView");
-    if (menuitems)
-      menuitems[selectedIndex].setAttribute("checked", true);
+    if (event.target.id == "snowlMenuPopup")
+      if (document.popupNode.localName == "toolbarbutton")
+        document.popupNode.setAttribute("open", true);
+  },
+
+  onSnowlMenuPopupHiding: function(event) {
+    event.target.hidden = false;
+    if (event.target.id == "snowlMenuPopup")
+      if (document.popupNode.localName == "toolbarbutton")
+        document.popupNode.removeAttribute("open");
   },
 
   layoutName: ["classic", "vertical", "widemessage", "widethread", "stacked"],
 
   onLayoutPopupShowing: function(event) {
+    // Layout checked state
     let layoutmenu = document.getElementById("snowlLayoutMenu");
     let lchecked = document.getElementById("viewSnowlList").hasAttribute("checked");
     let schecked = document.getElementById("viewSnowlStream").hasAttribute("checked");
@@ -158,23 +143,35 @@
           layoutmenuitems[i].setAttribute("checked", true);
       }
     }
+
+    // Header checked state
+    let menuitems = document.getElementsByAttribute("name", "snowlHeaderMenuitemGroup");
+    let selectedIndex = this._prefs.get("message.headerView");
+    if (menuitems) {
+      for (var i = 0; i < menuitems.length; i++) {
+        menuitems[i].setAttribute("disabled", !this._listMessageHeader());
+        if (i == selectedIndex)
+          menuitems[i].setAttribute("checked", true);
+      }
+    }
+
+    // Toolbars
     document.getElementById("snowlToolbarMenuitem").setAttribute("disabled",
         (!lchecked && !schecked) ? true : false);
     document.getElementById("snowlViewToolbarMenuitem").setAttribute("disabled",
         (!lchecked) ? true : false)
   },
 
-  onPopupHiding: function(event) {
-    let menuPopup = document.getElementById("snowlMenuPopup");
-    let menu = document.getElementById("snowlMenu");
-    event.target.parentNode.removeAttribute("open");
+  onSnowlButtonMouseDown: function(event) {
+    // Jumping thru hoops to reuse popup for menupopup and button..
+    let popup = document.getElementById("snowlMenuPopup");
+    popup.hidden = false;
+  },
 
-    // If the menu popup isn't on the Tools > Snowl menu, then move the popup
-    // back onto that menu so the popup appears when the user selects the menu.
-    // We'll move the popup back to the statusbar button when the user clicks
-    // on that button.
-    if (menuPopup.parentNode != menu)
-      menu.appendChild(menuPopup);
+  // Correct state of button based on message in current tab
+  // XXX better to add url change listener?
+  onSnowlToggleHeaderButtonMouseover: function(event) {
+    event.target.setAttribute("disabled", !this._listMessageHeader());
   },
 
 
@@ -208,6 +205,11 @@
       let tabIndex = gBrowser.mTabContainer.selectedIndex;
       this._mainWindow.setAttribute("snowltabindex", tabIndex);
       gBrowser.mTabs[tabIndex].setAttribute("snowl", "river");
+
+      let riverbroadcaster = document.getElementById("viewSnowlRiver");
+      let isRiverTab = gBrowser.selectedTab.hasAttribute("snowl");
+      if (riverbroadcaster)
+        riverbroadcaster.setAttribute("checked", isRiverTab);
     }
   },
 
@@ -219,7 +221,12 @@
   onTabSelect: function() {
     // Make sure desired header view showing..
     this._toggleHeader("TabSelect");
-    // others..
+
+    // Set checkstate of River broadcaster
+    let riverbroadcaster = document.getElementById("viewSnowlRiver");
+    let isRiverTab = gBrowser.selectedTab.hasAttribute("snowl");
+    if (riverbroadcaster)
+      riverbroadcaster.setAttribute("checked", isRiverTab);
   },
 
   onCheckForNewMessages: function() {
@@ -265,9 +272,7 @@
   _toggleHeader: function(val) {
     let contentWindowDoc = gBrowser.selectedBrowser.contentDocument;
     let selectedIndex = null;
-    let headerDeck = new XPCNativeWrapper(contentWindowDoc, "getElementById()")
-        .getElementById("headerDeck");
-
+    let headerDeck = this._listMessageHeader();
     let button = document.getElementById("snowlToggleHeaderButton");
     if (button)
       button.setAttribute("disabled", !headerDeck ? true : false);
@@ -310,6 +315,13 @@
     }
   },
 
+  _listMessageHeader: function() {
+    let contentWindowDoc = gBrowser.selectedBrowser.contentDocument;
+    let headerDeck = new XPCNativeWrapper(contentWindowDoc, "getElementById()")
+        .getElementById("headerDeck");
+    return headerDeck;
+  },
+
   // Need to init onLoad due to xul structure, toolbar exists in list and stream
   _initSnowlToolbar: function() {
     let menuitem = document.getElementById("snowlToolbarMenuitem");
@@ -334,11 +346,34 @@
     }
   },
 
+  // See if River tab exists
+  _snowlRiverTab: function() {
+    // Could be null if none else a reference to the tab
+    let gBrowser = document.getElementById("content");
+    let snowlTab = null;
+    let snowlTabOpen = false;
+    
+    for (let index = 0; index < gBrowser.mTabs.length && !snowlTabOpen; index++) {
+      // Get the next tab
+      let currentTab = gBrowser.mTabs[index];
+      if (currentTab.hasAttribute("snowl")) {
+        snowlTabOpen = true;
+        snowlTab = currentTab;
+      }
+    }
+    return snowlTab;
+  },
+
   // Need to init snowl River tab, if exists
   _initSnowlRiverTab: function() {
     let tabIndex = parseInt(this._mainWindow.getAttribute("snowltabindex"));
     if (tabIndex >= 0 && tabIndex <= gBrowser.mTabs.length)
       gBrowser.mTabs[tabIndex].setAttribute("snowl", "river");
+
+    let riverbroadcaster = document.getElementById("viewSnowlRiver");
+    let isRiverTab = gBrowser.selectedTab.hasAttribute("snowl");
+    if (riverbroadcaster)
+      riverbroadcaster.setAttribute("checked", isRiverTab);
   },
 
   // Need to reset snowl River tab index
--- a/content/browser.xul	Fri Oct 24 16:48:59 2008 -0700
+++ b/content/browser.xul	Mon Oct 27 17:07:35 2008 -0700
@@ -68,138 +68,183 @@
                  sidebarurl="chrome://snowl/content/stream.xul"
                  sidebartitle="&streamViewSidebar.label;"
                  oncommand="toggleSidebar('viewSnowlStream')"/>
+    <broadcaster id="viewSnowlRiver"
+                 autoCheck="false"
+                 type="checkbox"
+                 persist="checked"
+                 oncommand="Snowl.onRiverView()"/>
   </broadcasterset>
 
   <menupopup id="menu_ToolsPopup">
-    <menu id="snowlMenu" class="menu-iconic" label="&snowlMenu.label;"
-          image="chrome://snowl/content/icons/snowl-16.png"
-          accesskey="&snowlMenu.accesskey;" insertafter="menu_openAddons">
-      <menupopup id="snowlMenuPopup"
-                 onpopupshowing="Snowl.onPopupShowing(event)"
-                 onpopuphiding="Snowl.onPopupHiding(event)">
-        <menuitem observes="viewSnowlList" label="&listView.label;"
-                  accesskey="&listView.accesskey;"/>
-        <menuitem observes="viewSnowlStream" label="&streamView.label;"
-                  accesskey="&streamView.accesskey;"/>
-        <menuseparator/>
-        <menuitem id="viewSnowlRiver"
-                  label="&riverView.label;"
-                  accesskey="&riverView.accesskey;"
-                  autoCheck="false"
-                  type="checkbox"
-                  persist="checked"
-                  oncommand="Snowl.onRiverView()"/>
-        <menuseparator/>
-        <menuitem label="&checkForNewMessages.label;"
-                  accesskey="&checkForNewMessages.accesskey;"
-                  oncommand="Snowl.onCheckForNewMessages()"/>
-        <menuseparator/>
-        <menu id="snowlLayoutMenu"
-              label="&snowlLayoutMenu.label;"
-              accesskey="&snowlLayoutMenu.accesskey;">
-          <menupopup id="snowlLayoutPopup"
-                     onpopupshowing="Snowl.onLayoutPopupShowing(event)">
-            <menuitem id="snowlLayoutMenuitemClassic"
-                      label="&layoutClassic.label;"
-                      type="radio"
-                      checked="true"
-                      accesskey="&layoutClassic.accesskey;"
-                      name="snowlLayoutMenuitemGroup"
-                      oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kClassicLayout)"/>
-            <menuitem id="snowlLayoutMenuitemVertical"
-                      label="&layoutVertical.label;"
-                      type="radio"
-                      accesskey="&layoutVertical.accesskey;"
-                      name="snowlLayoutMenuitemGroup"
-                      oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kVerticalLayout)"/>
-            <menuitem id="snowlLayoutMenuitemWideMessage"
-                      label="&layoutWideMessage.label;"
-                      type="radio"
-                      accesskey="&layoutWideMessage.accesskey;"
-                      name="snowlLayoutMenuitemGroup"
-                      oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kWideMessageLayout)"/>
-            <menuitem id="snowlLayoutMenuitemWideThread"
-                      label="&layoutWideThread.label;"
-                      type="radio"
-                      accesskey="&layoutWideThread.accesskey;"
-                      name="snowlLayoutMenuitemGroup"
-                      oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kWideThreadLayout)"/>
-            <menuitem id="snowlLayoutMenuitemStacked"
-                      label="&layoutStacked.label;"
-                      type="radio"
-                      accesskey="&layoutStacked.accesskey;"
-                      name="snowlLayoutMenuitemGroup"
-                      oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kStackedLayout)"/>
-            <menuseparator/>
-            <menuitem id="snowlHeaderMenuitemNone"
-                      label="&headerNone.label;"
-                      type="radio"
-                      accesskey="&headerNone.accesskey;"
-                      name="snowlHeaderMenuitemGroup"
-                      headerType="Snowl.kNoHeader"
-                      oncommand="Snowl._toggleHeader(event)"/>
-            <menuitem id="snowlHeaderMenuitemBrief"
-                      label="&headerBrief.label;"
-                      type="radio"
-                      accesskey="&headerBrief.accesskey;"
-                      name="snowlHeaderMenuitemGroup"
-                      headerType="Snowl.kBriefHeader"
-                      oncommand="Snowl._toggleHeader(event)"/>
-            <menuitem id="snowlHeaderMenuitemFull"
-                      label="&headerFull.label;"
-                      type="radio"
-                      accesskey="&headerFull.accesskey;"
-                      name="snowlHeaderMenuitemGroup"
-                      headerType="Snowl.kFullHeader"
-                      oncommand="Snowl._toggleHeader(event)"/>
-            <menuseparator/>
-            <menuitem id="snowlToolbarMenuitem"
-                      label="&toolbar.label;"
-                      type="checkbox"
-                      accesskey="&toolbar.accesskey;"
-                      name="snowlToolbar"
-                      oncommand="Snowl._toggleToolbar(event)"/>
-            <menuitem id="snowlViewToolbarMenuitem"
-                      label="&viewtoolbar.label;"
-                      type="checkbox"
-                      checked="true"
-                      persist="checked"
-                      accesskey="&viewtoolbar.accesskey;"
-                      name="snowlViewToolbar"
-                      oncommand="Snowl._toggleToolbar(event)"/>
-          </menupopup>
-        </menu>
-        <menuseparator/>
-        <menuitem label="&subscribe.label;" accesskey="&subscribe.accesskey;"
-                  oncommand="Snowl.onSubscribe()"/>
-        <menuitem label="&importOPML.label;" accesskey="&importOPML.accesskey;"
-                  oncommand="Snowl.onImportOPML()"/>
-        <menuitem label="&exportOPML.label;" accesskey="&exportOPML.accesskey;"
-                  oncommand="Snowl.onExportOPML()"/>
-      </menupopup>
+    <menu id="snowlMenu"
+          class="menu-iconic"
+          label="&snowlMenu.label;"
+          accesskey="&snowlMenu.accesskey;"
+          insertafter="menu_openAddons">
+      <menupopup id="snowlToolsMenuPopup"
+          style="visibility: collapse"
+          onpopupshowing="Snowl.onToolsMenuPopupShowing(event)"
+          onpopuphiding="Snowl.onToolsMenuPopupHiding(event)"/>
     </menu>
   </menupopup>
 
+  <popupset id="mainPopupSet">
+    <popup id="snowlMenuPopup"
+               position="after_start"
+               onpopupshowing="Snowl.onSnowlMenuPopupShowing(event)"
+               onpopuphiding="Snowl.onSnowlMenuPopupHiding(event)">
+      <menuitem observes="viewSnowlList" label="&listView.label;"
+                accesskey="&listView.accesskey;"/>
+      <menuitem observes="viewSnowlStream" label="&streamView.label;"
+                accesskey="&streamView.accesskey;"/>
+      <menuseparator/>
+      <menuitem observes="viewSnowlRiver"
+                label="&riverView.label;"
+                accesskey="&riverView.accesskey;"/>
+      <menuseparator/>
+      <menuitem label="&checkForNewMessages.label;"
+                accesskey="&checkForNewMessages.accesskey;"
+                oncommand="Snowl.onCheckForNewMessages()"/>
+      <menuseparator/>
+      <menu id="snowlLayoutMenu"
+            label="&snowlLayoutMenu.label;"
+            popup="snowlLayoutPopup"
+            accesskey="&snowlLayoutMenu.accesskey;">
+
+        <menupopup id="snowlLayoutPopup"
+                   onpopupshowing="Snowl.onLayoutPopupShowing(event)">
+          <menuitem id="snowlLayoutMenuitemClassic"
+                    label="&layoutClassic.label;"
+                    type="radio"
+                    checked="true"
+                    accesskey="&layoutClassic.accesskey;"
+                    name="snowlLayoutMenuitemGroup"
+                    oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kClassicLayout)"/>
+          <menuitem id="snowlLayoutMenuitemVertical"
+                    label="&layoutVertical.label;"
+                    type="radio"
+                    accesskey="&layoutVertical.accesskey;"
+                    name="snowlLayoutMenuitemGroup"
+                    oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kVerticalLayout)"/>
+          <menuitem id="snowlLayoutMenuitemWideMessage"
+                    label="&layoutWideMessage.label;"
+                    type="radio"
+                    accesskey="&layoutWideMessage.accesskey;"
+                    name="snowlLayoutMenuitemGroup"
+                    oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kWideMessageLayout)"/>
+          <menuitem id="snowlLayoutMenuitemWideThread"
+                    label="&layoutWideThread.label;"
+                    type="radio"
+                    accesskey="&layoutWideThread.accesskey;"
+                    name="snowlLayoutMenuitemGroup"
+                    oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kWideThreadLayout)"/>
+          <menuitem id="snowlLayoutMenuitemStacked"
+                    label="&layoutStacked.label;"
+                    type="radio"
+                    accesskey="&layoutStacked.accesskey;"
+                    name="snowlLayoutMenuitemGroup"
+                    oncommand="SnowlMessageView.switchLayout(SnowlMessageView.kStackedLayout)"/>
+          <menuseparator/>
+          <menuitem id="snowlHeaderMenuitemNone"
+                    label="&headerNone.label;"
+                    type="radio"
+                    accesskey="&headerNone.accesskey;"
+                    name="snowlHeaderMenuitemGroup"
+                    headerType="Snowl.kNoHeader"
+                    oncommand="Snowl._toggleHeader(event)"/>
+          <menuitem id="snowlHeaderMenuitemBrief"
+                    label="&headerBrief.label;"
+                    type="radio"
+                    accesskey="&headerBrief.accesskey;"
+                    name="snowlHeaderMenuitemGroup"
+                    headerType="Snowl.kBriefHeader"
+                    oncommand="Snowl._toggleHeader(event)"/>
+          <menuitem id="snowlHeaderMenuitemFull"
+                    label="&headerFull.label;"
+                    type="radio"
+                    accesskey="&headerFull.accesskey;"
+                    name="snowlHeaderMenuitemGroup"
+                    headerType="Snowl.kFullHeader"
+                    oncommand="Snowl._toggleHeader(event)"/>
+          <menuseparator/>
+          <menuitem id="snowlToolbarMenuitem"
+                    label="&toolbar.label;"
+                    type="checkbox"
+                    accesskey="&toolbar.accesskey;"
+                    name="snowlToolbar"
+                    oncommand="Snowl._toggleToolbar(event)"/>
+          <menuitem id="snowlViewToolbarMenuitem"
+                    label="&viewtoolbar.label;"
+                    type="checkbox"
+                    checked="true"
+                    persist="checked"
+                    accesskey="&viewtoolbar.accesskey;"
+                    name="snowlViewToolbar"
+                    oncommand="Snowl._toggleToolbar(event)"/>
+        </menupopup>
+
+      </menu>
+      <menuseparator/>
+      <menuitem label="&subscribe.label;" accesskey="&subscribe.accesskey;"
+                oncommand="Snowl.onSubscribe()"/>
+      <menuitem label="&importOPML.label;" accesskey="&importOPML.accesskey;"
+                oncommand="Snowl.onImportOPML()"/>
+      <menuitem label="&exportOPML.label;" accesskey="&exportOPML.accesskey;"
+                oncommand="Snowl.onExportOPML()"/>
+    </popup>
+
+  </popupset>
+
   <toolbarpalette id="BrowserToolbarPalette">
     <toolbarbutton id="snowlToolbarButton"
                    type="menu"
+                   class="toolbarbutton-1"
+                   popup="snowlMenuPopup"
                    label="&snowlMenu.label;"
-                   tooltiptext="&snowlMenu.label;"
-                   onmousedown="Snowl.onStatusbarButtonMouseDown(event)"/>
+                   onmouseover="Snowl.onSnowlButtonMouseDown(event)"
+                   tooltiptext="&snowlMenu.label;"/>
+
+    <toolbarbutton id="snowlToggleListButton"
+                   observes="viewSnowlList"
+                   class="toolbarbutton-1"
+                   label="&toggleList.label;"
+                   type="checkbox"
+                   oncommand="toggleSidebar('viewSnowlList')"
+                   tooltiptext="&toggleList.tooltip;"/>
+
+    <toolbarbutton id="snowlToggleStreamButton"
+                   observes="viewSnowlStream"
+                   class="toolbarbutton-1"
+                   label="&toggleStream.label;"
+                   type="checkbox"
+                   oncommand="toggleSidebar('viewSnowlStream')"
+                   tooltiptext="&toggleStream.tooltip;"/>
+
+    <toolbarbutton id="snowlToggleRiverButton"
+                   observes="viewSnowlRiver"
+                   class="toolbarbutton-1"
+                   label="&toggleRiver.label;"
+                   type="checkbox"
+                   oncommand="Snowl.onRiverView()"
+                   tooltiptext="&toggleRiver.tooltip;"/>
 
     <toolbarbutton id="snowlToggleHeaderButton"
                    class="toolbarbutton-1"
                    oncommand="Snowl._toggleHeader('Toggle')"
+                   onmouseover="Snowl.onSnowlToggleHeaderButtonMouseover(event)"
                    label="&toggleHeader.label;"
                    snowlHeader="full"
+                   persist="disabled"
                    tooltiptext="&toggleHeader.tooltip;"/>
   </toolbarpalette>>
 
   <statusbar id="status-bar">
-    <statusbarpanel id="snowlStatusbarButton" class="statusbarpanel-menu-iconic"
-                    insertbefore="statusbar-display"
-                    src="chrome://snowl/content/icons/snowl-16.png"
-                    onmousedown="Snowl.onStatusbarButtonMouseDown(event)">
+    <statusbarpanel id="snowlStatusbarButton"
+                    class="statusbarpanel-menu-iconic"
+                    label="&snowlMenu.label;"
+                    popup="snowlMenuPopup"
+                    onmouseover="Snowl.onSnowlButtonMouseDown(event)"
+                    insertbefore="statusbar-display">
     </statusbarpanel>
   </statusbar>
 
Binary file content/icons/table_multiple.png has changed
--- a/locale/en-US/browser.dtd	Fri Oct 24 16:48:59 2008 -0700
+++ b/locale/en-US/browser.dtd	Mon Oct 27 17:07:35 2008 -0700
@@ -67,5 +67,13 @@
 <!ENTITY viewtoolbar.label                    "List Toolbar">
 <!ENTITY viewtoolbar.accesskey                "i">
 
+<!-- These labels and access keys are for toolbar buttons -->
+
+<!ENTITY toggleList.label                     "Snowl Toggle List View">
+<!ENTITY toggleList.tooltip                   "Toggle List View">
+<!ENTITY toggleStream.label                   "Snowl Toggle Stream View">
+<!ENTITY toggleStream.tooltip                 "Toggle Stream View">
+<!ENTITY toggleRiver.label                    "Snowl Toggle River View">
+<!ENTITY toggleRiver.tooltip                  "Toggle River View">
+<!ENTITY toggleHeader.label                   "Snowl Toggle Header">
 <!ENTITY toggleHeader.tooltip                 "Toggle message header to none, brief, or full">
-<!ENTITY toggleHeader.label                   "Snowl Toggle Header">