Web Inspector: Add new tab button to make it easy to bring a closed tab back
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2015 13:04:38 +0000 (13:04 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2015 13:04:38 +0000 (13:04 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144297

Reviewed by Joseph Pecoraro.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Base/Main.js:
(WebInspector.contentLoaded):
(WebInspector.isTabTypeAllowed):
(WebInspector._tabContentViewForType):
(WebInspector._rememberOpenTabs):
(WebInspector._updateNewTabButtonState):
(WebInspector._newTabItemClicked):
(WebInspector.isNewTabWithTypeAllowed):
(WebInspector.createNewTab):
(WebInspector.activateExtraDomains):
(WebInspector._restoreCookieForOpenTabs):
(WebInspector._saveCookieForOpenTabs):
(WebInspector._isTabTypeAllowed): Deleted.
* UserInterface/Images/NewTab.svg: Added.
* UserInterface/Images/NewTabPlus.svg:
* UserInterface/Main.html:
* UserInterface/Views/NewTabContentView.css: Added.
(.new-tab.tab.content-view):
(.new-tab.tab.content-view > .tab-item):
(.new-tab.tab.content-view > .tab-item.disabled):
(.new-tab.tab.content-view > .tab-item > .box):
(.new-tab.tab.content-view > .tab-item:not(.disabled):active > .box):
(.new-tab.tab.content-view > .tab-item > .box > img):
(.new-tab.tab.content-view > .tab-item > label):
* UserInterface/Views/NewTabContentView.js: Added.
(WebInspector.NewTabContentView):
(WebInspector.NewTabContentView.prototype.get type):
(WebInspector.NewTabContentView.prototype._createNewTab):
* UserInterface/Views/TabBar.css:
(.tab-bar > .item:not(.disabled).selected):
(.tab-bar > .item.new-tab-button:not(.disabled):hover):
(.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item):
(.tab-bar > .item.disabled > .icon):
(.tab-bar > .item.new-tab-button:not(.disabled):hover > .icon):
(.tab-bar > .item.selected): Deleted.
(.tab-bar > .item.new-tab-button:hover): Deleted.
(.tab-bar:not(.animating) > .item:not(.selected):hover + .item): Deleted.
(.tab-bar > .item.new-tab-button:hover > .icon): Deleted.
* UserInterface/Views/TabBar.js:
(WebInspector.TabBar.prototype.set selectedTabBarItem):
(WebInspector.TabBar.prototype._handleMouseDown):
* UserInterface/Views/TabBarItem.js:
(WebInspector.TabBarItem.prototype.get disabled):
(WebInspector.TabBarItem.prototype.set disabled):
* UserInterface/Views/TabBrowser.js:
(WebInspector.TabBrowser):
(WebInspector.TabBrowser.prototype.addTabForContentView):
(WebInspector.TabBrowser.prototype.showTabForContentView):
(WebInspector.TabBrowser.prototype.closeTabForContentView):

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

12 files changed:
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js
Source/WebInspectorUI/UserInterface/Base/Main.js
Source/WebInspectorUI/UserInterface/Images/NewTab.svg [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Images/NewTabPlus.svg
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/TabBar.css
Source/WebInspectorUI/UserInterface/Views/TabBar.js
Source/WebInspectorUI/UserInterface/Views/TabBarItem.js
Source/WebInspectorUI/UserInterface/Views/TabBrowser.js

index 1f70703..ff074a8 100644 (file)
@@ -1,3 +1,61 @@
+2015-04-27  Timothy Hatcher  <timothy@apple.com>
+
+        Web Inspector: Add new tab button to make it easy to bring a closed tab back
+        https://bugs.webkit.org/show_bug.cgi?id=144297
+
+        Reviewed by Joseph Pecoraro.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Base/Main.js:
+        (WebInspector.contentLoaded):
+        (WebInspector.isTabTypeAllowed):
+        (WebInspector._tabContentViewForType):
+        (WebInspector._rememberOpenTabs):
+        (WebInspector._updateNewTabButtonState):
+        (WebInspector._newTabItemClicked):
+        (WebInspector.isNewTabWithTypeAllowed):
+        (WebInspector.createNewTab):
+        (WebInspector.activateExtraDomains):
+        (WebInspector._restoreCookieForOpenTabs):
+        (WebInspector._saveCookieForOpenTabs):
+        (WebInspector._isTabTypeAllowed): Deleted.
+        * UserInterface/Images/NewTab.svg: Added.
+        * UserInterface/Images/NewTabPlus.svg:
+        * UserInterface/Main.html:
+        * UserInterface/Views/NewTabContentView.css: Added.
+        (.new-tab.tab.content-view):
+        (.new-tab.tab.content-view > .tab-item):
+        (.new-tab.tab.content-view > .tab-item.disabled):
+        (.new-tab.tab.content-view > .tab-item > .box):
+        (.new-tab.tab.content-view > .tab-item:not(.disabled):active > .box):
+        (.new-tab.tab.content-view > .tab-item > .box > img):
+        (.new-tab.tab.content-view > .tab-item > label):
+        * UserInterface/Views/NewTabContentView.js: Added.
+        (WebInspector.NewTabContentView):
+        (WebInspector.NewTabContentView.prototype.get type):
+        (WebInspector.NewTabContentView.prototype._createNewTab):
+        * UserInterface/Views/TabBar.css:
+        (.tab-bar > .item:not(.disabled).selected):
+        (.tab-bar > .item.new-tab-button:not(.disabled):hover):
+        (.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item):
+        (.tab-bar > .item.disabled > .icon):
+        (.tab-bar > .item.new-tab-button:not(.disabled):hover > .icon):
+        (.tab-bar > .item.selected): Deleted.
+        (.tab-bar > .item.new-tab-button:hover): Deleted.
+        (.tab-bar:not(.animating) > .item:not(.selected):hover + .item): Deleted.
+        (.tab-bar > .item.new-tab-button:hover > .icon): Deleted.
+        * UserInterface/Views/TabBar.js:
+        (WebInspector.TabBar.prototype.set selectedTabBarItem):
+        (WebInspector.TabBar.prototype._handleMouseDown):
+        * UserInterface/Views/TabBarItem.js:
+        (WebInspector.TabBarItem.prototype.get disabled):
+        (WebInspector.TabBarItem.prototype.set disabled):
+        * UserInterface/Views/TabBrowser.js:
+        (WebInspector.TabBrowser):
+        (WebInspector.TabBrowser.prototype.addTabForContentView):
+        (WebInspector.TabBrowser.prototype.showTabForContentView):
+        (WebInspector.TabBrowser.prototype.closeTabForContentView):
+
 2015-04-27  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Cannot scroll Timeline Overview horizontally, scrollbar cannot be interacted with
index 1de5054..c85353b 100644 (file)
Binary files a/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js and b/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js differ
index bfe54dd..99214e3 100644 (file)
@@ -197,6 +197,7 @@ WebInspector.contentLoaded = function()
     this.toolbar.sizeMode = WebInspector.Toolbar.SizeMode.Small;
 
     this.tabBar = new WebInspector.TabBar(document.getElementById("tab-bar"));
+    this.tabBar.addEventListener(WebInspector.TabBar.Event.NewTabItemClicked, this._newTabItemClicked, this);
 
     var contentElement = document.getElementById("content");
     contentElement.setAttribute("role", "main");
@@ -228,6 +229,9 @@ WebInspector.contentLoaded = function()
     this.tabBrowser = new WebInspector.TabBrowser(document.getElementById("tab-browser"), this.tabBar, this.navigationSidebar, this.detailsSidebar);
     this.tabBrowser.addEventListener(WebInspector.TabBrowser.Event.SelectedTabContentViewDidChange, this._tabBrowserSelectedTabContentViewDidChange, this);
 
+    this.tabBar.addEventListener(WebInspector.TabBar.Event.TabBarItemAdded, this._updateNewTabButtonState, this);
+    this.tabBar.addEventListener(WebInspector.TabBar.Event.TabBarItemRemoved, this._updateNewTabButtonState, this);
+
     this._reloadPageKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl, "R", this._reloadPage.bind(this));
     this._reloadPageIgnoringCacheKeyboardShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.CommandOrControl | WebInspector.KeyboardShortcut.Modifier.Shift, "R", this._reloadPageIgnoringCache.bind(this));
 
@@ -329,7 +333,7 @@ WebInspector.contentLoaded = function()
     this._pendingOpenTabTypes = [];
 
     for (var tabType of this._openTabsSetting.value) {
-        if (!this._isTabTypeAllowed(tabType)) {
+        if (!this.isTabTypeAllowed(tabType)) {
             this._pendingOpenTabTypes.push(tabType);
             continue;
         }
@@ -369,7 +373,7 @@ WebInspector.contentLoaded = function()
     this.runBootstrapOperations();
 };
 
-WebInspector._isTabTypeAllowed = function(tabType)
+WebInspector.isTabTypeAllowed = function(tabType)
 {
     switch (tabType) {
     case WebInspector.ElementsTabContentView.Type:
@@ -396,6 +400,8 @@ WebInspector._tabContentViewForType = function(tabType)
         return new WebInspector.ConsoleTabContentView;
     case WebInspector.SearchTabContentView.Type:
         return new WebInspector.SearchTabContentView;
+    case WebInspector.NewTabTabContentView.Type:
+        return new WebInspector.NewTabTabContentView;
     default:
         console.error("Unknown tab type", tabType);
     }
@@ -409,7 +415,9 @@ WebInspector._rememberOpenTabs = function()
 
     for (var tabBarItem of this.tabBar.tabBarItems) {
         var tabContentView = tabBarItem.representedObject;
-        if (tabContentView instanceof WebInspector.SettingsTabContentView)
+        if (!(tabContentView instanceof WebInspector.TabContentView))
+            continue;
+        if (tabContentView instanceof WebInspector.SettingsTabContentView || tabContentView instanceof WebInspector.NewTabContentView)
             continue;
         console.assert(tabContentView.type, "Tab type can't be null, undefined, or empty string", tabContentView.type, tabContentView);
         openTabs.push(tabContentView.type);
@@ -418,6 +426,53 @@ WebInspector._rememberOpenTabs = function()
     this._openTabsSetting.value = openTabs;
 };
 
+WebInspector._updateNewTabButtonState = function(event)
+{
+    var newTabAllowed = this.isNewTabWithTypeAllowed(WebInspector.ConsoleTabContentView.Type) || this.isNewTabWithTypeAllowed(WebInspector.ElementsTabContentView.Type);
+    this.tabBar.newTabItem.disabled = !newTabAllowed;
+};
+
+WebInspector._newTabItemClicked = function(event)
+{
+    var tabContentView = this.tabBrowser.bestTabContentViewForClass(WebInspector.NewTabContentView);
+    if (!tabContentView)
+        tabContentView = new WebInspector.NewTabContentView;
+    this.tabBrowser.showTabForContentView(tabContentView);
+};
+
+WebInspector.isNewTabWithTypeAllowed = function(tabType)
+{
+    if (!this.isTabTypeAllowed(tabType))
+        return false;
+
+    // Only allow one tab per class for now.
+    for (var tabBarItem of this.tabBar.tabBarItems) {
+        var tabContentView = tabBarItem.representedObject;
+        if (!(tabContentView instanceof WebInspector.TabContentView))
+            continue;
+        if (tabContentView.type === tabType)
+            return false;
+    }
+
+    return true;
+};
+
+WebInspector.createNewTab = function(tabType, newTabContentViewToReplace)
+{
+    console.assert(this.isNewTabWithTypeAllowed(tabType));
+
+    var tabContentView = this._tabContentViewForType(tabType);
+
+    if (newTabContentViewToReplace) {
+        var insertionIndex = this.tabBar.tabBarItems.indexOf(newTabContentViewToReplace.tabBarItem);
+        this.tabBrowser.closeTabForContentView(newTabContentViewToReplace, true);
+        this.tabBrowser.showTabForContentView(tabContentView, true, insertionIndex);
+        return;
+    }
+
+    this.tabBrowser.showTabForContentView(tabContentView);
+};
+
 WebInspector.activateExtraDomains = function(domains)
 {
     this.hasExtraDomains = true;
@@ -437,7 +492,7 @@ WebInspector.activateExtraDomains = function(domains)
 
     var stillPendingOpenTabTypes = [];
     for (var tabType of this._pendingOpenTabTypes) {
-        if (!this._isTabTypeAllowed(tabType)) {
+        if (!this.isTabTypeAllowed(tabType)) {
             stillPendingOpenTabTypes.push(tabType);
             continue;
         }
@@ -1061,6 +1116,8 @@ WebInspector._restoreCookieForOpenTabs = function(causedByReload)
 {
     for (var tabBarItem of this.tabBar.tabBarItems) {
         var tabContentView = tabBarItem.representedObject;
+        if (!(tabContentView instanceof WebInspector.TabContentView))
+            continue;
         tabContentView.restoreStateFromCookie(causedByReload);
     }
 };
@@ -1069,6 +1126,8 @@ WebInspector._saveCookieForOpenTabs = function()
 {
     for (var tabBarItem of this.tabBar.tabBarItems) {
         var tabContentView = tabBarItem.representedObject;
+        if (!(tabContentView instanceof WebInspector.TabContentView))
+            continue;
         tabContentView.saveStateToCookie();
     }
 };
diff --git a/Source/WebInspectorUI/UserInterface/Images/NewTab.svg b/Source/WebInspectorUI/UserInterface/Images/NewTab.svg
new file mode 100644 (file)
index 0000000..866f48d
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright © 2015 Apple Inc. All rights reserved. -->
+<svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
+    <rect x="0.5" y="0.5" width="15" height="15" rx="2" class="stroked" fill="none" stroke="black"/>
+    <path d="M 8 3 L 8 13 M 3 8 L 13 8" class="stroked" fill="none" stroke="black"/>
+</svg>
index bb2b5d6..4ee1bfe 100644 (file)
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- Copyright © 2015 Apple Inc. All rights reserved. -->
 <svg viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg">
-    <path d="M 8 2 L 8 13 M 2.5 7.5 L 13.5 7.5" class="stroked" fill="none" stroke="black"/>
+    <path d="M 8 2 L 8 14 M 2 8 L 14 8" class="stroked" fill="none" stroke="black"/>
 </svg>
index 882a4e4..17ef450 100644 (file)
     <link rel="stylesheet" href="Views/NavigationSidebarPanel.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">
     <script src="Views/DOMDetailsSidebarPanel.js"></script>
     <script src="Views/FolderTreeElement.js"></script>
     <script src="Views/FolderizedTreeElement.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>
diff --git a/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css b/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.css
new file mode 100644 (file)
index 0000000..2cd7649
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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;
+
+    background-color: rgb(246, 246, 246);
+
+    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;
+    -webkit-filter: brightness(90%);
+}
+
+.new-tab.tab.content-view > .tab-item > .box {
+    width: 94px;
+    height: 94px;
+
+    padding: 15px;
+    border-radius: 5px;
+
+    background-color: rgb(210, 210, 210);
+    box-shadow: rgba(0, 0, 0, 0.33) 0 1px 6px;
+
+    display: block;
+}
+
+.new-tab.tab.content-view > .tab-item:not(.disabled):active > .box {
+    -webkit-filter: brightness(90%);
+}
+
+.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;
+}
diff --git a/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js b/Source/WebInspectorUI/UserInterface/Views/NewTabContentView.js
new file mode 100644 (file)
index 0000000..cc8885d
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.NewTabContentView = function(identifier)
+{
+    var tabBarItem = new WebInspector.TabBarItem("Images/NewTab.svg", WebInspector.UIString("New Tab"));
+
+    WebInspector.TabContentView.call(this, identifier || "new-tab", "new-tab", tabBarItem);
+
+    var allowedNewTabs = [
+        {image: "Images/Elements.svg", title: WebInspector.UIString("Elements"), type: WebInspector.ElementsTabContentView.Type},
+        {image: "Images/Console.svg", title: WebInspector.UIString("Console"), type: WebInspector.ConsoleTabContentView.Type}
+    ];
+
+    for (var info of allowedNewTabs) {
+        if (!WebInspector.isTabTypeAllowed(info.type))
+            continue;
+
+        var tabItemElement = document.createElement("div");
+        tabItemElement.classList.add("tab-item");
+
+        if (WebInspector.isNewTabWithTypeAllowed(info.type))
+            tabItemElement.addEventListener("click", this._createNewTab.bind(this, info.type));
+        else
+            tabItemElement.classList.add("disabled");
+
+        var boxElement = tabItemElement.appendChild(document.createElement("div"));
+        boxElement.classList.add("box");
+
+        var imageElement = boxElement.appendChild(document.createElement("img"));
+        imageElement.src = info.image;
+
+        var labelElement = tabItemElement.appendChild(document.createElement("label"));
+        labelElement.textContent = info.title;
+
+        this.element.appendChild(tabItemElement);
+    }
+};
+
+WebInspector.NewTabContentView.prototype = {
+    constructor: WebInspector.NewTabContentView,
+    __proto__: WebInspector.TabContentView.prototype,
+
+    // Public
+
+    get type()
+    {
+        return WebInspector.NewTabContentView.Type;
+    },
+
+    // Private
+
+    _createNewTab: function(tabType, event)
+    {
+        WebInspector.createNewTab(tabType, this);
+    }
+};
+
+WebInspector.NewTabContentView.Type = "new-tab";
index 3956d1a..f12961c 100644 (file)
@@ -106,20 +106,20 @@ body.window-inactive .tab-bar > .top-border {
     justify-content: center;
 }
 
-.tab-bar > .item.selected {
+.tab-bar > .item:not(.disabled).selected {
     border-top-color: rgb(190, 190, 190);
     background-image: linear-gradient(to bottom, rgb(222, 222, 222), rgb(211, 211, 211));
     background-size: 100% 100%;
 }
 
-.tab-bar:not(.animating) > .item:not(.selected):hover,
-.tab-bar > .item.new-tab-button:hover {
+.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,
+.tab-bar > .item.new-tab-button:not(.disabled):hover {
     background-position: 0 100%;
     border-top-color: rgb(152, 152, 152);
     border-left-color: rgb(152, 152, 152);
 }
 
-.tab-bar:not(.animating) > .item:not(.selected):hover + .item {
+.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item {
     border-left-color: rgb(152, 152, 152);
 }
 
@@ -201,8 +201,12 @@ body:not(.window-inactive) .tab-bar:not(.single-tab) > .item:not(.hide-close-but
     opacity: 0.7;
 }
 
-.tab-bar:not(.animating) > .item:not(.selected):hover > .icon,
-.tab-bar > .item.new-tab-button:hover > .icon {
+.tab-bar > .item.disabled > .icon {
+    opacity: 0.35;
+}
+
+.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover > .icon,
+.tab-bar > .item.new-tab-button:not(.disabled):hover > .icon {
     opacity: 0.6;
 }
 
index bb02eb4..e618f37 100644 (file)
@@ -351,6 +351,8 @@ WebInspector.TabBar = class TabBar extends WebInspector.Object
     set selectedTabBarItem(tabBarItemOrIndex)
     {
         var tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
+        if (tabBarItem === this._newTabItem)
+            tabBarItem = this._tabBarItems[this._tabBarItems.length - 2];
 
         if (this._selectedTabBarItem === tabBarItem)
             return;
@@ -498,9 +500,17 @@ WebInspector.TabBar = class TabBar extends WebInspector.Object
             return;
 
         var tabBarItem = itemElement[WebInspector.TabBarItem.ElementReferenceSymbol];
-        if (!tabBarItem || tabBarItem === this._newTabItem)
+        if (!tabBarItem)
+            return;
+
+        if (tabBarItem.disabled)
             return;
 
+        if (tabBarItem === this._newTabItem) {
+            this.dispatchEventToListeners(WebInspector.TabBar.Event.NewTabItemClicked);
+            return;
+        }
+
         var closeButtonElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.TabBarItem.CloseButtonStyleClassName);
         if (closeButtonElement) {
             this.removeTabBarItem(tabBarItem, false, true);
@@ -668,5 +678,6 @@ WebInspector.TabBar.Event = {
     TabBarItemSelected: "tab-bar-tab-bar-item-selected",
     TabBarItemAdded: "tab-bar-tab-bar-item-added",
     TabBarItemRemoved: "tab-bar-tab-bar-item-removed",
-    TabBarItemsReordered: "tab-bar-tab-bar-items-reordered"
+    TabBarItemsReordered: "tab-bar-tab-bar-items-reordered",
+    NewTabItemClicked: "tab-bar-new-tab-item-clicked"
 };
index 99665bb..2a7a9e8 100644 (file)
@@ -100,6 +100,16 @@ WebInspector.TabBarItem = class TabBarItem extends WebInspector.Object
         this._element.classList.toggle("selected", selected);
     }
 
+    get disabled()
+    {
+        return this._element.classList.contains("disabled");
+    }
+
+    set disabled(disabled)
+    {
+        this._element.classList.toggle("disabled", disabled);
+    }
+
     get hideCloseButton()
     {
         return this._element.classList.contains("hide-close-button");
index 0c91b1b..cda01f8 100644 (file)
@@ -50,8 +50,7 @@ WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
         this._contentViewContainer = new WebInspector.ContentViewContainer;
         this._element.appendChild(this._contentViewContainer.element);
 
-        // FIXME: Support creating new tabs.
-        // this._tabBar.newTabItem = new WebInspector.TabBarItem(platformImagePath("NewTabPlus.svg"), WebInspector.UIString("Create a new tab"), true);
+        this._tabBar.newTabItem = new WebInspector.TabBarItem(platformImagePath("NewTabPlus.svg"), WebInspector.UIString("Create a new tab"), true);
 
         this._tabBar.addEventListener(WebInspector.TabBar.Event.TabBarItemSelected, this._tabBarItemSelected, this);
         this._tabBar.addEventListener(WebInspector.TabBar.Event.TabBarItemRemoved, this._tabBarItemRemoved, this);
@@ -116,7 +115,7 @@ WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
         return null;
     }
 
-    addTabForContentView(tabContentView, doNotAnimate)
+    addTabForContentView(tabContentView, doNotAnimate, insertionIndex)
     {
         console.assert(tabContentView instanceof WebInspector.TabContentView);
         if (!(tabContentView instanceof WebInspector.TabContentView))
@@ -143,7 +142,10 @@ WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
         else
             this._recentTabContentViews.push(tabContentView);
 
-        this._tabBar.addTabBarItem(tabBarItem, doNotAnimate);
+        if (typeof insertionIndex === "number")
+            this._tabBar.insertTabBarItem(tabBarItem, insertionIndex, doNotAnimate);
+        else
+            this._tabBar.addTabBarItem(tabBarItem, doNotAnimate);
 
         console.assert(this._recentTabContentViews.length === this._tabBar.tabBarItems.length - (this._tabBar.newTabItem ? 1 : 0));
         console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0]);
@@ -151,9 +153,9 @@ WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
         return true;
     }
 
-    showTabForContentView(tabContentView, doNotAnimate)
+    showTabForContentView(tabContentView, doNotAnimate, insertionIndex)
     {
-        if (!this.addTabForContentView(tabContentView, doNotAnimate))
+        if (!this.addTabForContentView(tabContentView, doNotAnimate, insertionIndex))
             return false;
 
         this._tabBar.selectedTabBarItem = tabContentView.tabBarItem;
@@ -171,10 +173,10 @@ WebInspector.TabBrowser = class TabBrowser extends WebInspector.Object
         if (!(tabContentView.tabBarItem instanceof WebInspector.TabBarItem))
             return false;
 
-        if (tabBarItem.parentTabBar !== this._tabBar)
+        if (tabContentView.tabBarItem.parentTabBar !== this._tabBar)
             return false;
 
-        this._tabBar.removeTabBarItem(tabBarItem, doNotAnimate);
+        this._tabBar.removeTabBarItem(tabContentView.tabBarItem, doNotAnimate);
 
         console.assert(this._recentTabContentViews.length === this._tabBar.tabBarItems.length - (this._tabBar.newTabItem ? 1 : 0));
         console.assert(!this.selectedTabContentView || this.selectedTabContentView === this._recentTabContentViews[0]);