Bug 400495 - Add "Clear List" button to download manager. r=mconnor, ui-r=beltzner, ui-r=mconnor, b-ff3=beltzner, a1.9=mconnor
authoredward.lee@engineering.uiuc.edu
Tue, 22 Apr 2008 20:57:05 -0700
changeset 14576 a8cbcd13b000204ff784a79335d2404888568939
parent 14575 4fd59211d9e1d20d0610dfed533d55f4c3452347
child 14577 15a3f46c795a5fa63c02e8db37fce9cddeb9659b
push id14
push userbsmedberg@mozilla.com
push dateTue, 29 Apr 2008 14:30:10 +0000
treeherdermozilla-central@78e482f2d4be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmconnor, beltzner, mconnor
bugs400495
milestone1.9pre
Bug 400495 - Add "Clear List" button to download manager. r=mconnor, ui-r=beltzner, ui-r=mconnor, b-ff3=beltzner, a1.9=mconnor
toolkit/mozapps/downloads/content/downloads.js
toolkit/mozapps/downloads/content/downloads.xul
toolkit/mozapps/downloads/tests/browser/browser_cleanup_search.js
toolkit/themes/gnomestripe/mozapps/downloads/downloads.css
toolkit/themes/pinstripe/mozapps/downloads/downloads.css
toolkit/themes/winstripe/mozapps/downloads/downloads.css
--- a/toolkit/mozapps/downloads/content/downloads.js
+++ b/toolkit/mozapps/downloads/content/downloads.js
@@ -347,16 +347,38 @@ function copySourceLocation(aDownload)
   if (typeof gPerformAllCallback == "function")
     gPerformAllCallback(uri);
   else {
     // It's a plain copy source, so copy it
     clipboard.copyString(uri);
   }
 }
 
+/**
+ * Remove the currently shown downloads from the download list.
+ */
+function clearDownloadList() {
+  // Clear the whole list if there's no search
+  if (gSearchTerms == "") {
+    gDownloadManager.cleanUp();
+    return;
+  }
+
+  // Remove each download starting from the end until we hit a download
+  // that is in progress
+  let item;
+  while ((item = gDownloadsView.lastChild) && !item.inProgress)
+    removeDownload(item);
+
+  // Clear the input as if the user did it and move focus to the list
+  gSearchBox.value = "";
+  gSearchBox.doCommand();
+  gDownloadsView.focus();
+}
+
 // This is called by the progress listener.
 var gLastComputedMean = -1;
 var gLastActiveDownloads = 0;
 function onUpdateProgress()
 {
   let numActiveDownloads = gDownloadManager.activeDownloadCount;
 
   // Use the default title and reset "last" values if there's no downloads
@@ -494,123 +516,109 @@ var gContextMenus = [
     , "menuitem_cancel"
     , "menuseparator"
     , "menuitem_show"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
-    , "menuseparator"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_FINISHED
   [
     "menuitem_open"
     , "menuitem_show"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_FAILED
   [
     "menuitem_retry"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_CANCELED
   [
     "menuitem_retry"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_PAUSED
   [
     "menuitem_resume"
     , "menuitem_cancel"
     , "menuseparator"
     , "menuitem_show"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
-    , "menuseparator"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_QUEUED
   [
     "menuitem_cancel"
     , "menuseparator"
     , "menuitem_show"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
-    , "menuseparator"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_BLOCKED_PARENTAL
   [
     "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_SCANNING
   [
     "menuitem_show"
     , "menuseparator"
     , "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
-    , "menuseparator"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_DIRTY
   [
     "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ],
   // DOWNLOAD_BLOCKED_POLICY
   [
     "menuitem_openReferrer"
     , "menuitem_copyLocation"
     , "menuseparator"
     , "menuitem_selectAll"
     , "menuseparator"
     , "menuitem_removeFromList"
-    , "menuitem_clearList"
   ]
 ];
 
 function buildContextMenu(aEvent)
 {
   if (aEvent.target.id != "downloadContextMenu")
     return false;
 
@@ -672,22 +680,16 @@ var gDownloadDNDObserver =
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Command Updating and Command Handlers
 
 var gDownloadViewController = {
   isCommandEnabled: function(aCommand, aItem)
   {
-    // This switch statement is for commands that do not need a download object
-    switch (aCommand) {
-      case "cmd_clearList":
-        return gDownloadManager.canCleanUp;
-    }
-
     let dl = aItem;
     let download = null; // used for getting an nsIDownload object
 
     switch (aCommand) {
       case "cmd_cancel":
         return dl.inProgress;
       case "cmd_open": {
         let file = getLocalFileFromNativePathOrUrl(dl.getAttribute("file"));
@@ -752,40 +754,16 @@ var gDownloadViewController = {
       retryDownload(aSelectedItem);
     },
     cmd_show: function(aSelectedItem) {
       showDownload(aSelectedItem);
     },
     cmd_copyLocation: function(aSelectedItem) {
       copySourceLocation(aSelectedItem);
     },
-    cmd_clearList: function() {
-      // If we're performing all, we can save some work by only doing it once
-      if (gPerformAllCallback === null)
-        gPerformAllCallback = function() {};
-      else if (gPerformAllCallback)
-        return;
-
-      // Clear the whole list if there's no search
-      if (gSearchTerms == "") {
-        gDownloadManager.cleanUp();
-      }
-      else {
-        // Remove each download starting from the end until we hit a download
-        // that is in progress
-        let item;
-        while ((item = gDownloadsView.lastChild) && !item.inProgress)
-          removeDownload(item);
-
-        // Clear the input as if the user did it and move focus to the list
-        gSearchBox.value = "";
-        gSearchBox.doCommand();
-        gDownloadsView.focus();
-      }
-    }
   }
 };
 
 /**
  * Helper function to do commands.
  *
  * @param aCmd
  *        The command to be performed.
--- a/toolkit/mozapps/downloads/content/downloads.xul
+++ b/toolkit/mozapps/downloads/content/downloads.xul
@@ -77,16 +77,17 @@
     <stringbundle id="brandStrings" src="chrome://branding/locale/brand.properties"/>
     <stringbundle id="downloadStrings" src="chrome://mozapps/locale/downloads/downloads.properties"/>
   </stringbundleset>
 
   <!-- Use this commandset for command which do not depened on focus or selection -->
   <commandset id="generalCommands">
     <command id="cmd_findDownload" oncommand="setSearchboxFocus();"/>
     <command id="cmd_selectAllDownloads" oncommand="gDownloadsView.selectAll();"/>
+    <command id="cmd_clearList" oncommand="clearDownloadList();"/>
   </commandset>
 
   <keyset id="downloadKeys">
     <key keycode="VK_ENTER" oncommand="doDefaultForSelected();"/>
     <key keycode="VK_RETURN" oncommand="doDefaultForSelected();"/>
     <key id="key_pauseResume" key=" " oncommand="performCommand('cmd_pauseResume');"/>
     <key id="key_removeFromList"  keycode="VK_DELETE" oncommand="performCommand('cmd_removeFromList');"/>
 #ifdef XP_MACOSX
@@ -162,31 +163,30 @@
               accesskey="&cmd.copyDownloadLink.accesskey;"
               oncommand="performCommand('cmd_copyLocation');"
               cmd="cmd_copyLocation"/>
 
     <menuitem id="menuitem_selectAll"
               label="&selectAllCmd.label;"
               accesskey="&selectAllCmd.accesskey;"
               command="cmd_selectAllDownloads"/>
-              
-    <menuitem id="menuitem_clearList"
-              label="&cmd.clearList.label;"
-              accesskey="&cmd.clearList.accesskey;"
-              oncommand="performCommand('cmd_clearList');"
-              cmd="cmd_clearList"/>
   </vbox>
   
   <menupopup id="downloadContextMenu" onpopupshowing="return buildContextMenu(event);"/>
 
   <richlistbox id="downloadView" seltype="multiple" flex="1"
                context="downloadContextMenu"
                ondblclick="onDownloadDblClick(event);"
                ondragover="nsDragAndDrop.dragOver(event, gDownloadDNDObserver);"
                ondragdrop="nsDragAndDrop.drop(event, gDownloadDNDObserver);">
   </richlistbox>
 
-  <hbox id="search">
+  <hbox id="search" align="center">
+    <button id="clearListButton" command="cmd_clearList"
+            label="&cmd.clearList.label;"
+            accesskey="&cmd.clearList.accesskey;"
+            tooltiptext="&cmd.clearList.tooltip;"/>
+    <spacer flex="1"/>
     <textbox type="timed" timeout="500" id="searchbox"
              oncommand="buildDownloadList();" emptytext="&searchBox.label;"/>
   </hbox>
 
 </window>
--- a/toolkit/mozapps/downloads/tests/browser/browser_cleanup_search.js
+++ b/toolkit/mozapps/downloads/tests/browser/browser_cleanup_search.js
@@ -110,17 +110,17 @@ function test()
         // Next phase checks for the download to delete
         testPhase++;
         return doTest();
       case 1:
         // Got it!
         ok(downloadView.itemCount == 1, "Search found the item to delete");
 
         // Clear the list that has the single matched item
-        $("menuitem_clearList").doCommand();
+        $("cmd_clearList").doCommand();
 
         // Make sure the default list is built
         testPhase++;
         return doTest();
       case 2:
         // Done rebuilding with one item left
         ok(downloadView.itemCount == 1, "Clear list rebuilt the list with one");
 
--- a/toolkit/themes/gnomestripe/mozapps/downloads/downloads.css
+++ b/toolkit/themes/gnomestripe/mozapps/downloads/downloads.css
@@ -100,8 +100,13 @@ menuitem:not([type]) {
   height: 32px;
 }
 
 /* prevent flickering when changing states */
 .downloadTypeIcon {
   min-height: 32px;
   min-width: 32px;
 }
+
+#clearListButton {
+  list-style-image: url(moz-icon://stock/gtk-clear?size=button);
+  margin-top: 4px;
+}
--- a/toolkit/themes/pinstripe/mozapps/downloads/downloads.css
+++ b/toolkit/themes/pinstripe/mozapps/downloads/downloads.css
@@ -104,16 +104,30 @@ richlistitem[type="download"] button {
 
 #search {
   -moz-box-pack: end;
   -moz-padding-end: 4px;
   background-image: url("chrome://global/skin/toolbar/toolbar-background.gif");
   background-repeat: repeat-x;
 }
 
+#clearListButton {
+  -moz-appearance: none;
+  border: 1px solid #5F5F5F;
+  -moz-border-radius: 4px;
+  background: url(chrome://global/skin/icons/white-gray-gradient.gif) #A09E9D repeat-x top center;
+  min-height: 0;
+  min-width: 0;
+  padding: 2px;
+}
+
+#clearListButton:hover:active {
+  background: url(chrome://global/skin/icons/white-gray-gradient-active.gif);
+}
+
 #searchbox {
   -moz-appearance: none;
   border: 3px solid;
   -moz-border-top-colors: #676767 #C5C5C5 -moz-Field;
   -moz-border-bottom-colors: #C2C2C2 #A4A4A4 -moz-Field;
   -moz-border-right-colors: #969696 #C5C5C5 -moz-Field;
   -moz-border-left-colors: #969696 #C5C5C5 -moz-Field;
   -moz-border-radius: 11.5px;
--- a/toolkit/themes/winstripe/mozapps/downloads/downloads.css
+++ b/toolkit/themes/winstripe/mozapps/downloads/downloads.css
@@ -63,8 +63,14 @@ richlistitem[type="download"] .dateTime 
   list-style-image: url(chrome://global/skin/icons/Error.png);
 }
 
 /* prevent flickering when changing states */
 .downloadTypeIcon {
   min-height: 32px;
   min-width: 32px;
 }
+
+#clearListButton {
+  min-height: 0;
+  min-width: 0;
+  height: 1em;
+}