1/*
2 * Copyright (C) 2013 Apple 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
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26WebInspector.ComputedStyleDetailsPanel = function()
27{
28    WebInspector.StyleDetailsPanel.call(this, WebInspector.ComputedStyleDetailsPanel.StyleClassName, "computed", WebInspector.UIString("Computed"));
29
30    this._computedStyleShowAllSetting = new WebInspector.Setting("computed-style-show-all", false);
31
32    var computedStyleShowAllLabel = document.createElement("label");
33    computedStyleShowAllLabel.textContent = WebInspector.UIString("Show All");
34
35    this._computedStyleShowAllCheckbox = document.createElement("input");
36    this._computedStyleShowAllCheckbox.type = "checkbox";
37    this._computedStyleShowAllCheckbox.checked = this._computedStyleShowAllSetting.value;
38    this._computedStyleShowAllCheckbox.addEventListener("change", this._computedStyleShowAllCheckboxValueChanged.bind(this));
39    computedStyleShowAllLabel.appendChild(this._computedStyleShowAllCheckbox);
40
41    this._propertiesTextEditor = new WebInspector.CSSStyleDeclarationTextEditor(this);
42    this._propertiesTextEditor.showsImplicitProperties = this._computedStyleShowAllSetting.value;
43    this._propertiesTextEditor.alwaysShowPropertyNames = ["display", "width", "height"];
44    this._propertiesTextEditor.sortProperties = true;
45
46    var propertiesRow = new WebInspector.DetailsSectionRow;
47    var propertiesGroup = new WebInspector.DetailsSectionGroup([propertiesRow]);
48    var propertiesSection = new WebInspector.DetailsSection("computed-style-properties", WebInspector.UIString("Properties"), [propertiesGroup], computedStyleShowAllLabel);
49
50    propertiesRow.element.appendChild(this._propertiesTextEditor.element);
51
52    // Region flow name is used to display the "flow-from" property of the Region Containers.
53    this._regionFlowFragment = document.createElement("span");
54    this._regionFlowFragment.appendChild(document.createElement("img")).className = "icon";
55    this._regionFlowNameLabelValue = this._regionFlowFragment.appendChild(document.createElement("span"));
56
57    var goToRegionFlowButton = this._regionFlowFragment.appendChild(WebInspector.createGoToArrowButton());
58    goToRegionFlowButton.addEventListener("click", this._goToRegionFlowArrowWasClicked.bind(this));
59
60    this._regionFlowNameRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Region Flow"));
61    this._regionFlowNameRow.element.classList.add("content-flow-link");
62
63    // Content flow name is used to display the "flow-into" property of the Content nodes.
64    this._contentFlowFragment = document.createElement("span");
65    this._contentFlowFragment.appendChild(document.createElement("img")).className = "icon";
66    this._contentFlowNameLabelValue = this._contentFlowFragment.appendChild(document.createElement("span"));
67
68    var goToContentFlowButton = this._contentFlowFragment.appendChild(WebInspector.createGoToArrowButton());
69    goToContentFlowButton.addEventListener("click", this._goToContentFlowArrowWasClicked.bind(this));
70
71    this._contentFlowNameRow = new WebInspector.DetailsSectionSimpleRow(WebInspector.UIString("Content Flow"));
72    this._contentFlowNameRow.element.classList.add("content-flow-link");
73
74    var flowNamesGroup = new WebInspector.DetailsSectionGroup([this._regionFlowNameRow, this._contentFlowNameRow]);
75    this._flowNamesSection = new WebInspector.DetailsSection("content-flow", WebInspector.UIString("Flows"), [flowNamesGroup]);
76
77    this._containerRegionsDataGrid = new WebInspector.DOMTreeDataGrid;
78    this._containerRegionsDataGrid.element.classList.add("no-header");
79
80    var containerRegionsRow = new WebInspector.DetailsSectionDataGridRow(this._containerRegionsDataGrid);
81    var containerRegionsGroup = new WebInspector.DetailsSectionGroup([containerRegionsRow]);
82    this._containerRegionsFlowSection = new WebInspector.DetailsSection("container-regions", WebInspector.UIString("Container Regions"), [containerRegionsGroup]);
83
84    this.element.appendChild(propertiesSection.element);
85    this.element.appendChild(this._flowNamesSection.element);
86    this.element.appendChild(this._containerRegionsFlowSection.element);
87
88    this._resetFlowDetails();
89};
90
91WebInspector.ComputedStyleDetailsPanel.StyleClassName = "computed";
92
93WebInspector.ComputedStyleDetailsPanel.prototype = {
94    constructor: WebInspector.ComputedStyleDetailsPanel,
95
96    // Public
97
98    get regionFlow()
99    {
100        return this._regionFlow;
101    },
102
103    set regionFlow(regionFlow)
104    {
105        this._regionFlow = regionFlow;
106        this._regionFlowNameLabelValue.textContent = regionFlow ? regionFlow.name : "";
107        this._regionFlowNameRow.value = regionFlow ? this._regionFlowFragment : null;
108        this._updateFlowNamesSectionVisibility();
109    },
110
111    get contentFlow()
112    {
113        return this._contentFlow;
114    },
115
116    set contentFlow(contentFlow)
117    {
118        this._contentFlow = contentFlow;
119        this._contentFlowNameLabelValue.textContent = contentFlow ? contentFlow.name : "";
120        this._contentFlowNameRow.value = contentFlow ? this._contentFlowFragment : null;
121        this._updateFlowNamesSectionVisibility();
122    },
123
124    get containerRegions()
125    {
126        return this._containerRegions;
127    },
128
129    set containerRegions(regions)
130    {
131        this._containerRegions = regions;
132
133        if (!regions || !regions.length) {
134            this._containerRegionsFlowSection.element.classList.add("hidden");
135            return;
136        }
137
138        this._containerRegionsDataGrid.removeChildren();
139        for (var regionNode of regions)
140            this._containerRegionsDataGrid.appendChild(new WebInspector.DOMTreeDataGridNode(regionNode));
141
142        this._containerRegionsFlowSection.element.classList.remove("hidden");
143    },
144
145    refresh: function()
146    {
147        this._propertiesTextEditor.style = this.nodeStyles.computedStyle;
148        this._refreshFlowDetails(this.nodeStyles.node);
149    },
150
151    // Protected
152
153    shown: function()
154    {
155        WebInspector.StyleDetailsPanel.prototype.shown.call(this);
156
157        this._propertiesTextEditor.updateLayout();
158    },
159
160    widthDidChange: function()
161    {
162        this._propertiesTextEditor.updateLayout();
163    },
164
165    // Private
166
167    _computedStyleShowAllCheckboxValueChanged: function(event)
168    {
169        var checked = this._computedStyleShowAllCheckbox.checked;
170        this._computedStyleShowAllSetting.value = checked;
171        this._propertiesTextEditor.showsImplicitProperties = checked;
172    },
173
174    _updateFlowNamesSectionVisibility: function()
175    {
176        this._flowNamesSection.element.classList.toggle("hidden", !this._contentFlow && !this._regionFlow);
177    },
178
179    _resetFlowDetails : function()
180    {
181        this.regionFlow = null;
182        this.contentFlow = null;
183        this.containerRegions = null;
184    },
185
186    _refreshFlowDetails: function(domNode)
187    {
188        this._resetFlowDetails();
189        if (!domNode)
190            return;
191
192        function contentFlowInfoReady(error, flowData)
193        {
194            // Element is not part of any flow.
195            if (error || !flowData) {
196                this._resetFlowDetails();
197                return;
198            }
199
200            this.regionFlow = flowData.regionFlow;
201            this.contentFlow = flowData.contentFlow;
202            this.containerRegions = flowData.regions;
203        }
204
205        WebInspector.domTreeManager.getNodeContentFlowInfo(domNode, contentFlowInfoReady.bind(this));
206    },
207
208    _goToRegionFlowArrowWasClicked: function()
209    {
210        WebInspector.resourceSidebarPanel.showContentFlowDOMTree(this._regionFlow);
211    },
212
213    _goToContentFlowArrowWasClicked: function()
214    {
215        WebInspector.resourceSidebarPanel.showContentFlowDOMTree(this._contentFlow, this.nodeStyles.node, true);
216    }
217};
218
219WebInspector.ComputedStyleDetailsPanel.prototype.__proto__ = WebInspector.StyleDetailsPanel.prototype;
220