browser/devtools/shared/widgets/SimpleListWidget.jsm

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 "use strict";
     8 const Ci = Components.interfaces;
     9 const Cu = Components.utils;
    11 Cu.import("resource:///modules/devtools/ViewHelpers.jsm");
    13 this.EXPORTED_SYMBOLS = ["SimpleListWidget"];
    15 /**
    16  * A very simple vertical list view.
    17  *
    18  * Note: this widget should be used in tandem with the WidgetMethods in
    19  * ViewHelpers.jsm.
    20  *
    21  * @param nsIDOMNode aNode
    22  *        The element associated with the widget.
    23  */
    24 function SimpleListWidget(aNode) {
    25   this.document = aNode.ownerDocument;
    26   this.window = this.document.defaultView;
    27   this._parent = aNode;
    29   // Create an internal list container.
    30   this._list = this.document.createElement("scrollbox");
    31   this._list.className = "simple-list-widget-container theme-body";
    32   this._list.setAttribute("flex", "1");
    33   this._list.setAttribute("orient", "vertical");
    34   this._parent.appendChild(this._list);
    36   // Delegate some of the associated node's methods to satisfy the interface
    37   // required by WidgetMethods instances.
    38   ViewHelpers.delegateWidgetAttributeMethods(this, aNode);
    39   ViewHelpers.delegateWidgetEventMethods(this, aNode);
    40 }
    42 SimpleListWidget.prototype = {
    43   /**
    44    * Inserts an item in this container at the specified index.
    45    *
    46    * @param number aIndex
    47    *        The position in the container intended for this item.
    48    * @param nsIDOMNode aContents
    49    *        The node displayed in the container.
    50    * @return nsIDOMNode
    51    *         The element associated with the displayed item.
    52    */
    53   insertItemAt: function(aIndex, aContents) {
    54     aContents.classList.add("simple-list-widget-item");
    56     let list = this._list;
    57     return list.insertBefore(aContents, list.childNodes[aIndex]);
    58   },
    60   /**
    61    * Returns the child node in this container situated at the specified index.
    62    *
    63    * @param number aIndex
    64    *        The position in the container intended for this item.
    65    * @return nsIDOMNode
    66    *         The element associated with the displayed item.
    67    */
    68   getItemAtIndex: function(aIndex) {
    69     return this._list.childNodes[aIndex];
    70   },
    72   /**
    73    * Immediately removes the specified child node from this container.
    74    *
    75    * @param nsIDOMNode aChild
    76    *        The element associated with the displayed item.
    77    */
    78   removeChild: function(aChild) {
    79     this._list.removeChild(aChild);
    81     if (this._selectedItem == aChild) {
    82       this._selectedItem = null;
    83     }
    84   },
    86   /**
    87    * Removes all of the child nodes from this container.
    88    */
    89   removeAllItems: function() {
    90     let list = this._list;
    91     let parent = this._parent;
    93     while (list.hasChildNodes()) {
    94       list.firstChild.remove();
    95     }
    97     parent.scrollTop = 0;
    98     parent.scrollLeft = 0;
    99     this._selectedItem = null;
   100   },
   102   /**
   103    * Gets the currently selected child node in this container.
   104    * @return nsIDOMNode
   105    */
   106   get selectedItem() {
   107     return this._selectedItem;
   108   },
   110   /**
   111    * Sets the currently selected child node in this container.
   112    * @param nsIDOMNode aChild
   113    */
   114   set selectedItem(aChild) {
   115     let childNodes = this._list.childNodes;
   117     if (!aChild) {
   118       this._selectedItem = null;
   119     }
   120     for (let node of childNodes) {
   121       if (node == aChild) {
   122         node.classList.add("selected");
   123         this._selectedItem = node;
   124       } else {
   125         node.classList.remove("selected");
   126       }
   127     }
   128   },
   130   /**
   131    * Adds a new attribute or changes an existing attribute on this container.
   132    *
   133    * @param string aName
   134    *        The name of the attribute.
   135    * @param string aValue
   136    *        The desired attribute value.
   137    */
   138   setAttribute: function(aName, aValue) {
   139     this._parent.setAttribute(aName, aValue);
   141     if (aName == "emptyText") {
   142       this._textWhenEmpty = aValue;
   143     } else if (aName == "headerText") {
   144       this._textAsHeader = aValue;
   145     }
   146   },
   148   /**
   149    * Removes an attribute on this container.
   150    *
   151    * @param string aName
   152    *        The name of the attribute.
   153    */
   154   removeAttribute: function(aName) {
   155     this._parent.removeAttribute(aName);
   157     if (aName == "emptyText") {
   158       this._removeEmptyText();
   159     }
   160   },
   162   /**
   163    * Ensures the specified element is visible.
   164    *
   165    * @param nsIDOMNode aElement
   166    *        The element to make visible.
   167    */
   168   ensureElementIsVisible: function(aElement) {
   169     if (!aElement) {
   170       return;
   171     }
   173     // Ensure the element is visible but not scrolled horizontally.
   174     let boxObject = this._list.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
   175     boxObject.ensureElementIsVisible(aElement);
   176     boxObject.scrollBy(-this._list.clientWidth, 0);
   177   },
   179   /**
   180    * Sets the text displayed permanently in this container as a header.
   181    * @param string aValue
   182    */
   183   set _textAsHeader(aValue) {
   184     if (this._headerTextNode) {
   185       this._headerTextNode.setAttribute("value", aValue);
   186     }
   187     this._headerTextValue = aValue;
   188     this._showHeaderText();
   189   },
   191   /**
   192    * Sets the text displayed in this container when empty.
   193    * @param string aValue
   194    */
   195   set _textWhenEmpty(aValue) {
   196     if (this._emptyTextNode) {
   197       this._emptyTextNode.setAttribute("value", aValue);
   198     }
   199     this._emptyTextValue = aValue;
   200     this._showEmptyText();
   201   },
   203   /**
   204    * Creates and appends a label displayed as this container's header.
   205    */
   206   _showHeaderText: function() {
   207     if (this._headerTextNode || !this._headerTextValue) {
   208       return;
   209     }
   210     let label = this.document.createElement("label");
   211     label.className = "plain simple-list-widget-perma-text";
   212     label.setAttribute("value", this._headerTextValue);
   214     this._parent.insertBefore(label, this._list);
   215     this._headerTextNode = label;
   216   },
   218   /**
   219    * Creates and appends a label signaling that this container is empty.
   220    */
   221   _showEmptyText: function() {
   222     if (this._emptyTextNode || !this._emptyTextValue) {
   223       return;
   224     }
   225     let label = this.document.createElement("label");
   226     label.className = "plain simple-list-widget-empty-text";
   227     label.setAttribute("value", this._emptyTextValue);
   229     this._parent.appendChild(label);
   230     this._emptyTextNode = label;
   231   },
   233   /**
   234    * Removes the label signaling that this container is empty.
   235    */
   236   _removeEmptyText: function() {
   237     if (!this._emptyTextNode) {
   238       return;
   239     }
   240     this._parent.removeChild(this._emptyTextNode);
   241     this._emptyTextNode = null;
   242   },
   244   window: null,
   245   document: null,
   246   _parent: null,
   247   _list: null,
   248   _selectedItem: null,
   249   _headerTextNode: null,
   250   _headerTextValue: "",
   251   _emptyTextNode: null,
   252   _emptyTextValue: ""
   253 };

mercurial