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 * @param {!WebInspector.LayerTreeModel} model 34 * @extends {WebInspector.View} 35 */ 36WebInspector.LayerDetailsView = function(model) 37{ 38 WebInspector.View.call(this); 39 this.element.classList.add("fill"); 40 this.element.classList.add("layer-details-view"); 41 this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("Select a layer to see its details")); 42 this._createTable(); 43 this._model = model; 44 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerTreeChanged, this._onLayerTreeUpdated, this); 45 this._model.addEventListener(WebInspector.LayerTreeModel.Events.LayerPainted, this._onLayerPainted, this); 46} 47 48/** 49 * @type {!Object.<string, string>} 50 */ 51WebInspector.LayerDetailsView.CompositingReasonDetail = { 52 "transform3D": WebInspector.UIString("Composition due to association with an element with a CSS 3D transform."), 53 "video": WebInspector.UIString("Composition due to association with a <video> element."), 54 "canvas": WebInspector.UIString("Composition due to the element being a <canvas> element."), 55 "plugin": WebInspector.UIString("Composition due to association with a plugin."), 56 "iFrame": WebInspector.UIString("Composition due to association with an <iframe> element."), 57 "backfaceVisibilityHidden": WebInspector.UIString("Composition due to association with an element with a \"backface-visibility: hidden\" style."), 58 "animation": WebInspector.UIString("Composition due to association with an animated element."), 59 "filters": WebInspector.UIString("Composition due to association with an element with CSS filters applied."), 60 "positionFixed": WebInspector.UIString("Composition due to association with an element with a \"position: fixed\" style."), 61 "positionSticky": WebInspector.UIString("Composition due to association with an element with a \"position: sticky\" style."), 62 "overflowScrollingTouch": WebInspector.UIString("Composition due to association with an element with a \"overflow-scrolling: touch\" style."), 63 "blending": WebInspector.UIString("Composition due to association with an element that has blend mode other than \"normal\"."), 64 "assumedOverlap": WebInspector.UIString("Composition due to association with an element that may overlap other composited elements."), 65 "overlap": WebInspector.UIString("Composition due to association with an element overlapping other composited elements."), 66 "negativeZIndexChildren": WebInspector.UIString("Composition due to association with an element with descendants that have a negative z-index."), 67 "transformWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with composited descendants."), 68 "opacityWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with opacity applied and composited descendants."), 69 "maskWithCompositedDescendants": WebInspector.UIString("Composition due to association with a masked element and composited descendants."), 70 "reflectionWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with a reflection and composited descendants."), 71 "filterWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with CSS filters applied and composited descendants."), 72 "blendingWithCompositedDescendants": WebInspector.UIString("Composition due to association with an element with CSS blending applied and composited descendants."), 73 "clipsCompositingDescendants": WebInspector.UIString("Composition due to association with an element clipping compositing descendants."), 74 "perspective": WebInspector.UIString("Composition due to association with an element with perspective applied."), 75 "preserve3D": WebInspector.UIString("Composition due to association with an element with a \"transform-style: preserve-3d\" style."), 76 "root": WebInspector.UIString("Root layer."), 77 "layerForClip": WebInspector.UIString("Layer for clip."), 78 "layerForScrollbar": WebInspector.UIString("Layer for scrollbar."), 79 "layerForScrollingContainer": WebInspector.UIString("Layer for scrolling container."), 80 "layerForForeground": WebInspector.UIString("Layer for foreground."), 81 "layerForBackground": WebInspector.UIString("Layer for background."), 82 "layerForMask": WebInspector.UIString("Layer for mask."), 83 "layerForVideoOverlay": WebInspector.UIString("Layer for video overlay.") 84}; 85 86WebInspector.LayerDetailsView.prototype = { 87 /** 88 * @param {?WebInspector.Layer} layer 89 */ 90 setLayer: function(layer) 91 { 92 this._layer = layer; 93 if (this.isShowing()) 94 this._update(); 95 }, 96 97 wasShown: function() 98 { 99 WebInspector.View.prototype.wasShown.call(this); 100 this._update(); 101 }, 102 103 _onLayerTreeUpdated: function() 104 { 105 if (this.isShowing()) 106 this._update(); 107 }, 108 109 /** 110 * @param {!WebInspector.Event} event 111 */ 112 _onLayerPainted: function(event) 113 { 114 var layer = /** @type {!WebInspector.Layer} */ (event.data); 115 if (this._layer === layer) 116 this._paintCountCell.textContent = layer.paintCount(); 117 }, 118 119 _update: function() 120 { 121 if (!this._layer) { 122 this._tableElement.remove(); 123 this._emptyView.show(this.element); 124 return; 125 } 126 this._emptyView.detach(); 127 this.element.appendChild(this._tableElement); 128 this._positionCell.textContent = WebInspector.UIString("%d,%d", this._layer.offsetX(), this._layer.offsetY()); 129 this._sizeCell.textContent = WebInspector.UIString("%d × %d", this._layer.width(), this._layer.height()); 130 this._paintCountCell.textContent = this._layer.paintCount(); 131 const bytesPerPixel = 4; 132 this._memoryEstimateCell.textContent = Number.bytesToString(this._layer.invisible() ? 0 : this._layer.width() * this._layer.height() * bytesPerPixel); 133 this._layer.requestCompositingReasons(this._updateCompositingReasons.bind(this)); 134 }, 135 136 _createTable: function() 137 { 138 this._tableElement = this.element.createChild("table"); 139 this._tbodyElement = this._tableElement.createChild("tbody"); 140 this._positionCell = this._createRow(WebInspector.UIString("Position in parent:")); 141 this._sizeCell = this._createRow(WebInspector.UIString("Size:")); 142 this._compositingReasonsCell = this._createRow(WebInspector.UIString("Compositing Reasons:")); 143 this._memoryEstimateCell = this._createRow(WebInspector.UIString("Memory estimate:")); 144 this._paintCountCell = this._createRow(WebInspector.UIString("Paint count:")); 145 }, 146 147 /** 148 * @param {string} title 149 */ 150 _createRow: function(title) 151 { 152 var tr = this._tbodyElement.createChild("tr"); 153 var titleCell = tr.createChild("td"); 154 titleCell.textContent = title; 155 return tr.createChild("td"); 156 }, 157 158 /** 159 * @param {!Array.<string>} compositingReasons 160 */ 161 _updateCompositingReasons: function(compositingReasons) 162 { 163 if (!compositingReasons || !compositingReasons.length) { 164 this._compositingReasonsCell.textContent = "n/a"; 165 return; 166 } 167 var fragment = document.createDocumentFragment(); 168 for (var i = 0; i < compositingReasons.length; ++i) { 169 if (i) 170 fragment.appendChild(document.createTextNode(",")); 171 var span = document.createElement("span"); 172 span.title = WebInspector.LayerDetailsView.CompositingReasonDetail[compositingReasons[i]] || ""; 173 span.textContent = compositingReasons[i]; 174 fragment.appendChild(span); 175 } 176 this._compositingReasonsCell.removeChildren(); 177 this._compositingReasonsCell.appendChild(fragment); 178 }, 179 180 __proto__: WebInspector.View.prototype 181} 182