Home | History | Annotate | Download | only in front_end
      1 /*
      2  * Copyright (C) 2012 Adobe Systems Incorporated. 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
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above
      9  *    copyright notice, this list of conditions and the following
     10  *    disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above
     12  *    copyright notice, this list of conditions and the following
     13  *    disclaimer in the documentation and/or other materials
     14  *    provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     20  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
     27  * OF THE POSSIBILITY OF SUCH DAMAGE.
     28  */
     29 
     30 /**
     31  * @constructor
     32  * @extends {WebInspector.View}
     33  * @param {!WebInspector.NamedFlow} flow
     34  */
     35 WebInspector.CSSNamedFlowView = function(flow)
     36 {
     37     WebInspector.View.call(this);
     38     this.element.classList.add("css-named-flow");
     39     this.element.classList.add("outline-disclosure");
     40 
     41     this._treeOutline = new TreeOutline(this.element.createChild("ol"), true);
     42 
     43     this._contentTreeItem = new TreeElement(WebInspector.UIString("content"), null, true);
     44     this._treeOutline.appendChild(this._contentTreeItem);
     45 
     46     this._regionsTreeItem = new TreeElement(WebInspector.UIString("region chain"), null, true);
     47     this._regionsTreeItem.expand();
     48     this._treeOutline.appendChild(this._regionsTreeItem);
     49 
     50     this._flow = flow;
     51 
     52     var content = flow.content;
     53     for (var i = 0; i < content.length; ++i)
     54         this._insertContentNode(content[i]);
     55 
     56     var regions = flow.regions;
     57     for (var i = 0; i < regions.length; ++i)
     58         this._insertRegion(regions[i]);
     59 }
     60 
     61 WebInspector.CSSNamedFlowView.OversetTypeMessageMap = {
     62     empty: "empty",
     63     fit: "fit",
     64     overset: "overset"
     65 }
     66 
     67 WebInspector.CSSNamedFlowView.prototype = {
     68     /**
     69      * @param {?WebInspector.DOMNode} rootDOMNode
     70      * @return {?WebInspector.ElementsTreeOutline}
     71      */
     72     _createFlowTreeOutline: function(rootDOMNode)
     73     {
     74         if (!rootDOMNode)
     75             return null;
     76 
     77         var treeOutline = new WebInspector.ElementsTreeOutline(false, false);
     78         treeOutline.element.classList.add("named-flow-element");
     79         treeOutline.setVisible(true);
     80         treeOutline.rootDOMNode = rootDOMNode;
     81         treeOutline.wireToDomAgent();
     82         WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, treeOutline._elementsTreeUpdater._documentUpdated, treeOutline._elementsTreeUpdater);
     83 
     84         return treeOutline;
     85     },
     86 
     87     /**
     88      * @param {!DOMAgent.NodeId} contentNodeId
     89      * @param {number=} index
     90      */
     91     _insertContentNode: function(contentNodeId, index)
     92     {
     93         var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(contentNodeId));
     94         var treeItem = new TreeElement(treeOutline.element, treeOutline);
     95 
     96         if (index === undefined) {
     97             this._contentTreeItem.appendChild(treeItem);
     98             return;
     99         }
    100 
    101         this._contentTreeItem.insertChild(treeItem, index);
    102     },
    103 
    104     /**
    105      * @param {!CSSAgent.Region} region
    106      * @param {number=} index
    107      */
    108     _insertRegion: function(region, index)
    109     {
    110         var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(region.nodeId));
    111         treeOutline.element.classList.add("region-" + region.regionOverset);
    112 
    113         var treeItem = new TreeElement(treeOutline.element, treeOutline);
    114         var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[region.regionOverset]);
    115         treeItem.tooltip = WebInspector.UIString("Region is %s.", oversetText);
    116 
    117         if (index === undefined) {
    118             this._regionsTreeItem.appendChild(treeItem);
    119             return;
    120         }
    121 
    122         this._regionsTreeItem.insertChild(treeItem, index);
    123     },
    124 
    125     get flow()
    126     {
    127         return this._flow;
    128     },
    129 
    130     set flow(newFlow)
    131     {
    132         this._update(newFlow);
    133     },
    134 
    135     /**
    136      * @param {!TreeElement} regionTreeItem
    137      * @param {string} newRegionOverset
    138      * @param {string} oldRegionOverset
    139      */
    140     _updateRegionOverset: function(regionTreeItem, newRegionOverset, oldRegionOverset)
    141     {
    142         var element = regionTreeItem.representedObject.element;
    143         element.classList.remove("region-" + oldRegionOverset);
    144         element.classList.add("region-" + newRegionOverset);
    145 
    146         var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[newRegionOverset]);
    147         regionTreeItem.tooltip = WebInspector.UIString("Region is %s." , oversetText);
    148     },
    149 
    150     /**
    151      * @param {!Array.<!DOMAgent.NodeId>} oldContent
    152      * @param {!Array.<!DOMAgent.NodeId>} newContent
    153      */
    154     _mergeContentNodes: function(oldContent, newContent)
    155     {
    156         var nodeIdSet = {};
    157         for (var i = 0; i < newContent.length; ++i)
    158             nodeIdSet[newContent[i]] = true;
    159 
    160         var oldContentIndex = 0;
    161         var newContentIndex = 0;
    162         var contentTreeChildIndex = 0;
    163 
    164         while (oldContentIndex < oldContent.length || newContentIndex < newContent.length) {
    165             if (oldContentIndex === oldContent.length) {
    166                 this._insertContentNode(newContent[newContentIndex]);
    167                 ++newContentIndex;
    168                 continue;
    169             }
    170 
    171             if (newContentIndex === newContent.length) {
    172                 this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
    173                 ++oldContentIndex;
    174                 continue;
    175             }
    176 
    177             if (oldContent[oldContentIndex] === newContent[newContentIndex]) {
    178                 ++oldContentIndex;
    179                 ++newContentIndex;
    180                 ++contentTreeChildIndex;
    181                 continue;
    182             }
    183 
    184             if (nodeIdSet[oldContent[oldContentIndex]]) {
    185                 this._insertContentNode(newContent[newContentIndex], contentTreeChildIndex);
    186                 ++newContentIndex;
    187                 ++contentTreeChildIndex;
    188                 continue;
    189             }
    190 
    191             this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
    192             ++oldContentIndex;
    193         }
    194     },
    195 
    196     /**
    197      * @param {!Array.<!CSSAgent.Region>} oldRegions
    198      * @param {!Array.<!CSSAgent.Region>} newRegions
    199      */
    200     _mergeRegions: function(oldRegions, newRegions)
    201     {
    202         var nodeIdSet = {};
    203         for (var i = 0; i < newRegions.length; ++i)
    204             nodeIdSet[newRegions[i].nodeId] = true;
    205 
    206         var oldRegionsIndex = 0;
    207         var newRegionsIndex = 0;
    208         var regionsTreeChildIndex = 0;
    209 
    210         while (oldRegionsIndex < oldRegions.length || newRegionsIndex < newRegions.length) {
    211             if (oldRegionsIndex === oldRegions.length) {
    212                 this._insertRegion(newRegions[newRegionsIndex]);
    213                 ++newRegionsIndex;
    214                 continue;
    215             }
    216 
    217             if (newRegionsIndex === newRegions.length) {
    218                 this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
    219                 ++oldRegionsIndex;
    220                 continue;
    221             }
    222 
    223             if (oldRegions[oldRegionsIndex].nodeId === newRegions[newRegionsIndex].nodeId) {
    224                 if (oldRegions[oldRegionsIndex].regionOverset !== newRegions[newRegionsIndex].regionOverset)
    225                     this._updateRegionOverset(this._regionsTreeItem.children[regionsTreeChildIndex], newRegions[newRegionsIndex].regionOverset, oldRegions[oldRegionsIndex].regionOverset);
    226                 ++oldRegionsIndex;
    227                 ++newRegionsIndex;
    228                 ++regionsTreeChildIndex;
    229                 continue;
    230             }
    231 
    232             if (nodeIdSet[oldRegions[oldRegionsIndex].nodeId]) {
    233                 this._insertRegion(newRegions[newRegionsIndex], regionsTreeChildIndex);
    234                 ++newRegionsIndex;
    235                 ++regionsTreeChildIndex;
    236                 continue;
    237             }
    238 
    239             this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
    240             ++oldRegionsIndex;
    241         }
    242     },
    243 
    244     /**
    245      * @param {!WebInspector.NamedFlow} newFlow
    246      */
    247     _update: function(newFlow)
    248     {
    249         this._mergeContentNodes(this._flow.content, newFlow.content);
    250         this._mergeRegions(this._flow.regions, newFlow.regions);
    251 
    252         this._flow = newFlow;
    253     },
    254 
    255     __proto__: WebInspector.View.prototype
    256 }
    257