Title: [222342] trunk/Source/WebInspectorUI
Revision
222342
Author
[email protected]
Date
2017-09-21 13:18:01 -0700 (Thu, 21 Sep 2017)

Log Message

Web Inspector: Add details sidebar to Layers tab.
https://bugs.webkit.org/show_bug.cgi?id=177115

Patch by Ross Kirsling <[email protected]> on 2017-09-21
Reviewed by Devin Rousso.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Main.html:
* UserInterface/Views/LayerDetailsSidebarPanel.css: Added.
* UserInterface/Views/LayerDetailsSidebarPanel.js: Added.
New files and strings for sidebar.

* UserInterface/Base/Utilities.js:
Add global identifier for "×" character.

* UserInterface/Models/Layer.js: Added.
Add a model class for layers so that we can instanceof-check them.

* UserInterface/Controllers/LayerTreeManager.js:
(WI.LayerTreeManager.prototype.layersForNode):
Utilize model class WI.Layer.

* UserInterface/Views/Layers3DContentView.js:
(WI.Layers3DContentView):
(WI.Layers3DContentView.prototype.get supplementalRepresentedObjects):
(WI.Layers3DContentView.prototype.layout):
(WI.Layers3DContentView.prototype._addLayer):
Pass layer data to sidebar and utilize model class WI.Layer.

* UserInterface/Views/LayersTabContentView.js:
(WI.LayersTabContentView):
Attach details sidebar.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (222341 => 222342)


--- trunk/Source/WebInspectorUI/ChangeLog	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/ChangeLog	2017-09-21 20:18:01 UTC (rev 222342)
@@ -1,3 +1,37 @@
+2017-09-21  Ross Kirsling  <[email protected]>
+
+        Web Inspector: Add details sidebar to Layers tab.
+        https://bugs.webkit.org/show_bug.cgi?id=177115
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Main.html:
+        * UserInterface/Views/LayerDetailsSidebarPanel.css: Added.
+        * UserInterface/Views/LayerDetailsSidebarPanel.js: Added.
+        New files and strings for sidebar.
+
+        * UserInterface/Base/Utilities.js:
+        Add global identifier for "×" character.
+        
+        * UserInterface/Models/Layer.js: Added.
+        Add a model class for layers so that we can instanceof-check them.
+
+        * UserInterface/Controllers/LayerTreeManager.js:
+        (WI.LayerTreeManager.prototype.layersForNode):
+        Utilize model class WI.Layer.
+
+        * UserInterface/Views/Layers3DContentView.js:
+        (WI.Layers3DContentView):
+        (WI.Layers3DContentView.prototype.get supplementalRepresentedObjects):
+        (WI.Layers3DContentView.prototype.layout):
+        (WI.Layers3DContentView.prototype._addLayer):
+        Pass layer data to sidebar and utilize model class WI.Layer.
+
+        * UserInterface/Views/LayersTabContentView.js:
+        (WI.LayersTabContentView):
+        Attach details sidebar.
+
 2017-09-21  Brian Burg  <[email protected]>
 
         Web Inspector: keyboard shortcut for "Reload page from origin" doesn't match Safari, and doesn't work

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (222341 => 222342)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -81,6 +81,7 @@
 localizedStrings["All"] = "All";
 localizedStrings["All Changes"] = "All Changes";
 localizedStrings["All Exceptions"] = "All Exceptions";
+localizedStrings["All Layers"] = "All Layers";
 localizedStrings["All Requests"] = "All Requests";
 localizedStrings["All Resources"] = "All Resources";
 localizedStrings["All Storage"] = "All Storage";
@@ -208,6 +209,7 @@
 localizedStrings["Compare snapshots"] = "Compare snapshots";
 localizedStrings["Comparison of total memory size at the end of the selected time range to the maximum memory size in this recording"] = "Comparison of total memory size at the end of the selected time range to the maximum memory size in this recording";
 localizedStrings["Composite"] = "Composite";
+localizedStrings["Composited"] = "Composited";
 localizedStrings["Compressed"] = "Compressed";
 localizedStrings["Compression"] = "Compression";
 localizedStrings["Condition"] = "Condition";
@@ -941,6 +943,7 @@
 localizedStrings["Vertex Shader"] = "Vertex Shader";
 localizedStrings["Vertical"] = "Vertical";
 localizedStrings["View variable value"] = "View variable value";
+localizedStrings["Visible"] = "Visible";
 localizedStrings["Visibility"] = "Visibility";
 localizedStrings["Warning: "] = "Warning: ";
 localizedStrings["Warnings"] = "Warnings";

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js (222341 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Utilities.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -28,6 +28,7 @@
 var figureDash = "\u2012";
 var ellipsis = "\u2026";
 var zeroWidthSpace = "\u200b";
+var multiplicationSign = "\u00d7";
 
 Object.defineProperty(Object, "shallowCopy",
 {

Modified: trunk/Source/WebInspectorUI/UserInterface/Controllers/LayerTreeManager.js (222341 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Controllers/LayerTreeManager.js	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/UserInterface/Controllers/LayerTreeManager.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -128,6 +128,8 @@
                 return;
             }
 
+            layers = layers.map(WI.Layer.fromPayload);
+
             var firstLayer = layers[0];
             var layerForNode = firstLayer.nodeId === node.id && !firstLayer.isGeneratedContent ? layers.shift() : null;
             callback(layerForNode, layers);

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (222341 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-09-21 20:18:01 UTC (rev 222342)
@@ -110,6 +110,7 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
+    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -370,6 +371,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""
@@ -627,6 +629,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""

Added: trunk/Source/WebInspectorUI/UserInterface/Models/Layer.js (0 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Models/Layer.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Models/Layer.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.Layer = class Layer {
+    constructor(layerId, nodeId, bounds, paintCount, memory, compositedBounds, isInShadowTree, isReflection, isGeneratedContent, isAnonymous, pseudoElementId, pseudoElement)
+    {
+        console.assert(typeof bounds === "object");
+
+        this._layerId = layerId;
+        this._nodeId = nodeId;
+        this._bounds = bounds;
+        this._paintCount = paintCount;
+        this._memory = memory;
+        this._compositedBounds = compositedBounds;
+        this._isInShadowTree = isInShadowTree;
+        this._isReflection = isReflection;
+        this._isGeneratedContent = isGeneratedContent;
+        this._isAnonymous = isAnonymous;
+        this._pseudoElementId = pseudoElementId;
+        this._pseudoElement = pseudoElement;
+
+        // FIXME: This should probably be moved to the backend.
+        this._compositedBounds.x = this._bounds.x;
+        this._compositedBounds.y = this._bounds.y;
+    }
+
+    // Static
+
+    static fromPayload(payload)
+    {
+        return new WI.Layer(
+            payload.layerId,
+            payload.nodeId,
+            payload.bounds,
+            payload.paintCount,
+            payload.memory,
+            payload.compositedBounds,
+            payload.isInShadowTree,
+            payload.isReflection,
+            payload.isGeneratedContent,
+            payload.isAnonymous,
+            payload.pseudoElementId,
+            payload.pseudoElement
+        );
+    }
+
+    // Public
+
+    get layerId() { return this._layerId; }
+    get nodeId() { return this._nodeId; }
+    get bounds() { return this._bounds; }
+    get paintCount() { return this._paintCount; }
+    get memory() { return this._memory; }
+    get compositedBounds() { return this._compositedBounds; }
+    get isInShadowTree() { return this._isInShadowTree; }
+    get isReflection() { return this._isReflection; }
+    get isGeneratedContent() { return this._isGeneratedContent; }
+    get isAnonymous() { return this._isAnonymous; }
+    get pseudoElementId() { return this._pseudoElementId; }
+    get pseudoElement() { return this._pseudoElement; }
+};

Added: trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.css (0 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.css	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.css	2017-09-21 20:18:01 UTC (rev 222342)
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.sidebar > .panel.details.layer > .content {
+    bottom: var(--console-prompt-min-height);
+}
+
+.panel.details.layer .data-grid {
+    height: 100%;
+    border: none;
+}
+
+.panel.details.layer .name-column .icon {
+    content: url(../Images/DOMElement.svg);
+}
+
+.panel.details.layer tr.reflection .name-column .icon {
+    content: url(../Images/Reflection.svg);
+}
+
+.panel.details.layer tr.pseudo-element .name-column .icon {
+    content: url(../Images/PseudoElement.svg);
+}
+
+.panel.details.layer .name-column :matches(.pseudo-element, .reflection) {
+    color: var(--text-color-gray-medium);
+}
+
+.panel.details.layer tr.selected .name-column :matches(.pseudo-element, .reflection) {
+    color: var(--selected-secondary-text-color);
+}
+
+.panel.details.layer .bottom-bar {
+    position: absolute;
+    display: flex;
+    bottom: 0;
+    height: var(--console-prompt-min-height);
+    width: 100%;
+    border-top: 1px solid var(--border-color);
+    background-color: white;
+}
+
+.panel.details.layer .bottom-bar > div {
+    display: flex;
+    flex: 1;
+    padding: 4px 6px;
+    line-height: 20px;
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+
+.panel.details.layer .layers-memory-label {
+    justify-content: flex-end;
+}
+
+.layer-popover {
+    max-width: 300px;
+    padding: 5px;
+}
+
+.layer-popover > div {
+    font-size: 1.1em;
+    font-weight: bold;
+}
+
+.layer-popover table {
+    margin: 10px 0;
+}
+.layer-popover td {
+    padding: 0 5px;
+    line-height: 1.3em;
+}
+
+.layer-popover ul {
+    margin: 10px 0 0;
+    padding: 0;
+
+    -webkit-margin-start: 1em;
+    -webkit-padding-start: 1em;
+}
+
+.layer-popover li {
+    line-height: 1.3em;
+}

Added: trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.js (0 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayerDetailsSidebarPanel.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -0,0 +1,363 @@
+/*
+ * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Sony Interactive Entertainment Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WI.LayerDetailsSidebarPanel = class LayerDetailsSidebarPanel extends WI.DetailsSidebarPanel
+{
+    constructor()
+    {
+        super("layer", WI.UIString("All Layers"));
+
+        this.element.classList.add("layer");
+
+        this._layers = [];
+        this._dataGridNodesByLayerId = new Map;
+
+        this._dataGrid = null;
+        this._bottomBar = null;
+        this._layersCountLabel = null;
+        this._layersMemoryLabel = null;
+        this._popover = null;
+    }
+
+    // Public
+
+    inspect(objects)
+    {
+        if (!(objects instanceof Array))
+            objects = [objects];
+
+        let layers = objects.filter((object) => object instanceof WI.Layer);
+        this._updateDisplayWithLayers(layers);
+
+        return !!layers.length;
+    }
+
+    // Private
+
+    _buildDataGrid()
+    {
+        const columns = {
+            name: {
+                title: WI.UIString("Node"),
+                sortable: false,
+            },
+            paintCount: {
+                title: WI.UIString("Paints"),
+                sortable: true,
+                aligned: "right",
+                width: "50px",
+            },
+            memory: {
+                title: WI.UIString("Memory"),
+                sortable: true,
+                aligned: "right",
+                width: "70px",
+            }
+        };
+
+        this._dataGrid = new WI.DataGrid(columns);
+        this._dataGrid.addEventListener(WI.DataGrid.Event.SortChanged, this._sortDataGrid, this);
+        this._dataGrid.addEventListener(WI.DataGrid.Event.SelectedNodeChanged, this._dataGridSelectedNodeChanged, this);
+
+        this._dataGrid.sortColumnIdentifier = "memory";
+        this._dataGrid.sortOrder = WI.DataGrid.SortOrder.Descending;
+        this._dataGrid.createSettings("layer-details-sidebar-panel");
+
+        this._dataGrid.element.addEventListener("focus", this._dataGridFocused.bind(this), false);
+        this._dataGrid.element.addEventListener("blur", this._dataGridBlurred.bind(this), false);
+        this._dataGrid.element.addEventListener("click", this._dataGridClicked.bind(this), false);
+
+        this.contentView.addSubview(this._dataGrid);
+    }
+
+    _buildBottomBar()
+    {
+        this._bottomBar = this.element.appendChild(document.createElement("div"));
+        this._bottomBar.className = "bottom-bar";
+
+        this._layersCountLabel = this._bottomBar.appendChild(document.createElement("div"));
+        this._layersCountLabel.className = "layers-count-label";
+
+        this._layersMemoryLabel = this._bottomBar.appendChild(document.createElement("div"));
+        this._layersMemoryLabel.className = "layers-memory-label";
+    }
+
+    _sortDataGrid()
+    {
+        let sortColumnIdentifier = this._dataGrid.sortColumnIdentifier;
+
+        function comparator(a, b) {
+            let itemA = a.layer[sortColumnIdentifier] || 0;
+            let itemB = b.layer[sortColumnIdentifier] || 0;
+            return itemA - itemB;
+        }
+
+        this._dataGrid.sortNodes(comparator);
+        this._updatePopoverForSelectedNode();
+    }
+
+    _dataGridSelectedNodeChanged()
+    {
+        if (this._dataGrid.selectedNode) {
+            this._highlightSelectedNode();
+            this._showPopoverForSelectedNode();
+        } else {
+            WI.domTreeManager.hideDOMNodeHighlight();
+            this._hidePopover();
+        }
+    }
+
+    _dataGridFocused(event)
+    {
+        this._highlightSelectedNode();
+        this._showPopoverForSelectedNode();
+    }
+
+    _dataGridBlurred(event)
+    {
+        WI.domTreeManager.hideDOMNodeHighlight();
+        this._hidePopover();
+    }
+
+    _dataGridClicked(event)
+    {
+        if (this._dataGrid.selectedNode && event.target.parentNode.classList.contains("filler"))
+            this._dataGrid.selectedNode.deselect();
+    }
+
+    _highlightSelectedNode()
+    {
+        if (!this._dataGrid.selectedNode)
+            return;
+
+        let layer = this._dataGrid.selectedNode.layer;
+        if (layer.isGeneratedContent || layer.isReflection || layer.isAnonymous) {
+            const usePageCoordinates = true;
+            WI.domTreeManager.highlightRect(layer.bounds, usePageCoordinates);
+        } else
+            WI.domTreeManager.highlightDOMNode(layer.nodeId);
+    }
+
+    _updateDisplayWithLayers(newLayers)
+    {
+        let previousLayers = this._layers;
+        this._layers = newLayers;
+
+        this._updateDataGrid(previousLayers);
+        this._updateBottomBar();
+    }
+
+    _updateDataGrid(previousLayers)
+    {
+        if (!this._dataGrid)
+            this._buildDataGrid();
+
+        let mutations = WI.layerTreeManager.layerTreeMutations(previousLayers, this._layers);
+
+        mutations.removals.forEach((layer) => {
+            let node = this._dataGridNodesByLayerId.get(layer.layerId);
+            if (!node)
+                return;
+
+            this._dataGrid.removeChild(node);
+            this._dataGridNodesByLayerId.delete(layer.layerId);
+        });
+
+        mutations.additions.forEach((layer) => {
+            let node = this._dataGridNodeForLayer(layer);
+            this._dataGrid.appendChild(node);
+        });
+
+        mutations.preserved.forEach((layer) => {
+            let node = this._dataGridNodesByLayerId.get(layer.layerId);
+            if (!node)
+                return;
+
+            node.layer = layer;
+        });
+
+        this._sortDataGrid();
+    }
+
+    _dataGridNodeForLayer(layer)
+    {
+        let node = new WI.LayerTreeDataGridNode(layer);
+        this._dataGridNodesByLayerId.set(layer.layerId, node);
+
+        return node;
+    }
+
+    _updateBottomBar()
+    {
+        if (!this._bottomBar)
+            this._buildBottomBar();
+
+        this._layersCountLabel.textContent = WI.UIString("Layer Count: %d").format(this._layers.length);
+
+        let totalMemory = this._layers.reduce((total, layer) => total + (layer.memory || 0), 0);
+        this._layersMemoryLabel.textContent = WI.UIString("Memory: %s").format(Number.bytesToString(totalMemory));
+    }
+
+    _showPopoverForSelectedNode()
+    {
+        let dataGridNode = this._dataGrid.selectedNode;
+        if (!dataGridNode)
+            return;
+
+        this._contentForPopover(dataGridNode.layer, (content) => {
+            if (dataGridNode === this._dataGrid.selectedNode)
+                this._updatePopoverForSelectedNode(content);
+        });
+    }
+
+    _updatePopoverForSelectedNode(content)
+    {
+        if (!this._dataGrid.selectedNode)
+            return;
+
+        if (!this._popover) {
+            this._popover = new WI.Popover;
+            this._popover.windowResizeHandler = () => { this._updatePopoverForSelectedNode(); };
+        }
+
+        let targetFrame = WI.Rect.rectFromClientRect(this._dataGrid.selectedNode.element.getBoundingClientRect());
+
+        if (content)
+            this._popover.content = content;
+
+        this._popover.present(targetFrame.pad(2), [WI.RectEdge.MIN_X]);
+    }
+
+    _hidePopover()
+    {
+        if (this._popover)
+            this._popover.dismiss();
+    }
+
+    _contentForPopover(layer, callback)
+    {
+        let content = document.createElement("div");
+        content.className = "layer-popover";
+
+        let dimensionsTitle = content.appendChild(document.createElement("div"));
+        dimensionsTitle.textContent = WI.UIString("Dimensions");
+
+        let dimensionsTable = content.appendChild(document.createElement("table"));
+
+        let compositedRow = dimensionsTable.appendChild(document.createElement("tr"));
+        let compositedLabel = compositedRow.appendChild(document.createElement("td"));
+        let compositedValue = compositedRow.appendChild(document.createElement("td"));
+        compositedLabel.textContent = WI.UIString("Composited");
+        compositedValue.textContent = `${layer.compositedBounds.width}px ${multiplicationSign} ${layer.compositedBounds.height}px`;
+
+        let visibleRow = dimensionsTable.appendChild(document.createElement("tr"));
+        let visibleLabel = visibleRow.appendChild(document.createElement("td"));
+        let visibleValue = visibleRow.appendChild(document.createElement("td"));
+        visibleLabel.textContent = WI.UIString("Visible");
+        visibleValue.textContent = `${layer.bounds.width}px ${multiplicationSign} ${layer.bounds.height}px`;
+
+        let reasonsTitle = content.appendChild(document.createElement("div"));
+        reasonsTitle.textContent = WI.UIString("Reasons for compositing:");
+
+        let list = content.appendChild(document.createElement("ul"));
+
+        WI.layerTreeManager.reasonsForCompositingLayer(layer, (compositingReasons) => {
+            if (isEmptyObject(compositingReasons)) {
+                callback(content);
+                return;
+            }
+
+            this._populateListOfCompositingReasons(list, compositingReasons);
+
+            callback(content);
+        });
+
+        return content;
+    }
+
+    _populateListOfCompositingReasons(list, compositingReasons)
+    {
+        function addReason(reason) {
+            let item = list.appendChild(document.createElement("li"));
+            item.textContent = reason;
+        }
+
+        if (compositingReasons.transform3D)
+            addReason(WI.UIString("Element has a 3D transform"));
+        if (compositingReasons.video)
+            addReason(WI.UIString("Element is <video>"));
+        if (compositingReasons.canvas)
+            addReason(WI.UIString("Element is <canvas>"));
+        if (compositingReasons.plugin)
+            addReason(WI.UIString("Element is a plug-in"));
+        if (compositingReasons.iFrame)
+            addReason(WI.UIString("Element is <iframe>"));
+        if (compositingReasons.backfaceVisibilityHidden)
+            addReason(WI.UIString("Element has “backface-visibility: hidden” style"));
+        if (compositingReasons.clipsCompositingDescendants)
+            addReason(WI.UIString("Element clips compositing descendants"));
+        if (compositingReasons.animation)
+            addReason(WI.UIString("Element is animated"));
+        if (compositingReasons.filters)
+            addReason(WI.UIString("Element has CSS filters applied"));
+        if (compositingReasons.positionFixed)
+            addReason(WI.UIString("Element has “position: fixed” style"));
+        if (compositingReasons.positionSticky)
+            addReason(WI.UIString("Element has “position: sticky” style"));
+        if (compositingReasons.overflowScrollingTouch)
+            addReason(WI.UIString("Element has “-webkit-overflow-scrolling: touch” style"));
+        if (compositingReasons.stacking)
+            addReason(WI.UIString("Element may overlap another compositing element"));
+        if (compositingReasons.overlap)
+            addReason(WI.UIString("Element overlaps other compositing element"));
+        if (compositingReasons.negativeZIndexChildren)
+            addReason(WI.UIString("Element has children with a negative z-index"));
+        if (compositingReasons.transformWithCompositedDescendants)
+            addReason(WI.UIString("Element has a 2D transform and composited descendants"));
+        if (compositingReasons.opacityWithCompositedDescendants)
+            addReason(WI.UIString("Element has opacity applied and composited descendants"));
+        if (compositingReasons.maskWithCompositedDescendants)
+            addReason(WI.UIString("Element is masked and composited descendants"));
+        if (compositingReasons.reflectionWithCompositedDescendants)
+            addReason(WI.UIString("Element has a reflection and composited descendants"));
+        if (compositingReasons.filterWithCompositedDescendants)
+            addReason(WI.UIString("Element has CSS filters applied and composited descendants"));
+        if (compositingReasons.blendingWithCompositedDescendants)
+            addReason(WI.UIString("Element has CSS blending applied and composited descendants"));
+        if (compositingReasons.isolatesCompositedBlendingDescendants)
+            addReason(WI.UIString("Element is a stacking context and has composited descendants with CSS blending applied"));
+        if (compositingReasons.perspective)
+            addReason(WI.UIString("Element has perspective applied"));
+        if (compositingReasons.preserve3D)
+            addReason(WI.UIString("Element has “transform-style: preserve-3d” style"));
+        if (compositingReasons.willChange)
+            addReason(WI.UIString("Element has “will-change” style with includes opacity, transform, transform-style, perspective, filter or backdrop-filter"));
+        if (compositingReasons.root)
+            addReason(WI.UIString("Element is the root element"));
+        if (compositingReasons.blending)
+            addReason(WI.UIString("Element has “blend-mode” style"));
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Layers3DContentView.js (222341 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Layers3DContentView.js	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Layers3DContentView.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -33,6 +33,7 @@
 
         WI.layerTreeManager.addEventListener(WI.LayerTreeManager.Event.LayerTreeDidChange, this._layerTreeDidChange, this);
 
+        this._layers = [];
         this._layersChangedWhileHidden = false;
         this._renderer = null;
         this._camera = null;
@@ -45,6 +46,11 @@
 
     // Public
 
+    get supplementalRepresentedObjects()
+    {
+        return this._layers;
+    }
+
     shown()
     {
         super.shown();
@@ -117,6 +123,9 @@
                 this._clearLayers();
                 for (let i = 0; i < childLayers.length; i++)
                     this._addLayer(childLayers[i], i);
+
+                this._layers = childLayers;
+                this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
             });
         });
     }
@@ -165,15 +174,8 @@
 
     _addLayer(layer, index)
     {
-        let compositedBounds = {
-            x: layer.bounds.x,
-            y: layer.bounds.y,
-            width: layer.compositedBounds.width,
-            height: layer.compositedBounds.height,
-        };
-
         this._boundsGroup.add(this._createLayerMesh(layer.bounds, index));
-        this._compositedBoundsGroup.add(this._createLayerMesh(compositedBounds, index, true));
+        this._compositedBoundsGroup.add(this._createLayerMesh(layer.compositedBounds, index, true));
     }
 
     _createLayerMesh(rect, index, isOutline = false)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayersTabContentView.js (222341 => 222342)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayersTabContentView.js	2017-09-21 20:16:52 UTC (rev 222341)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayersTabContentView.js	2017-09-21 20:18:01 UTC (rev 222342)
@@ -31,7 +31,7 @@
         let tabBarItem = new WI.GeneralTabBarItem(image, title);
 
         const navigationSidebarPanelConstructor = null;
-        const detailsSidebarPanelConstructors = null;
+        const detailsSidebarPanelConstructors = [WI.LayerDetailsSidebarPanel];
         const disableBackForward = true;
         super("layers", "layers", tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to