changeset 79:d2a718e4a21d

an order button for reordering the river of news
author Myk Melez <myk@mozilla.org>
date Thu, 15 May 2008 14:50:37 -0700
parents 7a0d3fec5102
children 1ab89e642261
files extension/content/river.css extension/content/river.js extension/content/river.xhtml
diffstat 3 files changed, 139 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/extension/content/river.css	Thu May 15 11:10:48 2008 -0700
+++ b/extension/content/river.css	Thu May 15 14:50:37 2008 -0700
@@ -1,3 +1,56 @@
+html {
+  color: black;
+  background-color: white;
+  font: message-box;
+  font-size: 100%;
+}
+
+body {
+  /* Remove the default margin around the body so the toolbar blends in
+   * with the surrounding chrome and appears to be part of it (rather than
+   * having white space all around it, which looks odd). */
+  margin: 0;
+}
+
+
+#toolbar {
+  color: -moz-DialogText;
+  background-color: -moz-dialog;
+  font: message-box;
+}
+
+/* Show icons in the sources menulist. */
+#sourceMenu > menupopup > menuitem > .menu-iconic-left {
+  display: block;
+}
+
+button {
+  /* Let the buttons be small. */
+  min-width: 0;
+
+  /* Make the button square and as tall as the list of sources.
+   * XXX Does this work on Windows and Mac? */
+  width: 29px;
+  height: 29px;
+}
+
+#orderButton .button-icon {
+  /* Compensate for the icon being packed to the left of its enclosing box.
+   * Maybe we should pack center (although we have to remove -moz-appearance
+   * to do that) or make the icon file larger instead.
+   * XXX Does this work on Windows and Mac? */
+  padding-left: 2px;
+}
+
+#unreadButton .button-text {
+  /* Compensate for the text being packed to the right of its enclosing box.
+   * Maybe we should pack center (although we have to remove -moz-appearance
+   * to do that).
+   * XXX Does this work on Windows and Mac? */
+  padding-right: 2px;
+}
+
+
 .entry {
   margin-top: 3em;
 }
@@ -23,21 +76,6 @@
   margin-top: 0;
 }
 
-html { 
-  background-color: white;
-  color: black;
-}
-
 label {
   -moz-margin-start: 0;
 }
-
-html {
-  font: message-box;
-  font-size: 100%;
-}
-
-/* Show icons on the sources menulist. */
-#sourceMenu > menupopup > menuitem > .menu-iconic-left {
-  display: block;
-}
--- a/extension/content/river.js	Thu May 15 11:10:48 2008 -0700
+++ b/extension/content/river.js	Thu May 15 14:50:37 2008 -0700
@@ -116,6 +116,20 @@
     return this._faviconSvc;
   },
 
+  get _orderButton() {
+    let orderButton = document.getElementById("orderButton");
+    delete this._orderButton;
+    this._orderButton = orderButton;
+    return this._orderButton;
+  },
+
+  get _unreadButton() {
+    let unreadButton = document.getElementById("unreadButton");
+    delete this._unreadButton;
+    this._unreadButton = unreadButton;
+    return this._unreadButton;
+  },
+
   // The set of messages to display in the view.
   _collection: null,
   
@@ -151,7 +165,7 @@
 
     if ("unread" in this._params) {
       this._collection.read = false;
-      document.getElementById("unreadButton").checked = true;
+      this._unreadButton.checked = true;
     }
 
     if ("filter" in this._params) {
@@ -171,14 +185,25 @@
       }
     }
 
+    if ("order" in this._params) {
+      switch(this._params.order) {
+        case "descending":
+          this._setOrder(-1);
+          break;
+        case "ascending":
+        default:
+          this._setOrder(1);
+          break;
+      }
+    }
   },
 
-  onCommandUnreadButton: function(aEvent, aButton) {
+  onCommandUnreadButton: function(aEvent) {
     // FIXME: instead of rebuilding from scratch each time, when going from
     // all to unread, simply hide the ones that are read (f.e. by setting a CSS
     // class on read items and then using a CSS rule to hide them).
 
-    if (aButton.checked) {
+    if (this._unreadButton.checked) {
       this._collection.read = false;
       this.rebuildView();
     }
@@ -190,6 +215,50 @@
     this._updateURI();
   },
 
+  onCommandOrderButton: function(aEvent) {
+    // checkState can be either 0, 1, or 2.  The default is 0, which means
+    // to sort in ascending order.  The value 1 means to sort in descending
+    // order.  The value 2 is undefined, but users can't make the button
+    // switch to that state; it must be set programmatically, and we don't
+    // use it (presumably we could one day make it mean "sort randomly").
+
+    switch(this._orderButton.checked) {
+      case true:
+        this._setOrder(-1);
+        break;
+      case false:
+      default:
+        this._setOrder(1);
+        break;
+    }
+
+    // Presumably here we could do messages.reverse(), which would be faster,
+    // but can we be sure the messages started in the reverse of the new state?
+    this._collection.sort(this._collection.sortProperty,
+                          this._collection.sortOrder);
+
+    this.rebuildView();
+    this._updateURI();
+  },
+
+  _setOrder: function(aOrder) {
+    switch (aOrder) {
+      case -1:
+        this._collection.sortOrder = -1;
+        this._orderButton.checkState = 1;
+        this._orderButton.checked = true;
+        this._orderButton.image = "chrome://snowl/content/arrow-up.png";
+        break;
+      case 1:
+      default:
+        this._collection.sortOrder = 1;
+        this._orderButton.checkState = 0;
+        this._orderButton.checked = false;
+        this._orderButton.image = "chrome://snowl/content/arrow-down.png";
+        break;
+    }
+  },
+
   onCommandFilterTextbox: function(aEvent, aFilterTextbox) {
     this._collection.filter = aFilterTextbox.value;
     this.rebuildView();
@@ -215,6 +284,9 @@
     if (this._collection.sourceID)
       params.push("sourceID=" + encodeURIComponent(this._collection.sourceID));
 
+    if (this._collection.sortOrder == -1)
+      params.push("order=descending");
+
     let query = params.length > 0 ? "?" + params.join("&") : "";
     let spec = "chrome://snowl/content/river.xhtml" + query;
     let uri = Cc["@mozilla.org/network/io-service;1"].
--- a/extension/content/river.xhtml	Thu May 15 11:10:48 2008 -0700
+++ b/extension/content/river.xhtml	Thu May 15 14:50:37 2008 -0700
@@ -13,9 +13,6 @@
   %feedDTD;
 ]>
 
-<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
-<?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
-
 <html id="feedHandler" xmlns="http://www.w3.org/1999/xhtml"
       xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <head>
@@ -25,16 +22,23 @@
     <script type="application/x-javascript;version=1.8" src="chrome://snowl/content/river.js"/>
   </head>
   <body onload="RiverView.init()">
-    <xul:hbox id="toolbar" align="center">
-      <xul:button id="unreadButton" type="checkbox" label="Unread"
-                  oncommand="RiverView.onCommandUnreadButton(event, this)"/>
-
+    <xul:hbox id="toolbar" align="center" style="width: 100%">
       <!-- Bug 348830 means there can't be whitespace between the menulist tags
          - and the menupopup tag. -->
       <xul:menulist id="sourceMenu" oncommand="RiverView.onCommandSourceMenu(event)"
         ><xul:menupopup id="sourcePopup"
       /></xul:menulist>
 
+      <xul:button id="unreadButton" type="checkbox" checked="false"
+                  label="U"
+                  oncommand="RiverView.onCommandUnreadButton(event)"/>
+
+      <xul:button id="orderButton" type="checkbox" checked="false"
+                  image="chrome://snowl/content/arrow-down.png"
+                  oncommand="RiverView.onCommandOrderButton(event)"/>
+
+      <xul:spacer flex="1"/>
+
       <xul:textbox id="filterTextbox" type="timed" timeout="200"
                    oncommand="RiverView.onCommandFilterTextbox(event, this)"/>
     </xul:hbox>