| /* |
| * Copyright (C) 2012 Google Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following disclaimer |
| * in the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. AND ITS CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GOOGLE INC. |
| * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @extends {WebInspector.View} |
| * @constructor |
| */ |
| WebInspector.NavigatorView = function() |
| { |
| WebInspector.View.call(this); |
| this.registerRequiredCSS("navigatorView.css"); |
| |
| var scriptsTreeElement = document.createElement("ol"); |
| this._scriptsTree = new WebInspector.NavigatorTreeOutline(scriptsTreeElement); |
| this._scriptsTree.childrenListElement.addEventListener("keypress", this._treeKeyPress.bind(this), true); |
| |
| var scriptsOutlineElement = document.createElement("div"); |
| scriptsOutlineElement.addStyleClass("outline-disclosure"); |
| scriptsOutlineElement.addStyleClass("navigator"); |
| scriptsOutlineElement.appendChild(scriptsTreeElement); |
| |
| this.element.addStyleClass("fill"); |
| this.element.addStyleClass("navigator-container"); |
| this.element.appendChild(scriptsOutlineElement); |
| this.setDefaultFocusedElement(this._scriptsTree.element); |
| |
| /** @type {!Map.<WebInspector.UISourceCode, !WebInspector.NavigatorUISourceCodeTreeNode>} */ |
| this._uiSourceCodeNodes = new Map(); |
| /** @type {!Map.<WebInspector.NavigatorTreeNode, !StringMap.<!WebInspector.NavigatorFolderTreeNode>>} */ |
| this._subfolderNodes = new Map(); |
| |
| this._rootNode = new WebInspector.NavigatorRootTreeNode(this); |
| this._rootNode.populate(); |
| |
| WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this); |
| } |
| |
| WebInspector.NavigatorView.Events = { |
| ItemSelected: "ItemSelected", |
| ItemSearchStarted: "ItemSearchStarted", |
| ItemRenamingRequested: "ItemRenamingRequested", |
| ItemCreationRequested: "ItemCreationRequested" |
| } |
| |
| WebInspector.NavigatorView.iconClassForType = function(type) |
| { |
| if (type === WebInspector.NavigatorTreeOutline.Types.Domain) |
| return "navigator-domain-tree-item"; |
| if (type === WebInspector.NavigatorTreeOutline.Types.FileSystem) |
| return "navigator-folder-tree-item"; |
| return "navigator-folder-tree-item"; |
| } |
| |
| WebInspector.NavigatorView.prototype = { |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| */ |
| addUISourceCode: function(uiSourceCode) |
| { |
| var projectNode = this._projectNode(uiSourceCode.project()); |
| var folderNode = this._folderNode(projectNode, uiSourceCode.parentPath()); |
| var uiSourceCodeNode = new WebInspector.NavigatorUISourceCodeTreeNode(this, uiSourceCode); |
| this._uiSourceCodeNodes.put(uiSourceCode, uiSourceCodeNode); |
| folderNode.appendChild(uiSourceCodeNode); |
| if (uiSourceCode.url === WebInspector.inspectedPageURL) |
| this.revealUISourceCode(uiSourceCode); |
| }, |
| |
| /** |
| * @param {WebInspector.Event} event |
| */ |
| _inspectedURLChanged: function(event) |
| { |
| var nodes = this._uiSourceCodeNodes.values(); |
| for (var i = 0; i < nodes.length; ++i) { |
| var uiSourceCode = nodes[i].uiSourceCode(); |
| if (uiSourceCode.url === WebInspector.inspectedPageURL) |
| this.revealUISourceCode(uiSourceCode); |
| } |
| }, |
| |
| /** |
| * @param {WebInspector.Project} project |
| * @return {WebInspector.NavigatorTreeNode} |
| */ |
| _projectNode: function(project) |
| { |
| if (!project.displayName()) |
| return this._rootNode; |
| |
| var projectNode = this._rootNode.child(project.id()); |
| if (!projectNode) { |
| var type = project.type() === WebInspector.projectTypes.FileSystem ? WebInspector.NavigatorTreeOutline.Types.FileSystem : WebInspector.NavigatorTreeOutline.Types.Domain; |
| projectNode = new WebInspector.NavigatorFolderTreeNode(this, project, project.id(), type, "", project.displayName()); |
| this._rootNode.appendChild(projectNode); |
| } |
| return projectNode; |
| }, |
| |
| /** |
| * @param {WebInspector.NavigatorTreeNode} projectNode |
| * @param {string} folderPath |
| * @return {WebInspector.NavigatorTreeNode} |
| */ |
| _folderNode: function(projectNode, folderPath) |
| { |
| if (!folderPath) |
| return projectNode; |
| |
| var subfolderNodes = this._subfolderNodes.get(projectNode); |
| if (!subfolderNodes) { |
| subfolderNodes = /** @type {!StringMap.<!WebInspector.NavigatorFolderTreeNode>} */ (new StringMap()); |
| this._subfolderNodes.put(projectNode, subfolderNodes); |
| } |
| |
| var folderNode = subfolderNodes.get(folderPath); |
| if (folderNode) |
| return folderNode; |
| |
| var parentNode = projectNode; |
| var index = folderPath.lastIndexOf("/"); |
| if (index !== -1) |
| parentNode = this._folderNode(projectNode, folderPath.substring(0, index)); |
| |
| var name = folderPath.substring(index + 1); |
| folderNode = new WebInspector.NavigatorFolderTreeNode(this, null, name, WebInspector.NavigatorTreeOutline.Types.Folder, folderPath, name); |
| subfolderNodes.put(folderPath, folderNode); |
| parentNode.appendChild(folderNode); |
| return folderNode; |
| }, |
| |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| * @param {boolean=} select |
| */ |
| revealUISourceCode: function(uiSourceCode, select) |
| { |
| var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| if (!node) |
| return null; |
| if (this._scriptsTree.selectedTreeElement) |
| this._scriptsTree.selectedTreeElement.deselect(); |
| this._lastSelectedUISourceCode = uiSourceCode; |
| node.reveal(select); |
| }, |
| |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| * @param {boolean} focusSource |
| */ |
| _scriptSelected: function(uiSourceCode, focusSource) |
| { |
| this._lastSelectedUISourceCode = uiSourceCode; |
| var data = { uiSourceCode: uiSourceCode, focusSource: focusSource}; |
| this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemSelected, data); |
| }, |
| |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| */ |
| removeUISourceCode: function(uiSourceCode) |
| { |
| var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| if (!node) |
| return; |
| |
| var projectNode = this._projectNode(uiSourceCode.project()); |
| var subfolderNodes = this._subfolderNodes.get(projectNode); |
| var parentNode = node.parent; |
| this._uiSourceCodeNodes.remove(uiSourceCode); |
| parentNode.removeChild(node); |
| node = parentNode; |
| |
| while (node) { |
| parentNode = node.parent; |
| if (!parentNode || !node.isEmpty()) |
| break; |
| if (subfolderNodes) |
| subfolderNodes.remove(node._folderPath); |
| parentNode.removeChild(node); |
| node = parentNode; |
| } |
| }, |
| |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| */ |
| requestRename: function(uiSourceCode) |
| { |
| this.dispatchEventToListeners(WebInspector.ScriptsNavigator.Events.ItemRenamingRequested, uiSourceCode); |
| }, |
| |
| /** |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| * @param {function(boolean)=} callback |
| */ |
| rename: function(uiSourceCode, callback) |
| { |
| var node = this._uiSourceCodeNodes.get(uiSourceCode); |
| if (!node) |
| return null; |
| node.rename(callback); |
| }, |
| |
| reset: function() |
| { |
| var nodes = this._uiSourceCodeNodes.values(); |
| for (var i = 0; i < nodes.length; ++i) |
| nodes[i].dispose(); |
| |
| this._scriptsTree.removeChildren(); |
| this._uiSourceCodeNodes.clear(); |
| this._subfolderNodes.clear(); |
| this._rootNode.reset(); |
| }, |
| |
| handleContextMenu: function(event, uiSourceCode) |
| { |
| var contextMenu = new WebInspector.ContextMenu(event); |
| contextMenu.appendApplicableItems(uiSourceCode); |
| contextMenu.show(); |
| }, |
| |
| handleFolderContextMenu: function(event, node) |
| { |
| var contextMenu = new WebInspector.ContextMenu(event); |
| var path = "/"; |
| while (node.parent !== this._rootNode) { |
| path = "/" + node.id + path; |
| node = node.parent; |
| } |
| |
| var project = node._project; |
| |
| if (project.type() === WebInspector.projectTypes.FileSystem) { |
| function refresh() |
| { |
| project.refresh(path); |
| } |
| |
| function create() |
| { |
| var data = {}; |
| data.project = project; |
| data.path = path; |
| this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemCreationRequested, data); |
| } |
| |
| contextMenu.appendItem(WebInspector.UIString("Refresh"), refresh.bind(this)); |
| contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "New file" : "New File"), create.bind(this)); |
| } |
| |
| contextMenu.show(); |
| }, |
| |
| _treeKeyPress: function(event) |
| { |
| if (WebInspector.isBeingEdited(this._scriptsTree.childrenListElement)) |
| return; |
| |
| var searchText = String.fromCharCode(event.charCode); |
| if (searchText.trim() !== searchText) |
| return; |
| this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemSearchStarted, searchText); |
| event.consume(true); |
| }, |
| |
| __proto__: WebInspector.View.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {TreeOutline} |
| * @param {Element} element |
| */ |
| WebInspector.NavigatorTreeOutline = function(element) |
| { |
| TreeOutline.call(this, element); |
| this.element = element; |
| |
| this.comparator = WebInspector.NavigatorTreeOutline._treeElementsCompare; |
| } |
| |
| WebInspector.NavigatorTreeOutline.Types = { |
| Root: "Root", |
| Domain: "Domain", |
| Folder: "Folder", |
| UISourceCode: "UISourceCode", |
| FileSystem: "FileSystem" |
| } |
| |
| WebInspector.NavigatorTreeOutline._treeElementsCompare = function compare(treeElement1, treeElement2) |
| { |
| // Insert in the alphabetical order, first domains, then folders, then scripts. |
| function typeWeight(treeElement) |
| { |
| var type = treeElement.type(); |
| if (type === WebInspector.NavigatorTreeOutline.Types.Domain) { |
| if (treeElement.titleText === WebInspector.inspectedPageDomain) |
| return 1; |
| return 2; |
| } |
| if (type === WebInspector.NavigatorTreeOutline.Types.FileSystem) |
| return 3; |
| if (type === WebInspector.NavigatorTreeOutline.Types.Folder) |
| return 4; |
| return 5; |
| } |
| |
| var typeWeight1 = typeWeight(treeElement1); |
| var typeWeight2 = typeWeight(treeElement2); |
| |
| var result; |
| if (typeWeight1 > typeWeight2) |
| result = 1; |
| else if (typeWeight1 < typeWeight2) |
| result = -1; |
| else { |
| var title1 = treeElement1.titleText; |
| var title2 = treeElement2.titleText; |
| result = title1.compareTo(title2); |
| } |
| return result; |
| } |
| |
| WebInspector.NavigatorTreeOutline.prototype = { |
| /** |
| * @return {Array.<WebInspector.UISourceCode>} |
| */ |
| scriptTreeElements: function() |
| { |
| var result = []; |
| if (this.children.length) { |
| for (var treeElement = this.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this, true)) { |
| if (treeElement instanceof WebInspector.NavigatorSourceTreeElement) |
| result.push(treeElement.uiSourceCode); |
| } |
| } |
| return result; |
| }, |
| |
| __proto__: TreeOutline.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {TreeElement} |
| * @param {string} type |
| * @param {string} title |
| * @param {Array.<string>} iconClasses |
| * @param {boolean} hasChildren |
| * @param {boolean=} noIcon |
| */ |
| WebInspector.BaseNavigatorTreeElement = function(type, title, iconClasses, hasChildren, noIcon) |
| { |
| this._type = type; |
| TreeElement.call(this, "", null, hasChildren); |
| this._titleText = title; |
| this._iconClasses = iconClasses; |
| this._noIcon = noIcon; |
| } |
| |
| WebInspector.BaseNavigatorTreeElement.prototype = { |
| onattach: function() |
| { |
| this.listItemElement.removeChildren(); |
| if (this._iconClasses) { |
| for (var i = 0; i < this._iconClasses.length; ++i) |
| this.listItemElement.addStyleClass(this._iconClasses[i]); |
| } |
| |
| var selectionElement = document.createElement("div"); |
| selectionElement.className = "selection"; |
| this.listItemElement.appendChild(selectionElement); |
| |
| if (!this._noIcon) { |
| this.imageElement = document.createElement("img"); |
| this.imageElement.className = "icon"; |
| this.listItemElement.appendChild(this.imageElement); |
| } |
| |
| this.titleElement = document.createElement("div"); |
| this.titleElement.className = "base-navigator-tree-element-title"; |
| this._titleTextNode = document.createTextNode(""); |
| this._titleTextNode.textContent = this._titleText; |
| this.titleElement.appendChild(this._titleTextNode); |
| this.listItemElement.appendChild(this.titleElement); |
| }, |
| |
| onreveal: function() |
| { |
| if (this.listItemElement) |
| this.listItemElement.scrollIntoViewIfNeeded(true); |
| }, |
| |
| /** |
| * @return {string} |
| */ |
| get titleText() |
| { |
| return this._titleText; |
| }, |
| |
| set titleText(titleText) |
| { |
| if (this._titleText === titleText) |
| return; |
| this._titleText = titleText || ""; |
| if (this.titleElement) |
| this.titleElement.textContent = this._titleText; |
| }, |
| |
| /** |
| * @return {string} |
| */ |
| type: function() |
| { |
| return this._type; |
| }, |
| |
| __proto__: TreeElement.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.BaseNavigatorTreeElement} |
| * @param {WebInspector.NavigatorView} navigatorView |
| * @param {string} type |
| * @param {string} title |
| */ |
| WebInspector.NavigatorFolderTreeElement = function(navigatorView, type, title) |
| { |
| var iconClass = WebInspector.NavigatorView.iconClassForType(type); |
| WebInspector.BaseNavigatorTreeElement.call(this, type, title, [iconClass], true); |
| this._navigatorView = navigatorView; |
| } |
| |
| WebInspector.NavigatorFolderTreeElement.prototype = { |
| onpopulate: function() |
| { |
| this._node.populate(); |
| }, |
| |
| onattach: function() |
| { |
| WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this); |
| this.collapse(); |
| this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false); |
| }, |
| |
| /** |
| * @param {WebInspector.NavigatorFolderTreeNode} node |
| */ |
| setNode: function(node) |
| { |
| this._node = node; |
| var paths = []; |
| while (node && !node.isRoot()) { |
| paths.push(node._title); |
| node = node.parent; |
| } |
| paths.reverse(); |
| this.tooltip = paths.join("/"); |
| }, |
| |
| /** |
| * @param {Event} event |
| */ |
| _handleContextMenuEvent: function(event) |
| { |
| if (!this._node) |
| return; |
| this.select(); |
| this._navigatorView.handleFolderContextMenu(event, this._node); |
| }, |
| |
| __proto__: WebInspector.BaseNavigatorTreeElement.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.BaseNavigatorTreeElement} |
| * @param {WebInspector.NavigatorView} navigatorView |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| * @param {string} title |
| */ |
| WebInspector.NavigatorSourceTreeElement = function(navigatorView, uiSourceCode, title) |
| { |
| WebInspector.BaseNavigatorTreeElement.call(this, WebInspector.NavigatorTreeOutline.Types.UISourceCode, title, ["navigator-" + uiSourceCode.contentType().name() + "-tree-item"], false); |
| this._navigatorView = navigatorView; |
| this._uiSourceCode = uiSourceCode; |
| this.tooltip = uiSourceCode.originURL(); |
| } |
| |
| WebInspector.NavigatorSourceTreeElement.prototype = { |
| /** |
| * @return {WebInspector.UISourceCode} |
| */ |
| get uiSourceCode() |
| { |
| return this._uiSourceCode; |
| }, |
| |
| onattach: function() |
| { |
| WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this); |
| this.listItemElement.draggable = true; |
| this.listItemElement.addEventListener("click", this._onclick.bind(this), false); |
| this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false); |
| this.listItemElement.addEventListener("mousedown", this._onmousedown.bind(this), false); |
| this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false); |
| }, |
| |
| _onmousedown: function(event) |
| { |
| if (event.which === 1) // Warm-up data for drag'n'drop |
| this._uiSourceCode.requestContent(callback.bind(this)); |
| /** |
| * @param {?string} content |
| * @param {boolean} contentEncoded |
| * @param {string} mimeType |
| */ |
| function callback(content, contentEncoded, mimeType) |
| { |
| this._warmedUpContent = content; |
| } |
| }, |
| |
| _shouldRenameOnMouseDown: function() |
| { |
| if (!this._uiSourceCode.canRename()) |
| return false; |
| var isSelected = this === this.treeOutline.selectedTreeElement; |
| var isFocused = this.treeOutline.childrenListElement.isSelfOrAncestor(document.activeElement); |
| return isSelected && isFocused && !WebInspector.isBeingEdited(this.treeOutline.element); |
| }, |
| |
| selectOnMouseDown: function(event) |
| { |
| if (event.which !== 1 || !this._shouldRenameOnMouseDown()) { |
| TreeElement.prototype.selectOnMouseDown.call(this, event); |
| return; |
| } |
| setTimeout(rename.bind(this), 300); |
| |
| function rename() |
| { |
| if (this._shouldRenameOnMouseDown()) |
| this._navigatorView.requestRename(this._uiSourceCode); |
| } |
| }, |
| |
| _ondragstart: function(event) |
| { |
| event.dataTransfer.setData("text/plain", this._warmedUpContent); |
| event.dataTransfer.effectAllowed = "copy"; |
| return true; |
| }, |
| |
| onspace: function() |
| { |
| this._navigatorView._scriptSelected(this.uiSourceCode, true); |
| return true; |
| }, |
| |
| /** |
| * @param {Event} event |
| */ |
| _onclick: function(event) |
| { |
| this._navigatorView._scriptSelected(this.uiSourceCode, false); |
| }, |
| |
| /** |
| * @param {Event} event |
| */ |
| ondblclick: function(event) |
| { |
| var middleClick = event.button === 1; |
| this._navigatorView._scriptSelected(this.uiSourceCode, !middleClick); |
| }, |
| |
| onenter: function() |
| { |
| this._navigatorView._scriptSelected(this.uiSourceCode, true); |
| return true; |
| }, |
| |
| /** |
| * @param {Event} event |
| */ |
| _handleContextMenuEvent: function(event) |
| { |
| this.select(); |
| this._navigatorView.handleContextMenu(event, this._uiSourceCode); |
| }, |
| |
| __proto__: WebInspector.BaseNavigatorTreeElement.prototype |
| } |
| |
| /** |
| * @constructor |
| * @param {string} id |
| */ |
| WebInspector.NavigatorTreeNode = function(id) |
| { |
| this.id = id; |
| /** @type {!StringMap.<!WebInspector.NavigatorTreeNode>} */ |
| this._children = new StringMap(); |
| } |
| |
| WebInspector.NavigatorTreeNode.prototype = { |
| /** |
| * @return {TreeElement} |
| */ |
| treeElement: function() { }, |
| |
| dispose: function() { }, |
| |
| /** |
| * @return {boolean} |
| */ |
| isRoot: function() |
| { |
| return false; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| hasChildren: function() |
| { |
| return true; |
| }, |
| |
| populate: function() |
| { |
| if (this.isPopulated()) |
| return; |
| if (this.parent) |
| this.parent.populate(); |
| this._populated = true; |
| this.wasPopulated(); |
| }, |
| |
| wasPopulated: function() |
| { |
| var children = this.children(); |
| for (var i = 0; i < children.length; ++i) |
| this.treeElement().appendChild(children[i].treeElement()); |
| }, |
| |
| /** |
| * @param {!WebInspector.NavigatorTreeNode} node |
| */ |
| didAddChild: function(node) |
| { |
| if (this.isPopulated()) |
| this.treeElement().appendChild(node.treeElement()); |
| }, |
| |
| /** |
| * @param {!WebInspector.NavigatorTreeNode} node |
| */ |
| willRemoveChild: function(node) |
| { |
| if (this.isPopulated()) |
| this.treeElement().removeChild(node.treeElement()); |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| isPopulated: function() |
| { |
| return this._populated; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| isEmpty: function() |
| { |
| return !this._children.size(); |
| }, |
| |
| /** |
| * @param {string} id |
| * @return {WebInspector.NavigatorTreeNode} |
| */ |
| child: function(id) |
| { |
| return this._children.get(id); |
| }, |
| |
| /** |
| * @return {!Array.<!WebInspector.NavigatorTreeNode>} |
| */ |
| children: function() |
| { |
| return this._children.values(); |
| }, |
| |
| /** |
| * @param {!WebInspector.NavigatorTreeNode} node |
| */ |
| appendChild: function(node) |
| { |
| this._children.put(node.id, node); |
| node.parent = this; |
| this.didAddChild(node); |
| }, |
| |
| /** |
| * @param {!WebInspector.NavigatorTreeNode} node |
| */ |
| removeChild: function(node) |
| { |
| this.willRemoveChild(node); |
| this._children.remove(node.id); |
| delete node.parent; |
| node.dispose(); |
| }, |
| |
| reset: function() |
| { |
| this._children.clear(); |
| } |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.NavigatorTreeNode} |
| * @param {WebInspector.NavigatorView} navigatorView |
| */ |
| WebInspector.NavigatorRootTreeNode = function(navigatorView) |
| { |
| WebInspector.NavigatorTreeNode.call(this, ""); |
| this._navigatorView = navigatorView; |
| } |
| |
| WebInspector.NavigatorRootTreeNode.prototype = { |
| /** |
| * @return {boolean} |
| */ |
| isRoot: function() |
| { |
| return true; |
| }, |
| |
| /** |
| * @return {TreeOutline} |
| */ |
| treeElement: function() |
| { |
| return this._navigatorView._scriptsTree; |
| }, |
| |
| __proto__: WebInspector.NavigatorTreeNode.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.NavigatorTreeNode} |
| * @param {WebInspector.NavigatorView} navigatorView |
| * @param {WebInspector.UISourceCode} uiSourceCode |
| */ |
| WebInspector.NavigatorUISourceCodeTreeNode = function(navigatorView, uiSourceCode) |
| { |
| WebInspector.NavigatorTreeNode.call(this, uiSourceCode.name()); |
| this._navigatorView = navigatorView; |
| this._uiSourceCode = uiSourceCode; |
| this._treeElement = null; |
| } |
| |
| WebInspector.NavigatorUISourceCodeTreeNode.prototype = { |
| /** |
| * @return {WebInspector.UISourceCode} |
| */ |
| uiSourceCode: function() |
| { |
| return this._uiSourceCode; |
| }, |
| |
| /** |
| * @return {TreeElement} |
| */ |
| treeElement: function() |
| { |
| if (this._treeElement) |
| return this._treeElement; |
| |
| this._treeElement = new WebInspector.NavigatorSourceTreeElement(this._navigatorView, this._uiSourceCode, ""); |
| this.updateTitle(); |
| |
| this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._titleChanged, this); |
| this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this); |
| this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this); |
| this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.FormattedChanged, this._formattedChanged, this); |
| |
| return this._treeElement; |
| }, |
| |
| /** |
| * @param {boolean=} ignoreIsDirty |
| */ |
| updateTitle: function(ignoreIsDirty) |
| { |
| if (!this._treeElement) |
| return; |
| |
| var titleText = this._uiSourceCode.displayName(); |
| if (!ignoreIsDirty && this._uiSourceCode.isDirty()) |
| titleText = "*" + titleText; |
| this._treeElement.titleText = titleText; |
| }, |
| |
| /** |
| * @return {boolean} |
| */ |
| hasChildren: function() |
| { |
| return false; |
| }, |
| |
| dispose: function() |
| { |
| if (!this._treeElement) |
| return; |
| this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.TitleChanged, this._titleChanged, this); |
| this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyChanged, this._workingCopyChanged, this); |
| this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.WorkingCopyCommitted, this._workingCopyCommitted, this); |
| this._uiSourceCode.removeEventListener(WebInspector.UISourceCode.Events.FormattedChanged, this._formattedChanged, this); |
| }, |
| |
| _titleChanged: function(event) |
| { |
| this.updateTitle(); |
| }, |
| |
| _workingCopyChanged: function(event) |
| { |
| this.updateTitle(); |
| }, |
| |
| _workingCopyCommitted: function(event) |
| { |
| this.updateTitle(); |
| }, |
| |
| _formattedChanged: function(event) |
| { |
| this.updateTitle(); |
| }, |
| |
| /** |
| * @param {boolean=} select |
| */ |
| reveal: function(select) |
| { |
| this.parent.populate(); |
| this.parent.treeElement().expand(); |
| this._treeElement.reveal(); |
| if (select) |
| this._treeElement.select(); |
| }, |
| |
| /** |
| * @param {function(boolean)=} callback |
| */ |
| rename: function(callback) |
| { |
| if (!this._treeElement) |
| return; |
| |
| // Tree outline should be marked as edited as well as the tree element to prevent search from starting. |
| var treeOutlineElement = this._treeElement.treeOutline.element; |
| WebInspector.markBeingEdited(treeOutlineElement, true); |
| |
| function commitHandler(element, newTitle, oldTitle) |
| { |
| if (newTitle !== oldTitle) { |
| this._treeElement.titleText = newTitle; |
| this._uiSourceCode.rename(newTitle, renameCallback.bind(this)); |
| return; |
| } |
| afterEditing.call(this, true); |
| } |
| |
| function renameCallback(success) |
| { |
| if (!success) { |
| WebInspector.markBeingEdited(treeOutlineElement, false); |
| this.updateTitle(); |
| this.rename(callback); |
| return; |
| } |
| afterEditing.call(this, true); |
| } |
| |
| function cancelHandler() |
| { |
| afterEditing.call(this, false); |
| } |
| |
| /** |
| * @param {boolean} committed |
| */ |
| function afterEditing(committed) |
| { |
| WebInspector.markBeingEdited(treeOutlineElement, false); |
| this.updateTitle(); |
| this._treeElement.treeOutline.childrenListElement.focus(); |
| if (callback) |
| callback(committed); |
| } |
| |
| var editingConfig = new WebInspector.EditingConfig(commitHandler.bind(this), cancelHandler.bind(this)); |
| this.updateTitle(true); |
| WebInspector.startEditing(this._treeElement.titleElement, editingConfig); |
| window.getSelection().setBaseAndExtent(this._treeElement.titleElement, 0, this._treeElement.titleElement, 1); |
| }, |
| |
| __proto__: WebInspector.NavigatorTreeNode.prototype |
| } |
| |
| /** |
| * @constructor |
| * @extends {WebInspector.NavigatorTreeNode} |
| * @param {WebInspector.NavigatorView} navigatorView |
| * @param {WebInspector.Project} project |
| * @param {string} id |
| * @param {string} type |
| * @param {string} folderPath |
| * @param {string} title |
| */ |
| WebInspector.NavigatorFolderTreeNode = function(navigatorView, project, id, type, folderPath, title) |
| { |
| WebInspector.NavigatorTreeNode.call(this, id); |
| this._navigatorView = navigatorView; |
| this._project = project; |
| this._type = type; |
| this._folderPath = folderPath; |
| this._title = title; |
| } |
| |
| WebInspector.NavigatorFolderTreeNode.prototype = { |
| /** |
| * @return {TreeElement} |
| */ |
| treeElement: function() |
| { |
| if (this._treeElement) |
| return this._treeElement; |
| this._treeElement = this._createTreeElement(this._title, this); |
| return this._treeElement; |
| }, |
| |
| /** |
| * @return {TreeElement} |
| */ |
| _createTreeElement: function(title, node) |
| { |
| var treeElement = new WebInspector.NavigatorFolderTreeElement(this._navigatorView, this._type, title); |
| treeElement.setNode(node); |
| return treeElement; |
| }, |
| |
| wasPopulated: function() |
| { |
| if (!this._treeElement || this._treeElement._node !== this) |
| return; |
| this._addChildrenRecursive(); |
| }, |
| |
| _addChildrenRecursive: function() |
| { |
| var children = this.children(); |
| for (var i = 0; i < children.length; ++i) { |
| var child = children[i]; |
| this.didAddChild(child); |
| if (child instanceof WebInspector.NavigatorFolderTreeNode) |
| child._addChildrenRecursive(); |
| } |
| }, |
| |
| _shouldMerge: function(node) |
| { |
| return this._type !== WebInspector.NavigatorTreeOutline.Types.Domain && node instanceof WebInspector.NavigatorFolderTreeNode; |
| }, |
| |
| didAddChild: function(node) |
| { |
| function titleForNode(node) |
| { |
| return node._title; |
| } |
| |
| if (!this._treeElement) |
| return; |
| |
| var children = this.children(); |
| |
| if (children.length === 1 && this._shouldMerge(node)) { |
| node._isMerged = true; |
| this._treeElement.titleText = this._treeElement.titleText + "/" + node._title; |
| node._treeElement = this._treeElement; |
| this._treeElement.setNode(node); |
| return; |
| } |
| |
| var oldNode; |
| if (children.length === 2) |
| oldNode = children[0] !== node ? children[0] : children[1]; |
| if (oldNode && oldNode._isMerged) { |
| delete oldNode._isMerged; |
| var mergedToNodes = []; |
| mergedToNodes.push(this); |
| var treeNode = this; |
| while (treeNode._isMerged) { |
| treeNode = treeNode.parent; |
| mergedToNodes.push(treeNode); |
| } |
| mergedToNodes.reverse(); |
| var titleText = mergedToNodes.map(titleForNode).join("/"); |
| |
| var nodes = []; |
| treeNode = oldNode; |
| do { |
| nodes.push(treeNode); |
| children = treeNode.children(); |
| treeNode = children.length === 1 ? children[0] : null; |
| } while (treeNode && treeNode._isMerged); |
| |
| if (!this.isPopulated()) { |
| this._treeElement.titleText = titleText; |
| this._treeElement.setNode(this); |
| for (var i = 0; i < nodes.length; ++i) { |
| delete nodes[i]._treeElement; |
| delete nodes[i]._isMerged; |
| } |
| return; |
| } |
| var oldTreeElement = this._treeElement; |
| var treeElement = this._createTreeElement(titleText, this); |
| for (var i = 0; i < mergedToNodes.length; ++i) |
| mergedToNodes[i]._treeElement = treeElement; |
| oldTreeElement.parent.appendChild(treeElement); |
| |
| oldTreeElement.setNode(nodes[nodes.length - 1]); |
| oldTreeElement.titleText = nodes.map(titleForNode).join("/"); |
| oldTreeElement.parent.removeChild(oldTreeElement); |
| this._treeElement.appendChild(oldTreeElement); |
| if (oldTreeElement.expanded) |
| treeElement.expand(); |
| } |
| if (this.isPopulated()) |
| this._treeElement.appendChild(node.treeElement()); |
| }, |
| |
| willRemoveChild: function(node) |
| { |
| if (node._isMerged || !this.isPopulated()) |
| return; |
| this._treeElement.removeChild(node._treeElement); |
| }, |
| |
| __proto__: WebInspector.NavigatorTreeNode.prototype |
| } |