Not reviewed. Added svn:eol-style native to unbreak some build bots.
[WebKit-https.git] / Source / WebCore / inspector / front-end / CSSNamedFlowCollectionsView.js
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.SplitView}
33  */
34 WebInspector.CSSNamedFlowCollectionsView = function()
35 {
36     WebInspector.SplitView.call(this, WebInspector.SplitView.SidebarPosition.Left);
37     this.registerRequiredCSS("cssNamedFlows.css");
38
39     this._namedFlows = {};
40     this._contentNodes = {};
41     this._regionNodes = {};
42
43     this.element.addStyleClass("css-named-flow-collections-view");
44     this.element.addStyleClass("fill");
45
46     this._statusElement = document.createElement("span");
47     this._statusElement.textContent = WebInspector.UIString("CSS Named Flows");
48
49     var sidebarHeader = this._leftElement.createChild("div", "tabbed-pane-header selected sidebar-header")
50     var tab = sidebarHeader.createChild("div", "tabbed-pane-header-tab");
51     tab.createChild("span", "tabbed-pane-header-tab-title").textContent = WebInspector.UIString("CSS Named Flows");
52
53     this._sidebarContentElement = this._leftElement.createChild("div", "sidebar-content outline-disclosure");
54     this._flowListElement = this._sidebarContentElement.createChild("ol");
55     this._flowTree = new TreeOutline(this._flowListElement);
56
57     this._emptyElement = document.createElement("div");
58     this._emptyElement.addStyleClass("info");
59     this._emptyElement.textContent = WebInspector.UIString("No CSS Named Flows");
60
61     this._tabbedPane = new WebInspector.TabbedPane();
62     this._tabbedPane.closeableTabs = true;
63     this._tabbedPane.show(this._rightElement);
64 }
65
66 WebInspector.CSSNamedFlowCollectionsView.prototype = {
67     showInDrawer: function()
68     {
69         WebInspector.showViewInDrawer(this._statusElement, this);
70     },
71
72     reset: function()
73     {
74         if (!this._document)
75             return;
76
77         WebInspector.cssModel.getNamedFlowCollectionAsync(this._document.id, this._resetNamedFlows.bind(this));
78     },
79
80     /**
81      * @param {WebInspector.DOMDocument} document
82      */
83     _setDocument: function(document)
84     {
85         this._document = document;
86         this.reset();
87     },
88
89     /**
90      * @param {WebInspector.Event} event
91      */
92     _documentUpdated: function(event)
93     {
94         var document = /** @type {WebInspector.DOMDocument} */ event.data;
95         this._setDocument(document);
96     },
97
98     /**
99      * @param {boolean} hasContent
100      */
101     _setSidebarHasContent: function(hasContent)
102     {
103         if (hasContent) {
104             if (!this._emptyElement.parentNode)
105                 return;
106
107             this._sidebarContentElement.removeChild(this._emptyElement);
108             this._sidebarContentElement.appendChild(this._flowListElement);
109         } else {
110             if (!this._flowListElement.parentNode)
111                 return;
112
113             this._sidebarContentElement.removeChild(this._flowListElement);
114             this._sidebarContentElement.appendChild(this._emptyElement);
115         }
116     },
117
118     /**
119      * @param {WebInspector.NamedFlow} flow
120      */
121     _appendNamedFlow: function(flow)
122     {
123         var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name);
124         var flowContainer = { flow: flow, flowHash: flowHash };
125
126         for (var i = 0; i < flow.content.length; ++i)
127             this._contentNodes[flow.content[i]] = flowHash;
128         for (var i = 0; i < flow.regions.length; ++i)
129             this._regionNodes[flow.regions[i].nodeId] = flowHash;
130
131         var container = document.createElement("div");
132         container.createChild("div", "selection");
133         container.createChild("span", "title").createChild("span").textContent = flow.name;
134
135         var flowTreeElement = new TreeElement(container, flowContainer);
136         if (flow.overset)
137             flowTreeElement.title.addStyleClass("named-flow-overflow")
138
139         flowContainer.flowTreeElement = flowTreeElement;
140         this._namedFlows[flowHash] = flowContainer;
141
142         if (!this._flowTree.children.length)
143             this._setSidebarHasContent(true);
144         this._flowTree.appendChild(flowTreeElement);
145     },
146
147     /**
148      * @param {string} flowHash
149      */
150     _removeNamedFlow: function(flowHash)
151     {
152         var flowContainer = this._namedFlows[flowHash];
153
154         this._flowTree.removeChild(flowContainer.flowTreeElement);
155
156         var flow = flowContainer.flow;
157         for (var i = 0; i < flow.content.length; ++i)
158             delete this._contentNodes[flow.content[i]];
159         for (var i = 0; i < flow.regions.length; ++i)
160             delete this._regionNodes[flow.regions[i].nodeId];
161
162         delete this._namedFlows[flowHash];
163
164         if (!this._flowTree.children.length)
165             this._setSidebarHasContent(false);
166     },
167
168     /**
169      * @param {WebInspector.NamedFlow} flow
170      */
171     _updateNamedFlow: function(flow)
172     {
173         var flowHash = this._hashNamedFlow(flow.documentNodeId, flow.name);
174         var flowContainer = this._namedFlows[flowHash];
175
176         if (!flowContainer)
177             return;
178
179         var oldFlow = flowContainer.flow;
180         flowContainer.flow = flow;
181
182         for (var i = 0; i < oldFlow.content.length; ++i)
183             delete this._contentNodes[oldFlow.content[i]];
184         for (var i = 0; i < oldFlow.regions.length; ++i)
185             delete this._regionNodes[oldFlow.regions[i].nodeId];
186
187         for (var i = 0; i < flow.content.length; ++i)
188             this._contentNodes[flow.content[i]] = flowHash;
189         for (var i = 0; i < flow.regions.length; ++i)
190             this._regionNodes[flow.regions[i].nodeId] = flowHash;
191
192         if (flow.overset !== oldFlow.overset) {
193             if (flow.overset)
194                 flowContainer.flowTreeElement.title.addStyleClass("named-flow-overflow");
195             else
196                 flowContainer.flowTreeElement.title.removeStyleClass("named-flow-overflow");
197         }
198     },
199
200     /**
201      * @param {WebInspector.NamedFlowCollection} namedFlowCollection
202      */
203     _resetNamedFlows: function(namedFlowCollection)
204     {
205         for (var flowHash in this._namedFlows)
206             this._removeNamedFlow(flowHash);
207
208         var namedFlows = namedFlowCollection.namedFlowMap;
209         for (var flowName in namedFlows)
210             this._appendNamedFlow(namedFlows[flowName]);
211
212         if (!this._flowTree.children.length)
213             this._setSidebarHasContent(false);
214         else
215             this._showNamedFlowForNode(WebInspector.panel("elements").treeOutline.selectedDOMNode());
216     },
217
218     /**
219      * @param {WebInspector.Event} event
220      */
221     _namedFlowCreated: function(event)
222     {
223         // FIXME: We only have support for Named Flows in the main document.
224         if (event.data.documentNodeId !== this._document.id)
225             return;
226
227         var flow = /** @type {WebInspector.NamedFlow} */ event.data;
228         this._appendNamedFlow(flow);
229     },
230
231     /**
232      * @param {WebInspector.Event} event
233      */
234     _namedFlowRemoved: function(event)
235     {
236         // FIXME: We only have support for Named Flows in the main document.
237         if (event.data.documentNodeId !== this._document.id)
238             return;
239
240         this._removeNamedFlow(this._hashNamedFlow(event.data.documentNodeId, event.data.flowName));
241     },
242
243     /**
244      * @param {WebInspector.Event} event
245      */
246     _regionLayoutUpdated: function(event)
247     {
248         // FIXME: We only have support for Named Flows in the main document.
249         if (event.data.documentNodeId !== this._document.id)
250             return;
251
252         var flow = /** @type {WebInspector.NamedFlow} */ event.data;
253         this._updateNamedFlow(flow);
254     },
255
256     /**
257      * @param {DOMAgent.NodeId} documentNodeId
258      * @param {string} flowName
259      */
260     _hashNamedFlow: function(documentNodeId, flowName)
261     {
262         return documentNodeId + "|" + flowName;
263     },
264
265     /**
266      * @param {string} flowHash
267      */
268     _showNamedFlow: function(flowHash)
269     {
270         this._selectNamedFlowInSidebar(flowHash);
271     },
272
273     /**
274      * @param {string} flowHash
275      */
276     _selectNamedFlowInSidebar: function(flowHash)
277     {
278         this._namedFlows[flowHash].flowTreeElement.select(true);
279     },
280
281     /**
282      * @param {WebInspector.Event} event
283      */
284     _selectedNodeChanged: function(event)
285     {
286         var node = /** @type {WebInspector.DOMNode} */ event.data;
287         this._showNamedFlowForNode(node);
288     },
289
290     /**
291      * @param {?WebInspector.DOMNode} node
292      */
293     _showNamedFlowForNode: function(node)
294     {
295         if (!node)
296             return;
297
298         if (this._regionNodes[node.id]) {
299             this._showNamedFlow(this._regionNodes[node.id]);
300             return;
301         }
302
303         while (node) {
304             if (this._contentNodes[node.id]) {
305                 this._showNamedFlow(this._contentNodes[node.id]);
306                 return;
307             }
308
309             node = node.parentNode;
310         }
311     },
312
313     wasShown: function()
314     {
315         WebInspector.SplitView.prototype.wasShown.call(this);
316
317         WebInspector.domAgent.requestDocument(this._setDocument.bind(this));
318
319         WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this);
320
321         WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this);
322         WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this);
323         WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this);
324
325         WebInspector.panel("elements").treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this);
326     },
327
328     willHide: function()
329     {
330         WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this);
331
332         WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowCreated, this._namedFlowCreated, this);
333         WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.NamedFlowRemoved, this._namedFlowRemoved, this);
334         WebInspector.cssModel.removeEventListener(WebInspector.CSSStyleModel.Events.RegionLayoutUpdated, this._regionLayoutUpdated, this);
335
336         WebInspector.panel("elements").treeOutline.removeEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this);
337     }
338 }
339
340 WebInspector.CSSNamedFlowCollectionsView.prototype.__proto__ = WebInspector.SplitView.prototype;