Home | History | Annotate | Download | only in layers
      1 /*
      2  * Copyright (C) 2013 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @extends {WebInspector.Object}
     34  * @param {!TreeOutline} treeOutline
     35  */
     36 WebInspector.LayerTreeOutline = function(treeOutline)
     37 {
     38     WebInspector.Object.call(this);
     39     this._treeOutline = treeOutline;
     40     this._treeOutline.childrenListElement.addEventListener("mousemove", this._onMouseMove.bind(this), false);
     41     this._treeOutline.childrenListElement.addEventListener("mouseout", this._onMouseMove.bind(this), false);
     42     this._treeOutline.childrenListElement.addEventListener("contextmenu", this._onContextMenu.bind(this), true);
     43     this._lastHoveredNode = null;
     44 }
     45 
     46 /**
     47  * @enum {string}
     48  */
     49 WebInspector.LayerTreeOutline.Events = {
     50     LayerHovered: "LayerHovered",
     51     LayerSelected: "LayerSelected"
     52 }
     53 
     54 WebInspector.LayerTreeOutline.prototype = {
     55     /**
     56      * @param {?WebInspector.Layer} layer
     57      */
     58     selectLayer: function(layer)
     59     {
     60         this.hoverLayer(null);
     61         var node = layer && this._treeOutline.getCachedTreeElement(layer);
     62         if (node)
     63             node.revealAndSelect(true);
     64         else if (this._treeOutline.selectedTreeElement)
     65             this._treeOutline.selectedTreeElement.deselect();
     66     },
     67 
     68     /**
     69      * @param {?WebInspector.Layer} layer
     70      */
     71     hoverLayer: function(layer)
     72     {
     73         var node = layer && this._treeOutline.getCachedTreeElement(layer);
     74         if (node === this._lastHoveredNode)
     75             return;
     76         if (this._lastHoveredNode)
     77             this._lastHoveredNode.setHovered(false);
     78         if (node)
     79             node.setHovered(true);
     80         this._lastHoveredNode = node;
     81     },
     82 
     83     /**
     84      * @param {?WebInspector.LayerTreeBase} layerTree
     85      */
     86     update: function(layerTree)
     87     {
     88         var seenLayers = new Map();
     89 
     90         /**
     91          * @param {!WebInspector.Layer} layer
     92          * @this {WebInspector.LayerTreeOutline}
     93          */
     94         function updateLayer(layer)
     95         {
     96             if (seenLayers.get(layer))
     97                 console.assert(false, "Duplicate layer: " + layer.id());
     98             seenLayers.put(layer, true);
     99             var node = this._treeOutline.getCachedTreeElement(layer);
    100             var parent = layer === layerTree.contentRoot() ? this._treeOutline : this._treeOutline.getCachedTreeElement(layer.parent());
    101             if (!parent)
    102                 console.assert(false, "Parent is not in the tree");
    103             if (!node) {
    104                 node = new WebInspector.LayerTreeElement(this, layer);
    105                 parent.appendChild(node);
    106             } else {
    107                 if (node.parent !== parent) {
    108                     node.parent.removeChild(node);
    109                     parent.appendChild(node);
    110                 }
    111                 node._update();
    112             }
    113         }
    114         if (layerTree && layerTree.contentRoot())
    115             layerTree.forEachLayer(updateLayer.bind(this), layerTree.contentRoot());
    116         // Cleanup layers that don't exist anymore from tree.
    117         for (var node = /** @type {!TreeElement|!TreeOutline|null} */ (this._treeOutline.children[0]); node && !node.root;) {
    118             if (seenLayers.get(node.representedObject)) {
    119                 node = node.traverseNextTreeElement(false);
    120             } else {
    121                 var nextNode = node.nextSibling || node.parent;
    122                 node.parent.removeChild(node);
    123                 if (node === this._lastHoveredNode)
    124                     this._lastHoveredNode = null;
    125                 node = nextNode;
    126             }
    127         }
    128     },
    129 
    130     /**
    131      * @param {?Event} event
    132      */
    133     _onMouseMove: function(event)
    134     {
    135         var node = this._treeOutline.treeElementFromPoint(event.pageX, event.pageY);
    136         if (node === this._lastHoveredNode)
    137             return;
    138         this.dispatchEventToListeners(WebInspector.LayerTreeOutline.Events.LayerHovered, node && node.representedObject ? {layer: node.representedObject} : null);
    139     },
    140 
    141     /**
    142      * @param {!WebInspector.LayerTreeElement} node
    143      */
    144     _selectedNodeChanged: function(node)
    145     {
    146         var layer = /** @type {!WebInspector.Layer} */ (node.representedObject);
    147         this.dispatchEventToListeners(WebInspector.LayerTreeOutline.Events.LayerSelected, {layer: layer});
    148     },
    149 
    150     /**
    151      * @param {?Event} event
    152      */
    153     _onContextMenu: function(event)
    154     {
    155         var node = this._treeOutline.treeElementFromPoint(event.pageX, event.pageY);
    156         if (!node || !node.representedObject)
    157             return;
    158         var layer = /** @type {!WebInspector.Layer} */ (node.representedObject);
    159         if (!layer)
    160             return;
    161         var domNode = layer.nodeForSelfOrAncestor();
    162         if (!domNode)
    163             return;
    164         var contextMenu = new WebInspector.ContextMenu(event);
    165         contextMenu.appendApplicableItems(domNode);
    166         contextMenu.show();
    167     },
    168 
    169     __proto__: WebInspector.Object.prototype
    170 }
    171 
    172 /**
    173   * @constructor
    174   * @param {!WebInspector.LayerTreeOutline} tree
    175   * @param {!WebInspector.Layer} layer
    176   * @extends {TreeElement}
    177   */
    178 WebInspector.LayerTreeElement = function(tree, layer)
    179 {
    180     TreeElement.call(this, "", layer);
    181     this._treeOutline = tree;
    182     this._update();
    183 }
    184 
    185 WebInspector.LayerTreeElement.prototype = {
    186     onattach: function()
    187     {
    188         var selection = document.createElement("div");
    189         selection.className = "selection";
    190         this.listItemElement.insertBefore(selection, this.listItemElement.firstChild);
    191     },
    192 
    193     _update: function()
    194     {
    195         var layer = /** @type {!WebInspector.Layer} */ (this.representedObject);
    196         var node = layer.nodeForSelfOrAncestor();
    197         var title = document.createDocumentFragment();
    198         title.createChild("div", "selection");
    199         title.appendChild(document.createTextNode(node ? WebInspector.DOMPresentationUtils.simpleSelector(node) : "#" + layer.id()));
    200         var details = title.createChild("span", "dimmed");
    201         details.textContent = WebInspector.UIString(" (%d  %d)", layer.width(), layer.height());
    202         this.title = title;
    203     },
    204 
    205     /**
    206      * @override
    207      * @return {boolean}
    208      */
    209     onselect: function()
    210     {
    211         this._treeOutline._selectedNodeChanged(this);
    212         return false;
    213     },
    214 
    215     /**
    216      * @param {boolean} hovered
    217      */
    218     setHovered: function(hovered)
    219     {
    220         this.listItemElement.classList.toggle("hovered", hovered);
    221     },
    222 
    223     __proto__: TreeElement.prototype
    224 }
    225