added Linux arm64 SDK
This commit is contained in:
@@ -0,0 +1,772 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
WI.NavigationSidebarPanel = class NavigationSidebarPanel extends WI.SidebarPanel
|
||||
{
|
||||
constructor(identifier, displayName, shouldAutoPruneStaleTopLevelResourceTreeElements, wantsTopOverflowShadow)
|
||||
{
|
||||
super(identifier, displayName);
|
||||
|
||||
this.element.classList.add("navigation");
|
||||
|
||||
this._updateContentOverflowShadowVisibilityDebouncer = new Debouncer(() => {
|
||||
this._updateContentOverflowShadowVisibility();
|
||||
});
|
||||
this._boundUpdateContentOverflowShadowVisibilitySoon = (event) => {
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
|
||||
};
|
||||
|
||||
this.contentView.element.addEventListener("scroll", this._boundUpdateContentOverflowShadowVisibilitySoon);
|
||||
|
||||
this._contentTreeOutlineGroup = new WI.TreeOutlineGroup;
|
||||
this._contentTreeOutline = this.createContentTreeOutline();
|
||||
|
||||
this._filterBar = new WI.FilterBar;
|
||||
this._filterBar.addEventListener(WI.FilterBar.Event.FilterDidChange, this._filterDidChange, this);
|
||||
this.element.appendChild(this._filterBar.element);
|
||||
|
||||
this._bottomOverflowShadowElement = document.createElement("div");
|
||||
this._bottomOverflowShadowElement.className = WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName;
|
||||
this.element.appendChild(this._bottomOverflowShadowElement);
|
||||
|
||||
if (wantsTopOverflowShadow) {
|
||||
this._topOverflowShadowElement = this.element.appendChild(document.createElement("div"));
|
||||
this._topOverflowShadowElement.classList.add(WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName, "top");
|
||||
}
|
||||
|
||||
window.addEventListener("resize", this._boundUpdateContentOverflowShadowVisibilitySoon);
|
||||
|
||||
this._filtersSetting = new WI.Setting(identifier + "-navigation-sidebar-filters", {});
|
||||
this._filterBar.filters = this._filtersSetting.value;
|
||||
|
||||
this._emptyContentPlaceholderElements = new Map;
|
||||
this._emptyFilterResults = new Set;
|
||||
|
||||
this._shouldAutoPruneStaleTopLevelResourceTreeElements = shouldAutoPruneStaleTopLevelResourceTreeElements || false;
|
||||
|
||||
if (this._shouldAutoPruneStaleTopLevelResourceTreeElements) {
|
||||
WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._checkForStaleResources, this);
|
||||
WI.Frame.addEventListener(WI.Frame.Event.ChildFrameWasRemoved, this._checkForStaleResources, this);
|
||||
WI.Frame.addEventListener(WI.Frame.Event.ResourceWasRemoved, this._checkForStaleResources, this);
|
||||
}
|
||||
|
||||
this._pendingViewStateCookie = null;
|
||||
this._restoringState = false;
|
||||
}
|
||||
|
||||
// Public
|
||||
|
||||
get filterBar() { return this._filterBar; }
|
||||
get hasActiveFilters() { return this._filterBar.hasActiveFilters(); }
|
||||
|
||||
closed()
|
||||
{
|
||||
window.removeEventListener("resize", this._boundUpdateContentOverflowShadowVisibilitySoon);
|
||||
|
||||
if (this._shouldAutoPruneStaleTopLevelResourceTreeElements) {
|
||||
WI.Frame.removeEventListener(WI.Frame.Event.MainResourceDidChange, this._checkForStaleResources, this);
|
||||
WI.Frame.removeEventListener(WI.Frame.Event.ChildFrameWasRemoved, this._checkForStaleResources, this);
|
||||
WI.Frame.removeEventListener(WI.Frame.Event.ResourceWasRemoved, this._checkForStaleResources, this);
|
||||
}
|
||||
}
|
||||
|
||||
get contentBrowser()
|
||||
{
|
||||
return this._contentBrowser;
|
||||
}
|
||||
|
||||
set contentBrowser(contentBrowser)
|
||||
{
|
||||
this._contentBrowser = contentBrowser || null;
|
||||
}
|
||||
|
||||
get contentTreeOutline()
|
||||
{
|
||||
return this._contentTreeOutline;
|
||||
}
|
||||
|
||||
get contentTreeOutlines()
|
||||
{
|
||||
return Array.from(this._contentTreeOutlineGroup);
|
||||
}
|
||||
|
||||
get currentRepresentedObject()
|
||||
{
|
||||
if (!this._contentBrowser)
|
||||
return null;
|
||||
|
||||
return this._contentBrowser.currentRepresentedObjects[0] || null;
|
||||
}
|
||||
|
||||
get restoringState()
|
||||
{
|
||||
return this._restoringState;
|
||||
}
|
||||
|
||||
cancelRestoringState()
|
||||
{
|
||||
this._pendingViewStateCookie = null;
|
||||
if (!this._finalAttemptToRestoreViewStateTimeout)
|
||||
return;
|
||||
|
||||
clearTimeout(this._finalAttemptToRestoreViewStateTimeout);
|
||||
this._finalAttemptToRestoreViewStateTimeout = undefined;
|
||||
}
|
||||
|
||||
createContentTreeOutline({ignoreCookieRestoration, suppressFiltering} = {})
|
||||
{
|
||||
let contentTreeOutline = new WI.TreeOutline;
|
||||
contentTreeOutline.allowsRepeatSelection = true;
|
||||
contentTreeOutline.element.classList.add(WI.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName);
|
||||
|
||||
this._contentTreeOutlineGroup.add(contentTreeOutline);
|
||||
|
||||
this.contentView.element.appendChild(contentTreeOutline.element);
|
||||
|
||||
if (!suppressFiltering) {
|
||||
contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._treeElementAddedOrChanged, this);
|
||||
contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementDidChange, this._treeElementAddedOrChanged, this);
|
||||
contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementDisclosureDidChanged, this._treeElementDisclosureDidChange, this);
|
||||
contentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._handleTreeElementRemoved, this);
|
||||
}
|
||||
|
||||
contentTreeOutline[WI.NavigationSidebarPanel.IgnoreCookieRestoration] = ignoreCookieRestoration;
|
||||
contentTreeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol] = suppressFiltering;
|
||||
|
||||
return contentTreeOutline;
|
||||
}
|
||||
|
||||
suppressFilteringOnTreeElements(treeElements)
|
||||
{
|
||||
console.assert(Array.isArray(treeElements), "TreeElements should be an array.");
|
||||
|
||||
for (let treeElement of treeElements)
|
||||
treeElement[WI.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 = WI.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);
|
||||
return true;
|
||||
}
|
||||
|
||||
canShowRepresentedObject(representedObject)
|
||||
{
|
||||
let selectedTabContentView = WI.tabBrowser.selectedTabContentView;
|
||||
console.assert(selectedTabContentView instanceof WI.TabContentView, "Missing TabContentView for NavigationSidebarPanel.");
|
||||
return selectedTabContentView && selectedTabContentView.canShowRepresentedObject(representedObject);
|
||||
}
|
||||
|
||||
saveStateToCookie(cookie)
|
||||
{
|
||||
console.assert(cookie);
|
||||
|
||||
if (!this._contentBrowser)
|
||||
return;
|
||||
|
||||
let representedObject = this.currentRepresentedObject;
|
||||
if (!representedObject)
|
||||
return;
|
||||
|
||||
cookie[WI.TypeIdentifierCookieKey] = representedObject.constructor.TypeIdentifier;
|
||||
|
||||
if (representedObject.saveIdentityToCookie) {
|
||||
representedObject.saveIdentityToCookie(cookie);
|
||||
return;
|
||||
}
|
||||
|
||||
console.error("NavigationSidebarPanel representedObject is missing a saveIdentityToCookie implementation.", representedObject);
|
||||
}
|
||||
|
||||
// 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._emptyContentPlaceholderElements.get(treeOutline);
|
||||
if (emptyContentPlaceholderElement)
|
||||
emptyContentPlaceholderElement.remove();
|
||||
|
||||
emptyContentPlaceholderElement = message instanceof Node ? message : WI.createMessageTextView(message);
|
||||
this._emptyContentPlaceholderElements.set(treeOutline, emptyContentPlaceholderElement);
|
||||
|
||||
let emptyContentPlaceholderParentElement = treeOutline.element.parentNode;
|
||||
emptyContentPlaceholderParentElement.appendChild(emptyContentPlaceholderElement);
|
||||
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.force();
|
||||
|
||||
return emptyContentPlaceholderElement;
|
||||
}
|
||||
|
||||
hideEmptyContentPlaceholder(treeOutline)
|
||||
{
|
||||
treeOutline = treeOutline || this._contentTreeOutline;
|
||||
|
||||
let emptyContentPlaceholderElement = this._emptyContentPlaceholderElements.get(treeOutline);
|
||||
if (!emptyContentPlaceholderElement || !emptyContentPlaceholderElement.parentNode)
|
||||
return;
|
||||
|
||||
emptyContentPlaceholderElement.remove();
|
||||
this._emptyContentPlaceholderElements.delete(treeOutline);
|
||||
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.force();
|
||||
}
|
||||
|
||||
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.has(treeOutline)) {
|
||||
// There are tree elements, and not all of them are hidden by the filter.
|
||||
this.hideEmptyContentPlaceholder(treeOutline);
|
||||
}
|
||||
}
|
||||
|
||||
updateFilter()
|
||||
{
|
||||
let filters = this._filterBar.filters;
|
||||
this._textFilterRegex = filters.text ? WI.SearchUtilities.filterRegExpForString(filters.text, WI.SearchUtilities.defaultSettings) : null;
|
||||
this._filtersSetting.value = filters;
|
||||
this._filterFunctions = filters.functions;
|
||||
|
||||
this._filterBar.invalid = filters.text && !this._textFilterRegex;
|
||||
|
||||
// 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[WI.NavigationSidebarPanel.SuppressFilteringSymbol])
|
||||
continue;
|
||||
|
||||
let currentTreeElement = treeOutline.children[0];
|
||||
while (currentTreeElement && !currentTreeElement.root) {
|
||||
if (!currentTreeElement[WI.NavigationSidebarPanel.SuppressFilteringSymbol]) {
|
||||
const currentTreeElementWasHidden = currentTreeElement.hidden;
|
||||
this.applyFiltersToTreeElement(currentTreeElement);
|
||||
if (currentTreeElementWasHidden !== currentTreeElement.hidden)
|
||||
this._treeElementWasFiltered(currentTreeElement);
|
||||
}
|
||||
|
||||
currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, dontPopulate);
|
||||
}
|
||||
|
||||
this._checkForEmptyFilterResults(treeOutline);
|
||||
}
|
||||
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.force();
|
||||
}
|
||||
|
||||
resetFilter()
|
||||
{
|
||||
this._filterBar.clear();
|
||||
}
|
||||
|
||||
shouldFilterPopulate()
|
||||
{
|
||||
// Overridden 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[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) {
|
||||
treeElement[WI.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[WI.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[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol]) {
|
||||
treeElement[WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol] = false;
|
||||
treeElement.collapse();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Make this element invisible since it does not match.
|
||||
treeElement.hidden = true;
|
||||
}
|
||||
|
||||
attached()
|
||||
{
|
||||
super.attached();
|
||||
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.force();
|
||||
|
||||
if (this._contentBrowser && !this._contentBrowser.currentContentView)
|
||||
this.showDefaultContentView();
|
||||
}
|
||||
|
||||
// Protected
|
||||
|
||||
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 (let i = contentTreeOutline.children.length - 1; i >= 0; --i) {
|
||||
let treeElement = contentTreeOutline.children[i];
|
||||
if (!(treeElement instanceof WI.ResourceTreeElement))
|
||||
continue;
|
||||
|
||||
// Local Overrides are never stale resources.
|
||||
let resource = treeElement.resource;
|
||||
if (resource.localResourceOverride)
|
||||
continue;
|
||||
|
||||
if (!resource.parentFrame || resource.parentFrame.isDetached())
|
||||
contentTreeOutline.removeChildAtIndex(i, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Private
|
||||
|
||||
_updateContentOverflowShadowVisibility()
|
||||
{
|
||||
if (!this.visible)
|
||||
return;
|
||||
|
||||
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(treeOutline)
|
||||
{
|
||||
if (treeOutline[WI.NavigationSidebarPanel.SuppressFilteringSymbol])
|
||||
return;
|
||||
|
||||
// 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[WI.NavigationSidebarPanel.SuppressFilteringSymbol];
|
||||
if (!suppressFilteringForTreeElement) {
|
||||
filterableTreeElementFound = true;
|
||||
|
||||
if (!currentTreeElement.hidden) {
|
||||
unfilteredTreeElementFound = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
currentTreeElement = currentTreeElement.nextSibling;
|
||||
}
|
||||
|
||||
if (unfilteredTreeElementFound || !filterableTreeElementFound) {
|
||||
this.hideEmptyContentPlaceholder(treeOutline);
|
||||
this._emptyFilterResults.delete(treeOutline);
|
||||
return;
|
||||
}
|
||||
|
||||
let message = WI.createMessageTextView(WI.UIString("No Filter Results"));
|
||||
|
||||
let buttonElement = message.appendChild(document.createElement("button"));
|
||||
buttonElement.textContent = WI.UIString("Clear Filters");
|
||||
buttonElement.addEventListener("click", () => {
|
||||
this.resetFilter();
|
||||
});
|
||||
|
||||
// All top level tree elements are hidden, so filtering hid everything. Show a message.
|
||||
this.showEmptyContentPlaceholder(message, treeOutline);
|
||||
this._emptyFilterResults.add(treeOutline);
|
||||
}
|
||||
|
||||
_filterDidChange()
|
||||
{
|
||||
this.updateFilter();
|
||||
}
|
||||
|
||||
_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[WI.NavigationSidebarPanel.SuppressFilteringSymbol]) {
|
||||
const currentTreeElementWasHidden = currentTreeElement.hidden;
|
||||
this.applyFiltersToTreeElement(currentTreeElement);
|
||||
if (currentTreeElementWasHidden !== currentTreeElement.hidden)
|
||||
this._treeElementWasFiltered(currentTreeElement);
|
||||
}
|
||||
|
||||
currentTreeElement = currentTreeElement.traverseNextTreeElement(false, treeElement, dontPopulate);
|
||||
}
|
||||
|
||||
this._checkForEmptyFilterResults(event.target);
|
||||
|
||||
if (this.visible)
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
|
||||
|
||||
if (this.selected && !treeElement.treeOutline[WI.NavigationSidebarPanel.IgnoreCookieRestoration])
|
||||
this._checkElementsForPendingViewStateCookie([treeElement]);
|
||||
}
|
||||
|
||||
_treeElementDisclosureDidChange(event)
|
||||
{
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
|
||||
}
|
||||
|
||||
_handleTreeElementRemoved(event)
|
||||
{
|
||||
this._checkForEmptyFilterResults(event.target);
|
||||
|
||||
if (this.visible)
|
||||
this._updateContentOverflowShadowVisibilityDebouncer.delayForTime(0);
|
||||
}
|
||||
|
||||
_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 WI.FolderTreeElement
|
||||
|| treeElement instanceof WI.DatabaseHostTreeElement
|
||||
|| treeElement instanceof WI.IndexedDatabaseHostTreeElement
|
||||
|| treeElement instanceof WI.ApplicationCacheManifestTreeElement
|
||||
|| treeElement instanceof WI.ThreadTreeElement
|
||||
|| treeElement instanceof WI.IdleTreeElement
|
||||
|| treeElement instanceof WI.DOMBreakpointTreeElement
|
||||
|| treeElement instanceof WI.EventBreakpointTreeElement
|
||||
|| treeElement instanceof WI.URLBreakpointTreeElement
|
||||
|| treeElement instanceof WI.SymbolicBreakpointTreeElement
|
||||
|| treeElement instanceof WI.CSSStyleSheetTreeElement
|
||||
|| typeof treeElement.representedObject === "string"
|
||||
|| treeElement.representedObject instanceof String;
|
||||
}
|
||||
|
||||
_checkOutlinesForPendingViewStateCookie(matchTypeOnly)
|
||||
{
|
||||
if (!this._pendingViewStateCookie)
|
||||
return;
|
||||
|
||||
this._checkForStaleResourcesIfNeeded();
|
||||
|
||||
var visibleTreeElements = [];
|
||||
this.contentTreeOutlines.forEach(function(outline) {
|
||||
if (outline[WI.NavigationSidebarPanel.IgnoreCookieRestoration])
|
||||
return;
|
||||
|
||||
var currentTreeElement = outline.hasChildren ? outline.children[0] : null;
|
||||
while (currentTreeElement) {
|
||||
visibleTreeElements.push(currentTreeElement);
|
||||
currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, false);
|
||||
}
|
||||
});
|
||||
|
||||
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[WI.TypeIdentifierCookieKey];
|
||||
if (typeIdentifier !== representedObject.constructor.TypeIdentifier)
|
||||
return false;
|
||||
|
||||
if (matchTypeOnly)
|
||||
return !!typeIdentifier;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_treeElementWasFiltered(treeElement)
|
||||
{
|
||||
if (treeElement.selected || treeElement.hidden)
|
||||
return;
|
||||
|
||||
let representedObject = this.currentRepresentedObject;
|
||||
if (!representedObject || treeElement.representedObject !== representedObject)
|
||||
return;
|
||||
|
||||
const omitFocus = true;
|
||||
const selectedByUser = false;
|
||||
const suppressNotification = true;
|
||||
treeElement.revealAndSelect(omitFocus, selectedByUser, suppressNotification);
|
||||
}
|
||||
};
|
||||
|
||||
WI.NavigationSidebarPanel.IgnoreCookieRestoration = Symbol("ignore-cookie-restoration");
|
||||
WI.NavigationSidebarPanel.SuppressFilteringSymbol = Symbol("suppress-filtering");
|
||||
WI.NavigationSidebarPanel.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering");
|
||||
|
||||
WI.NavigationSidebarPanel.OverflowShadowElementStyleClassName = "overflow-shadow";
|
||||
WI.NavigationSidebarPanel.ContentTreeOutlineElementStyleClassName = "navigation-sidebar-panel-content-tree-outline";
|
||||
Reference in New Issue
Block a user