OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * | 10 * |
11 * 2. Redistributions in binary form must reproduce the above | 11 * 2. Redistributions in binary form must reproduce the above |
12 * copyright notice, this list of conditions and the following disclaimer | 12 * copyright notice, this list of conditions and the following disclaimer |
13 * in the documentation and/or other materials provided with the | 13 * in the documentation and/or other materials provided with the |
14 * distribution. | 14 * distribution. |
15 * | 15 * |
16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS | 16 * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS |
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. | 19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. |
20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 20 * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 */ | 27 */ |
28 | |
29 /** | 28 /** |
30 * @constructor | |
31 * @extends {WebInspector.VBox} | |
32 * @implements {WebInspector.TargetManager.Observer} | 29 * @implements {WebInspector.TargetManager.Observer} |
| 30 * @unrestricted |
33 */ | 31 */ |
34 WebInspector.NavigatorView = function() | 32 WebInspector.NavigatorView = class extends WebInspector.VBox { |
35 { | 33 constructor() { |
36 WebInspector.VBox.call(this); | 34 super(); |
37 this.registerRequiredCSS("sources/navigatorView.css"); | 35 this.registerRequiredCSS('sources/navigatorView.css'); |
38 | 36 |
39 this._scriptsTree = new TreeOutlineInShadow(); | 37 this._scriptsTree = new TreeOutlineInShadow(); |
40 this._scriptsTree.registerRequiredCSS("sources/navigatorTree.css"); | 38 this._scriptsTree.registerRequiredCSS('sources/navigatorTree.css'); |
41 this._scriptsTree.setComparator(WebInspector.NavigatorView._treeElementsComp
are); | 39 this._scriptsTree.setComparator(WebInspector.NavigatorView._treeElementsComp
are); |
42 this.element.appendChild(this._scriptsTree.element); | 40 this.element.appendChild(this._scriptsTree.element); |
43 this.setDefaultFocusedElement(this._scriptsTree.element); | 41 this.setDefaultFocusedElement(this._scriptsTree.element); |
44 | 42 |
45 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.NavigatorUISource
CodeTreeNode>} */ | 43 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.NavigatorUISource
CodeTreeNode>} */ |
46 this._uiSourceCodeNodes = new Map(); | 44 this._uiSourceCodeNodes = new Map(); |
47 /** @type {!Map.<string, !WebInspector.NavigatorFolderTreeNode>} */ | 45 /** @type {!Map.<string, !WebInspector.NavigatorFolderTreeNode>} */ |
48 this._subfolderNodes = new Map(); | 46 this._subfolderNodes = new Map(); |
49 | 47 |
50 this._rootNode = new WebInspector.NavigatorRootTreeNode(this); | 48 this._rootNode = new WebInspector.NavigatorRootTreeNode(this); |
51 this._rootNode.populate(); | 49 this._rootNode.populate(); |
52 | 50 |
53 /** @type {!Map.<!WebInspector.ResourceTreeFrame, !WebInspector.NavigatorGro
upTreeNode>} */ | 51 /** @type {!Map.<!WebInspector.ResourceTreeFrame, !WebInspector.NavigatorGro
upTreeNode>} */ |
54 this._frameNodes = new Map(); | 52 this._frameNodes = new Map(); |
55 | 53 |
56 this.element.addEventListener("contextmenu", this.handleContextMenu.bind(thi
s), false); | 54 this.element.addEventListener('contextmenu', this.handleContextMenu.bind(thi
s), false); |
57 | 55 |
58 this._navigatorGroupByFolderSetting = WebInspector.moduleSetting("navigatorG
roupByFolder"); | 56 this._navigatorGroupByFolderSetting = WebInspector.moduleSetting('navigatorG
roupByFolder'); |
59 this._navigatorGroupByFolderSetting.addChangeListener(this._groupingChanged.
bind(this)); | 57 this._navigatorGroupByFolderSetting.addChangeListener(this._groupingChanged.
bind(this)); |
60 | 58 |
61 this._initGrouping(); | 59 this._initGrouping(); |
62 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.Events.FrameNavigated, this._frameNavigated, this
); | 60 WebInspector.targetManager.addModelListener( |
63 WebInspector.targetManager.addModelListener(WebInspector.ResourceTreeModel,
WebInspector.ResourceTreeModel.Events.FrameDetached, this._frameDetached, this); | 61 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Fr
ameNavigated, this._frameNavigated, |
64 | 62 this); |
65 if (Runtime.experiments.isEnabled("persistence2")) { | 63 WebInspector.targetManager.addModelListener( |
66 WebInspector.persistence.addEventListener(WebInspector.Persistence.Event
s.BindingCreated, this._onBindingChanged, this); | 64 WebInspector.ResourceTreeModel, WebInspector.ResourceTreeModel.Events.Fr
ameDetached, this._frameDetached, this); |
67 WebInspector.persistence.addEventListener(WebInspector.Persistence.Event
s.BindingRemoved, this._onBindingChanged, this); | 65 |
| 66 if (Runtime.experiments.isEnabled('persistence2')) { |
| 67 WebInspector.persistence.addEventListener( |
| 68 WebInspector.Persistence.Events.BindingCreated, this._onBindingChanged
, this); |
| 69 WebInspector.persistence.addEventListener( |
| 70 WebInspector.Persistence.Events.BindingRemoved, this._onBindingChanged
, this); |
68 } else { | 71 } else { |
69 WebInspector.persistence.addEventListener(WebInspector.Persistence.Event
s.BindingCreated, this._onBindingCreated, this); | 72 WebInspector.persistence.addEventListener( |
70 WebInspector.persistence.addEventListener(WebInspector.Persistence.Event
s.BindingRemoved, this._onBindingRemoved, this); | 73 WebInspector.Persistence.Events.BindingCreated, this._onBindingCreated
, this); |
71 } | 74 WebInspector.persistence.addEventListener( |
72 WebInspector.targetManager.addEventListener(WebInspector.TargetManager.Event
s.NameChanged, this._targetNameChanged, this); | 75 WebInspector.Persistence.Events.BindingRemoved, this._onBindingRemoved
, this); |
| 76 } |
| 77 WebInspector.targetManager.addEventListener( |
| 78 WebInspector.TargetManager.Events.NameChanged, this._targetNameChanged,
this); |
73 | 79 |
74 WebInspector.targetManager.observeTargets(this); | 80 WebInspector.targetManager.observeTargets(this); |
75 this._resetWorkspace(WebInspector.workspace); | 81 this._resetWorkspace(WebInspector.workspace); |
76 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); | 82 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); |
77 }; | 83 } |
78 | 84 |
79 WebInspector.NavigatorView.Types = { | 85 /** |
80 Category: "category", | 86 * @param {!TreeElement} treeElement |
81 Domain: "domain", | 87 */ |
82 File: "file", | 88 static _treeElementOrder(treeElement) { |
83 FileSystem: "fs", | |
84 FileSystemFolder: "fs-folder", | |
85 Frame: "frame", | |
86 NetworkFolder: "nw-folder", | |
87 Root: "root", | |
88 SourceMapFolder: "sm-folder", | |
89 Worker: "worker" | |
90 }; | |
91 | |
92 /** | |
93 * @param {!TreeElement} treeElement | |
94 */ | |
95 WebInspector.NavigatorView._treeElementOrder = function(treeElement) | |
96 { | |
97 if (treeElement._boostOrder) | 89 if (treeElement._boostOrder) |
98 return 0; | 90 return 0; |
99 | 91 |
100 if (!WebInspector.NavigatorView._typeOrders) { | 92 if (!WebInspector.NavigatorView._typeOrders) { |
101 var weights = {}; | 93 var weights = {}; |
102 var types = WebInspector.NavigatorView.Types; | 94 var types = WebInspector.NavigatorView.Types; |
103 weights[types.Root] = 1; | 95 weights[types.Root] = 1; |
104 weights[types.Category] = 1; | 96 weights[types.Category] = 1; |
105 weights[types.Domain] = 10; | 97 weights[types.Domain] = 10; |
106 weights[types.FileSystemFolder] = 1; | 98 weights[types.FileSystemFolder] = 1; |
107 weights[types.NetworkFolder] = 1; | 99 weights[types.NetworkFolder] = 1; |
108 weights[types.SourceMapFolder] = 2; | 100 weights[types.SourceMapFolder] = 2; |
109 weights[types.File] = 10; | 101 weights[types.File] = 10; |
110 weights[types.Frame] = 70; | 102 weights[types.Frame] = 70; |
111 weights[types.Worker] = 90; | 103 weights[types.Worker] = 90; |
112 weights[types.FileSystem] = 100; | 104 weights[types.FileSystem] = 100; |
113 WebInspector.NavigatorView._typeOrders = weights; | 105 WebInspector.NavigatorView._typeOrders = weights; |
114 } | 106 } |
115 | 107 |
116 var order = WebInspector.NavigatorView._typeOrders[treeElement._nodeType]; | 108 var order = WebInspector.NavigatorView._typeOrders[treeElement._nodeType]; |
117 if (treeElement._uiSourceCode) { | 109 if (treeElement._uiSourceCode) { |
118 var contentType = treeElement._uiSourceCode.contentType(); | 110 var contentType = treeElement._uiSourceCode.contentType(); |
119 if (contentType.isDocument()) | 111 if (contentType.isDocument()) |
120 order += 3; | 112 order += 3; |
121 else if (contentType.isScript()) | 113 else if (contentType.isScript()) |
122 order += 5; | 114 order += 5; |
123 else if (contentType.isStyleSheet()) | 115 else if (contentType.isStyleSheet()) |
124 order += 10; | 116 order += 10; |
125 else | 117 else |
126 order += 15; | 118 order += 15; |
127 } | 119 } |
128 | 120 |
129 return order; | 121 return order; |
130 }; | 122 } |
131 | 123 |
132 /** | 124 /** |
133 * @param {!WebInspector.ContextMenu} contextMenu | 125 * @param {!WebInspector.ContextMenu} contextMenu |
134 */ | 126 */ |
135 WebInspector.NavigatorView.appendAddFolderItem = function(contextMenu) | 127 static appendAddFolderItem(contextMenu) { |
136 { | 128 function addFolder() { |
137 function addFolder() | 129 WebInspector.isolatedFileSystemManager.addFileSystem(); |
138 { | 130 } |
139 WebInspector.isolatedFileSystemManager.addFileSystem(); | 131 |
140 } | 132 var addFolderLabel = WebInspector.UIString('Add folder to workspace'); |
141 | |
142 var addFolderLabel = WebInspector.UIString("Add folder to workspace"); | |
143 contextMenu.appendItem(addFolderLabel, addFolder); | 133 contextMenu.appendItem(addFolderLabel, addFolder); |
144 }; | 134 } |
145 | 135 |
146 /** | 136 /** |
147 * @param {!WebInspector.ContextMenu} contextMenu | 137 * @param {!WebInspector.ContextMenu} contextMenu |
148 * @param {string=} path | 138 * @param {string=} path |
149 */ | 139 */ |
150 WebInspector.NavigatorView.appendSearchItem = function(contextMenu, path) | 140 static appendSearchItem(contextMenu, path) { |
151 { | 141 function searchPath() { |
152 function searchPath() | 142 WebInspector.AdvancedSearchView.openSearch('', path.trim()); |
153 { | 143 } |
154 WebInspector.AdvancedSearchView.openSearch("", path.trim()); | 144 |
155 } | 145 var searchLabel = WebInspector.UIString('Search in folder'); |
156 | |
157 var searchLabel = WebInspector.UIString("Search in folder"); | |
158 if (!path || !path.trim()) { | 146 if (!path || !path.trim()) { |
159 path = "*"; | 147 path = '*'; |
160 searchLabel = WebInspector.UIString("Search in all files"); | 148 searchLabel = WebInspector.UIString('Search in all files'); |
161 } | 149 } |
162 contextMenu.appendItem(searchLabel, searchPath); | 150 contextMenu.appendItem(searchLabel, searchPath); |
163 }; | 151 } |
164 | 152 |
165 WebInspector.NavigatorView.prototype = { | 153 /** |
166 /** | 154 * @param {!TreeElement} treeElement1 |
167 * @param {!WebInspector.Event} event | 155 * @param {!TreeElement} treeElement2 |
168 */ | 156 * @return {number} |
169 _onBindingCreated: function(event) | 157 */ |
170 { | 158 static _treeElementsCompare(treeElement1, treeElement2) { |
171 var binding = /** @type {!WebInspector.PersistenceBinding} */(event.data
); | |
172 this._removeUISourceCode(binding.network); | |
173 }, | |
174 | |
175 /** | |
176 * @param {!WebInspector.Event} event | |
177 */ | |
178 _onBindingRemoved: function(event) | |
179 { | |
180 var binding = /** @type {!WebInspector.PersistenceBinding} */(event.data
); | |
181 this._addUISourceCode(binding.network); | |
182 }, | |
183 | |
184 /** | |
185 * @param {!WebInspector.Event} event | |
186 */ | |
187 _onBindingChanged: function(event) | |
188 { | |
189 var binding = /** @type {!WebInspector.PersistenceBinding} */(event.data
); | |
190 | |
191 // Update UISourceCode titles. | |
192 var networkNode = this._uiSourceCodeNodes.get(binding.network); | |
193 if (networkNode) | |
194 networkNode.updateTitle(); | |
195 var fileSystemNode = this._uiSourceCodeNodes.get(binding.fileSystem); | |
196 if (fileSystemNode) | |
197 fileSystemNode.updateTitle(); | |
198 | |
199 // Update folder titles. | |
200 var pathTokens = WebInspector.FileSystemWorkspaceBinding.relativePath(bi
nding.fileSystem); | |
201 var folderPath = ""; | |
202 for (var i = 0; i < pathTokens.length - 1; ++i) { | |
203 folderPath += pathTokens[i]; | |
204 var folderId = this._folderNodeId(binding.fileSystem.project(), null
, null, binding.fileSystem.origin(), folderPath); | |
205 var folderNode = this._subfolderNodes.get(folderId); | |
206 if (folderNode) | |
207 folderNode.updateTitle(); | |
208 folderPath += "/"; | |
209 } | |
210 | |
211 // Update fileSystem root title. | |
212 var fileSystemRoot = this._rootNode.child(binding.fileSystem.project().i
d()); | |
213 if (fileSystemRoot) | |
214 fileSystemRoot.updateTitle(); | |
215 }, | |
216 | |
217 /** | |
218 * @override | |
219 */ | |
220 focus: function() | |
221 { | |
222 this._scriptsTree.focus(); | |
223 }, | |
224 | |
225 /** | |
226 * @param {!WebInspector.Workspace} workspace | |
227 */ | |
228 _resetWorkspace: function(workspace) | |
229 { | |
230 this._workspace = workspace; | |
231 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceC
odeAdded, this._uiSourceCodeAdded, this); | |
232 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceC
odeRemoved, this._uiSourceCodeRemoved, this); | |
233 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectRe
moved, this._projectRemoved.bind(this), this); | |
234 }, | |
235 | |
236 /** | |
237 * @param {!WebInspector.UISourceCode} uiSourceCode | |
238 * @return {boolean} | |
239 */ | |
240 accept: function(uiSourceCode) | |
241 { | |
242 return !uiSourceCode.isFromServiceProject(); | |
243 }, | |
244 | |
245 /** | |
246 * @param {!WebInspector.UISourceCode} uiSourceCode | |
247 * @return {?WebInspector.ResourceTreeFrame} | |
248 */ | |
249 _uiSourceCodeFrame: function(uiSourceCode) | |
250 { | |
251 var frame = WebInspector.NetworkProject.frameForProject(uiSourceCode.pro
ject()); | |
252 if (!frame) { | |
253 var target = WebInspector.NetworkProject.targetForProject(uiSourceCo
de.project()); | |
254 var resourceTreeModel = target && WebInspector.ResourceTreeModel.fro
mTarget(target); | |
255 frame = resourceTreeModel && resourceTreeModel.mainFrame; | |
256 } | |
257 return frame; | |
258 }, | |
259 | |
260 /** | |
261 * @param {!WebInspector.UISourceCode} uiSourceCode | |
262 */ | |
263 _addUISourceCode: function(uiSourceCode) | |
264 { | |
265 if (!this.accept(uiSourceCode)) | |
266 return; | |
267 | |
268 var binding = WebInspector.persistence.binding(uiSourceCode); | |
269 if (!Runtime.experiments.isEnabled("persistence2") && binding && binding
.network === uiSourceCode) | |
270 return; | |
271 | |
272 var isFromSourceMap = uiSourceCode.contentType().isFromSourceMap(); | |
273 var path; | |
274 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSyst
em) | |
275 path = WebInspector.FileSystemWorkspaceBinding.relativePath(uiSource
Code).slice(0, -1); | |
276 else | |
277 path = WebInspector.ParsedURL.extractPath(uiSourceCode.url()).split(
"/").slice(1, -1); | |
278 | |
279 var project = uiSourceCode.project(); | |
280 var target = WebInspector.NetworkProject.targetForUISourceCode(uiSourceC
ode); | |
281 var frame = this._uiSourceCodeFrame(uiSourceCode); | |
282 | |
283 var folderNode = this._folderNode(uiSourceCode, project, target, frame,
uiSourceCode.origin(), path, isFromSourceMap); | |
284 var uiSourceCodeNode = new WebInspector.NavigatorUISourceCodeTreeNode(th
is, uiSourceCode); | |
285 this._uiSourceCodeNodes.set(uiSourceCode, uiSourceCodeNode); | |
286 folderNode.appendChild(uiSourceCodeNode); | |
287 this.uiSourceCodeAdded(uiSourceCode); | |
288 }, | |
289 | |
290 /** | |
291 * @param {!WebInspector.UISourceCode} uiSourceCode | |
292 */ | |
293 uiSourceCodeAdded: function(uiSourceCode) | |
294 { | |
295 }, | |
296 | |
297 /** | |
298 * @param {!WebInspector.Event} event | |
299 */ | |
300 _uiSourceCodeAdded: function(event) | |
301 { | |
302 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
); | |
303 this._addUISourceCode(uiSourceCode); | |
304 }, | |
305 | |
306 /** | |
307 * @param {!WebInspector.Event} event | |
308 */ | |
309 _uiSourceCodeRemoved: function(event) | |
310 { | |
311 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data
); | |
312 this._removeUISourceCode(uiSourceCode); | |
313 }, | |
314 | |
315 /** | |
316 * @param {!WebInspector.Event} event | |
317 */ | |
318 _projectRemoved: function(event) | |
319 { | |
320 var project = /** @type {!WebInspector.Project} */ (event.data); | |
321 | |
322 var frame = WebInspector.NetworkProject.frameForProject(project); | |
323 if (frame) | |
324 this._discardFrame(frame); | |
325 | |
326 var uiSourceCodes = project.uiSourceCodes(); | |
327 for (var i = 0; i < uiSourceCodes.length; ++i) | |
328 this._removeUISourceCode(uiSourceCodes[i]); | |
329 }, | |
330 | |
331 /** | |
332 * @param {!WebInspector.Project} project | |
333 * @param {?WebInspector.Target} target | |
334 * @param {?WebInspector.ResourceTreeFrame} frame | |
335 * @param {string} projectOrigin | |
336 * @param {string} path | |
337 * @return {string} | |
338 */ | |
339 _folderNodeId: function(project, target, frame, projectOrigin, path) | |
340 { | |
341 var targetId = target ? target.id() : ""; | |
342 var projectId = project.type() === WebInspector.projectTypes.FileSystem
? project.id() : ""; | |
343 var frameId = this._groupByFrame && frame ? frame.id : ""; | |
344 return targetId + ":" + projectId + ":" + frameId + ":" + projectOrigin
+ ":" + path; | |
345 }, | |
346 | |
347 /** | |
348 * @param {!WebInspector.UISourceCode} uiSourceCode | |
349 * @param {!WebInspector.Project} project | |
350 * @param {?WebInspector.Target} target | |
351 * @param {?WebInspector.ResourceTreeFrame} frame | |
352 * @param {string} projectOrigin | |
353 * @param {!Array<string>} path | |
354 * @param {boolean} fromSourceMap | |
355 * @return {!WebInspector.NavigatorTreeNode} | |
356 */ | |
357 _folderNode: function(uiSourceCode, project, target, frame, projectOrigin, p
ath, fromSourceMap) | |
358 { | |
359 if (project.type() === WebInspector.projectTypes.Snippets) | |
360 return this._rootNode; | |
361 | |
362 if (target && !this._groupByFolder && !fromSourceMap) | |
363 return this._domainNode(uiSourceCode, project, target, frame, projec
tOrigin); | |
364 | |
365 var folderPath = path.join("/"); | |
366 var folderId = this._folderNodeId(project, target, frame, projectOrigin,
folderPath); | |
367 var folderNode = this._subfolderNodes.get(folderId); | |
368 if (folderNode) | |
369 return folderNode; | |
370 | |
371 if (!path.length) { | |
372 if (target) | |
373 return this._domainNode(uiSourceCode, project, target, frame, pr
ojectOrigin); | |
374 var fileSystemNode = this._rootNode.child(project.id()); | |
375 if (!fileSystemNode) { | |
376 fileSystemNode = new WebInspector.NavigatorGroupTreeNode(this, p
roject, project.id(), WebInspector.NavigatorView.Types.FileSystem, project.disp
layName()); | |
377 this._rootNode.appendChild(fileSystemNode); | |
378 } | |
379 return fileSystemNode; | |
380 } | |
381 | |
382 var parentNode = this._folderNode(uiSourceCode, project, target, frame,
projectOrigin, path.slice(0, -1), fromSourceMap); | |
383 var type = fromSourceMap ? WebInspector.NavigatorView.Types.SourceMapFol
der : WebInspector.NavigatorView.Types.NetworkFolder; | |
384 if (project.type() === WebInspector.projectTypes.FileSystem) | |
385 type = WebInspector.NavigatorView.Types.FileSystemFolder; | |
386 var name = path[path.length - 1]; | |
387 | |
388 folderNode = new WebInspector.NavigatorFolderTreeNode(this, project, fol
derId, type, folderPath, name); | |
389 this._subfolderNodes.set(folderId, folderNode); | |
390 parentNode.appendChild(folderNode); | |
391 return folderNode; | |
392 }, | |
393 | |
394 /** | |
395 * @param {!WebInspector.UISourceCode} uiSourceCode | |
396 * @param {!WebInspector.Project} project | |
397 * @param {!WebInspector.Target} target | |
398 * @param {?WebInspector.ResourceTreeFrame} frame | |
399 * @param {string} projectOrigin | |
400 * @return {!WebInspector.NavigatorTreeNode} | |
401 */ | |
402 _domainNode: function(uiSourceCode, project, target, frame, projectOrigin) | |
403 { | |
404 var frameNode = this._frameNode(project, target, frame); | |
405 if (!this._groupByDomain) | |
406 return frameNode; | |
407 var domainNode = frameNode.child(projectOrigin); | |
408 if (domainNode) | |
409 return domainNode; | |
410 | |
411 domainNode = new WebInspector.NavigatorGroupTreeNode(this, project, proj
ectOrigin, WebInspector.NavigatorView.Types.Domain, this._computeProjectDisplay
Name(target, projectOrigin)); | |
412 if (frame && projectOrigin === WebInspector.ParsedURL.extractOrigin(fram
e.url)) | |
413 domainNode.treeNode()._boostOrder = true; | |
414 frameNode.appendChild(domainNode); | |
415 return domainNode; | |
416 }, | |
417 | |
418 /** | |
419 * @param {!WebInspector.Project} project | |
420 * @param {!WebInspector.Target} target | |
421 * @param {?WebInspector.ResourceTreeFrame} frame | |
422 * @return {!WebInspector.NavigatorTreeNode} | |
423 */ | |
424 _frameNode: function(project, target, frame) | |
425 { | |
426 if (!this._groupByFrame || !frame) | |
427 return this._targetNode(project, target); | |
428 | |
429 var frameNode = this._frameNodes.get(frame); | |
430 if (frameNode) | |
431 return frameNode; | |
432 | |
433 frameNode = new WebInspector.NavigatorGroupTreeNode(this, project, targe
t.id() + ":" + frame.id, WebInspector.NavigatorView.Types.Frame, frame.displayNa
me()); | |
434 frameNode.setHoverCallback(hoverCallback); | |
435 this._frameNodes.set(frame, frameNode); | |
436 this._frameNode(project, target, frame.parentFrame).appendChild(frameNod
e); | |
437 if (!frame.parentFrame) | |
438 frameNode.treeNode()._boostOrder = true; | |
439 | |
440 /** | |
441 * @param {boolean} hovered | |
442 */ | |
443 function hoverCallback(hovered) | |
444 { | |
445 if (hovered) { | |
446 var domModel = WebInspector.DOMModel.fromTarget(target); | |
447 if (domModel) | |
448 domModel.highlightFrame(frame.id); | |
449 } else { | |
450 WebInspector.DOMModel.hideDOMNodeHighlight(); | |
451 } | |
452 } | |
453 return frameNode; | |
454 }, | |
455 | |
456 /** | |
457 * @param {!WebInspector.Project} project | |
458 * @param {!WebInspector.Target} target | |
459 * @return {!WebInspector.NavigatorTreeNode} | |
460 */ | |
461 _targetNode: function(project, target) | |
462 { | |
463 if (target === WebInspector.targetManager.mainTarget()) | |
464 return this._rootNode; | |
465 | |
466 var targetNode = this._rootNode.child("target:" + target.id()); | |
467 if (!targetNode) { | |
468 targetNode = new WebInspector.NavigatorGroupTreeNode(this, project,
"target:" + target.id(), !target.hasBrowserCapability() ? WebInspector.Navigator
View.Types.Worker : WebInspector.NavigatorView.Types.NetworkFolder, target.name(
)); | |
469 this._rootNode.appendChild(targetNode); | |
470 } | |
471 return targetNode; | |
472 }, | |
473 | |
474 /** | |
475 * @param {!WebInspector.Target} target | |
476 * @param {string} projectOrigin | |
477 * @return {string} | |
478 */ | |
479 _computeProjectDisplayName: function(target, projectOrigin) | |
480 { | |
481 for (var context of target.runtimeModel.executionContexts()) { | |
482 if (context.name && context.origin && projectOrigin.startsWith(conte
xt.origin)) | |
483 return context.name; | |
484 } | |
485 | |
486 if (!projectOrigin) | |
487 return WebInspector.UIString("(no domain)"); | |
488 | |
489 var parsedURL = new WebInspector.ParsedURL(projectOrigin); | |
490 var prettyURL = parsedURL.isValid ? parsedURL.host + (parsedURL.port ? (
":" + parsedURL.port) : "") : ""; | |
491 | |
492 return (prettyURL || projectOrigin); | |
493 }, | |
494 | |
495 /** | |
496 * @param {!WebInspector.UISourceCode} uiSourceCode | |
497 * @param {boolean=} select | |
498 */ | |
499 revealUISourceCode: function(uiSourceCode, select) | |
500 { | |
501 var node = this._uiSourceCodeNodes.get(uiSourceCode); | |
502 if (!node) | |
503 return; | |
504 if (this._scriptsTree.selectedTreeElement) | |
505 this._scriptsTree.selectedTreeElement.deselect(); | |
506 this._lastSelectedUISourceCode = uiSourceCode; | |
507 node.reveal(select); | |
508 }, | |
509 | |
510 /** | |
511 * @param {!WebInspector.UISourceCode} uiSourceCode | |
512 * @param {boolean} focusSource | |
513 */ | |
514 _sourceSelected: function(uiSourceCode, focusSource) | |
515 { | |
516 this._lastSelectedUISourceCode = uiSourceCode; | |
517 WebInspector.Revealer.reveal(uiSourceCode, !focusSource); | |
518 }, | |
519 | |
520 /** | |
521 * @param {!WebInspector.UISourceCode} uiSourceCode | |
522 */ | |
523 sourceDeleted: function(uiSourceCode) | |
524 { | |
525 }, | |
526 | |
527 /** | |
528 * @param {!WebInspector.UISourceCode} uiSourceCode | |
529 */ | |
530 _removeUISourceCode: function(uiSourceCode) | |
531 { | |
532 var node = this._uiSourceCodeNodes.get(uiSourceCode); | |
533 if (!node) | |
534 return; | |
535 | |
536 var project = uiSourceCode.project(); | |
537 var target = WebInspector.NetworkProject.targetForUISourceCode(uiSourceC
ode); | |
538 var frame = this._uiSourceCodeFrame(uiSourceCode); | |
539 | |
540 var parentNode = node.parent; | |
541 this._uiSourceCodeNodes.delete(uiSourceCode); | |
542 parentNode.removeChild(node); | |
543 node = parentNode; | |
544 | |
545 while (node) { | |
546 parentNode = node.parent; | |
547 if (!parentNode || !node.isEmpty()) | |
548 break; | |
549 if (!(node instanceof WebInspector.NavigatorGroupTreeNode || node in
stanceof WebInspector.NavigatorFolderTreeNode)) | |
550 break; | |
551 if (node._type === WebInspector.NavigatorView.Types.Frame) | |
552 break; | |
553 | |
554 var folderId = this._folderNodeId(project, target, frame, uiSourceCo
de.origin(), node._folderPath); | |
555 this._subfolderNodes.delete(folderId); | |
556 parentNode.removeChild(node); | |
557 node = parentNode; | |
558 } | |
559 }, | |
560 | |
561 reset: function() | |
562 { | |
563 var nodes = this._uiSourceCodeNodes.valuesArray(); | |
564 for (var i = 0; i < nodes.length; ++i) | |
565 nodes[i].dispose(); | |
566 | |
567 this._scriptsTree.removeChildren(); | |
568 this._uiSourceCodeNodes.clear(); | |
569 this._subfolderNodes.clear(); | |
570 this._frameNodes.clear(); | |
571 this._rootNode.reset(); | |
572 }, | |
573 | |
574 /** | |
575 * @param {!Event} event | |
576 */ | |
577 handleContextMenu: function(event) | |
578 { | |
579 }, | |
580 | |
581 /** | |
582 * @param {!WebInspector.Project} project | |
583 * @param {string} path | |
584 * @param {!WebInspector.UISourceCode=} uiSourceCode | |
585 */ | |
586 _handleContextMenuCreate: function(project, path, uiSourceCode) | |
587 { | |
588 this.create(project, path, uiSourceCode); | |
589 }, | |
590 | |
591 /** | |
592 * @param {!WebInspector.UISourceCode} uiSourceCode | |
593 */ | |
594 _handleContextMenuRename: function(uiSourceCode) | |
595 { | |
596 this.rename(uiSourceCode, false); | |
597 }, | |
598 | |
599 /** | |
600 * @param {!WebInspector.Project} project | |
601 * @param {string} path | |
602 */ | |
603 _handleContextMenuExclude: function(project, path) | |
604 { | |
605 var shouldExclude = window.confirm(WebInspector.UIString("Are you sure y
ou want to exclude this folder?")); | |
606 if (shouldExclude) { | |
607 WebInspector.startBatchUpdate(); | |
608 project.excludeFolder(WebInspector.FileSystemWorkspaceBinding.comple
teURL(project, path)); | |
609 WebInspector.endBatchUpdate(); | |
610 } | |
611 }, | |
612 | |
613 /** | |
614 * @param {!WebInspector.UISourceCode} uiSourceCode | |
615 */ | |
616 _handleContextMenuDelete: function(uiSourceCode) | |
617 { | |
618 var shouldDelete = window.confirm(WebInspector.UIString("Are you sure yo
u want to delete this file?")); | |
619 if (shouldDelete) | |
620 uiSourceCode.project().deleteFile(uiSourceCode.url()); | |
621 }, | |
622 | |
623 /** | |
624 * @param {!Event} event | |
625 * @param {!WebInspector.UISourceCode} uiSourceCode | |
626 */ | |
627 handleFileContextMenu: function(event, uiSourceCode) | |
628 { | |
629 var contextMenu = new WebInspector.ContextMenu(event); | |
630 contextMenu.appendApplicableItems(uiSourceCode); | |
631 contextMenu.appendSeparator(); | |
632 | |
633 var project = uiSourceCode.project(); | |
634 if (project.type() === WebInspector.projectTypes.FileSystem) { | |
635 var parentURL = uiSourceCode.parentURL(); | |
636 contextMenu.appendItem(WebInspector.UIString("Rename\u2026"), this._
handleContextMenuRename.bind(this, uiSourceCode)); | |
637 contextMenu.appendItem(WebInspector.UIString("Make a copy\u2026"), t
his._handleContextMenuCreate.bind(this, project, parentURL, uiSourceCode)); | |
638 contextMenu.appendItem(WebInspector.UIString("Delete"), this._handle
ContextMenuDelete.bind(this, uiSourceCode)); | |
639 contextMenu.appendSeparator(); | |
640 } | |
641 | |
642 contextMenu.show(); | |
643 }, | |
644 | |
645 /** | |
646 * @param {!Event} event | |
647 * @param {!WebInspector.NavigatorFolderTreeNode} node | |
648 */ | |
649 handleFolderContextMenu: function(event, node) | |
650 { | |
651 var path = node._folderPath; | |
652 var project = node._project; | |
653 | |
654 var contextMenu = new WebInspector.ContextMenu(event); | |
655 | |
656 WebInspector.NavigatorView.appendSearchItem(contextMenu, path); | |
657 contextMenu.appendSeparator(); | |
658 | |
659 if (project.type() !== WebInspector.projectTypes.FileSystem) | |
660 return; | |
661 | |
662 contextMenu.appendItem(WebInspector.UIString("New file"), this._handleCo
ntextMenuCreate.bind(this, project, path)); | |
663 contextMenu.appendItem(WebInspector.UIString("Exclude folder"), this._ha
ndleContextMenuExclude.bind(this, project, path)); | |
664 | |
665 function removeFolder() | |
666 { | |
667 var shouldRemove = window.confirm(WebInspector.UIString("Are you sur
e you want to remove this folder?")); | |
668 if (shouldRemove) | |
669 project.remove(); | |
670 } | |
671 | |
672 contextMenu.appendSeparator(); | |
673 WebInspector.NavigatorView.appendAddFolderItem(contextMenu); | |
674 if (node instanceof WebInspector.NavigatorGroupTreeNode) | |
675 contextMenu.appendItem(WebInspector.UIString("Remove folder from wor
kspace"), removeFolder); | |
676 | |
677 contextMenu.show(); | |
678 }, | |
679 | |
680 /** | |
681 * @param {!WebInspector.UISourceCode} uiSourceCode | |
682 * @param {boolean} deleteIfCanceled | |
683 */ | |
684 rename: function(uiSourceCode, deleteIfCanceled) | |
685 { | |
686 var node = this._uiSourceCodeNodes.get(uiSourceCode); | |
687 console.assert(node); | |
688 node.rename(callback.bind(this)); | |
689 | |
690 /** | |
691 * @this {WebInspector.NavigatorView} | |
692 * @param {boolean} committed | |
693 */ | |
694 function callback(committed) | |
695 { | |
696 if (!committed) { | |
697 if (deleteIfCanceled) | |
698 uiSourceCode.remove(); | |
699 return; | |
700 } | |
701 | |
702 this._sourceSelected(uiSourceCode, true); | |
703 } | |
704 }, | |
705 | |
706 /** | |
707 * @param {!WebInspector.Project} project | |
708 * @param {string} path | |
709 * @param {!WebInspector.UISourceCode=} uiSourceCodeToCopy | |
710 */ | |
711 create: function(project, path, uiSourceCodeToCopy) | |
712 { | |
713 var filePath; | |
714 var uiSourceCode; | |
715 | |
716 /** | |
717 * @this {WebInspector.NavigatorView} | |
718 * @param {?string} content | |
719 */ | |
720 function contentLoaded(content) | |
721 { | |
722 createFile.call(this, content || ""); | |
723 } | |
724 | |
725 if (uiSourceCodeToCopy) | |
726 uiSourceCodeToCopy.requestContent().then(contentLoaded.bind(this)); | |
727 else | |
728 createFile.call(this); | |
729 | |
730 /** | |
731 * @this {WebInspector.NavigatorView} | |
732 * @param {string=} content | |
733 */ | |
734 function createFile(content) | |
735 { | |
736 project.createFile(path, null, content || "", fileCreated.bind(this)
); | |
737 } | |
738 | |
739 /** | |
740 * @this {WebInspector.NavigatorView} | |
741 * @param {?WebInspector.UISourceCode} uiSourceCode | |
742 */ | |
743 function fileCreated(uiSourceCode) | |
744 { | |
745 if (!uiSourceCode) | |
746 return; | |
747 this._sourceSelected(uiSourceCode, false); | |
748 this.revealUISourceCode(uiSourceCode, true); | |
749 this.rename(uiSourceCode, true); | |
750 } | |
751 }, | |
752 | |
753 _groupingChanged: function() | |
754 { | |
755 this.reset(); | |
756 this._initGrouping(); | |
757 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)
); | |
758 }, | |
759 | |
760 _initGrouping: function() | |
761 { | |
762 this._groupByFrame = true; | |
763 this._groupByDomain = this._navigatorGroupByFolderSetting.get(); | |
764 this._groupByFolder = this._groupByDomain; | |
765 }, | |
766 | |
767 _resetForTest: function() | |
768 { | |
769 this.reset(); | |
770 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)
); | |
771 }, | |
772 | |
773 /** | |
774 * @param {!WebInspector.Event} event | |
775 */ | |
776 _frameNavigated: function(event) | |
777 { | |
778 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); | |
779 var node = this._frameNodes.get(frame); | |
780 if (!node) | |
781 return; | |
782 | |
783 node.treeNode().title = frame.displayName(); | |
784 for (var child of frame.childFrames) | |
785 this._discardFrame(child); | |
786 }, | |
787 | |
788 /** | |
789 * @param {!WebInspector.Event} event | |
790 */ | |
791 _frameDetached: function(event) | |
792 { | |
793 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); | |
794 this._discardFrame(frame); | |
795 }, | |
796 | |
797 /** | |
798 * @param {!WebInspector.ResourceTreeFrame} frame | |
799 */ | |
800 _discardFrame: function(frame) | |
801 { | |
802 var node = this._frameNodes.get(frame); | |
803 if (!node) | |
804 return; | |
805 | |
806 if (node.parent) | |
807 node.parent.removeChild(node); | |
808 this._frameNodes.delete(frame); | |
809 for (var child of frame.childFrames) | |
810 this._discardFrame(child); | |
811 }, | |
812 | |
813 /** | |
814 * @override | |
815 * @param {!WebInspector.Target} target | |
816 */ | |
817 targetAdded: function(target) | |
818 { | |
819 }, | |
820 | |
821 /** | |
822 * @override | |
823 * @param {!WebInspector.Target} target | |
824 */ | |
825 targetRemoved: function(target) | |
826 { | |
827 var targetNode = this._rootNode.child("target:" + target.id()); | |
828 if (targetNode) | |
829 this._rootNode.removeChild(targetNode); | |
830 }, | |
831 | |
832 /** | |
833 * @param {!WebInspector.Event} event | |
834 */ | |
835 _targetNameChanged: function(event) | |
836 { | |
837 var target = /** @type {!WebInspector.Target} */ (event.data); | |
838 var targetNode = this._rootNode.child("target:" + target.id()); | |
839 if (targetNode) | |
840 targetNode.setTitle(target.name()); | |
841 }, | |
842 | |
843 __proto__: WebInspector.VBox.prototype | |
844 }; | |
845 | |
846 /** | |
847 * @param {!TreeElement} treeElement1 | |
848 * @param {!TreeElement} treeElement2 | |
849 * @return {number} | |
850 */ | |
851 WebInspector.NavigatorView._treeElementsCompare = function compare(treeElement1,
treeElement2) | |
852 { | |
853 var typeWeight1 = WebInspector.NavigatorView._treeElementOrder(treeElement1)
; | 159 var typeWeight1 = WebInspector.NavigatorView._treeElementOrder(treeElement1)
; |
854 var typeWeight2 = WebInspector.NavigatorView._treeElementOrder(treeElement2)
; | 160 var typeWeight2 = WebInspector.NavigatorView._treeElementOrder(treeElement2)
; |
855 | 161 |
856 var result; | 162 var result; |
857 if (typeWeight1 > typeWeight2) | 163 if (typeWeight1 > typeWeight2) |
858 return 1; | 164 return 1; |
859 if (typeWeight1 < typeWeight2) | 165 if (typeWeight1 < typeWeight2) |
860 return -1; | 166 return -1; |
861 return treeElement1.titleAsText().compareTo(treeElement2.titleAsText()); | 167 return treeElement1.titleAsText().compareTo(treeElement2.titleAsText()); |
| 168 } |
| 169 |
| 170 /** |
| 171 * @param {!WebInspector.Event} event |
| 172 */ |
| 173 _onBindingCreated(event) { |
| 174 var binding = /** @type {!WebInspector.PersistenceBinding} */ (event.data); |
| 175 this._removeUISourceCode(binding.network); |
| 176 } |
| 177 |
| 178 /** |
| 179 * @param {!WebInspector.Event} event |
| 180 */ |
| 181 _onBindingRemoved(event) { |
| 182 var binding = /** @type {!WebInspector.PersistenceBinding} */ (event.data); |
| 183 this._addUISourceCode(binding.network); |
| 184 } |
| 185 |
| 186 /** |
| 187 * @param {!WebInspector.Event} event |
| 188 */ |
| 189 _onBindingChanged(event) { |
| 190 var binding = /** @type {!WebInspector.PersistenceBinding} */ (event.data); |
| 191 |
| 192 // Update UISourceCode titles. |
| 193 var networkNode = this._uiSourceCodeNodes.get(binding.network); |
| 194 if (networkNode) |
| 195 networkNode.updateTitle(); |
| 196 var fileSystemNode = this._uiSourceCodeNodes.get(binding.fileSystem); |
| 197 if (fileSystemNode) |
| 198 fileSystemNode.updateTitle(); |
| 199 |
| 200 // Update folder titles. |
| 201 var pathTokens = WebInspector.FileSystemWorkspaceBinding.relativePath(bindin
g.fileSystem); |
| 202 var folderPath = ''; |
| 203 for (var i = 0; i < pathTokens.length - 1; ++i) { |
| 204 folderPath += pathTokens[i]; |
| 205 var folderId = |
| 206 this._folderNodeId(binding.fileSystem.project(), null, null, binding.f
ileSystem.origin(), folderPath); |
| 207 var folderNode = this._subfolderNodes.get(folderId); |
| 208 if (folderNode) |
| 209 folderNode.updateTitle(); |
| 210 folderPath += '/'; |
| 211 } |
| 212 |
| 213 // Update fileSystem root title. |
| 214 var fileSystemRoot = this._rootNode.child(binding.fileSystem.project().id())
; |
| 215 if (fileSystemRoot) |
| 216 fileSystemRoot.updateTitle(); |
| 217 } |
| 218 |
| 219 /** |
| 220 * @override |
| 221 */ |
| 222 focus() { |
| 223 this._scriptsTree.focus(); |
| 224 } |
| 225 |
| 226 /** |
| 227 * @param {!WebInspector.Workspace} workspace |
| 228 */ |
| 229 _resetWorkspace(workspace) { |
| 230 this._workspace = workspace; |
| 231 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeA
dded, this._uiSourceCodeAdded, this); |
| 232 this._workspace.addEventListener( |
| 233 WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRem
oved, this); |
| 234 this._workspace.addEventListener( |
| 235 WebInspector.Workspace.Events.ProjectRemoved, this._projectRemoved.bind(
this), this); |
| 236 } |
| 237 |
| 238 /** |
| 239 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 240 * @return {boolean} |
| 241 */ |
| 242 accept(uiSourceCode) { |
| 243 return !uiSourceCode.isFromServiceProject(); |
| 244 } |
| 245 |
| 246 /** |
| 247 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 248 * @return {?WebInspector.ResourceTreeFrame} |
| 249 */ |
| 250 _uiSourceCodeFrame(uiSourceCode) { |
| 251 var frame = WebInspector.NetworkProject.frameForProject(uiSourceCode.project
()); |
| 252 if (!frame) { |
| 253 var target = WebInspector.NetworkProject.targetForProject(uiSourceCode.pro
ject()); |
| 254 var resourceTreeModel = target && WebInspector.ResourceTreeModel.fromTarge
t(target); |
| 255 frame = resourceTreeModel && resourceTreeModel.mainFrame; |
| 256 } |
| 257 return frame; |
| 258 } |
| 259 |
| 260 /** |
| 261 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 262 */ |
| 263 _addUISourceCode(uiSourceCode) { |
| 264 if (!this.accept(uiSourceCode)) |
| 265 return; |
| 266 |
| 267 var binding = WebInspector.persistence.binding(uiSourceCode); |
| 268 if (!Runtime.experiments.isEnabled('persistence2') && binding && binding.net
work === uiSourceCode) |
| 269 return; |
| 270 |
| 271 var isFromSourceMap = uiSourceCode.contentType().isFromSourceMap(); |
| 272 var path; |
| 273 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) |
| 274 path = WebInspector.FileSystemWorkspaceBinding.relativePath(uiSourceCode).
slice(0, -1); |
| 275 else |
| 276 path = WebInspector.ParsedURL.extractPath(uiSourceCode.url()).split('/').s
lice(1, -1); |
| 277 |
| 278 var project = uiSourceCode.project(); |
| 279 var target = WebInspector.NetworkProject.targetForUISourceCode(uiSourceCode)
; |
| 280 var frame = this._uiSourceCodeFrame(uiSourceCode); |
| 281 |
| 282 var folderNode = |
| 283 this._folderNode(uiSourceCode, project, target, frame, uiSourceCode.orig
in(), path, isFromSourceMap); |
| 284 var uiSourceCodeNode = new WebInspector.NavigatorUISourceCodeTreeNode(this,
uiSourceCode); |
| 285 this._uiSourceCodeNodes.set(uiSourceCode, uiSourceCodeNode); |
| 286 folderNode.appendChild(uiSourceCodeNode); |
| 287 this.uiSourceCodeAdded(uiSourceCode); |
| 288 } |
| 289 |
| 290 /** |
| 291 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 292 */ |
| 293 uiSourceCodeAdded(uiSourceCode) { |
| 294 } |
| 295 |
| 296 /** |
| 297 * @param {!WebInspector.Event} event |
| 298 */ |
| 299 _uiSourceCodeAdded(event) { |
| 300 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); |
| 301 this._addUISourceCode(uiSourceCode); |
| 302 } |
| 303 |
| 304 /** |
| 305 * @param {!WebInspector.Event} event |
| 306 */ |
| 307 _uiSourceCodeRemoved(event) { |
| 308 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data); |
| 309 this._removeUISourceCode(uiSourceCode); |
| 310 } |
| 311 |
| 312 /** |
| 313 * @param {!WebInspector.Event} event |
| 314 */ |
| 315 _projectRemoved(event) { |
| 316 var project = /** @type {!WebInspector.Project} */ (event.data); |
| 317 |
| 318 var frame = WebInspector.NetworkProject.frameForProject(project); |
| 319 if (frame) |
| 320 this._discardFrame(frame); |
| 321 |
| 322 var uiSourceCodes = project.uiSourceCodes(); |
| 323 for (var i = 0; i < uiSourceCodes.length; ++i) |
| 324 this._removeUISourceCode(uiSourceCodes[i]); |
| 325 } |
| 326 |
| 327 /** |
| 328 * @param {!WebInspector.Project} project |
| 329 * @param {?WebInspector.Target} target |
| 330 * @param {?WebInspector.ResourceTreeFrame} frame |
| 331 * @param {string} projectOrigin |
| 332 * @param {string} path |
| 333 * @return {string} |
| 334 */ |
| 335 _folderNodeId(project, target, frame, projectOrigin, path) { |
| 336 var targetId = target ? target.id() : ''; |
| 337 var projectId = project.type() === WebInspector.projectTypes.FileSystem ? pr
oject.id() : ''; |
| 338 var frameId = this._groupByFrame && frame ? frame.id : ''; |
| 339 return targetId + ':' + projectId + ':' + frameId + ':' + projectOrigin + ':
' + path; |
| 340 } |
| 341 |
| 342 /** |
| 343 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 344 * @param {!WebInspector.Project} project |
| 345 * @param {?WebInspector.Target} target |
| 346 * @param {?WebInspector.ResourceTreeFrame} frame |
| 347 * @param {string} projectOrigin |
| 348 * @param {!Array<string>} path |
| 349 * @param {boolean} fromSourceMap |
| 350 * @return {!WebInspector.NavigatorTreeNode} |
| 351 */ |
| 352 _folderNode(uiSourceCode, project, target, frame, projectOrigin, path, fromSou
rceMap) { |
| 353 if (project.type() === WebInspector.projectTypes.Snippets) |
| 354 return this._rootNode; |
| 355 |
| 356 if (target && !this._groupByFolder && !fromSourceMap) |
| 357 return this._domainNode(uiSourceCode, project, target, frame, projectOrigi
n); |
| 358 |
| 359 var folderPath = path.join('/'); |
| 360 var folderId = this._folderNodeId(project, target, frame, projectOrigin, fol
derPath); |
| 361 var folderNode = this._subfolderNodes.get(folderId); |
| 362 if (folderNode) |
| 363 return folderNode; |
| 364 |
| 365 if (!path.length) { |
| 366 if (target) |
| 367 return this._domainNode(uiSourceCode, project, target, frame, projectOri
gin); |
| 368 var fileSystemNode = this._rootNode.child(project.id()); |
| 369 if (!fileSystemNode) { |
| 370 fileSystemNode = new WebInspector.NavigatorGroupTreeNode( |
| 371 this, project, project.id(), WebInspector.NavigatorView.Types.FileSy
stem, project.displayName()); |
| 372 this._rootNode.appendChild(fileSystemNode); |
| 373 } |
| 374 return fileSystemNode; |
| 375 } |
| 376 |
| 377 var parentNode = |
| 378 this._folderNode(uiSourceCode, project, target, frame, projectOrigin, pa
th.slice(0, -1), fromSourceMap); |
| 379 var type = fromSourceMap ? WebInspector.NavigatorView.Types.SourceMapFolder
: |
| 380 WebInspector.NavigatorView.Types.NetworkFolder; |
| 381 if (project.type() === WebInspector.projectTypes.FileSystem) |
| 382 type = WebInspector.NavigatorView.Types.FileSystemFolder; |
| 383 var name = path[path.length - 1]; |
| 384 |
| 385 folderNode = new WebInspector.NavigatorFolderTreeNode(this, project, folderI
d, type, folderPath, name); |
| 386 this._subfolderNodes.set(folderId, folderNode); |
| 387 parentNode.appendChild(folderNode); |
| 388 return folderNode; |
| 389 } |
| 390 |
| 391 /** |
| 392 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 393 * @param {!WebInspector.Project} project |
| 394 * @param {!WebInspector.Target} target |
| 395 * @param {?WebInspector.ResourceTreeFrame} frame |
| 396 * @param {string} projectOrigin |
| 397 * @return {!WebInspector.NavigatorTreeNode} |
| 398 */ |
| 399 _domainNode(uiSourceCode, project, target, frame, projectOrigin) { |
| 400 var frameNode = this._frameNode(project, target, frame); |
| 401 if (!this._groupByDomain) |
| 402 return frameNode; |
| 403 var domainNode = frameNode.child(projectOrigin); |
| 404 if (domainNode) |
| 405 return domainNode; |
| 406 |
| 407 domainNode = new WebInspector.NavigatorGroupTreeNode( |
| 408 this, project, projectOrigin, WebInspector.NavigatorView.Types.Domain, |
| 409 this._computeProjectDisplayName(target, projectOrigin)); |
| 410 if (frame && projectOrigin === WebInspector.ParsedURL.extractOrigin(frame.ur
l)) |
| 411 domainNode.treeNode()._boostOrder = true; |
| 412 frameNode.appendChild(domainNode); |
| 413 return domainNode; |
| 414 } |
| 415 |
| 416 /** |
| 417 * @param {!WebInspector.Project} project |
| 418 * @param {!WebInspector.Target} target |
| 419 * @param {?WebInspector.ResourceTreeFrame} frame |
| 420 * @return {!WebInspector.NavigatorTreeNode} |
| 421 */ |
| 422 _frameNode(project, target, frame) { |
| 423 if (!this._groupByFrame || !frame) |
| 424 return this._targetNode(project, target); |
| 425 |
| 426 var frameNode = this._frameNodes.get(frame); |
| 427 if (frameNode) |
| 428 return frameNode; |
| 429 |
| 430 frameNode = new WebInspector.NavigatorGroupTreeNode( |
| 431 this, project, target.id() + ':' + frame.id, WebInspector.NavigatorView.
Types.Frame, frame.displayName()); |
| 432 frameNode.setHoverCallback(hoverCallback); |
| 433 this._frameNodes.set(frame, frameNode); |
| 434 this._frameNode(project, target, frame.parentFrame).appendChild(frameNode); |
| 435 if (!frame.parentFrame) |
| 436 frameNode.treeNode()._boostOrder = true; |
| 437 |
| 438 /** |
| 439 * @param {boolean} hovered |
| 440 */ |
| 441 function hoverCallback(hovered) { |
| 442 if (hovered) { |
| 443 var domModel = WebInspector.DOMModel.fromTarget(target); |
| 444 if (domModel) |
| 445 domModel.highlightFrame(frame.id); |
| 446 } else { |
| 447 WebInspector.DOMModel.hideDOMNodeHighlight(); |
| 448 } |
| 449 } |
| 450 return frameNode; |
| 451 } |
| 452 |
| 453 /** |
| 454 * @param {!WebInspector.Project} project |
| 455 * @param {!WebInspector.Target} target |
| 456 * @return {!WebInspector.NavigatorTreeNode} |
| 457 */ |
| 458 _targetNode(project, target) { |
| 459 if (target === WebInspector.targetManager.mainTarget()) |
| 460 return this._rootNode; |
| 461 |
| 462 var targetNode = this._rootNode.child('target:' + target.id()); |
| 463 if (!targetNode) { |
| 464 targetNode = new WebInspector.NavigatorGroupTreeNode( |
| 465 this, project, 'target:' + target.id(), |
| 466 !target.hasBrowserCapability() ? WebInspector.NavigatorView.Types.Work
er : |
| 467 WebInspector.NavigatorView.Types.Netw
orkFolder, |
| 468 target.name()); |
| 469 this._rootNode.appendChild(targetNode); |
| 470 } |
| 471 return targetNode; |
| 472 } |
| 473 |
| 474 /** |
| 475 * @param {!WebInspector.Target} target |
| 476 * @param {string} projectOrigin |
| 477 * @return {string} |
| 478 */ |
| 479 _computeProjectDisplayName(target, projectOrigin) { |
| 480 for (var context of target.runtimeModel.executionContexts()) { |
| 481 if (context.name && context.origin && projectOrigin.startsWith(context.ori
gin)) |
| 482 return context.name; |
| 483 } |
| 484 |
| 485 if (!projectOrigin) |
| 486 return WebInspector.UIString('(no domain)'); |
| 487 |
| 488 var parsedURL = new WebInspector.ParsedURL(projectOrigin); |
| 489 var prettyURL = parsedURL.isValid ? parsedURL.host + (parsedURL.port ? (':'
+ parsedURL.port) : '') : ''; |
| 490 |
| 491 return (prettyURL || projectOrigin); |
| 492 } |
| 493 |
| 494 /** |
| 495 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 496 * @param {boolean=} select |
| 497 */ |
| 498 revealUISourceCode(uiSourceCode, select) { |
| 499 var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| 500 if (!node) |
| 501 return; |
| 502 if (this._scriptsTree.selectedTreeElement) |
| 503 this._scriptsTree.selectedTreeElement.deselect(); |
| 504 this._lastSelectedUISourceCode = uiSourceCode; |
| 505 node.reveal(select); |
| 506 } |
| 507 |
| 508 /** |
| 509 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 510 * @param {boolean} focusSource |
| 511 */ |
| 512 _sourceSelected(uiSourceCode, focusSource) { |
| 513 this._lastSelectedUISourceCode = uiSourceCode; |
| 514 WebInspector.Revealer.reveal(uiSourceCode, !focusSource); |
| 515 } |
| 516 |
| 517 /** |
| 518 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 519 */ |
| 520 sourceDeleted(uiSourceCode) { |
| 521 } |
| 522 |
| 523 /** |
| 524 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 525 */ |
| 526 _removeUISourceCode(uiSourceCode) { |
| 527 var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| 528 if (!node) |
| 529 return; |
| 530 |
| 531 var project = uiSourceCode.project(); |
| 532 var target = WebInspector.NetworkProject.targetForUISourceCode(uiSourceCode)
; |
| 533 var frame = this._uiSourceCodeFrame(uiSourceCode); |
| 534 |
| 535 var parentNode = node.parent; |
| 536 this._uiSourceCodeNodes.delete(uiSourceCode); |
| 537 parentNode.removeChild(node); |
| 538 node = parentNode; |
| 539 |
| 540 while (node) { |
| 541 parentNode = node.parent; |
| 542 if (!parentNode || !node.isEmpty()) |
| 543 break; |
| 544 if (!(node instanceof WebInspector.NavigatorGroupTreeNode || |
| 545 node instanceof WebInspector.NavigatorFolderTreeNode)) |
| 546 break; |
| 547 if (node._type === WebInspector.NavigatorView.Types.Frame) |
| 548 break; |
| 549 |
| 550 var folderId = this._folderNodeId(project, target, frame, uiSourceCode.ori
gin(), node._folderPath); |
| 551 this._subfolderNodes.delete(folderId); |
| 552 parentNode.removeChild(node); |
| 553 node = parentNode; |
| 554 } |
| 555 } |
| 556 |
| 557 reset() { |
| 558 var nodes = this._uiSourceCodeNodes.valuesArray(); |
| 559 for (var i = 0; i < nodes.length; ++i) |
| 560 nodes[i].dispose(); |
| 561 |
| 562 this._scriptsTree.removeChildren(); |
| 563 this._uiSourceCodeNodes.clear(); |
| 564 this._subfolderNodes.clear(); |
| 565 this._frameNodes.clear(); |
| 566 this._rootNode.reset(); |
| 567 } |
| 568 |
| 569 /** |
| 570 * @param {!Event} event |
| 571 */ |
| 572 handleContextMenu(event) { |
| 573 } |
| 574 |
| 575 /** |
| 576 * @param {!WebInspector.Project} project |
| 577 * @param {string} path |
| 578 * @param {!WebInspector.UISourceCode=} uiSourceCode |
| 579 */ |
| 580 _handleContextMenuCreate(project, path, uiSourceCode) { |
| 581 this.create(project, path, uiSourceCode); |
| 582 } |
| 583 |
| 584 /** |
| 585 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 586 */ |
| 587 _handleContextMenuRename(uiSourceCode) { |
| 588 this.rename(uiSourceCode, false); |
| 589 } |
| 590 |
| 591 /** |
| 592 * @param {!WebInspector.Project} project |
| 593 * @param {string} path |
| 594 */ |
| 595 _handleContextMenuExclude(project, path) { |
| 596 var shouldExclude = window.confirm(WebInspector.UIString('Are you sure you w
ant to exclude this folder?')); |
| 597 if (shouldExclude) { |
| 598 WebInspector.startBatchUpdate(); |
| 599 project.excludeFolder(WebInspector.FileSystemWorkspaceBinding.completeURL(
project, path)); |
| 600 WebInspector.endBatchUpdate(); |
| 601 } |
| 602 } |
| 603 |
| 604 /** |
| 605 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 606 */ |
| 607 _handleContextMenuDelete(uiSourceCode) { |
| 608 var shouldDelete = window.confirm(WebInspector.UIString('Are you sure you wa
nt to delete this file?')); |
| 609 if (shouldDelete) |
| 610 uiSourceCode.project().deleteFile(uiSourceCode.url()); |
| 611 } |
| 612 |
| 613 /** |
| 614 * @param {!Event} event |
| 615 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 616 */ |
| 617 handleFileContextMenu(event, uiSourceCode) { |
| 618 var contextMenu = new WebInspector.ContextMenu(event); |
| 619 contextMenu.appendApplicableItems(uiSourceCode); |
| 620 contextMenu.appendSeparator(); |
| 621 |
| 622 var project = uiSourceCode.project(); |
| 623 if (project.type() === WebInspector.projectTypes.FileSystem) { |
| 624 var parentURL = uiSourceCode.parentURL(); |
| 625 contextMenu.appendItem( |
| 626 WebInspector.UIString('Rename\u2026'), this._handleContextMenuRename.b
ind(this, uiSourceCode)); |
| 627 contextMenu.appendItem( |
| 628 WebInspector.UIString('Make a copy\u2026'), |
| 629 this._handleContextMenuCreate.bind(this, project, parentURL, uiSourceC
ode)); |
| 630 contextMenu.appendItem(WebInspector.UIString('Delete'), this._handleContex
tMenuDelete.bind(this, uiSourceCode)); |
| 631 contextMenu.appendSeparator(); |
| 632 } |
| 633 |
| 634 contextMenu.show(); |
| 635 } |
| 636 |
| 637 /** |
| 638 * @param {!Event} event |
| 639 * @param {!WebInspector.NavigatorFolderTreeNode} node |
| 640 */ |
| 641 handleFolderContextMenu(event, node) { |
| 642 var path = node._folderPath; |
| 643 var project = node._project; |
| 644 |
| 645 var contextMenu = new WebInspector.ContextMenu(event); |
| 646 |
| 647 WebInspector.NavigatorView.appendSearchItem(contextMenu, path); |
| 648 contextMenu.appendSeparator(); |
| 649 |
| 650 if (project.type() !== WebInspector.projectTypes.FileSystem) |
| 651 return; |
| 652 |
| 653 contextMenu.appendItem(WebInspector.UIString('New file'), this._handleContex
tMenuCreate.bind(this, project, path)); |
| 654 contextMenu.appendItem( |
| 655 WebInspector.UIString('Exclude folder'), this._handleContextMenuExclude.
bind(this, project, path)); |
| 656 |
| 657 function removeFolder() { |
| 658 var shouldRemove = window.confirm(WebInspector.UIString('Are you sure you
want to remove this folder?')); |
| 659 if (shouldRemove) |
| 660 project.remove(); |
| 661 } |
| 662 |
| 663 contextMenu.appendSeparator(); |
| 664 WebInspector.NavigatorView.appendAddFolderItem(contextMenu); |
| 665 if (node instanceof WebInspector.NavigatorGroupTreeNode) |
| 666 contextMenu.appendItem(WebInspector.UIString('Remove folder from workspace
'), removeFolder); |
| 667 |
| 668 contextMenu.show(); |
| 669 } |
| 670 |
| 671 /** |
| 672 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 673 * @param {boolean} deleteIfCanceled |
| 674 */ |
| 675 rename(uiSourceCode, deleteIfCanceled) { |
| 676 var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| 677 console.assert(node); |
| 678 node.rename(callback.bind(this)); |
| 679 |
| 680 /** |
| 681 * @this {WebInspector.NavigatorView} |
| 682 * @param {boolean} committed |
| 683 */ |
| 684 function callback(committed) { |
| 685 if (!committed) { |
| 686 if (deleteIfCanceled) |
| 687 uiSourceCode.remove(); |
| 688 return; |
| 689 } |
| 690 |
| 691 this._sourceSelected(uiSourceCode, true); |
| 692 } |
| 693 } |
| 694 |
| 695 /** |
| 696 * @param {!WebInspector.Project} project |
| 697 * @param {string} path |
| 698 * @param {!WebInspector.UISourceCode=} uiSourceCodeToCopy |
| 699 */ |
| 700 create(project, path, uiSourceCodeToCopy) { |
| 701 var filePath; |
| 702 var uiSourceCode; |
| 703 |
| 704 /** |
| 705 * @this {WebInspector.NavigatorView} |
| 706 * @param {?string} content |
| 707 */ |
| 708 function contentLoaded(content) { |
| 709 createFile.call(this, content || ''); |
| 710 } |
| 711 |
| 712 if (uiSourceCodeToCopy) |
| 713 uiSourceCodeToCopy.requestContent().then(contentLoaded.bind(this)); |
| 714 else |
| 715 createFile.call(this); |
| 716 |
| 717 /** |
| 718 * @this {WebInspector.NavigatorView} |
| 719 * @param {string=} content |
| 720 */ |
| 721 function createFile(content) { |
| 722 project.createFile(path, null, content || '', fileCreated.bind(this)); |
| 723 } |
| 724 |
| 725 /** |
| 726 * @this {WebInspector.NavigatorView} |
| 727 * @param {?WebInspector.UISourceCode} uiSourceCode |
| 728 */ |
| 729 function fileCreated(uiSourceCode) { |
| 730 if (!uiSourceCode) |
| 731 return; |
| 732 this._sourceSelected(uiSourceCode, false); |
| 733 this.revealUISourceCode(uiSourceCode, true); |
| 734 this.rename(uiSourceCode, true); |
| 735 } |
| 736 } |
| 737 |
| 738 _groupingChanged() { |
| 739 this.reset(); |
| 740 this._initGrouping(); |
| 741 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); |
| 742 } |
| 743 |
| 744 _initGrouping() { |
| 745 this._groupByFrame = true; |
| 746 this._groupByDomain = this._navigatorGroupByFolderSetting.get(); |
| 747 this._groupByFolder = this._groupByDomain; |
| 748 } |
| 749 |
| 750 _resetForTest() { |
| 751 this.reset(); |
| 752 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); |
| 753 } |
| 754 |
| 755 /** |
| 756 * @param {!WebInspector.Event} event |
| 757 */ |
| 758 _frameNavigated(event) { |
| 759 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); |
| 760 var node = this._frameNodes.get(frame); |
| 761 if (!node) |
| 762 return; |
| 763 |
| 764 node.treeNode().title = frame.displayName(); |
| 765 for (var child of frame.childFrames) |
| 766 this._discardFrame(child); |
| 767 } |
| 768 |
| 769 /** |
| 770 * @param {!WebInspector.Event} event |
| 771 */ |
| 772 _frameDetached(event) { |
| 773 var frame = /** @type {!WebInspector.ResourceTreeFrame} */ (event.data); |
| 774 this._discardFrame(frame); |
| 775 } |
| 776 |
| 777 /** |
| 778 * @param {!WebInspector.ResourceTreeFrame} frame |
| 779 */ |
| 780 _discardFrame(frame) { |
| 781 var node = this._frameNodes.get(frame); |
| 782 if (!node) |
| 783 return; |
| 784 |
| 785 if (node.parent) |
| 786 node.parent.removeChild(node); |
| 787 this._frameNodes.delete(frame); |
| 788 for (var child of frame.childFrames) |
| 789 this._discardFrame(child); |
| 790 } |
| 791 |
| 792 /** |
| 793 * @override |
| 794 * @param {!WebInspector.Target} target |
| 795 */ |
| 796 targetAdded(target) { |
| 797 } |
| 798 |
| 799 /** |
| 800 * @override |
| 801 * @param {!WebInspector.Target} target |
| 802 */ |
| 803 targetRemoved(target) { |
| 804 var targetNode = this._rootNode.child('target:' + target.id()); |
| 805 if (targetNode) |
| 806 this._rootNode.removeChild(targetNode); |
| 807 } |
| 808 |
| 809 /** |
| 810 * @param {!WebInspector.Event} event |
| 811 */ |
| 812 _targetNameChanged(event) { |
| 813 var target = /** @type {!WebInspector.Target} */ (event.data); |
| 814 var targetNode = this._rootNode.child('target:' + target.id()); |
| 815 if (targetNode) |
| 816 targetNode.setTitle(target.name()); |
| 817 } |
862 }; | 818 }; |
863 | 819 |
| 820 WebInspector.NavigatorView.Types = { |
| 821 Category: 'category', |
| 822 Domain: 'domain', |
| 823 File: 'file', |
| 824 FileSystem: 'fs', |
| 825 FileSystemFolder: 'fs-folder', |
| 826 Frame: 'frame', |
| 827 NetworkFolder: 'nw-folder', |
| 828 Root: 'root', |
| 829 SourceMapFolder: 'sm-folder', |
| 830 Worker: 'worker' |
| 831 }; |
| 832 |
| 833 |
864 /** | 834 /** |
865 * @constructor | 835 * @unrestricted |
866 * @extends {TreeElement} | |
867 * @param {!WebInspector.NavigatorView} navigatorView | |
868 * @param {string} type | |
869 * @param {string} title | |
870 * @param {function(boolean)=} hoverCallback | |
871 */ | 836 */ |
872 WebInspector.NavigatorFolderTreeElement = function(navigatorView, type, title, h
overCallback) | 837 WebInspector.NavigatorFolderTreeElement = class extends TreeElement { |
873 { | 838 /** |
874 TreeElement.call(this, "", true); | 839 * @param {!WebInspector.NavigatorView} navigatorView |
875 this.listItemElement.classList.add("navigator-" + type + "-tree-item", "navi
gator-folder-tree-item"); | 840 * @param {string} type |
| 841 * @param {string} title |
| 842 * @param {function(boolean)=} hoverCallback |
| 843 */ |
| 844 constructor(navigatorView, type, title, hoverCallback) { |
| 845 super('', true); |
| 846 this.listItemElement.classList.add('navigator-' + type + '-tree-item', 'navi
gator-folder-tree-item'); |
876 this._nodeType = type; | 847 this._nodeType = type; |
877 this.title = title; | 848 this.title = title; |
878 this.tooltip = title; | 849 this.tooltip = title; |
879 this.createIcon(); | 850 this.createIcon(); |
880 this._navigatorView = navigatorView; | 851 this._navigatorView = navigatorView; |
881 this._hoverCallback = hoverCallback; | 852 this._hoverCallback = hoverCallback; |
| 853 } |
| 854 |
| 855 /** |
| 856 * @override |
| 857 */ |
| 858 onpopulate() { |
| 859 this._node.populate(); |
| 860 } |
| 861 |
| 862 /** |
| 863 * @override |
| 864 */ |
| 865 onattach() { |
| 866 this.collapse(); |
| 867 this._node.onattach(); |
| 868 this.listItemElement.addEventListener('contextmenu', this._handleContextMenu
Event.bind(this), false); |
| 869 this.listItemElement.addEventListener('mousemove', this._mouseMove.bind(this
), false); |
| 870 this.listItemElement.addEventListener('mouseleave', this._mouseLeave.bind(th
is), false); |
| 871 } |
| 872 |
| 873 /** |
| 874 * @param {!WebInspector.NavigatorTreeNode} node |
| 875 */ |
| 876 setNode(node) { |
| 877 this._node = node; |
| 878 var paths = []; |
| 879 while (node && !node.isRoot()) { |
| 880 paths.push(node._title); |
| 881 node = node.parent; |
| 882 } |
| 883 paths.reverse(); |
| 884 this.tooltip = paths.join('/'); |
| 885 } |
| 886 |
| 887 /** |
| 888 * @param {!Event} event |
| 889 */ |
| 890 _handleContextMenuEvent(event) { |
| 891 if (!this._node) |
| 892 return; |
| 893 this.select(); |
| 894 this._navigatorView.handleFolderContextMenu(event, this._node); |
| 895 } |
| 896 |
| 897 /** |
| 898 * @param {!Event} event |
| 899 */ |
| 900 _mouseMove(event) { |
| 901 if (this._hovered || !this._hoverCallback) |
| 902 return; |
| 903 this._hovered = true; |
| 904 this._hoverCallback(true); |
| 905 } |
| 906 |
| 907 /** |
| 908 * @param {!Event} event |
| 909 */ |
| 910 _mouseLeave(event) { |
| 911 if (!this._hoverCallback) |
| 912 return; |
| 913 this._hovered = false; |
| 914 this._hoverCallback(false); |
| 915 } |
882 }; | 916 }; |
883 | 917 |
884 WebInspector.NavigatorFolderTreeElement.prototype = { | |
885 onpopulate: function() | |
886 { | |
887 this._node.populate(); | |
888 }, | |
889 | |
890 onattach: function() | |
891 { | |
892 this.collapse(); | |
893 this._node.onattach(); | |
894 this.listItemElement.addEventListener("contextmenu", this._handleContext
MenuEvent.bind(this), false); | |
895 this.listItemElement.addEventListener("mousemove", this._mouseMove.bind(
this), false); | |
896 this.listItemElement.addEventListener("mouseleave", this._mouseLeave.bin
d(this), false); | |
897 }, | |
898 | |
899 /** | |
900 * @param {!WebInspector.NavigatorTreeNode} node | |
901 */ | |
902 setNode: function(node) | |
903 { | |
904 this._node = node; | |
905 var paths = []; | |
906 while (node && !node.isRoot()) { | |
907 paths.push(node._title); | |
908 node = node.parent; | |
909 } | |
910 paths.reverse(); | |
911 this.tooltip = paths.join("/"); | |
912 }, | |
913 | |
914 /** | |
915 * @param {!Event} event | |
916 */ | |
917 _handleContextMenuEvent: function(event) | |
918 { | |
919 if (!this._node) | |
920 return; | |
921 this.select(); | |
922 this._navigatorView.handleFolderContextMenu(event, this._node); | |
923 }, | |
924 | |
925 /** | |
926 * @param {!Event} event | |
927 */ | |
928 _mouseMove: function(event) | |
929 { | |
930 if (this._hovered || !this._hoverCallback) | |
931 return; | |
932 this._hovered = true; | |
933 this._hoverCallback(true); | |
934 }, | |
935 | |
936 /** | |
937 * @param {!Event} event | |
938 */ | |
939 _mouseLeave: function(event) | |
940 { | |
941 if (!this._hoverCallback) | |
942 return; | |
943 this._hovered = false; | |
944 this._hoverCallback(false); | |
945 }, | |
946 | |
947 __proto__: TreeElement.prototype | |
948 }; | |
949 | |
950 /** | 918 /** |
951 * @constructor | 919 * @unrestricted |
952 * @extends {TreeElement} | |
953 * @param {!WebInspector.NavigatorView} navigatorView | |
954 * @param {!WebInspector.UISourceCode} uiSourceCode | |
955 * @param {string} title | |
956 */ | 920 */ |
957 WebInspector.NavigatorSourceTreeElement = function(navigatorView, uiSourceCode,
title) | 921 WebInspector.NavigatorSourceTreeElement = class extends TreeElement { |
958 { | 922 /** |
959 TreeElement.call(this, "", false); | 923 * @param {!WebInspector.NavigatorView} navigatorView |
| 924 * @param {!WebInspector.UISourceCode} uiSourceCode |
| 925 * @param {string} title |
| 926 */ |
| 927 constructor(navigatorView, uiSourceCode, title) { |
| 928 super('', false); |
960 this._nodeType = WebInspector.NavigatorView.Types.File; | 929 this._nodeType = WebInspector.NavigatorView.Types.File; |
961 this.title = title; | 930 this.title = title; |
962 this.listItemElement.classList.add("navigator-" + uiSourceCode.contentType()
.name() + "-tree-item", "navigator-file-tree-item"); | 931 this.listItemElement.classList.add( |
| 932 'navigator-' + uiSourceCode.contentType().name() + '-tree-item', 'naviga
tor-file-tree-item'); |
963 this.tooltip = uiSourceCode.url(); | 933 this.tooltip = uiSourceCode.url(); |
964 this.createIcon(); | 934 this.createIcon(); |
965 | 935 |
966 this._navigatorView = navigatorView; | 936 this._navigatorView = navigatorView; |
967 this._uiSourceCode = uiSourceCode; | 937 this._uiSourceCode = uiSourceCode; |
| 938 } |
| 939 |
| 940 /** |
| 941 * @return {!WebInspector.UISourceCode} |
| 942 */ |
| 943 get uiSourceCode() { |
| 944 return this._uiSourceCode; |
| 945 } |
| 946 |
| 947 /** |
| 948 * @override |
| 949 */ |
| 950 onattach() { |
| 951 this.listItemElement.draggable = true; |
| 952 this.listItemElement.addEventListener('click', this._onclick.bind(this), fal
se); |
| 953 this.listItemElement.addEventListener('contextmenu', this._handleContextMenu
Event.bind(this), false); |
| 954 this.listItemElement.addEventListener('mousedown', this._onmousedown.bind(th
is), false); |
| 955 this.listItemElement.addEventListener('dragstart', this._ondragstart.bind(th
is), false); |
| 956 } |
| 957 |
| 958 _onmousedown(event) { |
| 959 if (event.which === 1) // Warm-up data for drag'n'drop |
| 960 this._uiSourceCode.requestContent().then(callback.bind(this)); |
| 961 /** |
| 962 * @param {?string} content |
| 963 * @this {WebInspector.NavigatorSourceTreeElement} |
| 964 */ |
| 965 function callback(content) { |
| 966 this._warmedUpContent = content; |
| 967 } |
| 968 } |
| 969 |
| 970 _shouldRenameOnMouseDown() { |
| 971 if (!this._uiSourceCode.canRename()) |
| 972 return false; |
| 973 var isSelected = this === this.treeOutline.selectedTreeElement; |
| 974 return isSelected && this.treeOutline.element.hasFocus() && !WebInspector.is
BeingEdited(this.treeOutline.element); |
| 975 } |
| 976 |
| 977 /** |
| 978 * @override |
| 979 */ |
| 980 selectOnMouseDown(event) { |
| 981 if (event.which !== 1 || !this._shouldRenameOnMouseDown()) { |
| 982 super.selectOnMouseDown(event); |
| 983 return; |
| 984 } |
| 985 setTimeout(rename.bind(this), 300); |
| 986 |
| 987 /** |
| 988 * @this {WebInspector.NavigatorSourceTreeElement} |
| 989 */ |
| 990 function rename() { |
| 991 if (this._shouldRenameOnMouseDown()) |
| 992 this._navigatorView.rename(this.uiSourceCode, false); |
| 993 } |
| 994 } |
| 995 |
| 996 _ondragstart(event) { |
| 997 event.dataTransfer.setData('text/plain', this._warmedUpContent); |
| 998 event.dataTransfer.effectAllowed = 'copy'; |
| 999 return true; |
| 1000 } |
| 1001 |
| 1002 /** |
| 1003 * @override |
| 1004 * @return {boolean} |
| 1005 */ |
| 1006 onspace() { |
| 1007 this._navigatorView._sourceSelected(this.uiSourceCode, true); |
| 1008 return true; |
| 1009 } |
| 1010 |
| 1011 /** |
| 1012 * @param {!Event} event |
| 1013 */ |
| 1014 _onclick(event) { |
| 1015 this._navigatorView._sourceSelected(this.uiSourceCode, false); |
| 1016 } |
| 1017 |
| 1018 /** |
| 1019 * @override |
| 1020 * @return {boolean} |
| 1021 */ |
| 1022 ondblclick(event) { |
| 1023 var middleClick = event.button === 1; |
| 1024 this._navigatorView._sourceSelected(this.uiSourceCode, !middleClick); |
| 1025 return false; |
| 1026 } |
| 1027 |
| 1028 /** |
| 1029 * @override |
| 1030 * @return {boolean} |
| 1031 */ |
| 1032 onenter() { |
| 1033 this._navigatorView._sourceSelected(this.uiSourceCode, true); |
| 1034 return true; |
| 1035 } |
| 1036 |
| 1037 /** |
| 1038 * @override |
| 1039 * @return {boolean} |
| 1040 */ |
| 1041 ondelete() { |
| 1042 this._navigatorView.sourceDeleted(this.uiSourceCode); |
| 1043 return true; |
| 1044 } |
| 1045 |
| 1046 /** |
| 1047 * @param {!Event} event |
| 1048 */ |
| 1049 _handleContextMenuEvent(event) { |
| 1050 this.select(); |
| 1051 this._navigatorView.handleFileContextMenu(event, this._uiSourceCode); |
| 1052 } |
968 }; | 1053 }; |
969 | 1054 |
970 WebInspector.NavigatorSourceTreeElement.prototype = { | |
971 /** | |
972 * @return {!WebInspector.UISourceCode} | |
973 */ | |
974 get uiSourceCode() | |
975 { | |
976 return this._uiSourceCode; | |
977 }, | |
978 | |
979 onattach: function() | |
980 { | |
981 this.listItemElement.draggable = true; | |
982 this.listItemElement.addEventListener("click", this._onclick.bind(this),
false); | |
983 this.listItemElement.addEventListener("contextmenu", this._handleContext
MenuEvent.bind(this), false); | |
984 this.listItemElement.addEventListener("mousedown", this._onmousedown.bin
d(this), false); | |
985 this.listItemElement.addEventListener("dragstart", this._ondragstart.bin
d(this), false); | |
986 }, | |
987 | |
988 _onmousedown: function(event) | |
989 { | |
990 if (event.which === 1) // Warm-up data for drag'n'drop | |
991 this._uiSourceCode.requestContent().then(callback.bind(this)); | |
992 /** | |
993 * @param {?string} content | |
994 * @this {WebInspector.NavigatorSourceTreeElement} | |
995 */ | |
996 function callback(content) | |
997 { | |
998 this._warmedUpContent = content; | |
999 } | |
1000 }, | |
1001 | |
1002 _shouldRenameOnMouseDown: function() | |
1003 { | |
1004 if (!this._uiSourceCode.canRename()) | |
1005 return false; | |
1006 var isSelected = this === this.treeOutline.selectedTreeElement; | |
1007 return isSelected && this.treeOutline.element.hasFocus() && !WebInspecto
r.isBeingEdited(this.treeOutline.element); | |
1008 }, | |
1009 | |
1010 selectOnMouseDown: function(event) | |
1011 { | |
1012 if (event.which !== 1 || !this._shouldRenameOnMouseDown()) { | |
1013 TreeElement.prototype.selectOnMouseDown.call(this, event); | |
1014 return; | |
1015 } | |
1016 setTimeout(rename.bind(this), 300); | |
1017 | |
1018 /** | |
1019 * @this {WebInspector.NavigatorSourceTreeElement} | |
1020 */ | |
1021 function rename() | |
1022 { | |
1023 if (this._shouldRenameOnMouseDown()) | |
1024 this._navigatorView.rename(this.uiSourceCode, false); | |
1025 } | |
1026 }, | |
1027 | |
1028 _ondragstart: function(event) | |
1029 { | |
1030 event.dataTransfer.setData("text/plain", this._warmedUpContent); | |
1031 event.dataTransfer.effectAllowed = "copy"; | |
1032 return true; | |
1033 }, | |
1034 | |
1035 /** | |
1036 * @override | |
1037 * @return {boolean} | |
1038 */ | |
1039 onspace: function() | |
1040 { | |
1041 this._navigatorView._sourceSelected(this.uiSourceCode, true); | |
1042 return true; | |
1043 }, | |
1044 | |
1045 /** | |
1046 * @param {!Event} event | |
1047 */ | |
1048 _onclick: function(event) | |
1049 { | |
1050 this._navigatorView._sourceSelected(this.uiSourceCode, false); | |
1051 }, | |
1052 | |
1053 /** | |
1054 * @override | |
1055 * @return {boolean} | |
1056 */ | |
1057 ondblclick: function(event) | |
1058 { | |
1059 var middleClick = event.button === 1; | |
1060 this._navigatorView._sourceSelected(this.uiSourceCode, !middleClick); | |
1061 return false; | |
1062 }, | |
1063 | |
1064 /** | |
1065 * @override | |
1066 * @return {boolean} | |
1067 */ | |
1068 onenter: function() | |
1069 { | |
1070 this._navigatorView._sourceSelected(this.uiSourceCode, true); | |
1071 return true; | |
1072 }, | |
1073 | |
1074 /** | |
1075 * @override | |
1076 * @return {boolean} | |
1077 */ | |
1078 ondelete: function() | |
1079 { | |
1080 this._navigatorView.sourceDeleted(this.uiSourceCode); | |
1081 return true; | |
1082 }, | |
1083 | |
1084 /** | |
1085 * @param {!Event} event | |
1086 */ | |
1087 _handleContextMenuEvent: function(event) | |
1088 { | |
1089 this.select(); | |
1090 this._navigatorView.handleFileContextMenu(event, this._uiSourceCode); | |
1091 }, | |
1092 | |
1093 __proto__: TreeElement.prototype | |
1094 }; | |
1095 | |
1096 /** | 1055 /** |
1097 * @constructor | 1056 * @unrestricted |
1098 * @param {string} id | |
1099 * @param {string} type | |
1100 */ | 1057 */ |
1101 WebInspector.NavigatorTreeNode = function(id, type) | 1058 WebInspector.NavigatorTreeNode = class { |
1102 { | 1059 /** |
| 1060 * @param {string} id |
| 1061 * @param {string} type |
| 1062 */ |
| 1063 constructor(id, type) { |
1103 this.id = id; | 1064 this.id = id; |
1104 this._type = type; | 1065 this._type = type; |
1105 /** @type {!Map.<string, !WebInspector.NavigatorTreeNode>} */ | 1066 /** @type {!Map.<string, !WebInspector.NavigatorTreeNode>} */ |
1106 this._children = new Map(); | 1067 this._children = new Map(); |
| 1068 } |
| 1069 |
| 1070 /** |
| 1071 * @return {!TreeElement} |
| 1072 */ |
| 1073 treeNode() { |
| 1074 throw 'Not implemented'; |
| 1075 } |
| 1076 |
| 1077 dispose() { |
| 1078 } |
| 1079 |
| 1080 /** |
| 1081 * @return {boolean} |
| 1082 */ |
| 1083 isRoot() { |
| 1084 return false; |
| 1085 } |
| 1086 |
| 1087 /** |
| 1088 * @return {boolean} |
| 1089 */ |
| 1090 hasChildren() { |
| 1091 return true; |
| 1092 } |
| 1093 |
| 1094 onattach() { |
| 1095 } |
| 1096 |
| 1097 /** |
| 1098 * @param {string} title |
| 1099 */ |
| 1100 setTitle(title) { |
| 1101 throw 'Not implemented'; |
| 1102 } |
| 1103 |
| 1104 populate() { |
| 1105 if (this.isPopulated()) |
| 1106 return; |
| 1107 if (this.parent) |
| 1108 this.parent.populate(); |
| 1109 this._populated = true; |
| 1110 this.wasPopulated(); |
| 1111 } |
| 1112 |
| 1113 wasPopulated() { |
| 1114 var children = this.children(); |
| 1115 for (var i = 0; i < children.length; ++i) |
| 1116 this.treeNode().appendChild(/** @type {!TreeElement} */ (children[i].treeN
ode())); |
| 1117 } |
| 1118 |
| 1119 /** |
| 1120 * @param {!WebInspector.NavigatorTreeNode} node |
| 1121 */ |
| 1122 didAddChild(node) { |
| 1123 if (this.isPopulated()) |
| 1124 this.treeNode().appendChild(/** @type {!TreeElement} */ (node.treeNode()))
; |
| 1125 } |
| 1126 |
| 1127 /** |
| 1128 * @param {!WebInspector.NavigatorTreeNode} node |
| 1129 */ |
| 1130 willRemoveChild(node) { |
| 1131 if (this.isPopulated()) |
| 1132 this.treeNode().removeChild(/** @type {!TreeElement} */ (node.treeNode()))
; |
| 1133 } |
| 1134 |
| 1135 /** |
| 1136 * @return {boolean} |
| 1137 */ |
| 1138 isPopulated() { |
| 1139 return this._populated; |
| 1140 } |
| 1141 |
| 1142 /** |
| 1143 * @return {boolean} |
| 1144 */ |
| 1145 isEmpty() { |
| 1146 return !this._children.size; |
| 1147 } |
| 1148 |
| 1149 /** |
| 1150 * @return {!Array.<!WebInspector.NavigatorTreeNode>} |
| 1151 */ |
| 1152 children() { |
| 1153 return this._children.valuesArray(); |
| 1154 } |
| 1155 |
| 1156 /** |
| 1157 * @param {string} id |
| 1158 * @return {?WebInspector.NavigatorTreeNode} |
| 1159 */ |
| 1160 child(id) { |
| 1161 return this._children.get(id) || null; |
| 1162 } |
| 1163 |
| 1164 /** |
| 1165 * @param {!WebInspector.NavigatorTreeNode} node |
| 1166 */ |
| 1167 appendChild(node) { |
| 1168 this._children.set(node.id, node); |
| 1169 node.parent = this; |
| 1170 this.didAddChild(node); |
| 1171 } |
| 1172 |
| 1173 /** |
| 1174 * @param {!WebInspector.NavigatorTreeNode} node |
| 1175 */ |
| 1176 removeChild(node) { |
| 1177 this.willRemoveChild(node); |
| 1178 this._children.remove(node.id); |
| 1179 delete node.parent; |
| 1180 node.dispose(); |
| 1181 } |
| 1182 |
| 1183 reset() { |
| 1184 this._children.clear(); |
| 1185 } |
1107 }; | 1186 }; |
1108 | 1187 |
1109 WebInspector.NavigatorTreeNode.prototype = { | 1188 /** |
1110 /** | 1189 * @unrestricted |
1111 * @return {!TreeElement} | 1190 */ |
1112 */ | 1191 WebInspector.NavigatorRootTreeNode = class extends WebInspector.NavigatorTreeNod
e { |
1113 treeNode: function() { throw "Not implemented"; }, | 1192 /** |
1114 | 1193 * @param {!WebInspector.NavigatorView} navigatorView |
1115 dispose: function() { }, | 1194 */ |
1116 | 1195 constructor(navigatorView) { |
1117 /** | 1196 super('', WebInspector.NavigatorView.Types.Root); |
1118 * @return {boolean} | 1197 this._navigatorView = navigatorView; |
1119 */ | 1198 } |
1120 isRoot: function() | 1199 |
1121 { | 1200 /** |
1122 return false; | 1201 * @override |
1123 }, | 1202 * @return {boolean} |
1124 | 1203 */ |
1125 /** | 1204 isRoot() { |
1126 * @return {boolean} | 1205 return true; |
1127 */ | 1206 } |
1128 hasChildren: function() | 1207 |
1129 { | 1208 /** |
1130 return true; | 1209 * @override |
1131 }, | 1210 * @return {!TreeElement} |
1132 | 1211 */ |
1133 onattach: function() | 1212 treeNode() { |
1134 { | 1213 return this._navigatorView._scriptsTree.rootElement(); |
1135 }, | 1214 } |
1136 | |
1137 /** | |
1138 * @param {string} title | |
1139 */ | |
1140 setTitle: function(title) | |
1141 { | |
1142 throw "Not implemented"; | |
1143 }, | |
1144 | |
1145 populate: function() | |
1146 { | |
1147 if (this.isPopulated()) | |
1148 return; | |
1149 if (this.parent) | |
1150 this.parent.populate(); | |
1151 this._populated = true; | |
1152 this.wasPopulated(); | |
1153 }, | |
1154 | |
1155 wasPopulated: function() | |
1156 { | |
1157 var children = this.children(); | |
1158 for (var i = 0; i < children.length; ++i) | |
1159 this.treeNode().appendChild(/** @type {!TreeElement} */ (children[i]
.treeNode())); | |
1160 }, | |
1161 | |
1162 /** | |
1163 * @param {!WebInspector.NavigatorTreeNode} node | |
1164 */ | |
1165 didAddChild: function(node) | |
1166 { | |
1167 if (this.isPopulated()) | |
1168 this.treeNode().appendChild(/** @type {!TreeElement} */ (node.treeNo
de())); | |
1169 }, | |
1170 | |
1171 /** | |
1172 * @param {!WebInspector.NavigatorTreeNode} node | |
1173 */ | |
1174 willRemoveChild: function(node) | |
1175 { | |
1176 if (this.isPopulated()) | |
1177 this.treeNode().removeChild(/** @type {!TreeElement} */ (node.treeNo
de())); | |
1178 }, | |
1179 | |
1180 /** | |
1181 * @return {boolean} | |
1182 */ | |
1183 isPopulated: function() | |
1184 { | |
1185 return this._populated; | |
1186 }, | |
1187 | |
1188 /** | |
1189 * @return {boolean} | |
1190 */ | |
1191 isEmpty: function() | |
1192 { | |
1193 return !this._children.size; | |
1194 }, | |
1195 | |
1196 /** | |
1197 * @return {!Array.<!WebInspector.NavigatorTreeNode>} | |
1198 */ | |
1199 children: function() | |
1200 { | |
1201 return this._children.valuesArray(); | |
1202 }, | |
1203 | |
1204 /** | |
1205 * @param {string} id | |
1206 * @return {?WebInspector.NavigatorTreeNode} | |
1207 */ | |
1208 child: function(id) | |
1209 { | |
1210 return this._children.get(id) || null; | |
1211 }, | |
1212 | |
1213 /** | |
1214 * @param {!WebInspector.NavigatorTreeNode} node | |
1215 */ | |
1216 appendChild: function(node) | |
1217 { | |
1218 this._children.set(node.id, node); | |
1219 node.parent = this; | |
1220 this.didAddChild(node); | |
1221 }, | |
1222 | |
1223 /** | |
1224 * @param {!WebInspector.NavigatorTreeNode} node | |
1225 */ | |
1226 removeChild: function(node) | |
1227 { | |
1228 this.willRemoveChild(node); | |
1229 this._children.remove(node.id); | |
1230 delete node.parent; | |
1231 node.dispose(); | |
1232 }, | |
1233 | |
1234 reset: function() | |
1235 { | |
1236 this._children.clear(); | |
1237 } | |
1238 }; | 1215 }; |
1239 | 1216 |
1240 /** | 1217 /** |
1241 * @constructor | 1218 * @unrestricted |
1242 * @extends {WebInspector.NavigatorTreeNode} | |
1243 * @param {!WebInspector.NavigatorView} navigatorView | |
1244 */ | 1219 */ |
1245 WebInspector.NavigatorRootTreeNode = function(navigatorView) | 1220 WebInspector.NavigatorUISourceCodeTreeNode = class extends WebInspector.Navigato
rTreeNode { |
1246 { | 1221 /** |
1247 WebInspector.NavigatorTreeNode.call(this, "", WebInspector.NavigatorView.Typ
es.Root); | 1222 * @param {!WebInspector.NavigatorView} navigatorView |
1248 this._navigatorView = navigatorView; | 1223 * @param {!WebInspector.UISourceCode} uiSourceCode |
1249 }; | 1224 */ |
1250 | 1225 constructor(navigatorView, uiSourceCode) { |
1251 WebInspector.NavigatorRootTreeNode.prototype = { | 1226 super(uiSourceCode.project().id() + ':' + uiSourceCode.url(), WebInspector.N
avigatorView.Types.File); |
1252 /** | |
1253 * @override | |
1254 * @return {boolean} | |
1255 */ | |
1256 isRoot: function() | |
1257 { | |
1258 return true; | |
1259 }, | |
1260 | |
1261 /** | |
1262 * @override | |
1263 * @return {!TreeElement} | |
1264 */ | |
1265 treeNode: function() | |
1266 { | |
1267 return this._navigatorView._scriptsTree.rootElement(); | |
1268 }, | |
1269 | |
1270 __proto__: WebInspector.NavigatorTreeNode.prototype | |
1271 }; | |
1272 | |
1273 /** | |
1274 * @constructor | |
1275 * @extends {WebInspector.NavigatorTreeNode} | |
1276 * @param {!WebInspector.NavigatorView} navigatorView | |
1277 * @param {!WebInspector.UISourceCode} uiSourceCode | |
1278 */ | |
1279 WebInspector.NavigatorUISourceCodeTreeNode = function(navigatorView, uiSourceCod
e) | |
1280 { | |
1281 WebInspector.NavigatorTreeNode.call(this, uiSourceCode.project().id() + ":"
+ uiSourceCode.url(), WebInspector.NavigatorView.Types.File); | |
1282 this._navigatorView = navigatorView; | 1227 this._navigatorView = navigatorView; |
1283 this._uiSourceCode = uiSourceCode; | 1228 this._uiSourceCode = uiSourceCode; |
1284 this._treeElement = null; | 1229 this._treeElement = null; |
1285 this._eventListeners = []; | 1230 this._eventListeners = []; |
| 1231 } |
| 1232 |
| 1233 /** |
| 1234 * @return {!WebInspector.UISourceCode} |
| 1235 */ |
| 1236 uiSourceCode() { |
| 1237 return this._uiSourceCode; |
| 1238 } |
| 1239 |
| 1240 /** |
| 1241 * @override |
| 1242 * @return {!TreeElement} |
| 1243 */ |
| 1244 treeNode() { |
| 1245 if (this._treeElement) |
| 1246 return this._treeElement; |
| 1247 |
| 1248 this._treeElement = new WebInspector.NavigatorSourceTreeElement(this._naviga
torView, this._uiSourceCode, ''); |
| 1249 this.updateTitle(); |
| 1250 |
| 1251 var updateTitleBound = this.updateTitle.bind(this, undefined); |
| 1252 this._eventListeners = [ |
| 1253 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Title
Changed, updateTitleBound), |
| 1254 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Worki
ngCopyChanged, updateTitleBound), |
| 1255 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.Worki
ngCopyCommitted, updateTitleBound) |
| 1256 ]; |
| 1257 return this._treeElement; |
| 1258 } |
| 1259 |
| 1260 /** |
| 1261 * @param {boolean=} ignoreIsDirty |
| 1262 */ |
| 1263 updateTitle(ignoreIsDirty) { |
| 1264 if (!this._treeElement) |
| 1265 return; |
| 1266 |
| 1267 var titleText = this._uiSourceCode.displayName(); |
| 1268 if (!ignoreIsDirty && |
| 1269 (this._uiSourceCode.isDirty() || WebInspector.persistence.hasUnsavedComm
ittedChanges(this._uiSourceCode))) |
| 1270 titleText = '*' + titleText; |
| 1271 |
| 1272 var binding = WebInspector.persistence.binding(this._uiSourceCode); |
| 1273 if (binding && Runtime.experiments.isEnabled('persistence2')) { |
| 1274 var titleElement = createElement('span'); |
| 1275 titleElement.textContent = titleText; |
| 1276 var status = titleElement.createChild('span'); |
| 1277 status.classList.add('mapped-file-bubble'); |
| 1278 status.textContent = '\u25C9'; |
| 1279 if (this._uiSourceCode === binding.network) |
| 1280 status.title = WebInspector.UIString('Persisted to file system: %s', bin
ding.fileSystem.url().trimMiddle(150)); |
| 1281 else if (binding.network.contentType().isFromSourceMap()) |
| 1282 status.title = WebInspector.UIString('Linked to source map: %s', binding
.network.url().trimMiddle(150)); |
| 1283 else |
| 1284 status.title = WebInspector.UIString('Linked to %s', binding.network.url
().trimMiddle(150)); |
| 1285 this._treeElement.title = titleElement; |
| 1286 } else { |
| 1287 this._treeElement.title = titleText; |
| 1288 } |
| 1289 |
| 1290 var tooltip = this._uiSourceCode.url(); |
| 1291 if (this._uiSourceCode.contentType().isFromSourceMap()) |
| 1292 tooltip = WebInspector.UIString('%s (from source map)', this._uiSourceCode
.displayName()); |
| 1293 this._treeElement.tooltip = tooltip; |
| 1294 } |
| 1295 |
| 1296 /** |
| 1297 * @override |
| 1298 * @return {boolean} |
| 1299 */ |
| 1300 hasChildren() { |
| 1301 return false; |
| 1302 } |
| 1303 |
| 1304 /** |
| 1305 * @override |
| 1306 */ |
| 1307 dispose() { |
| 1308 WebInspector.EventTarget.removeEventListeners(this._eventListeners); |
| 1309 } |
| 1310 |
| 1311 /** |
| 1312 * @param {boolean=} select |
| 1313 */ |
| 1314 reveal(select) { |
| 1315 this.parent.populate(); |
| 1316 this.parent.treeNode().expand(); |
| 1317 this._treeElement.reveal(true); |
| 1318 if (select) |
| 1319 this._treeElement.select(true); |
| 1320 } |
| 1321 |
| 1322 /** |
| 1323 * @param {function(boolean)=} callback |
| 1324 */ |
| 1325 rename(callback) { |
| 1326 if (!this._treeElement) |
| 1327 return; |
| 1328 |
| 1329 // Tree outline should be marked as edited as well as the tree element to pr
event search from starting. |
| 1330 var treeOutlineElement = this._treeElement.treeOutline.element; |
| 1331 WebInspector.markBeingEdited(treeOutlineElement, true); |
| 1332 |
| 1333 /** |
| 1334 * @param {!Element} element |
| 1335 * @param {string} newTitle |
| 1336 * @param {string} oldTitle |
| 1337 * @this {WebInspector.NavigatorUISourceCodeTreeNode} |
| 1338 */ |
| 1339 function commitHandler(element, newTitle, oldTitle) { |
| 1340 if (newTitle !== oldTitle) { |
| 1341 this._treeElement.title = newTitle; |
| 1342 this._uiSourceCode.rename(newTitle, renameCallback.bind(this)); |
| 1343 return; |
| 1344 } |
| 1345 afterEditing.call(this, true); |
| 1346 } |
| 1347 |
| 1348 /** |
| 1349 * @param {boolean} success |
| 1350 * @this {WebInspector.NavigatorUISourceCodeTreeNode} |
| 1351 */ |
| 1352 function renameCallback(success) { |
| 1353 if (!success) { |
| 1354 WebInspector.markBeingEdited(treeOutlineElement, false); |
| 1355 this.updateTitle(); |
| 1356 this.rename(callback); |
| 1357 return; |
| 1358 } |
| 1359 afterEditing.call(this, true); |
| 1360 } |
| 1361 |
| 1362 /** |
| 1363 * @param {boolean} committed |
| 1364 * @this {WebInspector.NavigatorUISourceCodeTreeNode} |
| 1365 */ |
| 1366 function afterEditing(committed) { |
| 1367 WebInspector.markBeingEdited(treeOutlineElement, false); |
| 1368 this.updateTitle(); |
| 1369 this._treeElement.treeOutline.focus(); |
| 1370 if (callback) |
| 1371 callback(committed); |
| 1372 } |
| 1373 |
| 1374 this.updateTitle(true); |
| 1375 this._treeElement.startEditingTitle( |
| 1376 new WebInspector.InplaceEditor.Config(commitHandler.bind(this), afterEdi
ting.bind(this, false))); |
| 1377 } |
1286 }; | 1378 }; |
1287 | 1379 |
1288 WebInspector.NavigatorUISourceCodeTreeNode.prototype = { | |
1289 /** | |
1290 * @return {!WebInspector.UISourceCode} | |
1291 */ | |
1292 uiSourceCode: function() | |
1293 { | |
1294 return this._uiSourceCode; | |
1295 }, | |
1296 | |
1297 /** | |
1298 * @override | |
1299 * @return {!TreeElement} | |
1300 */ | |
1301 treeNode: function() | |
1302 { | |
1303 if (this._treeElement) | |
1304 return this._treeElement; | |
1305 | |
1306 this._treeElement = new WebInspector.NavigatorSourceTreeElement(this._na
vigatorView, this._uiSourceCode, ""); | |
1307 this.updateTitle(); | |
1308 | |
1309 var updateTitleBound = this.updateTitle.bind(this, undefined); | |
1310 this._eventListeners = [ | |
1311 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events
.TitleChanged, updateTitleBound), | |
1312 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events
.WorkingCopyChanged, updateTitleBound), | |
1313 this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events
.WorkingCopyCommitted, updateTitleBound) | |
1314 ]; | |
1315 return this._treeElement; | |
1316 }, | |
1317 | |
1318 /** | |
1319 * @param {boolean=} ignoreIsDirty | |
1320 */ | |
1321 updateTitle: function(ignoreIsDirty) | |
1322 { | |
1323 if (!this._treeElement) | |
1324 return; | |
1325 | |
1326 var titleText = this._uiSourceCode.displayName(); | |
1327 if (!ignoreIsDirty && (this._uiSourceCode.isDirty() || WebInspector.pers
istence.hasUnsavedCommittedChanges(this._uiSourceCode))) | |
1328 titleText = "*" + titleText; | |
1329 | |
1330 var binding = WebInspector.persistence.binding(this._uiSourceCode); | |
1331 if (binding && Runtime.experiments.isEnabled("persistence2")) { | |
1332 var titleElement = createElement("span"); | |
1333 titleElement.textContent = titleText; | |
1334 var status = titleElement.createChild("span"); | |
1335 status.classList.add("mapped-file-bubble"); | |
1336 status.textContent = "\u25C9"; | |
1337 if (this._uiSourceCode === binding.network) | |
1338 status.title = WebInspector.UIString("Persisted to file system:
%s", binding.fileSystem.url().trimMiddle(150)); | |
1339 else if (binding.network.contentType().isFromSourceMap()) | |
1340 status.title = WebInspector.UIString("Linked to source map: %s",
binding.network.url().trimMiddle(150)); | |
1341 else | |
1342 status.title = WebInspector.UIString("Linked to %s", binding.net
work.url().trimMiddle(150)); | |
1343 this._treeElement.title = titleElement; | |
1344 } else { | |
1345 this._treeElement.title = titleText; | |
1346 } | |
1347 | |
1348 var tooltip = this._uiSourceCode.url(); | |
1349 if (this._uiSourceCode.contentType().isFromSourceMap()) | |
1350 tooltip = WebInspector.UIString("%s (from source map)", this._uiSour
ceCode.displayName()); | |
1351 this._treeElement.tooltip = tooltip; | |
1352 }, | |
1353 | |
1354 /** | |
1355 * @override | |
1356 * @return {boolean} | |
1357 */ | |
1358 hasChildren: function() | |
1359 { | |
1360 return false; | |
1361 }, | |
1362 | |
1363 /** | |
1364 * @override | |
1365 */ | |
1366 dispose: function() | |
1367 { | |
1368 WebInspector.EventTarget.removeEventListeners(this._eventListeners); | |
1369 }, | |
1370 | |
1371 /** | |
1372 * @param {boolean=} select | |
1373 */ | |
1374 reveal: function(select) | |
1375 { | |
1376 this.parent.populate(); | |
1377 this.parent.treeNode().expand(); | |
1378 this._treeElement.reveal(true); | |
1379 if (select) | |
1380 this._treeElement.select(true); | |
1381 }, | |
1382 | |
1383 /** | |
1384 * @param {function(boolean)=} callback | |
1385 */ | |
1386 rename: function(callback) | |
1387 { | |
1388 if (!this._treeElement) | |
1389 return; | |
1390 | |
1391 // Tree outline should be marked as edited as well as the tree element t
o prevent search from starting. | |
1392 var treeOutlineElement = this._treeElement.treeOutline.element; | |
1393 WebInspector.markBeingEdited(treeOutlineElement, true); | |
1394 | |
1395 /** | |
1396 * @param {!Element} element | |
1397 * @param {string} newTitle | |
1398 * @param {string} oldTitle | |
1399 * @this {WebInspector.NavigatorUISourceCodeTreeNode} | |
1400 */ | |
1401 function commitHandler(element, newTitle, oldTitle) | |
1402 { | |
1403 if (newTitle !== oldTitle) { | |
1404 this._treeElement.title = newTitle; | |
1405 this._uiSourceCode.rename(newTitle, renameCallback.bind(this)); | |
1406 return; | |
1407 } | |
1408 afterEditing.call(this, true); | |
1409 } | |
1410 | |
1411 /** | |
1412 * @param {boolean} success | |
1413 * @this {WebInspector.NavigatorUISourceCodeTreeNode} | |
1414 */ | |
1415 function renameCallback(success) | |
1416 { | |
1417 if (!success) { | |
1418 WebInspector.markBeingEdited(treeOutlineElement, false); | |
1419 this.updateTitle(); | |
1420 this.rename(callback); | |
1421 return; | |
1422 } | |
1423 afterEditing.call(this, true); | |
1424 } | |
1425 | |
1426 /** | |
1427 * @param {boolean} committed | |
1428 * @this {WebInspector.NavigatorUISourceCodeTreeNode} | |
1429 */ | |
1430 function afterEditing(committed) | |
1431 { | |
1432 WebInspector.markBeingEdited(treeOutlineElement, false); | |
1433 this.updateTitle(); | |
1434 this._treeElement.treeOutline.focus(); | |
1435 if (callback) | |
1436 callback(committed); | |
1437 } | |
1438 | |
1439 this.updateTitle(true); | |
1440 this._treeElement.startEditingTitle(new WebInspector.InplaceEditor.Confi
g(commitHandler.bind(this), afterEditing.bind(this, false))); | |
1441 }, | |
1442 | |
1443 __proto__: WebInspector.NavigatorTreeNode.prototype | |
1444 }; | |
1445 | |
1446 /** | 1380 /** |
1447 * @constructor | 1381 * @unrestricted |
1448 * @extends {WebInspector.NavigatorTreeNode} | |
1449 * @param {!WebInspector.NavigatorView} navigatorView | |
1450 * @param {?WebInspector.Project} project | |
1451 * @param {string} id | |
1452 * @param {string} type | |
1453 * @param {string} folderPath | |
1454 * @param {string} title | |
1455 */ | 1382 */ |
1456 WebInspector.NavigatorFolderTreeNode = function(navigatorView, project, id, type
, folderPath, title) | 1383 WebInspector.NavigatorFolderTreeNode = class extends WebInspector.NavigatorTreeN
ode { |
1457 { | 1384 /** |
1458 WebInspector.NavigatorTreeNode.call(this, id, type); | 1385 * @param {!WebInspector.NavigatorView} navigatorView |
| 1386 * @param {?WebInspector.Project} project |
| 1387 * @param {string} id |
| 1388 * @param {string} type |
| 1389 * @param {string} folderPath |
| 1390 * @param {string} title |
| 1391 */ |
| 1392 constructor(navigatorView, project, id, type, folderPath, title) { |
| 1393 super(id, type); |
1459 this._navigatorView = navigatorView; | 1394 this._navigatorView = navigatorView; |
1460 this._project = project; | 1395 this._project = project; |
1461 this._folderPath = folderPath; | 1396 this._folderPath = folderPath; |
1462 this._title = title; | 1397 this._title = title; |
| 1398 } |
| 1399 |
| 1400 /** |
| 1401 * @override |
| 1402 * @return {!TreeElement} |
| 1403 */ |
| 1404 treeNode() { |
| 1405 if (this._treeElement) |
| 1406 return this._treeElement; |
| 1407 this._treeElement = this._createTreeElement(this._title, this); |
| 1408 this.updateTitle(); |
| 1409 return this._treeElement; |
| 1410 } |
| 1411 |
| 1412 updateTitle() { |
| 1413 if (!this._treeElement || this._project.type() !== WebInspector.projectTypes
.FileSystem) |
| 1414 return; |
| 1415 var absoluteFileSystemPath = |
| 1416 WebInspector.FileSystemWorkspaceBinding.fileSystemPath(this._project.id(
)) + '/' + this._folderPath; |
| 1417 var hasMappedFiles = Runtime.experiments.isEnabled('persistence2') ? |
| 1418 WebInspector.persistence.filePathHasBindings(absoluteFileSystemPath) : |
| 1419 true; |
| 1420 this._treeElement.listItemElement.classList.toggle('has-mapped-files', hasMa
ppedFiles); |
| 1421 } |
| 1422 |
| 1423 /** |
| 1424 * @return {!TreeElement} |
| 1425 */ |
| 1426 _createTreeElement(title, node) { |
| 1427 if (this._project.type() !== WebInspector.projectTypes.FileSystem) { |
| 1428 try { |
| 1429 title = decodeURI(title); |
| 1430 } catch (e) { |
| 1431 } |
| 1432 } |
| 1433 var treeElement = new WebInspector.NavigatorFolderTreeElement(this._navigato
rView, this._type, title); |
| 1434 treeElement.setNode(node); |
| 1435 return treeElement; |
| 1436 } |
| 1437 |
| 1438 /** |
| 1439 * @override |
| 1440 */ |
| 1441 wasPopulated() { |
| 1442 if (!this._treeElement || this._treeElement._node !== this) |
| 1443 return; |
| 1444 this._addChildrenRecursive(); |
| 1445 } |
| 1446 |
| 1447 _addChildrenRecursive() { |
| 1448 var children = this.children(); |
| 1449 for (var i = 0; i < children.length; ++i) { |
| 1450 var child = children[i]; |
| 1451 this.didAddChild(child); |
| 1452 if (child instanceof WebInspector.NavigatorFolderTreeNode) |
| 1453 child._addChildrenRecursive(); |
| 1454 } |
| 1455 } |
| 1456 |
| 1457 _shouldMerge(node) { |
| 1458 return this._type !== WebInspector.NavigatorView.Types.Domain && |
| 1459 node instanceof WebInspector.NavigatorFolderTreeNode; |
| 1460 } |
| 1461 |
| 1462 /** |
| 1463 * @param {!WebInspector.NavigatorTreeNode} node |
| 1464 * @override |
| 1465 */ |
| 1466 didAddChild(node) { |
| 1467 function titleForNode(node) { |
| 1468 return node._title; |
| 1469 } |
| 1470 |
| 1471 if (!this._treeElement) |
| 1472 return; |
| 1473 |
| 1474 var children = this.children(); |
| 1475 |
| 1476 if (children.length === 1 && this._shouldMerge(node)) { |
| 1477 node._isMerged = true; |
| 1478 this._treeElement.title = this._treeElement.title + '/' + node._title; |
| 1479 node._treeElement = this._treeElement; |
| 1480 this._treeElement.setNode(node); |
| 1481 return; |
| 1482 } |
| 1483 |
| 1484 var oldNode; |
| 1485 if (children.length === 2) |
| 1486 oldNode = children[0] !== node ? children[0] : children[1]; |
| 1487 if (oldNode && oldNode._isMerged) { |
| 1488 delete oldNode._isMerged; |
| 1489 var mergedToNodes = []; |
| 1490 mergedToNodes.push(this); |
| 1491 var treeNode = this; |
| 1492 while (treeNode._isMerged) { |
| 1493 treeNode = treeNode.parent; |
| 1494 mergedToNodes.push(treeNode); |
| 1495 } |
| 1496 mergedToNodes.reverse(); |
| 1497 var titleText = mergedToNodes.map(titleForNode).join('/'); |
| 1498 |
| 1499 var nodes = []; |
| 1500 treeNode = oldNode; |
| 1501 do { |
| 1502 nodes.push(treeNode); |
| 1503 children = treeNode.children(); |
| 1504 treeNode = children.length === 1 ? children[0] : null; |
| 1505 } while (treeNode && treeNode._isMerged); |
| 1506 |
| 1507 if (!this.isPopulated()) { |
| 1508 this._treeElement.title = titleText; |
| 1509 this._treeElement.setNode(this); |
| 1510 for (var i = 0; i < nodes.length; ++i) { |
| 1511 delete nodes[i]._treeElement; |
| 1512 delete nodes[i]._isMerged; |
| 1513 } |
| 1514 return; |
| 1515 } |
| 1516 var oldTreeElement = this._treeElement; |
| 1517 var treeElement = this._createTreeElement(titleText, this); |
| 1518 for (var i = 0; i < mergedToNodes.length; ++i) |
| 1519 mergedToNodes[i]._treeElement = treeElement; |
| 1520 oldTreeElement.parent.appendChild(treeElement); |
| 1521 |
| 1522 oldTreeElement.setNode(nodes[nodes.length - 1]); |
| 1523 oldTreeElement.title = nodes.map(titleForNode).join('/'); |
| 1524 oldTreeElement.parent.removeChild(oldTreeElement); |
| 1525 this._treeElement.appendChild(oldTreeElement); |
| 1526 if (oldTreeElement.expanded) |
| 1527 treeElement.expand(); |
| 1528 } |
| 1529 if (this.isPopulated()) |
| 1530 this._treeElement.appendChild(node.treeNode()); |
| 1531 } |
| 1532 |
| 1533 /** |
| 1534 * @override |
| 1535 * @param {!WebInspector.NavigatorTreeNode} node |
| 1536 */ |
| 1537 willRemoveChild(node) { |
| 1538 if (node._isMerged || !this.isPopulated()) |
| 1539 return; |
| 1540 this._treeElement.removeChild(node._treeElement); |
| 1541 } |
1463 }; | 1542 }; |
1464 | 1543 |
1465 WebInspector.NavigatorFolderTreeNode.prototype = { | |
1466 /** | |
1467 * @override | |
1468 * @return {!TreeElement} | |
1469 */ | |
1470 treeNode: function() | |
1471 { | |
1472 if (this._treeElement) | |
1473 return this._treeElement; | |
1474 this._treeElement = this._createTreeElement(this._title, this); | |
1475 this.updateTitle(); | |
1476 return this._treeElement; | |
1477 }, | |
1478 | |
1479 updateTitle: function() | |
1480 { | |
1481 if (!this._treeElement || this._project.type() !== WebInspector.projectT
ypes.FileSystem) | |
1482 return; | |
1483 var absoluteFileSystemPath = WebInspector.FileSystemWorkspaceBinding.fil
eSystemPath(this._project.id()) + "/" + this._folderPath; | |
1484 var hasMappedFiles = Runtime.experiments.isEnabled("persistence2") ? Web
Inspector.persistence.filePathHasBindings(absoluteFileSystemPath) : true; | |
1485 this._treeElement.listItemElement.classList.toggle("has-mapped-files", h
asMappedFiles); | |
1486 }, | |
1487 | |
1488 /** | |
1489 * @return {!TreeElement} | |
1490 */ | |
1491 _createTreeElement: function(title, node) | |
1492 { | |
1493 if (this._project.type() !== WebInspector.projectTypes.FileSystem) { | |
1494 try { | |
1495 title = decodeURI(title); | |
1496 } catch (e) { | |
1497 } | |
1498 } | |
1499 var treeElement = new WebInspector.NavigatorFolderTreeElement(this._navi
gatorView, this._type, title); | |
1500 treeElement.setNode(node); | |
1501 return treeElement; | |
1502 }, | |
1503 | |
1504 wasPopulated: function() | |
1505 { | |
1506 if (!this._treeElement || this._treeElement._node !== this) | |
1507 return; | |
1508 this._addChildrenRecursive(); | |
1509 }, | |
1510 | |
1511 _addChildrenRecursive: function() | |
1512 { | |
1513 var children = this.children(); | |
1514 for (var i = 0; i < children.length; ++i) { | |
1515 var child = children[i]; | |
1516 this.didAddChild(child); | |
1517 if (child instanceof WebInspector.NavigatorFolderTreeNode) | |
1518 child._addChildrenRecursive(); | |
1519 } | |
1520 }, | |
1521 | |
1522 _shouldMerge: function(node) | |
1523 { | |
1524 return this._type !== WebInspector.NavigatorView.Types.Domain && node in
stanceof WebInspector.NavigatorFolderTreeNode; | |
1525 }, | |
1526 | |
1527 didAddChild: function(node) | |
1528 { | |
1529 function titleForNode(node) | |
1530 { | |
1531 return node._title; | |
1532 } | |
1533 | |
1534 if (!this._treeElement) | |
1535 return; | |
1536 | |
1537 var children = this.children(); | |
1538 | |
1539 if (children.length === 1 && this._shouldMerge(node)) { | |
1540 node._isMerged = true; | |
1541 this._treeElement.title = this._treeElement.title + "/" + node._titl
e; | |
1542 node._treeElement = this._treeElement; | |
1543 this._treeElement.setNode(node); | |
1544 return; | |
1545 } | |
1546 | |
1547 var oldNode; | |
1548 if (children.length === 2) | |
1549 oldNode = children[0] !== node ? children[0] : children[1]; | |
1550 if (oldNode && oldNode._isMerged) { | |
1551 delete oldNode._isMerged; | |
1552 var mergedToNodes = []; | |
1553 mergedToNodes.push(this); | |
1554 var treeNode = this; | |
1555 while (treeNode._isMerged) { | |
1556 treeNode = treeNode.parent; | |
1557 mergedToNodes.push(treeNode); | |
1558 } | |
1559 mergedToNodes.reverse(); | |
1560 var titleText = mergedToNodes.map(titleForNode).join("/"); | |
1561 | |
1562 var nodes = []; | |
1563 treeNode = oldNode; | |
1564 do { | |
1565 nodes.push(treeNode); | |
1566 children = treeNode.children(); | |
1567 treeNode = children.length === 1 ? children[0] : null; | |
1568 } while (treeNode && treeNode._isMerged); | |
1569 | |
1570 if (!this.isPopulated()) { | |
1571 this._treeElement.title = titleText; | |
1572 this._treeElement.setNode(this); | |
1573 for (var i = 0; i < nodes.length; ++i) { | |
1574 delete nodes[i]._treeElement; | |
1575 delete nodes[i]._isMerged; | |
1576 } | |
1577 return; | |
1578 } | |
1579 var oldTreeElement = this._treeElement; | |
1580 var treeElement = this._createTreeElement(titleText, this); | |
1581 for (var i = 0; i < mergedToNodes.length; ++i) | |
1582 mergedToNodes[i]._treeElement = treeElement; | |
1583 oldTreeElement.parent.appendChild(treeElement); | |
1584 | |
1585 oldTreeElement.setNode(nodes[nodes.length - 1]); | |
1586 oldTreeElement.title = nodes.map(titleForNode).join("/"); | |
1587 oldTreeElement.parent.removeChild(oldTreeElement); | |
1588 this._treeElement.appendChild(oldTreeElement); | |
1589 if (oldTreeElement.expanded) | |
1590 treeElement.expand(); | |
1591 } | |
1592 if (this.isPopulated()) | |
1593 this._treeElement.appendChild(node.treeNode()); | |
1594 }, | |
1595 | |
1596 /** | |
1597 * @override | |
1598 * @param {!WebInspector.NavigatorTreeNode} node | |
1599 */ | |
1600 willRemoveChild: function(node) | |
1601 { | |
1602 if (node._isMerged || !this.isPopulated()) | |
1603 return; | |
1604 this._treeElement.removeChild(node._treeElement); | |
1605 }, | |
1606 | |
1607 __proto__: WebInspector.NavigatorTreeNode.prototype | |
1608 }; | |
1609 | |
1610 /** | 1544 /** |
1611 * @constructor | 1545 * @unrestricted |
1612 * @extends {WebInspector.NavigatorTreeNode} | |
1613 * @param {!WebInspector.NavigatorView} navigatorView | |
1614 * @param {!WebInspector.Project} project | |
1615 * @param {string} id | |
1616 * @param {string} type | |
1617 * @param {string} title | |
1618 */ | 1546 */ |
1619 WebInspector.NavigatorGroupTreeNode = function(navigatorView, project, id, type,
title) | 1547 WebInspector.NavigatorGroupTreeNode = class extends WebInspector.NavigatorTreeNo
de { |
1620 { | 1548 /** |
1621 WebInspector.NavigatorTreeNode.call(this, id, type); | 1549 * @param {!WebInspector.NavigatorView} navigatorView |
| 1550 * @param {!WebInspector.Project} project |
| 1551 * @param {string} id |
| 1552 * @param {string} type |
| 1553 * @param {string} title |
| 1554 */ |
| 1555 constructor(navigatorView, project, id, type, title) { |
| 1556 super(id, type); |
1622 this._project = project; | 1557 this._project = project; |
1623 this._navigatorView = navigatorView; | 1558 this._navigatorView = navigatorView; |
1624 this._title = title; | 1559 this._title = title; |
1625 this.populate(); | 1560 this.populate(); |
| 1561 } |
| 1562 |
| 1563 /** |
| 1564 * @param {function(boolean)} hoverCallback |
| 1565 */ |
| 1566 setHoverCallback(hoverCallback) { |
| 1567 this._hoverCallback = hoverCallback; |
| 1568 } |
| 1569 |
| 1570 /** |
| 1571 * @override |
| 1572 * @return {!TreeElement} |
| 1573 */ |
| 1574 treeNode() { |
| 1575 if (this._treeElement) |
| 1576 return this._treeElement; |
| 1577 this._treeElement = |
| 1578 new WebInspector.NavigatorFolderTreeElement(this._navigatorView, this._t
ype, this._title, this._hoverCallback); |
| 1579 this._treeElement.setNode(this); |
| 1580 return this._treeElement; |
| 1581 } |
| 1582 |
| 1583 /** |
| 1584 * @override |
| 1585 */ |
| 1586 onattach() { |
| 1587 this.updateTitle(); |
| 1588 } |
| 1589 |
| 1590 updateTitle() { |
| 1591 if (!this._treeElement || this._project.type() !== WebInspector.projectTypes
.FileSystem) |
| 1592 return; |
| 1593 if (!Runtime.experiments.isEnabled('persistence2')) { |
| 1594 this._treeElement.listItemElement.classList.add('has-mapped-files'); |
| 1595 return; |
| 1596 } |
| 1597 var fileSystemPath = WebInspector.FileSystemWorkspaceBinding.fileSystemPath(
this._project.id()); |
| 1598 var wasActive = this._treeElement.listItemElement.classList.contains('has-ma
pped-files'); |
| 1599 var isActive = WebInspector.persistence.filePathHasBindings(fileSystemPath); |
| 1600 if (wasActive === isActive) |
| 1601 return; |
| 1602 this._treeElement.listItemElement.classList.toggle('has-mapped-files', isAct
ive); |
| 1603 if (isActive) |
| 1604 this._treeElement.expand(); |
| 1605 else |
| 1606 this._treeElement.collapse(); |
| 1607 } |
| 1608 |
| 1609 /** |
| 1610 * @param {string} title |
| 1611 * @override |
| 1612 */ |
| 1613 setTitle(title) { |
| 1614 this._title = title; |
| 1615 if (this._treeElement) |
| 1616 this._treeElement.title = this._title; |
| 1617 } |
1626 }; | 1618 }; |
1627 | |
1628 WebInspector.NavigatorGroupTreeNode.prototype = { | |
1629 /** | |
1630 * @param {function(boolean)} hoverCallback | |
1631 */ | |
1632 setHoverCallback: function(hoverCallback) | |
1633 { | |
1634 this._hoverCallback = hoverCallback; | |
1635 }, | |
1636 | |
1637 /** | |
1638 * @override | |
1639 * @return {!TreeElement} | |
1640 */ | |
1641 treeNode: function() | |
1642 { | |
1643 if (this._treeElement) | |
1644 return this._treeElement; | |
1645 this._treeElement = new WebInspector.NavigatorFolderTreeElement(this._na
vigatorView, this._type, this._title, this._hoverCallback); | |
1646 this._treeElement.setNode(this); | |
1647 return this._treeElement; | |
1648 }, | |
1649 | |
1650 /** | |
1651 * @override | |
1652 */ | |
1653 onattach: function() | |
1654 { | |
1655 this.updateTitle(); | |
1656 }, | |
1657 | |
1658 updateTitle: function() | |
1659 { | |
1660 if (!this._treeElement || this._project.type() !== WebInspector.projectT
ypes.FileSystem) | |
1661 return; | |
1662 if (!Runtime.experiments.isEnabled("persistence2")) { | |
1663 this._treeElement.listItemElement.classList.add("has-mapped-files"); | |
1664 return; | |
1665 } | |
1666 var fileSystemPath = WebInspector.FileSystemWorkspaceBinding.fileSystemP
ath(this._project.id()); | |
1667 var wasActive = this._treeElement.listItemElement.classList.contains("ha
s-mapped-files"); | |
1668 var isActive = WebInspector.persistence.filePathHasBindings(fileSystemPa
th); | |
1669 if (wasActive === isActive) | |
1670 return; | |
1671 this._treeElement.listItemElement.classList.toggle("has-mapped-files", i
sActive); | |
1672 if (isActive) | |
1673 this._treeElement.expand(); | |
1674 else | |
1675 this._treeElement.collapse(); | |
1676 }, | |
1677 | |
1678 /** | |
1679 * @param {string} title | |
1680 * @override | |
1681 */ | |
1682 setTitle: function(title) | |
1683 { | |
1684 this._title = title; | |
1685 if (this._treeElement) | |
1686 this._treeElement.title = this._title; | |
1687 }, | |
1688 | |
1689 __proto__: WebInspector.NavigatorTreeNode.prototype | |
1690 }; | |
OLD | NEW |