Title: [191976] trunk/Source/WebInspectorUI
Revision
191976
Author
mattba...@apple.com
Date
2015-11-03 13:56:35 -0800 (Tue, 03 Nov 2015)

Log Message

Web Inspector: Create View base class, refactor some core view classes
https://bugs.webkit.org/show_bug.cgi?id=149186

Reviewed by Brian Burg and Timothy Hatcher.

This patch introduces a new View base class, which encapsulates DOM element creation,
layout scheduling, and subview management. The View class constructor accepts an optional
element parameter, allowing an existing DOM element to be associated with the View object,
rather than dynamically creating a new element. View also adds a `__view` property to its
associated DOM element to facilitate debugging the Inspector UI.

For the view classes refactored in this patch, the changes are largely mechanical. Dynamically
created DOM elements and redundant element getters have been removed. needsLayout has replaced
updateLayoutIfNeeded where appropriate. updateLayout has been removed entirely for views that
performed no layout other than to cascade layouts to their children.

* UserInterface/Base/Main.js:
Moved TabBar layout updates out of TabBrowser and into Main.js.

* UserInterface/Main.html:
* UserInterface/Views/ConsolePrompt.js:
(WebInspector.ConsolePrompt):
(WebInspector.ConsolePrompt.prototype.layout):
(WebInspector.ConsolePrompt.prototype.get element): Deleted.
(WebInspector.ConsolePrompt.prototype.updateLayout): Deleted.
* UserInterface/Views/ContentBrowser.js:
(WebInspector.ContentBrowser):
(WebInspector.ContentBrowser.prototype.get element): Deleted.
(WebInspector.ContentBrowser.prototype.updateLayout): Deleted.
* UserInterface/Views/ContentBrowserTabContentView.js:
(WebInspector.ContentBrowserTabContentView):
(WebInspector.ContentBrowserTabContentView.prototype.updateLayout): Deleted.
* UserInterface/Views/ContentView.js:
(WebInspector.ContentView):
(WebInspector.ContentView.prototype.get element): Deleted.
(WebInspector.ContentView.prototype.updateLayout): Deleted.
* UserInterface/Views/ContentViewContainer.js:
(WebInspector.ContentViewContainer):
(WebInspector.ContentViewContainer.prototype._showEntry):
(WebInspector.ContentViewContainer.prototype._hideEntry):
(WebInspector.ContentViewContainer.prototype.get element): Deleted.
(WebInspector.ContentViewContainer.prototype.updateLayout): Deleted.
(WebInspector.ContentViewContainer.prototype._addContentViewElement): Deleted.
(WebInspector.ContentViewContainer.prototype._removeContentViewElement): Deleted.
* UserInterface/Views/DataGrid.js:
(WebInspector.DataGrid.prototype.autoSizeColumns):
(WebInspector.DataGrid.prototype.layout):
(WebInspector.DataGrid.prototype.applyColumnWidthsMap):
(WebInspector.DataGrid): Deleted.
(WebInspector.DataGrid.prototype.updateLayout): Deleted.
(WebInspector.DataGrid.prototype.resizerDragging): Deleted.
(WebInspector.DataGrid.prototype.resizerDragEnded): Deleted.
* UserInterface/Views/HierarchicalPathNavigationItem.js:
(WebInspector.HierarchicalPathNavigationItem.prototype.set components):
* UserInterface/Views/LayoutTimelineView.js:
(WebInspector.LayoutTimelineView):
(WebInspector.LayoutTimelineView.prototype.layout):
(WebInspector.LayoutTimelineView.prototype.updateLayout): Deleted.
* UserInterface/Views/NavigationBar.js:
(WebInspector.NavigationBar):
(WebInspector.NavigationBar.prototype.insertNavigationItem):
(WebInspector.NavigationBar.prototype.removeNavigationItem):
(WebInspector.NavigationBar.prototype.get minimumWidth):
(WebInspector.NavigationBar.prototype.layout):
(WebInspector.NavigationBar.prototype._mouseDown):
(WebInspector.NavigationBar.prototype._mouseMoved):
(WebInspector.NavigationBar.prototype._mouseUp):
(WebInspector.NavigationBar.prototype._calculateMinimumWidth):
(WebInspector.NavigationBar.prototype.updateLayoutSoon.update): Deleted.
(WebInspector.NavigationBar.prototype.updateLayoutSoon): Deleted.
(WebInspector.NavigationBar.prototype.updateLayout): Deleted.
(WebInspector.NavigationBar.prototype.get element): Deleted.
* UserInterface/Views/NavigationItem.js:
(WebInspector.NavigationItem.prototype.set hidden):
* UserInterface/Views/NetworkTimelineView.js:
(WebInspector.NetworkTimelineView):
(WebInspector.NetworkTimelineView.prototype.layout):
(WebInspector.NetworkTimelineView.prototype.updateLayout): Deleted.
* UserInterface/Views/OverviewTimelineView.js:
(WebInspector.OverviewTimelineView):
(WebInspector.OverviewTimelineView.prototype.layout):
(WebInspector.OverviewTimelineView.prototype.updateLayout): Deleted.
* UserInterface/Views/QuickConsole.js:
(WebInspector.QuickConsole):
(WebInspector.QuickConsole.prototype.layout):
(WebInspector.QuickConsole.prototype.get element): Deleted.
(WebInspector.QuickConsole.prototype.updateLayout): Deleted.
* UserInterface/Views/RenderingFrameTimelineView.js:
(WebInspector.RenderingFrameTimelineView):
(WebInspector.RenderingFrameTimelineView.prototype.layout):
(WebInspector.RenderingFrameTimelineView.prototype.updateLayout): Deleted.
* UserInterface/Views/ScriptTimelineView.js:
(WebInspector.ScriptTimelineView):
(WebInspector.ScriptTimelineView.prototype.layout):
(WebInspector.ScriptTimelineView.prototype.updateLayout): Deleted.
* UserInterface/Views/TabBar.js:
(WebInspector.TabBar):
(WebInspector.TabBar.prototype.insertTabBarItem.animateTabs):
(WebInspector.TabBar.prototype.insertTabBarItem.removeStyles):
(WebInspector.TabBar.prototype.insertTabBarItem):
(WebInspector.TabBar.prototype.removeTabBarItem.animateTabs):
(WebInspector.TabBar.prototype.removeTabBarItem.removeStyles):
(WebInspector.TabBar.prototype.removeTabBarItem):
(WebInspector.TabBar.prototype.hasNormalTab):
(WebInspector.TabBar.prototype.layout):
(WebInspector.TabBar.prototype._recordTabBarItemSizesAndPositions):
(WebInspector.TabBar.prototype._finishExpandingTabsAfterClose.):
(WebInspector.TabBar.prototype._finishExpandingTabsAfterClose):
(WebInspector.TabBar.prototype._handleClick):
(WebInspector.TabBar.prototype._handleMouseMoved):
(WebInspector.TabBar.prototype._handleMouseUp):
(WebInspector.TabBar.prototype._handleMouseLeave):
(WebInspector.TabBar.prototype._handleNewTabMouseEnter):
(WebInspector.TabBar.prototype.updateLayoutSoon.update): Deleted.
(WebInspector.TabBar.prototype.updateLayoutSoon): Deleted.
(WebInspector.TabBar.prototype.updateLayout): Deleted.
(WebInspector.TabBar.prototype.get element): Deleted.
* UserInterface/Views/TabBrowser.js:
(WebInspector.TabBrowser):
(WebInspector.TabBrowser.prototype.get element): Deleted.
(WebInspector.TabBrowser.prototype.updateLayout): Deleted.
* UserInterface/Views/TimelineView.js:
(WebInspector.TimelineView.prototype.filterUpdated):
(WebInspector.TimelineView.prototype.needsLayout):
(WebInspector.TimelineView.prototype.updateLayout): Deleted.
(WebInspector.TimelineView.prototype.updateLayoutIfNeeded): Deleted.
(WebInspector.TimelineView): Deleted.

* UserInterface/Views/Toolbar.js:
(WebInspector.Toolbar):
(WebInspector.Toolbar.prototype.set displayMode):
(WebInspector.Toolbar.prototype.set sizeMode):
(WebInspector.Toolbar.prototype.addToolbarItem):
(WebInspector.Toolbar.prototype.layout):
(WebInspector.Toolbar.prototype.customUpdateLayout): Deleted.
Renamed to layout. This eliminated a layering violation in NavigationBar,
where the function previously known as updateLayout checked for a
a `customUpdateLayout` function property, and would call it instead of its
own layout logic if found.

* UserInterface/Views/View.js: Added.
(WebInspector.View):
(WebInspector.View.prototype.get element):
(WebInspector.View.prototype.get subviews):
(WebInspector.View.prototype.addSubview):
Appends a view to the end of the subview list.
(WebInspector.View.prototype.insertSubviewBefore):
Inserts a view into subview list before another subview.
(WebInspector.View.prototype.removeSubview):
(WebInspector.View.prototype.replaceSubview):
(WebInspector.View.prototype.updateLayout):
No longer overridden by subclasses.
(WebInspector.View.prototype.updateLayoutIfNeeded):
Forces a layout if one has been scheduled, otherwise does nothing.
(WebInspector.View.prototype.needsLayout):
Schedules a layout for the view.
(WebInspector.View.prototype.layout):
Overridden by views that require special layout logic. Layouts
cascade to child views automatically.
(WebInspector.View.prototype._layoutSubtree):
Main layout entry point. Called by requestAnimationFrame via needsLayut, by
updateLayout when forcing a synchronous layout, and called recursively during
subview traversal.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (191975 => 191976)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-11-03 21:56:35 UTC (rev 191976)
@@ -1,3 +1,169 @@
+2015-11-03  Matt Baker  <mattba...@apple.com>
+
+        Web Inspector: Create View base class, refactor some core view classes
+        https://bugs.webkit.org/show_bug.cgi?id=149186
+
+        Reviewed by Brian Burg and Timothy Hatcher.
+
+        This patch introduces a new View base class, which encapsulates DOM element creation,
+        layout scheduling, and subview management. The View class constructor accepts an optional
+        element parameter, allowing an existing DOM element to be associated with the View object,
+        rather than dynamically creating a new element. View also adds a `__view` property to its
+        associated DOM element to facilitate debugging the Inspector UI.
+
+        For the view classes refactored in this patch, the changes are largely mechanical. Dynamically
+        created DOM elements and redundant element getters have been removed. needsLayout has replaced
+        updateLayoutIfNeeded where appropriate. updateLayout has been removed entirely for views that
+        performed no layout other than to cascade layouts to their children.
+
+        * UserInterface/Base/Main.js:
+        Moved TabBar layout updates out of TabBrowser and into Main.js.
+
+        * UserInterface/Main.html:
+        * UserInterface/Views/ConsolePrompt.js:
+        (WebInspector.ConsolePrompt):
+        (WebInspector.ConsolePrompt.prototype.layout):
+        (WebInspector.ConsolePrompt.prototype.get element): Deleted.
+        (WebInspector.ConsolePrompt.prototype.updateLayout): Deleted.
+        * UserInterface/Views/ContentBrowser.js:
+        (WebInspector.ContentBrowser):
+        (WebInspector.ContentBrowser.prototype.get element): Deleted.
+        (WebInspector.ContentBrowser.prototype.updateLayout): Deleted.
+        * UserInterface/Views/ContentBrowserTabContentView.js:
+        (WebInspector.ContentBrowserTabContentView):
+        (WebInspector.ContentBrowserTabContentView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/ContentView.js:
+        (WebInspector.ContentView):
+        (WebInspector.ContentView.prototype.get element): Deleted.
+        (WebInspector.ContentView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/ContentViewContainer.js:
+        (WebInspector.ContentViewContainer):
+        (WebInspector.ContentViewContainer.prototype._showEntry):
+        (WebInspector.ContentViewContainer.prototype._hideEntry):
+        (WebInspector.ContentViewContainer.prototype.get element): Deleted.
+        (WebInspector.ContentViewContainer.prototype.updateLayout): Deleted.
+        (WebInspector.ContentViewContainer.prototype._addContentViewElement): Deleted.
+        (WebInspector.ContentViewContainer.prototype._removeContentViewElement): Deleted.
+        * UserInterface/Views/DataGrid.js:
+        (WebInspector.DataGrid.prototype.autoSizeColumns):
+        (WebInspector.DataGrid.prototype.layout):
+        (WebInspector.DataGrid.prototype.applyColumnWidthsMap):
+        (WebInspector.DataGrid): Deleted.
+        (WebInspector.DataGrid.prototype.updateLayout): Deleted.
+        (WebInspector.DataGrid.prototype.resizerDragging): Deleted.
+        (WebInspector.DataGrid.prototype.resizerDragEnded): Deleted.
+        * UserInterface/Views/HierarchicalPathNavigationItem.js:
+        (WebInspector.HierarchicalPathNavigationItem.prototype.set components):
+        * UserInterface/Views/LayoutTimelineView.js:
+        (WebInspector.LayoutTimelineView):
+        (WebInspector.LayoutTimelineView.prototype.layout):
+        (WebInspector.LayoutTimelineView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/NavigationBar.js:
+        (WebInspector.NavigationBar):
+        (WebInspector.NavigationBar.prototype.insertNavigationItem):
+        (WebInspector.NavigationBar.prototype.removeNavigationItem):
+        (WebInspector.NavigationBar.prototype.get minimumWidth):
+        (WebInspector.NavigationBar.prototype.layout):
+        (WebInspector.NavigationBar.prototype._mouseDown):
+        (WebInspector.NavigationBar.prototype._mouseMoved):
+        (WebInspector.NavigationBar.prototype._mouseUp):
+        (WebInspector.NavigationBar.prototype._calculateMinimumWidth):
+        (WebInspector.NavigationBar.prototype.updateLayoutSoon.update): Deleted.
+        (WebInspector.NavigationBar.prototype.updateLayoutSoon): Deleted.
+        (WebInspector.NavigationBar.prototype.updateLayout): Deleted.
+        (WebInspector.NavigationBar.prototype.get element): Deleted.
+        * UserInterface/Views/NavigationItem.js:
+        (WebInspector.NavigationItem.prototype.set hidden):
+        * UserInterface/Views/NetworkTimelineView.js:
+        (WebInspector.NetworkTimelineView):
+        (WebInspector.NetworkTimelineView.prototype.layout):
+        (WebInspector.NetworkTimelineView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/OverviewTimelineView.js:
+        (WebInspector.OverviewTimelineView):
+        (WebInspector.OverviewTimelineView.prototype.layout):
+        (WebInspector.OverviewTimelineView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/QuickConsole.js:
+        (WebInspector.QuickConsole):
+        (WebInspector.QuickConsole.prototype.layout):
+        (WebInspector.QuickConsole.prototype.get element): Deleted.
+        (WebInspector.QuickConsole.prototype.updateLayout): Deleted.
+        * UserInterface/Views/RenderingFrameTimelineView.js:
+        (WebInspector.RenderingFrameTimelineView):
+        (WebInspector.RenderingFrameTimelineView.prototype.layout):
+        (WebInspector.RenderingFrameTimelineView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/ScriptTimelineView.js:
+        (WebInspector.ScriptTimelineView):
+        (WebInspector.ScriptTimelineView.prototype.layout):
+        (WebInspector.ScriptTimelineView.prototype.updateLayout): Deleted.
+        * UserInterface/Views/TabBar.js:
+        (WebInspector.TabBar):
+        (WebInspector.TabBar.prototype.insertTabBarItem.animateTabs):
+        (WebInspector.TabBar.prototype.insertTabBarItem.removeStyles):
+        (WebInspector.TabBar.prototype.insertTabBarItem):
+        (WebInspector.TabBar.prototype.removeTabBarItem.animateTabs):
+        (WebInspector.TabBar.prototype.removeTabBarItem.removeStyles):
+        (WebInspector.TabBar.prototype.removeTabBarItem):
+        (WebInspector.TabBar.prototype.hasNormalTab):
+        (WebInspector.TabBar.prototype.layout):
+        (WebInspector.TabBar.prototype._recordTabBarItemSizesAndPositions):
+        (WebInspector.TabBar.prototype._finishExpandingTabsAfterClose.):
+        (WebInspector.TabBar.prototype._finishExpandingTabsAfterClose):
+        (WebInspector.TabBar.prototype._handleClick):
+        (WebInspector.TabBar.prototype._handleMouseMoved):
+        (WebInspector.TabBar.prototype._handleMouseUp):
+        (WebInspector.TabBar.prototype._handleMouseLeave):
+        (WebInspector.TabBar.prototype._handleNewTabMouseEnter):
+        (WebInspector.TabBar.prototype.updateLayoutSoon.update): Deleted.
+        (WebInspector.TabBar.prototype.updateLayoutSoon): Deleted.
+        (WebInspector.TabBar.prototype.updateLayout): Deleted.
+        (WebInspector.TabBar.prototype.get element): Deleted.
+        * UserInterface/Views/TabBrowser.js:
+        (WebInspector.TabBrowser):
+        (WebInspector.TabBrowser.prototype.get element): Deleted.
+        (WebInspector.TabBrowser.prototype.updateLayout): Deleted.
+        * UserInterface/Views/TimelineView.js:
+        (WebInspector.TimelineView.prototype.filterUpdated):
+        (WebInspector.TimelineView.prototype.needsLayout):
+        (WebInspector.TimelineView.prototype.updateLayout): Deleted.
+        (WebInspector.TimelineView.prototype.updateLayoutIfNeeded): Deleted.
+        (WebInspector.TimelineView): Deleted.
+
+        * UserInterface/Views/Toolbar.js:
+        (WebInspector.Toolbar):
+        (WebInspector.Toolbar.prototype.set displayMode):
+        (WebInspector.Toolbar.prototype.set sizeMode):
+        (WebInspector.Toolbar.prototype.addToolbarItem):
+        (WebInspector.Toolbar.prototype.layout):
+        (WebInspector.Toolbar.prototype.customUpdateLayout): Deleted.
+        Renamed to layout. This eliminated a layering violation in NavigationBar,
+        where the function previously known as updateLayout checked for a
+        a `customUpdateLayout` function property, and would call it instead of its
+        own layout logic if found.
+
+        * UserInterface/Views/View.js: Added.
+        (WebInspector.View):
+        (WebInspector.View.prototype.get element):
+        (WebInspector.View.prototype.get subviews):
+        (WebInspector.View.prototype.addSubview):
+        Appends a view to the end of the subview list.
+        (WebInspector.View.prototype.insertSubviewBefore):
+        Inserts a view into subview list before another subview.
+        (WebInspector.View.prototype.removeSubview):
+        (WebInspector.View.prototype.replaceSubview):
+        (WebInspector.View.prototype.updateLayout):
+        No longer overridden by subclasses.
+        (WebInspector.View.prototype.updateLayoutIfNeeded):
+        Forces a layout if one has been scheduled, otherwise does nothing.
+        (WebInspector.View.prototype.needsLayout):
+        Schedules a layout for the view.
+        (WebInspector.View.prototype.layout):
+        Overridden by views that require special layout logic. Layouts
+        cascade to child views automatically.
+        (WebInspector.View.prototype._layoutSubtree):
+        Main layout entry point. Called by requestAnimationFrame via needsLayut, by
+        updateLayout when forcing a synchronous layout, and called recursively during
+        subview traversal.
+
 2015-11-03  Joseph Pecoraro  <pecor...@apple.com>
 
         Web Inspector: Handle or Remove ParseHTML Timeline Event Records

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -1282,6 +1282,7 @@
 WebInspector._windowResized = function(event)
 {
     this.toolbar.updateLayout();
+    this.tabBar.updateLayout();
     this._tabBrowserSizeDidChange();
 };
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2015-11-03 21:56:35 UTC (rev 191976)
@@ -336,6 +336,8 @@
     <script src=""
     <script src=""
 
+    <script src=""
+
     <script src=""
     <script src=""
     <script src=""

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ConsolePrompt.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ConsolePrompt.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ConsolePrompt.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,16 +23,15 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ConsolePrompt = class ConsolePrompt extends WebInspector.Object
+WebInspector.ConsolePrompt = class ConsolePrompt extends WebInspector.View
 {
     constructor(delegate, mimeType, element)
     {
-        super();
+        super(element);
 
         mimeType = parseMIMEType(mimeType).type;
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("console-prompt", WebInspector.SyntaxHighlightedStyleClassName);
+        this.element.classList.add("console-prompt", WebInspector.SyntaxHighlightedStyleClassName);
 
         this._delegate = delegate || null;
 
@@ -66,11 +65,6 @@
 
     // Public
 
-    get element()
-    {
-        return this._element;
-    }
-
     get delegate()
     {
         return this._delegate;
@@ -126,11 +120,6 @@
         this._codeMirror.refresh();
     }
 
-    updateLayout()
-    {
-        this._codeMirror.refresh();
-    }
-
     updateCompletions(completions, implicitSuffix)
     {
         this._completionController.updateCompletions(completions, implicitSuffix);
@@ -158,6 +147,11 @@
         return !!this.text;
     }
 
+    layout()
+    {
+        this._codeMirror.refresh();
+    }
+
     // Private
 
     _handleTabKey(codeMirror)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,29 +23,28 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ContentBrowser = class ContentBrowser extends WebInspector.Object
+WebInspector.ContentBrowser = class ContentBrowser extends WebInspector.View
 {
     constructor(element, delegate, disableBackForward)
     {
-        super();
+        super(element);
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("content-browser");
+        this.element.classList.add("content-browser");
 
         this._navigationBar = new WebInspector.NavigationBar;
-        this._element.appendChild(this._navigationBar.element);
+        this.addSubview(this._navigationBar);
 
         this._contentViewContainer = new WebInspector.ContentViewContainer;
         this._contentViewContainer.addEventListener(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange, this._currentContentViewDidChange, this);
-        this._element.appendChild(this._contentViewContainer.element);
+        this.addSubview(this._contentViewContainer);
 
         this._findBanner = new WebInspector.FindBanner(this);
         this._findBanner.addEventListener(WebInspector.FindBanner.Event.DidShow, this._findBannerDidShow, this);
         this._findBanner.addEventListener(WebInspector.FindBanner.Event.DidHide, this._findBannerDidHide, this);
 
         if (!disableBackForward) {
-            this._backKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Control, WebInspector.KeyboardShortcut.Key.Left, this._backButtonClicked.bind(this), this._element);
-            this._forwardKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Control, WebInspector.KeyboardShortcut.Key.Right, this._forwardButtonClicked.bind(this), this._element);
+            this._backKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Control, WebInspector.KeyboardShortcut.Key.Left, this._backButtonClicked.bind(this), this.element);
+            this._forwardKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Control, WebInspector.KeyboardShortcut.Key.Right, this._forwardButtonClicked.bind(this), this.element);
 
             this._backButtonNavigationItem = new WebInspector.ButtonNavigationItem("back", WebInspector.UIString("Back (%s)").format(this._backKeyboardShortcut.displayName), "Images/BackForwardArrows.svg#back-arrow-mask", 8, 13);
             this._backButtonNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._backButtonClicked, this);
@@ -81,11 +80,6 @@
 
     // Public
 
-    get element()
-    {
-        return this._element;
-    }
-
     get navigationBar()
     {
         return this._navigationBar;
@@ -133,12 +127,6 @@
         return representedObjects;
     }
 
-    updateLayout()
-    {
-        this._navigationBar.updateLayout();
-        this._contentViewContainer.updateLayout();
-    }
-
     showContentViewForRepresentedObject(representedObject, cookie, extraArguments)
     {
         var contentView = this.contentViewForRepresentedObject(representedObject, false, extraArguments);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -42,7 +42,6 @@
 
         this._lastSelectedDetailsSidebarPanelSetting = new WebInspector.Setting(identifier + "-last-selected-details-sidebar-panel", null);
 
-        this._contentBrowser = this._contentBrowser;
         this._contentBrowser.addEventListener(WebInspector.ContentBrowser.Event.CurrentRepresentedObjectsDidChange, this.showDetailsSidebarPanels, this);
         this._contentBrowser.addEventListener(WebInspector.ContentBrowser.Event.CurrentContentViewDidChange, this._contentBrowserCurrentContentViewDidChange, this);
 
@@ -82,7 +81,7 @@
             WebInspector.detailsSidebar.addEventListener(WebInspector.Sidebar.Event.SidebarPanelSelected, this._detailsSidebarPanelSelected, this);
         }
 
-        this.element.appendChild(this._contentBrowser.element);
+        this.addSubview(this._contentBrowser);
     }
 
     // Public
@@ -122,13 +121,6 @@
         this._contentBrowser.contentViewContainer.closeAllContentViews();
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        this._contentBrowser.updateLayout();
-    }
-
     get managesDetailsSidebarPanels()
     {
         return true;

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,7 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ContentView = class ContentView extends WebInspector.Object
+WebInspector.ContentView = class ContentView extends WebInspector.View
 {
     constructor(representedObject, extraArguments)
     {
@@ -34,8 +34,7 @@
 
         this._representedObject = representedObject;
 
-        this._element = document.createElement("div");
-        this._element.classList.add("content-view");
+        this.element.classList.add("content-view");
 
         this._parentContainer = null;
     }
@@ -195,11 +194,6 @@
         return [];
     }
 
-    get element()
-    {
-        return this._element;
-    }
-
     get parentContainer()
     {
         return this._parentContainer;
@@ -245,11 +239,6 @@
         return true;
     }
 
-    updateLayout()
-    {
-        // Implemented by subclasses.
-    }
-
     shown()
     {
         // Implemented by subclasses.

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,14 +23,13 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.ContentViewContainer = class ContentViewContainer extends WebInspector.Object
+WebInspector.ContentViewContainer = class ContentViewContainer extends WebInspector.View
 {
-    constructor(element)
+    constructor()
     {
         super();
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("content-view-container");
+        this.element.classList.add("content-view-container");
 
         this._backForwardList = [];
         this._currentIndex = -1;
@@ -38,11 +37,6 @@
 
     // Public
 
-    get element()
-    {
-        return this._element;
-    }
-
     get currentIndex()
     {
         return this._currentIndex;
@@ -67,13 +61,6 @@
         return this._backForwardList[this._currentIndex];
     }
 
-    updateLayout()
-    {
-        var currentContentView = this.currentContentView;
-        if (currentContentView)
-            currentContentView.updateLayout();
-    }
-
     contentViewForRepresentedObject(representedObject, onlyExisting, extraArguments)
     {
         console.assert(representedObject);
@@ -428,18 +415,6 @@
 
     // Private
 
-    _addContentViewElement(contentView)
-    {
-        if (contentView.element.parentNode !== this._element)
-            this._element.appendChild(contentView.element);
-    }
-
-    _removeContentViewElement(contentView)
-    {
-        if (contentView.element.parentNode)
-            contentView.element.parentNode.removeChild(contentView.element);
-    }
-
     _disassociateFromContentView(contentView)
     {
         console.assert(!contentView.visible);
@@ -460,7 +435,9 @@
     {
         console.assert(entry instanceof WebInspector.BackForwardEntry);
 
-        this._addContentViewElement(entry.contentView);
+        if (!this.subviews.includes(entry.contentView))
+            this.addSubview(entry.contentView)
+
         entry.prepareToShow(shouldCallShown);
     }
 
@@ -469,7 +446,8 @@
         console.assert(entry instanceof WebInspector.BackForwardEntry);
 
         entry.prepareToHide();
-        this._removeContentViewElement(entry.contentView);
+        if (this.subviews.includes(entry.contentView))
+            this.removeSubview(entry.contentView)
     }
 };
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,7 +23,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.DataGrid = class DataGrid extends WebInspector.Object
+WebInspector.DataGrid = class DataGrid extends WebInspector.View
 {
     constructor(columnsData, editCallback, deleteCallback, preferredColumnOrder)
     {
@@ -48,7 +48,6 @@
         this.resizers = [];
         this._columnWidthsInitialized = false;
 
-        this.element = document.createElement("div");
         this.element.className = "data-grid";
         this.element.tabIndex = 0;
         this.element.addEventListener("keydown", this._keyDown.bind(this), false);
@@ -400,7 +399,7 @@
         for (var [identifier, column] of this.columns)
             column["element"].style.width = widths[identifier] + "%";
         this._columnWidthsInitialized = false;
-        this.updateLayout();
+        this.needsLayout();
     }
 
     insertColumn(columnIdentifier, columnData, insertionIndex)
@@ -552,9 +551,9 @@
     //
     // If this function is not called after the DataGrid is attached to its
     // parent element, then the DataGrid's columns will not be resizable.
-    updateLayout()
+    layout()
     {
-        // Do not attempt to use offsetes if we're not attached to the document tree yet.
+        // Do not attempt to use offsets if we're not attached to the document tree yet.
         if (!this._columnWidthsInitialized && this.element.offsetWidth) {
             // Give all the columns initial widths now so that during a resize,
             // when the two columns that get resized get a percent value for
@@ -580,7 +579,6 @@
         }
 
         this._positionResizerElements();
-        this.dispatchEventToListeners(WebInspector.DataGrid.Event.DidLayout);
     }
 
     columnWidthsMap()
@@ -602,7 +600,7 @@
             this._dataTableColumnGroupElement.children[ordinal].style.width = width;
         }
 
-        this.updateLayout();
+        this.needsLayout();
     }
 
     _isColumnVisible(columnIdentifier)
@@ -1260,7 +1258,6 @@
 
         this._positionResizerElements();
         event.preventDefault();
-        this.dispatchEventToListeners(WebInspector.DataGrid.Event.DidLayout);
     }
 
     resizerDragEnded(resizer)
@@ -1270,12 +1267,10 @@
             return;
 
         this._currentResizer = null;
-        this.dispatchEventToListeners(WebInspector.DataGrid.Event.DidLayout);
     }
 };
 
 WebInspector.DataGrid.Event = {
-    DidLayout: "datagrid-did-layout",
     SortChanged: "datagrid-sort-changed",
     SelectedNodeChanged: "datagrid-selected-node-changed",
     ExpandedNode: "datagrid-expanded-node",

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -61,7 +61,7 @@
 
         // Update layout for the so other items can adjust to the extra space (or lack thereof) too.
         if (this.parentNavigationBar)
-            this.parentNavigationBar.updateLayoutSoon();
+            this.parentNavigationBar.needsLayout();
     }
 
     get lastComponent()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -86,7 +86,7 @@
         this.navigationSidebarTreeOutline.element.addEventListener("mouseleave", this._mouseLeaveTreeOutline.bind(this));
 
         this.element.classList.add("layout");
-        this.element.appendChild(this._dataGrid.element);
+        this.addSubview(this._dataGrid);
 
         timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._layoutTimelineRecordAdded, this);
 
@@ -133,15 +133,6 @@
         this._updateHighlight();
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        this._dataGrid.updateLayout();
-
-        this._processPendingRecords();
-    }
-
     matchTreeElementAgainstCustomFilters(treeElement)
     {
         return this._dataGrid.treeElementMatchesActiveScopeFilters(treeElement);
@@ -185,6 +176,11 @@
         this._updateHighlight();
     }
 
+    layout()
+    {
+        this._processPendingRecords();
+    }
+
     // Private
 
     _processPendingRecords()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,26 +23,26 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.NavigationBar = class NavigationBar extends WebInspector.Object
+WebInspector.NavigationBar = class NavigationBar extends WebInspector.View
 {
     constructor(element, navigationItems, role, label)
     {
-        super();
+        super(element);
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add(this.constructor.StyleClassName || "navigation-bar");
-        this._element.tabIndex = 0;
+        this.element.classList.add(this.constructor.StyleClassName || "navigation-bar");
+        this.element.tabIndex = 0;
 
         if (role)
-            this._element.setAttribute("role", role);
+            this.element.setAttribute("role", role);
         if (label)
-            this._element.setAttribute("aria-label", label);
+            this.element.setAttribute("aria-label", label);
 
-        this._element.addEventListener("focus", this._focus.bind(this), false);
-        this._element.addEventListener("blur", this._blur.bind(this), false);
-        this._element.addEventListener("keydown", this._keyDown.bind(this), false);
-        this._element.addEventListener("mousedown", this._mouseDown.bind(this), false);
+        this.element.addEventListener("focus", this._focus.bind(this), false);
+        this.element.addEventListener("blur", this._blur.bind(this), false);
+        this.element.addEventListener("keydown", this._keyDown.bind(this), false);
+        this.element.addEventListener("mousedown", this._mouseDown.bind(this), false);
 
+        this._minimumWidth = NaN;
         this._navigationItems = [];
 
         if (navigationItems) {
@@ -75,7 +75,7 @@
         this._navigationItems.splice(index, 0, navigationItem);
 
         if (!parentElement)
-            parentElement = this._element;
+            parentElement = this.element;
 
         var nextSibling = this._navigationItems[index + 1];
         var nextSiblingElement = nextSibling ? nextSibling.element : null;
@@ -84,9 +84,9 @@
 
         parentElement.insertBefore(navigationItem.element, nextSiblingElement);
 
-        this._minimumWidthNeedsRecalculation = true;
+        this._minimumWidth = NaN;
 
-        this.updateLayoutSoon();
+        this.needsLayout();
 
         return navigationItem;
     }
@@ -105,72 +105,13 @@
         this._navigationItems.remove(navigationItem);
         navigationItem.element.remove();
 
-        this._minimumWidthNeedsRecalculation = true;
+        this._minimumWidth = NaN;
 
-        this.updateLayoutSoon();
+        this.needsLayout();
 
         return navigationItem;
     }
 
-    updateLayoutSoon()
-    {
-        if (this._updateLayoutIdentifier)
-            return;
-
-        this._needsLayout = true;
-
-        function update()
-        {
-            this._updateLayoutIdentifier = undefined;
-
-            if (this._needsLayout)
-                this.updateLayout();
-        }
-
-        this._updateLayoutIdentifier = requestAnimationFrame(update.bind(this));
-    }
-
-    updateLayout()
-    {
-        if (this._updateLayoutIdentifier) {
-            cancelAnimationFrame(this._updateLayoutIdentifier);
-            this._updateLayoutIdentifier = undefined;
-        }
-
-        this._needsLayout = false;
-
-        if (typeof this.customUpdateLayout === "function") {
-            this.customUpdateLayout();
-            return;
-        }
-
-        // Remove the collapsed style class to test if the items can fit at full width.
-        this._element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
-
-        // Tell each navigation item to update to full width if needed.
-        for (var i = 0; i < this._navigationItems.length; ++i)
-            this._navigationItems[i].updateLayout(true);
-
-        var totalItemWidth = 0;
-        for (var i = 0; i < this._navigationItems.length; ++i) {
-            // Skip flexible space items since they can take up no space at the minimum width.
-            if (this._navigationItems[i] instanceof WebInspector.FlexibleSpaceNavigationItem)
-                continue;
-
-            totalItemWidth += this._navigationItems[i].element.realOffsetWidth;
-        }
-
-        var barWidth = this._element.realOffsetWidth;
-
-        // Add the collapsed class back if the items are wider than the bar.
-        if (totalItemWidth > barWidth)
-            this._element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
-
-        // Give each navigation item the opportunity to collapse further.
-        for (var i = 0; i < this._navigationItems.length; ++i)
-            this._navigationItems[i].updateLayout();
-    }
-
     get selectedNavigationItem()
     {
         return this._selectedNavigationItem || null;
@@ -206,18 +147,10 @@
         return this._navigationItems;
     }
 
-    get element()
-    {
-        return this._element;
-    }
-
     get minimumWidth()
     {
-        if (this._minimumWidth === undefined || this._minimumWidthNeedsRecalculation) {
+        if (isNaN(this._minimumWidth))
             this._minimumWidth = this._calculateMinimumWidth();
-            delete this._minimumWidthNeedsRecalculation;
-        }
-
         return this._minimumWidth;
     }
 
@@ -227,6 +160,35 @@
         return false;
     }
 
+    layout()
+    {
+        // Remove the collapsed style class to test if the items can fit at full width.
+        this.element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
+
+        // Tell each navigation item to update to full width if needed.
+        for (let navigationItem of this._navigationItems)
+            navigationItem.updateLayout(true);
+
+        let totalItemWidth = 0;
+        for (let navigationItem of this._navigationItems) {
+            // Skip flexible space items since they can take up no space at the minimum width.
+            if (navigationItem instanceof WebInspector.FlexibleSpaceNavigationItem)
+                continue;
+
+            totalItemWidth += navigationItem.element.realOffsetWidth;
+        }
+
+        const barWidth = this.element.realOffsetWidth;
+
+        // Add the collapsed class back if the items are wider than the bar.
+        if (totalItemWidth > barWidth)
+            this.element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
+
+        // Give each navigation item the opportunity to collapse further.
+        for (let navigationItem of this._navigationItems)
+            navigationItem.updateLayout(false);
+    }
+
     // Private
 
     _findNavigationItem(navigationItemOrIdentifierOrIndex)
@@ -259,7 +221,7 @@
         // Remove the tabIndex so clicking the navigation bar does not give it focus.
         // Only keep the tabIndex if already focused from keyboard navigation. This matches Xcode.
         if (!this._focused)
-            this._element.removeAttribute("tabindex");
+            this.element.removeAttribute("tabindex");
 
         var itemElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.RadioButtonNavigationItem.StyleClassName);
         if (!itemElement || !itemElement.navigationItem)
@@ -297,15 +259,15 @@
         event.stopPropagation();
 
         var itemElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.RadioButtonNavigationItem.StyleClassName);
-        if (!itemElement || !itemElement.navigationItem || !this._element.contains(itemElement)) {
+        if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement)) {
             // Find the element that is at the X position of the mouse, even when the mouse is no longer
             // vertically in the navigation bar.
-            var element = document.elementFromPoint(event.pageX, this._element.totalOffsetTop + (this._element.offsetHeight / 2));
+            var element = document.elementFromPoint(event.pageX, this.element.totalOffsetTop + (this.element.offsetHeight / 2));
             if (!element)
                 return;
 
             itemElement = element.enclosingNodeOrSelfWithClass(WebInspector.RadioButtonNavigationItem.StyleClassName);
-            if (!itemElement || !itemElement.navigationItem || !this._element.contains(itemElement))
+            if (!itemElement || !itemElement.navigationItem || !this.element.contains(itemElement))
                 return;
         }
 
@@ -336,7 +298,7 @@
         delete this._mouseUpEventListener;
 
         // Restore the tabIndex so the navigation bar can be in the keyboard tab loop.
-        this._element.tabIndex = 0;
+        this.element.tabIndex = 0;
 
         // Dispatch the selected event here since the selectedNavigationItem setter surpresses it
         // while the mouse is down to prevent sending it while scrubbing the bar.
@@ -393,11 +355,11 @@
 
     _calculateMinimumWidth()
     {
-        var wasCollapsed = this._element.classList.contains(WebInspector.NavigationBar.CollapsedStyleClassName);
+        const wasCollapsed = this.element.classList.contains(WebInspector.NavigationBar.CollapsedStyleClassName);
 
         // Add the collapsed style class to calculate the width of the items when they are collapsed.
         if (!wasCollapsed)
-            this._element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
+            this.element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
 
         var totalItemWidth = 0;
         for (var i = 0; i < this._navigationItems.length; ++i) {
@@ -409,7 +371,7 @@
 
         // Remove the collapsed style class if we were not collapsed before.
         if (!wasCollapsed)
-            this._element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
+            this.element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
 
         return totalItemWidth;
     }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NavigationItem.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NavigationItem.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NavigationItem.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -80,7 +80,7 @@
         this._element.classList.toggle("hidden", flag);
 
         if (this._parentNavigationBar)
-            this._parentNavigationBar.updateLayoutSoon();
+            this._parentNavigationBar.needsLayout();
     }
 
     // Private

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -93,7 +93,7 @@
         this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
 
         this.element.classList.add("network");
-        this.element.appendChild(this._dataGrid.element);
+        this.addSubview(this._dataGrid);
 
         timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
 
@@ -129,15 +129,6 @@
         this._dataGrid.closed();
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        this._dataGrid.updateLayout();
-
-        this._processPendingRecords();
-    }
-
     matchTreeElementAgainstCustomFilters(treeElement)
     {
         return this._dataGrid.treeElementMatchesActiveScopeFilters(treeElement);
@@ -187,6 +178,11 @@
         super.treeElementSelected(treeElement, selectedByUser);
     }
 
+    layout()
+    {
+        this._processPendingRecords();
+    }
+
     // Private
 
     _processPendingRecords()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -41,13 +41,14 @@
 
         this._timelineRuler = new WebInspector.TimelineRuler;
         this._timelineRuler.allowsClippedLabels = true;
+        // FIXME: change to `this.addSubview(this._timelineRuler)` once <https://webkit.org/b/150703> is fixed.
         this.element.appendChild(this._timelineRuler.element);
 
         this._currentTimeMarker = new WebInspector.TimelineMarker(0, WebInspector.TimelineMarker.Type.CurrentTime);
         this._timelineRuler.addMarker(this._currentTimeMarker);
 
         this.element.classList.add("overview");
-        this.element.appendChild(this._dataGrid.element);
+        this.addSubview(this._dataGrid);
 
         this._networkTimeline = recording.timelines.get(WebInspector.TimelineRecord.Type.Network);
         this._networkTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
@@ -88,35 +89,6 @@
         this._recording.removeEventListener(null, null, this);
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        var oldZeroTime = this._timelineRuler.zeroTime;
-        var oldStartTime = this._timelineRuler.startTime;
-        var oldEndTime = this._timelineRuler.endTime;
-        var oldCurrentTime = this._currentTimeMarker.time;
-
-        this._timelineRuler.zeroTime = this.zeroTime;
-        this._timelineRuler.startTime = this.startTime;
-        this._timelineRuler.endTime = this.endTime;
-        this._currentTimeMarker.time = this.currentTime;
-
-        // The TimelineDataGridNode graphs are positioned with percentages, so they auto resize with the view.
-        // We only need to refresh the graphs when the any of the times change.
-        if (this.zeroTime !== oldZeroTime || this.startTime !== oldStartTime || this.endTime !== oldEndTime || this.currentTime !== oldCurrentTime) {
-            var dataGridNode = this._dataGrid.children[0];
-            while (dataGridNode) {
-                dataGridNode.refreshGraph();
-                dataGridNode = dataGridNode.traverseNextNode(true, null, true);
-            }
-        }
-
-        this._timelineRuler.updateLayout();
-
-        this._processPendingRepresentedObjects();
-    }
-
     get selectionPathComponents()
     {
         var dataGridNode = this._dataGrid.selectedNode;
@@ -187,6 +159,34 @@
         WebInspector.showOriginalOrFormattedSourceCodeLocation(treeElement.sourceCodeTimeline.sourceCodeLocation);
     }
 
+    layout()
+    {
+        let oldZeroTime = this._timelineRuler.zeroTime;
+        let oldStartTime = this._timelineRuler.startTime;
+        let oldEndTime = this._timelineRuler.endTime;
+        let oldCurrentTime = this._currentTimeMarker.time;
+
+        this._timelineRuler.zeroTime = this.zeroTime;
+        this._timelineRuler.startTime = this.startTime;
+        this._timelineRuler.endTime = this.endTime;
+        this._currentTimeMarker.time = this.currentTime;
+
+        // The TimelineDataGridNode graphs are positioned with percentages, so they auto resize with the view.
+        // We only need to refresh the graphs when the any of the times change.
+        if (this.zeroTime !== oldZeroTime || this.startTime !== oldStartTime || this.endTime !== oldEndTime || this.currentTime !== oldCurrentTime) {
+            let dataGridNode = this._dataGrid.children[0];
+            while (dataGridNode) {
+                dataGridNode.refreshGraph();
+                dataGridNode = dataGridNode.traverseNextNode(true, null, true);
+            }
+        }
+
+        // FIXME: remove once <https://webkit.org/b/150703> is fixed.
+        this._timelineRuler.updateLayout();
+
+        this._processPendingRepresentedObjects();
+    }
+
     // Private
 
     _compareTreeElementsByDetails(a, b)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/QuickConsole.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/QuickConsole.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/QuickConsole.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,11 +23,11 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.QuickConsole = class QuickConsole extends WebInspector.Object
+WebInspector.QuickConsole = class QuickConsole extends WebInspector.View
 {
     constructor(element)
     {
-        super();
+        super(element);
 
         this._toggleOrFocusKeyboardShortcut = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Escape, this._toggleOrFocus.bind(this));
 
@@ -38,12 +38,11 @@
         this._otherExecutionContextPathComponents = [];
         this._frameIdentifierToExecutionContextPathComponentMap = {};
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("quick-console");
+        this.element.classList.add("quick-console");
 
         this.prompt = new WebInspector.ConsolePrompt(null, "text/_javascript_");
         this.prompt.element.classList.add("text-prompt");
-        this._element.appendChild(this.prompt.element);
+        this.addSubview(this.prompt);
 
         // FIXME: CodeMirror 4 has a default "Esc" key handler that always prevents default.
         // Our keyboard shortcut above will respect the default prevented and ignore the event
@@ -55,7 +54,7 @@
         this.prompt.shown();
 
         this._navigationBar = new WebInspector.QuickConsoleNavigationBar;
-        this._element.appendChild(this._navigationBar.element);
+        this.addSubview(this._navigationBar);
 
         this._executionContextSelectorItem = new WebInspector.HierarchicalPathNavigationItem;
         this._executionContextSelectorItem.showSelectorArrows = true;
@@ -74,11 +73,6 @@
 
     // Public
 
-    get element()
-    {
-        return this._element;
-    }
-
     get navigationBar()
     {
         return this._navigationBar;
@@ -89,13 +83,6 @@
         return this._selectedExecutionContextPathComponent._executionContextIdentifier;
     }
 
-    updateLayout()
-    {
-        // A hard maximum size of 33% of the window.
-        var maximumAllowedHeight = Math.round(window.innerHeight * 0.33);
-        this.prompt.element.style.maxHeight = maximumAllowedHeight + "px";
-    }
-
     consoleLogVisibilityChanged(visible)
     {
         if (visible === this.element.classList.contains(WebInspector.QuickConsole.ShowingLogClassName))
@@ -106,6 +93,15 @@
         this.dispatchEventToListeners(WebInspector.QuickConsole.Event.DidResize);
     }
 
+    // Protected
+
+    layout()
+    {
+        // A hard maximum size of 33% of the window.
+        let maximumAllowedHeight = Math.round(window.innerHeight * 0.33);
+        this.prompt.element.style.maxHeight = maximumAllowedHeight + "px";
+    }
+
     // Private
 
     _executionContextPathComponentsToDisplay()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -79,7 +79,7 @@
         this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
 
         this.element.classList.add("rendering-frame");
-        this.element.appendChild(this._dataGrid.element);
+        this.addSubview(this._dataGrid);
 
         timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._renderingFrameTimelineRecordAdded, this);
 
@@ -131,15 +131,6 @@
         this._dataGrid.closed();
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        this._dataGrid.updateLayout();
-
-        this._processPendingRecords();
-    }
-
     get selectionPathComponents()
     {
         var dataGridNode = this._dataGrid.selectedNode;
@@ -245,6 +236,11 @@
         return null;
     }
 
+    layout()
+    {
+        this._processPendingRecords();
+    }
+
     // Private
 
     _processPendingRecords()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -68,7 +68,7 @@
         this._dataGrid.sortOrder = WebInspector.DataGrid.SortOrder.Ascending;
 
         this.element.classList.add("script");
-        this.element.appendChild(this._dataGrid.element);
+        this.addSubview(this._dataGrid);
 
         timeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._scriptTimelineRecordAdded, this);
 
@@ -104,28 +104,6 @@
         this._dataGrid.closed();
     }
 
-    updateLayout()
-    {
-        super.updateLayout();
-
-        this._dataGrid.updateLayout();
-
-        if (this.startTime !== this._oldStartTime || this.endTime !== this._oldEndTime) {
-            var dataGridNode = this._dataGrid.children[0];
-            while (dataGridNode) {
-                dataGridNode.updateRangeTimes(this.startTime, this.endTime);
-                if (dataGridNode.revealed)
-                    dataGridNode.refreshIfNeeded();
-                dataGridNode = dataGridNode.traverseNextNode(false, null, true);
-            }
-
-            this._oldStartTime = this.startTime;
-            this._oldEndTime = this.endTime;
-        }
-
-        this._processPendingRecords();
-    }
-
     get selectionPathComponents()
     {
         var dataGridNode = this._dataGrid.selectedNode;
@@ -217,6 +195,24 @@
         }
     }
 
+    layout()
+    {
+        if (this.startTime !== this._oldStartTime || this.endTime !== this._oldEndTime) {
+            let dataGridNode = this._dataGrid.children[0];
+            while (dataGridNode) {
+                dataGridNode.updateRangeTimes(this.startTime, this.endTime);
+                if (dataGridNode.revealed)
+                    dataGridNode.refreshIfNeeded();
+                dataGridNode = dataGridNode.traverseNextNode(false, null, true);
+            }
+
+            this._oldStartTime = this.startTime;
+            this._oldEndTime = this.endTime;
+        }
+
+        this._processPendingRecords();
+    }
+
     // Private
 
     _processPendingRecords()

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,23 +23,22 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.TabBar = class TabBar extends WebInspector.Object
+WebInspector.TabBar = class TabBar extends WebInspector.View
 {
     constructor(element, tabBarItems)
     {
-        super();
+        super(element);
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("tab-bar");
-        this._element.setAttribute("role", "tablist");
+        this.element.classList.add("tab-bar");
+        this.element.setAttribute("role", "tablist");
 
         var topBorderElement = document.createElement("div");
         topBorderElement.classList.add("top-border");
-        this._element.appendChild(topBorderElement);
+        this.element.appendChild(topBorderElement);
 
-        this._element.addEventListener("mousedown", this._handleMouseDown.bind(this));
-        this._element.addEventListener("click", this._handleClick.bind(this));
-        this._element.addEventListener("mouseleave", this._handleMouseLeave.bind(this));
+        this.element.addEventListener("mousedown", this._handleMouseDown.bind(this));
+        this.element.addEventListener("click", this._handleClick.bind(this));
+        this.element.addEventListener("mouseleave", this._handleMouseLeave.bind(this));
 
         this._tabBarItems = [];
 
@@ -111,7 +110,7 @@
         var lastIndex = this._newTabItem ? this._tabBarItems.length - 1 : this._tabBarItems.length;
         index = Math.max(0, Math.min(index, lastIndex));
 
-        if (this._element.classList.contains("animating")) {
+        if (this.element.classList.contains("animating")) {
             requestAnimationFrame(removeStyles.bind(this));
             doNotAnimate = true;
         }
@@ -125,34 +124,34 @@
         var nextSibling = this._tabBarItems[index + 1];
         var nextSiblingElement = nextSibling ? nextSibling.element : (this._newTabItem ? this._newTabItem.element : null);
 
-        this._element.insertBefore(tabBarItem.element, nextSiblingElement);
+        this.element.insertBefore(tabBarItem.element, nextSiblingElement);
 
-        this._element.classList.toggle("single-tab", !this._hasMoreThanOneNormalTab());
+        this.element.classList.toggle("single-tab", !this._hasMoreThanOneNormalTab());
 
         tabBarItem.element.style.left = null;
         tabBarItem.element.style.width = null;
 
         function animateTabs()
         {
-            this._element.classList.add("animating");
-            this._element.classList.add("inserting-tab");
+            this.element.classList.add("animating");
+            this.element.classList.add("inserting-tab");
 
             this._applyTabBarItemSizesAndPositions(afterTabSizesAndPositions);
 
-            this._element.addEventListener("webkitTransitionEnd", removeStylesListener);
+            this.element.addEventListener("webkitTransitionEnd", removeStylesListener);
         }
 
         function removeStyles()
         {
-            this._element.classList.remove("static-layout");
-            this._element.classList.remove("animating");
-            this._element.classList.remove("inserting-tab");
+            this.element.classList.remove("static-layout");
+            this.element.classList.remove("animating");
+            this.element.classList.remove("inserting-tab");
 
             tabBarItem.element.classList.remove("being-inserted");
 
             this._clearTabBarItemSizesAndPositions();
 
-            this._element.removeEventListener("webkitTransitionEnd", removeStylesListener);
+            this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
         }
 
         if (!doNotAnimate) {
@@ -168,7 +167,7 @@
             else
                 beforeTabSizesAndPositions.set(tabBarItem, {left: 0, width: 0});
 
-            this._element.classList.add("static-layout");
+            this.element.classList.add("static-layout");
             tabBarItem.element.classList.add("being-inserted");
 
             this._applyTabBarItemSizesAndPositions(beforeTabSizesAndPositions);
@@ -177,7 +176,7 @@
 
             requestAnimationFrame(animateTabs.bind(this));
         } else
-            this.updateLayoutSoon();
+            this.needsLayout();
 
         this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemAdded, {tabBarItem});
 
@@ -204,7 +203,7 @@
             this.selectedTabBarItem = nextTabBarItem;
         }
 
-        if (this._element.classList.contains("animating")) {
+        if (this.element.classList.contains("animating")) {
             requestAnimationFrame(removeStyles.bind(this));
             doNotAnimate = true;
         }
@@ -219,7 +218,7 @@
         tabBarItem.element.remove();
 
         var hasMoreThanOneNormalTab = this._hasMoreThanOneNormalTab();
-        this._element.classList.toggle("single-tab", !hasMoreThanOneNormalTab);
+        this.element.classList.toggle("single-tab", !hasMoreThanOneNormalTab);
 
         const shouldOpenDefaultTab = !tabBarItem.isDefaultTab && !this.hasNormalTab();
         if (shouldOpenDefaultTab)
@@ -230,7 +229,7 @@
                 this._tabAnimatedClosedSinceMouseEnter = true;
                 this._finishExpandingTabsAfterClose(beforeTabSizesAndPositions);
             } else
-                this.updateLayoutSoon();
+                this.needsLayout();
 
             this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemRemoved, {tabBarItem});
 
@@ -244,8 +243,8 @@
 
         function animateTabs()
         {
-            this._element.classList.add("animating");
-            this._element.classList.add("closing-tab");
+            this.element.classList.add("animating");
+            this.element.classList.add("closing-tab");
 
             var left = 0;
             for (var currentTabBarItem of this._tabBarItems) {
@@ -266,7 +265,7 @@
             if (lastNormalTabBarItem !== this._selectedTabBarItem)
                 lastNormalTabBarItem.element.style.width = (parseFloat(lastNormalTabBarItem.element.style.width) + 1) + "px";
 
-            this._element.addEventListener("webkitTransitionEnd", removeStylesListener);
+            this.element.addEventListener("webkitTransitionEnd", removeStylesListener);
         }
 
         function removeStyles()
@@ -275,16 +274,16 @@
             if (this._selectedTabBarItem && this._selectedTabBarItem !== lastNormalTabBarItem)
                 this._selectedTabBarItem.element.style.width = (parseFloat(this._selectedTabBarItem.element.style.width) - 1) + "px";
 
-            this._element.classList.remove("animating");
-            this._element.classList.remove("closing-tab");
+            this.element.classList.remove("animating");
+            this.element.classList.remove("closing-tab");
 
             this.updateLayout();
 
-            this._element.removeEventListener("webkitTransitionEnd", removeStylesListener);
+            this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
         }
 
         if (!doNotAnimate) {
-            this._element.classList.add("static-layout");
+            this.element.classList.add("static-layout");
 
             this._tabAnimatedClosedSinceMouseEnter = true;
 
@@ -294,7 +293,7 @@
 
             requestAnimationFrame(animateTabs.bind(this));
         } else
-            this.updateLayoutSoon();
+            this.needsLayout();
 
         this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemRemoved, {tabBarItem});
 
@@ -350,61 +349,6 @@
         this.selectedTabBarItem = this._tabBarItems[newIndex];
     }
 
-    updateLayoutSoon()
-    {
-        if (this._updateLayoutIdentifier)
-            return;
-
-        this._needsLayout = true;
-
-        function update()
-        {
-            this._updateLayoutIdentifier = undefined;
-
-            if (this._needsLayout)
-                this.updateLayout();
-        }
-
-        this._updateLayoutIdentifier = requestAnimationFrame(update.bind(this));
-    }
-
-    updateLayout()
-    {
-        if (this._updateLayoutIdentifier) {
-            cancelAnimationFrame(this._updateLayoutIdentifier);
-            this._updateLayoutIdentifier = undefined;
-        }
-
-        if (this._element.classList.contains("static-layout"))
-            return;
-
-        this._needsLayout = false;
-
-        this._element.classList.remove("hide-titles");
-        this._element.classList.remove("collapsed");
-
-        var firstNormalTabItem = null;
-        for (var tabItem of this._tabBarItems) {
-            if (tabItem.pinned)
-                continue;
-            firstNormalTabItem = tabItem;
-            break;
-        }
-
-        if (!firstNormalTabItem)
-            return;
-
-        if (firstNormalTabItem.element.offsetWidth >= 120)
-            return;
-
-        this._element.classList.add("collapsed");
-
-        if (firstNormalTabItem.element.offsetWidth >= 60)
-            return;
-
-        this._element.classList.add("hide-titles");
-    }
-
     get selectedTabBarItem()
     {
         return this._selectedTabBarItem;
@@ -435,14 +379,41 @@
         return this._tabBarItems;
     }
 
-    get element()
+    hasNormalTab()
     {
-        return this._element;
+        return this._tabBarItems.some((tab) => !tab.pinned);
     }
 
-    hasNormalTab()
+    // Protected
+
+    layout()
     {
-        return this._tabBarItems.some((tab) => !tab.pinned);
+        if (this.element.classList.contains("static-layout"))
+            return;
+
+        this.element.classList.remove("hide-titles");
+        this.element.classList.remove("collapsed");
+
+        let firstNormalTabItem = null;
+        for (let tabItem of this._tabBarItems) {
+            if (tabItem.pinned)
+                continue;
+            firstNormalTabItem = tabItem;
+            break;
+        }
+
+        if (!firstNormalTabItem)
+            return;
+
+        if (firstNormalTabItem.element.offsetWidth >= 120)
+            return;
+
+        this.element.classList.add("collapsed");
+
+        if (firstNormalTabItem.element.offsetWidth >= 60)
+            return;
+
+        this.element.classList.add("hide-titles");
     }
 
     // Private
@@ -483,7 +454,7 @@
     {
         var tabBarItemSizesAndPositions = new Map;
 
-        var barRect = this._element.getBoundingClientRect();
+        const barRect = this.element.getBoundingClientRect();
 
         for (var tabBarItem of this._tabBarItems) {
             var boundingRect = tabBarItem.element.getBoundingClientRect();
@@ -522,7 +493,7 @@
             if (!beforeTabSizesAndPositions)
                 beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
 
-            this._element.classList.remove("static-layout");
+            this.element.classList.remove("static-layout");
             this._clearTabBarItemSizesAndPositions();
 
             var afterTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
@@ -532,26 +503,26 @@
 
             function animateTabs()
             {
-                this._element.classList.add("static-layout");
-                this._element.classList.add("animating");
-                this._element.classList.add("expanding-tabs");
+                this.element.classList.add("static-layout");
+                this.element.classList.add("animating");
+                this.element.classList.add("expanding-tabs");
 
                 this._applyTabBarItemSizesAndPositions(afterTabSizesAndPositions);
 
-                this._element.addEventListener("webkitTransitionEnd", removeStylesListener);
+                this.element.addEventListener("webkitTransitionEnd", removeStylesListener);
             }
 
             function removeStyles()
             {
-                this._element.classList.remove("static-layout");
-                this._element.classList.remove("animating");
-                this._element.classList.remove("expanding-tabs");
+                this.element.classList.remove("static-layout");
+                this.element.classList.remove("animating");
+                this.element.classList.remove("expanding-tabs");
 
                 this._clearTabBarItemSizesAndPositions();
 
                 this.updateLayout();
 
-                this._element.removeEventListener("webkitTransitionEnd", removeStylesListener);
+                this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
 
                 resolve();
             }
@@ -630,7 +601,7 @@
         var closeButtonElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.TabBarItem.CloseButtonStyleClassName);
         if (closeButtonElement || clickedMiddleButton) {
             // Disallow closing the default tab if it is the only tab.
-            if (tabBarItem.isDefaultTab && this._element.classList.contains("single-tab"))
+            if (tabBarItem.isDefaultTab && this.element.classList.contains("single-tab"))
                 return;
 
             this.removeTabBarItem(tabBarItem, false, true);
@@ -651,10 +622,10 @@
         event.preventDefault();
         event.stopPropagation();
 
-        if (!this._element.classList.contains("static-layout")) {
+        if (!this.element.classList.contains("static-layout")) {
             this._applyTabBarItemSizesAndPositions(this._recordTabBarItemSizesAndPositions());
-            this._element.classList.add("static-layout");
-            this._element.classList.add("dragging-tab");
+            this.element.classList.add("static-layout");
+            this.element.classList.add("dragging-tab");
         }
 
         if (this._mouseOffset === undefined)
@@ -695,7 +666,7 @@
         var nextSibling = this._tabBarItems[newIndex + 1];
         var nextSiblingElement = nextSibling ? nextSibling.element : (this._newTabItem ? this._newTabItem.element : null);
 
-        this._element.insertBefore(this._selectedTabBarItem.element, nextSiblingElement);
+        this.element.insertBefore(this._selectedTabBarItem.element, nextSiblingElement);
 
         // FIXME: Animate the tabs that move to make room for the selected tab. This was causing me trouble when I tried.
 
@@ -714,10 +685,10 @@
         if (!this._mouseIsDown)
             return;
 
-        this._element.classList.remove("dragging-tab");
+        this.element.classList.remove("dragging-tab");
 
         if (!this._tabAnimatedClosedSinceMouseEnter) {
-            this._element.classList.remove("static-layout");
+            this.element.classList.remove("static-layout");
             this._clearTabBarItemSizesAndPositions();
         } else {
             var left = 0;
@@ -745,14 +716,14 @@
 
     _handleMouseLeave(event)
     {
-        if (this._mouseIsDown || !this._tabAnimatedClosedSinceMouseEnter || !this._element.classList.contains("static-layout") || this._element.classList.contains("animating"))
+        if (this._mouseIsDown || !this._tabAnimatedClosedSinceMouseEnter || !this.element.classList.contains("static-layout") || this.element.classList.contains("animating"))
             return;
 
         // This event can still fire when the mouse is inside the element if DOM nodes are added, removed or generally change inside.
         // Check if the mouse really did leave the element by checking the bounds.
         // FIXME: Is this a WebKit bug or correct behavior?
-        var barRect = this._element.getBoundingClientRect();
-        var newTabItemRect = this._newTabItem ? this._newTabItem.element.getBoundingClientRect() : null;
+        const barRect = this.element.getBoundingClientRect();
+        const newTabItemRect = this._newTabItem ? this._newTabItem.element.getBoundingClientRect() : null;
         if (event.pageY > barRect.top && event.pageY < barRect.bottom && event.pageX > barRect.left && event.pageX < (newTabItemRect ? newTabItemRect.right : barRect.right))
             return;
 
@@ -768,7 +739,7 @@
 
     _handleNewTabMouseEnter(event)
     {
-        if (!this._tabAnimatedClosedSinceMouseEnter || !this._element.classList.contains("static-layout") || this._element.classList.contains("animating"))
+        if (!this._tabAnimatedClosedSinceMouseEnter || !this.element.classList.contains("static-layout") || this.element.classList.contains("animating"))
             return;
 
         this._finishExpandingTabsAfterClose();

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBrowser.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -23,19 +23,17 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
+WebInspector.TabBrowser = class TabBrowser extends WebInspector.View
 {
     constructor(element, tabBar, navigationSidebar, detailsSidebar)
     {
-        super();
+        console.assert(tabBar, "Must provide a TabBar.");
 
-        this._element = element || document.createElement("div");
-        this._element.classList.add("tab-browser");
+        super(element);
 
-        this._tabBar = tabBar || new WebInspector.TabBar;
-        if (!tabBar)
-            this._element.appendChild(this._tabBar.element);
+        this.element.classList.add("tab-browser");
 
+        this._tabBar = tabBar;
         this._navigationSidebar = navigationSidebar || null;
         this._detailsSidebar = detailsSidebar || null;
 
@@ -48,7 +46,7 @@
         }
 
         this._contentViewContainer = new WebInspector.ContentViewContainer;
-        this._element.appendChild(this._contentViewContainer.element);
+        this.addSubview(this._contentViewContainer);
 
         var showNextTab = this._showNextTab.bind(this);
         var showPreviousTab = this._showPreviousTab.bind(this);
@@ -73,11 +71,6 @@
 
     // Public
 
-    get element()
-    {
-        return this._element;
-    }
-
     get tabBar()
     {
         return this._tabBar;
@@ -98,12 +91,6 @@
         return this._contentViewContainer.currentContentView;
     }
 
-    updateLayout()
-    {
-        this._tabBar.updateLayout();
-        this._contentViewContainer.updateLayout();
-    }
-
     bestTabContentViewForClass(constructor)
     {
         console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0]);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineView.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineView.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineView.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -172,26 +172,18 @@
         return true;
     }
 
-    updateLayout()
+    filterUpdated()
     {
-        if (this._scheduledLayoutUpdateIdentifier) {
-            cancelAnimationFrame(this._scheduledLayoutUpdateIdentifier);
-            this._scheduledLayoutUpdateIdentifier = undefined;
-        }
-
-        // Implemented by sub-classes if needed.
+        this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
     }
 
-    updateLayoutIfNeeded()
+    needsLayout()
     {
-        if (!this._scheduledLayoutUpdateIdentifier)
+        // FIXME: needsLayout can be removed once <https://webkit.org/b/150741> is fixed.
+        if (!this.visible)
             return;
-        this.updateLayout();
-    }
 
-    filterUpdated()
-    {
-        this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
+        super.needsLayout();
     }
 
     // Protected
@@ -247,15 +239,4 @@
 
         this.showContentViewForTreeElement(treeElement);
     }
-
-    needsLayout()
-    {
-        if (!this.visible)
-            return;
-
-        if (this._scheduledLayoutUpdateIdentifier)
-            return;
-
-        this._scheduledLayoutUpdateIdentifier = requestAnimationFrame(this.updateLayout.bind(this));
-    }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Toolbar.js (191975 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Toolbar.js	2015-11-03 21:52:42 UTC (rev 191975)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Toolbar.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -34,30 +34,30 @@
 
         this._controlSectionElement = document.createElement("div");
         this._controlSectionElement.className = WebInspector.Toolbar.ControlSectionStyleClassName;
-        this._element.appendChild(this._controlSectionElement);
+        this.element.appendChild(this._controlSectionElement);
 
         this._leftSectionElement = document.createElement("div");
         this._leftSectionElement.className = WebInspector.Toolbar.ItemSectionStyleClassName + " " + WebInspector.Toolbar.LeftItemSectionStyleClassName;
-        this._element.appendChild(this._leftSectionElement);
+        this.element.appendChild(this._leftSectionElement);
 
         this._centerLeftSectionElement = document.createElement("div");
         this._centerLeftSectionElement.className = WebInspector.Toolbar.ItemSectionStyleClassName + " " + WebInspector.Toolbar.CenterLeftItemSectionStyleClassName;
-        this._element.appendChild(this._centerLeftSectionElement);
+        this.element.appendChild(this._centerLeftSectionElement);
 
         this._centerSectionElement = document.createElement("div");
         this._centerSectionElement.className = WebInspector.Toolbar.ItemSectionStyleClassName + " " + WebInspector.Toolbar.CenterItemSectionStyleClassName;
-        this._element.appendChild(this._centerSectionElement);
+        this.element.appendChild(this._centerSectionElement);
 
         this._centerRightSectionElement = document.createElement("div");
         this._centerRightSectionElement.className = WebInspector.Toolbar.ItemSectionStyleClassName + " " + WebInspector.Toolbar.CenterRightItemSectionStyleClassName;
-        this._element.appendChild(this._centerRightSectionElement);
+        this.element.appendChild(this._centerRightSectionElement);
 
         this._rightSectionElement = document.createElement("div");
         this._rightSectionElement.className = WebInspector.Toolbar.ItemSectionStyleClassName + " " + WebInspector.Toolbar.RightItemSectionStyleClassName;
-        this._element.appendChild(this._rightSectionElement);
+        this.element.appendChild(this._rightSectionElement);
 
         if (!dontAllowModeChanges)
-            this._element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);
+            this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);
     }
 
     // Public
@@ -73,15 +73,15 @@
             return;
 
         if (this._displayMode)
-            this._element.classList.remove(this._displayMode);
+            this.element.classList.remove(this._displayMode);
 
         // Revert the forced icon-only mode if it was applied.
         if (this._displayMode === WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal)
-            this._element.classList.remove(WebInspector.Toolbar.DisplayMode.IconOnly);
+            this.element.classList.remove(WebInspector.Toolbar.DisplayMode.IconOnly);
 
         this._displayMode = mode;
 
-        this._element.classList.add(mode);
+        this.element.classList.add(mode);
 
         this.updateLayout();
 
@@ -99,36 +99,74 @@
             return;
 
         if (this._sizeMode)
-            this._element.classList.remove(this._sizeMode);
+            this.element.classList.remove(this._sizeMode);
 
         this._sizeMode = mode;
 
-        this._element.classList.add(mode);
+        this.element.classList.add(mode);
 
         this.updateLayout();
 
         this.dispatchEventToListeners(WebInspector.Toolbar.Event.SizeModeDidChange);
     }
 
-    customUpdateLayout()
+    addToolbarItem(toolbarItem, sectionIdentifier)
     {
+        var sectionElement;
+
+        switch (sectionIdentifier) {
+        case WebInspector.Toolbar.Section.Control:
+            sectionElement = this._controlSectionElement;
+            break;
+
+        case WebInspector.Toolbar.Section.Left:
+            sectionElement = this._leftSectionElement;
+            break;
+
+        case WebInspector.Toolbar.Section.CenterLeft:
+            sectionElement = this._centerLeftSectionElement;
+            break;
+
+        default:
+        case WebInspector.Toolbar.Section.Center:
+            sectionElement = this._centerSectionElement;
+            break;
+
+        case WebInspector.Toolbar.Section.CenterRight:
+            sectionElement = this._centerRightSectionElement;
+            break;
+
+        case WebInspector.Toolbar.Section.Right:
+            sectionElement = this._rightSectionElement;
+            break;
+        }
+
+        console.assert(sectionElement);
+
+        this.addNavigationItem(toolbarItem, sectionElement);
+    }
+
+    // Protected
+
+    layout()
+    {
         // Bail early if our sections are not created yet. This means we are being called during construction.
         if (!this._leftSectionElement || !this._centerSectionElement || !this._rightSectionElement)
             return;
 
         // Force collapsed style for _javascript_ debuggables.
         if (WebInspector.debuggableType === WebInspector.DebuggableType._javascript_) {
-            this._element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
+            this.element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
             return;
         }
 
         // Remove the collapsed style class to test if the items can fit at full width.
-        this._element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
+        this.element.classList.remove(WebInspector.NavigationBar.CollapsedStyleClassName);
 
         // Revert the forced icon-only mode if it was applied.
         if (this._displayMode === WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal) {
-            this._element.classList.remove(WebInspector.Toolbar.DisplayMode.IconOnly);
-            this._element.classList.add(WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal);
+            this.element.classList.remove(WebInspector.Toolbar.DisplayMode.IconOnly);
+            this.element.classList.add(WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal);
         }
 
         function isOverflowingToolbar()
@@ -147,52 +185,16 @@
         // Only the horizontal display mode supports collapsing labels.
         // If any sections are overflowing the toolbar then force the display mode to be icon only.
         if (this._displayMode === WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal && isOverflowingToolbar.call(this)) {
-            this._element.classList.remove(WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal);
-            this._element.classList.add(WebInspector.Toolbar.DisplayMode.IconOnly);
+            this.element.classList.remove(WebInspector.Toolbar.DisplayMode.IconAndLabelHorizontal);
+            this.element.classList.add(WebInspector.Toolbar.DisplayMode.IconOnly);
         }
 
         if (!isOverflowingToolbar.call(this))
             return;
 
-        this._element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
+        this.element.classList.add(WebInspector.NavigationBar.CollapsedStyleClassName);
     }
 
-    addToolbarItem(toolbarItem, sectionIdentifier)
-    {
-        var sectionElement;
-
-        switch (sectionIdentifier) {
-        case WebInspector.Toolbar.Section.Control:
-            sectionElement = this._controlSectionElement;
-            break;
-
-        case WebInspector.Toolbar.Section.Left:
-            sectionElement = this._leftSectionElement;
-            break;
-
-        case WebInspector.Toolbar.Section.CenterLeft:
-            sectionElement = this._centerLeftSectionElement;
-            break;
-
-        default:
-        case WebInspector.Toolbar.Section.Center:
-            sectionElement = this._centerSectionElement;
-            break;
-
-        case WebInspector.Toolbar.Section.CenterRight:
-            sectionElement = this._centerRightSectionElement;
-            break;
-
-        case WebInspector.Toolbar.Section.Right:
-            sectionElement = this._rightSectionElement;
-            break;
-        }
-
-        console.assert(sectionElement);
-
-        this.addNavigationItem(toolbarItem, sectionElement);
-    }
-
     // Private
 
     _handleContextMenuEvent(event)

Added: trunk/Source/WebInspectorUI/UserInterface/Views/View.js (0 => 191976)


--- trunk/Source/WebInspectorUI/UserInterface/Views/View.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/View.js	2015-11-03 21:56:35 UTC (rev 191976)
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 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.View = class View extends WebInspector.Object
+{
+    constructor(element)
+    {
+        super();
+
+        this._element = element || document.createElement("div");
+        this._element.__view = this;
+        this._subviews = [];
+    }
+
+    // Public
+
+    get element()
+    {
+        return this._element;
+    }
+
+    get subviews()
+    {
+        return this._subviews;
+    }
+
+    addSubview(view)
+    {
+        this.insertSubviewBefore(view, null);
+    }
+
+    insertSubviewBefore(view, referenceView)
+    {
+        console.assert(view instanceof WebInspector.View);
+        console.assert(!referenceView || referenceView instanceof WebInspector.View);
+
+        if (this._subviews.includes(view)) {
+            console.assert(false, "Cannot add view that is already a subview.", view);
+            return;
+        }
+
+        const beforeIndex = referenceView ? this._subviews.indexOf(referenceView) : this._subviews.length;
+        if (beforeIndex === -1) {
+            console.assert(false, "Cannot insert view. Invalid reference view.", referenceView);
+            return;
+        }
+
+        this._subviews.insertAtIndex(view, beforeIndex);
+        this._element.insertBefore(view.element, referenceView ? referenceView.element : null);
+    }
+
+    removeSubview(view)
+    {
+        console.assert(view instanceof WebInspector.View);
+        console.assert(view.element.parentNode === this._element, "Subview DOM element must be a child of the parent view element.");
+
+        if (!this._subviews.includes(view)) {
+            console.assert(false, "Cannot remove view which isn't a subview.", view);
+            return;
+        }
+
+        this._subviews.remove(view, true);
+        this._element.removeChild(view.element);
+    }
+
+    replaceSubview(oldView, newView)
+    {
+        console.assert(oldView !== newView, "Cannot replace subview with itself.");
+
+        this.insertSubviewBefore(newView, oldView);
+        this.removeSubview(oldView);
+    }
+
+    updateLayout()
+    {
+        this._layoutSubtree();
+    }
+
+    updateLayoutIfNeeded()
+    {
+        if (!this._scheduledLayoutUpdateIdentifier)
+            return;
+
+        this.updateLayout();
+    }
+
+    needsLayout()
+    {
+        if (this._scheduledLayoutUpdateIdentifier)
+            return;
+
+        this._scheduledLayoutUpdateIdentifier = requestAnimationFrame(() => {
+            this._scheduledLayoutUpdateIdentifier = undefined;
+            this._layoutSubtree();
+        });
+    }
+
+    // Protected
+
+    layout()
+    {
+        // Overridden by subclasses.
+        // Not responsible for recursing to child views.
+        // Should not be called directly; use updateLayout() instead.
+    }
+
+    // Private
+
+    _layoutSubtree()
+    {
+        if (this._scheduledLayoutUpdateIdentifier) {
+            cancelAnimationFrame(this._scheduledLayoutUpdateIdentifier);
+            this._scheduledLayoutUpdateIdentifier = undefined;
+        }
+
+        this.layout();
+
+        for (let view of this._subviews)
+            view._layoutSubtree();
+    }
+};
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to