diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2017-06-27 06:07:23 +0000 |
commit | 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch) | |
tree | 46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js | |
parent | 32761a6cee1d0dee366b885b7b9c777e67885688 (diff) | |
download | WebKitGtk-tarball-master.tar.gz |
webkitgtk-2.16.5HEADwebkitgtk-2.16.5master
Diffstat (limited to 'Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js')
-rw-r--r-- | Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js | 754 |
1 files changed, 754 insertions, 0 deletions
diff --git a/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js b/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js new file mode 100644 index 000000000..b1ddb6a20 --- /dev/null +++ b/Source/WebInspectorUI/UserInterface/Views/NavigationSidebarPanel.js @@ -0,0 +1,754 @@ +/* + * Copyright (C) 2013, 2015 Apple 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 APPLE 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 APPLE 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. + */ + +WebInspector.NavigationSidebarPanel = class NavigationSidebarPanel extends WebInspector.SidebarPanel +{ + constructor(identifier, displayName, shouldAutoPruneStaleTopLevelResourceTreeElements, wantsTopOverflowShadow, element, role, label) + { + super(identifier, displayName, element, role, label || displayName); + + this.element.classList.add("navigation"); + + this.contentView.element.addEventListener("scroll", this.soon._updateContentOverflowShadowVisibility); + + this._contentTreeOutlineGroup = new WebInspector.TreeOutlineGroup; + this._contentTreeOutline = this.createContentTreeOutline(); + + this._filterBar = new WebInspector.FilterBar; + this._filterBar.addEventListener(WebInspector.FilterBar.Event.FilterDidChange, this._filterDidChange, this); + this.element.appendChild(this._filterBar.element); + + this._bottomOverflowShadowElement = document.createElement("div"); + this._bottomOverflowShadowElement.className = WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName; + this.element.appendChild(this._bottomOverflowShadowElement); + + if (wantsTopOverflowShadow) { + this._topOverflowShadowElement = document.createElement("div"); + this._topOverflowShadowElement.classList.add(WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName); + this._topOverflowShadowElement.classList.add(WebInspector.NavigationSidebarPanel.TopOverflowShadowElementStyleClassName); + this.element.appendChild(this._topOverflowShadowElement); + } + + this._boundUpdateContentOverflowShadowVisibility = this.soon._updateContentOverflowShadowVisibility; + window.addEventListener("resize", this._boundUpdateContentOverflowShadowVisibility); + + this._filtersSetting = new WebInspector.Setting(identifier + "-navigation-sidebar-filters", {}); + this._filterBar.filters = this._filtersSetting.value; + + this._emptyContentPlaceholderElements = new Map; + this._emptyFilterResults = new Map; + + this._shouldAutoPruneStaleTopLevelResourceTreeElements = shouldAutoPruneStaleTopLevelResourceTreeElements || false; + + if (this._shouldAutoPruneStaleTopLevelResourceTreeElements) { + WebInspector.Frame.addEventListener(WebInspector.Frame.Event.MainResourceDidChange, this._checkForStaleResources, this); + WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ChildFrameWasRemoved, this._checkForStaleResources, this); + WebInspector.Frame.addEventListener(WebInspector.Frame.Event.ResourceWasRemoved, this._checkForStaleResources, this); + } + + this._pendingViewStateCookie = null; + this._restoringState = false; + } + + // Public + + closed() + { + window.removeEventListener("resize", this._boundUpdateContentOverflowShadowVisibility); + WebInspector.Frame.removeEventListener(null, null, this); + } + + get contentBrowser() + { + return this._contentBrowser; + } + + set contentBrowser(contentBrowser) + { + this._contentBrowser = contentBrowser || null; + } + + get contentTreeOutline() + { + return this._contentTreeOutline; + } + + get contentTreeOutlines() + { + return this._contentTreeOutlineGroup.items; + } + + get hasSelectedElement() + { + return !!this._contentTreeOutlineGroup.selectedTreeElement + } + + get filterBar() + { + return this._filterBar; + } + + get restoringState() + { + return this._restoringState; + } + + cancelRestoringState() + { + if (!this._finalAttemptToRestoreViewStateTimeout) + return; + + clearTimeout(this._finalAttemptToRestoreViewStateTimeout); + this._finalAttemptToRestoreViewStateTimeout = undefined; + } + + createContentTreeOutline(suppressFiltering) + { + let contentTreeOutline = new WebInspector.TreeOutline; + contentTreeOutline.allowsRepeatSelection = true; + contentTreeOutline.element.classList.add(WebInspector.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName); + + this._contentTreeOutlineGroup.add(contentTreeOutline); + + this.contentView.element.appendChild(contentTreeOutline.element); + + if (!suppressFiltering) { + contentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementAdded, this._treeElementAddedOrChanged, this); + contentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDidChange, this._treeElementAddedOrChanged, this); + contentTreeOutline.addEventListener(WebInspector.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange, this); + } + + contentTreeOutline[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol] = suppressFiltering; + + return contentTreeOutline; + } + + suppressFilteringOnTreeElements(treeElements) + { + console.assert(Array.isArray(treeElements), "TreeElements should be an array."); + + for (let treeElement of treeElements) + treeElement[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol] = true; + + this._updateFilter(); + } + + treeElementForRepresentedObject(representedObject) + { + let treeElement = null; + for (let treeOutline of this.contentTreeOutlines) { + treeElement = treeOutline.getCachedTreeElement(representedObject); + if (treeElement) + break; + } + + return treeElement; + } + + showDefaultContentView() + { + // Implemented by subclasses if needed to show a content view when no existing tree element is selected. + } + + showDefaultContentViewForTreeElement(treeElement) + { + console.assert(treeElement); + console.assert(treeElement.representedObject); + if (!treeElement || !treeElement.representedObject) + return false; + + // FIXME: <https://webkit.org/b/153634> Web Inspector: some background tabs think they are the foreground tab and do unnecessary work + // Do not steal a content view if we are not the active tab/sidebar. + if (!this.selected) { + let contentView = this.contentBrowser.contentViewForRepresentedObject(treeElement.representedObject); + if (contentView && contentView.parentContainer && contentView.parentContainer !== this.contentBrowser.contentViewContainer) + return false; + + // contentView.parentContainer may be null. Check for selected tab, too. + let selectedTabContentView = WebInspector.tabBrowser.selectedTabContentView; + if (selectedTabContentView && selectedTabContentView.contentBrowser !== this.contentBrowser) + return false; + } + + let contentView = this.contentBrowser.showContentViewForRepresentedObject(treeElement.representedObject); + if (!contentView) + return false; + + treeElement.revealAndSelect(true, false, true, true); + return true; + } + + saveStateToCookie(cookie) + { + console.assert(cookie); + + // This does not save folder selections, which lack a represented object and content view. + var selectedTreeElement = null; + this.contentTreeOutlines.forEach(function(outline) { + if (outline.selectedTreeElement) + selectedTreeElement = outline.selectedTreeElement; + }); + + if (!selectedTreeElement) + return; + + if (this._isTreeElementWithoutRepresentedObject(selectedTreeElement)) + return; + + var representedObject = selectedTreeElement.representedObject; + cookie[WebInspector.TypeIdentifierCookieKey] = representedObject.constructor.TypeIdentifier; + + if (representedObject.saveIdentityToCookie) + representedObject.saveIdentityToCookie(cookie); + else + console.error("Error: TreeElement.representedObject is missing a saveIdentityToCookie implementation. TreeElement.constructor: ", selectedTreeElement.constructor); + } + + // This can be supplemented by subclasses that admit a simpler strategy for static tree elements. + restoreStateFromCookie(cookie, relaxedMatchDelay) + { + this._pendingViewStateCookie = cookie; + this._restoringState = true; + + // Check if any existing tree elements in any outline match the cookie. + this._checkOutlinesForPendingViewStateCookie(); + + if (this._finalAttemptToRestoreViewStateTimeout) + clearTimeout(this._finalAttemptToRestoreViewStateTimeout); + + if (relaxedMatchDelay === 0) + return; + + function finalAttemptToRestoreViewStateFromCookie() + { + this._finalAttemptToRestoreViewStateTimeout = undefined; + + this._checkOutlinesForPendingViewStateCookie(true); + + this._pendingViewStateCookie = null; + this._restoringState = false; + } + + // If the specific tree element wasn't found, we may need to wait for the resources + // to be registered. We try one last time (match type only) after an arbitrary amount of timeout. + this._finalAttemptToRestoreViewStateTimeout = setTimeout(finalAttemptToRestoreViewStateFromCookie.bind(this), relaxedMatchDelay); + } + + showEmptyContentPlaceholder(message, treeOutline) + { + console.assert(message); + + treeOutline = treeOutline || this._contentTreeOutline; + + let emptyContentPlaceholderElement = this._createEmptyContentPlaceholderIfNeeded(treeOutline); + if (emptyContentPlaceholderElement.parentNode && emptyContentPlaceholderElement.children[0].textContent === message) + return; + + emptyContentPlaceholderElement.children[0].textContent = message; + + let emptyContentPlaceholderParentElement = treeOutline.element.parentNode; + emptyContentPlaceholderParentElement.appendChild(emptyContentPlaceholderElement); + + this._updateContentOverflowShadowVisibility(); + } + + hideEmptyContentPlaceholder(treeOutline) + { + treeOutline = treeOutline || this._contentTreeOutline; + + let emptyContentPlaceholderElement = this._emptyContentPlaceholderElements.get(treeOutline); + if (!emptyContentPlaceholderElement || !emptyContentPlaceholderElement.parentNode) + return; + + emptyContentPlaceholderElement.remove(); + + this._updateContentOverflowShadowVisibility(); + } + + updateEmptyContentPlaceholder(message, treeOutline) + { + treeOutline = treeOutline || this._contentTreeOutline; + + if (!treeOutline.children.length) { + // No tree elements, so no results. + this.showEmptyContentPlaceholder(message, treeOutline); + } else if (!this._emptyFilterResults.get(treeOutline)) { + // There are tree elements, and not all of them are hidden by the filter. + this.hideEmptyContentPlaceholder(treeOutline); + } + } + + updateFilter() + { + this._updateFilter(); + } + + shouldFilterPopulate() + { + // Overriden by subclasses if needed. + return this.hasCustomFilters(); + } + + hasCustomFilters() + { + // Implemented by subclasses if needed. + return false; + } + + matchTreeElementAgainstCustomFilters(treeElement) + { + // Implemented by subclasses if needed. + return true; + } + + matchTreeElementAgainstFilterFunctions(treeElement) + { + if (!this._filterFunctions || !this._filterFunctions.length) + return true; + + for (var filterFunction of this._filterFunctions) { + if (filterFunction(treeElement)) + return true; + } + + return false; + } + + applyFiltersToTreeElement(treeElement) + { + if (!this._filterBar.hasActiveFilters() && !this.hasCustomFilters()) { + // No filters, so make everything visible. + treeElement.hidden = false; + + // If this tree element was expanded during filtering, collapse it again. + if (treeElement.expanded && treeElement[WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) { + treeElement[WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol] = false; + treeElement.collapse(); + } + + return; + } + + var filterableData = treeElement.filterableData || {}; + + var flags = {expandTreeElement: false}; + var filterRegex = this._textFilterRegex; + + function matchTextFilter(inputs) + { + if (!inputs || !filterRegex) + return true; + + console.assert(inputs instanceof Array, "filterableData.text should be an array of text inputs"); + + // Loop over all the inputs and try to match them. + for (var input of inputs) { + if (!input) + continue; + if (filterRegex.test(input)) { + flags.expandTreeElement = true; + return true; + } + } + + // No inputs matched. + return false; + } + + function makeVisible() + { + // Make this element visible. + treeElement.hidden = false; + + // Make the ancestors visible and expand them. + var currentAncestor = treeElement.parent; + while (currentAncestor && !currentAncestor.root) { + currentAncestor.hidden = false; + + // Only expand if the built-in filters matched, not custom filters. + if (flags.expandTreeElement && !currentAncestor.expanded) { + currentAncestor.__wasExpandedDuringFiltering = true; + currentAncestor.expand(); + } + + currentAncestor = currentAncestor.parent; + } + } + + let suppressFiltering = treeElement[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]; + + if (suppressFiltering || (matchTextFilter(filterableData.text) && this.matchTreeElementAgainstFilterFunctions(treeElement, flags) && this.matchTreeElementAgainstCustomFilters(treeElement, flags))) { + // Make this element visible since it matches. + makeVisible(); + + // If this tree element didn't match a built-in filter and was expanded earlier during filtering, collapse it again. + if (!flags.expandTreeElement && treeElement.expanded && treeElement[WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) { + treeElement[WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol] = false; + treeElement.collapse(); + } + + return; + } + + // Make this element invisible since it does not match. + treeElement.hidden = true; + } + + shown() + { + super.shown(); + + this._updateContentOverflowShadowVisibility(); + } + + // Protected + + representedObjectWasFiltered(representedObject, filtered) + { + // Implemented by subclasses if needed. + } + + pruneStaleResourceTreeElements() + { + if (this._checkForStaleResourcesTimeoutIdentifier) { + clearTimeout(this._checkForStaleResourcesTimeoutIdentifier); + this._checkForStaleResourcesTimeoutIdentifier = undefined; + } + + for (let contentTreeOutline of this.contentTreeOutlines) { + // Check all the ResourceTreeElements at the top level to make sure their Resource still has a parentFrame in the frame hierarchy. + // If the parentFrame is no longer in the frame hierarchy we know it was removed due to a navigation or some other page change and + // we should remove the issues for that resource. + for (var i = contentTreeOutline.children.length - 1; i >= 0; --i) { + var treeElement = contentTreeOutline.children[i]; + if (!(treeElement instanceof WebInspector.ResourceTreeElement)) + continue; + + var resource = treeElement.resource; + if (!resource.parentFrame || resource.parentFrame.isDetached()) + contentTreeOutline.removeChildAtIndex(i, true, true); + } + } + } + + treeElementAddedOrChanged(treeElement) + { + // Implemented by subclasses if needed. + } + + // Private + + _updateContentOverflowShadowVisibility() + { + if (!this.visible) + return; + + this._updateContentOverflowShadowVisibility.cancelDebounce(); + + let scrollHeight = this.contentView.element.scrollHeight; + let offsetHeight = this.contentView.element.offsetHeight; + + if (scrollHeight < offsetHeight) { + if (this._topOverflowShadowElement) + this._topOverflowShadowElement.style.opacity = 0; + this._bottomOverflowShadowElement.style.opacity = 0; + return; + } + + let edgeThreshold = 1; + let scrollTop = this.contentView.element.scrollTop; + + let topCoverage = Math.min(scrollTop, edgeThreshold); + let bottomCoverage = Math.max(0, (offsetHeight + scrollTop) - (scrollHeight - edgeThreshold)); + + if (this._topOverflowShadowElement) + this._topOverflowShadowElement.style.opacity = (topCoverage / edgeThreshold).toFixed(1); + this._bottomOverflowShadowElement.style.opacity = (1 - (bottomCoverage / edgeThreshold)).toFixed(1); + } + + _checkForEmptyFilterResults() + { + function checkTreeOutlineForEmptyFilterResults(treeOutline) + { + // No tree elements, so don't touch the empty content placeholder. + if (!treeOutline.children.length) + return; + + // Iterate over all the top level tree elements. If any filterable elements are visible, return early. + let filterableTreeElementFound = false; + let unfilteredTreeElementFound = false; + let currentTreeElement = treeOutline.children[0]; + while (currentTreeElement) { + let suppressFilteringForTreeElement = currentTreeElement[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]; + if (!suppressFilteringForTreeElement) { + filterableTreeElementFound = true; + + if (!currentTreeElement.hidden) { + unfilteredTreeElementFound = true; + break; + } + } + + currentTreeElement = currentTreeElement.nextSibling; + } + + if (unfilteredTreeElementFound || !filterableTreeElementFound) { + this.hideEmptyContentPlaceholder(treeOutline); + this._emptyFilterResults.set(treeOutline, false); + return; + } + + // All top level tree elements are hidden, so filtering hid everything. Show a message. + this.showEmptyContentPlaceholder(WebInspector.UIString("No Filter Results"), treeOutline); + this._emptyFilterResults.set(treeOutline, true); + } + + for (let treeOutline of this.contentTreeOutlines) { + if (treeOutline[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]) + continue; + + checkTreeOutlineForEmptyFilterResults.call(this, treeOutline); + } + } + + _filterDidChange() + { + this._updateFilter(); + } + + _updateFilter() + { + let selectedTreeElement; + for (let treeOutline of this.contentTreeOutlines) { + if (treeOutline.hidden || treeOutline[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]) + continue; + + selectedTreeElement = treeOutline.selectedTreeElement; + if (selectedTreeElement) + break; + } + + let filters = this._filterBar.filters; + this._textFilterRegex = simpleGlobStringToRegExp(filters.text, "i"); + this._filtersSetting.value = filters; + this._filterFunctions = filters.functions; + + // Don't populate if we don't have any active filters. + // We only need to populate when a filter needs to reveal. + let dontPopulate = !this._filterBar.hasActiveFilters() && !this.shouldFilterPopulate(); + + // Update all trees that allow filtering. + for (let treeOutline of this.contentTreeOutlines) { + if (treeOutline.hidden || treeOutline[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]) + continue; + + let currentTreeElement = treeOutline.children[0]; + while (currentTreeElement && !currentTreeElement.root) { + if (!currentTreeElement[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]) { + const currentTreeElementWasHidden = currentTreeElement.hidden; + this.applyFiltersToTreeElement(currentTreeElement); + if (currentTreeElementWasHidden !== currentTreeElement.hidden) + this.representedObjectWasFiltered(currentTreeElement.representedObject, currentTreeElement.hidden); + } + + currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, dontPopulate); + } + } + + this._checkForEmptyFilterResults(); + this._updateContentOverflowShadowVisibility(); + } + + _treeElementAddedOrChanged(event) + { + // Don't populate if we don't have any active filters. + // We only need to populate when a filter needs to reveal. + var dontPopulate = !this._filterBar.hasActiveFilters() && !this.shouldFilterPopulate(); + + // Apply the filters to the tree element and its descendants. + let treeElement = event.data.element; + let currentTreeElement = treeElement; + while (currentTreeElement && !currentTreeElement.root) { + if (!currentTreeElement[WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol]) { + const currentTreeElementWasHidden = currentTreeElement.hidden; + this.applyFiltersToTreeElement(currentTreeElement); + if (currentTreeElementWasHidden !== currentTreeElement.hidden) + this.representedObjectWasFiltered(currentTreeElement.representedObject, currentTreeElement.hidden); + } + + currentTreeElement = currentTreeElement.traverseNextTreeElement(false, treeElement, dontPopulate); + } + + this._checkForEmptyFilterResults(); + + if (this.visible) + this.soon._updateContentOverflowShadowVisibility(); + + if (this.selected) + this._checkElementsForPendingViewStateCookie([treeElement]); + + this.treeElementAddedOrChanged(treeElement); + } + + _treeElementDisclosureDidChange(event) + { + this.soon._updateContentOverflowShadowVisibility(); + } + + _checkForStaleResourcesIfNeeded() + { + if (!this._checkForStaleResourcesTimeoutIdentifier || !this._shouldAutoPruneStaleTopLevelResourceTreeElements) + return; + this.pruneStaleResourceTreeElements(); + } + + _checkForStaleResources(event) + { + console.assert(this._shouldAutoPruneStaleTopLevelResourceTreeElements); + + if (this._checkForStaleResourcesTimeoutIdentifier) + return; + + // Check on a delay to coalesce multiple calls to _checkForStaleResources. + this._checkForStaleResourcesTimeoutIdentifier = setTimeout(this.pruneStaleResourceTreeElements.bind(this)); + } + + _isTreeElementWithoutRepresentedObject(treeElement) + { + return treeElement instanceof WebInspector.FolderTreeElement + || treeElement instanceof WebInspector.DatabaseHostTreeElement + || treeElement instanceof WebInspector.IndexedDatabaseHostTreeElement + || treeElement instanceof WebInspector.ApplicationCacheManifestTreeElement + || treeElement instanceof WebInspector.ThreadTreeElement + || treeElement instanceof WebInspector.IdleTreeElement + || typeof treeElement.representedObject === "string" + || treeElement.representedObject instanceof String; + } + + _checkOutlinesForPendingViewStateCookie(matchTypeOnly) + { + if (!this._pendingViewStateCookie) + return; + + this._checkForStaleResourcesIfNeeded(); + + var visibleTreeElements = []; + this.contentTreeOutlines.forEach(function(outline) { + var currentTreeElement = outline.hasChildren ? outline.children[0] : null; + while (currentTreeElement) { + visibleTreeElements.push(currentTreeElement); + currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, false); + } + }); + + return this._checkElementsForPendingViewStateCookie(visibleTreeElements, matchTypeOnly); + } + + _checkElementsForPendingViewStateCookie(treeElements, matchTypeOnly) + { + if (!this._pendingViewStateCookie) + return; + + var cookie = this._pendingViewStateCookie; + + function treeElementMatchesCookie(treeElement) + { + if (this._isTreeElementWithoutRepresentedObject(treeElement)) + return false; + + var representedObject = treeElement.representedObject; + if (!representedObject) + return false; + + var typeIdentifier = cookie[WebInspector.TypeIdentifierCookieKey]; + if (typeIdentifier !== representedObject.constructor.TypeIdentifier) + return false; + + if (matchTypeOnly) + return true; + + var candidateObjectCookie = {}; + if (representedObject.saveIdentityToCookie) + representedObject.saveIdentityToCookie(candidateObjectCookie); + + var candidateCookieKeys = Object.keys(candidateObjectCookie); + return candidateCookieKeys.length && candidateCookieKeys.every((key) => candidateObjectCookie[key] === cookie[key]); + } + + var matchedElement = null; + treeElements.some((element) => { + if (treeElementMatchesCookie.call(this, element)) { + matchedElement = element; + return true; + } + return false; + }); + + if (matchedElement) { + let didShowContentView = this.showDefaultContentViewForTreeElement(matchedElement); + if (!didShowContentView) + return; + + this._pendingViewStateCookie = null; + + // Delay clearing the restoringState flag until the next runloop so listeners + // checking for it in this runloop still know state was being restored. + setTimeout(() => { + this._restoringState = false; + }, 0); + + if (this._finalAttemptToRestoreViewStateTimeout) { + clearTimeout(this._finalAttemptToRestoreViewStateTimeout); + this._finalAttemptToRestoreViewStateTimeout = undefined; + } + } + } + + _createEmptyContentPlaceholderIfNeeded(treeOutline) + { + let emptyContentPlaceholderElement = this._emptyContentPlaceholderElements.get(treeOutline); + if (emptyContentPlaceholderElement) + return emptyContentPlaceholderElement; + + emptyContentPlaceholderElement = document.createElement("div"); + emptyContentPlaceholderElement.classList.add(WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderElementStyleClassName); + this._emptyContentPlaceholderElements.set(treeOutline, emptyContentPlaceholderElement); + + let emptyContentPlaceholderMessageElement = document.createElement("div"); + emptyContentPlaceholderMessageElement.className = WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderMessageElementStyleClassName; + emptyContentPlaceholderElement.appendChild(emptyContentPlaceholderMessageElement); + + return emptyContentPlaceholderElement; + } +}; + +WebInspector.NavigationSidebarPanel.SuppressFilteringSymbol = Symbol("suppress-filtering"); +WebInspector.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering"); + +WebInspector.NavigationSidebarPanel.OverflowShadowElementStyleClassName = "overflow-shadow"; +WebInspector.NavigationSidebarPanel.TopOverflowShadowElementStyleClassName = "top"; +WebInspector.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName = "navigation-sidebar-panel-content-tree-outline"; +WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderElementStyleClassName = "empty-content-placeholder"; +WebInspector.NavigationSidebarPanel.EmptyContentPlaceholderMessageElementStyleClassName = "message"; |