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