Web Inspector: Create Separate Model and View Objects for RemoteObjects / ObjectPrevi...
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / ObjectTreeCollectionTreeElement.js
1 /*
2  * Copyright (C) 2015 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
26 WebInspector.ObjectTreeCollectionTreeElement = function(remoteObject)
27 {
28     console.assert(remoteObject instanceof WebInspector.RemoteObject);
29
30     this._remoteObject = remoteObject;
31     this._requestingEntries = false;
32     this._trackingEntries = false;
33
34     TreeElement.call(this, "<entries>", null, false);
35     this.toggleOnClick = true;
36     this.selectable = false;
37     this.hasChildren = true;
38     this.expand();
39
40     // FIXME: When a parent TreeElement is collapsed, we do not get a chance
41     // to releaseWeakCollectionEntries. We should.
42 };
43
44 WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry = function(name, value)
45 {
46     var descriptor = {name: name, value: value, enumerable: true, writable: false};
47     return new WebInspector.PropertyDescriptor(descriptor, true, false, false);
48 }
49
50 WebInspector.ObjectTreeCollectionTreeElement.prototype = {
51     constructor: WebInspector.ObjectTreeCollectionTreeElement,
52     __proto__: TreeElement.prototype,
53
54     // Public
55
56     get remoteObject()
57     {
58         return this._remoteObject;
59     },
60
61     // Protected
62
63     onexpand: function()
64     {
65         if (this.children.length && !this.shouldRefreshChildren)
66             return;
67
68         if (this._requestingEntries)
69             return;
70
71         this._requestingEntries = true;
72
73         function callback(entries) {
74             this._requestingEntries = false;
75
76             this.removeChildren();
77
78             if (!entries || !entries.length) {
79                 this.appendChild(new WebInspector.ObjectTreeEmptyCollectionTreeElement);
80                 return;
81             }
82
83             this._trackWeakEntries();
84
85             for (var i = 0; i < entries.length; ++i) {
86                 var entry = entries[i];
87                 if (entry.key)
88                     this.appendChild(new WebInspector.ObjectTreeCollectionEntryTreeElement(entry, i));
89                 else {
90                     var propertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("" + i, entry.value);
91                     this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(propertyDescriptor));
92                 }
93             }
94         }
95
96         this._remoteObject.getCollectionEntries(0, 100, callback.bind(this));
97     },
98
99     oncollapse: function()
100     {
101         this._untrackWeakEntries();
102     },
103
104     ondetach: function()
105     {
106         this._untrackWeakEntries();
107     },
108
109     // Private.
110
111     _trackWeakEntries: function()
112     {
113         if (!this._remoteObject.isWeakCollection())
114             return;
115
116         if (this._trackingEntries)
117             return;
118
119         this._trackingEntries = true;
120
121         WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
122         WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
123         WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
124     },
125
126     _untrackWeakEntries: function()
127     {
128         if (!this._remoteObject.isWeakCollection())
129             return;
130
131         if (!this._trackingEntries)
132             return;
133
134         this._trackingEntries = false;
135
136         this._remoteObject.releaseWeakCollectionEntries();
137
138         WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.Cleared, this._untrackWeakEntries, this);
139         WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.ActiveLogCleared, this._untrackWeakEntries, this);
140         WebInspector.logManager.removeEventListener(WebInspector.LogManager.Event.SessionStarted, this._untrackWeakEntries, this);
141
142         this.removeChildren();
143
144         if (this.expanded)
145             this.collapse();
146     },
147 };
148
149 WebInspector.ObjectTreeCollectionEntryTreeElement = function(entry, index)
150 {
151     console.assert(entry instanceof WebInspector.CollectionEntry);
152     console.assert(entry.key instanceof WebInspector.RemoteObject);
153     console.assert(entry.value instanceof WebInspector.RemoteObject);
154
155     this._name = "" + index;
156     this._key = entry.key;
157     this._value = entry.value;
158
159     TreeElement.call(this, "", null, false);
160     this.toggleOnClick = true;
161     this.selectable = false;
162     this.hasChildren = true;
163 }
164
165 WebInspector.ObjectTreeCollectionEntryTreeElement.prototype = {
166     constructor: WebInspector.ObjectTreeCollectionEntryTreeElement,
167     __proto__: TreeElement.prototype,
168
169     // Protected
170
171     onpopulate: function()
172     {
173         if (this.children.length && !this.shouldRefreshChildren)
174             return;
175
176         var keyPropertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("key", this._key);
177         this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(keyPropertyDescriptor));
178
179         var valuePropertyDescriptor = WebInspector.ObjectTreeCollectionTreeElement.propertyDescriptorForEntry("value", this._value);
180         this.appendChild(new WebInspector.ObjectTreePropertyTreeElement(valuePropertyDescriptor));
181     },
182
183     onattach: function()
184     {
185         var nameElement = document.createElement("span");
186         nameElement.className = "name";
187         nameElement.textContent = "" + this._name;
188
189         var separatorElement = document.createElement("span");
190         separatorElement.className = "separator";
191         separatorElement.textContent = ": ";
192
193         var valueElement = document.createElement("span");
194         valueElement.className = "value";
195         valueElement.textContent = "{" + this._key.description + " => " + this._value.description + "}";
196
197         this.listItemElement.classList.add("object-tree-property");
198
199         this.listItemElement.removeChildren();
200         this.listItemElement.appendChild(nameElement);
201         this.listItemElement.appendChild(separatorElement);
202         this.listItemElement.appendChild(valueElement);
203     }
204 };
205
206 WebInspector.ObjectTreeEmptyCollectionTreeElement = function()
207 {
208     TreeElement.call(this, WebInspector.UIString("Empty Collection"), null, false);
209     this.selectable = false;
210 }
211
212 WebInspector.ObjectTreeEmptyCollectionTreeElement.prototype = {
213     constructor: WebInspector.ObjectTreeEmptyCollectionTreeElement,
214     __proto__: TreeElement.prototype
215 };