Web Inspector: Items in the toolbar take up to much vertical space
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Mar 2020 03:22:01 +0000 (03:22 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 3 Mar 2020 03:22:01 +0000 (03:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=204627
<rdar://problem/59091905>

Reviewed by Timothy Hatcher.

Source/WebCore:

Now that there is no toolbar area, there is nothing obstructing the ability for the window
to be moved around when dragging via the title bar area. As such, we can remove the unused
`InspectorFrontendHost` APIs.

* inspector/InspectorFrontendHost.idl:
* inspector/InspectorFrontendHost.h:
* inspector/InspectorFrontendHost.cpp:
(WebCore::InspectorFrontendHost::startWindowDrag): Deleted.
(WebCore::InspectorFrontendHost::moveWindowBy const): Deleted.

* inspector/InspectorFrontendClient.h:
* inspector/InspectorFrontendClientLocal.h:
* inspector/InspectorFrontendClientLocal.cpp:
(WebCore::InspectorFrontendClientLocal::moveWindowBy): Deleted.

Source/WebInspectorUI:

Merge the toolbar are and tab bar to waste less vertical space.

Existing toolbar buttons have been moved to a space before the tab bar, and are only shown
when needed (e.g. only show the reload button when remotely inspecting).

If there are any console warnings/errors, an icon for each type of message is shown between
the left buttons and the tabs, and each button's opacity is animated whenever a new message
is added.

Whenever the debugger pauses, change the tab bar icon of the Sources Tab to an image that
includes paused iconography to help convey the debugger's state no matter which tab is
currently selected, just like the debugger dashboard.

The dashboard network information has been moved to the Network Tab (described below).

When undocked, the tab bar and all the content below it are pushed down by 22px to make room
for the system close/minimize/maximize buttons and the window title.

* UserInterface/Base/Main.js:
(WI.loaded):
(WI._handleSettingsKeyboardShortcut):
(WI._tryToRestorePendingTabs):
(WI.isNewTabWithTypeAllowed):
(WI._openDefaultTab): Deleted.
(WI.showNewTabTab): Deleted.
* UserInterface/Views/Main.css:
(#undocked-title-area): Added.
(body.docked #undocked-title-area): Added.
(body.window-inactive #undocked-title-area): Added.
(#main):
(@keyframes tab-bar-console-item-pulse): Added.
(.tab-bar > .navigation-bar :matches(.console-warnings, .console-errors):not(.disabled).pulsing): Added.
(@media (prefers-color-scheme: dark) #undocked-title-area): Added.
(@media (prefers-color-scheme: dark) body.window-inactive #undocked-title-area): Added.
(body.docked.bottom): Deleted.
(body.docked.bottom #toolbar): Deleted.
(body.docked.bottom #toolbar .item:not(.flexible-space)): Deleted.

* UserInterface/Views/TabBar.js:
(WI.TabBar):
(WI.TabBar.get horizontalPadding): Added.
(WI.TabBar.prototype.addNavigationItemBefore): Added.
(WI.TabBar.prototype.addNavigationItemAfter): Added.
(WI.TabBar.prototype.insertTabBarItem):
(WI.TabBar.prototype.insertTabBarItem.animateTabs):
(WI.TabBar.prototype.insertTabBarItem.removeStyles):
(WI.TabBar.prototype.removeTabBarItem):
(WI.TabBar.prototype.removeTabBarItem.animateTabs):
(WI.TabBar.prototype.removeTabBarItem.removeStyles):
(WI.TabBar.prototype.set selectedTabBarItem):
(WI.TabBar.prototype.get tabCount): Added.
(WI.TabBar.prototype.layout):
(WI.TabBar.prototype.layout.measureItemWidth):
(WI.TabBar.prototype.layout.recalculateItemWidths):
(WI.TabBar.prototype.didLayoutSubtree): Added.
(WI.TabBar.prototype._recordTabBarItemSizesAndPositions):
(WI.TabBar.prototype._recordTabBarItemSizesAndPositions.add): Added.
(WI.TabBar.prototype._applyTabBarItemSizesAndPositions):
(WI.TabBar.prototype._finishExpandingTabsAfterClose):
(WI.TabBar.prototype._finishExpandingTabsAfterClose.animateTabs):
(WI.TabBar.prototype._finishExpandingTabsAfterClose.removeStyles):
(WI.TabBar.prototype._handleClick):
(WI.TabBar.prototype._handleMouseMoved):
(WI.TabBar.prototype._handleMouseMoved.inlineStyleValue): Added.
(WI.TabBar.prototype._handleMouseUp):
(WI.TabBar.prototype._handleMouseLeave):
(WI.TabBar.prototype._handleContextMenu):
(WI.TabBar.prototype.get saveableTabCount): Deleted.
(WI.TabBar.layout.forceItemHidden): Deleted.
* UserInterface/Views/TabBar.css:
(.tab-bar):
(body:not(.docked) .tab-bar): Added.
(body.docked .tab-bar): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar): Added.
(.tab-bar > .border): Added.
(.tab-bar > .border.top): Added.
(.tab-bar > .border.bottom): Added.
(body.docked.bottom .tab-bar > .border.top): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .border): Added.
(.tab-bar > .navigation-bar): Added.
(.tab-bar > .navigation-bar > .item.group > .item): Added.
(.tab-bar > .navigation-bar > .item.group > .item:nth-child(1 of :not(.hidden))): Added.
(.tab-bar > .navigation-bar > .item.group > .item:nth-last-child(1 of :not(.hidden))): Added.
(.tab-bar > .navigation-bar .item.divider): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .navigation-bar > .item.divider): Added.
(.tab-bar > .tabs): Added.
(body.docked .tab-bar .tabs): Added.
(.tab-bar > .tabs > .item): Added.
(body:not(.docked) .tab-bar > .tabs > .item): Added.
(body:not(.docked) .tab-bar > .tabs > .item:not(.pinned)): Added.
(body.docked .tab-bar > .tabs > .item): Added.
(.tab-bar > .tabs.calculate-width > .item): Added.
(body[dir=ltr]:not(.docked) .tab-bar > .tabs > .item:not(:first-child), body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child, body[dir=ltr]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child): Added.
(body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child, body[dir=rtl]:not(.docked) .tab-bar > .tabs > .item:not(:first-child), body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child, body[dir=rtl]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected): Added.
(.tab-bar > .tabs > .item.pinned): Added.
(body.docked .tab-bar > .tabs > .item.pinned): Added.
(body:not(.docked) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(body.docked .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
(body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
(body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover, body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover): Added.
(body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item): Added.
(body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item): Added.
(body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(body.docked:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(.tab-bar > .tabs > .item > .flex-space): Added.
(.tab-bar > .tabs > .item > .icon): Added.
(.tab-bar > .tabs > .item.pinned > .icon): Added.
(.tab-bar > .tabs > .item:not(.selected):hover > .icon): Added.
(.tab-bar > .tabs > .item:not(.disabled).selected > .icon): Added.
(.tab-bar > .tabs > .item.disabled > .icon): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .icon): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .icon): Added.
(.tab-bar > .tabs > .item > .title): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .title): Added.
(.tab-bar > .tabs > .item > .title > .content): Added.
(.tab-bar > .tabs:not(.animating) > .item:not(.selected):hover > .title): Added.
(.tab-bar > .tabs > .item:not(.disabled).selected > .title): Added.
(body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .title): Added.
(.tab-bar > .tabs.static-layout): Added.
(.tab-bar > .tabs.static-layout > :matches(.flexible-space, .item)): Added.
(.tab-bar > .tabs.animating.closing-tab > .item): Added.
(.tab-bar > .tabs.animating:matches(.expanding-tabs, .inserting-tab) > .item): Added.
(.tab-bar > .tabs.animating.inserting-tab > .item.being-inserted): Added.
(body:not(.docked) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected, body:not(.docked) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)), body:not(.docked) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected): Added.
(body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected, body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)), body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected): Added.
(.tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected): Added.
(@media (prefers-color-scheme: dark) .tab-bar): Added.
(@media (prefers-color-scheme: dark) body.docked.bottom .tab-bar > .border.top): Added.
(@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs > .item): Added.
(@media (prefers-color-scheme: dark) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
(@media (prefers-color-scheme: dark) body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
(@media (prefers-color-scheme: dark) .tab-bar > .tabs > .item > .icon): Added.
(@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover > .icon): Added.
(@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive) .tab-bar): Added.
(@media (prefers-color-scheme: dark) body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item): Added.
(@media (prefers-color-scheme: dark) body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
(body.window-inactive .tab-bar): Deleted.
(.tab-bar > .top-border): Deleted.
(body.window-inactive .tab-bar > .top-border): Deleted.
(.tab-bar > .item): Deleted.
(.tab-bar.calculate-width > .item): Deleted.
(body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),): Deleted.
(body[dir=rtl] .tab-bar > :nth-child(n + 2 of .item),): Deleted.
(.tab-bar > .item.pinned): Deleted.
(.tab-bar > .item.pinned.tab-picker): Deleted.
(.tab-bar > .item:not(.disabled).selected): Deleted.
(.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover): Deleted.
(body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,): Deleted.
(body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,): Deleted.
(body.window-inactive .tab-bar > .item): Deleted.
(body[dir=ltr].window-inactive .tab-bar > .item): Deleted.
(body[dir=rtl].window-inactive .tab-bar > .item): Deleted.
(body.window-inactive .tab-bar > .item.selected): Deleted.
(.tab-bar > .item > .close): Deleted.
(body:not(.window-inactive) .tab-bar > .item:hover > .close): Deleted.
(body:not(.window-inactive) .tab-bar.single-tab > .item.default-tab:hover > .close): Deleted.
(.tab-bar.single-tab > .item.default-tab > .close): Deleted.
(.tab-bar > .item > .close:hover): Deleted.
(.tab-bar > .item > .close:active): Deleted.
(.tab-bar > .item > .flex-space): Deleted.
(.tab-bar > .item.ephemeral > .flex-space:last-child): Deleted.
(.tab-bar > .item > .icon): Deleted.
(.tab-bar > .item.pinned > .icon): Deleted.
(.tab-bar > .item.selected > .icon): Deleted.
(.tab-bar > .item.disabled > .icon): Deleted.
(@media not (prefers-color-scheme: dark) .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover > .icon): Deleted.
(.tab-bar > .item > .title): Deleted.
(.tab-bar:not(.collapsed) > .item > .title): Deleted.
(.tab-bar > .item > .title > .content): Deleted.
(.tab-bar:not(.animating) > .item:not(.selected):hover > .title): Deleted.
(.tab-bar > .item.selected > .title): Deleted.
(.tab-bar.collapsed > .item): Deleted.
(.tab-bar.collapsed > .item:not(.pinned) > .icon): Deleted.
(.tab-bar.collapsed > .item > .flex-space): Deleted.
(.tab-bar.collapsed > .item > .close): Deleted.
(.tab-bar.collapsed > .item:hover > .close): Deleted.
(.tab-bar.collapsed > .item.ephemeral:hover > .icon): Deleted.
(.tab-bar.collapsed > .item.ephemeral:hover > .title): Deleted.
(.tab-bar.static-layout): Deleted.
(.tab-bar.static-layout > .item): Deleted.
(.tab-bar.animating.closing-tab > .item): Deleted.
(.tab-bar.animating:matches(.expanding-tabs, .inserting-tab) > .item): Deleted.
(.tab-bar.animating.inserting-tab > .item.being-inserted): Deleted.
(.tab-bar.dragging-tab > .item.selected,): Deleted.
(body.window-inactive .tab-bar.dragging-tab > .item.selected,): Deleted.
(.tab-bar.dragging-tab > .item.selected): Deleted.
(@media (prefers-color-scheme: dark) .tab-bar > .item): Deleted.
(@media (prefers-color-scheme: dark) .tab-bar > .item > .title): Deleted.
(@media (prefers-color-scheme: dark) .tab-bar > .item:not(.disabled).selected): Deleted.
(@media (prefers-color-scheme: dark) .tab-bar:not(.animating) > .item:not(.selected):hover): Deleted.
(@media (prefers-color-scheme: dark) .tab-bar > .item > .close,): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive .tab-bar): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item.selected): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item > .title): Deleted.

* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype.reset):
(WI.NetworkTableContentView.prototype.tablePopulateCell):
(WI.NetworkTableContentView.prototype._changeCollection):
(WI.NetworkTableContentView.prototype.initialLayout):
(WI.NetworkTableContentView.prototype.processHAR):
(WI.NetworkTableContentView.prototype._processPendingEntries):
(WI.NetworkTableContentView.prototype._updateEntryForResource):
(WI.NetworkTableContentView.prototype._mainResourceDidChange):
(WI.NetworkTableContentView.prototype._handleResourceSizeDidChange): Added.
(WI.NetworkTableContentView.prototype._resourceTransferSizeDidChange):
(WI.NetworkTableContentView.prototype._handleResourceAdded):
(WI.NetworkTableContentView.prototype._handleFrameWasAdded):
(WI.NetworkTableContentView.prototype._entryForResource):
(WI.NetworkTableContentView.prototype._updateStatistics): Added.
(WI.NetworkTableContentView.prototype._updateStatistic): Added.
(WI.NetworkTableContentView.prototype._startUpdatingLoadTimeStatistic): Added.
(WI.NetworkTableContentView.prototype._stopUpdatingLoadTimeStatistic): Added.
(WI.NetworkTableContentView.prototype._updateLoadTimeStatistic): Added.
* UserInterface/Views/NetworkTableContentView.css:
(.content-view.network .network-table): Added.
(.network-table > .statistics): Added.
(.network-table > .statistics > .statistic): Added.
(.network-table > .statistics > .statistic[hidden]): Added.
(.network-table > .statistics > .statistic > .icon): Added.
(.network-table > .statistics > .statistic > .text): Added.
Add a fixed row below the network table that contains statistics information based on the
current shown collection (e.g. live data vs HAR):
 - number of domains
 - number of resources
 - total resource size
 - total transfer size
 - number of redirects
 - time to load
NOTE: elided renaming CSS changes.

* UserInterface/Views/TabBrowser.js:
(WI.TabBrowser.prototype.addTabForContentView):
(WI.TabBrowser.prototype.closeTabForContentView):
(WI.TabBrowser.prototype._tabBarItemSelected):
(WI.TabBrowser.prototype._tabBarItemRemoved):

* UserInterface/Views/TabContentView.js:
(WI.TabContentView.shouldPinTab): Added.
* UserInterface/Views/AuditTabContentView.js:
(WI.AuditTabContentView):
(WI.AuditTabContentView.tabInfo):
* UserInterface/Views/CanvasTabContentView.js:
(WI.CanvasTabContentView):
(WI.CanvasTabContentView.tabInfo):
* UserInterface/Views/ConsoleTabContentView.js:
(WI.ConsoleTabContentView):
(WI.ConsoleTabContentView.tabInfo):
* UserInterface/Views/ContentBrowserTabContentView.js:
(WI.ContentBrowserTabContentView):
* UserInterface/Views/ElementsTabContentView.js:
(WI.ElementsTabContentView):
(WI.ElementsTabContentView.tabInfo):
* UserInterface/Views/LayersTabContentView.js:
(WI.LayersTabContentView):
(WI.LayersTabContentView.tabInfo):
* UserInterface/Views/NetworkTabContentView.js:
(WI.NetworkTabContentView):
(WI.NetworkTabContentView.tabInfo):
* UserInterface/Views/SearchTabContentView.js:
(WI.SearchTabContentView):
(WI.SearchTabContentView.tabInfo):
(WI.SearchTabContentView.shouldPinTab): Added.
(WI.SearchTabContentView.shouldSaveTab): Added.
* UserInterface/Views/SettingsTabContentView.js:
(WI.SettingsTabContentView):
(WI.SettingsTabContentView.tabInfo):
(WI.SettingsTabContentView.shouldPinTab): Added.
(WI.SettingsTabContentView.prototype._createExperimentalSettingsView):
* UserInterface/Views/SourcesTabContentView.js:
(WI.SourcesTabContentView):
(WI.SourcesTabContentView.tabInfo):
(WI.SourcesTabContentView.prototype._handleDebuggerPaused): Added.
(WI.SourcesTabContentView.prototype._handleDebuggerResumed): Added.
* UserInterface/Views/StorageTabContentView.js:
(WI.StorageTabContentView):
(WI.StorageTabContentView.tabInfo):
* UserInterface/Views/TimelineTabContentView.js:
(WI.TimelineTabContentView):
(WI.TimelineTabContentView.tabInfo):
* UserInterface/Views/TabBarItem.js:
(WI.TabBarItem):
(WI.TabBarItem.get horizontalMargin): Added.
(WI.TabBarItem.prototype.get element):
(WI.TabBarItem.prototype.get representedObject):
(WI.TabBarItem.prototype.set disabled):
(WI.TabBarItem.prototype.get hidden): Added.
(WI.TabBarItem.prototype.set hidden): Added.
(WI.TabBarItem.prototype.set representedObject): Deleted.
(WI.TabBarItem.prototype.get isDefaultTab): Deleted.
(WI.TabBarItem.prototype.set isDefaultTab): Deleted.
* UserInterface/Views/GeneralTabBarItem.js:
(WI.GeneralTabBarItem.fromTabContentView): Added.
(WI.GeneralTabBarItem): Deleted.
(WI.GeneralTabBarItem.fromTabInfo): Deleted.
(WI.GeneralTabBarItem.prototype.get isEphemeral): Deleted.
(WI.GeneralTabBarItem.prototype._handleContextMenuEvent): Deleted.
* UserInterface/Views/PinnedTabBarItem.js:
(WI.PinnedTabBarItem):
(WI.PinnedTabBarItem.fromTabContentView): Added.
(WI.PinnedTabBarItem.titleDidChange):
(WI.PinnedTabBarItem.fromTabInfo): Deleted.
(WI.PinnedTabBarItem.prototype.titleDidChange): Deleted.
(WI.PinnedTabBarItem.prototype._handleContextMenuEvent): Deleted.
Simplify how tab bar items are created.

* UserInterface/Views/NavigationBar.js:
(WI.NavigationBar.prototype.get sizesToFit):
(WI.NavigationBar.prototype.addNavigationItem):
(WI.NavigationBar.prototype.insertNavigationItem):
* UserInterface/Views/SizesToFitNavigationBar.js: Removed.
* UserInterface/Views/Sidebar.js:
(WI.Sidebar):
* UserInterface/Views/GraphicsOverviewContentView.js:
(WI.GraphicsOverviewContentView.prototype.initialLayout):
Support marking `sizesToFit` during construction, instead of having to make a subclass.

* UserInterface/Views/ButtonNavigationItem.js:
(WI.ButtonNavigationItem):
(WI.ButtonNavigationItem.prototype.get imageType): Added.
(WI.ButtonNavigationItem.prototype.set imageType): Added.
(WI.ButtonNavigationItem.prototype._update):
* UserInterface/Views/ButtonNavigationItem.css:
(.tab-bar > .navigation-bar .item.button.image-and-text > span): Added.
(.navigation-bar .item.button > img): Added.
(.navigation-bar .item.button.disabled > img): Added.
(body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button > img): Added.
(body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button.disabled > img): Added.
(@media (prefers-color-scheme: dark) .navigation-bar .item.button.disabled > img): Added.
Allow `WI.ButtonNavigationItem` to use an `<img>` instead of an `<svg>` for it's image. This
is to work around a compositing bug <https://webkit.org/b/207022>.

* UserInterface/Views/GroupNavigationItem.js:
(WI.GroupNavigationItem.prototype.get hidden): Added.
(WI.GroupNavigationItem.prototype.set hidden): Added.
(WI.GroupNavigationItem.prototype.get additionalClassNames): Added.
Add a special case where this item is considered `hidden` if all sub-items are also `hidden`.

* UserInterface/Views/Variables.css:
(:root):
(body:matches(.window-inactive, .window-docked-inactive)): Added.
(body:matches(.window-inactive, .window-docked-inactive) *): Added.
(body:not(.docked)): Added.
(@media (prefers-color-scheme: dark) :root):
(@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive)): Added.
(@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive) *): Added.
(body.window-inactive): Deleted.
(body.window-inactive *): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive): Deleted.
(@media (prefers-color-scheme: dark) body.window-inactive *): Deleted.
Replace `--toolbar-height` with `--undocked-title-area-height`, which is set when docked.
Define `--tab-bar-height` in terms of `--navigation-bar-height` so they share the same value.

* UserInterface/Views/DividerNavigationItem.css:
(.navigation-bar .item.divider):
(@media (prefers-color-scheme: dark)):
Simplify the CSS in order to better support being used in the tab bar.

* UserInterface/Views/FlexibleSpaceNavigationItem.css:
(.navigation-bar .item.flexible-space):
(.navigation-bar .item.flexible-space.align-start > .item):
(.navigation-bar .item.flexible-space.align-end > .item):
(:matches(.navigation-bar, .toolbar) .item.flexible-space): Deleted.
(:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item): Deleted.
(:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item): Deleted.
Remove toolbar styles.

* UserInterface/Controllers/ConsoleManager.js:
(WI.ConsoleManager):
(WI.ConsoleManager.prototype.get warningCount): Added.
(WI.ConsoleManager.prototype.get errorCount): Added.
(WI.ConsoleManager.prototype.messageWasAdded):
(WI.ConsoleManager.prototype.messagesCleared):
(WI.ConsoleManager.prototype.messageRepeatCountUpdated):
(WI.ConsoleManager.prototype._incrementMessageLevelCount): Added.
(WI.ConsoleManager.prototype._delayedMessagesCleared):
Keep track of the count of warnings and errors so that they can be used to determine when to
show Console button navigation items in the tab bar.

* UserInterface/Views/DOMTreeContentView.css:
(body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint): Added.
(body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree): Added.
(body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint): Deleted.
(body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree): Deleted.
* UserInterface/Views/RenderingFrameTimelineOverviewGraph.css:
(body:matches(.window-inactive, .window-docked-inactive) .timeline-overview-graph.rendering-frame > .frame-marker): Added.
(body.window-inactive .timeline-overview-graph.rendering-frame > .frame-marker): Deleted.
* UserInterface/Views/TimelineOverview.css:
(.timeline-overview > .tree-outline.timelines .item.selected + .item, body:matches(.window-inactive, .window-docked-inactive) .timeline-overview > .tree-outline.timelines .item.selected + .item): Added.
(@media (prefers-color-scheme: dark) .timeline-overview > .tree-outline.timelines .item.selected + .item, body:matches(.window-inactive, .window-docked-inactive) .timeline-overview > .tree-outline.timelines .item.selected + .item): Added.
(.timeline-overview > .tree-outline.timelines .item.selected + .item, body.window-inactive .timeline-overview > .tree-outline.timelines .item.selected + .item): Deleted.
(@media (prefers-color-scheme: dark) .timeline-overview > .tree-outline.timelines .item.selected + .item, body.window-inactive .timeline-overview > .tree-outline.timelines .item.selected + .item): Deleted.
* UserInterface/Views/TimelineRecordFrame.css:
(body:matches(.window-inactive, .window-docked-inactive) .timeline-record-frame.selected): Added.
(body.window-inactive .timeline-record-frame.selected): Deleted.
* UserInterface/Views/TimelineRuler.css:
(body:matches(.window-inactive, .window-docked-inactive) .timeline-ruler > .header > .divider): Added.
(body.window-inactive .timeline-ruler > .header > .divider): Deleted.
Add selectors for `.window-docked-inactive` everywhere that `.window-inactive` exists.

* UserInterface/Base/Setting.js:
Remove new tab bar experimental setting.

* UserInterface/Debug/Bootstrap.js:
(WI.runBootstrapOperations):
(WI.runBootstrapOperations.applyDumpMessagesState):
(WI.runBootstrapOperations.updateDebugUI):

* UserInterface/Main.html:
* Localizations/en.lproj/localizedStrings.js:

* UserInterface/Views/ActivateButtonToolbarItem.js: Removed.
* UserInterface/Views/ButtonToolbarItem.js: Removed.
* UserInterface/Views/ButtonToolbarItem.css: Removed.
* UserInterface/Views/ControlToolbarItem.js: Removed.
* UserInterface/Views/ControlToolbarItem.css: Removed.
* UserInterface/Views/Toolbar.js: Removed.
* UserInterface/Views/Toolbar.css: Removed.
Remove toolbar related code now that it has been merged into the tab bar.

* UserInterface/Models/DebuggerDashboard.js: Removed.
* UserInterface/Models/DefaultDashboard.js: Removed.
* UserInterface/Views/DashboardContainerView.js: Removed.
* UserInterface/Views/DashboardContainerView.css: Removed.
* UserInterface/Views/DashboardView.js: Removed.
* UserInterface/Views/DebuggerDashboardView.js: Removed.
* UserInterface/Views/DebuggerDashboardView.css: Removed.
* UserInterface/Views/DefaultDashboardView.js: Removed.
* UserInterface/Views/DefaultDashboardView.css: Removed.
Remove dashboard related code now that it has been merged into the tab bar.

* UserInterface/Views/LegacyTabBar.js: Removed.
* UserInterface/Views/NewTabContentView.js: Removed.
* UserInterface/Views/NewTabContentView.css: Removed.
* UserInterface/Images/NewTab.svg: Removed.
* UserInterface/Images/NewTabPlus.svg: Removed.
* UserInterface/Images/SearchResults.svg: Removed.
Remove the lebacy tab bar in favor of the new tab bar.

Source/WebKit:

Now that there is no toolbar area, there is nothing obstructing the ability for the window
to be moved around when dragging via the title bar area. As such, we can remove the unused
`InspectorFrontendHost` APIs.

* WebProcess/Inspector/WebInspectorUI.h:
* WebProcess/Inspector/WebInspectorUI.cpp:
(WebKit::WebInspectorUI::startWindowDrag): Deleted.
(WebKit::WebInspectorUI::moveWindowBy): Deleted.
* UIProcess/Inspector/WebInspectorProxy.messages.in:
* UIProcess/Inspector/WebInspectorProxy.h:
* UIProcess/Inspector/WebInspectorProxy.cpp:
(WebKit::WebInspectorProxy::startWindowDrag): Deleted.
(WebKit::WebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp:
(WebKit::WebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/mac/WebInspectorProxyMac.mm:
(WebKit::WebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/win/WebInspectorProxyWin.cpp:
(WebKit::WebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/wpe/WebInspectorProxyWPE.cpp:
(WebKit::WebInspectorProxy::platformStartWindowDrag): Deleted.

* WebProcess/Inspector/RemoteWebInspectorUI.h:
* WebProcess/Inspector/RemoteWebInspectorUI.cpp:
(WebKit::RemoteWebInspectorUI::startWindowDrag): Deleted.
(WebKit::RemoteWebInspectorUI::moveWindowBy): Deleted.
* UIProcess/Inspector/RemoteWebInspectorProxy.messages.in:
* UIProcess/Inspector/RemoteWebInspectorProxy.cpp:
* UIProcess/Inspector/RemoteWebInspectorProxy.h:
(WebKit::RemoteWebInspectorProxy::startWindowDrag): Deleted.
(WebKit::RemoteWebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/gtk/RemoteWebInspectorProxyGtk.cpp:
(WebKit::RemoteWebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/mac/RemoteWebInspectorProxyMac.mm:
(WebKit::RemoteWebInspectorProxy::platformStartWindowDrag): Deleted.
* UIProcess/Inspector/win/RemoteWebInspectorProxyWin.cpp:
(WebKit::RemoteWebInspectorProxy::platformStartWindowDrag): Deleted.

Source/WebKitLegacy/ios:

Now that there is no toolbar area, there is nothing obstructing the ability for the window
to be moved around when dragging via the title bar area. As such, we can remove the unused
`InspectorFrontendHost` APIs.

* WebCoreSupport/WebInspectorClientIOS.mm:
(WebInspectorFrontendClient::startWindowDrag): Deleted.

Source/WebKitLegacy/mac:

Now that there is no toolbar area, there is nothing obstructing the ability for the window
to be moved around when dragging via the title bar area. As such, we can remove the unused
`InspectorFrontendHost` APIs.

* WebCoreSupport/WebInspectorClient.h:
* WebCoreSupport/WebInspectorClient.mm:
(WebInspectorFrontendClient::startWindowDrag): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@257759 268f45cc-cd09-0410-ab3c-d52691b4dbfc

98 files changed:
Source/WebCore/ChangeLog
Source/WebCore/inspector/InspectorFrontendClient.h
Source/WebCore/inspector/InspectorFrontendClientLocal.cpp
Source/WebCore/inspector/InspectorFrontendClientLocal.h
Source/WebCore/inspector/InspectorFrontendHost.cpp
Source/WebCore/inspector/InspectorFrontendHost.h
Source/WebCore/inspector/InspectorFrontendHost.idl
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Base/Main.js
Source/WebInspectorUI/UserInterface/Base/Setting.js
Source/WebInspectorUI/UserInterface/Controllers/ConsoleManager.js
Source/WebInspectorUI/UserInterface/Debug/Bootstrap.js
Source/WebInspectorUI/UserInterface/Images/NewTab.svg [deleted file]
Source/WebInspectorUI/UserInterface/Images/NewTabPlus.svg [deleted file]
Source/WebInspectorUI/UserInterface/Images/SearchResults.svg [deleted file]
Source/WebInspectorUI/UserInterface/Images/SourcesPaused.svg [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/DebuggerDashboard.js [deleted file]
Source/WebInspectorUI/UserInterface/Models/DefaultDashboard.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/ActivateButtonToolbarItem.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/AuditTabContentView.js
Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css
Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.js
Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/ConsoleTabContentView.js
Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js
Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.css
Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/DashboardView.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/DividerNavigationItem.css
Source/WebInspectorUI/UserInterface/Views/ElementsTabContentView.js
Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.css
Source/WebInspectorUI/UserInterface/Views/GeneralTabBarItem.js
Source/WebInspectorUI/UserInterface/Views/GraphicsOverviewContentView.js
Source/WebInspectorUI/UserInterface/Views/GraphicsTabContentView.js
Source/WebInspectorUI/UserInterface/Views/GroupNavigationItem.js
Source/WebInspectorUI/UserInterface/Views/LayersTabContentView.js
Source/WebInspectorUI/UserInterface/Views/LegacyTabBar.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/Main.css
Source/WebInspectorUI/UserInterface/Views/NavigationBar.js
Source/WebInspectorUI/UserInterface/Views/NetworkDetailView.css
Source/WebInspectorUI/UserInterface/Views/NetworkTabContentView.js
Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css
Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js
Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/PinnedTabBarItem.js
Source/WebInspectorUI/UserInterface/Views/QuickConsole.js
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.css
Source/WebInspectorUI/UserInterface/Views/SearchTabContentView.js
Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js
Source/WebInspectorUI/UserInterface/Views/Sidebar.js
Source/WebInspectorUI/UserInterface/Views/SizesToFitNavigationBar.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/SourcesTabContentView.js
Source/WebInspectorUI/UserInterface/Views/StorageTabContentView.js
Source/WebInspectorUI/UserInterface/Views/TabBar.css
Source/WebInspectorUI/UserInterface/Views/TabBar.js
Source/WebInspectorUI/UserInterface/Views/TabBarItem.js
Source/WebInspectorUI/UserInterface/Views/TabBrowser.js
Source/WebInspectorUI/UserInterface/Views/TabContentView.js
Source/WebInspectorUI/UserInterface/Views/TimelineOverview.css
Source/WebInspectorUI/UserInterface/Views/TimelineRecordFrame.css
Source/WebInspectorUI/UserInterface/Views/TimelineRuler.css
Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js
Source/WebInspectorUI/UserInterface/Views/Toolbar.css [deleted file]
Source/WebInspectorUI/UserInterface/Views/Toolbar.js [deleted file]
Source/WebInspectorUI/UserInterface/Views/Variables.css
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Inspector/RemoteWebInspectorProxy.cpp
Source/WebKit/UIProcess/Inspector/RemoteWebInspectorProxy.h
Source/WebKit/UIProcess/Inspector/RemoteWebInspectorProxy.messages.in
Source/WebKit/UIProcess/Inspector/WebInspectorProxy.cpp
Source/WebKit/UIProcess/Inspector/WebInspectorProxy.h
Source/WebKit/UIProcess/Inspector/WebInspectorProxy.messages.in
Source/WebKit/UIProcess/Inspector/gtk/RemoteWebInspectorProxyGtk.cpp
Source/WebKit/UIProcess/Inspector/gtk/WebInspectorProxyGtk.cpp
Source/WebKit/UIProcess/Inspector/mac/RemoteWebInspectorProxyMac.mm
Source/WebKit/UIProcess/Inspector/mac/WebInspectorProxyMac.mm
Source/WebKit/UIProcess/Inspector/win/RemoteWebInspectorProxyWin.cpp
Source/WebKit/UIProcess/Inspector/win/WebInspectorProxyWin.cpp
Source/WebKit/WebProcess/Inspector/RemoteWebInspectorUI.cpp
Source/WebKit/WebProcess/Inspector/RemoteWebInspectorUI.h
Source/WebKit/WebProcess/Inspector/WebInspectorUI.cpp
Source/WebKit/WebProcess/Inspector/WebInspectorUI.h
Source/WebKitLegacy/ios/ChangeLog
Source/WebKitLegacy/ios/WebCoreSupport/WebInspectorClientIOS.mm
Source/WebKitLegacy/mac/ChangeLog
Source/WebKitLegacy/mac/WebCoreSupport/WebInspectorClient.h
Source/WebKitLegacy/mac/WebCoreSupport/WebInspectorClient.mm

index c4a2a39..130f4d3 100644 (file)
@@ -1,5 +1,28 @@
 2020-03-02  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: Items in the toolbar take up to much vertical space
+        https://bugs.webkit.org/show_bug.cgi?id=204627
+        <rdar://problem/59091905>
+
+        Reviewed by Timothy Hatcher.
+
+        Now that there is no toolbar area, there is nothing obstructing the ability for the window
+        to be moved around when dragging via the title bar area. As such, we can remove the unused
+        `InspectorFrontendHost` APIs.
+
+        * inspector/InspectorFrontendHost.idl:
+        * inspector/InspectorFrontendHost.h:
+        * inspector/InspectorFrontendHost.cpp:
+        (WebCore::InspectorFrontendHost::startWindowDrag): Deleted.
+        (WebCore::InspectorFrontendHost::moveWindowBy const): Deleted.
+
+        * inspector/InspectorFrontendClient.h:
+        * inspector/InspectorFrontendClientLocal.h:
+        * inspector/InspectorFrontendClientLocal.cpp:
+        (WebCore::InspectorFrontendClientLocal::moveWindowBy): Deleted.
+
+2020-03-02  Devin Rousso  <drousso@apple.com>
+
         Remove the required `LockHolder` when calling `WebAnimation::instances()`
         https://bugs.webkit.org/show_bug.cgi?id=208493
 
index 137d0e6..6e477e9 100644 (file)
@@ -55,9 +55,6 @@ public:
     WEBCORE_EXPORT virtual void windowObjectCleared() = 0;
     virtual void frontendLoaded() = 0;
 
-    virtual void startWindowDrag() = 0;
-    virtual void moveWindowBy(float x, float y) = 0;
-
     // Information about the debuggable.
     virtual bool isRemote() const = 0;
     virtual String localizedStringsURL() const = 0;
index f2685fc..75c0688 100644 (file)
@@ -270,13 +270,6 @@ void InspectorFrontendClientLocal::openInNewTab(const String& url)
     frame->loader().changeLocation(WTFMove(frameLoadRequest2));
 }
 
-void InspectorFrontendClientLocal::moveWindowBy(float x, float y)
-{
-    FloatRect frameRect = m_frontendPage->chrome().windowRect();
-    frameRect.move(x, y);
-    m_frontendPage->chrome().setWindowRect(frameRect);
-}
-
 void InspectorFrontendClientLocal::setAttachedWindow(DockSide dockSide)
 {
     const char* side = "undocked";
index 0ec320d..055df42 100644 (file)
@@ -67,9 +67,6 @@ public:
     WEBCORE_EXPORT void windowObjectCleared() final;
     WEBCORE_EXPORT void frontendLoaded() override;
 
-    void startWindowDrag() override { }
-    WEBCORE_EXPORT void moveWindowBy(float x, float y) final;
-
     WEBCORE_EXPORT UserInterfaceLayoutDirection userInterfaceLayoutDirection() const final;
 
     WEBCORE_EXPORT void requestSetDockSide(DockSide) final;
index 93c1b57..1d6d9cc 100644 (file)
@@ -271,18 +271,6 @@ void InspectorFrontendHost::setSheetRect(float x, float y, unsigned width, unsig
         m_client->changeSheetRect(FloatRect(x, y, width, height));
 }
 
-void InspectorFrontendHost::startWindowDrag()
-{
-    if (m_client)
-        m_client->startWindowDrag();
-}
-
-void InspectorFrontendHost::moveWindowBy(float x, float y) const
-{
-    if (m_client)
-        m_client->moveWindowBy(x, y);
-}
-
 bool InspectorFrontendHost::isRemote() const
 {
     return m_client && m_client->isRemote();
index 51fa505..7a65ed1 100644 (file)
@@ -79,9 +79,6 @@ public:
 
     void setSheetRect(float x, float y, unsigned width, unsigned height);
 
-    void startWindowDrag();
-    void moveWindowBy(float x, float y) const;
-
     bool isRemote() const;
     String localizedStringsURL() const;
     String backendCommandsURL() const;
index d5a9e1e..3db0e7f 100644 (file)
@@ -59,9 +59,6 @@
 
     void setSheetRect(unrestricted float x, unrestricted float y, unsigned long width, unsigned long height);
 
-    void startWindowDrag();
-    void moveWindowBy(unrestricted float x, unrestricted float y);
-
     readonly attribute boolean isRemote;
     readonly attribute DOMString localizedStringsURL;
     readonly attribute DOMString backendCommandsURL;
index 4e0141e..fa4dc3e 100644 (file)
@@ -1,3 +1,454 @@
+2020-03-02  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: Items in the toolbar take up to much vertical space
+        https://bugs.webkit.org/show_bug.cgi?id=204627
+        <rdar://problem/59091905>
+
+        Reviewed by Timothy Hatcher.
+
+        Merge the toolbar are and tab bar to waste less vertical space.
+
+        Existing toolbar buttons have been moved to a space before the tab bar, and are only shown
+        when needed (e.g. only show the reload button when remotely inspecting).
+
+        If there are any console warnings/errors, an icon for each type of message is shown between
+        the left buttons and the tabs, and each button's opacity is animated whenever a new message
+        is added.
+
+        Whenever the debugger pauses, change the tab bar icon of the Sources Tab to an image that
+        includes paused iconography to help convey the debugger's state no matter which tab is
+        currently selected, just like the debugger dashboard.
+
+        The dashboard network information has been moved to the Network Tab (described below).
+
+        When undocked, the tab bar and all the content below it are pushed down by 22px to make room
+        for the system close/minimize/maximize buttons and the window title.
+
+        * UserInterface/Base/Main.js:
+        (WI.loaded):
+        (WI._handleSettingsKeyboardShortcut):
+        (WI._tryToRestorePendingTabs):
+        (WI.isNewTabWithTypeAllowed):
+        (WI._openDefaultTab): Deleted.
+        (WI.showNewTabTab): Deleted.
+        * UserInterface/Views/Main.css:
+        (#undocked-title-area): Added.
+        (body.docked #undocked-title-area): Added.
+        (body.window-inactive #undocked-title-area): Added.
+        (#main):
+        (@keyframes tab-bar-console-item-pulse): Added.
+        (.tab-bar > .navigation-bar :matches(.console-warnings, .console-errors):not(.disabled).pulsing): Added.
+        (@media (prefers-color-scheme: dark) #undocked-title-area): Added.
+        (@media (prefers-color-scheme: dark) body.window-inactive #undocked-title-area): Added.
+        (body.docked.bottom): Deleted.
+        (body.docked.bottom #toolbar): Deleted.
+        (body.docked.bottom #toolbar .item:not(.flexible-space)): Deleted.
+
+        * UserInterface/Views/TabBar.js:
+        (WI.TabBar):
+        (WI.TabBar.get horizontalPadding): Added.
+        (WI.TabBar.prototype.addNavigationItemBefore): Added.
+        (WI.TabBar.prototype.addNavigationItemAfter): Added.
+        (WI.TabBar.prototype.insertTabBarItem):
+        (WI.TabBar.prototype.insertTabBarItem.animateTabs):
+        (WI.TabBar.prototype.insertTabBarItem.removeStyles):
+        (WI.TabBar.prototype.removeTabBarItem):
+        (WI.TabBar.prototype.removeTabBarItem.animateTabs):
+        (WI.TabBar.prototype.removeTabBarItem.removeStyles):
+        (WI.TabBar.prototype.set selectedTabBarItem):
+        (WI.TabBar.prototype.get tabCount): Added.
+        (WI.TabBar.prototype.layout):
+        (WI.TabBar.prototype.layout.measureItemWidth):
+        (WI.TabBar.prototype.layout.recalculateItemWidths):
+        (WI.TabBar.prototype.didLayoutSubtree): Added.
+        (WI.TabBar.prototype._recordTabBarItemSizesAndPositions):
+        (WI.TabBar.prototype._recordTabBarItemSizesAndPositions.add): Added.
+        (WI.TabBar.prototype._applyTabBarItemSizesAndPositions):
+        (WI.TabBar.prototype._finishExpandingTabsAfterClose):
+        (WI.TabBar.prototype._finishExpandingTabsAfterClose.animateTabs):
+        (WI.TabBar.prototype._finishExpandingTabsAfterClose.removeStyles):
+        (WI.TabBar.prototype._handleClick):
+        (WI.TabBar.prototype._handleMouseMoved):
+        (WI.TabBar.prototype._handleMouseMoved.inlineStyleValue): Added.
+        (WI.TabBar.prototype._handleMouseUp):
+        (WI.TabBar.prototype._handleMouseLeave):
+        (WI.TabBar.prototype._handleContextMenu):
+        (WI.TabBar.prototype.get saveableTabCount): Deleted.
+        (WI.TabBar.layout.forceItemHidden): Deleted.
+        * UserInterface/Views/TabBar.css:
+        (.tab-bar):
+        (body:not(.docked) .tab-bar): Added.
+        (body.docked .tab-bar): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar): Added.
+        (.tab-bar > .border): Added.
+        (.tab-bar > .border.top): Added.
+        (.tab-bar > .border.bottom): Added.
+        (body.docked.bottom .tab-bar > .border.top): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .border): Added.
+        (.tab-bar > .navigation-bar): Added.
+        (.tab-bar > .navigation-bar > .item.group > .item): Added.
+        (.tab-bar > .navigation-bar > .item.group > .item:nth-child(1 of :not(.hidden))): Added.
+        (.tab-bar > .navigation-bar > .item.group > .item:nth-last-child(1 of :not(.hidden))): Added.
+        (.tab-bar > .navigation-bar .item.divider): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .navigation-bar > .item.divider): Added.
+        (.tab-bar > .tabs): Added.
+        (body.docked .tab-bar .tabs): Added.
+        (.tab-bar > .tabs > .item): Added.
+        (body:not(.docked) .tab-bar > .tabs > .item): Added.
+        (body:not(.docked) .tab-bar > .tabs > .item:not(.pinned)): Added.
+        (body.docked .tab-bar > .tabs > .item): Added.
+        (.tab-bar > .tabs.calculate-width > .item): Added.
+        (body[dir=ltr]:not(.docked) .tab-bar > .tabs > .item:not(:first-child), body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child, body[dir=ltr]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child): Added.
+        (body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child, body[dir=rtl]:not(.docked) .tab-bar > .tabs > .item:not(:first-child), body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child, body[dir=rtl]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected): Added.
+        (.tab-bar > .tabs > .item.pinned): Added.
+        (body.docked .tab-bar > .tabs > .item.pinned): Added.
+        (body:not(.docked) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (body.docked .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
+        (body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
+        (body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover, body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover): Added.
+        (body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover, body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item): Added.
+        (body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item): Added.
+        (body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (body.docked:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (.tab-bar > .tabs > .item > .flex-space): Added.
+        (.tab-bar > .tabs > .item > .icon): Added.
+        (.tab-bar > .tabs > .item.pinned > .icon): Added.
+        (.tab-bar > .tabs > .item:not(.selected):hover > .icon): Added.
+        (.tab-bar > .tabs > .item:not(.disabled).selected > .icon): Added.
+        (.tab-bar > .tabs > .item.disabled > .icon): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .icon): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .icon): Added.
+        (.tab-bar > .tabs > .item > .title): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .title): Added.
+        (.tab-bar > .tabs > .item > .title > .content): Added.
+        (.tab-bar > .tabs:not(.animating) > .item:not(.selected):hover > .title): Added.
+        (.tab-bar > .tabs > .item:not(.disabled).selected > .title): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .title): Added.
+        (.tab-bar > .tabs.static-layout): Added.
+        (.tab-bar > .tabs.static-layout > :matches(.flexible-space, .item)): Added.
+        (.tab-bar > .tabs.animating.closing-tab > .item): Added.
+        (.tab-bar > .tabs.animating:matches(.expanding-tabs, .inserting-tab) > .item): Added.
+        (.tab-bar > .tabs.animating.inserting-tab > .item.being-inserted): Added.
+        (body:not(.docked) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected, body:not(.docked) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)), body:not(.docked) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected): Added.
+        (body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected, body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)), body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected): Added.
+        (.tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected): Added.
+        (@media (prefers-color-scheme: dark) .tab-bar): Added.
+        (@media (prefers-color-scheme: dark) body.docked.bottom .tab-bar > .border.top): Added.
+        (@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs > .item): Added.
+        (@media (prefers-color-scheme: dark) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
+        (@media (prefers-color-scheme: dark) body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover): Added.
+        (@media (prefers-color-scheme: dark) .tab-bar > .tabs > .item > .icon): Added.
+        (@media (prefers-color-scheme: dark) body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover > .icon): Added.
+        (@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive) .tab-bar): Added.
+        (@media (prefers-color-scheme: dark) body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item): Added.
+        (@media (prefers-color-scheme: dark) body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected): Added.
+        (body.window-inactive .tab-bar): Deleted.
+        (.tab-bar > .top-border): Deleted.
+        (body.window-inactive .tab-bar > .top-border): Deleted.
+        (.tab-bar > .item): Deleted.
+        (.tab-bar.calculate-width > .item): Deleted.
+        (body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),): Deleted.
+        (body[dir=rtl] .tab-bar > :nth-child(n + 2 of .item),): Deleted.
+        (.tab-bar > .item.pinned): Deleted.
+        (.tab-bar > .item.pinned.tab-picker): Deleted.
+        (.tab-bar > .item:not(.disabled).selected): Deleted.
+        (.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover): Deleted.
+        (body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,): Deleted.
+        (body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,): Deleted.
+        (body.window-inactive .tab-bar > .item): Deleted.
+        (body[dir=ltr].window-inactive .tab-bar > .item): Deleted.
+        (body[dir=rtl].window-inactive .tab-bar > .item): Deleted.
+        (body.window-inactive .tab-bar > .item.selected): Deleted.
+        (.tab-bar > .item > .close): Deleted.
+        (body:not(.window-inactive) .tab-bar > .item:hover > .close): Deleted.
+        (body:not(.window-inactive) .tab-bar.single-tab > .item.default-tab:hover > .close): Deleted.
+        (.tab-bar.single-tab > .item.default-tab > .close): Deleted.
+        (.tab-bar > .item > .close:hover): Deleted.
+        (.tab-bar > .item > .close:active): Deleted.
+        (.tab-bar > .item > .flex-space): Deleted.
+        (.tab-bar > .item.ephemeral > .flex-space:last-child): Deleted.
+        (.tab-bar > .item > .icon): Deleted.
+        (.tab-bar > .item.pinned > .icon): Deleted.
+        (.tab-bar > .item.selected > .icon): Deleted.
+        (.tab-bar > .item.disabled > .icon): Deleted.
+        (@media not (prefers-color-scheme: dark) .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover > .icon): Deleted.
+        (.tab-bar > .item > .title): Deleted.
+        (.tab-bar:not(.collapsed) > .item > .title): Deleted.
+        (.tab-bar > .item > .title > .content): Deleted.
+        (.tab-bar:not(.animating) > .item:not(.selected):hover > .title): Deleted.
+        (.tab-bar > .item.selected > .title): Deleted.
+        (.tab-bar.collapsed > .item): Deleted.
+        (.tab-bar.collapsed > .item:not(.pinned) > .icon): Deleted.
+        (.tab-bar.collapsed > .item > .flex-space): Deleted.
+        (.tab-bar.collapsed > .item > .close): Deleted.
+        (.tab-bar.collapsed > .item:hover > .close): Deleted.
+        (.tab-bar.collapsed > .item.ephemeral:hover > .icon): Deleted.
+        (.tab-bar.collapsed > .item.ephemeral:hover > .title): Deleted.
+        (.tab-bar.static-layout): Deleted.
+        (.tab-bar.static-layout > .item): Deleted.
+        (.tab-bar.animating.closing-tab > .item): Deleted.
+        (.tab-bar.animating:matches(.expanding-tabs, .inserting-tab) > .item): Deleted.
+        (.tab-bar.animating.inserting-tab > .item.being-inserted): Deleted.
+        (.tab-bar.dragging-tab > .item.selected,): Deleted.
+        (body.window-inactive .tab-bar.dragging-tab > .item.selected,): Deleted.
+        (.tab-bar.dragging-tab > .item.selected): Deleted.
+        (@media (prefers-color-scheme: dark) .tab-bar > .item): Deleted.
+        (@media (prefers-color-scheme: dark) .tab-bar > .item > .title): Deleted.
+        (@media (prefers-color-scheme: dark) .tab-bar > .item:not(.disabled).selected): Deleted.
+        (@media (prefers-color-scheme: dark) .tab-bar:not(.animating) > .item:not(.selected):hover): Deleted.
+        (@media (prefers-color-scheme: dark) .tab-bar > .item > .close,): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive .tab-bar): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item.selected): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive .tab-bar > .item > .title): Deleted.
+
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView):
+        (WI.NetworkTableContentView.prototype.reset):
+        (WI.NetworkTableContentView.prototype.tablePopulateCell):
+        (WI.NetworkTableContentView.prototype._changeCollection):
+        (WI.NetworkTableContentView.prototype.initialLayout):
+        (WI.NetworkTableContentView.prototype.processHAR):
+        (WI.NetworkTableContentView.prototype._processPendingEntries):
+        (WI.NetworkTableContentView.prototype._updateEntryForResource):
+        (WI.NetworkTableContentView.prototype._mainResourceDidChange):
+        (WI.NetworkTableContentView.prototype._handleResourceSizeDidChange): Added.
+        (WI.NetworkTableContentView.prototype._resourceTransferSizeDidChange):
+        (WI.NetworkTableContentView.prototype._handleResourceAdded):
+        (WI.NetworkTableContentView.prototype._handleFrameWasAdded):
+        (WI.NetworkTableContentView.prototype._entryForResource):
+        (WI.NetworkTableContentView.prototype._updateStatistics): Added.
+        (WI.NetworkTableContentView.prototype._updateStatistic): Added.
+        (WI.NetworkTableContentView.prototype._startUpdatingLoadTimeStatistic): Added.
+        (WI.NetworkTableContentView.prototype._stopUpdatingLoadTimeStatistic): Added.
+        (WI.NetworkTableContentView.prototype._updateLoadTimeStatistic): Added.
+        * UserInterface/Views/NetworkTableContentView.css:
+        (.content-view.network .network-table): Added.
+        (.network-table > .statistics): Added.
+        (.network-table > .statistics > .statistic): Added.
+        (.network-table > .statistics > .statistic[hidden]): Added.
+        (.network-table > .statistics > .statistic > .icon): Added.
+        (.network-table > .statistics > .statistic > .text): Added.
+        Add a fixed row below the network table that contains statistics information based on the
+        current shown collection (e.g. live data vs HAR):
+         - number of domains
+         - number of resources
+         - total resource size
+         - total transfer size
+         - number of redirects
+         - time to load
+        NOTE: elided renaming CSS changes.
+
+        * UserInterface/Views/TabBrowser.js:
+        (WI.TabBrowser.prototype.addTabForContentView):
+        (WI.TabBrowser.prototype.closeTabForContentView):
+        (WI.TabBrowser.prototype._tabBarItemSelected):
+        (WI.TabBrowser.prototype._tabBarItemRemoved):
+
+        * UserInterface/Views/TabContentView.js:
+        (WI.TabContentView.shouldPinTab): Added.
+        * UserInterface/Views/AuditTabContentView.js:
+        (WI.AuditTabContentView):
+        (WI.AuditTabContentView.tabInfo):
+        * UserInterface/Views/CanvasTabContentView.js:
+        (WI.CanvasTabContentView):
+        (WI.CanvasTabContentView.tabInfo):
+        * UserInterface/Views/ConsoleTabContentView.js:
+        (WI.ConsoleTabContentView):
+        (WI.ConsoleTabContentView.tabInfo):
+        * UserInterface/Views/ContentBrowserTabContentView.js:
+        (WI.ContentBrowserTabContentView):
+        * UserInterface/Views/ElementsTabContentView.js:
+        (WI.ElementsTabContentView):
+        (WI.ElementsTabContentView.tabInfo):
+        * UserInterface/Views/LayersTabContentView.js:
+        (WI.LayersTabContentView):
+        (WI.LayersTabContentView.tabInfo):
+        * UserInterface/Views/NetworkTabContentView.js:
+        (WI.NetworkTabContentView):
+        (WI.NetworkTabContentView.tabInfo):
+        * UserInterface/Views/SearchTabContentView.js:
+        (WI.SearchTabContentView):
+        (WI.SearchTabContentView.tabInfo):
+        (WI.SearchTabContentView.shouldPinTab): Added.
+        (WI.SearchTabContentView.shouldSaveTab): Added.
+        * UserInterface/Views/SettingsTabContentView.js:
+        (WI.SettingsTabContentView):
+        (WI.SettingsTabContentView.tabInfo):
+        (WI.SettingsTabContentView.shouldPinTab): Added.
+        (WI.SettingsTabContentView.prototype._createExperimentalSettingsView):
+        * UserInterface/Views/SourcesTabContentView.js:
+        (WI.SourcesTabContentView):
+        (WI.SourcesTabContentView.tabInfo):
+        (WI.SourcesTabContentView.prototype._handleDebuggerPaused): Added.
+        (WI.SourcesTabContentView.prototype._handleDebuggerResumed): Added.
+        * UserInterface/Views/StorageTabContentView.js:
+        (WI.StorageTabContentView):
+        (WI.StorageTabContentView.tabInfo):
+        * UserInterface/Views/TimelineTabContentView.js:
+        (WI.TimelineTabContentView):
+        (WI.TimelineTabContentView.tabInfo):
+        * UserInterface/Views/TabBarItem.js:
+        (WI.TabBarItem):
+        (WI.TabBarItem.get horizontalMargin): Added.
+        (WI.TabBarItem.prototype.get element):
+        (WI.TabBarItem.prototype.get representedObject):
+        (WI.TabBarItem.prototype.set disabled):
+        (WI.TabBarItem.prototype.get hidden): Added.
+        (WI.TabBarItem.prototype.set hidden): Added.
+        (WI.TabBarItem.prototype.set representedObject): Deleted.
+        (WI.TabBarItem.prototype.get isDefaultTab): Deleted.
+        (WI.TabBarItem.prototype.set isDefaultTab): Deleted.
+        * UserInterface/Views/GeneralTabBarItem.js:
+        (WI.GeneralTabBarItem.fromTabContentView): Added.
+        (WI.GeneralTabBarItem): Deleted.
+        (WI.GeneralTabBarItem.fromTabInfo): Deleted.
+        (WI.GeneralTabBarItem.prototype.get isEphemeral): Deleted.
+        (WI.GeneralTabBarItem.prototype._handleContextMenuEvent): Deleted.
+        * UserInterface/Views/PinnedTabBarItem.js:
+        (WI.PinnedTabBarItem):
+        (WI.PinnedTabBarItem.fromTabContentView): Added.
+        (WI.PinnedTabBarItem.titleDidChange):
+        (WI.PinnedTabBarItem.fromTabInfo): Deleted.
+        (WI.PinnedTabBarItem.prototype.titleDidChange): Deleted.
+        (WI.PinnedTabBarItem.prototype._handleContextMenuEvent): Deleted.
+        Simplify how tab bar items are created.
+
+        * UserInterface/Views/NavigationBar.js:
+        (WI.NavigationBar.prototype.get sizesToFit):
+        (WI.NavigationBar.prototype.addNavigationItem):
+        (WI.NavigationBar.prototype.insertNavigationItem):
+        * UserInterface/Views/SizesToFitNavigationBar.js: Removed.
+        * UserInterface/Views/Sidebar.js:
+        (WI.Sidebar):
+        * UserInterface/Views/GraphicsOverviewContentView.js:
+        (WI.GraphicsOverviewContentView.prototype.initialLayout):
+        Support marking `sizesToFit` during construction, instead of having to make a subclass.
+
+        * UserInterface/Views/ButtonNavigationItem.js:
+        (WI.ButtonNavigationItem):
+        (WI.ButtonNavigationItem.prototype.get imageType): Added.
+        (WI.ButtonNavigationItem.prototype.set imageType): Added.
+        (WI.ButtonNavigationItem.prototype._update):
+        * UserInterface/Views/ButtonNavigationItem.css:
+        (.tab-bar > .navigation-bar .item.button.image-and-text > span): Added.
+        (.navigation-bar .item.button > img): Added.
+        (.navigation-bar .item.button.disabled > img): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button > img): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button.disabled > img): Added.
+        (@media (prefers-color-scheme: dark) .navigation-bar .item.button.disabled > img): Added.
+        Allow `WI.ButtonNavigationItem` to use an `<img>` instead of an `<svg>` for it's image. This
+        is to work around a compositing bug <https://webkit.org/b/207022>.
+
+        * UserInterface/Views/GroupNavigationItem.js:
+        (WI.GroupNavigationItem.prototype.get hidden): Added.
+        (WI.GroupNavigationItem.prototype.set hidden): Added.
+        (WI.GroupNavigationItem.prototype.get additionalClassNames): Added.
+        Add a special case where this item is considered `hidden` if all sub-items are also `hidden`.
+
+        * UserInterface/Views/Variables.css:
+        (:root):
+        (body:matches(.window-inactive, .window-docked-inactive)): Added.
+        (body:matches(.window-inactive, .window-docked-inactive) *): Added.
+        (body:not(.docked)): Added.
+        (@media (prefers-color-scheme: dark) :root):
+        (@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive)): Added.
+        (@media (prefers-color-scheme: dark) body:matches(.window-inactive, .window-docked-inactive) *): Added.
+        (body.window-inactive): Deleted.
+        (body.window-inactive *): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive): Deleted.
+        (@media (prefers-color-scheme: dark) body.window-inactive *): Deleted.
+        Replace `--toolbar-height` with `--undocked-title-area-height`, which is set when docked.
+        Define `--tab-bar-height` in terms of `--navigation-bar-height` so they share the same value.
+
+        * UserInterface/Views/DividerNavigationItem.css:
+        (.navigation-bar .item.divider):
+        (@media (prefers-color-scheme: dark)):
+        Simplify the CSS in order to better support being used in the tab bar.
+
+        * UserInterface/Views/FlexibleSpaceNavigationItem.css:
+        (.navigation-bar .item.flexible-space):
+        (.navigation-bar .item.flexible-space.align-start > .item):
+        (.navigation-bar .item.flexible-space.align-end > .item):
+        (:matches(.navigation-bar, .toolbar) .item.flexible-space): Deleted.
+        (:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item): Deleted.
+        (:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item): Deleted.
+        Remove toolbar styles.
+
+        * UserInterface/Controllers/ConsoleManager.js:
+        (WI.ConsoleManager):
+        (WI.ConsoleManager.prototype.get warningCount): Added.
+        (WI.ConsoleManager.prototype.get errorCount): Added.
+        (WI.ConsoleManager.prototype.messageWasAdded):
+        (WI.ConsoleManager.prototype.messagesCleared):
+        (WI.ConsoleManager.prototype.messageRepeatCountUpdated):
+        (WI.ConsoleManager.prototype._incrementMessageLevelCount): Added.
+        (WI.ConsoleManager.prototype._delayedMessagesCleared):
+        Keep track of the count of warnings and errors so that they can be used to determine when to
+        show Console button navigation items in the tab bar.
+
+        * UserInterface/Views/DOMTreeContentView.css:
+        (body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint): Added.
+        (body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree): Added.
+        (body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint): Deleted.
+        (body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree): Deleted.
+        * UserInterface/Views/RenderingFrameTimelineOverviewGraph.css:
+        (body:matches(.window-inactive, .window-docked-inactive) .timeline-overview-graph.rendering-frame > .frame-marker): Added.
+        (body.window-inactive .timeline-overview-graph.rendering-frame > .frame-marker): Deleted.
+        * UserInterface/Views/TimelineOverview.css:
+        (.timeline-overview > .tree-outline.timelines .item.selected + .item, body:matches(.window-inactive, .window-docked-inactive) .timeline-overview > .tree-outline.timelines .item.selected + .item): Added.
+        (@media (prefers-color-scheme: dark) .timeline-overview > .tree-outline.timelines .item.selected + .item, body:matches(.window-inactive, .window-docked-inactive) .timeline-overview > .tree-outline.timelines .item.selected + .item): Added.
+        (.timeline-overview > .tree-outline.timelines .item.selected + .item, body.window-inactive .timeline-overview > .tree-outline.timelines .item.selected + .item): Deleted.
+        (@media (prefers-color-scheme: dark) .timeline-overview > .tree-outline.timelines .item.selected + .item, body.window-inactive .timeline-overview > .tree-outline.timelines .item.selected + .item): Deleted.
+        * UserInterface/Views/TimelineRecordFrame.css:
+        (body:matches(.window-inactive, .window-docked-inactive) .timeline-record-frame.selected): Added.
+        (body.window-inactive .timeline-record-frame.selected): Deleted.
+        * UserInterface/Views/TimelineRuler.css:
+        (body:matches(.window-inactive, .window-docked-inactive) .timeline-ruler > .header > .divider): Added.
+        (body.window-inactive .timeline-ruler > .header > .divider): Deleted.
+        Add selectors for `.window-docked-inactive` everywhere that `.window-inactive` exists.
+
+        * UserInterface/Base/Setting.js:
+        Remove new tab bar experimental setting.
+
+        * UserInterface/Debug/Bootstrap.js:
+        (WI.runBootstrapOperations):
+        (WI.runBootstrapOperations.applyDumpMessagesState):
+        (WI.runBootstrapOperations.updateDebugUI):
+
+        * UserInterface/Main.html:
+        * Localizations/en.lproj/localizedStrings.js:
+
+        * UserInterface/Views/ActivateButtonToolbarItem.js: Removed.
+        * UserInterface/Views/ButtonToolbarItem.js: Removed.
+        * UserInterface/Views/ButtonToolbarItem.css: Removed.
+        * UserInterface/Views/ControlToolbarItem.js: Removed.
+        * UserInterface/Views/ControlToolbarItem.css: Removed.
+        * UserInterface/Views/Toolbar.js: Removed.
+        * UserInterface/Views/Toolbar.css: Removed.
+        Remove toolbar related code now that it has been merged into the tab bar.
+
+        * UserInterface/Models/DebuggerDashboard.js: Removed.
+        * UserInterface/Models/DefaultDashboard.js: Removed.
+        * UserInterface/Views/DashboardContainerView.js: Removed.
+        * UserInterface/Views/DashboardContainerView.css: Removed.
+        * UserInterface/Views/DashboardView.js: Removed.
+        * UserInterface/Views/DebuggerDashboardView.js: Removed.
+        * UserInterface/Views/DebuggerDashboardView.css: Removed.
+        * UserInterface/Views/DefaultDashboardView.js: Removed.
+        * UserInterface/Views/DefaultDashboardView.css: Removed.
+        Remove dashboard related code now that it has been merged into the tab bar.
+
+        * UserInterface/Views/LegacyTabBar.js: Removed.
+        * UserInterface/Views/NewTabContentView.js: Removed.
+        * UserInterface/Views/NewTabContentView.css: Removed.
+        * UserInterface/Images/NewTab.svg: Removed.
+        * UserInterface/Images/NewTabPlus.svg: Removed.
+        * UserInterface/Images/SearchResults.svg: Removed.
+        Remove the lebacy tab bar in favor of the new tab bar.
+
 2020-03-02  Jon Davis  <jond@apple.com>
 
         Updated breakpoint and search type icons
index c9205b0..8038a9f 100644 (file)
@@ -40,8 +40,14 @@ localizedStrings["%d Warning"] = "%d Warning";
 localizedStrings["%d Warnings"] = "%d Warnings";
 localizedStrings["%d \xd7 %d pixels"] = "%d \xd7 %d pixels";
 localizedStrings["%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)"] = "%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)";
+localizedStrings["%d domain"] = "%d domain";
+localizedStrings["%d domains"] = "%d domains";
 localizedStrings["%d matches"] = "%d matches";
 localizedStrings["%d of %d"] = "%d of %d";
+localizedStrings["%d redirect"] = "%d redirect";
+localizedStrings["%d redirects"] = "%d redirects";
+localizedStrings["%d resource"] = "%d resource";
+localizedStrings["%d resources"] = "%d resources";
 localizedStrings["%dpx"] = "%dpx";
 localizedStrings["%dpx\u00B2"] = "%dpx\u00B2";
 localizedStrings["%s (%s)"] = "%s (%s)";
@@ -61,6 +67,8 @@ localizedStrings["%s cannot be modified"] = "%s cannot be modified";
 localizedStrings["%s delay"] = "%s delay";
 localizedStrings["%s eval\n%s async"] = "%s eval\n%s async";
 localizedStrings["%s interval"] = "%s interval";
+localizedStrings["%s total"] = "%s total";
+localizedStrings["%s transferred"] = "%s transferred";
 localizedStrings["%s:"] = "%s:";
 localizedStrings["(Action %s)"] = "(Action %s)";
 localizedStrings["(Disk)"] = "(Disk)";
@@ -78,13 +86,14 @@ localizedStrings["(program)"] = "(program)";
 localizedStrings["(service worker)"] = "(service worker)";
 localizedStrings["(uninitialized)"] = "(uninitialized)";
 localizedStrings[", "] = ", ";
+localizedStrings["0 Console errors"] = "0 Console errors";
+localizedStrings["0 Console warnings"] = "0 Console warnings";
 localizedStrings["1 match"] = "1 match";
 localizedStrings["2D"] = "2D";
 localizedStrings["Accessibility"] = "Accessibility";
 localizedStrings["Action"] = "Action";
 /* Tooltip for a time range bar that represents when a CSS animation/transition is running */
 localizedStrings["Active"] = "Active";
-localizedStrings["Activity Viewer"] = "Activity Viewer";
 localizedStrings["Add"] = "Add";
 localizedStrings["Add %s Rule"] = "Add %s Rule";
 localizedStrings["Add Action"] = "Add Action";
@@ -261,17 +270,19 @@ localizedStrings["Clear object store"] = "Clear object store";
 localizedStrings["Clear samples"] = "Clear samples";
 localizedStrings["Clear watch expressions"] = "Clear watch expressions";
 localizedStrings["Click Listener"] = "Click Listener";
-localizedStrings["Click to close this tab"] = "Click to close this tab";
 localizedStrings["Click to create a Local Override from this content"] = "Click to create a Local Override from this content";
 localizedStrings["Click to import a file and create a Local Override\nShift-click to create a Local Override from this content"] = "Click to import a file and create a Local Override\nShift-click to create a Local Override from this content";
 localizedStrings["Click to select a color"] = "Click to select a color";
 localizedStrings["Click to select a color\nShift-click to switch color formats"] = "Click to select a color\nShift-click to switch color formats";
+localizedStrings["Click to show %d error in the Console"] = "Click to show %d error in the Console";
+localizedStrings["Click to show %d errors in the Console"] = "Click to show %d errors in the Console";
+localizedStrings["Click to show %d warning in the Console"] = "Click to show %d warning in the Console";
+localizedStrings["Click to show %d warnings in the Console"] = "Click to show %d warnings in the Console";
 localizedStrings["Click to view variable value\nShift-click to replace variable with value"] = "Click to view variable value\nShift-click to replace variable with value";
 localizedStrings["Clickable"] = "Clickable";
 localizedStrings["Clients"] = "Clients";
 localizedStrings["Close"] = "Close";
 localizedStrings["Close %s timeline view"] = "Close %s timeline view";
-localizedStrings["Close Tab"] = "Close Tab";
 localizedStrings["Close detail view"] = "Close detail view";
 localizedStrings["Closed"] = "Closed";
 localizedStrings["Closure Variables"] = "Closure Variables";
@@ -337,7 +348,6 @@ localizedStrings["Create %s Rule"] = "Create %s Rule";
 localizedStrings["Create Breakpoint"] = "Create Breakpoint";
 localizedStrings["Create Local Override"] = "Create Local Override";
 localizedStrings["Create Resource"] = "Create Resource";
-localizedStrings["Create a new tab"] = "Create a new tab";
 localizedStrings["Cross-Origin Restrictions"] = "Cross-Origin Restrictions";
 localizedStrings["Current"] = "Current";
 localizedStrings["Current State"] = "Current State";
@@ -359,7 +369,6 @@ localizedStrings["Database no longer has expected version."] = "Database no long
 localizedStrings["Databases"] = "Databases";
 localizedStrings["Date"] = "Date";
 localizedStrings["Debug: "] = "Debug: ";
-localizedStrings["Debugger Paused"] = "Debugger Paused";
 localizedStrings["Debugger Statement"] = "Debugger Statement";
 localizedStrings["Debugger Statements"] = "Debugger Statements";
 localizedStrings["Debugger disabled during Audit"] = "Debugger disabled during Audit";
@@ -480,7 +489,6 @@ localizedStrings["Enable Event Listener"] = "Enable Event Listener";
 localizedStrings["Enable Event Listeners"] = "Enable Event Listeners";
 localizedStrings["Enable Inspector Bootstrap Script"] = "Enable Inspector Bootstrap Script";
 localizedStrings["Enable Local Override"] = "Enable Local Override";
-localizedStrings["Enable New Tab Bar"] = "Enable New Tab Bar";
 localizedStrings["Enable Preview Features"] = "Enable Preview Features";
 localizedStrings["Enable Program"] = "Enable Program";
 localizedStrings["Enable Rule"] = "Enable Rule";
@@ -707,6 +715,8 @@ localizedStrings["Live Activity"] = "Live Activity";
 localizedStrings["Live Size"] = "Live Size";
 localizedStrings["Load \u2014 %s"] = "Load \u2014 %s";
 localizedStrings["Load cancelled"] = "Load cancelled";
+localizedStrings["Loaded in %s"] = "Loaded in %s";
+localizedStrings["Loading for %s"] = "Loading for %s";
 localizedStrings["Local File"] = "Local File";
 localizedStrings["Local Override"] = "Local Override";
 localizedStrings["Local Override\u2026"] = "Local Override\u2026";
@@ -770,7 +780,6 @@ localizedStrings["Network"] = "Network";
 localizedStrings["Network Issue"] = "Network Issue";
 localizedStrings["Network Requests"] = "Network Requests";
 localizedStrings["Network Requests:"] = "Network Requests:";
-localizedStrings["New Tab"] = "New Tab";
 /* A submenu item of 'Add' to add DOM nodes after the selected DOM node */
 localizedStrings["Next Sibling"] = "Next Sibling";
 localizedStrings["No"] = "No";
@@ -1089,21 +1098,15 @@ localizedStrings["Show Scope Chain on pause"] = "Show Scope Chain on pause";
 localizedStrings["Show all actions"] = "Show all actions";
 localizedStrings["Show all resources"] = "Show all resources";
 localizedStrings["Show compositing borders"] = "Show compositing borders";
-localizedStrings["Show errors logged to the Console"] = "Show errors logged to the Console";
 localizedStrings["Show full certificate"] = "Show full certificate";
 localizedStrings["Show hidden tabs"] = "Show hidden tabs";
-localizedStrings["Show messages logged to the Console"] = "Show messages logged to the Console";
-localizedStrings["Show network information"] = "Show network information";
 localizedStrings["Show only for selected node"] = "Show only for selected node";
-localizedStrings["Show page load timing"] = "Show page load timing";
-localizedStrings["Show page resources"] = "Show page resources";
 localizedStrings["Show page rulers and node border lines"] = "Show page rulers and node border lines";
 localizedStrings["Show rulers"] = "Show rulers";
 localizedStrings["Show the details sidebar (%s)"] = "Show the details sidebar (%s)";
 localizedStrings["Show the navigation sidebar (%s)"] = "Show the navigation sidebar (%s)";
 localizedStrings["Show transparency grid"] = "Show transparency grid";
 localizedStrings["Show type information"] = "Show type information";
-localizedStrings["Show warnings logged to the Console"] = "Show warnings logged to the Console";
 localizedStrings["Show:"] = "Show:";
 localizedStrings["Site-specific Hacks"] = "Site-specific Hacks";
 localizedStrings["Size"] = "Size";
@@ -1300,7 +1303,6 @@ localizedStrings["Use the resource cache when loading resources"] = "Use the res
 localizedStrings["User Agent"] = "User Agent";
 localizedStrings["User Agent Style Sheet"] = "User Agent Style Sheet";
 localizedStrings["User Agent:"] = "User Agent:";
-localizedStrings["User Interface:"] = "User Interface:";
 localizedStrings["User Style Sheet"] = "User Style Sheet";
 localizedStrings["Valid From"] = "Valid From";
 localizedStrings["Valid Until"] = "Valid Until";
index 42e7a52..3ac63d9 100644 (file)
@@ -131,7 +131,6 @@ WI.loaded = function()
 
     // Register for events.
     WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, WI._debuggerDidPause);
-    WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, WI._debuggerDidResume);
     WI.domManager.addEventListener(WI.DOMManager.Event.InspectModeStateChanged, WI._inspectModeStateChanged);
     WI.domManager.addEventListener(WI.DOMManager.Event.DOMNodeWasInspected, WI._domNodeWasInspected);
     WI.domStorageManager.addEventListener(WI.DOMStorageManager.Event.DOMStorageObjectWasInspected, WI._domStorageWasInspected);
@@ -153,6 +152,7 @@ WI.loaded = function()
         WI.TimelineTabContentView.Type,
         WI.StorageTabContentView.Type,
         WI.GraphicsTabContentView.Type,
+        WI.LayersTabContentView.Type,
         WI.AuditTabContentView.Type,
         WI.ConsoleTabContentView.Type,
     ]);
@@ -242,7 +242,6 @@ WI.contentLoaded = function()
     window.addEventListener("resize", WI._windowResized);
     window.addEventListener("keydown", WI._windowKeyDown);
     window.addEventListener("keyup", WI._windowKeyUp);
-    window.addEventListener("mousedown", WI._mouseDown, true);
     window.addEventListener("mousemove", WI._mouseMoved, true);
     window.addEventListener("pagehide", WI._pageHidden);
     window.addEventListener("contextmenu", WI._contextMenuRequested);
@@ -283,19 +282,8 @@ WI.contentLoaded = function()
     WI.settings.showWhitespaceCharacters.addEventListener(WI.Setting.Event.Changed, setWhitespaceCharacterClassName);
     setWhitespaceCharacterClassName();
 
-    WI.settingsTabContentView = new WI.SettingsTabContentView;
-
-    WI._settingsKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Comma, WI._handleSettingsKeyboardShortcut);
-
     // Create the user interface elements.
-    WI.toolbar = new WI.Toolbar(document.getElementById("toolbar"));
-
-    if (WI.settings.experimentalEnableNewTabBar.value)
-        WI.tabBar = new WI.TabBar(document.getElementById("tab-bar"));
-    else {
-        WI.tabBar = new WI.LegacyTabBar(document.getElementById("tab-bar"));
-        WI.tabBar.addEventListener(WI.TabBar.Event.OpenDefaultTab, WI._openDefaultTab);
-    }
+    WI.tabBar = new WI.TabBar(document.getElementById("tab-bar"));
 
     WI._contentElement = document.getElementById("content");
     WI._contentElement.setAttribute("role", "main");
@@ -347,7 +335,6 @@ WI.contentLoaded = function()
     WI._resetZoomKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, "0", WI._resetZoom);
 
     WI._showTabAtIndexKeyboardShortcuts = [1, 2, 3, 4, 5, 6, 7, 8, 9].map((i) => new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Option, `${i}`, (event) => { WI._showTabAtIndexFromShortcut(i); }));
-    WI._openNewTabKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Option, "T", WI._showNewTabFromShortcut);
 
     WI.tabBrowser = new WI.TabBrowser(document.getElementById("tab-browser"), WI.tabBar, WI.navigationSidebar, WI.detailsSidebar);
     WI.tabBrowser.addEventListener(WI.TabBrowser.Event.SelectedTabContentViewDidChange, WI._tabBrowserSelectedTabContentViewDidChange);
@@ -376,94 +363,104 @@ WI.contentLoaded = function()
     WI.stepIntoAlternateKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Semicolon, WI.debuggerStepInto);
     WI.stepOutAlternateKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.Shift | WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Semicolon, WI.debuggerStepOut);
 
-    WI._closeToolbarButton = new WI.ControlToolbarItem("dock-close", WI.UIString("Close"), "Images/Close.svg", 16, 14);
-    WI._closeToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.close);
+    WI._settingsKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl, WI.KeyboardShortcut.Key.Comma, WI._handleSettingsKeyboardShortcut);
 
-    WI._undockToolbarButton = new WI.ButtonToolbarItem("undock", WI.UIString("Detach into separate window"), "Images/Undock.svg");
-    WI._undockToolbarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
-    WI._undockToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._undock);
+    WI._togglePreviousDockConfigurationKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "D", WI._togglePreviousDockConfiguration);
 
-    let dockImage = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "Images/DockLeft.svg" : "Images/DockRight.svg";
-    WI._dockToSideToolbarButton = new WI.ButtonToolbarItem("dock-right", WI.UIString("Dock to side of window"), dockImage);
-    WI._dockToSideToolbarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
+    WI._closeTabBarButton = new WI.ButtonNavigationItem("dock-close", WI.UIString("Close"), "Images/CloseLarge.svg");
+    WI._closeTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.close);
 
-    let dockToSideCallback = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? WI._dockLeft : WI._dockRight;
-    WI._dockToSideToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, dockToSideCallback);
+    WI._dockToSideTabBarButton = new WI.ButtonNavigationItem("dock-right", WI.UIString("Dock to side of window"), WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "Images/DockLeft.svg" : "Images/DockRight.svg", 16, 16);
+    WI._dockToSideTabBarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
+    WI._dockToSideTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? WI._dockLeft : WI._dockRight);
 
-    WI._dockBottomToolbarButton = new WI.ButtonToolbarItem("dock-bottom", WI.UIString("Dock to bottom of window"), "Images/DockBottom.svg");
-    WI._dockBottomToolbarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
-    WI._dockBottomToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._dockBottom);
+    WI._dockBottomTabBarButton = new WI.ButtonNavigationItem("dock-bottom", WI.UIString("Dock to bottom of window"), "Images/DockBottom.svg", 16, 16);
+    WI._dockBottomTabBarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
+    WI._dockBottomTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._dockBottom);
 
-    WI._togglePreviousDockConfigurationKeyboardShortcut = new WI.KeyboardShortcut(WI.KeyboardShortcut.Modifier.CommandOrControl | WI.KeyboardShortcut.Modifier.Shift, "D", WI._togglePreviousDockConfiguration);
+    WI._undockTabBarButton = new WI.ButtonNavigationItem("undock", WI.UIString("Detach into separate window"), "Images/Undock.svg", 16, 16);
+    WI._undockTabBarButton.element.classList.add(WI.Popover.IgnoreAutoDismissClassName);
+    WI._undockTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._undock);
 
-    let reloadToolTip;
-    if (WI.sharedApp.debuggableType === WI.DebuggableType.JavaScript)
-        reloadToolTip = WI.UIString("Restart (%s)").format(WI._reloadPageKeyboardShortcut.displayName);
-    else
-        reloadToolTip = WI.UIString("Reload page (%s)\nReload page ignoring cache (%s)").format(WI._reloadPageKeyboardShortcut.displayName, WI._reloadPageFromOriginKeyboardShortcut.displayName);
-    WI._reloadToolbarButton = new WI.ButtonToolbarItem("reload", reloadToolTip, "Images/ReloadToolbar.svg");
-    WI._reloadToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._reloadToolbarButtonClicked);
-
-    WI._downloadToolbarButton = new WI.ButtonToolbarItem("download", WI.UIString("Download Web Archive"), "Images/DownloadArrow.svg");
-    WI._downloadToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._downloadWebArchive);
+    let inspectedPageControlNavigationItems = [];
 
     let elementSelectionToolTip = WI.UIString("Start element selection (%s)").format(WI._inspectModeKeyboardShortcut.displayName);
     let activatedElementSelectionToolTip = WI.UIString("Stop element selection (%s)").format(WI._inspectModeKeyboardShortcut.displayName);
-    WI._inspectModeToolbarButton = new WI.ActivateButtonToolbarItem("inspect", elementSelectionToolTip, activatedElementSelectionToolTip, "Images/Crosshair.svg");
-    WI._inspectModeToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._toggleInspectMode);
-
-    // COMPATIBILITY (iOS 12.2): Page.overrideSetting did not exist.
-    if ((InspectorFrontendHost.isRemote || WI.isDebugUIEnabled()) && InspectorBackend.hasCommand("Page.overrideUserAgent") && InspectorBackend.hasCommand("Page.overrideSetting")) {
-        const deviceSettingsTooltip = WI.UIString("Device Settings");
-        WI._deviceSettingsToolbarButton = new WI.ActivateButtonToolbarItem("device-settings", deviceSettingsTooltip, deviceSettingsTooltip, "Images/Device.svg");
-        WI._deviceSettingsToolbarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._handleDeviceSettingsToolbarButtonClicked);
-
-        WI._deviceSettingsPopover = null;
-    }
-
-    WI._updateReloadToolbarButton();
-    WI._updateDownloadToolbarButton();
-    WI._updateInspectModeToolbarButton();
-
-    WI._dashboards = {
-        default: new WI.DefaultDashboard,
-        debugger: new WI.DebuggerDashboard,
-    };
-
-    WI._dashboardContainer = new WI.DashboardContainerView;
-    WI._dashboardContainer.showDashboardViewForRepresentedObject(WI._dashboards.default);
+    WI._inspectModeTabBarButton = new WI.ActivateButtonNavigationItem("inspect", elementSelectionToolTip, activatedElementSelectionToolTip, "Images/Crosshair.svg");
+    WI._inspectModeTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._toggleInspectMode);
+    inspectedPageControlNavigationItems.push(WI._inspectModeTabBarButton);
 
-    WI.toolbar.addToolbarItem(WI._closeToolbarButton, WI.Toolbar.Section.Control);
+    if (InspectorFrontendHost.isRemote || WI.isDebugUIEnabled()) {
+        // COMPATIBILITY (iOS 12.2): Page.overrideSetting did not exist.
+        if (InspectorBackend.hasCommand("Page.overrideUserAgent") && InspectorBackend.hasCommand("Page.overrideSetting")) {
+            const deviceSettingsTooltip = WI.UIString("Device Settings");
+            WI._deviceSettingsTabBarButton = new WI.ActivateButtonNavigationItem("device-settings", deviceSettingsTooltip, deviceSettingsTooltip, "Images/Device.svg");
+            WI._deviceSettingsTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._handleDeviceSettingsTabBarButtonClicked);
+            inspectedPageControlNavigationItems.push(WI._deviceSettingsTabBarButton);
 
-    WI.toolbar.addToolbarItem(WI._undockToolbarButton, WI.Toolbar.Section.Left);
-    WI.toolbar.addToolbarItem(WI._dockToSideToolbarButton, WI.Toolbar.Section.Left);
-    WI.toolbar.addToolbarItem(WI._dockBottomToolbarButton, WI.Toolbar.Section.Left);
+            WI._deviceSettingsPopover = null;
+        }
 
-    WI.toolbar.addToolbarItem(WI._reloadToolbarButton, WI.Toolbar.Section.CenterLeft);
-    WI.toolbar.addToolbarItem(WI._downloadToolbarButton, WI.Toolbar.Section.CenterLeft);
+        let reloadToolTip;
+        if (WI.sharedApp.debuggableType === WI.DebuggableType.JavaScript)
+            reloadToolTip = WI.UIString("Restart (%s)").format(WI._reloadPageKeyboardShortcut.displayName);
+        else
+            reloadToolTip = WI.UIString("Reload page (%s)\nReload page ignoring cache (%s)").format(WI._reloadPageKeyboardShortcut.displayName, WI._reloadPageFromOriginKeyboardShortcut.displayName);
+        WI._reloadTabBarButton = new WI.ButtonNavigationItem("reload", reloadToolTip, "Images/ReloadToolbar.svg");
+        WI._reloadTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._reloadTabBarButtonClicked);
+        inspectedPageControlNavigationItems.push(WI._reloadTabBarButton);
+
+        WI._downloadTabBarButton = new WI.ButtonNavigationItem("download", WI.UIString("Download Web Archive"), "Images/DownloadArrow.svg");
+        WI._downloadTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI._downloadWebArchive);
+        inspectedPageControlNavigationItems.push(WI._downloadTabBarButton);
+    }
+
+    WI.tabBar.addNavigationItemBefore(new WI.GroupNavigationItem([
+        WI._closeTabBarButton,
+        WI._dockToSideTabBarButton,
+        WI._dockBottomTabBarButton,
+        WI._undockTabBarButton,
+        ...inspectedPageControlNavigationItems,
+    ]));
+
+    WI._consoleDividerNavigationItem = new WI.DividerNavigationItem;
+    WI.tabBar.addNavigationItemBefore(WI._consoleDividerNavigationItem);
+
+    WI._consoleWarningsTabBarButton = new WI.ButtonNavigationItem("console-warnings", WI.UIString("0 Console warnings"), "Images/IssuesEnabled.svg");
+    WI._consoleWarningsTabBarButton.imageType = WI.ButtonNavigationItem.ImageType.IMG;
+    WI._consoleWarningsTabBarButton.hidden = true;
+    WI._consoleWarningsTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+        WI.showConsoleTab(WI.LogContentView.Scopes.Warnings, {
+            initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard,
+        });
+    }, WI);
 
-    WI.toolbar.addToolbarItem(WI._dashboardContainer.toolbarItem, WI.Toolbar.Section.Center);
+    WI._consoleErrorsTabBarButton = new WI.ButtonNavigationItem("console-errors", WI.UIString("0 Console errors"), "Images/ErrorsEnabled.svg");
+    WI._consoleErrorsTabBarButton.imageType = WI.ButtonNavigationItem.ImageType.IMG;
+    WI._consoleErrorsTabBarButton.hidden = true;
+    WI._consoleErrorsTabBarButton.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+        WI.showConsoleTab(WI.LogContentView.Scopes.Errors, {
+            initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard,
+        });
+    }, WI);
 
-    WI.toolbar.addToolbarItem(WI._inspectModeToolbarButton, WI.Toolbar.Section.CenterRight);
+    WI.tabBar.addNavigationItemBefore(new WI.GroupNavigationItem([
+        WI._consoleWarningsTabBarButton,
+        WI._consoleErrorsTabBarButton,
+    ]));
 
-    if (WI._deviceSettingsToolbarButton)
-        WI.toolbar.addToolbarItem(WI._deviceSettingsToolbarButton, WI.Toolbar.Section.CenterRight);
+    WI._updateInspectModeTabBarButton();
+    WI._updateDownloadTabBarButton();
+    WI._updateReloadTabBarButton();
 
-    WI._searchTabContentView = new WI.SearchTabContentView;
+    WI.consoleManager.addEventListener(WI.ConsoleManager.Event.MessageAdded, WI._updateConsoleTabBarButtons, WI);
+    WI.consoleManager.addEventListener(WI.ConsoleManager.Event.PreviousMessageRepeatCountUpdated, WI._updateConsoleTabBarButtons, WI);
+    WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, WI._updateConsoleTabBarButtons, WI);
+    WI._updateConsoleTabBarButtons();
 
-    if (WI.settings.experimentalEnableNewTabBar.value) {
-        WI.tabBrowser.addTabForContentView(WI._searchTabContentView, {suppressAnimations: true});
-        WI.tabBar.addTabBarItem(WI.settingsTabContentView.tabBarItem, {suppressAnimations: true});
-    } else {
-        const incremental = false;
-        WI._searchToolbarItem = new WI.SearchBar("inspector-search", WI.UIString("Search"), incremental);
-        WI._searchToolbarItem.addEventListener(WI.SearchBar.Event.TextChanged, WI._searchTextDidChange);
-        WI.toolbar.addToolbarItem(WI._searchToolbarItem, WI.Toolbar.Section.Right);
-    }
-
-    let dockedResizerElement = document.getElementById("docked-resizer");
-    dockedResizerElement.classList.add(WI.Popover.IgnoreAutoDismissClassName);
-    dockedResizerElement.addEventListener("mousedown", WI._dockedResizerMouseDown);
+    WI._dockedResizerElement = document.getElementById("docked-resizer");
+    WI._dockedResizerElement.classList.add(WI.Popover.IgnoreAutoDismissClassName);
+    WI._dockedResizerElement.addEventListener("mousedown", WI._dockedResizerMouseDown);
 
     WI._dockingAvailable = false;
 
@@ -483,7 +480,6 @@ WI.contentLoaded = function()
         WI.AuditTabContentView,
         WI.ConsoleTabContentView,
         WI.SearchTabContentView,
-        WI.NewTabContentView,
         WI.SettingsTabContentView,
     ];
 
@@ -495,6 +491,12 @@ WI.contentLoaded = function()
 
     WI._pendingOpenTabs = [];
 
+    WI._searchTabContentView = new WI.SearchTabContentView;
+    WI.tabBrowser.addTabForContentView(WI._searchTabContentView, {suppressAnimations: true});
+
+    WI._settingsTabContentView = new WI.SettingsTabContentView;
+    WI.tabBrowser.addTabForContentView(WI._settingsTabContentView, {suppressAnimations: true});
+
     // Previously we may have stored duplicates in WI setting. Avoid creating duplicate tabs.
     let openTabTypes = WI._openTabsSetting.value;
     let seenTabTypes = new Set;
@@ -522,13 +524,16 @@ WI.contentLoaded = function()
 
     WI._restoreCookieForOpenTabs(WI.StateRestorationType.Load);
 
-    WI.tabBar.selectedTabBarItem = WI._selectedTabIndexSetting.value;
-
-    if (!WI.tabBar.selectedTabBarItem)
+    if (WI.tabBar.normalTabCount)
+        WI.tabBar.selectedTabBarItem = WI._selectedTabIndexSetting.value;
+    else {
+        // If no tabs were able to be restored, show all tabs that are allowed.
+        for (let tabType of WI._openTabsSetting.defaultValue) {
+            if (WI.isNewTabWithTypeAllowed(tabType))
+                WI.createNewTabWithType(tabType)
+        }
         WI.tabBar.selectedTabBarItem = 0;
-
-    if (!WI.tabBar.normalTabCount)
-        WI.showNewTabTab({suppressAnimations: true});
+    }
 
     // Listen to the events after restoring the saved tabs to avoid recursion.
     WI.tabBar.addEventListener(WI.TabBar.Event.TabBarItemAdded, WI._rememberOpenTabs);
@@ -538,9 +543,19 @@ WI.contentLoaded = function()
     function updateConsoleSavedResultPrefixCSSVariable() {
         document.body.style.setProperty("--console-saved-result-prefix", "\"" + WI.RuntimeManager.preferredSavedResultPrefix() + "\"");
     }
-    WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, updateConsoleSavedResultPrefixCSSVariable);
+
+    WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, updateConsoleSavedResultPrefixCSSVariable, WI);
+
     updateConsoleSavedResultPrefixCSSVariable();
 
+    function updateZoomFactorCSSVariable() {
+        document.body.style.setProperty("--zoom-factor", WI.settings.zoomFactor.value);
+    }
+
+    WI.settings.zoomFactor.addEventListener(WI.Setting.Event.Changed, updateZoomFactorCSSVariable, WI);
+
+    updateZoomFactorCSSVariable();
+
     WI.settings.frontendAppearance.addEventListener(WI.Setting.Event.Changed, (event) => {
         InspectorFrontendHost.setForcedAppearance(WI.settings.frontendAppearance.value);
     }, WI);
@@ -681,15 +696,10 @@ WI._rememberOpenTabs = function()
     WI._openTabsSetting.value = openTabs;
 };
 
-WI._openDefaultTab = function(event)
-{
-    WI.showNewTabTab({suppressAnimations: true});
-};
-
 WI._handleSettingsKeyboardShortcut = function(event)
 {
     if (event.keyIdentifier === "U+002C") { // ","
-        WI.tabBrowser.showTabForContentView(WI.settingsTabContentView, {
+        WI.tabBrowser.showTabForContentView(WI._settingsTabContentView, {
             initiatorHint: WI.TabBrowser.TabNavigationInitiator.KeyboardShortcut,
         });
     }
@@ -717,20 +727,6 @@ WI._tryToRestorePendingTabs = function()
     }
 
     WI._pendingOpenTabs = stillPendingOpenTabs;
-
-    if (!WI.settings.experimentalEnableNewTabBar.value)
-        WI.tabBar.updateNewTabTabBarItemState();
-};
-
-WI.showNewTabTab = function(options)
-{
-    if (!WI.isNewTabWithTypeAllowed(WI.NewTabContentView.Type))
-        return;
-
-    let tabContentView = WI.tabBrowser.bestTabContentViewForClass(WI.NewTabContentView);
-    if (!tabContentView)
-        tabContentView = new WI.NewTabContentView;
-    WI.tabBrowser.showTabForContentView(tabContentView, options);
 };
 
 WI.isNewTabWithTypeAllowed = function(tabType)
@@ -748,13 +744,6 @@ WI.isNewTabWithTypeAllowed = function(tabType)
             return false;
     }
 
-    if (tabClass === WI.NewTabContentView) {
-        let allTabs = Array.from(WI.knownTabClasses());
-        let addableTabs = allTabs.filter((tabClass) => !tabClass.tabInfo().isEphemeral);
-        let canMakeNewTab = addableTabs.some((tabClass) => WI.isNewTabWithTypeAllowed(tabClass.Type));
-        return canMakeNewTab;
-    }
-
     return true;
 };
 
@@ -798,9 +787,9 @@ WI.activateExtraDomains = function(domains)
             WI.networkManager.initializeTarget(WI.mainTarget);
     }
 
-    WI._updateReloadToolbarButton();
-    WI._updateDownloadToolbarButton();
-    WI._updateInspectModeToolbarButton();
+    WI._updateInspectModeTabBarButton();
+    WI._updateDownloadTabBarButton();
+    WI._updateReloadTabBarButton();
 
     WI._tryToRestorePendingTabs();
 };
@@ -860,8 +849,6 @@ WI.updateDockedState = function(side)
 
     WI.docked = side !== WI.DockConfiguration.Undocked;
 
-    WI._ignoreToolbarModeDidChangeEvents = true;
-
     if (side === WI.DockConfiguration.Bottom) {
         document.body.classList.add("docked", WI.DockConfiguration.Bottom);
         document.body.classList.remove("window-inactive", WI.DockConfiguration.Right, WI.DockConfiguration.Left);
@@ -874,8 +861,6 @@ WI.updateDockedState = function(side)
     } else
         document.body.classList.remove("docked", WI.DockConfiguration.Right, WI.DockConfiguration.Left, WI.DockConfiguration.Bottom);
 
-    WI._ignoreToolbarModeDidChangeEvents = false;
-
     WI._updateDockNavigationItems();
 
     if (!WI.dockedConfigurationSupportsSplitContentBrowser() && !WI.doesCurrentTabSupportSplitContentBrowser())
@@ -1141,10 +1126,10 @@ WI.isShowingLayersTab = function()
 
 WI.showSettingsTab = function(options = {})
 {
-    WI.tabBrowser.showTabForContentView(WI.settingsTabContentView, options);
+    WI.tabBrowser.showTabForContentView(WI._settingsTabContentView, options);
 
     if (options.blackboxPatternToSelect)
-        WI.settingsTabContentView.selectBlackboxPattern(options.blackboxPatternToSelect);
+        WI._settingsTabContentView.selectBlackboxPattern(options.blackboxPatternToSelect);
 };
 
 WI.indentString = function()
@@ -1389,35 +1374,14 @@ WI.debuggerStepOut = function(event)
     WI.debuggerManager.stepOut();
 };
 
-WI._searchTextDidChange = function(event)
+WI._focusSearchField = function(event)
 {
-    var tabContentView = WI.tabBrowser.bestTabContentViewForClass(WI.SearchTabContentView);
-    if (!tabContentView)
-        tabContentView = new WI.SearchTabContentView;
-
-    var searchQuery = WI._searchToolbarItem.text;
-    WI._searchToolbarItem.text = "";
-
-    WI.tabBrowser.showTabForContentView(tabContentView, {
+    WI.tabBrowser.showTabForContentView(WI._searchTabContentView, {
         // Classify this as a keyboard shortcut, as the only other way to get to Search Tab is via TabBar itself.
         initiatorHint: WI.TabBrowser.TabNavigationInitiator.KeyboardShortcut,
     });
 
-    tabContentView.performSearch(searchQuery);
-};
-
-WI._focusSearchField = function(event)
-{
-    if (WI.settings.experimentalEnableNewTabBar.value)
-        WI.tabBrowser.showTabForContentView(WI._searchTabContentView);
-
-    if (WI.tabBrowser.selectedTabContentView instanceof WI.SearchTabContentView) {
-        WI.tabBrowser.selectedTabContentView.focusSearchField();
-        return;
-    }
-
-    if (WI._searchToolbarItem)
-        WI._searchToolbarItem.focus();
+    WI._searchTabContentView.focusSearchField();
 };
 
 WI._focusChanged = function(event)
@@ -1526,16 +1490,9 @@ WI._debuggerDidPause = function(event)
 {
     WI.showSourcesTab({showScopeChainSidebar: WI.settings.showScopeChainOnPause.value});
 
-    WI._dashboardContainer.showDashboardViewForRepresentedObject(WI._dashboards.debugger);
-
     InspectorFrontendHost.bringToFront();
 };
 
-WI._debuggerDidResume = function(event)
-{
-    WI._dashboardContainer.closeDashboardViewForRepresentedObject(WI._dashboards.debugger);
-};
-
 WI._frameWasAdded = function(event)
 {
     if (!WI._frameIdentifierToShowSourceCodeWhenAvailable)
@@ -1561,7 +1518,7 @@ WI._frameWasAdded = function(event)
 
 WI._mainFrameDidChange = function(event)
 {
-    WI._updateDownloadToolbarButton();
+    WI._updateDownloadTabBarButton();
 
     WI.updateWindowTitle();
 };
@@ -1577,7 +1534,7 @@ WI._mainResourceDidChange = function(event)
         WI._restoreCookieForOpenTabs(WI.StateRestorationType.Navigation);
     });
 
-    WI._updateDownloadToolbarButton();
+    WI._updateDownloadTabBarButton();
 
     WI.updateWindowTitle();
 };
@@ -1596,6 +1553,8 @@ WI._restoreCookieForOpenTabs = function(restorationType)
         var tabContentView = tabBarItem.representedObject;
         if (!(tabContentView instanceof WI.TabContentView))
             continue;
+        if (!tabContentView.constructor.shouldSaveTab())
+            continue;
         tabContentView.restoreStateFromCookie(restorationType);
     }
 
@@ -1617,6 +1576,8 @@ WI._saveCookieForOpenTabs = function()
         var tabContentView = tabBarItem.representedObject;
         if (!(tabContentView instanceof WI.TabContentView))
             continue;
+        if (!tabContentView.constructor.shouldSaveTab())
+            continue;
         tabContentView.saveStateToCookie();
     }
 };
@@ -1641,7 +1602,6 @@ WI._windowBlurred = function(event)
 
 WI._windowResized = function(event)
 {
-    WI.toolbar.updateLayout(WI.View.LayoutReason.Resize);
     WI.tabBar.updateLayout(WI.View.LayoutReason.Resize);
     WI._tabBrowserSizeDidChange();
     WI._updateSheetRect();
@@ -1685,12 +1645,6 @@ WI._windowKeyUp = function(event)
     WI._updateModifierKeys(event);
 };
 
-WI._mouseDown = function(event)
-{
-    if (WI.toolbar.element.contains(event.target))
-        WI._toolbarMouseDown(event);
-};
-
 WI._mouseMoved = function(event)
 {
     WI._updateModifierKeys(event);
@@ -1775,16 +1729,18 @@ WI._togglePreviousDockConfiguration = function(event)
 WI._updateDockNavigationItems = function()
 {
     if (WI._dockingAvailable || WI.docked) {
-        WI._closeToolbarButton.hidden = !WI.docked;
-        WI._undockToolbarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Undocked;
-        WI._dockBottomToolbarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Bottom;
-        WI._dockToSideToolbarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Right || WI._dockConfiguration === WI.DockConfiguration.Left;
+        WI._closeTabBarButton.hidden = !WI.docked;
+        WI._undockTabBarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Undocked;
+        WI._dockBottomTabBarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Bottom;
+        WI._dockToSideTabBarButton.hidden = WI._dockConfiguration === WI.DockConfiguration.Right || WI._dockConfiguration === WI.DockConfiguration.Left;
     } else {
-        WI._closeToolbarButton.hidden = true;
-        WI._undockToolbarButton.hidden = true;
-        WI._dockBottomToolbarButton.hidden = true;
-        WI._dockToSideToolbarButton.hidden = true;
+        WI._closeTabBarButton.hidden = true;
+        WI._undockTabBarButton.hidden = true;
+        WI._dockBottomTabBarButton.hidden = true;
+        WI._dockToSideTabBarButton.hidden = true;
     }
+
+    WI._updateTabBarDividers();
 };
 
 WI._tabBrowserSizeDidChange = function()
@@ -1814,7 +1770,6 @@ WI._sidebarWidthDidChange = function(event)
 WI._setupViewHierarchy = function()
 {
     let rootView = WI.View.rootView();
-    rootView.addSubview(WI.toolbar);
     rootView.addSubview(WI.tabBar);
     rootView.addSubview(WI.navigationSidebar);
     rootView.addSubview(WI.tabBrowser);
@@ -1840,20 +1795,6 @@ WI._tabBrowserSelectedTabContentViewDidChange = function(event)
     WI.hideSplitConsole();
 };
 
-WI._toolbarMouseDown = function(event)
-{
-    if (event.ctrlKey)
-        return;
-
-    if (WI._dockConfiguration === WI.DockConfiguration.Right || WI._dockConfiguration === WI.DockConfiguration.Left)
-        return;
-
-    if (WI.docked)
-        WI._dockedResizerMouseDown(event);
-    else
-        WI._moveWindowMouseDown(event);
-};
-
 WI._dockedResizerMouseDown = function(event)
 {
     if (event.button !== 0 || event.ctrlKey)
@@ -1863,8 +1804,7 @@ WI._dockedResizerMouseDown = function(event)
         return;
 
     // Only start dragging if the target is one of the elements that we expect.
-    if (event.target.id !== "docked-resizer" && !event.target.classList.contains("toolbar") &&
-        !event.target.classList.contains("flexible-space") && !event.target.classList.contains("item-section"))
+    if (event.target !== WI._dockedResizerElement)
         return;
 
     event[WI.Popover.EventPreventDismissSymbol] = true;
@@ -1932,54 +1872,6 @@ WI._dockedResizerMouseDown = function(event)
     WI.elementDragStart(resizerElement, dockedResizerDrag, dockedResizerDragEnd, event, WI._dockConfiguration === WI.DockConfiguration.Bottom ? "row-resize" : "col-resize");
 };
 
-WI._moveWindowMouseDown = function(event)
-{
-    console.assert(!WI.docked);
-
-    if (event.button !== 0 || event.ctrlKey)
-        return;
-
-    // Only start dragging if the target is one of the elements that we expect.
-    if (!event.target.classList.contains("toolbar") && !event.target.classList.contains("flexible-space") &&
-        !event.target.classList.contains("item-section"))
-        return;
-
-    event[WI.Popover.EventPreventDismissSymbol] = true;
-
-    if (WI.Platform.name === "mac") {
-        InspectorFrontendHost.startWindowDrag();
-        event.preventDefault();
-        return;
-    }
-
-    var lastScreenX = event.screenX;
-    var lastScreenY = event.screenY;
-
-    function toolbarDrag(event)
-    {
-        if (event.button !== 0)
-            return;
-
-        var x = event.screenX - lastScreenX;
-        var y = event.screenY - lastScreenY;
-
-        InspectorFrontendHost.moveWindowBy(x, y);
-
-        lastScreenX = event.screenX;
-        lastScreenY = event.screenY;
-    }
-
-    function toolbarDragEnd(event)
-    {
-        if (event.button !== 0)
-            return;
-
-        WI.elementDragEnd(event);
-    }
-
-    WI.elementDragStart(event.target, toolbarDrag, toolbarDragEnd, event, "default");
-};
-
 WI._domStorageWasInspected = function(event)
 {
     WI.showStorageTab({initiatorHint: WI.TabBrowser.TabNavigationInitiator.Inspect});
@@ -2008,7 +1900,7 @@ WI._domNodeWasInspected = function(event)
 
 WI._inspectModeStateChanged = function(event)
 {
-    WI._inspectModeToolbarButton.activated = WI.domManager.inspectModeEnabled;
+    WI._inspectModeTabBarButton.activated = WI.domManager.inspectModeEnabled;
 };
 
 WI._toggleInspectMode = function(event)
@@ -2016,7 +1908,7 @@ WI._toggleInspectMode = function(event)
     WI.domManager.inspectModeEnabled = !WI.domManager.inspectModeEnabled;
 };
 
-WI._handleDeviceSettingsToolbarButtonClicked = function(event)
+WI._handleDeviceSettingsTabBarButtonClicked = function(event)
 {
     if (WI._deviceSettingsPopover) {
         WI._deviceSettingsPopover.dismiss();
@@ -2027,7 +1919,7 @@ WI._handleDeviceSettingsToolbarButtonClicked = function(event)
     let target = WI.assumingMainTarget();
 
     function updateActivatedState() {
-        WI._deviceSettingsToolbarButton.activated = WI._overridenDeviceUserAgent || WI._overridenDeviceSettings.size > 0;
+        WI._deviceSettingsTabBarButton.activated = WI._overridenDeviceUserAgent || WI._overridenDeviceSettings.size > 0;
     }
 
     function applyOverriddenUserAgent(value, force) {
@@ -2105,10 +1997,10 @@ WI._handleDeviceSettingsToolbarButtonClicked = function(event)
     }
 
     function calculateTargetFrame() {
-        return WI.Rect.rectFromClientRect(WI._deviceSettingsToolbarButton.element.getBoundingClientRect());
+        return WI.Rect.rectFromClientRect(WI._deviceSettingsTabBarButton.element.getBoundingClientRect()).pad(2);
     }
 
-    const preferredEdges = [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_X, WI.RectEdge.MAX_X];
+    const preferredEdges = [WI.RectEdge.MAX_Y, WI.RectEdge.MAX_X];
 
     WI._deviceSettingsPopover = new WI.Popover(WI);
     WI._deviceSettingsPopover.windowResizeHandler = function(event) {
@@ -2315,7 +2207,7 @@ WI._reloadPageFromOrigin = function(event)
     target.PageAgent.reload.invoke({ignoreCache: true});
 };
 
-WI._reloadToolbarButtonClicked = function(event)
+WI._reloadTabBarButtonClicked = function(event)
 {
     if (InspectorFrontendHost.inspectionLevel > 1) {
         WI._reloadInspectedInspector();
@@ -2327,29 +2219,103 @@ WI._reloadToolbarButtonClicked = function(event)
     target.PageAgent.reload.invoke({ignoreCache: WI.modifierKeys.shiftKey});
 };
 
-WI._updateReloadToolbarButton = function()
+WI._updateReloadTabBarButton = function()
 {
-    WI._reloadToolbarButton.hidden = !InspectorBackend.hasDomain("Page");
+    if (!WI._reloadTabBarButton)
+        return;
+
+    WI._reloadTabBarButton.hidden = !InspectorBackend.hasDomain("Page");
+    WI._updateTabBarDividers();
 };
 
-WI._updateDownloadToolbarButton = function()
+WI._updateDownloadTabBarButton = function()
 {
+    if (!WI._reloadTabBarButton)
+        return;
+
     if (!InspectorBackend.hasDomain("Page")) {
-        WI._downloadToolbarButton.hidden = true;
+        WI._downloadTabBarButton.hidden = true;
+        WI._updateTabBarDividers();
         return;
     }
 
     if (WI._downloadingPage) {
-        WI._downloadToolbarButton.enabled = false;
+        WI._downloadTabBarButton.enabled = false;
         return;
     }
 
-    WI._downloadToolbarButton.enabled = WI.canArchiveMainFrame();
+    WI._downloadTabBarButton.enabled = WI.canArchiveMainFrame();
 };
 
-WI._updateInspectModeToolbarButton = function()
+WI._updateInspectModeTabBarButton = function()
 {
-    WI._inspectModeToolbarButton.hidden = !InspectorBackend.hasDomain("DOM");
+    WI._inspectModeTabBarButton.hidden = !InspectorBackend.hasDomain("DOM");
+    WI._updateTabBarDividers();
+};
+
+WI._updateTabBarDividers = function()
+{
+    let closeHidden = WI._closeTabBarButton.hidden;
+    let dockToSideHidden = WI._dockToSideTabBarButton.hidden;
+    let dockBottomHidden = WI._dockBottomTabBarButton.hidden;
+    let undockHidden = WI._undockTabBarButton.hidden;
+
+    let inspectModeHidden = WI._inspectModeTabBarButton.hidden;
+    let deviceSettingsHidden = WI._deviceSettingsTabBarButton && WI._deviceSettingsTabBarButton.hidden;
+    let reloadHidden = WI._reloadTabBarButton && WI._reloadTabBarButton.hidden;
+    let downloadHidden = WI._downloadTabBarButton && WI._downloadTabBarButton.hidden;
+
+    let warningsHidden = WI._consoleWarningsTabBarButton.hidden;
+    let errorsHidden = WI._consoleErrorsTabBarButton.hidden;
+
+    // Hide the divider if everything to the left is hidden OR if everything to the right is hidden.
+    WI._consoleDividerNavigationItem.hidden = (closeHidden && dockToSideHidden && dockBottomHidden && undockHidden && inspectModeHidden && deviceSettingsHidden && reloadHidden && downloadHidden) || (warningsHidden && errorsHidden);
+
+    WI.tabBar.needsLayout();
+};
+
+WI._updateConsoleTabBarButtons = function()
+{
+    function pulse(element) {
+        // We need to force a style invalidation in the case where we already
+        // were animating this item after we've removed the pulsing CSS class.
+        if (element.classList.contains("pulsing")) {
+            element.classList.remove("pulsing");
+            element.recalculateStyles();
+        } else {
+            element.addEventListener("animationend", () => {
+                element.classList.remove("pulsing");
+            }, {once: true});
+        }
+
+        element.classList.add("pulsing");
+    }
+    let warningCount = WI.consoleManager.warningCount;
+    if (warningCount) {
+        let warningFormat = (warningCount === 1) ? WI.UIString("Click to show %d warning in the Console") : WI.UIString("Click to show %d warnings in the Console");
+        WI._consoleWarningsTabBarButton.tooltip = warningFormat.format(warningCount);
+        WI._consoleWarningsTabBarButton.hidden = false;
+
+        if (warningCount !== WI._consoleWarningsTabBarButton.__lastWarningCount)
+            pulse(WI._consoleWarningsTabBarButton.element);
+    } else
+        WI._consoleWarningsTabBarButton.hidden = true;
+
+    let errorCount = WI.consoleManager.errorCount;
+    if (errorCount) {
+        let errorFormat = (errorCount === 1) ? WI.UIString("Click to show %d error in the Console") : WI.UIString("Click to show %d errors in the Console");
+        WI._consoleErrorsTabBarButton.tooltip = errorFormat.format(errorCount);
+        WI._consoleErrorsTabBarButton.hidden = false;
+
+        if (errorCount !== WI._consoleErrorsTabBarButton.__lastErrorCount)
+            pulse(WI._consoleErrorsTabBarButton.element);
+    } else
+        WI._consoleErrorsTabBarButton.hidden = true;
+
+    WI._updateTabBarDividers();
+
+    WI._consoleWarningsTabBarButton.__lastWarningCount = warningCount;
+    WI._consoleErrorsTabBarButton.__lastErrorCount = errorCount;
 };
 
 WI._showConsoleTab = function(event)
@@ -2706,14 +2672,9 @@ WI.setLayoutDirection = function(value)
     InspectorFrontendHost.reopen();
 };
 
-WI._showNewTabFromShortcut = function()
-{
-    WI.showNewTabTab({initiatorHint: WI.TabBrowser.TabNavigationInitiator.KeyboardShortcut});
-}
-
 WI._showTabAtIndexFromShortcut = function(i)
 {
-    if (i <= WI.tabBar.tabBarItems.length) {
+    if (i <= WI.tabBar.tabCount) {
         WI.tabBar.selectTabBarItem(i - 1, {
             initiatorHint: WI.TabBrowser.TabNavigationInitiator.KeyboardShortcut,
         });
@@ -3163,12 +3124,12 @@ WI.revertDOMChanges = function(domChanges)
 WI.archiveMainFrame = function()
 {
     WI._downloadingPage = true;
-    WI._updateDownloadToolbarButton();
+    WI._updateDownloadTabBarButton();
 
     let target = WI.assumingMainTarget();
     target.PageAgent.archive((error, data) => {
         WI._downloadingPage = false;
-        WI._updateDownloadToolbarButton();
+        WI._updateDownloadTabBarButton();
 
         if (error)
             return;
index 21305b7..99d7ae8 100644 (file)
@@ -218,7 +218,6 @@ WI.settings = {
 
     // Experimental
     experimentalEnablePreviewFeatures: new WI.Setting("experimental-enable-preview-features", true),
-    experimentalEnableNewTabBar: new WI.Setting("experimental-enable-new-tab-bar", false),
     experimentalEnableStylesJumpToEffective: new WI.Setting("experimental-styles-jump-to-effective", false),
 
     // Protocol
index d90e9aa..82fbbf1 100644 (file)
@@ -30,8 +30,11 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
     {
         super();
 
+        this._warningCount = 0;
+        this._errorCount = 0;
         this._issues = [];
 
+        this._lastMessageLevel = null;
         this._clearMessagesRequested = false;
         this._isNewPageOrReload = false;
         this._remoteObjectsToRelease = null;
@@ -62,6 +65,8 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
 
     // Public
 
+    get warningCount() { return this._warningCount; }
+    get errorCount() { return this._errorCount; }
     get customLoggingChannels() { return this._customLoggingChannels; }
     get logChannelSources() { return this._loggingChannelSources; }
 
@@ -96,9 +101,11 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
 
         let message = new WI.ConsoleMessage(target, source, level, text, type, url, line, column, repeatCount, parameters, stackTrace, null);
 
+        this._incrementMessageLevelCount(message.level, message.repeatCount);
+
         this.dispatchEventToListeners(WI.ConsoleManager.Event.MessageAdded, {message});
 
-        if (message.level === "warning" || message.level === "error") {
+        if (message.level === WI.ConsoleMessage.MessageLevel.Warning || message.level === WI.ConsoleMessage.MessageLevel.Error) {
             let issue = new WI.IssueMessage(message);
             this._issues.push(issue);
 
@@ -120,8 +127,12 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
             // Frontend requested "clear console" and Backend successfully completed the request.
             this._clearMessagesRequested = false;
 
+            this._warningCount = 0;
+            this._errorCount = 0;
             this._issues = [];
 
+            this._lastMessageLevel = null;
+
             this.dispatchEventToListeners(WI.ConsoleManager.Event.Cleared);
         } else {
             // Received an unrequested clear console event.
@@ -134,6 +145,8 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
 
     messageRepeatCountUpdated(count)
     {
+        this._incrementMessageLevelCount(this._lastMessageLevel, 1);
+
         this.dispatchEventToListeners(WI.ConsoleManager.Event.PreviousMessageRepeatCountUpdated, {count});
     }
 
@@ -169,6 +182,20 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
 
     // Private
 
+    _incrementMessageLevelCount(level, count)
+    {
+        switch (level) {
+        case WI.ConsoleMessage.MessageLevel.Warning:
+            this._warningCount += count;
+            break;
+        case WI.ConsoleMessage.MessageLevel.Error:
+            this._errorCount += count;
+            break;
+        }
+
+        this._lastMessageLevel = level;
+    }
+
     _delayedMessagesCleared()
     {
         if (this._isNewPageOrReload) {
@@ -178,8 +205,12 @@ WI.ConsoleManager = class ConsoleManager extends WI.Object
                 return;
         }
 
+        this._warningCount = 0;
+        this._errorCount = 0;
         this._issues = [];
 
+        this._lastMessageLevel = null;
+
         // A console.clear() or command line clear() happened.
         this.dispatchEventToListeners(WI.ConsoleManager.Event.Cleared);
     }
index 12a1232..826fc15 100644 (file)
@@ -56,7 +56,7 @@ WI.runBootstrapOperations = function() {
     const DumpMessagesState = {Off: "off", Filtering: "filtering", Everything: "everything"};
     const dumpMessagesToolTip = WI.unlocalizedString("Enable dump inspector messages to console.\nShift-click to dump all inspector messages with no filtering.");
     const dumpMessagesActivatedToolTip = WI.unlocalizedString("Disable dump inspector messages to console");
-    let dumpMessagesToolbarItem = new WI.ActivateButtonToolbarItem("dump-messages", dumpMessagesToolTip, dumpMessagesActivatedToolTip, "Images/Console.svg");
+    let dumpMessagesTabBarNavigationItem = new WI.ActivateButtonNavigationItem("dump-messages", dumpMessagesToolTip, dumpMessagesActivatedToolTip, "Images/Console.svg");
 
     function dumpMessagesCurrentState() {
         if (!InspectorBackend.dumpInspectorProtocolMessages)
@@ -72,27 +72,26 @@ WI.runBootstrapOperations = function() {
         case DumpMessagesState.Off:
             InspectorBackend.dumpInspectorProtocolMessages = false;
             InspectorBackend.filterMultiplexingBackendInspectorProtocolMessages = false;
-            dumpMessagesToolbarItem.activated = false;
-            dumpMessagesToolbarItem.element.style.removeProperty("color");
+            dumpMessagesTabBarNavigationItem.activated = false;
+            dumpMessagesTabBarNavigationItem.element.style.removeProperty("color");
             break;
         case DumpMessagesState.Filtering:
             InspectorBackend.dumpInspectorProtocolMessages = true;
             InspectorBackend.filterMultiplexingBackendInspectorProtocolMessages = true;
-            dumpMessagesToolbarItem.activated = true;
-            dumpMessagesToolbarItem.element.style.removeProperty("color");
+            dumpMessagesTabBarNavigationItem.activated = true;
+            dumpMessagesTabBarNavigationItem.element.style.removeProperty("color");
             break;
         case DumpMessagesState.Everything:
             InspectorBackend.dumpInspectorProtocolMessages = true;
             InspectorBackend.filterMultiplexingBackendInspectorProtocolMessages = false;
-            dumpMessagesToolbarItem.activated = true;
-            dumpMessagesToolbarItem.element.style.color = "rgb(164, 41, 154)";
+            dumpMessagesTabBarNavigationItem.activated = true;
+            dumpMessagesTabBarNavigationItem.element.style.color = "rgb(164, 41, 154)";
             break;
         }
         ignoreChangesToState = false;
     }
 
-    WI.toolbar.addToolbarItem(dumpMessagesToolbarItem, WI.Toolbar.Section.CenterRight);
-    dumpMessagesToolbarItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+    dumpMessagesTabBarNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
         let nextState;
         switch (dumpMessagesCurrentState()) {
         case DumpMessagesState.Off:
@@ -117,13 +116,19 @@ WI.runBootstrapOperations = function() {
     // Next Level Inspector.
     let inspectionLevel = InspectorFrontendHost.inspectionLevel;
     const inspectInspectorToolTip = WI.unlocalizedString("Open Web Inspector [%d]").format(inspectionLevel + 1);
-    let inspectInspectorToolbarItem = new WI.ButtonToolbarItem("inspect-inspector", inspectInspectorToolTip);
-    WI.toolbar.addToolbarItem(inspectInspectorToolbarItem, WI.Toolbar.Section.CenterRight);
-    inspectInspectorToolbarItem.element.textContent = inspectionLevel + 1;
-    inspectInspectorToolbarItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
+    let inspectInspectorTabBarNavigationItem = new WI.ButtonNavigationItem("inspect-inspector", inspectInspectorToolTip);
+    inspectInspectorTabBarNavigationItem.element.textContent = inspectionLevel + 1;
+    inspectInspectorTabBarNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, () => {
         InspectorFrontendHost.inspectInspector();
     });
 
+    let groupNavigationItem = new WI.GroupNavigationItem([
+        dumpMessagesTabBarNavigationItem,
+        inspectInspectorTabBarNavigationItem,
+    ]);
+    WI.tabBar.addNavigationItemAfter(groupNavigationItem);
+
+
     function setFocusDebugOutline() {
         document.body.classList.toggle("focus-debug", WI.settings.debugOutlineFocusedElement.value);
     }
@@ -133,8 +138,8 @@ WI.runBootstrapOperations = function() {
     setFocusDebugOutline();
 
     function updateDebugUI() {
-        dumpMessagesToolbarItem.hidden = !WI.showDebugUISetting.value;
-        inspectInspectorToolbarItem.hidden = !WI.showDebugUISetting.value;
+        groupNavigationItem.hidden = !WI.showDebugUISetting.value;
+        WI.tabBar.needsLayout();
     }
 
     WI.showDebugUISetting.addEventListener(WI.Setting.Event.Changed, () => {
diff --git a/Source/WebInspectorUI/UserInterface/Images/NewTab.svg b/Source/WebInspectorUI/UserInterface/Images/NewTab.svg
deleted file mode 100644 (file)
index 48c6f22..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright © 2015 Apple Inc. All rights reserved. -->
-<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
-    <rect fill="none" stroke="currentColor" x="0.5" y="0.5" width="15" height="15" rx="2"/>
-    <path fill="none" stroke="currentColor" d="M 8 3 L 8 13 M 3 8 L 13 8"/>
-</svg>
diff --git a/Source/WebInspectorUI/UserInterface/Images/NewTabPlus.svg b/Source/WebInspectorUI/UserInterface/Images/NewTabPlus.svg
deleted file mode 100644 (file)
index 2616a8a..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright © 2015 Apple Inc. All rights reserved. -->
-<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 15 15">
-    <path fill="none" stroke="currentColor" d="M 7.5 2 V 13 M 2 7.5 H 13"/>
-</svg>
diff --git a/Source/WebInspectorUI/UserInterface/Images/SearchResults.svg b/Source/WebInspectorUI/UserInterface/Images/SearchResults.svg
deleted file mode 100644 (file)
index 2082c24..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright © 2015 Apple Inc. All rights reserved. -->
-<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
-    <rect fill="none" stroke="currentColor" x="0.5" y="0.5" width="15" height="15" rx="2"/>
-    <circle fill="none" stroke="currentColor" cx="7" cy="7" r="3"/>
-    <path fill="none" stroke="currentColor" d="M 9.5 9.5 L 12.5 12.5"/>
-</svg>
diff --git a/Source/WebInspectorUI/UserInterface/Images/SourcesPaused.svg b/Source/WebInspectorUI/UserInterface/Images/SourcesPaused.svg
new file mode 100644 (file)
index 0000000..e9bc547
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright © 2020 Apple Inc. All rights reserved. -->
+<svg xmlns="http://www.w3.org/2000/svg" id="root" version="1.1" viewBox="0 0 16 16">
+    <path fill="none" stroke="currentColor" d="M 7.7 14.5 2.5 14.5 2.5 1.5 9.5 1.5 13.5 5.5 13.5 8.8"/>
+    <path fill="currentColor" d="M 9.0 3.0 L 9.0 6.0 L 12.0 6.0 Z"/>
+    <circle fill="none" cx="10.5" cy="11.5" r="4" stroke="currentColor"/>
+    <path stroke="currentColor" d="M 9.5 9.5 L 9.5 13.5 M 11.5 9.5 L 11.5 13.5"/>
+</svg>
index 8bd92d9..c496094 100644 (file)
@@ -47,7 +47,6 @@
     <link rel="stylesheet" href="Views/BreakpointPopoverController.css">
     <link rel="stylesheet" href="Views/BreakpointTreeElement.css">
     <link rel="stylesheet" href="Views/ButtonNavigationItem.css">
-    <link rel="stylesheet" href="Views/ButtonToolbarItem.css">
     <link rel="stylesheet" href="Views/CPUTimelineOverviewGraph.css">
     <link rel="stylesheet" href="Views/CPUTimelineView.css">
     <link rel="stylesheet" href="Views/CPUUsageCombinedView.css">
@@ -80,7 +79,6 @@
     <link rel="stylesheet" href="Views/ContentBrowserTabContentView.css">
     <link rel="stylesheet" href="Views/ContentView.css">
     <link rel="stylesheet" href="Views/ContentViewContainer.css">
-    <link rel="stylesheet" href="Views/ControlToolbarItem.css">
     <link rel="stylesheet" href="Views/CookieStorageContentView.css">
     <link rel="stylesheet" href="Views/DOMBreakpointTreeElement.css">
     <link rel="stylesheet" href="Views/DOMEventsBreakdownView.css">
     <link rel="stylesheet" href="Views/DOMStorageContentView.css">
     <link rel="stylesheet" href="Views/DOMTreeContentView.css">
     <link rel="stylesheet" href="Views/DOMTreeOutline.css">
-    <link rel="stylesheet" href="Views/DashboardContainerView.css">
     <link rel="stylesheet" href="Views/DataGrid.css">
     <link rel="stylesheet" href="Views/DatabaseContentView.css">
     <link rel="stylesheet" href="Views/DatabaseTableContentView.css">
-    <link rel="stylesheet" href="Views/DebuggerDashboardView.css">
-    <link rel="stylesheet" href="Views/DefaultDashboardView.css">
     <link rel="stylesheet" href="Views/DetailsSection.css">
     <link rel="stylesheet" href="Views/DividerNavigationItem.css">
     <link rel="stylesheet" href="Views/DropZoneView.css">
     <link rel="stylesheet" href="Views/NetworkTableContentView.css">
     <link rel="stylesheet" href="Views/NetworkTimelineOverviewGraph.css">
     <link rel="stylesheet" href="Views/NetworkTimelineView.css">
-    <link rel="stylesheet" href="Views/NewTabContentView.css">
     <link rel="stylesheet" href="Views/ObjectPreviewView.css">
     <link rel="stylesheet" href="Views/ObjectTreeArrayIndexTreeElement.css">
     <link rel="stylesheet" href="Views/ObjectTreeMapEntryTreeElement.css">
     <link rel="stylesheet" href="Views/TimelineTabContentView.css">
     <link rel="stylesheet" href="Views/TimelineView.css">
     <link rel="stylesheet" href="Views/TitleView.css">
-    <link rel="stylesheet" href="Views/Toolbar.css">
     <link rel="stylesheet" href="Views/TreeElementStatusButton.css">
     <link rel="stylesheet" href="Views/TreeOutline.css">
     <link rel="stylesheet" href="Views/TypeTokenView.css">
     <script src="Models/DOMTree.js"></script>
     <script src="Models/DatabaseObject.js"></script>
     <script src="Models/DatabaseTableObject.js"></script>
-    <script src="Models/DebuggerDashboard.js"></script>
     <script src="Models/DebuggerData.js"></script>
-    <script src="Models/DefaultDashboard.js"></script>
     <script src="Models/EventBreakpoint.js"></script>
     <script src="Models/ExecutionContext.js"></script>
     <script src="Models/ExecutionContextList.js"></script>
     <script src="Views/TreeOutline.js"></script>
     <script src="Views/TreeOutlineGroup.js"></script>
 
-    <script src="Views/LegacyTabBar.js"></script>
-
     <script src="Views/ButtonNavigationItem.js"></script>
     <script src="Views/DatabaseUserQueryViewBase.js"></script>
     <script src="Views/DatabaseUserQueryErrorView.js"></script>
     <script src="Views/FolderizedTreeElement.js"></script>
     <script src="Views/NetworkDetailView.js"></script>
     <script src="Views/NetworkTabContentView.js"></script>
-    <script src="Views/NewTabContentView.js"></script>
     <script src="Views/ObjectTreeBaseTreeElement.js"></script>
     <script src="Views/SourceCodeTreeElement.js"></script>
     <script src="Views/StorageTreeElement.js"></script>
     <script src="Views/LocalRemoteObjectContentView.js"></script>
 
     <script src="Views/ActivateButtonNavigationItem.js"></script>
-    <script src="Views/ActivateButtonToolbarItem.js"></script>
     <script src="Views/AnimationCollectionContentView.js"></script>
     <script src="Views/AnimationContentView.js"></script>
     <script src="Views/AnimationDetailsSidebarPanel.js"></script>
     <script src="Views/BoxModelDetailsSectionRow.js"></script>
     <script src="Views/BreakpointActionView.js"></script>
     <script src="Views/BreakpointTreeElement.js"></script>
-    <script src="Views/ButtonToolbarItem.js"></script>
     <script src="Views/CPUTimelineOverviewGraph.js"></script>
     <script src="Views/CPUTimelineView.js"></script>
     <script src="Views/CPUUsageCombinedView.js"></script>
     <script src="Views/ContentViewContainer.js"></script>
     <script src="Views/ContextMenu.js"></script>
     <script src="Views/ContextMenuUtilities.js"></script>
-    <script src="Views/ControlToolbarItem.js"></script>
     <script src="Views/CookieStorageContentView.js"></script>
     <script src="Views/CookieStorageTreeElement.js"></script>
     <script src="Views/DOMBreakpointTreeElement.js"></script>
     <script src="Views/DOMTreeElementPathComponent.js"></script>
     <script src="Views/DOMTreeOutline.js"></script>
     <script src="Views/DOMTreeUpdater.js"></script>
-    <script src="Views/DashboardContainerView.js"></script>
-    <script src="Views/DashboardView.js"></script>
     <script src="Views/DatabaseContentView.js"></script>
     <script src="Views/DatabaseHostTreeElement.js"></script>
     <script src="Views/DatabaseTableContentView.js"></script>
     <script src="Views/DatabaseTableTreeElement.js"></script>
     <script src="Views/DatabaseTreeElement.js"></script>
-    <script src="Views/DebuggerDashboardView.js"></script>
-    <script src="Views/DefaultDashboardView.js"></script>
     <script src="Views/DividerNavigationItem.js"></script>
     <script src="Views/DropZoneView.js"></script>
     <script src="Views/EditableDataGridNode.js"></script>
     <script src="Views/ShaderProgramContentView.js"></script>
     <script src="Views/ShaderProgramTreeElement.js"></script>
     <script src="Views/Sidebar.js"></script>
-    <script src="Views/SizesToFitNavigationBar.js"></script>
     <script src="Views/Slider.js"></script>
     <script src="Views/SoftContextMenu.js"></script>
     <script src="Views/SourceCodeTextEditor.js"></script>
     <script src="Views/TimelineRuler.js"></script>
     <script src="Views/TitleView.js"></script>
     <script src="Views/ToggleButtonNavigationItem.js"></script>
-    <script src="Views/Toolbar.js"></script>
     <script src="Views/TreeElementStatusButton.js"></script>
     <script src="Views/TypeTokenView.js"></script>
     <script src="Views/TypeTreeElement.js"></script>
 </head>
 <body>
 <div id="docked-resizer"></div>
-<div id="toolbar"></div>
+<div id="undocked-title-area"></div>
 <div id="tab-bar"></div>
 <div id="main">
     <div id="content">
diff --git a/Source/WebInspectorUI/UserInterface/Models/DebuggerDashboard.js b/Source/WebInspectorUI/UserInterface/Models/DebuggerDashboard.js
deleted file mode 100644 (file)
index 4411b10..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2014 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DebuggerDashboard = class DebuggerDashboard
-{
-};
diff --git a/Source/WebInspectorUI/UserInterface/Models/DefaultDashboard.js b/Source/WebInspectorUI/UserInterface/Models/DefaultDashboard.js
deleted file mode 100644 (file)
index c8cb9f5..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * Copyright (C) 2013, 2014 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DefaultDashboard = class DefaultDashboard extends WI.Object
-{
-    constructor()
-    {
-        super();
-
-        this._waitingForFirstMainResourceToStartTrackingSize = true;
-
-        // Necessary event required to track page load time and resource sizes.
-        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
-        WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingStateChanged, this._handleTimelineCapturingStateChanged, this);
-
-        // Necessary events required to track load of resources.
-        WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceWasAdded, this);
-        WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._resourceWasAdded, this);
-        WI.networkManager.addEventListener(WI.NetworkManager.Event.FrameWasAdded, this._frameWasAdded, this);
-
-        // Necessary events required to track console messages.
-        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._consoleWasCleared, this);
-        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.MessageAdded, this._consoleMessageAdded, this);
-        WI.consoleManager.addEventListener(WI.ConsoleManager.Event.PreviousMessageRepeatCountUpdated, this._consoleMessageWasRepeated, this);
-
-        // FIXME: This is working around the order of events. Normal page navigation
-        // triggers a MainResource change and then a MainFrame change. Page Transition
-        // triggers a MainFrame change then a MainResource change.
-        this._transitioningPageTarget = false;
-
-        WI.notifications.addEventListener(WI.Notification.TransitionPageTarget, this._transitionPageTarget, this);
-
-        this._resourcesCount = 0;
-        this._resourcesSize = 0;
-        this._time = 0;
-        this._logs = 0;
-        this._errors = 0;
-        this._issues = 0;
-    }
-
-    // Public
-
-    get resourcesCount()
-    {
-        return this._resourcesCount;
-    }
-
-    set resourcesCount(value)
-    {
-        this._resourcesCount = value;
-        this._dataDidChange();
-    }
-
-    get resourcesSize()
-    {
-        return this._resourcesSize;
-    }
-
-    set resourcesSize(value)
-    {
-        this._resourcesSize = value;
-        this._dataDidChange();
-    }
-
-    get time()
-    {
-        return this._time;
-    }
-
-    set time(value)
-    {
-        this._time = value;
-        this._dataDidChange();
-    }
-
-    get logs()
-    {
-        return this._logs;
-    }
-
-    set logs(value)
-    {
-        this._logs = value;
-        this._dataDidChange();
-    }
-
-    get errors()
-    {
-        return this._errors;
-    }
-
-    set errors(value)
-    {
-        this._errors = value;
-        this._dataDidChange();
-    }
-
-    get issues()
-    {
-        return this._issues;
-    }
-
-    set issues(value)
-    {
-        this._issues = value;
-        this._dataDidChange();
-    }
-
-    // Private
-
-    _dataDidChange()
-    {
-        this.dispatchEventToListeners(WI.DefaultDashboard.Event.DataDidChange);
-    }
-
-    _mainResourceDidChange(event)
-    {
-        console.assert(event.target instanceof WI.Frame);
-
-        if (!event.target.isMainFrame())
-            return;
-
-        if (!this._transitioningPageTarget) {
-            this._time = 0;
-            this._resourcesCount = 1;
-            this._resourcesSize = WI.networkManager.mainFrame.mainResource.size || 0;
-        }
-
-        // We should only track resource sizes on fresh loads.
-        if (this._waitingForFirstMainResourceToStartTrackingSize) {
-            this._waitingForFirstMainResourceToStartTrackingSize = false;
-            WI.Resource.addEventListener(WI.Resource.Event.SizeDidChange, this._resourceSizeDidChange, this);
-        }
-
-        this._dataDidChange();
-
-        if (!this._transitioningPageTarget)
-            this._startUpdatingTime();
-
-        if (this._transitioningPageTarget)
-            this._transitioningPageTarget = false;
-    }
-
-    _handleTimelineCapturingStateChanged(event)
-    {
-        if (WI.timelineManager.isCapturing())
-            return;
-
-        // If recording stops, we should stop the timer if it hasn't stopped already.
-        this._stopUpdatingTime();
-    }
-
-    _resourceWasAdded(event)
-    {
-        ++this.resourcesCount;
-    }
-
-    _frameWasAdded(event)
-    {
-        ++this.resourcesCount;
-    }
-
-    _resourceSizeDidChange(event)
-    {
-        if (event.target.urlComponents.scheme === "data")
-            return;
-
-        let delta = event.target.size - event.data.previousSize;
-        console.assert(!isNaN(delta), "Resource size change should never be NaN.");
-        this.resourcesSize += delta;
-    }
-
-    _startUpdatingTime()
-    {
-        this._stopUpdatingTime();
-
-        this.time = 0;
-
-        this._timelineBaseTime = Date.now();
-        this._timeIntervalDelay = 50;
-        this._timeIntervalIdentifier = setInterval(this._updateTime.bind(this), this._timeIntervalDelay);
-    }
-
-    _stopUpdatingTime()
-    {
-        if (!this._timeIntervalIdentifier)
-            return;
-
-        clearInterval(this._timeIntervalIdentifier);
-        this._timeIntervalIdentifier = undefined;
-    }
-
-    _updateTime()
-    {
-        var duration = Date.now() - this._timelineBaseTime;
-
-        var timeIntervalDelay = this._timeIntervalDelay;
-        if (duration >= 1000) // 1 second
-            timeIntervalDelay = 100;
-        else if (duration >= 60000) // 60 seconds
-            timeIntervalDelay = 1000;
-        else if (duration >= 3600000) // 1 minute
-            timeIntervalDelay = 10000;
-
-        if (timeIntervalDelay !== this._timeIntervalDelay) {
-            this._timeIntervalDelay = timeIntervalDelay;
-
-            clearInterval(this._timeIntervalIdentifier);
-            this._timeIntervalIdentifier = setInterval(this._updateTime.bind(this), this._timeIntervalDelay);
-        }
-
-        var mainFrame = WI.networkManager.mainFrame;
-        var mainFrameStartTime = mainFrame.mainResource.firstTimestamp;
-        var mainFrameLoadEventTime = mainFrame.loadEventTimestamp;
-
-        if (isNaN(mainFrameStartTime) || isNaN(mainFrameLoadEventTime)) {
-            this.time = duration / 1000;
-            return;
-        }
-
-        this.time = mainFrameLoadEventTime - mainFrameStartTime;
-
-        this._stopUpdatingTime();
-    }
-
-    _consoleMessageAdded(event)
-    {
-        var message = event.data.message;
-        this._lastConsoleMessageType = message.level;
-        this._incrementConsoleMessageType(message.level, message.repeatCount);
-    }
-
-    _consoleMessageWasRepeated(event)
-    {
-        this._incrementConsoleMessageType(this._lastConsoleMessageType, 1);
-    }
-
-    _incrementConsoleMessageType(type, increment)
-    {
-        switch (type) {
-        case WI.ConsoleMessage.MessageLevel.Log:
-        case WI.ConsoleMessage.MessageLevel.Info:
-        case WI.ConsoleMessage.MessageLevel.Debug:
-            this.logs += increment;
-            break;
-        case WI.ConsoleMessage.MessageLevel.Warning:
-            this.issues += increment;
-            break;
-        case WI.ConsoleMessage.MessageLevel.Error:
-            this.errors += increment;
-            break;
-        }
-    }
-
-    _consoleWasCleared(event)
-    {
-        this._logs = 0;
-        this._issues = 0;
-        this._errors = 0;
-        this._dataDidChange();
-    }
-
-    _transitionPageTarget()
-    {
-        this._transitioningPageTarget = true;
-
-        this._time = 0;
-        this._resourcesCount = 0;
-        this._resourcesSize = 0;
-
-        this._dataDidChange();
-    }
-};
-
-WI.DefaultDashboard.Event = {
-    DataDidChange: "default-dashboard-data-did-change"
-};
diff --git a/Source/WebInspectorUI/UserInterface/Views/ActivateButtonToolbarItem.js b/Source/WebInspectorUI/UserInterface/Views/ActivateButtonToolbarItem.js
deleted file mode 100644 (file)
index d57542c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.ActivateButtonToolbarItem = class ActivateButtonToolbarItem extends WI.ActivateButtonNavigationItem
-{
-    constructor(identifier, defaultToolTip, activatedToolTip, image, role)
-    {
-        super(identifier, defaultToolTip, activatedToolTip, image, 16, 16, role);
-    }
-};
index 215dba5..532d0c3 100644 (file)
@@ -27,7 +27,9 @@ WI.AuditTabContentView = class AuditTabContentView extends WI.ContentBrowserTabC
 {
     constructor()
     {
-        super("audit", ["audit"], WI.GeneralTabBarItem.fromTabInfo(WI.AuditTabContentView.tabInfo()), WI.AuditNavigationSidebarPanel);
+        super(AuditTabContentView.tabInfo(), {
+            navigationSidebarPanelConstructor: WI.AuditNavigationSidebarPanel,
+        });
 
         this._startStopShortcut = new WI.KeyboardShortcut(null, WI.KeyboardShortcut.Key.Space, this._handleSpace.bind(this));
         this._startStopShortcut.implicitlyPreventsDefault = false;
@@ -39,6 +41,7 @@ WI.AuditTabContentView = class AuditTabContentView extends WI.ContentBrowserTabC
     static tabInfo()
     {
         return {
+            identifier: AuditTabContentView.Type,
             image: "Images/Audit.svg",
             title: WI.UIString("Audit"),
         };
index e96e24f..9dbee33 100644 (file)
     -webkit-padding-start: 4px;
 }
 
+.tab-bar > .navigation-bar .item.button.image-and-text > span {
+    padding-bottom: 0;
+}
+
 .navigation-bar .item.button.text-only {
     padding: 1px 8px 3px;
     margin: 0 2px; /* WI.ButtonNavigationItem.prototype.get totalMargin */
     color: var(--glyph-color-disabled);
 }
 
+.navigation-bar .item.button > img {
+    width: 100%;
+    height: 100%;
+}
+
+.navigation-bar .item.button.disabled > img {
+    opacity: 0.3;
+}
+
+body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button > img {
+    opacity: 0.6;
+}
+
+body:matches(.window-inactive, .window-docked-inactive) .navigation-bar .item.button.disabled > img {
+    opacity: 0.18;
+}
+
 @media (prefers-color-scheme: dark) {
     .navigation-bar .item.button {
         color: var(--text-color-secondary);
     }
+
+    .navigation-bar .item.button.disabled > img {
+        filter: invert();
+    }
 }
index 52dce82..7beab8c 100644 (file)
@@ -57,6 +57,8 @@ WI.ButtonNavigationItem = class ButtonNavigationItem extends WI.NavigationItem
 
         this.buttonStyle = this._image ? WI.ButtonNavigationItem.Style.Image : WI.ButtonNavigationItem.Style.Text;
 
+        this.imageType = this._image ? WI.ButtonNavigationItem.ImageType.SVG : null;
+
         if (this.buttonStyle === WI.ButtonNavigationItem.Style.Image)
             this.tooltip = toolTipOrLabel;
     }
@@ -132,6 +134,27 @@ WI.ButtonNavigationItem = class ButtonNavigationItem extends WI.NavigationItem
             this.parentNavigationBar.needsLayout();
     }
 
+    get imageType()
+    {
+        return this._imageType;
+    }
+
+    set imageType(imageType)
+    {
+        console.assert(!imageType || Object.values(WI.ButtonNavigationItem.ImageType).includes(imageType), imageType);
+        console.assert(!imageType || (this._buttonStyle === WI.ButtonNavigationItem.Style.Image || this._buttonStyle === WI.ButtonNavigationItem.Style.ImageAndText));
+
+        if (this._imageType === imageType)
+            return;
+
+        this._imageType = imageType;
+
+        this._update();
+
+        if (this.parentNavigationBar)
+            this.parentNavigationBar.needsLayout();
+    }
+
     // Protected
 
     get totalMargin()
@@ -182,10 +205,22 @@ WI.ButtonNavigationItem = class ButtonNavigationItem extends WI.NavigationItem
         if (this._buttonStyle === WI.ButtonNavigationItem.Style.Text)
             this.element.textContent = this._label;
         else {
-            let glyphElement = WI.ImageUtilities.useSVGSymbol(this._image, "glyph");
-            glyphElement.style.width = this._imageWidth + "px";
-            glyphElement.style.height = this._imageHeight + "px";
-            this.element.appendChild(glyphElement);
+            switch (this._imageType) {
+            case null:
+            case WI.ButtonNavigationItem.ImageType.SVG: {
+                let glyphElement = WI.ImageUtilities.useSVGSymbol(this._image, "glyph");
+                glyphElement.style.width = this._imageWidth + "px";
+                glyphElement.style.height = this._imageHeight + "px";
+                this.element.appendChild(glyphElement);
+                break;
+            }
+
+            case WI.ButtonNavigationItem.ImageType.IMG: {
+                let img = this.element.appendChild(document.createElement("img"));
+                img.src = this._image;
+                break;
+            }
+            }
 
             if (this._buttonStyle === WI.ButtonNavigationItem.Style.ImageAndText) {
                 let labelElement = this.element.appendChild(document.createElement("span"));
@@ -204,3 +239,8 @@ WI.ButtonNavigationItem.Style = {
     Text: "text-only",
     ImageAndText: "image-and-text",
 };
+
+WI.ButtonNavigationItem.ImageType = {
+    SVG: "image-type-svg",
+    IMG: "image-type-img",
+};
diff --git a/Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.css b/Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.css
deleted file mode 100644 (file)
index 442818a..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (C) 2013-2017 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.
- */
-
-.toolbar .item.button {
-    align-items: center;
-    justify-content: center;
-
-    margin: 4px;
-    padding: 0 10px;
-
-    color: hsl(0, 0%, 45%);
-    outline-offset: -2px;
-}
-
-.toolbar .item.button:not(.disabled):active {
-    color: hsl(0, 0%, 30%);
-}
-
-.toolbar .item.button:not(.disabled).activate.activated {
-    color: var(--glyph-color-active);
-}
-
-.toolbar .item.button > .glyph {
-    width: 16px;
-    height: 16px;
-}
-
-body.window-inactive .toolbar .item.button {
-    opacity: 0.65;
-}
-
-.toolbar .item.button.disabled {
-    opacity: 0.55 !important;
-}
-
-body.window-inactive .toolbar .item.button.disabled {
-    opacity: 0.35 !important;
-}
-
-@media (prefers-color-scheme: dark) {
-    .toolbar .item.button {
-        color: var(--color-button);
-    }
-
-    .toolbar .item.button:not(.disabled):active {
-        color: var(--color-button-active);
-        background-image: none;
-        background: var(--button-background-color-pressed);
-    }
-
-    body:not(.window-inactive) .toolbar .item.button:not(.disabled).activate.activated > .glyph {
-        filter: brightness(1.35);
-    }
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.js b/Source/WebInspectorUI/UserInterface/Views/ButtonToolbarItem.js
deleted file mode 100644 (file)
index 9e4f6d0..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.ButtonToolbarItem = class ButtonToolbarItem extends WI.ButtonNavigationItem
-{
-    constructor(identifier, toolTip, image, role)
-    {
-        super(identifier, toolTip, image, 16, 16, role);
-    }
-};
index 125986a..f68a9fa 100644 (file)
 
 WI.ConsoleTabContentView = class ConsoleTabContentView extends WI.ContentBrowserTabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.ConsoleTabContentView.tabInfo());
-
-        super(identifier || "console", "console", tabBarItem, null, null, true);
+        super(ConsoleTabContentView.tabInfo(), {disableBackForward: true});
     }
 
     static tabInfo()
     {
         return {
+            identifier: ConsoleTabContentView.Type,
             image: "Images/Console.svg",
             title: WI.UIString("Console"),
         };
index 2d75c0d..bc3d518 100644 (file)
 
 WI.ContentBrowserTabContentView = class ContentBrowserTabContentView extends WI.TabContentView
 {
-    constructor(identifier, styleClassNames, tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward, flexibleNavigationItem)
+    constructor(tabInfo, {navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward, flexibleNavigationItem} = {})
     {
-        if (typeof styleClassNames === "string")
-            styleClassNames = [styleClassNames];
+        super(tabInfo, {navigationSidebarPanelConstructor, detailsSidebarPanelConstructors});
 
-        styleClassNames.push("content-browser");
-
-        var contentBrowser = new WI.ContentBrowser(null, null, disableBackForward, false, flexibleNavigationItem);
-
-        super(identifier, styleClassNames, tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors);
-
-        this._contentBrowser = contentBrowser;
-        this._contentBrowser.delegate = this;
+        const contentBrowserElement = null;
+        const disableFindBanner = false;
+        this._contentBrowser = new WI.ContentBrowser(contentBrowserElement, this, disableBackForward, disableFindBanner, flexibleNavigationItem);
 
         this._ignoreNavigationSidebarPanelCollapsedEvent = false;
         this._ignoreDetailsSidebarPanelCollapsedEvent = false;
         this._ignoreDetailsSidebarPanelSelectedEvent = false;
 
-        this._lastSelectedDetailsSidebarPanelSetting = new WI.Setting(identifier + "-last-selected-details-sidebar-panel", null);
+        this._lastSelectedDetailsSidebarPanelSetting = new WI.Setting(this._identifier + "-last-selected-details-sidebar-panel", null);
 
         this._contentBrowser.addEventListener(WI.ContentBrowser.Event.CurrentRepresentedObjectsDidChange, this._contentBrowserCurrentRepresentedObjectsDidChange, this);
         this._contentBrowser.addEventListener(WI.ContentBrowser.Event.CurrentContentViewDidChange, this._contentBrowserCurrentContentViewDidChange, this);
@@ -52,7 +46,7 @@ WI.ContentBrowserTabContentView = class ContentBrowserTabContentView extends WI.
         // Explicitly update the path for the navigation bar to prevent it from showing up as blank.
         this._contentBrowser.updateHierarchicalPathForCurrentContentView();
 
-        if (navigationSidebarPanelConstructor) {
+        if (this._navigationSidebarPanelConstructor) {
             let showToolTip = WI.UIString("Show the navigation sidebar (%s)").format(WI.navigationSidebarKeyboardShortcut.displayName);
             let hideToolTip = WI.UIString("Hide the navigation sidebar (%s)").format(WI.navigationSidebarKeyboardShortcut.displayName);
             let image = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "Images/ToggleRightSidebar.svg" : "Images/ToggleLeftSidebar.svg";
@@ -68,7 +62,7 @@ WI.ContentBrowserTabContentView = class ContentBrowserTabContentView extends WI.
             WI.navigationSidebar.addEventListener(WI.Sidebar.Event.CollapsedStateDidChange, this._navigationSidebarCollapsedStateDidChange, this);
         }
 
-        if (detailsSidebarPanelConstructors && detailsSidebarPanelConstructors.length) {
+        if (this._detailsSidebarPanelConstructors.length) {
             let showToolTip = WI.UIString("Show the details sidebar (%s)").format(WI.detailsSidebarKeyboardShortcut.displayName);
             let hideToolTip = WI.UIString("Hide the details sidebar (%s)").format(WI.detailsSidebarKeyboardShortcut.displayName);
             let image = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "Images/ToggleLeftSidebar.svg" : "Images/ToggleRightSidebar.svg";
@@ -86,6 +80,8 @@ WI.ContentBrowserTabContentView = class ContentBrowserTabContentView extends WI.
             WI.detailsSidebar.addEventListener(WI.Sidebar.Event.SidebarPanelSelected, this._detailsSidebarPanelSelected, this);
         }
 
+        this.element.classList.add("content-browser");
+
         this.addSubview(this._contentBrowser);
     }
 
diff --git a/Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.css b/Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.css
deleted file mode 100644 (file)
index 490f59a..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013-2017 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.
- */
-
-.toolbar .item.control {
-    align-items: center;
-    justify-content: center;
-
-    padding: 0 2px;
-
-    opacity: 0.5;
-}
-
-.toolbar.small-size .item.control {
-    padding: 2px;
-}
-
-.toolbar .item.control:hover {
-    opacity: 0.75;
-}
-
-.toolbar .item.control:active {
-    opacity: 1;
-}
-
-.toolbar .item.control > .glyph {
-    width: 16px;
-    height: 16px;
-
-    background-repeat: no-repeat;
-    background-position: center center;
-}
-
-.toolbar .item.control:focus {
-    outline: none;
-}
-
-.toolbar .item.control:focus > .glyph {
-    outline: auto -webkit-focus-ring-color;
-}
-
-body.window-inactive .toolbar .item.control {
-    opacity: 0.35;
-}
-
-.toolbar .item.control.disabled {
-    opacity: 0.35 !important;
-}
-
-body.window-inactive .toolbar .item.control.disabled {
-    opacity: 0.2 !important;
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.js b/Source/WebInspectorUI/UserInterface/Views/ControlToolbarItem.js
deleted file mode 100644 (file)
index 3c428c8..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.ControlToolbarItem = class ControlToolbarItem extends WI.ButtonNavigationItem
-{
-    constructor(identifier, toolTip, image, imageWidth, imageHeight)
-    {
-        super(identifier, toolTip, image, imageWidth, imageHeight, false);
-    }
-
-    // Protected
-
-    get additionalClassNames()
-    {
-        return ["control"];
-    }
-};
index 413d06d..c89e9d0 100644 (file)
@@ -59,7 +59,7 @@ body[dir=rtl] .content-view.dom-tree .tree-outline.dom li .status-image {
     fill: var(--breakpoint-color);
 }
 
-body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint {
+body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint {
     stroke: var(--selected-foreground-color);
 }
 
@@ -76,7 +76,7 @@ body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:mat
     stroke: var(--breakpoint-color);
 }
 
-body:not(.window-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree {
+body:not(.window-inactive, .window-docked-inactive) .content-view.dom-tree .tree-outline.dom:focus li:matches(.selected, .hovered) .status-image.breakpoint.subtree {
     stroke: var(--selected-foreground-color);
 }
 
diff --git a/Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.css b/Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.css
deleted file mode 100644 (file)
index c3cba7f..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright (C) 2013-2017 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.
- */
-
-.toolbar .dashboard-container {
-    position: relative;
-    margin: 4px;
-    height: 22px;
-
-    border-radius: 4px;
-    overflow: hidden;
-}
-
-body:matches(.page, .web-page) .toolbar .dashboard-container {
-    width: 36vw;
-    min-width: 350px;
-}
-
-body:not(.page, .web-page) .toolbar .dashboard-container {
-    width: 25vw;
-    min-width: 175px;
-}
-
-.toolbar.collapsed .dashboard-container {
-    min-width: 175px !important;
-    width: 175px !important;
-}
-
-/* Default styles for dashboards */
-.toolbar .dashboard {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    left: 0;
-    right: 0;
-    -webkit-padding-start: 10px;
-    -webkit-padding-end: 5px;
-    animation-duration: 0.4s;
-}
-
-.toolbar .dashboard.visible {
-    z-index: 1; /* Establish a stacking context. */
-}
-
-.toolbar .dashboard:not(.visible) {
-    display: none !important;
-}
-
-.toolbar .dashboard.slide-out-up {
-    animation-name: slide-top-edge;
-    animation-direction: reverse;
-}
-
-.toolbar .dashboard.slide-out-down {
-    animation-name: slide-bottom-edge;
-}
-
-.toolbar .dashboard.slide-in-up {
-    animation-name: slide-bottom-edge;
-    animation-direction: reverse;
-}
-
-.toolbar .dashboard.slide-in-down {
-    animation-name: slide-top-edge;
-}
-
-@keyframes slide-top-edge {
-    from {
-        transform: translateY(-30px);
-    }
-    to {
-        transform: translateY(0);
-    }
-}
-
-@keyframes slide-bottom-edge {
-    from {
-        transform: translateY(0);
-    }
-    to {
-        transform: translateY(30px);
-    }
-}
-
-.dashboard-container .advance-arrow {
-    position: absolute;
-    width: 19px;
-    top: 0;
-    bottom: 0;
-    padding: 4px 0;
-    opacity: 0.6;
-
-    z-index: 2;
-    background-repeat: no-repeat;
-    background-size: 8px;
-    background-image: url(../Images/UpDownArrows.svg);
-
-    transition-property: opacity;
-    transition-duration: 0.2s;
-    background-clip: content-box;
-
-    --dashboard-advance-arrow-offset-end: 0px;
-}
-
-body[dir=ltr] .dashboard-container .advance-arrow {
-    right: var(--dashboard-advance-arrow-offset-end);
-}
-
-body[dir=rtl] .dashboard-container .advance-arrow {
-    left: var(--dashboard-advance-arrow-offset-end);
-}
-
-.dashboard-container .advance-arrow:hover {
-    opacity: 0.8;
-}
-
-.dashboard-container .advance-arrow:active {
-    opacity: 1;
-}
-
-.dashboard-container .advance-arrow.inactive {
-    opacity: 0;
-    pointer-events: none;
-}
-
-.dashboard-container .advance-arrow.advance-forward {
-    top: 0;
-    background-position: 50% 4px;
-}
-
-.dashboard-container .advance-arrow.advance-backward {
-    bottom: 0;
-    background-position: 50% -4px;
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.js b/Source/WebInspectorUI/UserInterface/Views/DashboardContainerView.js
deleted file mode 100644 (file)
index 3973070..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DashboardContainerView = class DashboardContainerView extends WI.Object
-{
-    constructor()
-    {
-        super();
-
-        this._toolbarItem = new WI.NavigationItem("dashboard-container", "group", WI.UIString("Activity Viewer"));
-
-        this._advanceForwardArrowElement = this._toolbarItem.element.appendChild(document.createElement("div"));
-        this._advanceForwardArrowElement.className = "advance-arrow advance-forward";
-        this._advanceBackwardArrowElement = this._toolbarItem.element.appendChild(document.createElement("div"));
-        this._advanceBackwardArrowElement.className = "advance-arrow advance-backward";
-
-        this._advanceForwardArrowElement.addEventListener("click", this._advanceForwardArrowClicked.bind(this));
-        this._advanceBackwardArrowElement.addEventListener("click", this._advanceBackwardArrowClicked.bind(this));
-
-        // Represents currently open dashboards, with the most recent entries appended to the end.
-        this._dashboardStack = [];
-        this._currentIndex = -1;
-
-        this._updateAdvanceArrowVisibility();
-    }
-
-    // Public
-
-    get toolbarItem()
-    {
-        return this._toolbarItem;
-    }
-
-    get currentDashboardView()
-    {
-        if (this._currentIndex === -1)
-            return null;
-
-        return this._dashboardStack[this._currentIndex];
-    }
-
-    showDashboardViewForRepresentedObject(representedObject)
-    {
-        var dashboardView = this._dashboardViewForRepresentedObject(representedObject);
-        if (!dashboardView)
-            return null;
-
-        if (this.currentDashboardView === dashboardView)
-            return dashboardView;
-
-        var index = this._dashboardStack.indexOf(dashboardView);
-        this._showDashboardAtIndex(index);
-        return dashboardView;
-    }
-
-    hideDashboardViewForRepresentedObject(representedObject)
-    {
-        var onlyReturnExistingViews = true;
-        var dashboardView = this._dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews);
-
-        if (this.currentDashboardView !== dashboardView)
-            return;
-
-        console.assert(this._currentIndex > 0);
-        this._showDashboardAtIndex(this._currentIndex - 1);
-    }
-
-    closeDashboardViewForRepresentedObject(representedObject)
-    {
-        var onlyReturnExistingViews = true;
-        var dashboardView = this._dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews);
-        if (!dashboardView)
-            return;
-
-        this._closeDashboardView(dashboardView);
-    }
-
-    // Private
-
-    _advanceForwardArrowClicked()
-    {
-        this._showDashboardAtIndex(this._currentIndex + 1);
-    }
-
-    _advanceBackwardArrowClicked()
-    {
-        this._showDashboardAtIndex(this._currentIndex - 1);
-    }
-
-    _dismissAdvanceArrows()
-    {
-        this._advanceForwardArrowElement.classList.add(WI.DashboardContainerView.InactiveStyleClassName);
-        this._advanceBackwardArrowElement.classList.add(WI.DashboardContainerView.InactiveStyleClassName);
-    }
-
-    _updateAdvanceArrowVisibility()
-    {
-        var canAdvanceForward = this._currentIndex < this._dashboardStack.length - 1;
-        var canAdvanceBackward = this._currentIndex > 0;
-        this._advanceForwardArrowElement.classList.toggle(WI.DashboardContainerView.InactiveStyleClassName, !canAdvanceForward);
-        this._advanceBackwardArrowElement.classList.toggle(WI.DashboardContainerView.InactiveStyleClassName, !canAdvanceBackward);
-    }
-
-    _dashboardViewForRepresentedObject(representedObject, onlyReturnExistingViews)
-    {
-        console.assert(representedObject);
-
-        // Iterate over all known dashboard views and see if any are for this object.
-        for (var dashboardView of this._dashboardStack) {
-            if (dashboardView.representedObject === representedObject)
-                return dashboardView;
-        }
-
-        if (onlyReturnExistingViews)
-            return null;
-
-        // No existing content view found, make a new one.
-        dashboardView = WI.DashboardView.create(representedObject);
-
-        console.assert(dashboardView, "Unknown representedObject", representedObject);
-        if (!dashboardView)
-            return null;
-
-        this._dashboardStack.push(dashboardView);
-        this._toolbarItem.element.appendChild(dashboardView.element);
-
-        return dashboardView;
-    }
-
-    _showDashboardAtIndex(index)
-    {
-        console.assert(index >= 0 && index <= this._dashboardStack.length - 1);
-
-        if (this._currentIndex === index)
-            return;
-
-        var advanceDirection = null;
-        if (this._currentIndex < index)
-            advanceDirection = WI.DashboardContainerView.AdvanceDirection.Forward;
-        else
-            advanceDirection = WI.DashboardContainerView.AdvanceDirection.Backward;
-        var initialDirection = WI.DashboardContainerView.AdvanceDirection.None;
-        var isInitialDashboard = this._currentIndex === -1;
-        if (!isInitialDashboard)
-            this._hideDashboardView(this.currentDashboardView, advanceDirection);
-
-        this._currentIndex = index;
-        this._showDashboardView(this.currentDashboardView, isInitialDashboard ? initialDirection : advanceDirection);
-    }
-
-    _showDashboardView(dashboardView, advanceDirection)
-    {
-        console.assert(dashboardView instanceof WI.DashboardView);
-
-        dashboardView.shown();
-        this._dismissAdvanceArrows();
-
-        var animationClass = null;
-        if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Forward)
-            animationClass = WI.DashboardContainerView.ForwardIncomingDashboardStyleClassName;
-        if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Backward)
-            animationClass = WI.DashboardContainerView.BackwardIncomingDashboardStyleClassName;
-
-        var container = this;
-        dashboardView.element.classList.add(WI.DashboardContainerView.VisibleDashboardStyleClassName);
-
-        function animationEnded(event) {
-            if (event.target !== dashboardView.element)
-                return;
-
-            dashboardView.element.removeEventListener("animationend", animationEnded);
-            dashboardView.element.classList.remove(animationClass);
-            container._updateAdvanceArrowVisibility();
-        }
-
-        if (animationClass) {
-            dashboardView.element.classList.add(animationClass);
-            dashboardView.element.addEventListener("animationend", animationEnded);
-        }
-
-        return dashboardView;
-    }
-
-    _hideDashboardView(dashboardView, advanceDirection, callback)
-    {
-        console.assert(dashboardView instanceof WI.DashboardView);
-        console.assert(this.currentDashboardView === dashboardView);
-
-        dashboardView.hidden();
-        this._dismissAdvanceArrows();
-
-        var animationClass = null;
-        if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Forward)
-            animationClass = WI.DashboardContainerView.ForwardOutgoingDashboardStyleClassName;
-        if (advanceDirection === WI.DashboardContainerView.AdvanceDirection.Backward)
-            animationClass = WI.DashboardContainerView.BackwardOutgoingDashboardStyleClassName;
-
-        var container = this;
-
-        function animationEnded(event) {
-            if (event.target !== dashboardView.element)
-                return;
-
-            dashboardView.element.removeEventListener("animationend", animationEnded);
-            dashboardView.element.classList.remove(animationClass);
-            dashboardView.element.classList.remove(WI.DashboardContainerView.VisibleDashboardStyleClassName);
-            container._updateAdvanceArrowVisibility();
-
-            if (typeof callback === "function")
-                callback();
-        }
-
-        if (animationClass) {
-            dashboardView.element.classList.add(animationClass);
-            dashboardView.element.addEventListener("animationend", animationEnded);
-        } else
-            dashboardView.element.classList.remove(WI.DashboardContainerView.VisibleDashboardStyleClassName);
-    }
-
-    _closeDashboardView(dashboardView)
-    {
-        console.assert(dashboardView instanceof WI.DashboardView);
-
-        function dissociateDashboardView() {
-            dashboardView.closed();
-            dashboardView.element.parentNode.removeChild(dashboardView.element);
-        }
-
-        var index = this._dashboardStack.indexOf(dashboardView);
-
-        if (this.currentDashboardView === dashboardView) {
-            var direction = WI.DashboardContainerView.AdvanceDirection.Backward;
-            this._hideDashboardView(this.currentDashboardView, direction, dissociateDashboardView);
-            this._dashboardStack.splice(index, 1);
-            --this._currentIndex;
-            this._showDashboardView(this.currentDashboardView, direction);
-            return;
-        }
-
-        this._dashboardStack.splice(index, 1);
-        if (this._currentIndex > index)
-            --this._currentIndex;
-        dissociateDashboardView.call(this);
-
-        this._updateAdvanceArrowVisibility();
-    }
-};
-
-WI.DashboardContainerView.VisibleDashboardStyleClassName = "visible";
-WI.DashboardContainerView.InactiveStyleClassName = "inactive";
-
-WI.DashboardContainerView.AdvanceDirection = {
-    Forward: Symbol("dashboard-container-view-advance-direction-forward"),
-    Backward: Symbol("dashboard-container-view-advance-direction-backward"),
-    None: Symbol("dashboard-container-view-advance-direction-none")
-};
-
-WI.DashboardContainerView.ForwardIncomingDashboardStyleClassName = "slide-in-down";
-WI.DashboardContainerView.BackwardIncomingDashboardStyleClassName = "slide-in-up";
-WI.DashboardContainerView.ForwardOutgoingDashboardStyleClassName = "slide-out-down";
-WI.DashboardContainerView.BackwardOutgoingDashboardStyleClassName = "slide-out-up";
diff --git a/Source/WebInspectorUI/UserInterface/Views/DashboardView.js b/Source/WebInspectorUI/UserInterface/Views/DashboardView.js
deleted file mode 100644 (file)
index 0f45cba..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DashboardView = class DashboardView extends WI.Object
-{
-    constructor(representedObject, identifier)
-    {
-        console.assert(identifier);
-
-        super();
-
-        this._representedObject = representedObject;
-
-        this._element = document.createElement("div");
-        this._element.classList.add("dashboard");
-        this._element.classList.add(identifier);
-    }
-
-    // Static
-
-    static create(representedObject)
-    {
-        console.assert(representedObject);
-
-        if (representedObject instanceof WI.DefaultDashboard)
-            return new WI.DefaultDashboardView(representedObject);
-
-        if (representedObject instanceof WI.DebuggerDashboard)
-            return new WI.DebuggerDashboardView(representedObject);
-
-        throw "Can't make a DashboardView for an unknown representedObject.";
-    }
-
-    // Public
-
-    get element()
-    {
-        return this._element;
-    }
-
-    get representedObject()
-    {
-        return this._representedObject;
-    }
-
-    shown()
-    {
-        // Implemented by subclasses.
-    }
-
-    hidden()
-    {
-        // Implemented by subclasses.
-    }
-
-    closed()
-    {
-        // Implemented by subclasses.
-    }
-};
diff --git a/Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.css b/Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.css
deleted file mode 100644 (file)
index cf7a68a..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (C) 2014-2017 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.
- */
-
-.toolbar .dashboard.debugger {
-    display: flex;
-    flex-wrap: nowrap;
-    justify-content: center;
-    align-items: center;
-    -webkit-padding-start: 5px;
-    -webkit-padding-end: 12px;
-    text-align: center;
-    color: hsl(0, 0%, 23%);
-}
-
-.dashboard.debugger > .message {
-    font-weight: bold;
-}
-
-.dashboard.debugger .navigation-bar {
-    -webkit-margin-end: 4px;
-    border: 0;
-}
-
-.toolbar:not(.small-size) .dashboard.debugger .navigation-bar {
-    margin-top: 1px;
-}
-
-.dashboard.debugger .navigation-bar .item.button {
-    flex-direction: row;
-    width: 16px;
-    height: 16px;
-    cursor: pointer;
-    padding: 0;
-    border: none !important;
-    background-image: none !important;
-    box-shadow: none !important;
-}
-
-.dashboard.debugger .navigation-bar .item.button > .glyph {
-    width: 16px;
-    height: 16px;
-    animation-name: pulse-pause-button;
-    animation-duration: 1s;
-    animation-timing-function: ease-out;
-    animation-iteration-count: infinite;
-    animation-direction: alternate;
-    color: hsl(207, 46%, 59%);
-}
-
-body.window-inactive .dashboard.debugger .navigation-bar .item.button > .glyph {
-    animation-name: none;
-}
-
-.dashboard.debugger .navigation-bar .item.debugger-dashboard-pause.activated {
-    fill: none;
-    stroke: var(--glyph-color-active);
-}
-
-@keyframes pulse-pause-button {
-    from { opacity: 0.7; transform: scale(1); }
-    to { opacity: 1; transform: scale(1.1); }
-}
-
-.dashboard.debugger > .divider {
-    width: 1px;
-    height: 100%;
-
-    margin: 0 10px;
-
-    background-image: linear-gradient(hsl(0, 0%, 74%), hsl(0, 0%, 74%));
-    background-size: 100% 66%;
-    background-repeat: no-repeat;
-    background-position: center;
-}
-
-.dashboard.debugger > div {
-    display: flex;
-    align-items: center;
-    flex: none;
-}
-
-.dashboard.debugger > .location {
-    overflow: hidden;
-    flex: initial;
-}
-
-.dashboard.debugger > .location > * {
-    flex: none;
-}
-
-.dashboard.debugger > .location > :first-child {
-    align-self: center;
-    width: 16px;
-    height: 16px;
-}
-
-/* Add spacing between the ellipsis'd location and the up/down arrows. */
-.dashboard.debugger > .location > :last-child {
-    -webkit-margin-end: 5px;
-}
-
-.toolbar:not(.small-size) .dashboard.debugger > .location :not(:first-child) {
-    margin-top: 1px;
-}
-
-.dashboard.debugger > .location img.icon {
-    width: 16px;
-    height: 16px;
-}
-
-.dashboard.debugger > .location :matches(.function-icon, .event-listener-icon) {
-    -webkit-margin-end: 5px;
-}
-
-.dashboard.debugger > .location .function-name {
-    color: hsl(0, 0%, 11%);
-    padding-bottom: 1px;
-}
-
-.dashboard.debugger > .location .function-name::after {
-    content: "\00A0\2014\00A0"; /* &nbsp;&mdash;&nbsp; */;
-}
-
-.dashboard.debugger > .location .go-to-link {
-    padding-bottom: 1px;
-    -webkit-text-decoration-color: hsl(0, 0%, 66%);
-
-    flex: initial;
-    text-overflow: ellipsis;
-    overflow: hidden;
-}
-
-.toolbar.collapsed .dashboard.debugger > :not(.message, .navigation-bar) {
-    display: none;
-}
-
-.toolbar.small-size .dashboard.debugger > .message {
-    font-size: 10px;
-}
-
-.toolbar.small-size .dashboard.debugger > .location img.icon,
-.toolbar.small-size .dashboard.debugger > .location > :first-child {
-    width: 14px;
-    height: 14px;
-}
-
-@media (prefers-color-scheme: dark) {
-    .toolbar .dashboard.debugger {
-        color: var(--text-color);
-    }
-
-    .dashboard.debugger .navigation-bar .item.button > .glyph {
-        color: var(--glyph-color-active);
-    }
-
-    .dashboard.debugger > .location .function-name {
-        color: var(--text-color-active);
-    }
-
-    .dashboard.debugger > .location .go-to-link {
-        padding-bottom: 1px;
-        -webkit-text-decoration-color: var(--text-color-secondary);
-    }
-
-    .dashboard.debugger > .divider {
-        background-image: linear-gradient(var(--text-color-tertiary), var(--text-color-tertiary));
-    }
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.js b/Source/WebInspectorUI/UserInterface/Views/DebuggerDashboardView.js
deleted file mode 100644 (file)
index b103267..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2014-2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DebuggerDashboardView = class DebuggerDashboardView extends WI.DashboardView
-{
-    constructor(representedObject)
-    {
-        super(representedObject, "debugger");
-
-        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._rebuildLocation, this);
-
-        this._navigationBar = new WI.NavigationBar;
-        this.element.appendChild(this._navigationBar.element);
-
-        var tooltip = WI.UIString("Continue script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName);
-        this._debuggerResumeButtonItem = new WI.ActivateButtonNavigationItem("debugger-dashboard-pause", tooltip, tooltip, "Images/Resume.svg", 15, 15);
-        this._debuggerResumeButtonItem.activated = true;
-        this._debuggerResumeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._resumeButtonClicked, this);
-        this._navigationBar.addNavigationItem(this._debuggerResumeButtonItem);
-
-        var message = this._messageElement = document.createElement("div");
-        message.classList.add("message");
-        message.title = message.textContent = WI.UIString("Debugger Paused");
-        this.element.appendChild(message);
-
-        var dividerElement = document.createElement("div");
-        dividerElement.classList.add("divider");
-        this.element.appendChild(dividerElement);
-
-        var locationElement = this._locationElement = document.createElement("div");
-        locationElement.classList.add("location");
-        this.element.appendChild(locationElement);
-
-        this._rebuildLocation();
-    }
-
-    // Public
-
-    closed()
-    {
-        WI.debuggerManager.removeEventListener(null, null, this);
-
-        super.closed();
-    }
-
-    // Private
-
-    _rebuildLocation()
-    {
-        if (!WI.debuggerManager.activeCallFrame)
-            return;
-
-        this._locationElement.removeChildren();
-
-        var callFrame = WI.debuggerManager.activeCallFrame;
-        var functionName = callFrame.functionName || WI.UIString("(anonymous function)");
-
-        var iconClassName = WI.DebuggerDashboardView.FunctionIconStyleClassName;
-
-        // This is more than likely an event listener function with an "on" prefix and it is
-        // as long or longer than the shortest event listener name -- "oncut".
-        if (callFrame.functionName && callFrame.functionName.startsWith("on") && callFrame.functionName.length >= 5)
-            iconClassName = WI.DebuggerDashboardView.EventListenerIconStyleClassName;
-
-        var iconElement = document.createElement("div");
-        iconElement.classList.add(iconClassName);
-        this._locationElement.appendChild(iconElement);
-
-        var iconImageElement = document.createElement("img");
-        iconImageElement.className = "icon";
-        iconElement.appendChild(iconImageElement);
-
-        var nameElement = document.createElement("div");
-        nameElement.append(functionName);
-        nameElement.classList.add("function-name");
-        this._locationElement.appendChild(nameElement);
-
-        const options = {
-            dontFloat: true,
-            ignoreNetworkTab: true,
-            ignoreSearchTab: true,
-        };
-        let linkElement = WI.createSourceCodeLocationLink(WI.debuggerManager.activeCallFrame.sourceCodeLocation, options);
-        this._locationElement.appendChild(linkElement);
-    }
-
-    _resumeButtonClicked()
-    {
-        WI.debuggerManager.resume();
-    }
-};
-
-WI.DebuggerDashboardView.FunctionIconStyleClassName = WI.CallFrameView.FunctionIconStyleClassName;
-WI.DebuggerDashboardView.EventListenerIconStyleClassName = WI.CallFrameView.EventListenerIconStyleClassName;
diff --git a/Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.css b/Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.css
deleted file mode 100644 (file)
index 5e943fe..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2013-2017 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.
- */
-
-body:matches(.page, .web-page) .toolbar.collapsed .dashboard.default > :matches(.resourcesSize, .time, .logs) {
-    display: none;
-}
-
-body:not(.page, .web-page) .toolbar .dashboard.default > :matches(.resourcesCount, .resourcesSize, .time) {
-    display: none;
-}
-
-.toolbar .dashboard.default {
-    display: flex;
-    flex-flow: row nowrap;
-    justify-content: center;
-}
-
-.toolbar .dashboard.default > .item {
-    line-height: 13px;
-
-    margin: 1px 0;
-    padding: 0 5px;
-
-    display: flex;
-
-    min-width: 45px;
-
-    justify-content: center;
-    align-items: center;
-
-    border-radius: 4px;
-    border: 1px solid transparent;
-
-    font-family: -webkit-system-font, sans-serif;
-    font-variant-numeric: tabular-nums;
-}
-
-.toolbar .dashboard.default > :matches(.time, .resourcesSize) {
-    min-width: 70px;
-}
-
-.toolbar .dashboard.default > .item.enabled:hover {
-    border: 1px solid hsla(0, 0%, 0%, 0.1);
-}
-
-.toolbar .dashboard.default > .item.enabled:active {
-    border: 1px solid hsla(0, 0%, 0%, 0.2);
-}
-
-.toolbar .dashboard.default > .item > * {
-    display: flex;
-    align-items: center;
-}
-
-.toolbar .dashboard.default > .item > img {
-    opacity: 0.2;
-    width: 16px;
-    height: 16px;
-    pointer-events: none;
-}
-
-.toolbar .dashboard.default > .item.enabled > img {
-    opacity: 0.5;
-}
-
-.toolbar .dashboard.default > .item.enabled:hover > img {
-    opacity: 0.65;
-}
-
-.toolbar .dashboard.default > .item > div {
-    display: flex;
-    flex: 1;
-    -webkit-padding-start: 2px;
-    color: hsla(0, 0%, 0%, 0.2);
-}
-
-.toolbar .dashboard.default > .item.enabled > div {
-    color: hsla(0, 0%, 0%, 0.7);
-}
-
-.toolbar .dashboard.default > .item.enabled:hover > div {
-    color: hsla(0, 0%, 0%, 0.85);
-}
-
-.toolbar .dashboard.default > .resourcesCount > img {
-    content: url(../Images/Resources.svg);
-}
-
-.toolbar .dashboard.default > .time > img {
-    content: url(../Images/Time.svg);
-}
-
-.toolbar .dashboard.default > .logs > img {
-    content: url(../Images/Logs.svg);
-}
-
-.toolbar .dashboard.default > .resourcesSize > img {
-    content: url(../Images/Weight.svg);
-}
-
-.toolbar .dashboard.default > .errors > img {
-    content: url(../Images/Errors.svg);
-}
-
-.toolbar .dashboard.default > .errors.enabled > img {
-    content: url(../Images/ErrorsEnabled.svg);
-    opacity: 0.9;
-}
-
-.toolbar .dashboard.default > .errors.enabled:hover > img {
-    opacity: 1;
-}
-
-.toolbar .dashboard.default > .errors.enabled > div {
-    color: hsla(359, 57%, 50%, 0.9);
-}
-
-.toolbar .dashboard.default > .errors.enabled:hover > div {
-    color: hsl(359, 57%, 50%);
-}
-
-.toolbar .dashboard.default > .issues > img {
-    content: url(../Images/Issues.svg);
-}
-
-.toolbar .dashboard.default > .issues.enabled > img {
-    content: url(../Images/IssuesEnabled.svg);
-    opacity: 0.9;
-}
-
-.toolbar .dashboard.default > .issues.enabled:hover > img {
-    opacity: 1;
-}
-
-.toolbar .dashboard.default > .issues.enabled > div {
-    color: hsla(43, 96%, 44%, 0.9);
-}
-
-.toolbar .dashboard.default > .issues.enabled:hover > div {
-    color: hsl(43, 96%, 44%);
-}
-
-/* Styles for the pulsing animated state of console items */
-
-.toolbar .dashboard.default > .item.pulsing {
-    animation-name: console-item-pulse;
-    animation-duration: 0.75s;
-}
-
-@keyframes console-item-pulse {
-    50% { opacity: 0.6; }
-}
-
-@media (prefers-color-scheme: dark) {
-    .toolbar .dashboard.default > .item > div {
-        /* FIXME: introduce a variable for opacity and use it for both text and icons */
-        color: hsla(0, 100%, 100%, 0.2);
-    }
-
-    .toolbar .dashboard.default > .item.enabled > div {
-        color: var(--glyph-color);
-    }
-
-    .toolbar .dashboard.default > .item.enabled:hover {
-        border-color: hsla(0, 0%, var(--foreground-lightness), 0.1);
-    }
-
-    .toolbar .dashboard.default > .item.enabled:hover > div {
-        color: hsla(0, 100%, 100%, 0.85);
-    }
-
-    .toolbar .dashboard.default > .resourcesCount > img,
-    .toolbar .dashboard.default > .resourcesSize > img,
-    .toolbar .dashboard.default > .time > img,
-    .toolbar .dashboard.default > .logs > img,
-    .toolbar .dashboard.default > .errors:not(.enabled) > img,
-    .toolbar .dashboard.default > .issues:not(.enabled) > img {
-        filter: var(--filter-invert);
-    }
-
-    .toolbar .dashboard .item.button,
-    .toolbar .dashboard .item.button:active {
-        background: none;
-    }
-
-    .dashboard-container .advance-arrow {
-        filter: var(--filter-invert);
-    }
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.js b/Source/WebInspectorUI/UserInterface/Views/DefaultDashboardView.js
deleted file mode 100644 (file)
index d624932..0000000
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.DefaultDashboardView = class DefaultDashboardView extends WI.DashboardView
-{
-    constructor(representedObject)
-    {
-        super(representedObject, "default");
-
-        representedObject.addEventListener(WI.DefaultDashboard.Event.DataDidChange, () => { this._updateDisplaySoon(); });
-        this._scheduledUpdateIdentifier = undefined;
-
-        this._items = {
-            resourcesCount: {
-                tooltip: WI.UIString("Show page resources"),
-                handler: this._resourcesItemWasClicked
-            },
-            resourcesSize: {
-                tooltip: WI.UIString("Show network information"),
-                handler: this._networkItemWasClicked
-            },
-            time: {
-                tooltip: WI.UIString("Show page load timing"),
-                handler: this._timelineItemWasClicked
-            },
-            logs: {
-                tooltip: WI.UIString("Show messages logged to the Console"),
-                handler: this._consoleItemWasClicked.bind(this, WI.LogContentView.Scopes.Logs)
-            },
-            errors: {
-                tooltip: WI.UIString("Show errors logged to the Console"),
-                handler: this._consoleItemWasClicked.bind(this, WI.LogContentView.Scopes.Errors)
-            },
-            issues: {
-                tooltip: WI.UIString("Show warnings logged to the Console"),
-                handler: this._consoleItemWasClicked.bind(this, WI.LogContentView.Scopes.Warnings)
-            }
-        };
-
-        for (var name in this._items)
-            this._appendElementForNamedItem(name);
-    }
-
-    // Private
-
-    _updateDisplaySoon()
-    {
-        if (this._scheduledUpdateIdentifier)
-            return;
-
-        this._scheduledUpdateIdentifier = requestAnimationFrame(this._updateDisplay.bind(this));
-    }
-
-    _updateDisplay()
-    {
-        this._scheduledUpdateIdentifier = undefined;
-
-        var dashboard = this.representedObject;
-
-        for (var category of ["logs", "issues", "errors"])
-            this._setConsoleItemValue(category, dashboard[category]);
-
-        var timeItem = this._items.time;
-        timeItem.text = dashboard.time ? Number.secondsToString(dashboard.time) : emDash;
-        this._setItemEnabled(timeItem, dashboard.time > 0);
-
-        var countItem = this._items.resourcesCount;
-        countItem.text = Number.abbreviate(dashboard.resourcesCount);
-        this._setItemEnabled(countItem, dashboard.resourcesCount > 0);
-
-        var sizeItem = this._items.resourcesSize;
-        sizeItem.text = dashboard.resourcesSize ? Number.bytesToString(dashboard.resourcesSize, false) : emDash;
-        this._setItemEnabled(sizeItem, dashboard.resourcesSize > 0);
-    }
-
-    _appendElementForNamedItem(name)
-    {
-        var item = this._items[name];
-
-        item.container = this._element.appendChild(document.createElement("div"));
-        item.container.className = "item " + name;
-
-        item.container.appendChild(document.createElement("img"));
-
-        item.outlet = item.container.appendChild(document.createElement("div"));
-
-        Object.defineProperty(item, "text", {
-            set: function(newText)
-            {
-                newText = newText.toString();
-                if (newText === item.outlet.textContent)
-                    return;
-                item.outlet.textContent = newText;
-            }
-        });
-
-        item.container.addEventListener("click", (event) => {
-            this._itemWasClicked(name);
-        });
-    }
-
-    _itemWasClicked(name)
-    {
-        var item = this._items[name];
-        if (!item.container.classList.contains(WI.DefaultDashboardView.EnabledItemStyleClassName))
-            return;
-
-        if (item.handler)
-            item.handler.call(this);
-    }
-
-    _resourcesItemWasClicked()
-    {
-        WI.showSourcesTab({initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard});
-    }
-
-    _networkItemWasClicked()
-    {
-        WI.showNetworkTab({initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard});
-    }
-
-    _timelineItemWasClicked()
-    {
-        WI.showTimelineTab({initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard});
-    }
-
-    _consoleItemWasClicked(scope)
-    {
-        WI.showConsoleTab(scope, {
-            initiatorHint: WI.TabBrowser.TabNavigationInitiator.Dashboard,
-        });
-    }
-
-    _setConsoleItemValue(itemName, newValue)
-    {
-        var iVarName = "_" + itemName;
-        var previousValue = this[iVarName];
-        this[iVarName] = newValue;
-
-        var item = this._items[itemName];
-        item.text = Number.abbreviate(newValue);
-        this._setItemEnabled(item, newValue > 0);
-
-        if (newValue <= previousValue)
-            return;
-
-        var container = item.container;
-
-        function animationEnded(event)
-        {
-            if (event.target === container) {
-                container.classList.remove("pulsing");
-                container.removeEventListener("animationend", animationEnded);
-            }
-        }
-
-        // We need to force a style invalidation in the case where we already
-        // were animating this item after we've removed the pulsing CSS class.
-        if (container.classList.contains("pulsing")) {
-            container.classList.remove("pulsing");
-            container.recalculateStyles();
-        } else
-            container.addEventListener("animationend", animationEnded);
-
-        container.classList.add("pulsing");
-    }
-
-    _setItemEnabled(item, enabled)
-    {
-        if (enabled) {
-            item.container.title = item.tooltip;
-            item.container.classList.add(WI.DefaultDashboardView.EnabledItemStyleClassName);
-        } else {
-            item.container.title = "";
-            item.container.classList.remove(WI.DefaultDashboardView.EnabledItemStyleClassName);
-        }
-    }
-};
-
-WI.DefaultDashboardView.EnabledItemStyleClassName = "enabled";
index 23792d2..0c77668 100644 (file)
 
 .navigation-bar .item.divider {
     width: 1px;
-    height: 100%;
-    background-image: linear-gradient(hsl(0, 0%, 74%), hsl(0, 0%, 74%));
-    background-size: 100% 16px;
-    background-repeat: no-repeat;
-    background-position: center;
+    height: 16px;
+    background-color: hsl(0, 0%, 74%);
 }
 
 @media (-webkit-min-device-pixel-ratio: 2) {
@@ -40,7 +37,6 @@
 
 @media (prefers-color-scheme: dark) {
     .navigation-bar .item.divider {
-        --divider-background: hsl(0, 0%, 40%);
-        background-image: linear-gradient(var(--divider-background), var(--divider-background));
+        background-color: hsl(0, 0%, 40%);
     }
 }
index 627297f..ff21cf0 100644 (file)
 
 WI.ElementsTabContentView = class ElementsTabContentView extends WI.ContentBrowserTabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.ElementsTabContentView.tabInfo());
-
-        let detailsSidebarPanelConstructors = [WI.RulesStyleDetailsSidebarPanel, WI.ComputedStyleDetailsSidebarPanel, WI.ChangesDetailsSidebarPanel, WI.DOMNodeDetailsSidebarPanel];
+        let detailsSidebarPanelConstructors = [
+            WI.RulesStyleDetailsSidebarPanel,
+            WI.ComputedStyleDetailsSidebarPanel,
+            WI.ChangesDetailsSidebarPanel,
+            WI.DOMNodeDetailsSidebarPanel,
+        ];
         if (InspectorBackend.hasDomain("LayerTree"))
             detailsSidebarPanelConstructors.push(WI.LayerTreeDetailsSidebarPanel);
 
-        super(identifier || "elements", "elements", tabBarItem, null, detailsSidebarPanelConstructors, true);
+        super(ElementsTabContentView.tabInfo(), {detailsSidebarPanelConstructors, disableBackForward: true});
 
         WI.networkManager.addEventListener(WI.NetworkManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
         WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
@@ -42,6 +45,7 @@ WI.ElementsTabContentView = class ElementsTabContentView extends WI.ContentBrows
     static tabInfo()
     {
         return {
+            identifier: ElementsTabContentView.Type,
             image: "Images/Elements.svg",
             title: WI.UIString("Elements"),
         };
index 034405e..5fa922e 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-:matches(.navigation-bar, .toolbar) .item.flexible-space {
+.navigation-bar .item.flexible-space {
     flex: 1;
 }
 
-:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item {
+.navigation-bar .item.flexible-space.align-start > .item {
     -webkit-margin-end: auto;
 }
 
-:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item {
+.navigation-bar .item.flexible-space.align-end > .item {
     -webkit-margin-start: auto;
 }
index 6d3ac07..e0fc288 100644 (file)
 
 WI.GeneralTabBarItem = class GeneralTabBarItem extends WI.TabBarItem
 {
-    constructor(image, title, isEphemeral = false)
-    {
-        super(image, title);
-
-        this._isEphemeral = isEphemeral;
-
-        if (this._isEphemeral) {
-            this.element.classList.add("ephemeral");
-
-            let closeButtonElement = document.createElement("div");
-            closeButtonElement.classList.add(WI.TabBarItem.CloseButtonStyleClassName);
-            closeButtonElement.title = WI.UIString("Click to close this tab");
-
-            this.element.insertBefore(closeButtonElement, this.element.firstChild);
-            this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this));
-        }
-    }
+    // Static
 
-    static fromTabInfo({image, title, isEphemeral})
+    static fromTabContentView(tabContentView)
     {
-        return new WI.GeneralTabBarItem(image, title, isEphemeral);
+        console.assert(tabContentView instanceof WI.TabContentView);
+
+        let {image, title} = tabContentView.constructor.tabInfo();
+        return new WI.GeneralTabBarItem(tabContentView, image, title);
     }
 
     // Public
 
-    get isEphemeral() { return this._isEphemeral; }
-
     get title()
     {
         return super.title;
@@ -79,18 +64,4 @@ WI.GeneralTabBarItem = class GeneralTabBarItem extends WI.TabBarItem
 
         super.title = title;
     }
-
-    // Private
-
-    _handleContextMenuEvent(event)
-    {
-        if (!this._parentTabBar)
-            return;
-
-        let contextMenu = WI.ContextMenu.createFromEvent(event);
-        contextMenu.appendItem(WI.UIString("Close Tab"), () => {
-            this._parentTabBar.removeTabBarItem(this);
-        }, this.isDefaultTab);
-        contextMenu.appendSeparator();
-    }
 };
index e0c0ae0..084c3df 100644 (file)
@@ -104,7 +104,7 @@ WI.GraphicsOverviewContentView = class GraphicsOverviewContentView extends WI.Co
 
                 let navigationItems = overviewView.navigationItems;
                 if (navigationItems.length) {
-                    let navigationBar = new WI.NavigationBar(document.createElement("nav"), navigationItems);
+                    let navigationBar = new WI.NavigationBar(document.createElement("nav"), {navigationItems});
                     headerElement.appendChild(navigationBar.element);
                     this.addSubview(navigationBar);
                 }
index 2e6d857..cc029e3 100644 (file)
@@ -27,17 +27,16 @@ WI.GraphicsTabContentView = class GraphicsTabContentView extends WI.ContentBrows
 {
     constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.GraphicsTabContentView.tabInfo());
-
-        const navigationSidebarPanelConstructor = WI.CanvasSidebarPanel;
-        const detailsSidebarPanelConstructors = [
-            WI.RecordingStateDetailsSidebarPanel,
-            WI.RecordingTraceDetailsSidebarPanel,
-            WI.CanvasDetailsSidebarPanel,
-            WI.AnimationDetailsSidebarPanel,
-        ];
-        const disableBackForward = true;
-        super("graphics", ["graphics"], tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward);
+        super(GraphicsTabContentView.tabInfo(), {
+            navigationSidebarPanelConstructor: WI.CanvasSidebarPanel,
+            detailsSidebarPanelConstructors: [
+                WI.RecordingStateDetailsSidebarPanel,
+                WI.RecordingTraceDetailsSidebarPanel,
+                WI.CanvasDetailsSidebarPanel,
+                WI.AnimationDetailsSidebarPanel,
+            ],
+            disableBackForward: true,
+        });
 
         this._canvasesTreeOutline = new WI.TreeOutline;
         this._canvasesTreeOutline.allowsRepeatSelection = true;
@@ -65,6 +64,7 @@ WI.GraphicsTabContentView = class GraphicsTabContentView extends WI.ContentBrows
     static tabInfo()
     {
         return {
+            identifier: GraphicsTabContentView.Type,
             image: "Images/Graphics.svg",
             title: WI.UIString("Graphics"),
         };
index ebb88d8..5c604d9 100644 (file)
@@ -51,6 +51,16 @@ WI.GroupNavigationItem = class GroupNavigationItem extends WI.NavigationItem
         this._needsUpdate = true;
     }
 
+    get hidden()
+    {
+        return super.hidden || this._navigationItems.every((item) => item.hidden);
+    }
+
+    set hidden(flag)
+    {
+        super.hidden = flag;
+    }
+
     get width()
     {
         this._updateItems();
@@ -67,6 +77,11 @@ WI.GroupNavigationItem = class GroupNavigationItem extends WI.NavigationItem
 
     // Protected
 
+    get additionalClassNames()
+    {
+        return ["group"];
+    }
+
     update(options = {})
     {
         super.update(options);
index 2eaff5d..2bc0c9b 100644 (file)
@@ -27,12 +27,9 @@ WI.LayersTabContentView = class LayersTabContentView extends WI.ContentBrowserTa
 {
     constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.LayersTabContentView.tabInfo());
-
-        const navigationSidebarPanelConstructor = null;
-        const detailsSidebarPanelConstructors = [WI.LayerDetailsSidebarPanel];
-        const disableBackForward = true;
-        super("layers", "layers", tabBarItem, navigationSidebarPanelConstructor, detailsSidebarPanelConstructors, disableBackForward);
+        super(LayersTabContentView.tabInfo(), {
+            detailsSidebarPanelConstructors: [WI.LayerDetailsSidebarPanel],
+        });
 
         this._layerDetailsSidebarPanel = this.detailsSidebarPanels[0];
         this._layerDetailsSidebarPanel.addEventListener(WI.LayerDetailsSidebarPanel.Event.SelectedLayerChanged, this._detailsSidebarSelectedLayerChanged, this);
@@ -46,6 +43,7 @@ WI.LayersTabContentView = class LayersTabContentView extends WI.ContentBrowserTa
     static tabInfo()
     {
         return {
+            identifier: LayersTabContentView.Type,
             image: "Images/Layers.svg",
             title: WI.UIString("Layers"),
         };
diff --git a/Source/WebInspectorUI/UserInterface/Views/LegacyTabBar.js b/Source/WebInspectorUI/UserInterface/Views/LegacyTabBar.js
deleted file mode 100644 (file)
index dd1bbdd..0000000
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * Copyright (C) 2018 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.LegacyTabBar = class LegacyTabBar extends WI.View
-{
-    constructor(element, tabBarItems)
-    {
-        super(element);
-
-        this.element.classList.add("tab-bar");
-        this.element.setAttribute("role", "tablist");
-        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("contextmenu", this._handleContextMenu.bind(this));
-
-        this.element.createChild("div", "top-border");
-
-        this._tabBarItems = [];
-        this._hiddenTabBarItems = [];
-
-        if (tabBarItems) {
-            for (let tabBarItem in tabBarItems)
-                this.addTabBarItem(tabBarItem);
-        }
-
-        this.addTabBarItem(WI.settingsTabContentView.tabBarItem, {suppressAnimations: true});
-
-        this._newTabTabBarItem = new WI.PinnedTabBarItem("Images/NewTabPlus.svg", WI.UIString("Create a new tab"));
-        this._newTabTabBarItem.element.addEventListener("mouseenter", this._handleNewTabMouseEnter.bind(this));
-        this._newTabTabBarItem.element.addEventListener("click", this._handleNewTabClick.bind(this));
-        this.addTabBarItem(this._newTabTabBarItem, {suppressAnimations: true});
-
-        this._tabPickerTabBarItem = new WI.PinnedTabBarItem("Images/TabPicker.svg", WI.UIString("Show hidden tabs"));
-        this._tabPickerTabBarItem.element.classList.add("tab-picker");
-        this.addTabBarItem(this._tabPickerTabBarItem, {suppressAnimations: true});
-    }
-
-    // Public
-
-    get newTabTabBarItem() { return this._newTabTabBarItem; }
-
-    updateNewTabTabBarItemState()
-    {
-        let newTabExists = !WI.isNewTabWithTypeAllowed(WI.NewTabContentView.Type);
-        this._newTabTabBarItem.disabled = newTabExists;
-    }
-
-    addTabBarItem(tabBarItem, options = {})
-    {
-        return this.insertTabBarItem(tabBarItem, this._tabBarItems.length, options);
-    }
-
-    insertTabBarItem(tabBarItem, index, options = {})
-    {
-        console.assert(tabBarItem instanceof WI.TabBarItem);
-        if (!(tabBarItem instanceof WI.TabBarItem))
-            return null;
-
-        if (tabBarItem.parentTabBar === this)
-            return null;
-
-        if (this._tabAnimatedClosedSinceMouseEnter) {
-            // Delay adding the new tab until we can expand the tabs after a closed tab.
-            this._finishExpandingTabsAfterClose().then(() => {
-                this.insertTabBarItem(tabBarItem, index, options);
-            });
-            return null;
-        }
-
-        if (tabBarItem.parentTabBar)
-            tabBarItem.parentTabBar.removeTabBarItem(tabBarItem);
-
-        tabBarItem.parentTabBar = this;
-
-        index = Number.constrain(index, 0, this.normalTabCount);
-
-        if (this.element.classList.contains("animating")) {
-            requestAnimationFrame(removeStyles.bind(this));
-            options.suppressAnimations = true;
-        }
-
-        var beforeTabSizesAndPositions;
-        if (!options.suppressAnimations)
-            beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
-
-        this._tabBarItems.splice(index, 0, tabBarItem);
-
-        var nextSibling = this._tabBarItems[index + 1];
-        let nextSiblingElement = nextSibling ? nextSibling.element : this._tabBarItems.lastValue.element;
-
-        if (this.element.contains(nextSiblingElement))
-            this.element.insertBefore(tabBarItem.element, nextSiblingElement);
-        else
-            this.element.appendChild(tabBarItem.element);
-
-        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._applyTabBarItemSizesAndPositions(afterTabSizesAndPositions);
-
-            this.element.addEventListener("webkitTransitionEnd", removeStylesListener);
-        }
-
-        function removeStyles()
-        {
-            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);
-        }
-
-        if (!options.suppressAnimations) {
-            var afterTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
-
-            this.updateLayout();
-
-            let tabBarItems = this._tabBarItemsFromLeftToRight();
-            let previousTabBarItem = tabBarItems[tabBarItems.indexOf(tabBarItem) - 1] || null;
-            let previousTabBarItemSizeAndPosition = previousTabBarItem ? beforeTabSizesAndPositions.get(previousTabBarItem) : null;
-
-            if (previousTabBarItemSizeAndPosition)
-                beforeTabSizesAndPositions.set(tabBarItem, {left: previousTabBarItemSizeAndPosition.left + previousTabBarItemSizeAndPosition.width, width: 0});
-            else
-                beforeTabSizesAndPositions.set(tabBarItem, {left: 0, width: 0});
-
-            this.element.classList.add("static-layout");
-            tabBarItem.element.classList.add("being-inserted");
-
-            this._applyTabBarItemSizesAndPositions(beforeTabSizesAndPositions);
-
-            var removeStylesListener = removeStyles.bind(this);
-
-            requestAnimationFrame(animateTabs.bind(this));
-        } else
-            this.needsLayout();
-
-        if (!(tabBarItem instanceof WI.PinnedTabBarItem))
-            this.updateNewTabTabBarItemState();
-
-        this.dispatchEventToListeners(WI.TabBar.Event.TabBarItemAdded, {tabBarItem});
-
-        return tabBarItem;
-    }
-
-    removeTabBarItem(tabBarItemOrIndex, options = {})
-    {
-        let tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
-        if (!tabBarItem || tabBarItem instanceof WI.PinnedTabBarItem)
-            return null;
-
-        tabBarItem.parentTabBar = null;
-
-        if (this._selectedTabBarItem === tabBarItem) {
-            var index = this._tabBarItems.indexOf(tabBarItem);
-            var nextTabBarItem = this._tabBarItems[index + 1];
-            if (!nextTabBarItem || nextTabBarItem instanceof WI.PinnedTabBarItem)
-                nextTabBarItem = this._tabBarItems[index - 1];
-
-            let initiatorHint = options.initiatorHint || WI.TabBrowser.TabNavigationInitiator.Unknown;
-            this.selectTabBarItem(nextTabBarItem, {initiatorHint});
-        }
-
-        if (this.element.classList.contains("animating")) {
-            requestAnimationFrame(removeStyles.bind(this));
-            options.suppressAnimations = true;
-        }
-
-        var beforeTabSizesAndPositions;
-        if (!options.suppressAnimations)
-            beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
-
-        // Subtract 1 from normalTabCount since arrays begin indexing at 0.
-        let wasLastNormalTab = this._tabBarItems.indexOf(tabBarItem) === this.normalTabCount - 1;
-
-        this._tabBarItems.remove(tabBarItem);
-        tabBarItem.element.remove();
-
-        var hasMoreThanOneNormalTab = this._hasMoreThanOneNormalTab();
-        this.element.classList.toggle("single-tab", !hasMoreThanOneNormalTab);
-
-        const shouldOpenDefaultTab = !tabBarItem.isDefaultTab && !this.normalTabCount;
-        if (shouldOpenDefaultTab)
-            options.suppressAnimations = true;
-
-        if (!hasMoreThanOneNormalTab || wasLastNormalTab || !options.suppressExpansion) {
-            if (!options.suppressAnimations) {
-                this._tabAnimatedClosedSinceMouseEnter = true;
-                this._finishExpandingTabsAfterClose(beforeTabSizesAndPositions);
-            } else
-                this.needsLayout();
-
-            this.updateNewTabTabBarItemState();
-
-            this.dispatchEventToListeners(WI.TabBar.Event.TabBarItemRemoved, {tabBarItem});
-
-            if (shouldOpenDefaultTab)
-                this._openDefaultTab();
-
-            return tabBarItem;
-        }
-
-        var lastNormalTabBarItem;
-
-        function animateTabs()
-        {
-            this.element.classList.add("animating");
-            this.element.classList.add("closing-tab");
-
-            // For RTL, we need to place extra space between pinned tab and first normal tab.
-            // From left to right there is pinned tabs, extra space, then normal tabs. Compute
-            // how much extra space we need to additionally add for normal tab items.
-            let extraSpaceBetweenNormalAndPinnedTabs = 0;
-            if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL) {
-                extraSpaceBetweenNormalAndPinnedTabs = this.element.getBoundingClientRect().width;
-                for (let currentTabBarItem of this._tabBarItemsFromLeftToRight())
-                    extraSpaceBetweenNormalAndPinnedTabs -= currentTabBarItem.element.getBoundingClientRect().width;
-            }
-
-            let left = 0;
-            for (let currentTabBarItem of this._tabBarItemsFromLeftToRight()) {
-                let sizeAndPosition = beforeTabSizesAndPositions.get(currentTabBarItem);
-
-                if (!(currentTabBarItem instanceof WI.PinnedTabBarItem)) {
-                    currentTabBarItem.element.style.left = extraSpaceBetweenNormalAndPinnedTabs + left + "px";
-                    left += sizeAndPosition.width;
-                    lastNormalTabBarItem = currentTabBarItem;
-                } else
-                    left = sizeAndPosition.left + sizeAndPosition.width;
-            }
-
-            // The selected tab and last tab need to draw a right border as well, so make them 1px wider.
-            if (this._selectedTabBarItem)
-                this._selectedTabBarItem.element.style.width = (parseFloat(this._selectedTabBarItem.element.style.width) + 1) + "px";
-
-            if (lastNormalTabBarItem !== this._selectedTabBarItem)
-                lastNormalTabBarItem.element.style.width = (parseFloat(lastNormalTabBarItem.element.style.width) + 1) + "px";
-
-            this.element.addEventListener("webkitTransitionEnd", removeStylesListener);
-        }
-
-        function removeStyles()
-        {
-            // The selected tab needs to stop drawing the right border, so make it 1px smaller. Only if it isn't the last.
-            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.updateLayout();
-
-            this.element.removeEventListener("webkitTransitionEnd", removeStylesListener);
-        }
-
-        if (!options.suppressAnimations) {
-            this.element.classList.add("static-layout");
-
-            this._tabAnimatedClosedSinceMouseEnter = true;
-
-            this._applyTabBarItemSizesAndPositions(beforeTabSizesAndPositions);
-
-            var removeStylesListener = removeStyles.bind(this);
-
-            requestAnimationFrame(animateTabs.bind(this));
-        } else
-            this.needsLayout();
-
-        this.updateNewTabTabBarItemState();
-
-        this.dispatchEventToListeners(WI.TabBar.Event.TabBarItemRemoved, {tabBarItem});
-
-        if (shouldOpenDefaultTab)
-            this._openDefaultTab();
-
-        return tabBarItem;
-    }
-
-    selectPreviousTab()
-    {
-        if (this._tabBarItems.length <= 1)
-            return;
-
-        var startIndex = this._tabBarItems.indexOf(this._selectedTabBarItem);
-        var newIndex = startIndex;
-        do {
-            if (newIndex === 0)
-                newIndex = this._tabBarItems.length - 1;
-            else
-                newIndex--;
-
-            if (!(this._tabBarItems[newIndex] instanceof WI.PinnedTabBarItem))
-                break;
-        } while (newIndex !== startIndex);
-
-        if (newIndex === startIndex)
-            return;
-
-        this.selectedTabBarItem = this._tabBarItems[newIndex];
-    }
-
-    selectNextTab()
-    {
-        if (this._tabBarItems.length <= 1)
-            return;
-
-        var startIndex = this._tabBarItems.indexOf(this._selectedTabBarItem);
-        var newIndex = startIndex;
-        do {
-            if (newIndex === this._tabBarItems.length - 1)
-                newIndex = 0;
-            else
-                newIndex++;
-
-            if (!(this._tabBarItems[newIndex] instanceof WI.PinnedTabBarItem))
-                break;
-        } while (newIndex !== startIndex);
-
-        if (newIndex === startIndex)
-            return;
-
-        this.selectedTabBarItem = this._tabBarItems[newIndex];
-    }
-
-    get selectedTabBarItem()
-    {
-        return this._selectedTabBarItem;
-    }
-
-    set selectedTabBarItem(tabBarItemOrIndex)
-    {
-        this.selectTabBarItem(tabBarItemOrIndex);
-    }
-
-    selectTabBarItem(tabBarItemOrIndex, options = {})
-    {
-        let tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
-        if (tabBarItem === this._newTabTabBarItem || tabBarItem === this._tabPickerTabBarItem) {
-            // Get the last normal tab item if the item is not selectable.
-            tabBarItem = this._tabBarItems[this.normalTabCount - 1];
-        }
-
-        if (this._selectedTabBarItem === tabBarItem)
-            return;
-
-        let previousTabBarItem = this._selectedTabBarItem;
-
-        if (this._selectedTabBarItem)
-            this._selectedTabBarItem.selected = false;
-
-        this._selectedTabBarItem = tabBarItem || null;
-
-        if (this._selectedTabBarItem) {
-            this._selectedTabBarItem.selected = true;
-            if (this._selectedTabBarItem.element.classList.contains("hidden"))
-                this.needsLayout();
-        }
-
-        let initiatorHint = options.initiatorHint || WI.TabBrowser.TabNavigationInitiator.Unknown;
-        this.dispatchEventToListeners(WI.TabBar.Event.TabBarItemSelected, {previousTabBarItem, initiatorHint});
-    }
-
-    get tabBarItems()
-    {
-        return this._tabBarItems;
-    }
-
-    get normalTabCount()
-    {
-        return this._tabBarItems.filter((item) => !(item instanceof WI.PinnedTabBarItem)).length;
-    }
-
-    get saveableTabCount()
-    {
-        return this._tabBarItems.filter((item) => item.representedObject && item.representedObject.constructor.shouldSaveTab()).length;
-    }
-
-    // Protected
-
-    layout()
-    {
-        if (this.element.classList.contains("static-layout"))
-            return;
-
-        this.element.classList.add("calculate-width");
-        this.element.classList.remove("collapsed");
-
-        function forceItemHidden(item, hidden) {
-            item.element.classList.toggle("hidden", !!hidden);
-        }
-
-        for (let item of this._tabBarItems)
-            forceItemHidden(item, item === this._tabPickerTabBarItem);
-
-        function measureItemWidth(item) {
-            if (!item[WI.TabBar.CachedWidthSymbol])
-                item[WI.TabBar.CachedWidthSymbol] = item.element.realOffsetWidth;
-            return item[WI.TabBar.CachedWidthSymbol];
-        }
-
-        let recalculateItemWidths = () => {
-            return this._tabBarItems.reduce((total, item) => {
-                item[WI.TabBar.CachedWidthSymbol] = undefined;
-                return total + measureItemWidth(item);
-            }, 0);
-        };
-
-        this._hiddenTabBarItems = [];
-
-        let totalItemWidth = recalculateItemWidths();
-        let barWidth = this.element.realOffsetWidth;
-
-        if (totalItemWidth > barWidth) {
-            this.element.classList.add("collapsed");
-            totalItemWidth = recalculateItemWidths();
-            if (totalItemWidth > barWidth) {
-                forceItemHidden(this._tabPickerTabBarItem, false);
-                totalItemWidth += measureItemWidth(this._tabPickerTabBarItem);
-            }
-
-            let tabBarItems = this._tabBarItemsFromLeftToRight();
-            let index = tabBarItems.length;
-            while (totalItemWidth > barWidth && --index >= 0) {
-                let item = tabBarItems[index];
-                if (item === this.selectedTabBarItem || item instanceof WI.PinnedTabBarItem)
-                    continue;
-
-                totalItemWidth -= measureItemWidth(item);
-                forceItemHidden(item, true);
-
-                this._hiddenTabBarItems.push(item);
-            }
-        }
-
-        this.element.classList.remove("calculate-width");
-    }
-
-    // Private
-
-    _tabBarItemsFromLeftToRight()
-    {
-        return WI.resolvedLayoutDirection() === WI.LayoutDirection.LTR ? this._tabBarItems : this._tabBarItems.slice().reverse();
-    }
-
-    _findTabBarItem(tabBarItemOrIndex)
-    {
-        if (typeof tabBarItemOrIndex === "number")
-            return this._tabBarItems[tabBarItemOrIndex] || null;
-
-        if (tabBarItemOrIndex instanceof WI.TabBarItem) {
-            if (this._tabBarItems.includes(tabBarItemOrIndex))
-                return tabBarItemOrIndex;
-        }
-
-        return null;
-    }
-
-    _hasMoreThanOneNormalTab()
-    {
-        let normalTabCount = 0;
-        for (let tabBarItem of this._tabBarItems) {
-            if (tabBarItem instanceof WI.PinnedTabBarItem)
-                continue;
-
-            ++normalTabCount;
-            if (normalTabCount >= 2)
-                return true;
-        }
-
-        return false;
-    }
-
-    _openDefaultTab()
-    {
-        this.dispatchEventToListeners(WI.TabBar.Event.OpenDefaultTab);
-    }
-
-    _recordTabBarItemSizesAndPositions()
-    {
-        var tabBarItemSizesAndPositions = new Map;
-
-        const barRect = this.element.getBoundingClientRect();
-
-        for (var tabBarItem of this._tabBarItems) {
-            var boundingRect = tabBarItem.element.getBoundingClientRect();
-            tabBarItemSizesAndPositions.set(tabBarItem, {left: boundingRect.left - barRect.left, width: boundingRect.width});
-        }
-
-        return tabBarItemSizesAndPositions;
-    }
-
-    _applyTabBarItemSizesAndPositions(tabBarItemSizesAndPositions, skipTabBarItem)
-    {
-        for (var [tabBarItem, sizeAndPosition] of tabBarItemSizesAndPositions) {
-            if (skipTabBarItem && tabBarItem === skipTabBarItem)
-                continue;
-            tabBarItem.element.style.left = sizeAndPosition.left + "px";
-            tabBarItem.element.style.width = sizeAndPosition.width + "px";
-        }
-    }
-
-    _clearTabBarItemSizesAndPositions(skipTabBarItem)
-    {
-        for (var tabBarItem of this._tabBarItems) {
-            if (skipTabBarItem && tabBarItem === skipTabBarItem)
-                continue;
-            tabBarItem.element.style.left = null;
-            tabBarItem.element.style.width = null;
-        }
-    }
-
-    _finishExpandingTabsAfterClose(beforeTabSizesAndPositions)
-    {
-        return new Promise(function(resolve, reject) {
-            console.assert(this._tabAnimatedClosedSinceMouseEnter);
-            this._tabAnimatedClosedSinceMouseEnter = false;
-
-            if (!beforeTabSizesAndPositions)
-                beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
-
-            this.element.classList.remove("static-layout");
-            this._clearTabBarItemSizesAndPositions();
-
-            var afterTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
-
-            this._applyTabBarItemSizesAndPositions(beforeTabSizesAndPositions);
-            this.element.classList.add("static-layout");
-
-            function animateTabs()
-            {
-                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);
-            }
-
-            function removeStyles()
-            {
-                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);
-
-                resolve();
-            }
-
-            var removeStylesListener = removeStyles.bind(this);
-
-            requestAnimationFrame(animateTabs.bind(this));
-        }.bind(this));
-    }
-
-    _handleMouseDown(event)
-    {
-        // Only consider left mouse clicks for tab movement.
-        if (event.button !== 0 || event.ctrlKey)
-            return;
-
-        let itemElement = event.target.closest("." + WI.TabBarItem.StyleClassName);
-        if (!itemElement)
-            return;
-
-        let tabBarItem = itemElement[WI.TabBarItem.ElementReferenceSymbol];
-        if (!tabBarItem)
-            return;
-
-        if (tabBarItem.disabled)
-            return;
-
-        if (tabBarItem === this._newTabTabBarItem)
-            return;
-
-        if (tabBarItem === this._tabPickerTabBarItem) {
-            if (!this._hiddenTabBarItems.length)
-                return;
-
-            if (this._ignoreTabPickerMouseDown)
-                return;
-
-            this._ignoreTabPickerMouseDown = true;
-
-            let contextMenu = WI.ContextMenu.createFromEvent(event);
-            contextMenu.addBeforeShowCallback(() => {
-                this._ignoreTabPickerMouseDown = false;
-            });
-
-            for (let item of this._hiddenTabBarItems) {
-                contextMenu.appendItem(item.title, () => {
-                    this.selectTabBarItem(item, {
-                        initiatorHint: WI.TabBrowser.TabNavigationInitiator.ContextMenu,
-                    });
-                });
-            }
-
-            contextMenu.show();
-            return;
-        }
-
-        let closeButtonElement = event.target.closest("." + WI.TabBarItem.CloseButtonStyleClassName);
-        if (closeButtonElement)
-            return;
-
-        this.selectTabBarItem(tabBarItem, {
-            initiatorHint: WI.TabBrowser.TabNavigationInitiator.TabClick,
-        });
-
-        if (tabBarItem instanceof WI.PinnedTabBarItem || !this._hasMoreThanOneNormalTab())
-            return;
-
-        this._firstNormalTabItemIndex = 0;
-        for (let i = 0; i < this._tabBarItems.length; ++i) {
-            if (this._tabBarItems[i] instanceof WI.PinnedTabBarItem)
-                continue;
-
-            this._firstNormalTabItemIndex = i;
-            break;
-        }
-
-        this._mouseIsDown = true;
-
-        this._mouseMovedEventListener = this._handleMouseMoved.bind(this);
-        this._mouseUpEventListener = this._handleMouseUp.bind(this);
-
-        // Register these listeners on the document so we can track the mouse if it leaves the tab bar.
-        document.addEventListener("mousemove", this._mouseMovedEventListener, true);
-        document.addEventListener("mouseup", this._mouseUpEventListener, true);
-
-        event.preventDefault();
-        event.stopPropagation();
-    }
-
-    _handleClick(event)
-    {
-        var itemElement = event.target.closest("." + WI.TabBarItem.StyleClassName);
-        if (!itemElement)
-            return;
-
-        var tabBarItem = itemElement[WI.TabBarItem.ElementReferenceSymbol];
-        if (!tabBarItem)
-            return;
-
-        if (tabBarItem.disabled)
-            return;
-
-        const clickedMiddleButton = event.button === 1;
-
-        var closeButtonElement = event.target.closest("." + WI.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"))
-                return;
-
-            if (!event.altKey) {
-                let options = {
-                    suppressExpansion: true,
-                    initiatorHint: WI.TabBrowser.TabNavigationInitiator.TabClick,
-                };
-                this.removeTabBarItem(tabBarItem, options);
-                return;
-            }
-
-            for (let i = this._tabBarItems.length - 1; i >= 0; --i) {
-                let item = this._tabBarItems[i];
-                if (item === tabBarItem || item instanceof WI.PinnedTabBarItem)
-                    continue;
-                this.removeTabBarItem(item);
-            }
-        }
-    }
-
-    _handleMouseMoved(event)
-    {
-        console.assert(event.button === 0);
-        console.assert(this._mouseIsDown);
-        if (!this._mouseIsDown)
-            return;
-
-        console.assert(this._selectedTabBarItem);
-        if (!this._selectedTabBarItem)
-            return;
-
-        event.preventDefault();
-        event.stopPropagation();
-
-        if (!this.element.classList.contains("static-layout")) {
-            this._applyTabBarItemSizesAndPositions(this._recordTabBarItemSizesAndPositions());
-            this.element.classList.add("static-layout");
-            this.element.classList.add("dragging-tab");
-        }
-
-        if (this._mouseOffset === undefined)
-            this._mouseOffset = event.pageX - this._selectedTabBarItem.element.totalOffsetLeft;
-
-        var tabBarMouseOffset = event.pageX - this.element.totalOffsetLeft;
-        var newLeft = tabBarMouseOffset - this._mouseOffset;
-
-        this._selectedTabBarItem.element.style.left = newLeft + "px";
-
-        var selectedTabMidX = newLeft + (this._selectedTabBarItem.element.realOffsetWidth / 2);
-
-        var currentIndex = this._tabBarItems.indexOf(this._selectedTabBarItem);
-        var newIndex = currentIndex;
-
-        for (let tabBarItem of this._tabBarItems) {
-            if (tabBarItem === this._selectedTabBarItem)
-                continue;
-
-            var tabBarItemRect = tabBarItem.element.getBoundingClientRect();
-
-            if (selectedTabMidX < tabBarItemRect.left || selectedTabMidX > tabBarItemRect.right)
-                continue;
-
-            newIndex = this._tabBarItems.indexOf(tabBarItem);
-            break;
-        }
-
-        // Subtract 1 from normalTabCount since arrays begin indexing at 0.
-        newIndex = Number.constrain(newIndex, this._firstNormalTabItemIndex, this.normalTabCount - 1);
-
-        if (currentIndex === newIndex)
-            return;
-
-        this._tabBarItems.splice(currentIndex, 1);
-        this._tabBarItems.splice(newIndex, 0, this._selectedTabBarItem);
-
-        let nextSibling = this._tabBarItems[newIndex + 1];
-        let nextSiblingElement = nextSibling ? nextSibling.element : this._newTabTabBarItem.element;
-
-        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.
-
-        let left = 0;
-        for (let tabBarItem of this._tabBarItemsFromLeftToRight()) {
-            if (tabBarItem !== this._selectedTabBarItem && tabBarItem !== this._newTabTabBarItem && parseFloat(tabBarItem.element.style.left) !== left)
-                tabBarItem.element.style.left = left + "px";
-            left += parseFloat(tabBarItem.element.style.width);
-        }
-    }
-
-    _handleMouseUp(event)
-    {
-        console.assert(event.button === 0);
-        console.assert(this._mouseIsDown);
-        if (!this._mouseIsDown)
-            return;
-
-        this.element.classList.remove("dragging-tab");
-
-        if (!this._tabAnimatedClosedSinceMouseEnter) {
-            this.element.classList.remove("static-layout");
-            this._clearTabBarItemSizesAndPositions();
-        } else {
-            let left = 0;
-            for (let tabBarItem of this._tabBarItemsFromLeftToRight()) {
-                if (tabBarItem === this._selectedTabBarItem)
-                    tabBarItem.element.style.left = left + "px";
-                left += parseFloat(tabBarItem.element.style.width);
-            }
-        }
-
-        this._mouseIsDown = false;
-        this._mouseOffset = undefined;
-
-        document.removeEventListener("mousemove", this._mouseMovedEventListener, true);
-        document.removeEventListener("mouseup", this._mouseUpEventListener, true);
-
-        this._mouseMovedEventListener = null;
-        this._mouseUpEventListener = null;
-
-        event.preventDefault();
-        event.stopPropagation();
-
-        this.dispatchEventToListeners(WI.TabBar.Event.TabBarItemsReordered);
-    }
-
-    _handleMouseLeave(event)
-    {
-        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?
-        const barRect = this.element.getBoundingClientRect();
-        const newTabItemRect = this._newTabTabBarItem.element.getBoundingClientRect();
-        if (event.pageY > barRect.top && event.pageY < barRect.bottom && event.pageX > barRect.left && event.pageX < (newTabItemRect ? newTabItemRect.right : barRect.right))
-            return;
-
-        this._finishExpandingTabsAfterClose();
-    }
-
-    _handleContextMenu(event)
-    {
-        let contextMenu = WI.ContextMenu.createFromEvent(event);
-
-        for (let tabClass of WI.knownTabClasses()) {
-            if (!tabClass.isTabAllowed() || tabClass.tabInfo().isEphemeral)
-                continue;
-
-            let openTabBarItem = null;
-            for (let tabBarItem of this._tabBarItems) {
-                let tabContentView = tabBarItem.representedObject;
-                if (!(tabContentView instanceof WI.TabContentView))
-                    continue;
-
-                if (tabContentView.type === tabClass.Type) {
-                    openTabBarItem = tabBarItem;
-                    break;
-                }
-            }
-
-            contextMenu.appendCheckboxItem(tabClass.tabInfo().title, () => {
-                if (openTabBarItem)
-                    this.removeTabBarItem(openTabBarItem);
-                else
-                    WI.createNewTabWithType(tabClass.Type, {shouldShowNewTab: true});
-            }, !!openTabBarItem);
-        }
-    }
-
-    _handleNewTabClick(event)
-    {
-        let options = {initiatorHint: WI.TabBrowser.TabNavigationInitiator.TabClick};
-        WI.showNewTabTab(options);
-    }
-
-    _handleNewTabMouseEnter(event)
-    {
-        if (!this._tabAnimatedClosedSinceMouseEnter || !this.element.classList.contains("static-layout") || this.element.classList.contains("animating"))
-            return;
-
-        this._finishExpandingTabsAfterClose();
-    }
-};
index 10cd64a..c9e7383 100644 (file)
@@ -64,10 +64,6 @@ body {
     background-color: var(--background-color-content);
 }
 
-body.docked.bottom {
-    border-top: 1px solid var(--border-color);
-}
-
 body.docked.right {
     border-left: 1px solid var(--border-color);
 }
@@ -113,12 +109,23 @@ body.docked.left #docked-resizer {
     cursor: col-resize;
 }
 
-body.docked.bottom #toolbar {
-    cursor: row-resize;
+#undocked-title-area {
+    position: absolute;
+    top: 0;
+    right: 0;
+    left: 0;
+    height: var(--undocked-title-area-height);
+    background-image: linear-gradient(to bottom, hsl(0, 0%, 92%), hsl(0, 0%, 87%));
+    box-shadow: inset hsla(0, 0%, 100%, 0.5) 0 1px 1px;
 }
 
-body.docked.bottom #toolbar .item:not(.flexible-space) {
-    cursor: default;
+body.docked #undocked-title-area {
+    display: none;
+}
+
+body.window-inactive #undocked-title-area {
+    background-color: hsl(0, 0%, 96%);
+    background-image: none;
 }
 
 input[type=range] {
@@ -137,7 +144,7 @@ input[type=range]::-webkit-slider-runnable-track {
 
 #main {
     position: absolute;
-    top: calc(var(--toolbar-height) + var(--tab-bar-height));
+    top: calc(var(--undocked-title-area-height) + var(--tab-bar-height));
     left: 0;
     right: 0;
     bottom: 0;
@@ -475,6 +482,15 @@ body[dir=rtl] [dir=ltr] .go-to-arrow {
     }
 }
 
+@keyframes tab-bar-console-item-pulse {
+    50% { opacity: 0.6; }
+}
+
+.tab-bar > .navigation-bar :matches(.console-warnings, .console-errors):not(.disabled).pulsing {
+    animation-name: tab-bar-console-item-pulse;
+    animation-duration: 0.75s;
+}
+
 .device-settings-content {
     position: relative;
     padding: 0 4px;
@@ -539,6 +555,15 @@ body[dir=rtl] .device-settings-content > .reference-page-link-container {
 }
 
 @media (prefers-color-scheme: dark) {
+    #undocked-title-area {
+        background-image: linear-gradient(to bottom, hsl(0, 0%, 26%), hsl(0, 0%, 23%));
+        box-shadow: none;
+    }
+
+    body.window-inactive #undocked-title-area {
+        background-color: var(--background-color);
+    }
+
     .go-to-arrow {
         filter: invert();
     }
index 9967ecb..83afb92 100644 (file)
@@ -25,7 +25,7 @@
 
 WI.NavigationBar = class NavigationBar extends WI.View
 {
-    constructor(element, navigationItems, role, label)
+    constructor(element, {role, sizesToFit, navigationItems} = {})
     {
         super(element);
 
@@ -33,20 +33,19 @@ WI.NavigationBar = class NavigationBar extends WI.View
 
         if (role)
             this.element.setAttribute("role", role);
-        if (label)
-            this.element.setAttribute("aria-label", label);
 
         this.element.addEventListener("keydown", this._keyDown.bind(this), false);
         this.element.addEventListener("mousedown", this._mouseDown.bind(this), true);
 
         this._role = role;
-        this._mouseMovedEventListener = this._mouseMoved.bind(this);
-        this._mouseUpEventListener = this._mouseUp.bind(this);
-
+        this._sizesToFit = sizesToFit || false;
         this._minimumWidth = NaN;
         this._navigationItems = [];
         this._selectedNavigationItem = null;
 
+        this._mouseMovedEventListener = this._mouseMoved.bind(this);
+        this._mouseUpEventListener = this._mouseUp.bind(this);
+
         if (navigationItems) {
             for (var i = 0; i < navigationItems.length; ++i)
                 this.addNavigationItem(navigationItems[i]);
@@ -55,9 +54,11 @@ WI.NavigationBar = class NavigationBar extends WI.View
 
     // Public
 
+    get sizesToFit() { return this._sizesToFit; }
+
     addNavigationItem(navigationItem, parentElement)
     {
-        return this.insertNavigationItem(navigationItem, this._navigationItems.length, parentElement);
+        return this.insertNavigationItem(navigationItem, Infinity, parentElement);
     }
 
     insertNavigationItem(navigationItem, index, parentElement)
@@ -71,7 +72,7 @@ WI.NavigationBar = class NavigationBar extends WI.View
 
         navigationItem.didAttach(this);
 
-        console.assert(index >= 0 && index <= this._navigationItems.length);
+        console.assert(!isFinite(index) || (index >= 0 && index <= this._navigationItems.length));
         index = Math.max(0, Math.min(index, this._navigationItems.length));
 
         this._navigationItems.splice(index, 0, navigationItem);
@@ -166,12 +167,6 @@ WI.NavigationBar = class NavigationBar extends WI.View
         return this._minimumWidth;
     }
 
-    get sizesToFit()
-    {
-        // Can be overridden by subclasses.
-        return false;
-    }
-
     findNavigationItem(identifier)
     {
         function matchingSelfOrChild(item) {
index bea568f..c02ecb8 100644 (file)
@@ -28,7 +28,7 @@
     top: 0;
     left: 0;
     right: 0;
-    bottom: 0;
+    bottom: var(--network-statistics-height);
     /* left or right set by NetworkTableView on display / resize */
     z-index: 10;
     background-color: white;
index b0e3a30..65110ac 100644 (file)
 
 WI.NetworkTabContentView = class NetworkTabContentView extends WI.TabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.NetworkTabContentView.tabInfo());
-
-        super(identifier || "network", "network", tabBarItem);
+        super(NetworkTabContentView.tabInfo());
 
         this._networkTableContentView = new WI.NetworkTableContentView;
 
@@ -50,6 +48,7 @@ WI.NetworkTabContentView = class NetworkTabContentView extends WI.TabContentView
     static tabInfo()
     {
         return {
+            identifier: NetworkTabContentView.Type,
             image: "Images/Network.svg",
             title: WI.UIString("Network"),
         };
index bbf2624..e297819 100644 (file)
     content: url(../Images/NetworkHAR.svg);
 }
 
-.content-view.network .network-table .icon {
+.content-view.network .network-table {
+    display: flex;
+    flex-direction: column;
+}
+
+.content-view.network .network-table > .table .icon {
     position: relative;
     width: 16px;
     height: 16px;
@@ -49,7 +54,7 @@
     opacity: 0.5;
 }
 
-.network-table li:not(.filler) .cell.name {
+.network-table > .table li:not(.filler) .cell.name {
     cursor: pointer;
 }
 
@@ -57,7 +62,7 @@
     content: url(../Images/InstrumentIcons.svg#DOMElement-light);
 }
 
-.network-table .cell.dom-node.name .disclosure {
+.network-table > .table .cell.dom-node.name .disclosure {
     width: 13px;
     height: 13px;
     vertical-align: -2px;
     background-repeat: no-repeat;
 }
 
-body[dir=rtl] .network-table .cell.dom-node.name .disclosure {
+body[dir=rtl] .network-table > .table .cell.dom-node.name .disclosure {
     transform: scaleX(-1);
 }
 
-.network-table:focus li.selected .cell.dom-node.name .disclosure {
+.network-table:focus > .table li.selected .cell.dom-node.name .disclosure {
     content: url(../Images/DisclosureTriangles.svg#closed-selected);
 }
 
-.network-table .cell.dom-node.name .disclosure.expanded {
+.network-table > .table .cell.dom-node.name .disclosure.expanded {
     content: url(../Images/DisclosureTriangles.svg#open-normal);
 }
 
-.network-table:focus li.selected .cell.dom-node.name .disclosure.expanded {
+.network-table:focus > .table li.selected .cell.dom-node.name .disclosure.expanded {
     content: url(../Images/DisclosureTriangles.svg#open-selected);
 }
 
-.network-table.grouped .data-container .cell.name {
+.network-table > .table.grouped .data-container .cell.name {
     --item-padding-start: 19px;
     --item-disclosure-width: 11px;
 }
 
-.network-table.grouped .data-container .cell:not(.parent).name {
+.network-table > .table.grouped .data-container .cell:not(.parent).name {
     -webkit-padding-start: var(--item-padding-start);
 }
 
-.network-table.grouped .data-container .cell.child.name {
+.network-table > .table.grouped .data-container .cell.child.name {
     -webkit-padding-start: calc(var(--item-padding-start) + var(--item-disclosure-width));
 }
 
-.network-table .data-container .cell.name .range {
+.network-table > .table .data-container .cell.name .range {
     color: hsla(0, 0%, 0%, 0.7);
 }
 
-.network-table .data-container .cell.name .range::before {
+.network-table > .table .data-container .cell.name .range::before {
     content: "\00A0\2014\00A0"; /* &nbsp;&mdash;&nbsp; */;
 }
 
-.network-table:focus .data-container li.selected .cell.name .range {
+.network-table:focus > .table .data-container li.selected .cell.name .range {
     color: hsla(0, 0%, 100%, 0.9);
 }
 
-.network-table li:not(.selected) .cell:matches(.cache-type, .multiple) {
+.network-table > .table li:not(.selected) .cell:matches(.cache-type, .multiple) {
     color: var(--text-color-gray-medium);
 }
 
-.network-table .error {
+.network-table > .table .error {
     color: var(--error-text-color);
 }
 
-.network-table .cell.domain > .lock {
+.network-table > .table .cell.domain > .lock {
     width: 8px;
     height: 10px;
     content: url(../Images/Locked.svg);
     -webkit-margin-end: 5px;
 }
 
-.network-table li.selected .cell.domain > .lock {
+.network-table > .table li.selected .cell.domain > .lock {
     /* FIXME: <https://webkit.org/b/189773> Web Inspector: create special Network waterfall for media events */
     filter: invert();
 }
 
-.network-table .cell.name > .status {
+.network-table > .table .cell.name > .status {
     -webkit-margin-start: 4px;
 }
 
-body[dir=ltr] .network-table .cell.name > .status {
+body[dir=ltr] .network-table > .table .cell.name > .status {
     float: right;
 }
 
-body[dir=rtl] .network-table .cell.name > .status {
+body[dir=rtl] .network-table > .table .cell.name > .status {
     float: left;
 }
 
-.network-table .cell.name > .status .indeterminate-progress-spinner {
+.network-table > .table .cell.name > .status .indeterminate-progress-spinner {
     margin-top: 3px;
     width: 14px;
     height: 14px;
 }
 
-.showing-detail .network-table .cell:not(.name) {
+.network-table.showing-detail > .table .cell:not(.name) {
     display: none;
 }
 
-.showing-detail .network-table .resizer:not(:first-of-type) {
+.network-table.showing-detail > .table .resizer:not(:first-of-type) {
     display: none;
 }
 
-.showing-detail .network-table .timeline-ruler {
+.network-table.showing-detail > .table .timeline-ruler {
     display: none;
 }
 
-.network-table .header .cell.waterfall {
+.network-table > .table .header .cell.waterfall {
     /* Hide the label for this column. */
     color: transparent;
 }
 
-.network-table :not(.header) .cell:first-of-type {
+.network-table > .table :not(.header) .cell:first-of-type {
     background: rgba(0, 0, 0, 0.07);
 }
 
-.network-table :not(.header) .cell.waterfall {
+.network-table > .table :not(.header) .cell.waterfall {
     position: absolute;
     height: 20px;
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container {
     position: absolute;
     top: 0;
     left: 0;
@@ -179,7 +184,7 @@ body[dir=rtl] .network-table .cell.name > .status {
     bottom: 0;
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-event {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .dom-event {
     position: absolute;
     top: calc(50% - (var(--node-waterfall-dom-event-size) / 2));
     min-width: var(--node-waterfall-dom-event-size);
@@ -188,17 +193,17 @@ body[dir=rtl] .network-table .cell.name > .status {
     border-radius: calc(var(--node-waterfall-dom-event-size) / 2);
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-activity {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .dom-activity {
     position: absolute;
     top: calc(50% - 0.5px);
     border-top: 1px dashed var(--selected-background-color-active);
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .dom-activity.playing {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .dom-activity.playing {
     border-top-style: solid;
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .area {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .area {
     position: absolute;
     top: var(--area-padding);
     height: calc(100% - (var(--area-padding) * 2));
@@ -207,22 +212,22 @@ body[dir=rtl] .network-table .cell.name > .status {
     --area-padding: calc((50% - (var(--node-waterfall-dom-event-size) / 2)) / 2);
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .area.dom-fullscreen {
     background-color: hsl(0, 0%, 40%);
 }
 
-.network-table :not(.header) .cell.waterfall .waterfall-container > .area.power-efficient-playback {
+.network-table > .table :not(.header) .cell.waterfall .waterfall-container > .area.power-efficient-playback {
     background-color: var(--network-request-color);
 }
 
-.network-table .timeline-ruler {
+.network-table > .table .timeline-ruler {
     position: absolute;
     top: 0;
     bottom: 0;
     overflow: hidden;
 }
 
-.network-table .timeline-ruler > .header {
+.network-table > .table .timeline-ruler > .header {
     top: calc(var(--navigation-bar-height) - var(--timeline-ruler-height));
 }
 
@@ -231,7 +236,7 @@ body[dir=rtl] .network-table .cell.name > .status {
     font-weight: normal;
 }
 
-.waterfall .block {
+.network-table > .table .waterfall .block {
     position: absolute;
     top: 8px;
     min-width: 2px;
@@ -241,14 +246,14 @@ body[dir=rtl] .network-table .cell.name > .status {
     --end-radius: 2px;
 }
 
-body[dir=ltr] .waterfall .block {
+body[dir=ltr] .network-table > .table .waterfall .block {
     border-top-left-radius: var(--start-radius);
     border-top-right-radius: var(--end-radius);
     border-bottom-left-radius: var(--start-radius);
     border-bottom-right-radius: var(--end-radius);
 }
 
-body[dir=rtl] .waterfall .block {
+body[dir=rtl] .network-table > .table .waterfall .block {
     border-top-left-radius: var(--end-radius);
     border-top-right-radius: var(--start-radius);
     border-bottom-left-radius: var(--end-radius);
@@ -269,62 +274,91 @@ body[dir=rtl] .waterfall .block {
     --end-radius: 2px;
 }
 
-.waterfall .block.request,
-.waterfall .block.response {
+.network-table > .table .waterfall .block.request,
+.network-table > .table .waterfall .block.response {
     top: 3px;
     height: 14px;
 }
 
-.waterfall .block.mouse-tracking {
+.network-table > .table .waterfall .block.mouse-tracking {
     top: 1px;
     z-index: 2;
     height: 18px;
 }
 
-.waterfall .block.filler {
+.network-table > .table .waterfall .block.filler {
     top: 9px;
     height: 2px;
     background-color: lightgrey;
 }
 
-.waterfall .block.redirect {
+.network-table > .table .waterfall .block.redirect {
     background-color: var(--network-redirect-color);
 }
 
-.waterfall .block.queue {
+.network-table > .table .waterfall .block.queue {
     background-color: var(--network-queue-color);
 }
 
-.waterfall .block.dns {
+.network-table > .table .waterfall .block.dns {
     background-color: var(--network-dns-color);
 }
 
-.waterfall .block.connect {
+.network-table > .table .waterfall .block.connect {
     background-color: var(--network-connect-color);
 }
 
-.waterfall .block.secure {
+.network-table > .table .waterfall .block.secure {
     background-color: var(--network-secure-color);
 }
 
-.waterfall .block.request {
+.network-table > .table .waterfall .block.request {
     background-color: var(--network-request-color);
 }
 
-.waterfall .block.response {
+.network-table > .table .waterfall .block.response {
     background-color: var(--network-response-color);
 }
 
+.network-table > .statistics {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    min-height: var(--network-statistics-height);
+    padding: 4px 0;
+    border-top: 1px solid var(--border-color);
+}
+
+.network-table > .statistics > .statistic {
+    display: flex;
+    padding: 0 8px;
+}
+
+.network-table > .statistics > .statistic[hidden] {
+    display: none;
+}
+
+.network-table > .statistics > .statistic > .icon {
+    width: 16px;
+    height: 16px;
+}
+
+.network-table > .statistics > .statistic > .text {
+    padding-top: 1px;
+    -webkit-padding-start: 4px;
+    -webkit-user-select: all;
+}
+
 @media (prefers-color-scheme: dark) {
     .content-view.tab.network > .content-browser > .navigation-bar .hierarchical-path .icon {
         filter: invert(88%);
     }
 
-    .network-table .cell.domain > .lock {
+    .network-table > .table .cell.domain > .lock {
         filter: var(--filter-invert);
     }
 
-    .network-table .data-container .cell.name .range {
+    .network-table > .table .data-container .cell.name .range {
         color: var(--text-color-secondary);
     }
 
index b2ce2a9..4e837fa 100644 (file)
@@ -56,6 +56,10 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         // FIXME: Network Timeline.
         // FIXME: Throttling.
 
+        this._statistics = {};
+
+        this.element.classList.add("network-table");
+
         this._typeFilterScopeBarItemAll = new WI.ScopeBarItem("network-type-filter-all", WI.UIString("All"), {exclusive: true});
         let typeFilterScopeBarItems = [this._typeFilterScopeBarItemAll];
 
@@ -164,6 +168,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         WI.Frame.addEventListener(WI.Frame.Event.ChildFrameWasAdded, this._handleFrameWasAdded, this);
         WI.Resource.addEventListener(WI.Resource.Event.LoadingDidFinish, this._resourceLoadingDidFinish, this);
         WI.Resource.addEventListener(WI.Resource.Event.LoadingDidFail, this._resourceLoadingDidFail, this);
+        WI.Resource.addEventListener(WI.Resource.Event.SizeDidChange, this._handleResourceSizeDidChange, this);
         WI.Resource.addEventListener(WI.Resource.Event.TransferSizeDidChange, this._resourceTransferSizeDidChange, this);
         WI.networkManager.addEventListener(WI.NetworkManager.Event.MainFrameDidChange, this._mainFrameDidChange, this);
 
@@ -304,8 +309,11 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
 
     reset()
     {
-        this._runForMainCollection((collection) => {
+        this._runForMainCollection((collection, wasMain) => {
             this._resetCollection(collection);
+
+            if (wasMain)
+                this._updateStatistics();
         });
 
         for (let detailView of this._detailViewMap.values())
@@ -442,6 +450,8 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
     {
         let entry = this._activeCollection.filteredEntries[rowIndex];
 
+        cell.classList.toggle("current-session", entry.currentSession);
+
         if (entry.resource)
             cell.classList.toggle("error", entry.resource.hadLoadingError());
 
@@ -601,6 +611,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         this._updateFilteredEntries();
         this._updateWaterfallTimelineRuler();
         this._reloadTable();
+        this._updateStatistics();
         this._hideDetailView();
 
         this.needsLayout();
@@ -1238,6 +1249,31 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         }
 
         this.addSubview(this._table);
+
+        let statisticsContainer = this.element.appendChild(document.createElement("div"));
+        statisticsContainer.className = "statistics";
+
+        let createStatisticElement = (name, image) => {
+            let statistic = this._statistics[name];
+            if (!statistic)
+                statistic = this._statistics[name] = {};
+
+            statistic.container = statisticsContainer.appendChild(document.createElement("div"));
+            statistic.container.classList.add("statistic", name);
+
+            statistic.container.appendChild(WI.ImageUtilities.useSVGSymbol(image, "icon"));
+
+            statistic.element = statistic.container.appendChild(document.createElement("div"));
+            statistic.element.className = "text";
+        };
+        createStatisticElement("domain-count", "Images/Origin.svg");
+        createStatisticElement("resource-count", "Images/Resources.svg");
+        createStatisticElement("resource-size", "Images/Weight.svg");
+        createStatisticElement("transfer-size", "Images/Network.svg");
+        createStatisticElement("redirect-count", "Images/StepOver.svg");
+        createStatisticElement("load-time", "Images/Time.svg");
+
+        this._updateStatistics();
     }
 
     layout()
@@ -1272,6 +1308,8 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
 
         for (let resource of resources)
             this._insertResourceAndReloadTable(resource);
+
+        this._updateStatistics();
     }
 
     handleClearShortcut(event)
@@ -1359,6 +1397,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
                 this._insertResourceAndReloadTable(resource);
             console.assert(collection.pendingInsertions.length === originalLength);
             collection.pendingInsertions = [];
+            this._updateStatistics();
             return;
         }
 
@@ -1378,6 +1417,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         this._updateSort();
         this._updateFilteredEntries();
         this._reloadTable();
+        this._updateStatistics();
     }
 
     _populateWithInitialResourcesIfNeeded(collection)
@@ -1465,6 +1505,8 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
             return;
 
         updateExistingEntry(collection.filteredEntries[rowIndex], entry);
+
+        this._updateStatistics();
     }
 
     _hidePopover()
@@ -1595,23 +1637,33 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
 
     _mainResourceDidChange(event)
     {
-        this._runForMainCollection((collection, wasMain) => {
-            let frame = event.target;
-            if (frame.isMainFrame() && WI.settings.clearNetworkOnNavigate.value) {
-                this._resetCollection(collection);
+        let frame = event.target;
+
+        if (frame.isMainFrame() && !this._transitioningPageTarget)
+            this._startUpdatingLoadTimeStatistic();
 
-                if (wasMain && !this._needsInitialPopulate)
-                    this._hideDetailView();
+        this._runForMainCollection((collection, wasMain) => {
+            if (frame.isMainFrame()) {
+                if (WI.settings.clearNetworkOnNavigate.value) {
+                    this._resetCollection(collection);
+
+                    if (wasMain && !this._needsInitialPopulate)
+                        this._hideDetailView();
+                } else {
+                    for (let entry of collection.entries)
+                        entry.currentSession = false;
+                }
             }
 
             if (this._transitioningPageTarget) {
                 this._transitioningPageTarget = false;
                 this._needsInitialPopulate = true;
                 this._populateWithInitialResourcesIfNeeded(collection);
-                return;
-            }
+            } else
+                this._insertResourceAndReloadTable(frame.mainResource);
 
-            this._insertResourceAndReloadTable(frame.mainResource);
+            if (wasMain)
+                this._updateStatistics();
         });
     }
 
@@ -1654,6 +1706,41 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         });
     }
 
+    _handleResourceSizeDidChange(event)
+    {
+        if (!this._table)
+            return;
+
+        this._runForMainCollection((collection, wasMain) => {
+            let resource = event.target;
+
+            // In the unlikely event that this is the sort column, we may need to resort.
+            if (this._table.sortColumnIdentifier === "resourceSize") {
+                collection.pendingUpdates.push(resource);
+                this.needsLayout();
+                return;
+            }
+
+            let index = collection.entries.findIndex((x) => x.resource === resource);
+            if (index === -1)
+                return;
+
+            let entry = collection.entries[index];
+            entry.resourceSize = resource.size;
+
+            if (!wasMain)
+                return;
+
+            let rowIndex = this._rowIndexForRepresentedObject(resource);
+            if (rowIndex === -1)
+                return;
+
+            this._table.reloadCell(rowIndex, "resourceSize");
+
+            this._updateStatistics();
+        });
+    }
+
     _resourceTransferSizeDidChange(event)
     {
         if (!this._table)
@@ -1684,13 +1771,18 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
                 return;
 
             this._table.reloadCell(rowIndex, "transferSize");
+
+            this._updateStatistics();
         });
     }
 
     _handleResourceAdded(event)
     {
-        this._runForMainCollection((collection) => {
+        this._runForMainCollection((collection, wasMain) => {
             this._insertResourceAndReloadTable(event.data.resource);
+
+            if (wasMain)
+                this._updateStatistics();
         });
     }
 
@@ -1699,12 +1791,15 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         if (this._needsInitialPopulate)
             return;
 
-        this._runForMainCollection((collection) => {
+        this._runForMainCollection((collection, wasMain) => {
             let frame = event.data.childFrame;
             let mainResource = frame.provisionalMainResource || frame.mainResource;
             console.assert(mainResource, "Frame should have a main resource.");
             this._insertResourceAndReloadTable(mainResource);
 
+            if (wasMain)
+                this._updateStatistics();
+
             console.assert(!frame.resourceCollection.size, "New frame should be empty.");
             console.assert(!frame.childFrameCollection.size, "New frame should be empty.");
         });
@@ -1808,6 +1903,7 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
             remoteAddress: resource.remoteAddress,
             connectionIdentifier: resource.connectionIdentifier,
             startTime: resource.firstTimestamp,
+            currentSession: true,
         };
     }
 
@@ -1974,6 +2070,131 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
         this._updateEmptyFilterResultsMessage();
     }
 
+    _updateStatistics()
+    {
+        if (!this.didInitialLayout)
+            return;
+
+        let entries = this._activeCollection.entries.filter((entry) => entry.currentSession);
+
+        let domains = new Set;
+        let resourceSize = 0;
+        let transferSize = 0;
+        let redirectCount = 0;
+        for (let entry of entries) {
+            domains.add(entry.domain);
+            if (!isNaN(entry.resourceSize))
+                resourceSize += entry.resourceSize;
+            if (!isNaN(entry.transferSize))
+                transferSize += entry.transferSize;
+            if (entry.resource)
+                redirectCount += entry.resource.redirects.length;
+        }
+
+        this._updateStatistic("domain-count", domains.size === 1 ? WI.UIString("%d domain") : WI.UIString("%d domains"), domains.size);
+
+        let resourceCount = entries.length;
+        this._updateStatistic("resource-count", resourceCount === 1 ? WI.UIString("%d resource") : WI.UIString("%d resources"), resourceCount);
+
+        const higherResolution = false;
+        this._updateStatistic("resource-size", WI.UIString("%s total"), Number.bytesToString(resourceSize, higherResolution));
+        this._updateStatistic("transfer-size", WI.UIString("%s transferred"), Number.bytesToString(transferSize, higherResolution));
+
+        this._updateStatistic("redirect-count", redirectCount === 1 ? WI.UIString("%d redirect") : WI.UIString("%d redirects"), redirectCount);
+
+        let loadTimeStatistic = this._statistics["load-time"];
+        if (loadTimeStatistic.format && this._isShowingMainCollection()) {
+            this._updateStatistic("load-time");
+            loadTimeStatistic.container.hidden = false;
+        } else
+            loadTimeStatistic.container.hidden = true;
+    }
+
+    _updateStatistic(name, format, value)
+    {
+        let statistic = this._statistics[name];
+
+        if (format)
+            statistic.format = format;
+        else
+            format = statistic.format;
+
+        if (value || value === 0)
+            statistic.value = value;
+        else
+            value = statistic.value;
+
+        if (statistic.container)
+            statistic.container.title = format.format(value);
+
+        if (statistic.element)
+            statistic.element.textContent = value;
+    }
+
+    _startUpdatingLoadTimeStatistic()
+    {
+        this._stopUpdatingLoadTimeStatistic();
+
+        let loadTimeStatistic = this._statistics["load-time"];
+        if (!loadTimeStatistic)
+            loadTimeStatistic = this._statistics["load-time"] = {};
+
+        loadTimeStatistic.start = Date.now();
+        loadTimeStatistic.delay = 50;
+        loadTimeStatistic.timer = setInterval(this._updateLoadTimeStatistic.bind(this), loadTimeStatistic.delay);
+    }
+
+    _stopUpdatingLoadTimeStatistic()
+    {
+        let loadTimeStatistic = this._statistics["load-time"];
+        if (!loadTimeStatistic)
+            return;
+
+        if (loadTimeStatistic.timer) {
+            clearInterval(loadTimeStatistic.timer);
+            loadTimeStatistic.timer = undefined;
+        }
+    }
+
+    _updateLoadTimeStatistic()
+    {
+        let loadTimeStatistic = this._statistics["load-time"];
+        console.assert(loadTimeStatistic);
+
+        let duration = Date.now() - loadTimeStatistic.start;
+
+        let delay = loadTimeStatistic.delay;
+        if (duration >= 1000) // 1 second
+            delay = 100;
+        else if (duration >= 60000) // 60 seconds
+            delay = 1000;
+        else if (duration >= 3600000) // 1 minute
+            delay = 10000;
+
+        if (delay !== loadTimeStatistic.delay) {
+            loadTimeStatistic.delay = delay;
+
+            clearInterval(loadTimeStatistic.timer);
+            loadTimeStatistic.timer = setInterval(this._updateLoadTimeStatistic.bind(this), loadTimeStatistic.delay);
+        }
+
+        let mainFrame = WI.networkManager.mainFrame;
+        let mainFrameStartTime = mainFrame.mainResource.firstTimestamp;
+        let mainFrameLoadEventTime = mainFrame.loadEventTimestamp;
+
+        if (loadTimeStatistic.container)
+            loadTimeStatistic.container.hidden = !this._isShowingMainCollection();
+
+        if (isNaN(mainFrameStartTime) || isNaN(mainFrameLoadEventTime)) {
+            this._updateStatistic("load-time", WI.UIString("Loading for %s"), Number.secondsToString(duration / 1000));
+            return;
+        }
+
+        this._updateStatistic("load-time", WI.UIString("Loaded in %s"), Number.secondsToString(mainFrameLoadEventTime - mainFrameStartTime));
+
+        this._stopUpdatingLoadTimeStatistic();
+    }
+
     _reloadTable()
     {
         this._table.reloadData();
diff --git a/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css b/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css
deleted file mode 100644 (file)
index db299b5..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * 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.
- */
-
-.new-tab.tab.content-view {
-    display: flex;
-    flex-flow: row wrap;
-    justify-content: center;
-    align-content: center;
-    align-items: center;
-
-    background-color: hsl(0, 0%, 96%);
-
-    padding: 10px;
-
-    overflow-y: auto;
-}
-
-.new-tab.tab.content-view > .tab-item {
-    display: flex;
-
-    min-width: 110px;
-    min-height: 110px;
-
-    margin: 10px;
-
-    flex-direction: column;
-    align-items: center;
-}
-
-.new-tab.tab.content-view > .tab-item.disabled {
-    opacity: 0.5;
-    filter: brightness(90%);
-}
-
-.new-tab.tab.content-view > .tab-item > .box {
-    width: 94px;
-    height: 94px;
-
-    padding: 15px;
-    border-radius: 5px;
-
-    background-color: hsl(0, 0%, 82%);
-    box-shadow: hsla(0, 0%, 0%, 0.33) 0 1px 6px;
-
-    display: block;
-}
-
-.new-tab.tab.content-view > .tab-item:not(.disabled):hover > .box {
-    filter: brightness(90%);
-}
-
-.new-tab.tab.content-view > .tab-item:not(.disabled):active > .box {
-    filter: brightness(75%);
-}
-
-.new-tab.tab.content-view > .tab-item > .box > img {
-    width: 64px;
-    height: 64px;
-
-    opacity: 0.55; /* Assumes black glyphs. */
-
-    -webkit-user-drag: none;
-}
-
-.new-tab.tab.content-view > .tab-item > label {
-    display: block;
-    margin-top: 8px;
-}
-
-@media (prefers-color-scheme: dark) {
-    .new-tab.tab.content-view {
-        background-color: var(--background-color-content);
-    }
-}
diff --git a/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js b/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js
deleted file mode 100644 (file)
index a9b235f..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * 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.
- */
-
-WI.NewTabContentView = class NewTabContentView extends WI.TabContentView
-{
-    constructor(identifier)
-    {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.NewTabContentView.tabInfo());
-        tabBarItem.isDefaultTab = true;
-
-        super(identifier || "new-tab", "new-tab", tabBarItem);
-
-        this._tabElementsByTabClass = new Map;
-
-        let allTabClasses = Array.from(WI.knownTabClasses());
-        this._shownTabClasses = allTabClasses.filter((tabClass) => tabClass.isTabAllowed() && !tabClass.tabInfo().isEphemeral);
-        this._shownTabClasses.sort((a, b) => a.tabInfo().title.extendedLocaleCompare(b.tabInfo().title));
-    }
-
-    static tabInfo()
-    {
-        return {
-            image: "Images/NewTab.svg",
-            title: WI.UIString("New Tab"),
-            isEphemeral: true,
-        };
-    }
-
-    static shouldSaveTab()
-    {
-        return false;
-    }
-
-    // Public
-
-    get type()
-    {
-        return WI.NewTabContentView.Type;
-    }
-
-    shown()
-    {
-        WI.tabBar.addEventListener(WI.TabBar.Event.TabBarItemAdded, this._updateTabItems, this);
-        WI.tabBar.addEventListener(WI.TabBar.Event.TabBarItemRemoved, this._updateTabItems, this);
-
-        this._updateTabItems();
-    }
-
-    hidden()
-    {
-        WI.tabBar.removeEventListener(null, null, this);
-    }
-
-    get supportsSplitContentBrowser()
-    {
-        // Showing the split console is problematic because some new tabs will cause it to
-        // disappear and not reappear, but others won't. Just prevent it from ever showing.
-        return false;
-    }
-
-    layout()
-    {
-        this._tabElementsByTabClass.clear();
-        this.element.removeChildren();
-
-        for (let tabClass of this._shownTabClasses) {
-            let tabItemElement = document.createElement("div");
-            tabItemElement.classList.add("tab-item");
-            tabItemElement.addEventListener("click", this._createNewTabWithType.bind(this, tabClass.Type));
-            tabItemElement[WI.NewTabContentView.TypeSymbol] = tabClass.Type;
-
-            let boxElement = tabItemElement.appendChild(document.createElement("div"));
-            boxElement.classList.add("box");
-
-            let info = tabClass.tabInfo();
-            let imageElement = boxElement.appendChild(document.createElement("img"));
-            imageElement.src = info.image;
-
-            let labelElement = tabItemElement.appendChild(document.createElement("label"));
-            labelElement.textContent = info.title;
-
-            this.element.appendChild(tabItemElement);
-            this._tabElementsByTabClass.set(tabClass, tabItemElement);
-        }
-
-        this._updateTabItems();
-    }
-
-    // Private
-
-    _createNewTabWithType(tabType, event)
-    {
-        if (!WI.isNewTabWithTypeAllowed(tabType))
-            return;
-
-        const canCreateAdditionalTabs = this._allowableTabTypes().length > 1;
-        const options = {
-            referencedView: this,
-            shouldReplaceTab: !canCreateAdditionalTabs || !WI.modifierKeys.metaKey,
-            shouldShowNewTab: !WI.modifierKeys.metaKey,
-            initiatorHint: WI.TabBrowser.TabNavigationInitiator.ButtonClick,
-        };
-        WI.createNewTabWithType(tabType, options);
-    }
-
-    _allowableTabTypes()
-    {
-        let tabTypes = this._shownTabClasses.map((tabClass) => tabClass.Type);
-        return tabTypes.filter((type) => WI.isNewTabWithTypeAllowed(type));
-    }
-
-    _updateTabItems()
-    {
-        for (let [tabClass, tabItemElement] of this._tabElementsByTabClass.entries()) {
-            let allowed = WI.isNewTabWithTypeAllowed(tabClass.Type);
-            tabItemElement.classList.toggle(WI.NewTabContentView.DisabledStyleClassName, !allowed);
-        }
-    }
-};
-
-WI.NewTabContentView.Type = "new-tab";
-WI.NewTabContentView.TypeSymbol = Symbol("type");
-
-WI.NewTabContentView.TabItemStyleClassName = "tab-item";
-WI.NewTabContentView.DisabledStyleClassName = "disabled";
index 9b0bcc7..d58203b 100644 (file)
 
 WI.PinnedTabBarItem = class PinnedTabBarItem extends WI.TabBarItem
 {
-    constructor(image, title)
+    constructor(representedObject, image, title)
     {
-        super(image, title);
+        super(representedObject, image, title);
 
         this.element.classList.add("pinned");
-
-        this.element.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this));
     }
 
-    static fromTabInfo({image, title})
-    {
-        return new WI.PinnedTabBarItem(image, title);
-    }
+    // Static
 
-    titleDidChange()
+    static fromTabContentView(tabContentView)
     {
-        this.element.title = this.title;
+        console.assert(tabContentView instanceof WI.TabContentView);
+
+        let {image, title} = tabContentView.constructor.tabInfo();
+        return new WI.PinnedTabBarItem(tabContentView, image, title);
     }
 
-    // Private
+    // Protected
 
-    _handleContextMenuEvent(event)
+    titleDidChange()
     {
-        event.preventDefault();
-
-        let contextMenu = WI.ContextMenu.createFromEvent(event);
-
-        this.dispatchEventToListeners(WI.PinnedTabBarItem.Event.ContextMenu, {contextMenu});
+        this.element.title = this.title;
     }
 };
-
-WI.PinnedTabBarItem.Event = {
-    ContextMenu: "pinned-tab-bar-item-context-menu",
-};
index c7b7bc2..6bee1a1 100644 (file)
@@ -51,7 +51,8 @@ WI.QuickConsole = class QuickConsole extends WI.View
         // would be for CodeMirror's event handler to pass if it doesn't do anything.
         this.prompt.escapeKeyHandlerWhenEmpty = function() { WI.toggleSplitConsole(); };
 
-        this._navigationBar = new WI.SizesToFitNavigationBar;
+        const navigationbarElement = null;
+        this._navigationBar = new WI.NavigationBar(navigationbarElement, {sizesToFit: true});
         this.addSubview(this._navigationBar);
 
         this._activeExecutionContextNavigationItemDivider = new WI.DividerNavigationItem;
index ee1faca..cc5c7bd 100644 (file)
@@ -58,6 +58,6 @@
     pointer-events: none;
 }
 
-body.window-inactive .timeline-overview-graph.rendering-frame > .frame-marker {
+body:matches(.window-inactive, .window-docked-inactive) .timeline-overview-graph.rendering-frame > .frame-marker {
     background-image: linear-gradient(to right, hsl(0, 0%, 60%), hsl(0, 0%, 60%));
 }
index 34b32c7..0061640 100644 (file)
 
 WI.SearchTabContentView = class SearchTabContentView extends WI.ContentBrowserTabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem;
-        if (WI.settings.experimentalEnableNewTabBar.value)
-            tabBarItem = WI.PinnedTabBarItem.fromTabInfo(WI.SearchTabContentView.tabInfo());
-        else
-            tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.SearchTabContentView.tabInfo());
-
-        let detailsSidebarPanelConstructors = [WI.ResourceDetailsSidebarPanel, WI.ProbeDetailsSidebarPanel,
-            WI.DOMNodeDetailsSidebarPanel, WI.ComputedStyleDetailsSidebarPanel, WI.RulesStyleDetailsSidebarPanel];
-
+        let detailsSidebarPanelConstructors = [
+            WI.ResourceDetailsSidebarPanel,
+            WI.ProbeDetailsSidebarPanel,
+            WI.DOMNodeDetailsSidebarPanel,
+            WI.ComputedStyleDetailsSidebarPanel,
+            WI.RulesStyleDetailsSidebarPanel,
+        ];
         if (InspectorBackend.hasDomain("LayerTree"))
             detailsSidebarPanelConstructors.push(WI.LayerTreeDetailsSidebarPanel);
 
-        super(identifier || "search", "search", tabBarItem, WI.SearchSidebarPanel, detailsSidebarPanelConstructors);
-
-        // Ensures that the Search tab is displayable from a pinned tab bar item.
-        tabBarItem.representedObject = this;
+        super(SearchTabContentView.tabInfo(), {
+            navigationSidebarPanelConstructor: WI.SearchSidebarPanel,
+            detailsSidebarPanelConstructors,
+        });
 
         this._forcePerformSearch = false;
     }
 
     static tabInfo()
     {
-        let image = WI.settings.experimentalEnableNewTabBar.value ? "Images/Search.svg" : "Images/SearchResults.svg";
         return {
-            image,
+            identifier: SearchTabContentView.Type,
+            image: "Images/Search.svg",
             title: WI.UIString("Search"),
-            isEphemeral: true,
         };
     }
 
+    static shouldPinTab()
+    {
+        return true;
+    }
+
+    static shouldSaveTab()
+    {
+        return false;
+    }
+
     // Public
 
     get type()
index f816120..b1edaac 100644 (file)
 
 WI.SettingsTabContentView = class SettingsTabContentView extends WI.TabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem = WI.PinnedTabBarItem.fromTabInfo(WI.SettingsTabContentView.tabInfo());
-
-        super(identifier || "settings", "settings", tabBarItem);
-
-        // Ensures that the Settings tab is displayable from a pinned tab bar item.
-        tabBarItem.representedObject = this;
+        super(SettingsTabContentView.tabInfo());
 
         this._selectedSettingsView = null;
         this._settingsViews = [];
@@ -42,12 +37,17 @@ WI.SettingsTabContentView = class SettingsTabContentView extends WI.TabContentVi
     static tabInfo()
     {
         return {
+            identifier: SettingsTabContentView.Type,
             image: "Images/Gear.svg",
             title: WI.UIString("Settings"),
-            isEphemeral: true,
         };
     }
 
+    static shouldPinTab()
+    {
+        return true;
+    }
+
     static shouldSaveTab()
     {
         return false;
@@ -376,9 +376,6 @@ WI.SettingsTabContentView = class SettingsTabContentView extends WI.TabContentVi
             experimentalSettingsView.addSeparator();
         }
 
-        experimentalSettingsView.addSetting(WI.UIString("User Interface:"), WI.settings.experimentalEnableNewTabBar, WI.UIString("Enable New Tab Bar"));
-        experimentalSettingsView.addSeparator();
-
         if (InspectorBackend.hasDomain("CSS")) {
             let stylesGroup = experimentalSettingsView.addGroup(WI.UIString("Styles:"));
             stylesGroup.addSetting(WI.settings.experimentalEnableStylesJumpToEffective, WI.UIString("Show Jump to Effective Property Button"));
@@ -402,7 +399,6 @@ WI.SettingsTabContentView = class SettingsTabContentView extends WI.TabContentVi
         }
 
         listenForChange(WI.settings.experimentalEnablePreviewFeatures);
-        listenForChange(WI.settings.experimentalEnableNewTabBar);
 
         if (InspectorBackend.hasDomain("CSS"))
             listenForChange(WI.settings.experimentalEnableStylesJumpToEffective);
index 10a1319..64dc895 100644 (file)
@@ -42,7 +42,8 @@ WI.Sidebar = class Sidebar extends WI.View
         if (hasNavigationBar) {
             this.element.classList.add("has-navigation-bar");
 
-            this._navigationBar = new WI.NavigationBar(null, null, "tablist");
+            const navigationBarElement = null;
+            this._navigationBar = new WI.NavigationBar(navigationBarElement, {role: "tablist"});
             this._navigationBar.addEventListener(WI.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);
             this.addSubview(this._navigationBar);
         }
diff --git a/Source/WebInspectorUI/UserInterface/Views/SizesToFitNavigationBar.js b/Source/WebInspectorUI/UserInterface/Views/SizesToFitNavigationBar.js
deleted file mode 100644 (file)
index f4c9d9e..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (C) 2020 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-WI.SizesToFitNavigationBar = class SizesToFitNavigationBar extends WI.NavigationBar
-{
-    get sizesToFit()
-    {
-        return true;
-    }
-};
index c5ad77b..13b1d55 100644 (file)
@@ -27,16 +27,25 @@ WI.SourcesTabContentView = class SourcesTabContentView extends WI.ContentBrowser
 {
     constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.SourcesTabContentView.tabInfo());
-        const detailsSidebarPanelConstructors = [WI.ResourceDetailsSidebarPanel, WI.ScopeChainDetailsSidebarPanel, WI.ProbeDetailsSidebarPanel];
-        super("sources", ["sources"], tabBarItem, WI.SourcesNavigationSidebarPanel, detailsSidebarPanelConstructors);
+        super(SourcesTabContentView.tabInfo(), {
+            navigationSidebarPanelConstructor: WI.SourcesNavigationSidebarPanel,
+            detailsSidebarPanelConstructors: [
+                WI.ResourceDetailsSidebarPanel,
+                WI.ScopeChainDetailsSidebarPanel,
+                WI.ProbeDetailsSidebarPanel,
+            ],
+        });
 
         this._showScopeChainDetailsSidebarPanel = false;
+
+        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, this._handleDebuggerPaused, this);
+        WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, this._handleDebuggerResumed, this);
     }
 
     static tabInfo()
     {
         return {
+            identifier: SourcesTabContentView.Type,
             image: "Images/Sources.svg",
             title: WI.UIString("Sources"),
         };
@@ -98,6 +107,18 @@ WI.SourcesTabContentView = class SourcesTabContentView extends WI.ContentBrowser
         if (treeElement)
             treeElement.revealAndSelect();
     }
+
+    // Private
+
+    _handleDebuggerPaused(event)
+    {
+        this.tabBarItem.image = "Images/SourcesPaused.svg";
+    }
+
+    _handleDebuggerResumed(event)
+    {
+        this.tabBarItem.image = "Images/Sources.svg";
+    }
 };
 
 WI.SourcesTabContentView.Type = "sources";
index 3d1f155..9540ab8 100644 (file)
 
 WI.StorageTabContentView = class StorageTabContentView extends WI.ContentBrowserTabContentView
 {
-    constructor(identifier)
+    constructor()
     {
-        let tabBarItem = WI.GeneralTabBarItem.fromTabInfo(WI.StorageTabContentView.tabInfo());
-        let detailsSidebarPanelConstructors = [WI.ApplicationCacheDetailsSidebarPanel, WI.IndexedDatabaseDetailsSidebarPanel];
-
-        super(identifier || "storage", "storage", tabBarItem, WI.StorageSidebarPanel, detailsSidebarPanelConstructors);
+        super(StorageTabContentView.tabInfo(), {
+            navigationSidebarPanelConstructor: WI.StorageSidebarPanel,
+            detailsSidebarPanelConstructors: [
+                WI.ApplicationCacheDetailsSidebarPanel,
+                WI.IndexedDatabaseDetailsSidebarPanel,
+            ],
+        });
 
         WI.applicationCacheManager.enable();
         WI.databaseManager.enable();
@@ -41,6 +44,7 @@ WI.StorageTabContentView = class StorageTabContentView extends WI.ContentBrowser
     static tabInfo()
     {
         return {
+            identifier: StorageTabContentView.Type,
             image: "Images/Storage.svg",
             title: WI.UIString("Storage"),
         };
index 3d7cd7a..aec6b61 100644 (file)
 
 .tab-bar {
     position: absolute;
-    top: var(--toolbar-height);
+    top: var(--undocked-title-area-height);
     left: 0;
     right: 0;
     height: var(--tab-bar-height);
 
     display: flex;
-    justify-content: space-between;
-    flex-wrap: wrap;
-
-    border-bottom: var(--tab-item-medium-border-style);
-
-    background-image: linear-gradient(to bottom, hsl(0, 0%, 78%), hsl(0, 0%, 72%));
-    background-size: 100% 200%;
-
-    white-space: nowrap;
-    overflow: hidden;
-
-    outline: none;
 
     --tab-item-dark-border-color: hsl(0, 0%, 59%);
     --tab-item-medium-border-color: hsl(0, 0%, 65%);
     --tab-item-light-border-style: 1px solid var(--tab-item-light-border-color);
 }
 
-body.window-inactive .tab-bar {
-    border-bottom-color: var(--tab-item-light-border-color);
+body:not(.docked) .tab-bar {
+    background-image: linear-gradient(to bottom, hsl(0, 0%, 78%), hsl(0, 0%, 72%));
+    background-size: 100% 200%;
+}
 
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar {
     background-image: none !important;
     background-color: var(--tab-item-extra-light-border-color) !important;
 }
 
-.tab-bar > .top-border {
+body.docked:matches(.window-inactive, .window-docked-inactive) .tab-bar {
+    background-color: var(--background-color-unfocused) !important;
+}
+
+.tab-bar > .border {
     position: absolute;
-    top: 0;
     left: 0;
     right: 0;
+    z-index: 10;
+    background-color: var(--tab-item-medium-border-color);
+}
+
+.tab-bar > .border.top {
+    top: 0;
+    height: calc(1px / var(--zoom-factor));
+}
+
+.tab-bar > .border.bottom {
+    bottom: 0;
     height: 1px;
+}
 
-    background-color: var(--tab-item-medium-border-color);
+body.docked.bottom .tab-bar > .border.top {
+    filter: brightness(80%);
+}
+
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .border {
+    background-color: var(--tab-item-light-border-color);
+}
+
+.tab-bar > .navigation-bar {
+    height: var(--tab-bar-height);
+}
+
+.tab-bar > .navigation-bar > .item.group > .item {
+    width: auto !important;
+    margin: 0 4px !important;
+    padding: 0 !important;
+}
 
-    z-index: 0;
+.tab-bar > .navigation-bar > .item.group > .item:nth-child(1 of :not(.hidden)) {
+    -webkit-margin-start: 8px !important;
 }
 
-body.window-inactive .tab-bar > .top-border {
+.tab-bar > .navigation-bar > .item.group > .item:nth-last-child(1 of :not(.hidden)) {
+    -webkit-margin-end: 8px !important;
+}
+
+.tab-bar > .navigation-bar .item.divider {
+    margin-top: 1px;
+    background-color: var(--tab-item-medium-border-color);
+}
+
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .navigation-bar > .item.divider {
     background-color: var(--tab-item-light-border-color);
 }
 
-.tab-bar > .item {
+.tab-bar > .tabs {
     display: flex;
+    flex-wrap: wrap;
+    position: relative;
+    width: 100%;
+    height: 100%;
+}
+
+body.docked .tab-bar .tabs {
+    justify-content: space-around;
+    padding: 0 4px; /* Keep in sync with `WI.TabBar.horizontalPadding` */
+}
+
+body.docked .tab-bar > .tabs > .flexible-space {
     flex-grow: 1;
+}
+
+.tab-bar > .tabs > .item {
+    display: flex;
 
     position: relative;
 
@@ -86,17 +134,11 @@ body.window-inactive .tab-bar > .top-border {
 
     align-items: center;
 
-    padding: 0 6px;
+    padding: 0 8px;
 
-    min-width: 24px;
+    height: var(--tab-bar-item-height);
     overflow: hidden;
 
-    background-image: linear-gradient(to bottom, hsl(0, 0%, 78%), hsl(0, 0%, 72%));
-    background-size: 100% 200%;
-
-    border-top: var(--tab-item-medium-border-style);
-
-    height: 100%;
     line-height: 15px;
     outline: none;
 
@@ -104,56 +146,91 @@ body.window-inactive .tab-bar > .top-border {
     /* transition-property: background-position, border-color; */
     /* transition-duration: 250ms; */
     /* transition-delay: 50ms; */
+
+    --tab-bar-item-height: 100%;
+}
+
+body:not(.docked) .tab-bar > .tabs > .item {
+    background-image: linear-gradient(to bottom, hsl(0, 0%, 78%), hsl(0, 0%, 72%));
+    background-size: 100% 200%;
+}
+
+body:not(.docked) .tab-bar > .tabs > .item:not(.pinned) {
+    flex-grow: 1;
 }
 
-.tab-bar.calculate-width > .item {
+body.docked .tab-bar > .tabs > .item {
+    margin: var(--tab-bar-item-vertical-margin) 2px 0; /* Keep in sync with `WI.TabBarItem.horizontalMargin` */
+
+    --tab-bar-item-height: calc(var(--tab-bar-height) - (2 * var(--tab-bar-item-vertical-margin)));
+    --tab-bar-item-vertical-margin: 4px;
+}
+
+.tab-bar > .tabs.calculate-width > .item {
     flex: initial;
 }
 
-body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),
-body[dir=ltr] .tab-bar.dragging-tab > .item.selected {
+body[dir=ltr]:not(.docked) .tab-bar > .tabs > .item:not(:first-child),
+body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child,
+body[dir=ltr]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child {
     border-left: var(--tab-item-medium-border-style);
 }
 
-body[dir=rtl] .tab-bar > :nth-child(n + 2 of .item),
-body[dir=rtl] .tab-bar.dragging-tab > .item.selected {
+body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.hide-border-end) > .item:last-child,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs > .item:not(:first-child),
+body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.hide-border-start) > .item:first-child,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs.dragging-tab > .item.selected {
     border-right: var(--tab-item-medium-border-style);
 }
 
-.tab-bar > .item.pinned {
-    width: 24px;
+.tab-bar > .tabs > .item.pinned {
     flex: none;
     justify-content: center;
+    width: var(--tab-bar-height);
+    padding: 0;
 }
 
-.tab-bar > .item.pinned.tab-picker {
-    width: 18px;
-    min-width: initial;
+body.docked .tab-bar > .tabs > .item.pinned {
+    width: var(--tab-bar-item-height); /* Make pinned tabs square */
 }
 
-.tab-bar > .item:not(.disabled).selected {
-    border-top-color: hsl(0, 0%, 74%);
+body:not(.docked) .tab-bar > .tabs > .item:not(.disabled).selected {
     background-image: linear-gradient(to bottom, hsl(0, 0%, 87%), hsl(0, 0%, 82%));
     background-size: 100% 100%;
 }
 
-.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover {
+body.docked .tab-bar > .tabs > .item:not(.disabled):matches(.selected, :hover) {
+    border-radius: var(--tab-bar-item-vertical-margin);
+}
+
+body.docked .tab-bar > .tabs > .item:not(.disabled).selected {
+    background-color: lightgrey;
+}
+
+body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover {
     background-image: linear-gradient(to bottom, hsl(0, 0%, 67%), hsl(0, 0%, 64%));
-    border-top-color: var(--tab-item-dark-border-color);
 }
 
-body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,
-body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item {
+body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover {
+    background-color: hsl(0, 0%, 95%);
+}
+
+body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover,
+body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover {
     border-left-color: var(--tab-item-dark-border-color);
 }
 
-body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,
-body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item {
+body[dir=ltr]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:last-child:not(.selected, .disabled):hover,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover,
+body[dir=rtl]:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover + .item {
     border-right-color: var(--tab-item-dark-border-color);
 }
 
-body.window-inactive .tab-bar > .item {
-    border-top-color: var(--tab-item-light-border-color) !important;
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item {
+    border-right-color: var(--tab-item-light-border-color) !important;
+    border-left-color: var(--tab-item-light-border-color) !important;
 
     background-image: none !important;
     background-color: var(--tab-item-extra-light-border-color) !important;
@@ -161,70 +238,25 @@ body.window-inactive .tab-bar > .item {
     transition: none;
 }
 
-body[dir=ltr].window-inactive .tab-bar > .item {
-    border-left-color: var(--tab-item-light-border-color) !important;
-}
-
-body[dir=rtl].window-inactive .tab-bar > .item {
-    border-right-color: var(--tab-item-light-border-color) !important;
-}
-
-body.window-inactive .tab-bar > .item.selected {
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected {
     background-image: none !important;
     background-color: hsl(0, 0%, 96%) !important;
 }
 
-.tab-bar > .item > .close {
-    width: 16px;
-    height: 16px;
-
-    min-width: 16px;
-    min-height: 16px;
-
-    opacity: 0;
-
-    border-radius: 2px;
-
-    background-image: url(../Images/Close.svg);
-    background-repeat: no-repeat;
-
-    transition-property: background-color, opacity;
-    transition-duration: 250ms, 500ms;
-    transition-delay: 0s, 50ms;
-
-    -webkit-margin-end: 4px;
-}
-
-body:not(.window-inactive) .tab-bar > .item:hover > .close {
-    opacity: 0.6;
-}
-
-body:not(.window-inactive) .tab-bar.single-tab > .item.default-tab:hover > .close {
-    opacity: 0;
-}
-
-.tab-bar.single-tab > .item.default-tab > .close {
-    pointer-events: none;
-}
-
-.tab-bar > .item > .close:hover {
-    background-color: hsla(0, 0%, 0%, 0.2);
+body.docked .tab-bar > .tabs > .item:not(.disabled):matches(.selected, :hover) {
+    box-shadow: 0 1px 2px hsla(0, 0%, 0%, 0.15) inset;
 }
 
-.tab-bar > .item > .close:active {
-    opacity: 0.8 !important;
+body.docked:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected {
+    background-color: hsl(0, 0%, 90%);
 }
 
-.tab-bar > .item > .flex-space {
+.tab-bar > .tabs > .item > .flex-space {
     display: flex;
     flex: 1;
 }
 
-.tab-bar > .item.ephemeral > .flex-space:last-child {
-    -webkit-margin-end: 16px;
-}
-
-.tab-bar > .item > .icon {
+.tab-bar > .tabs > .item > .icon {
     width: 16px;
     height: 16px;
 
@@ -236,41 +268,48 @@ body:not(.window-inactive) .tab-bar.single-tab > .item.default-tab:hover > .clos
     -webkit-user-drag: none;
 }
 
-.tab-bar > .item.pinned > .icon {
+.tab-bar > .tabs > .item.pinned > .icon {
     width: 15px;
     height: 15px;
     min-width: 15px;
     min-height: 15px;
 }
 
-.tab-bar > .item.selected > .icon {
+.tab-bar > .tabs > .item:not(.selected):hover > .icon {
+    opacity: 0.6;
+}
+
+.tab-bar > .tabs > .item:not(.disabled).selected > .icon {
     opacity: 0.7;
 }
 
-.tab-bar > .item.disabled > .icon {
+.tab-bar > .tabs > .item.disabled > .icon {
     opacity: 0.35;
 }
 
-@media not (prefers-color-scheme: dark) {
-    .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover > .icon {
-        opacity: 0.6;
-    }
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .icon {
+    opacity: 0.3;
+}
+
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .icon {
+    opacity: 0.4;
 }
 
-.tab-bar > .item > .title {
-    color: hsla(0, 0%, 0%, 0.55);
+.tab-bar > .tabs > .item > .title {
+    color: hsla(0, 0%, var(--foreground-lightness), 0.6);
 
     display: flex;
 
     min-width: 0;
     max-width: 400px;
+    -webkit-margin-start: 6px;
 }
 
-.tab-bar:not(.collapsed) > .item > .title {
-    -webkit-margin-start: 6px;
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item > .title {
+    color: hsla(0, 0%, var(--foreground-lightness), 0.4);
 }
 
-.tab-bar > .item > .title > .content {
+.tab-bar > .tabs > .item > .title > .content {
     min-width: 0;
     width: 100%;
     overflow: hidden;
@@ -278,91 +317,65 @@ body:not(.window-inactive) .tab-bar.single-tab > .item.default-tab:hover > .clos
     white-space: nowrap;
 }
 
-.tab-bar:not(.animating) > .item:not(.selected):hover > .title {
-    color: hsla(0, 0%, 0%, 0.6);
-}
-
-.tab-bar > .item.selected > .title {
-    color: hsla(0, 0%, 0%, 0.7);
+.tab-bar > .tabs > .item:not(.selected):hover > .title {
+    color: hsla(0, 0%, var(--foreground-lightness), 0.7);
 }
 
-.tab-bar.collapsed > .item {
-    justify-content: center;
-}
-
-.tab-bar.collapsed > .item:not(.pinned) > .icon {
-    display: none;
+.tab-bar > .tabs > .item:not(.disabled).selected > .title {
+    color: hsla(0, 0%, var(--foreground-lightness), 0.8);
 }
 
-.tab-bar.collapsed > .item > .flex-space {
-    display: none;
+body:matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected > .title {
+    color: hsla(0, 0%, var(--foreground-lightness), 0.5);
 }
 
-.tab-bar.collapsed > .item > .close {
-    display: none;
-    -webkit-margin-end: 0;
-}
-
-.tab-bar.collapsed > .item:hover > .close {
-    display: inline-block;
-    position: absolute;
-}
-
-.tab-bar.collapsed > .item.ephemeral:hover > .icon {
-    display: none;
-}
-
-.tab-bar.collapsed > .item.ephemeral:hover > .title {
-    visibility: hidden;
-}
-
-.tab-bar.static-layout {
+.tab-bar > .tabs.static-layout {
     position: relative;
 }
 
-.tab-bar.static-layout > .item {
+.tab-bar > .tabs.static-layout > :matches(.flexible-space, .item) {
     position: absolute !important;
     top: 0;
 }
 
-.tab-bar.animating.closing-tab > .item {
+.tab-bar > .tabs.animating.closing-tab > .item {
     transition-property: left;
     transition-duration: 250ms;
     transition-timing-function: ease-in-out;
 }
 
-.tab-bar.animating:matches(.expanding-tabs, .inserting-tab) > .item {
+.tab-bar > .tabs.animating:matches(.expanding-tabs, .inserting-tab) > .item {
     transition-property: left, width;
     transition-duration: 250ms;
     transition-timing-function: ease-in-out;
 }
 
-.tab-bar.animating.inserting-tab > .item.being-inserted {
+.tab-bar > .tabs.animating.inserting-tab > .item.being-inserted {
     z-index: 2;
     min-width: 0 !important;
     padding: 0 !important;
 }
 
-.tab-bar.dragging-tab > .item.selected,
-.tab-bar.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)),
-.tab-bar.animating.closing-tab > .item.selected {
+body:not(.docked) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected,
+body:not(.docked) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)),
+body:not(.docked) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected {
     border-right: var(--tab-item-medium-border-style);
 }
 
-body.window-inactive .tab-bar.dragging-tab > .item.selected,
-body.window-inactive .tab-bar.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)),
-body.window-inactive .tab-bar.animating.closing-tab > .item.selected {
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected,
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.static-layout:not(.animating.inserting-tab):not(.dragging-tab) > .item:nth-last-child(1 of :not(.pinned)),
+body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs.animating.closing-tab > .item:not(.disabled).selected {
     border-right-color: var(--tab-item-light-border-color) !important;
 }
 
-.tab-bar.dragging-tab > .item.selected {
+.tab-bar > .tabs.dragging-tab > .item:not(.disabled).selected {
     z-index: 2;
     pointer-events: none;
 }
 
 @media (prefers-color-scheme: dark) {
     .tab-bar {
-        background-image: linear-gradient(to bottom, hsl(0, 0%, 12%), hsl(0, 0%, 10%));
+        background-image: linear-gradient(to bottom, hsl(0, 0%, 12%), hsl(0, 0%, 10%)) !important;
 
         --tab-item-border-color: hsl(0, 0%, 36%);
 
@@ -373,46 +386,47 @@ body.window-inactive .tab-bar.animating.closing-tab > .item.selected {
         --tab-item-extra-light-border-color: var(--tab-item-border-color);
     }
 
-    .tab-bar > .item {
+    body.docked.bottom .tab-bar > .border.top {
+        filter: brightness(120%);
+    }
+
+    body:not(.docked) .tab-bar > .tabs > .item {
         background-image: linear-gradient(to bottom, hsl(0, 0%, 12%), hsl(0, 0%, 10%));
     }
 
-    .tab-bar > .item > .title {
-        color: white !important;
+    .tab-bar > .tabs > .item:not(.disabled).selected {
+        background-image: linear-gradient(to bottom, hsl(0, 0%, 23%), hsl(0, 0%, 21%)) !important;
     }
 
-    .tab-bar > .item:not(.disabled).selected {
-        background-image: linear-gradient(to bottom, hsl(0, 0%, 23%), hsl(0, 0%, 21%));
-        border-top-color: hsl(0, 0%, 37%);
+    body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover {
+        background-image: linear-gradient(to bottom, hsl(0, 0%, 11%), hsl(0, 0%, 9%)) !important;
     }
 
-    .tab-bar:not(.animating) > .item:not(.selected):hover {
-        background-image: linear-gradient(to bottom, hsl(0, 0%, 11%), hsl(0, 0%, 9%));
+    body.docked .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover {
+        background-color: hsl(0, 0%, 15%);
     }
 
-    .tab-bar > .item > .close,
-    .tab-bar > .item > .icon {
+    .tab-bar > .tabs > .item > .icon {
         filter: var(--filter-invert);
     }
 
-    body.window-inactive .tab-bar {
+    body:not(.docked) .tab-bar > .tabs:not(.animating) > .item:not(.selected, .disabled):hover > .icon {
+        opacity: 0.6;
+    }
+
+    body:matches(.window-inactive, .window-docked-inactive) .tab-bar {
         --tab-item-border-color: hsl(0, 0%, 34%);
-        border-bottom-color: var(--tab-item-border-color);
 
         background-image: none !important;
         background-color: hsl(0, 0%, 13%) !important;
     }
 
-    body.window-inactive .tab-bar > .item {
+    body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item {
         background-image: none !important;
         background-color: hsl(0, 0%, 13%) !important;
     }
 
-    body.window-inactive .tab-bar > .item.selected {
+    body:not(.docked):matches(.window-inactive, .window-docked-inactive) .tab-bar > .tabs > .item:not(.disabled).selected {
         background-color: hsl(0, 0%, 19%) !important;
     }
-
-    body.window-inactive .tab-bar > .item > .title {
-        color: hsl(0, 0%, 58%) !important;
-    }
 }
index 801b17d..8111ee0 100644 (file)
 
 WI.TabBar = class TabBar extends WI.View
 {
-    constructor(element, tabBarItems)
+    constructor(element)
     {
         super(element);
 
         this.element.classList.add("tab-bar");
-        this.element.setAttribute("role", "tablist");
-        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("contextmenu", this._handleContextMenu.bind(this));
 
-        this.element.createChild("div", "top-border");
+        this.element.createChild("div", "border top");
+
+        const navigationBarBeforeElement = null;
+        this._navigationBarBefore = new WI.NavigationBar(navigationBarBeforeElement, {sizesToFit: true});
+        this.addSubview(this._navigationBarBefore);
+
+        this._tabContainer = this.element.appendChild(document.createElement("div"));
+        this._tabContainer.className = "tabs";
+        this._tabContainer.setAttribute("role", "tablist");
+        this._tabContainer.addEventListener("mousedown", this._handleMouseDown.bind(this));
+        this._tabContainer.addEventListener("click", this._handleClick.bind(this));
+        this._tabContainer.addEventListener("mouseleave", this._handleMouseLeave.bind(this));
+        this._tabContainer.addEventListener("contextmenu", this._handleContextMenu.bind(this));
+
+        this._flexibleSpaceBeforeElement = this._tabContainer.appendChild(document.createElement("div"));
+        this._flexibleSpaceBeforeElement.className = "flexible-space";
+
+        this._flexibleSpaceAfterElement = this._tabContainer.appendChild(document.createElement("div"));
+        this._flexibleSpaceAfterElement.className = "flexible-space";
+
+        const navigationBarAfterElement = null;
+        this._navigationBarAfter = new WI.NavigationBar(navigationBarAfterElement, {sizesToFit: true});
+        this.addSubview(this._navigationBarAfter);