Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: third_party/WebKit/Source/devtools/front_end/sources/NavigatorView.js

Issue 2466123002: DevTools: reformat front-end code to match chromium style. (Closed)
Patch Set: all done Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 };
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698