Bug 1117145 - Part 2 - Unify DownloadsViewItem and DownloadsViewItemController. r=jaws draft
authorPaolo Amadini <paolo.mozmail@amadzone.org>
Wed, 10 Feb 2016 14:54:24 +0000
changeset 330927 d7664756102fd09d59b17cb38c0376f688c20382
parent 330926 4282601d24c84535f61851e8884c108edf219fcf
child 330928 d2938e83954c4162825a442311352b3e20d0a13c
push id10859
push userpaolo.mozmail@amadzone.org
push dateSun, 14 Feb 2016 17:41:24 +0000
reviewersjaws
bugs1117145
milestone47.0a1
Bug 1117145 - Part 2 - Unify DownloadsViewItem and DownloadsViewItemController. r=jaws MozReview-Commit-ID: 8qcV5Y7t1hM
browser/components/downloads/content/downloads.js
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -18,26 +18,23 @@
  *
  * DownloadsView
  * Builds and updates the downloads list widget, responding to changes in the
  * download state and real-time data.  In addition, handles part of the user
  * interaction events raised by the downloads list widget.
  *
  * DownloadsViewItem
  * Builds and updates a single item in the downloads list widget, responding to
- * changes in the download state and real-time data.
+ * changes in the download state and real-time data, and handles the user
+ * interaction events related to a single item in the downloads list widgets.
  *
  * DownloadsViewController
  * Handles part of the user interaction events raised by the downloads list
  * widget, in particular the "commands" that apply to multiple items, and
  * dispatches the commands that apply to individual items.
- *
- * DownloadsViewItemController
- * Handles all the user interaction events, in particular the "commands",
- * related to a single item in the downloads list widgets.
  */
 
 /**
  * A few words on focus and focusrings
  *
  * We do quite a few hacks in the Downloads Panel for focusrings. In fact, we
  * basically suppress most if not all XUL-level focusrings, and style/draw
  * them ourselves (using :focus instead of -moz-focusring). There are a few
@@ -841,38 +838,37 @@ const DownloadsView = {
       }
     }
 
     this._itemCountChanged();
   },
 
   /**
    * Associates each richlistitem for a download with its corresponding
-   * DownloadsViewItemController object.
+   * DownloadsViewItem object.
    */
-  _controllersForElements: new Map(),
+  _itemsForElements: new Map(),
 
-  controllerForElement(element) {
-    return this._controllersForElements.get(element);
+  itemForElement(element) {
+    return this._itemsForElements.get(element);
   },
 
   /**
    * Creates a new view item associated with the specified data item, and adds
    * it to the top or the bottom of the list.
    */
   _addViewItem(download, aNewest)
   {
     DownloadsCommon.log("Adding a new DownloadsViewItem to the downloads list.",
                         "aNewest =", aNewest);
 
     let element = document.createElement("richlistitem");
     let viewItem = new DownloadsViewItem(download, element);
     this._visibleViewItems.set(download, viewItem);
-    let viewItemController = new DownloadsViewItemController(download);
-    this._controllersForElements.set(element, viewItemController);
+    this._itemsForElements.set(element, viewItem);
     if (aNewest) {
       this.richListBox.insertBefore(element, this.richListBox.firstChild);
     } else {
       this.richListBox.appendChild(element);
     }
   },
 
   /**
@@ -883,17 +879,17 @@ const DownloadsView = {
     let element = this._visibleViewItems.get(download).element;
     let previousSelectedIndex = this.richListBox.selectedIndex;
     this.richListBox.removeChild(element);
     if (previousSelectedIndex != -1) {
       this.richListBox.selectedIndex = Math.min(previousSelectedIndex,
                                                 this.richListBox.itemCount - 1);
     }
     this._visibleViewItems.delete(download);
-    this._controllersForElements.delete(element);
+    this._itemsForElements.delete(element);
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// User interface event functions
 
   /**
    * Helper function to do commands on a specific download item.
    *
@@ -904,17 +900,17 @@ const DownloadsView = {
    * @param aCommand
    *        The command to be performed.
    */
   onDownloadCommand(aEvent, aCommand) {
     let target = aEvent.target;
     while (target.nodeName != "richlistitem") {
       target = target.parentNode;
     }
-    DownloadsView.controllerForElement(target).doCommand(aCommand);
+    DownloadsView.itemForElement(target).doCommand(aCommand);
   },
 
   onDownloadClick(aEvent) {
     // Handle primary clicks only, and exclude the action button.
     if (aEvent.button == 0 &&
         !aEvent.originalTarget.hasAttribute("oncommand")) {
       goDoCommand("downloadsCmd_open");
     }
@@ -981,17 +977,17 @@ const DownloadsView = {
 
   onDownloadDragStart(aEvent) {
     let element = this.richListBox.selectedItem;
     if (!element) {
       return;
     }
 
     // We must check for existence synchronously because this is a DOM event.
-    let file = new FileUtils.File(DownloadsView.controllerForElement(element)
+    let file = new FileUtils.File(DownloadsView.itemForElement(element)
                                                .download.target.path);
     if (!file.exists()) {
       return;
     }
 
     let dataTransfer = aEvent.dataTransfer;
     dataTransfer.mozSetDataAt("application/x-moz-file", file, 0);
     dataTransfer.effectAllowed = "copyMove";
@@ -1006,17 +1002,18 @@ const DownloadsView = {
 
 XPCOMUtils.defineConstant(this, "DownloadsView", DownloadsView);
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsViewItem
 
 /**
  * Builds and updates a single item in the downloads list widget, responding to
- * changes in the download state and real-time data.
+ * changes in the download state and real-time data, and handles the user
+ * interaction events related to a single item in the downloads list widgets.
  *
  * @param download
  *        Download object to be associated with the view item.
  * @param aElement
  *        XUL element corresponding to the single download item in the view.
  */
 function DownloadsViewItem(download, aElement) {
   this.download = download;
@@ -1046,123 +1043,17 @@ DownloadsViewItem.prototype = {
   onChanged() {
     // This cannot be placed within onStateChanged because
     // when a download goes from hasBlockedData to !hasBlockedData
     // it will still remain in the same state.
     this.element.classList.toggle("temporary-block",
                                   !!this.download.hasBlockedData);
     this._updateProgress();
   },
-};
 
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewController
-
-/**
- * Handles part of the user interaction events raised by the downloads list
- * widget, in particular the "commands" that apply to multiple items, and
- * dispatches the commands that apply to individual items.
- */
-const DownloadsViewController = {
-  //////////////////////////////////////////////////////////////////////////////
-  //// Initialization and termination
-
-  initialize() {
-    window.controllers.insertControllerAt(0, this);
-  },
-
-  terminate() {
-    window.controllers.removeController(this);
-  },
-
-  //////////////////////////////////////////////////////////////////////////////
-  //// nsIController
-
-  supportsCommand(aCommand) {
-    // Firstly, determine if this is a command that we can handle.
-    if (!(aCommand in this.commands) &&
-        !(aCommand in DownloadsViewItemController.prototype.commands)) {
-      return false;
-    }
-    // Secondly, determine if focus is on a control in the downloads list.
-    let element = document.commandDispatcher.focusedElement;
-    while (element && element != DownloadsView.richListBox) {
-      element = element.parentNode;
-    }
-    // We should handle the command only if the downloads list is among the
-    // ancestors of the focused element.
-    return !!element;
-  },
-
-  isCommandEnabled(aCommand) {
-    // Handle commands that are not selection-specific.
-    if (aCommand == "downloadsCmd_clearList") {
-      return DownloadsCommon.getData(window).canRemoveFinished;
-    }
-
-    // Other commands are selection-specific.
-    let element = DownloadsView.richListBox.selectedItem;
-    return element && DownloadsView.controllerForElement(element)
-                                   .isCommandEnabled(aCommand);
-  },
-
-  doCommand(aCommand) {
-    // If this command is not selection-specific, execute it.
-    if (aCommand in this.commands) {
-      this.commands[aCommand].apply(this);
-      return;
-    }
-
-    // Other commands are selection-specific.
-    let element = DownloadsView.richListBox.selectedItem;
-    if (element) {
-      // The doCommand function also checks if the command is enabled.
-      DownloadsView.controllerForElement(element).doCommand(aCommand);
-    }
-  },
-
-  onEvent() {},
-
-  //////////////////////////////////////////////////////////////////////////////
-  //// Other functions
-
-  updateCommands() {
-    Object.keys(this.commands).forEach(goUpdateCommand);
-    Object.keys(DownloadsViewItemController.prototype.commands)
-          .forEach(goUpdateCommand);
-  },
-
-  //////////////////////////////////////////////////////////////////////////////
-  //// Selection-independent commands
-
-  /**
-   * This object contains one key for each command that operates regardless of
-   * the currently selected item in the list.
-   */
-  commands: {
-    downloadsCmd_clearList() {
-      DownloadsCommon.getData(window).removeFinished();
-    }
-  }
-};
-
-XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController);
-
-////////////////////////////////////////////////////////////////////////////////
-//// DownloadsViewItemController
-
-/**
- * Handles all the user interaction events, in particular the "commands",
- * related to a single item in the downloads list widgets.
- */
-function DownloadsViewItemController(download) {
-  this.download = download;
-}
-
-DownloadsViewItemController.prototype = {
   isCommandEnabled(aCommand) {
     switch (aCommand) {
       case "downloadsCmd_open": {
         if (!this.download.succeeded) {
           return false;
         }
 
         let file = new FileUtils.File(this.download.target.path);
@@ -1206,17 +1097,17 @@ DownloadsViewItemController.prototype = 
   },
 
   //////////////////////////////////////////////////////////////////////////////
   //// Item commands
 
   /**
    * This object contains one key for each command that operates on this item.
    *
-   * In commands, the "this" identifier points to the controller item.
+   * In commands, the "this" identifier points to the DownloadsViewItem.
    */
   commands: {
     cmd_delete() {
       DownloadsCommon.removeAndFinalizeDownload(this.download);
       PlacesUtils.bhistory.removePage(
                              NetUtil.newURI(this.download.source.url));
     },
 
@@ -1305,16 +1196,108 @@ DownloadsViewItemController.prototype = 
       }.apply(this);
       if (defaultCommand && this.isCommandEnabled(defaultCommand)) {
         this.doCommand(defaultCommand);
       }
     },
   },
 };
 
+////////////////////////////////////////////////////////////////////////////////
+//// DownloadsViewController
+
+/**
+ * Handles part of the user interaction events raised by the downloads list
+ * widget, in particular the "commands" that apply to multiple items, and
+ * dispatches the commands that apply to individual items.
+ */
+const DownloadsViewController = {
+  //////////////////////////////////////////////////////////////////////////////
+  //// Initialization and termination
+
+  initialize() {
+    window.controllers.insertControllerAt(0, this);
+  },
+
+  terminate() {
+    window.controllers.removeController(this);
+  },
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// nsIController
+
+  supportsCommand(aCommand) {
+    // Firstly, determine if this is a command that we can handle.
+    if (!(aCommand in this.commands) &&
+        !(aCommand in DownloadsViewItem.prototype.commands)) {
+      return false;
+    }
+    // Secondly, determine if focus is on a control in the downloads list.
+    let element = document.commandDispatcher.focusedElement;
+    while (element && element != DownloadsView.richListBox) {
+      element = element.parentNode;
+    }
+    // We should handle the command only if the downloads list is among the
+    // ancestors of the focused element.
+    return !!element;
+  },
+
+  isCommandEnabled(aCommand) {
+    // Handle commands that are not selection-specific.
+    if (aCommand == "downloadsCmd_clearList") {
+      return DownloadsCommon.getData(window).canRemoveFinished;
+    }
+
+    // Other commands are selection-specific.
+    let element = DownloadsView.richListBox.selectedItem;
+    return element && DownloadsView.itemForElement(element)
+                                   .isCommandEnabled(aCommand);
+  },
+
+  doCommand(aCommand) {
+    // If this command is not selection-specific, execute it.
+    if (aCommand in this.commands) {
+      this.commands[aCommand].apply(this);
+      return;
+    }
+
+    // Other commands are selection-specific.
+    let element = DownloadsView.richListBox.selectedItem;
+    if (element) {
+      // The doCommand function also checks if the command is enabled.
+      DownloadsView.itemForElement(element).doCommand(aCommand);
+    }
+  },
+
+  onEvent() {},
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Other functions
+
+  updateCommands() {
+    Object.keys(this.commands).forEach(goUpdateCommand);
+    Object.keys(DownloadsViewItem.prototype.commands)
+          .forEach(goUpdateCommand);
+  },
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Selection-independent commands
+
+  /**
+   * This object contains one key for each command that operates regardless of
+   * the currently selected item in the list.
+   */
+  commands: {
+    downloadsCmd_clearList() {
+      DownloadsCommon.getData(window).removeFinished();
+    }
+  }
+};
+
+XPCOMUtils.defineConstant(this, "DownloadsViewController", DownloadsViewController);
 
 ////////////////////////////////////////////////////////////////////////////////
 //// DownloadsSummary
 
 /**
  * Manages the summary at the bottom of the downloads panel list if the number
  * of items in the list exceeds the panels limit.
  */