Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Unified Diff: third_party/WebKit/Source/devtools/front_end/ui/View.js

Issue 2217783002: DevTools: use view locations in the elements and sources sidebars. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/devtools/front_end/ui/View.js
diff --git a/third_party/WebKit/Source/devtools/front_end/ui/View.js b/third_party/WebKit/Source/devtools/front_end/ui/View.js
index 5863780fc30b4062abbea84c4aae1430e46358fc..1f5f639beb23a8ed280de260849909a388a9a2c7 100644
--- a/third_party/WebKit/Source/devtools/front_end/ui/View.js
+++ b/third_party/WebKit/Source/devtools/front_end/ui/View.js
@@ -3,12 +3,52 @@
// found in the LICENSE file.
/**
+ * @interface
+ */
+WebInspector.View = function()
+{
+}
+
+WebInspector.View.prototype = {
+ /**
+ * @return {string}
+ */
+ viewId: function() { },
+
+ /**
+ * @return {string}
+ */
+ title: function() { },
+
+ /**
+ * @return {boolean}
+ */
+ isCloseable: function() { },
+
+ /**
+ * @return {boolean}
+ */
+ isTransient: function() { },
+
+ /**
+ * @return {!Promise<!Array<!WebInspector.ToolbarItem>>}
+ */
+ toolbarItems: function() { },
+
+ /**
+ * @return {!Promise<!WebInspector.Widget>}
+ */
+ widget: function() { }
+}
+
+/**
* @constructor
* @extends {WebInspector.VBox}
+ * @implements {WebInspector.View}
* @param {string} title
* @param {boolean=} isWebComponent
*/
-WebInspector.View = function(title, isWebComponent)
+WebInspector.SimpleView = function(title, isWebComponent)
{
WebInspector.VBox.call(this, isWebComponent);
this._title = title;
@@ -16,8 +56,18 @@ WebInspector.View = function(title, isWebComponent)
this._toolbarItems = [];
}
-WebInspector.View.prototype = {
+WebInspector.SimpleView.prototype = {
+ /**
+ * @override
+ * @return {string}
+ */
+ viewId: function()
+ {
+ return this._title;
+ },
+
/**
+ * @override
* @return {string}
*/
title: function()
@@ -26,6 +76,50 @@ WebInspector.View.prototype = {
},
/**
+ * @override
+ * @return {boolean}
+ */
+ isCloseable: function()
+ {
+ return false;
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ isTransient: function()
+ {
+ return false;
+ },
+
+ /**
+ * @override
+ * @return {!Promise<!Array<!WebInspector.ToolbarItem>>}
+ */
+ toolbarItems: function()
+ {
+ return Promise.resolve(this._toolbarItems);
dgozman 2016/08/05 01:32:09 this.syncToolbarItems()
+ },
+
+ /**
+ * @return {!Array<!WebInspector.ToolbarItem>}
+ */
+ syncToolbarItems: function()
+ {
+ return this._toolbarItems;
+ },
+
+ /**
+ * @override
+ * @return {!Promise<!WebInspector.Widget>}
+ */
+ widget: function()
+ {
+ return /** @type {!Promise<!WebInspector.Widget>} */ (Promise.resolve(this));
+ },
+
+ /**
* @param {!WebInspector.ToolbarItem} item
*/
addToolbarItem: function(item)
@@ -33,15 +127,73 @@ WebInspector.View.prototype = {
this._toolbarItems.push(item);
},
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.View}
+ * @param {!Runtime.Extension} extension
+ */
+WebInspector.ProvidedView = function(extension)
+{
+ this._extension = extension;
+}
+
+WebInspector.ProvidedView.prototype = {
/**
- * @return {!Array<!WebInspector.ToolbarItem>}
+ * @override
+ * @return {string}
+ */
+ viewId: function()
+ {
+ return this._extension.descriptor()["id"];
+ },
+
+ /**
+ * @override
+ * @return {string}
+ */
+ title: function()
+ {
+ return this._extension.title();
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ isCloseable: function()
+ {
+ return this._extension.descriptor()["persistence"] === "closeable";
+ },
+
+ /**
+ * @override
+ * @return {boolean}
+ */
+ isTransient: function()
+ {
+ return this._extension.descriptor()["persistence"] === "transient";
+ },
+
+ /**
+ * @override
+ * @return {!Promise<!Array<!WebInspector.ToolbarItem>>}
*/
toolbarItems: function()
{
- return this._toolbarItems;
+ return Promise.resolve([]);
},
- __proto__: WebInspector.VBox.prototype
+ /**
+ * @override
+ * @return {!Promise<!WebInspector.Widget>}
+ */
+ widget: function()
+ {
+ return /** @type {!Promise<!WebInspector.Widget>} */ (this._extension.instance());
+ }
}
/**
@@ -51,9 +203,14 @@ WebInspector.ViewLocation = function() { }
WebInspector.ViewLocation.prototype = {
/**
- * @param {string} viewId
+ * @param {!WebInspector.View} view
+ */
+ appendView: function(view) { },
+
+ /**
+ * @param {!WebInspector.View} view
*/
- showView: function(viewId) { },
+ showView: function(view) { },
/**
* @return {!WebInspector.Widget}
@@ -92,32 +249,47 @@ WebInspector.ViewLocationResolver.prototype = {
*/
WebInspector.ViewManager = function()
{
+ /** @type {!Map<string, !WebInspector.View>} */
+ this._views = new Map();
+ /** @type {!Map<string, string>} */
+ this._locations = new Map();
dgozman 2016/08/05 01:32:09 _locationIdByViewId
+
+ for (var extension of self.runtime.extensions("view")) {
+ var descriptor = extension.descriptor();
+ this._views.set(descriptor["id"], new WebInspector.ProvidedView(extension));
+ this._locations.set(descriptor["id"], descriptor["location"]);
+ }
}
WebInspector.ViewManager.prototype = {
+
dgozman 2016/08/05 01:32:09 nit: extra blank line
/**
* @param {string} viewId
*/
showView: function(viewId)
{
- var extensions = self.runtime.extensions("view").filter(extension => extension.descriptor()["id"] === viewId);
- if (!extensions.length) {
+ var view = this._views.get(viewId);
+ if (!view) {
console.error("Could not find view for id: '" + viewId + "'");
return;
}
- var extension = extensions[0];
- var location = extensions[0].descriptor()["location"];
+ var location = this._locations.get(viewId);
+ if (!location) {
dgozman 2016/08/05 01:32:09 Can just assert since _locations and _views share
+ console.error("Could not find location for id: '" + viewId + "'");
+ return;
+ }
if (location === "drawer-view")
WebInspector.userMetrics.drawerShown(viewId);
+
var resolverExtensions = self.runtime.extensions(WebInspector.ViewLocationResolver).filter(extension => extension.descriptor()["name"] === location);
if (!resolverExtensions.length)
return;
var resolverExtension = resolverExtensions[0];
- resolverExtension.instance().then(this._revealLocation.bind(this, viewId, location));
+ resolverExtension.instance().then(this._revealLocation.bind(this, view, location));
},
/**
- * @param {string} location
+ * @param {string=} location
* @param {boolean=} restoreSelection
* @param {boolean=} enableMoreTabsButton
* @return {!WebInspector.TabbedViewLocation}
@@ -128,32 +300,164 @@ WebInspector.ViewManager.prototype = {
},
/**
- * @param {string} viewId
+ * @param {string=} location
+ * @return {!WebInspector.ViewLocation}
+ */
+ createStackLocation: function(location)
+ {
+ return new WebInspector.ViewManager._StackLocation(this, location);
+ },
+
+ /**
+ * @param {!WebInspector.View} view
* @param {string} location
* @param {!WebInspector.ViewLocationResolver} resolver
*/
- _revealLocation: function(viewId, location, resolver)
+ _revealLocation: function(view, location, resolver)
{
var viewLocation = resolver.revealLocation(location);
if (viewLocation)
- viewLocation.showView(viewId);
+ viewLocation.showView(view);
},
/**
* @param {string} location
- * @return {!Array<!Runtime.Extension>}
+ * @return {!Array<!WebInspector.View>}
*/
_viewsForLocation: function(location)
{
- return self.runtime.extensions("view").filter(extension => extension.descriptor()["location"] === location);
+ var result = [];
+ for (var id of this._views.keys()) {
+ if (this._locations.get(id) === location)
+ result.push(this._views.get(id));
+ }
+ return result;
}
}
/**
* @constructor
+ * @extends {WebInspector.VBox}
+ * @param {!WebInspector.View} view
+ */
+WebInspector.ViewManager._ContainerWidget = function(view)
+{
+ WebInspector.VBox.call(this);
+ this.element.classList.add("flex-auto", "view-container", "overflow-auto");
+ this._view = view;
+}
+
+WebInspector.ViewManager._ContainerWidget.prototype = {
+ /**
+ * @return {!Promise<!WebInspector.Widget>}
+ */
+ _materialize: function()
+ {
+ if (this._materializePromise)
+ return this._materializePromise;
+ var promises = [];
+ promises.push(this._view.toolbarItems().then(toolbarItems => {
dgozman 2016/08/05 01:32:09 style: named function please
+ if (toolbarItems.length) {
+ var toolbar = new WebInspector.Toolbar("", this.element);
+ for (var item of toolbarItems)
+ toolbar.appendToolbarItem(item);
+ }
+ }));
+ promises.push(this._view.widget().then(widget => widget.show(this.element)));
+ this._materializePromise = Promise.all(promises).then(() => this);
+ return this._materializePromise;
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.VBox}
+ * @param {!WebInspector.View} view
+ */
+WebInspector.ViewManager._ExpandableContainerWidget = function(view)
+{
+ WebInspector.VBox.call(this, true);
+ this.element.classList.add("flex-none");
+ this.registerRequiredCSS("ui/viewContainers.css");
+
+ this._titleElement = createElementWithClass("div", "expandable-view-title");
+ this._titleElement.textContent = 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;
+}
+
+WebInspector.ViewManager._ExpandableContainerWidget.prototype = {
+ /**
+ * @return {!Promise<!WebInspector.Widget>}
+ */
+ _materialize: function()
dgozman 2016/08/05 01:32:09 All this boilerplate code...
+ {
+ if (this._materializePromise)
+ return this._materializePromise;
+ var promises = [];
+ promises.push(this._view.toolbarItems().then(toolbarItems => {
+ if (toolbarItems.length) {
+ var toolbar = new WebInspector.Toolbar("", this._titleElement);
+ for (var item of toolbarItems)
+ toolbar.appendToolbarItem(item);
+ }
+ }));
+ promises.push(this._view.widget().then(widget => {
+ this._widget = widget;
+ widget.show(this.element);
+ }));
+ this._materializePromise = Promise.all(promises).then(() => this);
+ return this._materializePromise;
+ },
+
+ _expand: function()
+ {
+ if (this._titleElement.classList.contains("expanded"))
+ return;
+ this._titleElement.classList.add("expanded");
+ this._materialize().then(() => this._widget.show(this.element));
+ },
+
+ _collapse: function()
+ {
+ if (!this._titleElement.classList.contains("expanded"))
+ return;
+ this._titleElement.classList.remove("expanded");
+ this._materialize().then(() => this._widget.detach());
+ },
+
+ _toggleExpanded: function()
+ {
+ if (this._titleElement.classList.contains("expanded"))
+ this._collapse();
+ else
+ this._expand();
+ },
+
+ /**
+ * @param {!Event} event
+ */
+ _onTitleKeyDown: function(event)
+ {
+ if (isEnterKey(event) || event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code)
+ this._toggleExpanded();
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
* @implements {WebInspector.TabbedViewLocation}
* @param {!WebInspector.ViewManager} manager
- * @param {string} location
+ * @param {string=} location
* @param {boolean=} restoreSelection
* @param {boolean=} enableMoreTabsButton
*/
@@ -162,7 +466,7 @@ WebInspector.ViewManager._TabbedLocation = function(manager, location, restoreSe
this._manager = manager;
this._tabbedPane = new WebInspector.TabbedPane();
this._location = location;
- /** @type {!Object.<string, !Promise.<?WebInspector.Widget>>} */
+ /** @type {!Object.<string, !Promise>} */
this._promiseForId = {};
this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
@@ -170,7 +474,11 @@ WebInspector.ViewManager._TabbedLocation = function(manager, location, restoreSe
this._closeableTabSetting = WebInspector.settings.createSetting(location + "-closeableTabs", {});
if (restoreSelection)
this._lastSelectedTabSetting = WebInspector.settings.createSetting(location + "-selectedTab", "");
- this._initialize();
+
+ /** @type {!Map.<string, !WebInspector.View>} */
+ this._views = new Map();
+ this._populateLocation();
+
if (enableMoreTabsButton) {
var toolbar = new WebInspector.Toolbar("drawer-toolbar");
toolbar.appendToolbarItem(new WebInspector.ToolbarMenuButton(this._appendTabsToMenu.bind(this)));
@@ -198,19 +506,19 @@ WebInspector.ViewManager._TabbedLocation.prototype = {
return this._tabbedPane;
},
- _initialize: function()
+ _populateLocation: function()
{
- /** @type {!Map.<string, !Runtime.Extension>} */
- this._extensions = new Map();
- var extensions = this._manager._viewsForLocation(this._location);
-
- for (var i = 0; i < extensions.length; ++i) {
- var id = extensions[i].descriptor()["id"];
- this._extensions.set(id, extensions[i]);
- if (this._isPermanentTab(id))
- this._appendTab(extensions[i]);
- else if (this._isCloseableTab(id) && this._closeableTabSetting.get()[id])
- this._appendTab(extensions[i]);
+ if (!this._location)
+ return;
+ for (var view of this._manager._viewsForLocation(this._location)) {
+ var id = view.viewId();
+ this._views.set(id, view);
+ if (view.isTransient())
+ continue;
+ if (!view.isCloseable())
+ this._appendTab(view);
+ else if (this._closeableTabSetting.get()[id])
+ this._appendTab(view);
}
},
@@ -224,59 +532,46 @@ WebInspector.ViewManager._TabbedLocation.prototype = {
},
/**
- * @param {string} id
- * @return {boolean}
+ * @param {!WebInspector.ContextMenu} contextMenu
*/
- _isPermanentTab: function(id)
+ _appendTabsToMenu: function(contextMenu)
{
- return this._extensions.get(id).descriptor()["persistence"] === "permanent" || !this._extensions.get(id).descriptor()["persistence"];
+ for (var view of this._views.values()) {
+ var title = WebInspector.UIString(view.title());
+ contextMenu.appendItem(title, this.showView.bind(this, view));
+ }
},
/**
- * @param {string} id
- * @return {boolean}
+ * @param {!WebInspector.View} view
*/
- _isCloseableTab: function(id)
+ _appendTab: function(view)
{
- return this._extensions.get(id).descriptor()["persistence"] === "closeable";
+ this._tabbedPane.appendTab(view.viewId(), view.title(), new WebInspector.Widget(), undefined, false, view.isCloseable() || view.isTransient());
},
/**
- * @param {!WebInspector.ContextMenu} contextMenu
+ * @override
+ * @param {!WebInspector.View} view
*/
- _appendTabsToMenu: function(contextMenu)
+ appendView: function(view)
{
- var extensions = self.runtime.extensions("view", undefined, true);
- for (var extension of extensions) {
- if (extension.descriptor()["location"] !== this._location)
- continue;
- var title = WebInspector.UIString(extension.title());
- contextMenu.appendItem(title, this.showView.bind(this, extension.descriptor()["id"]));
+ if (!this._tabbedPane.hasTab(view.viewId())) {
dgozman 2016/08/05 01:32:09 Who calls it twice for the same id?
+ this._views.set(view.viewId(), view);
+ this._appendTab(view);
}
},
/**
- * @param {!Runtime.Extension} extension
- */
- _appendTab: function(extension)
- {
- var descriptor = extension.descriptor();
- var id = descriptor["id"];
- var title = WebInspector.UIString(extension.title());
- var closeable = descriptor["persistence"] === "closeable" || descriptor["persistence"] === "temporary";
- this._tabbedPane.appendTab(id, title, new WebInspector.Widget(), undefined, false, closeable);
- },
-
- /**
* @override
- * @param {string} id
+ * @param {!WebInspector.View} view
*/
- showView: function(id)
+ showView: function(view)
{
- if (!this._tabbedPane.hasTab(id))
- this._appendTab(/** @type {!Runtime.Extension} */(this._extensions.get(id)));
+ if (!this._tabbedPane.hasTab(view.viewId()))
+ this._appendTab(view);
this._tabbedPane.focus();
- this._tabbedPane.selectTab(id);
+ this._tabbedPane.selectTab(view.viewId());
},
/**
@@ -287,13 +582,13 @@ WebInspector.ViewManager._TabbedLocation.prototype = {
var tabId = /** @type {string} */ (event.data.tabId);
if (this._lastSelectedTabSetting && event.data["isUserGesture"])
this._lastSelectedTabSetting.set(tabId);
- if (!this._extensions.has(tabId))
+ var view = this._views.get(tabId);
+ if (!view)
return;
- this._viewForId(tabId);
+ this._materializeWidget(view);
- var descriptor = this._extensions.get(tabId).descriptor();
- if (descriptor["persistence"] === "closeable") {
+ if (view.isCloseable()) {
var tabs = this._closeableTabSetting.get();
if (!tabs[tabId]) {
tabs[tabId] = true;
@@ -317,29 +612,82 @@ WebInspector.ViewManager._TabbedLocation.prototype = {
},
/**
- * @param {string} id
- * @return {!Promise.<?WebInspector.Widget>}
+ * @param {!WebInspector.View} view
*/
- _viewForId: function(id)
+ _materializeWidget: function(view)
{
- if (this._promiseForId[id])
- return this._promiseForId[id];
+ if (this._promiseForId[view.viewId()])
+ return;
- var promise = this._extensions.get(id).instance();
- this._promiseForId[id] = /** @type {!Promise.<?WebInspector.Widget>} */ (promise);
- return promise.then(cacheView.bind(this));
+ var widget = new WebInspector.ViewManager._ContainerWidget(view);
+ var promise = widget._materialize().then(() => {
+ this._tabbedPane.changeTabView(view.viewId(), widget);
+ });
+ this._promiseForId[view.viewId()] = promise;
+ }
+}
- /**
- * @param {!Object} object
- * @this {WebInspector.ViewManager._TabbedLocation}
- */
- function cacheView(object)
- {
- var view = /** @type {!WebInspector.Widget} */ (object);
- this._tabbedPane.changeTabView(id, view);
- return view;
+/**
+ * @constructor
+ * @implements {WebInspector.ViewLocation}
+ * @param {!WebInspector.ViewManager} manager
+ * @param {string=} location
+ */
+WebInspector.ViewManager._StackLocation = function(manager, location)
+{
+ this._manager = manager;
+ this._location = location;
+ this._vbox = new WebInspector.VBox();
+ /** @type {!Map<string, !WebInspector.ViewManager._ExpandableContainerWidget>} */
+ this._expandableContainers = new Map();
+ this._populateLocation();
+}
+
+WebInspector.ViewManager._StackLocation.prototype = {
+ /**
+ * @override
+ * @return {!WebInspector.Widget}
+ */
+ widget: function()
+ {
+ return this._vbox;
+ },
+
+ /**
+ * @override
+ * @param {!WebInspector.View} view
+ */
+ appendView: function(view)
+ {
+ var container = this._expandableContainers.get(view.viewId());
+ if (!container) {
dgozman 2016/08/05 01:32:09 Let's move this if to showView, and don't call app
pfeldman 2016/08/05 04:42:16 We need it for appendView.
+ container = new WebInspector.ViewManager._ExpandableContainerWidget(view);
+ container.show(this._vbox.contentElement);
+ this._expandableContainers.set(view.viewId(), container);
}
+ },
+
+ /**
+ * @override
+ * @param {!WebInspector.View} view
+ */
+ showView: function(view)
+ {
+ this.appendView(view);
+ var container = this._expandableContainers.get(view.viewId());
+ container._expand();
+ },
+
+ _populateLocation: function()
+ {
+ if (!this._location)
+ return;
+ for (var view of this._manager._viewsForLocation(this._location))
+ this.appendView(view);
}
}
-WebInspector.viewManager = new WebInspector.ViewManager();
+/**
+ * @type {!WebInspector.ViewManager}
+ */
+WebInspector.viewManager;

Powered by Google App Engine
This is Rietveld 408576698