mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-10 05:35:05 +08:00
Move and rename files. NOAUTOREVERT=true NOPRESUBMIT=true NOTREECHECKS=true Bug: 768828 TBR=darin@chromium.org NOTRY=true Change-Id: I66d3b155808bc5bdbf237b80208e1e552bcf7f28 Reviewed-on: https://chromium-review.googlesource.com/1001153 Reviewed-by: Blink Reformat <blink-reformat@chromium.org> Commit-Queue: Blink Reformat <blink-reformat@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#549061} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 0aee4434a4dba42a42abaea9bfbc0cd196a63bc1
923 lines
23 KiB
JavaScript
923 lines
23 KiB
JavaScript
// Copyright 2016 The Chromium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
/**
|
|
* @interface
|
|
*/
|
|
UI.View = function() {};
|
|
|
|
UI.View.prototype = {
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
viewId() {},
|
|
|
|
/**
|
|
* @return {string}
|
|
*/
|
|
title() {},
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
isCloseable() {},
|
|
|
|
/**
|
|
* @return {boolean}
|
|
*/
|
|
isTransient() {},
|
|
|
|
/**
|
|
* @return {!Promise<!Array<!UI.ToolbarItem>>}
|
|
*/
|
|
toolbarItems() {},
|
|
|
|
/**
|
|
* @return {!Promise<!UI.Widget>}
|
|
*/
|
|
widget() {},
|
|
|
|
disposeView() {}
|
|
};
|
|
|
|
UI.View._symbol = Symbol('view');
|
|
UI.View._widgetSymbol = Symbol('widget');
|
|
|
|
/**
|
|
* @implements {UI.View}
|
|
* @unrestricted
|
|
*/
|
|
UI.SimpleView = class extends UI.VBox {
|
|
/**
|
|
* @param {string} title
|
|
* @param {boolean=} isWebComponent
|
|
*/
|
|
constructor(title, isWebComponent) {
|
|
super(isWebComponent);
|
|
this._title = title;
|
|
/** @type {!Array<!UI.ToolbarItem>} */
|
|
this._toolbarItems = [];
|
|
this[UI.View._symbol] = this;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
viewId() {
|
|
return this._title;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
title() {
|
|
return this._title;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {boolean}
|
|
*/
|
|
isCloseable() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {boolean}
|
|
*/
|
|
isTransient() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!Promise<!Array<!UI.ToolbarItem>>}
|
|
*/
|
|
toolbarItems() {
|
|
return Promise.resolve(this.syncToolbarItems());
|
|
}
|
|
|
|
/**
|
|
* @return {!Array<!UI.ToolbarItem>}
|
|
*/
|
|
syncToolbarItems() {
|
|
return this._toolbarItems;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!Promise<!UI.Widget>}
|
|
*/
|
|
widget() {
|
|
return /** @type {!Promise<!UI.Widget>} */ (Promise.resolve(this));
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.ToolbarItem} item
|
|
*/
|
|
addToolbarItem(item) {
|
|
this._toolbarItems.push(item);
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise}
|
|
*/
|
|
revealView() {
|
|
return UI.viewManager.revealView(this);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
disposeView() {
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @implements {UI.View}
|
|
* @unrestricted
|
|
*/
|
|
UI.ProvidedView = class {
|
|
/**
|
|
* @param {!Runtime.Extension} extension
|
|
*/
|
|
constructor(extension) {
|
|
this._extension = extension;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
viewId() {
|
|
return this._extension.descriptor()['id'];
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {string}
|
|
*/
|
|
title() {
|
|
return this._extension.title();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {boolean}
|
|
*/
|
|
isCloseable() {
|
|
return this._extension.descriptor()['persistence'] === 'closeable';
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {boolean}
|
|
*/
|
|
isTransient() {
|
|
return this._extension.descriptor()['persistence'] === 'transient';
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!Promise<!Array<!UI.ToolbarItem>>}
|
|
*/
|
|
toolbarItems() {
|
|
const actionIds = this._extension.descriptor()['actionIds'];
|
|
if (actionIds) {
|
|
const result = actionIds.split(',').map(id => UI.Toolbar.createActionButtonForId(id.trim()));
|
|
return Promise.resolve(result);
|
|
}
|
|
|
|
if (this._extension.descriptor()['hasToolbar'])
|
|
return this.widget().then(widget => /** @type {!UI.ToolbarItem.ItemsProvider} */ (widget).toolbarItems());
|
|
return Promise.resolve([]);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!Promise<!UI.Widget>}
|
|
*/
|
|
async widget() {
|
|
this._widgetRequested = true;
|
|
const widget = await this._extension.instance();
|
|
if (!(widget instanceof UI.Widget))
|
|
throw new Error('view className should point to a UI.Widget');
|
|
widget[UI.View._symbol] = this;
|
|
return /** @type {!UI.Widget} */ (widget);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
async disposeView() {
|
|
if (!this._widgetRequested)
|
|
return;
|
|
const widget = await this.widget();
|
|
widget.ownerViewDisposed();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @interface
|
|
*/
|
|
UI.ViewLocation = function() {};
|
|
|
|
UI.ViewLocation.prototype = {
|
|
/**
|
|
* @param {string} locationName
|
|
*/
|
|
appendApplicableItems(locationName) {},
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
*/
|
|
appendView(view, insertBefore) {},
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
* @param {boolean=} userGesture
|
|
* @return {!Promise}
|
|
*/
|
|
showView(view, insertBefore, userGesture) {},
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
*/
|
|
removeView(view) {},
|
|
|
|
/**
|
|
* @return {!UI.Widget}
|
|
*/
|
|
widget() {}
|
|
};
|
|
|
|
/**
|
|
* @interface
|
|
* @extends {UI.ViewLocation}
|
|
*/
|
|
UI.TabbedViewLocation = function() {};
|
|
|
|
UI.TabbedViewLocation.prototype = {
|
|
/**
|
|
* @return {!UI.TabbedPane}
|
|
*/
|
|
tabbedPane() {},
|
|
|
|
enableMoreTabsButton() {}
|
|
};
|
|
|
|
/**
|
|
* @interface
|
|
*/
|
|
UI.ViewLocationResolver = function() {};
|
|
|
|
UI.ViewLocationResolver.prototype = {
|
|
/**
|
|
* @param {string} location
|
|
* @return {?UI.ViewLocation}
|
|
*/
|
|
resolveLocation(location) {}
|
|
};
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager = class {
|
|
constructor() {
|
|
/** @type {!Map<string, !UI.View>} */
|
|
this._views = new Map();
|
|
/** @type {!Map<string, string>} */
|
|
this._locationNameByViewId = new Map();
|
|
|
|
for (const extension of self.runtime.extensions('view')) {
|
|
const descriptor = extension.descriptor();
|
|
this._views.set(descriptor['id'], new UI.ProvidedView(extension));
|
|
this._locationNameByViewId.set(descriptor['id'], descriptor['location']);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!Element} element
|
|
* @param {!Array<!UI.ToolbarItem>} toolbarItems
|
|
*/
|
|
static _populateToolbar(element, toolbarItems) {
|
|
if (!toolbarItems.length)
|
|
return;
|
|
const toolbar = new UI.Toolbar('');
|
|
element.insertBefore(toolbar.element, element.firstChild);
|
|
for (const item of toolbarItems)
|
|
toolbar.appendToolbarItem(item);
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @return {!Promise}
|
|
*/
|
|
revealView(view) {
|
|
const location = /** @type {?UI.ViewManager._Location} */ (view[UI.ViewManager._Location.symbol]);
|
|
if (!location)
|
|
return Promise.resolve();
|
|
location._reveal();
|
|
return location.showView(view);
|
|
}
|
|
|
|
/**
|
|
* @param {string} viewId
|
|
* @return {?UI.View}
|
|
*/
|
|
view(viewId) {
|
|
return this._views.get(viewId);
|
|
}
|
|
|
|
/**
|
|
* @param {string} viewId
|
|
* @return {?UI.Widget}
|
|
*/
|
|
materializedWidget(viewId) {
|
|
const view = this.view(viewId);
|
|
return view ? view[UI.View._widgetSymbol] : null;
|
|
}
|
|
|
|
/**
|
|
* @param {string} viewId
|
|
* @param {boolean=} userGesture
|
|
* @param {boolean=} omitFocus
|
|
* @return {!Promise}
|
|
*/
|
|
showView(viewId, userGesture, omitFocus) {
|
|
const view = this._views.get(viewId);
|
|
if (!view) {
|
|
console.error('Could not find view for id: \'' + viewId + '\' ' + new Error().stack);
|
|
return Promise.resolve();
|
|
}
|
|
|
|
const locationName = this._locationNameByViewId.get(viewId);
|
|
|
|
const location = view[UI.ViewManager._Location.symbol];
|
|
if (location) {
|
|
location._reveal();
|
|
return location.showView(view, undefined, userGesture, omitFocus);
|
|
}
|
|
|
|
return this.resolveLocation(locationName).then(location => {
|
|
if (!location)
|
|
throw new Error('Could not resolve location for view: ' + viewId);
|
|
location._reveal();
|
|
return location.showView(view, undefined, userGesture, omitFocus);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @param {string=} location
|
|
* @return {!Promise<?UI.ViewManager._Location>}
|
|
*/
|
|
resolveLocation(location) {
|
|
if (!location)
|
|
return /** @type {!Promise<?UI.ViewManager._Location>} */ (Promise.resolve(null));
|
|
|
|
const resolverExtensions = self.runtime.extensions(UI.ViewLocationResolver)
|
|
.filter(extension => extension.descriptor()['name'] === location);
|
|
if (!resolverExtensions.length)
|
|
throw new Error('Unresolved location: ' + location);
|
|
const resolverExtension = resolverExtensions[0];
|
|
return resolverExtension.instance().then(
|
|
resolver => /** @type {?UI.ViewManager._Location} */ (resolver.resolveLocation(location)));
|
|
}
|
|
|
|
/**
|
|
* @param {function()=} revealCallback
|
|
* @param {string=} location
|
|
* @param {boolean=} restoreSelection
|
|
* @param {boolean=} allowReorder
|
|
* @param {?string=} defaultTab
|
|
* @return {!UI.TabbedViewLocation}
|
|
*/
|
|
createTabbedLocation(revealCallback, location, restoreSelection, allowReorder, defaultTab) {
|
|
return new UI.ViewManager._TabbedLocation(
|
|
this, revealCallback, location, restoreSelection, allowReorder, defaultTab);
|
|
}
|
|
|
|
/**
|
|
* @param {function()=} revealCallback
|
|
* @param {string=} location
|
|
* @return {!UI.ViewLocation}
|
|
*/
|
|
createStackLocation(revealCallback, location) {
|
|
return new UI.ViewManager._StackLocation(this, revealCallback, location);
|
|
}
|
|
|
|
/**
|
|
* @param {string} location
|
|
* @return {boolean}
|
|
*/
|
|
hasViewsForLocation(location) {
|
|
return !!this._viewsForLocation(location).length;
|
|
}
|
|
|
|
/**
|
|
* @param {string} location
|
|
* @return {!Array<!UI.View>}
|
|
*/
|
|
_viewsForLocation(location) {
|
|
const result = [];
|
|
for (const id of this._views.keys()) {
|
|
if (this._locationNameByViewId.get(id) === location)
|
|
result.push(this._views.get(id));
|
|
}
|
|
return result;
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager._ContainerWidget = class extends UI.VBox {
|
|
/**
|
|
* @param {!UI.View} view
|
|
*/
|
|
constructor(view) {
|
|
super();
|
|
this.element.classList.add('flex-auto', 'view-container', 'overflow-auto');
|
|
this._view = view;
|
|
this.element.tabIndex = -1;
|
|
this.setDefaultFocusedElement(this.element);
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise}
|
|
*/
|
|
_materialize() {
|
|
if (this._materializePromise)
|
|
return this._materializePromise;
|
|
const promises = [];
|
|
promises.push(this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this.element)));
|
|
promises.push(this._view.widget().then(widget => {
|
|
// Move focus from |this| to loaded |widget| if any.
|
|
const shouldFocus = this.element.hasFocus();
|
|
this.setDefaultFocusedElement(null);
|
|
this._view[UI.View._widgetSymbol] = widget;
|
|
widget.show(this.element);
|
|
if (shouldFocus)
|
|
widget.focus();
|
|
}));
|
|
this._materializePromise = Promise.all(promises);
|
|
return this._materializePromise;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
wasShown() {
|
|
this._materialize().then(() => {
|
|
this._wasShownForTest();
|
|
});
|
|
}
|
|
|
|
_wasShownForTest() {
|
|
// This method is sniffed in tests.
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager._ExpandableContainerWidget = class extends UI.VBox {
|
|
/**
|
|
* @param {!UI.View} view
|
|
*/
|
|
constructor(view) {
|
|
super(true);
|
|
this.element.classList.add('flex-none');
|
|
this.registerRequiredCSS('ui/viewContainers.css');
|
|
|
|
this._titleElement = createElementWithClass('div', 'expandable-view-title');
|
|
UI.ARIAUtils.markAsLink(this._titleElement);
|
|
this._titleExpandIcon = UI.Icon.create('smallicon-triangle-right', 'title-expand-icon');
|
|
this._titleElement.appendChild(this._titleExpandIcon);
|
|
this._titleElement.createTextChild(view.title());
|
|
this._titleElement.tabIndex = 0;
|
|
this._titleElement.addEventListener('click', this._toggleExpanded.bind(this), false);
|
|
this._titleElement.addEventListener('keydown', this._onTitleKeyDown.bind(this), false);
|
|
this.contentElement.insertBefore(this._titleElement, this.contentElement.firstChild);
|
|
|
|
this.contentElement.createChild('content');
|
|
this._view = view;
|
|
view[UI.ViewManager._ExpandableContainerWidget._symbol] = this;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise}
|
|
*/
|
|
_materialize() {
|
|
if (this._materializePromise)
|
|
return this._materializePromise;
|
|
const promises = [];
|
|
promises.push(
|
|
this._view.toolbarItems().then(UI.ViewManager._populateToolbar.bind(UI.ViewManager, this._titleElement)));
|
|
promises.push(this._view.widget().then(widget => {
|
|
this._widget = widget;
|
|
this._view[UI.View._widgetSymbol] = widget;
|
|
widget.show(this.element);
|
|
}));
|
|
this._materializePromise = Promise.all(promises);
|
|
return this._materializePromise;
|
|
}
|
|
|
|
/**
|
|
* @return {!Promise}
|
|
*/
|
|
_expand() {
|
|
if (this._titleElement.classList.contains('expanded'))
|
|
return this._materialize();
|
|
this._titleElement.classList.add('expanded');
|
|
UI.ARIAUtils.setExpanded(this._titleElement, true);
|
|
this._titleExpandIcon.setIconType('smallicon-triangle-down');
|
|
return this._materialize().then(() => this._widget.show(this.element));
|
|
}
|
|
|
|
_collapse() {
|
|
if (!this._titleElement.classList.contains('expanded'))
|
|
return;
|
|
this._titleElement.classList.remove('expanded');
|
|
UI.ARIAUtils.setExpanded(this._titleElement, false);
|
|
this._titleExpandIcon.setIconType('smallicon-triangle-right');
|
|
this._materialize().then(() => this._widget.detach());
|
|
}
|
|
|
|
_toggleExpanded() {
|
|
if (this._titleElement.classList.contains('expanded'))
|
|
this._collapse();
|
|
else
|
|
this._expand();
|
|
}
|
|
|
|
/**
|
|
* @param {!Event} event
|
|
*/
|
|
_onTitleKeyDown(event) {
|
|
if (isEnterKey(event) || event.keyCode === UI.KeyboardShortcut.Keys.Space.code) {
|
|
this._toggleExpanded();
|
|
} else if (event.key === 'ArrowLeft') {
|
|
this._collapse();
|
|
} else if (event.key === 'ArrowRight') {
|
|
if (!this._titleElement.classList.contains('expanded'))
|
|
this._expand();
|
|
else if (this._widget)
|
|
this._widget.focus();
|
|
}
|
|
}
|
|
};
|
|
|
|
UI.ViewManager._ExpandableContainerWidget._symbol = Symbol('container');
|
|
|
|
/**
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager._Location = class {
|
|
/**
|
|
* @param {!UI.ViewManager} manager
|
|
* @param {!UI.Widget} widget
|
|
* @param {function()=} revealCallback
|
|
*/
|
|
constructor(manager, widget, revealCallback) {
|
|
this._manager = manager;
|
|
this._revealCallback = revealCallback;
|
|
this._widget = widget;
|
|
}
|
|
|
|
/**
|
|
* @return {!UI.Widget}
|
|
*/
|
|
widget() {
|
|
return this._widget;
|
|
}
|
|
|
|
_reveal() {
|
|
if (this._revealCallback)
|
|
this._revealCallback();
|
|
}
|
|
};
|
|
|
|
UI.ViewManager._Location.symbol = Symbol('location');
|
|
|
|
/**
|
|
* @implements {UI.TabbedViewLocation}
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager._TabbedLocation = class extends UI.ViewManager._Location {
|
|
/**
|
|
* @param {!UI.ViewManager} manager
|
|
* @param {function()=} revealCallback
|
|
* @param {string=} location
|
|
* @param {boolean=} restoreSelection
|
|
* @param {boolean=} allowReorder
|
|
* @param {?string=} defaultTab
|
|
*/
|
|
constructor(manager, revealCallback, location, restoreSelection, allowReorder, defaultTab) {
|
|
const tabbedPane = new UI.TabbedPane();
|
|
if (allowReorder)
|
|
tabbedPane.setAllowTabReorder(true);
|
|
|
|
super(manager, tabbedPane, revealCallback);
|
|
this._tabbedPane = tabbedPane;
|
|
this._allowReorder = allowReorder;
|
|
|
|
this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this._tabSelected, this);
|
|
this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabClosed, this._tabClosed, this);
|
|
this._closeableTabSetting = Common.settings.createSetting(location + '-closeableTabs', {});
|
|
this._tabOrderSetting = Common.settings.createSetting(location + '-tabOrder', {});
|
|
this._tabbedPane.addEventListener(UI.TabbedPane.Events.TabOrderChanged, this._persistTabOrder, this);
|
|
if (restoreSelection)
|
|
this._lastSelectedTabSetting = Common.settings.createSetting(location + '-selectedTab', '');
|
|
this._defaultTab = defaultTab;
|
|
|
|
/** @type {!Map.<string, !UI.View>} */
|
|
this._views = new Map();
|
|
|
|
if (location)
|
|
this.appendApplicableItems(location);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!UI.Widget}
|
|
*/
|
|
widget() {
|
|
return this._tabbedPane;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @return {!UI.TabbedPane}
|
|
*/
|
|
tabbedPane() {
|
|
return this._tabbedPane;
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
*/
|
|
enableMoreTabsButton() {
|
|
this._tabbedPane.leftToolbar().appendToolbarItem(new UI.ToolbarMenuButton(this._appendTabsToMenu.bind(this)));
|
|
this._tabbedPane.disableOverflowMenu();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} locationName
|
|
*/
|
|
appendApplicableItems(locationName) {
|
|
const views = this._manager._viewsForLocation(locationName);
|
|
if (this._allowReorder) {
|
|
let i = 0;
|
|
const persistedOrders = this._tabOrderSetting.get();
|
|
const orders = new Map();
|
|
for (const view of views)
|
|
orders.set(view.viewId(), persistedOrders[view.viewId()] || (++i) * UI.ViewManager._TabbedLocation.orderStep);
|
|
views.sort((a, b) => orders.get(a.viewId()) - orders.get(b.viewId()));
|
|
}
|
|
|
|
for (const view of views) {
|
|
const id = view.viewId();
|
|
this._views.set(id, view);
|
|
view[UI.ViewManager._Location.symbol] = this;
|
|
if (view.isTransient())
|
|
continue;
|
|
if (!view.isCloseable())
|
|
this._appendTab(view);
|
|
else if (this._closeableTabSetting.get()[id])
|
|
this._appendTab(view);
|
|
}
|
|
if (this._defaultTab && this._tabbedPane.hasTab(this._defaultTab))
|
|
this._tabbedPane.selectTab(this._defaultTab);
|
|
else if (this._lastSelectedTabSetting && this._tabbedPane.hasTab(this._lastSelectedTabSetting.get()))
|
|
this._tabbedPane.selectTab(this._lastSelectedTabSetting.get());
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.ContextMenu} contextMenu
|
|
*/
|
|
_appendTabsToMenu(contextMenu) {
|
|
const views = Array.from(this._views.values());
|
|
views.sort((viewa, viewb) => viewa.title().localeCompare(viewb.title()));
|
|
for (const view of views) {
|
|
const title = Common.UIString(view.title());
|
|
contextMenu.defaultSection().appendItem(title, this.showView.bind(this, view, undefined, true));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @param {number=} index
|
|
*/
|
|
_appendTab(view, index) {
|
|
this._tabbedPane.appendTab(
|
|
view.viewId(), view.title(), new UI.ViewManager._ContainerWidget(view), undefined, false,
|
|
view.isCloseable() || view.isTransient(), index);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
*/
|
|
appendView(view, insertBefore) {
|
|
if (this._tabbedPane.hasTab(view.viewId()))
|
|
return;
|
|
const oldLocation = view[UI.ViewManager._Location.symbol];
|
|
if (oldLocation && oldLocation !== this)
|
|
oldLocation.removeView(view);
|
|
view[UI.ViewManager._Location.symbol] = this;
|
|
this._manager._views.set(view.viewId(), view);
|
|
this._views.set(view.viewId(), view);
|
|
let index = undefined;
|
|
const tabIds = this._tabbedPane.tabIds();
|
|
if (this._allowReorder) {
|
|
const orderSetting = this._tabOrderSetting.get();
|
|
const order = orderSetting[view.viewId()];
|
|
for (let i = 0; order && i < tabIds.length; ++i) {
|
|
if (orderSetting[tabIds[i]] && orderSetting[tabIds[i]] > order) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
} else if (insertBefore) {
|
|
for (let i = 0; i < tabIds.length; ++i) {
|
|
if (tabIds[i] === insertBefore.viewId()) {
|
|
index = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
this._appendTab(view, index);
|
|
|
|
if (view.isCloseable()) {
|
|
const tabs = this._closeableTabSetting.get();
|
|
const tabId = view.viewId();
|
|
if (!tabs[tabId]) {
|
|
tabs[tabId] = true;
|
|
this._closeableTabSetting.set(tabs);
|
|
}
|
|
}
|
|
this._persistTabOrder();
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
* @param {boolean=} userGesture
|
|
* @param {boolean=} omitFocus
|
|
* @return {!Promise}
|
|
*/
|
|
showView(view, insertBefore, userGesture, omitFocus) {
|
|
this.appendView(view, insertBefore);
|
|
this._tabbedPane.selectTab(view.viewId(), userGesture);
|
|
if (!omitFocus)
|
|
this._tabbedPane.focus();
|
|
const widget = /** @type {!UI.ViewManager._ContainerWidget} */ (this._tabbedPane.tabView(view.viewId()));
|
|
return widget._materialize();
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @override
|
|
*/
|
|
removeView(view) {
|
|
if (!this._tabbedPane.hasTab(view.viewId()))
|
|
return;
|
|
|
|
delete view[UI.ViewManager._Location.symbol];
|
|
this._manager._views.delete(view.viewId());
|
|
this._tabbedPane.closeTab(view.viewId());
|
|
this._views.delete(view.viewId());
|
|
}
|
|
|
|
/**
|
|
* @param {!Common.Event} event
|
|
*/
|
|
_tabSelected(event) {
|
|
const tabId = /** @type {string} */ (event.data.tabId);
|
|
if (this._lastSelectedTabSetting && event.data['isUserGesture'])
|
|
this._lastSelectedTabSetting.set(tabId);
|
|
}
|
|
|
|
/**
|
|
* @param {!Common.Event} event
|
|
*/
|
|
_tabClosed(event) {
|
|
const id = /** @type {string} */ (event.data['tabId']);
|
|
const tabs = this._closeableTabSetting.get();
|
|
if (tabs[id]) {
|
|
delete tabs[id];
|
|
this._closeableTabSetting.set(tabs);
|
|
}
|
|
this._views.get(id).disposeView();
|
|
}
|
|
|
|
_persistTabOrder() {
|
|
const tabIds = this._tabbedPane.tabIds();
|
|
const tabOrders = {};
|
|
for (let i = 0; i < tabIds.length; i++)
|
|
tabOrders[tabIds[i]] = (i + 1) * UI.ViewManager._TabbedLocation.orderStep;
|
|
this._tabOrderSetting.set(tabOrders);
|
|
}
|
|
};
|
|
|
|
UI.ViewManager._TabbedLocation.orderStep = 10; // Keep in sync with descriptors.
|
|
|
|
/**
|
|
* @implements {UI.ViewLocation}
|
|
* @unrestricted
|
|
*/
|
|
UI.ViewManager._StackLocation = class extends UI.ViewManager._Location {
|
|
/**
|
|
* @param {!UI.ViewManager} manager
|
|
* @param {function()=} revealCallback
|
|
* @param {string=} location
|
|
*/
|
|
constructor(manager, revealCallback, location) {
|
|
const vbox = new UI.VBox();
|
|
super(manager, vbox, revealCallback);
|
|
this._vbox = vbox;
|
|
|
|
/** @type {!Map<string, !UI.ViewManager._ExpandableContainerWidget>} */
|
|
this._expandableContainers = new Map();
|
|
|
|
if (location)
|
|
this.appendApplicableItems(location);
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
*/
|
|
appendView(view, insertBefore) {
|
|
const oldLocation = view[UI.ViewManager._Location.symbol];
|
|
if (oldLocation && oldLocation !== this)
|
|
oldLocation.removeView(view);
|
|
|
|
let container = this._expandableContainers.get(view.viewId());
|
|
if (!container) {
|
|
view[UI.ViewManager._Location.symbol] = this;
|
|
this._manager._views.set(view.viewId(), view);
|
|
container = new UI.ViewManager._ExpandableContainerWidget(view);
|
|
let beforeElement = null;
|
|
if (insertBefore) {
|
|
const beforeContainer = insertBefore[UI.ViewManager._ExpandableContainerWidget._symbol];
|
|
beforeElement = beforeContainer ? beforeContainer.element : null;
|
|
}
|
|
container.show(this._vbox.contentElement, beforeElement);
|
|
this._expandableContainers.set(view.viewId(), container);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {!UI.View} view
|
|
* @param {?UI.View=} insertBefore
|
|
* @return {!Promise}
|
|
*/
|
|
showView(view, insertBefore) {
|
|
this.appendView(view, insertBefore);
|
|
const container = this._expandableContainers.get(view.viewId());
|
|
return container._expand();
|
|
}
|
|
|
|
/**
|
|
* @param {!UI.View} view
|
|
* @override
|
|
*/
|
|
removeView(view) {
|
|
const container = this._expandableContainers.get(view.viewId());
|
|
if (!container)
|
|
return;
|
|
|
|
container.detach();
|
|
this._expandableContainers.delete(view.viewId());
|
|
delete view[UI.ViewManager._Location.symbol];
|
|
this._manager._views.delete(view.viewId());
|
|
}
|
|
|
|
/**
|
|
* @override
|
|
* @param {string} locationName
|
|
*/
|
|
appendApplicableItems(locationName) {
|
|
for (const view of this._manager._viewsForLocation(locationName))
|
|
this.appendView(view);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @type {!UI.ViewManager}
|
|
*/
|
|
UI.viewManager;
|