<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[183322] trunk/Source/WebInspectorUI</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/183322">183322</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2015-04-25 18:15:03 -0700 (Sat, 25 Apr 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Add a WebInspector.TabBar class
https://bugs.webkit.org/show_bug.cgi?id=143442
Reviewed by Joseph Pecoraro.
* UserInterface/Main.html:
Added new files.
* UserInterface/Protocol/InspectorFrontendHostStub.js:
(window.Symbol):
(WebInspector.InspectorFrontendHostStub.prototype.showContextMenu):
Added some stubs needed to work standalone.
* UserInterface/Views/TabBar.css: Added.
(.tab-bar):
(body.window-inactive .tab-bar):
(.tab-bar > .top-border):
(body.window-inactive .tab-bar > .top-border):
(.tab-bar > .item):
(.tab-bar > :nth-child(n + 2 of .item)):
(.tab-bar > .item.pinned):
(.tab-bar > .item.selected):
(.tab-bar > .item.new-tab-button:hover):
(.tab-bar:not(.animating) > .item:not(.selected):hover + .item):
(body.window-inactive .tab-bar > .item):
(body.window-inactive .tab-bar > .item.selected):
(.tab-bar > .item > .close):
(body:not(.window-inactive) .tab-bar:not(.single-tab) > .item:hover > .close):
(.tab-bar.single-tab > .item > .close):
(.tab-bar > .item > .close:hover):
(.tab-bar > .item > .close:active):
(.tab-bar > .item > .flex-space):
(.tab-bar > .item > .flex-space:last-child):
(.tab-bar > .item > .icon):
(.tab-bar > .item.selected > .icon):
(.tab-bar > .item.new-tab-button:hover > .icon):
(.tab-bar > .item > .title):
(.tab-bar > .item > .title > .content):
(.tab-bar:not(.animating) > .item:not(.selected):hover > .title):
(.tab-bar > .item.selected > .title):
(.tab-bar.collapsed > .item):
(.tab-bar.collapsed > .item > .flex-space):
(.tab-bar.collapsed > .item > .close):
(.tab-bar.hide-titles > .item > .title):
(.tab-bar.hide-titles > .item.selected:hover > .icon):
(.tab-bar.hide-titles > .item.selected:hover > .close):
(.tab-bar.static-layout):
(.tab-bar.static-layout > .item):
(.tab-bar.animating.closing-tab > .item):
(.tab-bar.animating:matches(.expanding-tabs, .inserting-tab) > .item):
(.tab-bar.animating.inserting-tab > .item.being-inserted):
(.tab-bar.animating.closing-tab > .item.selected):
(body.window-inactive .tab-bar.animating.closing-tab > .item.selected):
(.tab-bar.dragging-tab > .item.selected):
* UserInterface/Views/TabBar.js: Added.
(WebInspector.TabBar):
(WebInspector.TabBar.prototype.get newTabItem):
(WebInspector.TabBar.prototype.set newTabItem):
(WebInspector.TabBar.prototype.addTabBarItem):
(WebInspector.TabBar.prototype.insertTabBarItem.animateTabs):
(WebInspector.TabBar.prototype.insertTabBarItem.removeStyles):
(WebInspector.TabBar.prototype.insertTabBarItem):
(WebInspector.TabBar.prototype.insertTabBarItem.set else):
(WebInspector.TabBar.prototype.insertTabBarItem.set this):
(WebInspector.TabBar.animateTabs.get if):
(WebInspector.TabBar.animateTabs):
(WebInspector.TabBar.removeStyles):
(WebInspector.TabBar.prototype.insertTabBarItem):
(WebInspector.TabBar.prototype.updateLayoutSoon.update):
(WebInspector.TabBar.prototype.updateLayoutSoon):
(WebInspector.TabBar.prototype.updateLayout):
(WebInspector.TabBar.prototype.get selectedTabBarItem):
(WebInspector.TabBar.prototype.set selectedTabBarItem):
(WebInspector.TabBar.prototype.get tabBarItems):
(WebInspector.TabBar.prototype.get element):
(WebInspector.TabBar.prototype._findTabBarItem):
(WebInspector.TabBar.prototype._hasMoreThanOneNormalTab):
(WebInspector.TabBar.prototype._recordTabBarItemSizesAndPositions):
(WebInspector.TabBar.prototype._clearTabBarItemSizesAndPositions):
(WebInspector.TabBar.prototype._finishExpandingTabsAfterClose.):
(WebInspector.TabBar.prototype._finishExpandingTabsAfterClose):
(WebInspector.TabBar.prototype._handleMouseDown):
(WebInspector.TabBar.prototype._handleMouseMoved):
(WebInspector.TabBar.prototype._handleMouseUp):
(WebInspector.TabBar.prototype._handleMouseLeave):
(WebInspector.TabBar.prototype._handleNewTabMouseEnter):
* UserInterface/Views/TabBarItem.js: Added.
(WebInspector.TabBarItem):
(WebInspector.TabBarItem.prototype.get identifier):
(WebInspector.TabBarItem.prototype.get element):
(WebInspector.TabBarItem.prototype.get parentTabBar):
(WebInspector.TabBarItem.prototype.set parentTabBar):
(WebInspector.TabBarItem.prototype.get selected):
(WebInspector.TabBarItem.prototype.set selected):
(WebInspector.TabBarItem.prototype.get pinned):
(WebInspector.TabBarItem.prototype.get image):
(WebInspector.TabBarItem.prototype.set image):
(WebInspector.TabBarItem.prototype.get title):
(WebInspector.TabBarItem.prototype.set title):
(WebInspector.TabBarItem.prototype.updateLayout):</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceProtocolInspectorFrontendHostStubjs">trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendHostStub.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabBarcss">trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabBarjs">trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabBarItemjs">trunk/Source/WebInspectorUI/UserInterface/Views/TabBarItem.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (183321 => 183322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2015-04-26 01:14:13 UTC (rev 183321)
+++ trunk/Source/WebInspectorUI/ChangeLog        2015-04-26 01:15:03 UTC (rev 183322)
</span><span class="lines">@@ -1,3 +1,108 @@
</span><ins>+2015-04-06 Timothy Hatcher <timothy@apple.com>
+
+ Web Inspector: Add a WebInspector.TabBar class
+ https://bugs.webkit.org/show_bug.cgi?id=143442
+
+ Reviewed by Joseph Pecoraro.
+
+ * UserInterface/Main.html:
+ Added new files.
+
+ * UserInterface/Protocol/InspectorFrontendHostStub.js:
+ (window.Symbol):
+ (WebInspector.InspectorFrontendHostStub.prototype.showContextMenu):
+ Added some stubs needed to work standalone.
+
+ * UserInterface/Views/TabBar.css: Added.
+ (.tab-bar):
+ (body.window-inactive .tab-bar):
+ (.tab-bar > .top-border):
+ (body.window-inactive .tab-bar > .top-border):
+ (.tab-bar > .item):
+ (.tab-bar > :nth-child(n + 2 of .item)):
+ (.tab-bar > .item.pinned):
+ (.tab-bar > .item.selected):
+ (.tab-bar > .item.new-tab-button:hover):
+ (.tab-bar:not(.animating) > .item:not(.selected):hover + .item):
+ (body.window-inactive .tab-bar > .item):
+ (body.window-inactive .tab-bar > .item.selected):
+ (.tab-bar > .item > .close):
+ (body:not(.window-inactive) .tab-bar:not(.single-tab) > .item:hover > .close):
+ (.tab-bar.single-tab > .item > .close):
+ (.tab-bar > .item > .close:hover):
+ (.tab-bar > .item > .close:active):
+ (.tab-bar > .item > .flex-space):
+ (.tab-bar > .item > .flex-space:last-child):
+ (.tab-bar > .item > .icon):
+ (.tab-bar > .item.selected > .icon):
+ (.tab-bar > .item.new-tab-button:hover > .icon):
+ (.tab-bar > .item > .title):
+ (.tab-bar > .item > .title > .content):
+ (.tab-bar:not(.animating) > .item:not(.selected):hover > .title):
+ (.tab-bar > .item.selected > .title):
+ (.tab-bar.collapsed > .item):
+ (.tab-bar.collapsed > .item > .flex-space):
+ (.tab-bar.collapsed > .item > .close):
+ (.tab-bar.hide-titles > .item > .title):
+ (.tab-bar.hide-titles > .item.selected:hover > .icon):
+ (.tab-bar.hide-titles > .item.selected:hover > .close):
+ (.tab-bar.static-layout):
+ (.tab-bar.static-layout > .item):
+ (.tab-bar.animating.closing-tab > .item):
+ (.tab-bar.animating:matches(.expanding-tabs, .inserting-tab) > .item):
+ (.tab-bar.animating.inserting-tab > .item.being-inserted):
+ (.tab-bar.animating.closing-tab > .item.selected):
+ (body.window-inactive .tab-bar.animating.closing-tab > .item.selected):
+ (.tab-bar.dragging-tab > .item.selected):
+
+ * UserInterface/Views/TabBar.js: Added.
+ (WebInspector.TabBar):
+ (WebInspector.TabBar.prototype.get newTabItem):
+ (WebInspector.TabBar.prototype.set newTabItem):
+ (WebInspector.TabBar.prototype.addTabBarItem):
+ (WebInspector.TabBar.prototype.insertTabBarItem.animateTabs):
+ (WebInspector.TabBar.prototype.insertTabBarItem.removeStyles):
+ (WebInspector.TabBar.prototype.insertTabBarItem):
+ (WebInspector.TabBar.prototype.insertTabBarItem.set else):
+ (WebInspector.TabBar.prototype.insertTabBarItem.set this):
+ (WebInspector.TabBar.animateTabs.get if):
+ (WebInspector.TabBar.animateTabs):
+ (WebInspector.TabBar.removeStyles):
+ (WebInspector.TabBar.prototype.insertTabBarItem):
+ (WebInspector.TabBar.prototype.updateLayoutSoon.update):
+ (WebInspector.TabBar.prototype.updateLayoutSoon):
+ (WebInspector.TabBar.prototype.updateLayout):
+ (WebInspector.TabBar.prototype.get selectedTabBarItem):
+ (WebInspector.TabBar.prototype.set selectedTabBarItem):
+ (WebInspector.TabBar.prototype.get tabBarItems):
+ (WebInspector.TabBar.prototype.get element):
+ (WebInspector.TabBar.prototype._findTabBarItem):
+ (WebInspector.TabBar.prototype._hasMoreThanOneNormalTab):
+ (WebInspector.TabBar.prototype._recordTabBarItemSizesAndPositions):
+ (WebInspector.TabBar.prototype._clearTabBarItemSizesAndPositions):
+ (WebInspector.TabBar.prototype._finishExpandingTabsAfterClose.):
+ (WebInspector.TabBar.prototype._finishExpandingTabsAfterClose):
+ (WebInspector.TabBar.prototype._handleMouseDown):
+ (WebInspector.TabBar.prototype._handleMouseMoved):
+ (WebInspector.TabBar.prototype._handleMouseUp):
+ (WebInspector.TabBar.prototype._handleMouseLeave):
+ (WebInspector.TabBar.prototype._handleNewTabMouseEnter):
+
+ * UserInterface/Views/TabBarItem.js: Added.
+ (WebInspector.TabBarItem):
+ (WebInspector.TabBarItem.prototype.get identifier):
+ (WebInspector.TabBarItem.prototype.get element):
+ (WebInspector.TabBarItem.prototype.get parentTabBar):
+ (WebInspector.TabBarItem.prototype.set parentTabBar):
+ (WebInspector.TabBarItem.prototype.get selected):
+ (WebInspector.TabBarItem.prototype.set selected):
+ (WebInspector.TabBarItem.prototype.get pinned):
+ (WebInspector.TabBarItem.prototype.get image):
+ (WebInspector.TabBarItem.prototype.set image):
+ (WebInspector.TabBarItem.prototype.get title):
+ (WebInspector.TabBarItem.prototype.set title):
+ (WebInspector.TabBarItem.prototype.updateLayout):
+
</ins><span class="cx"> 2015-04-25 Timothy Hatcher <timothy@apple.com>
</span><span class="cx">
</span><span class="cx"> Web Inspector: Make closing ContentViews more leak proof
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceProtocolInspectorFrontendHostStubjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendHostStub.js (183321 => 183322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendHostStub.js        2015-04-26 01:14:13 UTC (rev 183321)
+++ trunk/Source/WebInspectorUI/UserInterface/Protocol/InspectorFrontendHostStub.js        2015-04-26 01:15:03 UTC (rev 183322)
</span><span class="lines">@@ -30,6 +30,13 @@
</span><span class="cx"> * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx"> */
</span><span class="cx">
</span><ins>+if (!window.Symbol) {
+ window.Symbol = function(string)
+ {
+ return string;
+ }
+}
+
</ins><span class="cx"> if (!window.InspectorFrontendHost) {
</span><span class="cx"> WebInspector.InspectorFrontendHostStub = function()
</span><span class="cx"> {
</span><span class="lines">@@ -143,6 +150,10 @@
</span><span class="cx"> {
</span><span class="cx"> },
</span><span class="cx">
</span><ins>+ showContextMenu: function(event, menuObject)
+ {
+ },
+
</ins><span class="cx"> // Private
</span><span class="cx">
</span><span class="cx"> _sendPendingMessagesToBackendIfNeeded: function()
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabBarcss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css (0 => 183322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css         (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css        2015-04-26 01:15:03 UTC (rev 183322)
</span><span class="lines">@@ -0,0 +1,305 @@
</span><ins>+/*
+ * 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.
+ */
+
+.tab-bar {
+ display: flex;
+ justify-content: space-between;
+ flex-wrap: wrap;
+
+ position: relative;
+
+ border-bottom: 1px solid rgb(168, 168, 168);
+
+ background-image: linear-gradient(to bottom, rgb(199, 199, 199), rgb(184, 184, 184));
+ background-size: 100% 200%;
+
+ height: 30px;
+
+ white-space: nowrap;
+ overflow: hidden;
+
+ outline: none;
+}
+
+body.window-inactive .tab-bar {
+ border-bottom-color: rgb(219, 219, 219);
+
+ background-image: none !important;
+ background-color: rgb(236, 236, 236) !important;
+}
+
+.tab-bar > .top-border {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 1px;
+
+ background-color: rgb(168, 168, 168);
+
+ z-index: 0;
+}
+
+body.window-inactive .tab-bar > .top-border {
+ background-color: rgb(219, 219, 219);
+}
+
+.tab-bar > .item {
+ display: flex;
+ flex: 1;
+
+ position: relative;
+
+ z-index: 1;
+
+ align-items: center;
+
+ padding: 0 6px;
+
+ min-width: 30px;
+ overflow: hidden;
+
+ background-image: linear-gradient(to bottom, rgb(199, 199, 199), rgb(184, 184, 184));
+ background-size: 100% 200%;
+
+ border-top: 1px solid rgb(168, 168, 168);
+
+ height: 100%;
+ outline: none;
+
+ /* FIXME: These cause noticeable transitions when focusing the window. Fix that with JavaScript? */
+ /* transition-property: background-position, border-color; */
+ /* transition-duration: 250ms; */
+ /* transition-delay: 50ms; */
+}
+
+.tab-bar > :nth-child(n + 2 of .item),
+.tab-bar.dragging-tab > .item.selected {
+ border-left: 1px solid rgb(168, 168, 168);
+}
+
+.tab-bar > .item.pinned {
+ width: 30px;
+ flex: none;
+ justify-content: center;
+}
+
+.tab-bar > .item.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 {
+ 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 {
+ border-left-color: rgb(152, 152, 152);
+}
+
+body.window-inactive .tab-bar > .item {
+ border-left-color: rgb(219, 219, 219) !important;
+ border-top-color: rgb(219, 219, 219) !important;
+
+ background-image: none !important;
+ background-color: rgb(236, 236, 236) !important;
+
+ transition: none;
+}
+
+body.window-inactive .tab-bar > .item.selected {
+ background-image: none !important;
+ background-color: rgb(246, 246, 246) !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;
+
+ margin-right: 4px;
+
+ transition-property: background-color, opacity;
+ transition-duration: 250ms, 500ms;
+ transition-delay: 0, 50ms;
+}
+
+body:not(.window-inactive) .tab-bar:not(.single-tab) > .item:not(.hide-close-button):hover > .close {
+ opacity: 0.6;
+}
+
+.tab-bar.single-tab > .item > .close,
+.tab-bar > .item.hide-close-button > .close {
+ pointer-events: none;
+}
+
+.tab-bar > .item > .close:hover {
+ background-color: rgba(0, 0, 0, 0.2);
+}
+
+.tab-bar > .item > .close:active {
+ opacity: 0.8 !important;
+}
+
+.tab-bar > .item > .flex-space {
+ display: flex;
+ flex: 1;
+}
+
+.tab-bar > .item > .flex-space:last-child {
+ margin-right: 16px;
+}
+
+.tab-bar > .item > .icon {
+ width: 16px;
+ height: 16px;
+
+ min-width: 16px;
+ min-height: 16px;
+
+ opacity: 0.55; /* Assumes black glyphs. */
+
+ -webkit-user-drag: none;
+}
+
+.tab-bar > .item.selected > .icon {
+ opacity: 0.7;
+}
+
+.tab-bar:not(.animating) > .item:not(.selected):hover > .icon,
+.tab-bar > .item.new-tab-button:hover > .icon {
+ opacity: 0.6;
+}
+
+.tab-bar > .item > .title {
+ margin-left: 6px;
+
+ color: rgba(0, 0, 0, 0.55);
+
+ display: flex;
+
+ min-width: 0;
+ max-width: 400px;
+}
+
+.tab-bar > .item > .title > .content {
+ min-width: 0;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.tab-bar:not(.animating) > .item:not(.selected):hover > .title {
+ color: rgba(0, 0, 0, 0.6);
+}
+
+.tab-bar > .item.selected > .title {
+ color: rgba(0, 0, 0, 0.7);
+}
+
+.tab-bar.collapsed > .item {
+ justify-content: center;
+}
+
+.tab-bar.collapsed > .item > .flex-space {
+ display: none;
+}
+
+.tab-bar.collapsed > .item > .close {
+ display: none;
+ margin-right: 0;
+}
+
+.tab-bar.hide-titles > .item > .title {
+ display: none;
+}
+
+.tab-bar.collapsed:not(.hide-titles) > .item:not(.pinned, .hide-close-button):hover > .icon,
+.tab-bar.hide-titles > .item.selected:hover > .icon {
+ display: none;
+}
+
+.tab-bar.collapsed:not(.hide-titles) > .item:not(.hide-close-button):hover > .close,
+.tab-bar.hide-titles > .item.selected:hover > .close {
+ display: inline-block;
+}
+
+.tab-bar.static-layout {
+ position: relative;
+}
+
+.tab-bar.static-layout > .item {
+ position: absolute !important;
+ top: 0;
+}
+
+.tab-bar.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 {
+ transition-property: left, width;
+ transition-duration: 250ms;
+ transition-timing-function: ease-in-out;
+}
+
+.tab-bar.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 {
+ border-right: 1px solid rgb(168, 168, 168);
+}
+
+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 {
+ border-right-color: rgb(219, 219, 219) !important;
+}
+
+.tab-bar.dragging-tab > .item.selected {
+ z-index: 2;
+ pointer-events: none;
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabBarjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js (0 => 183322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js         (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js        2015-04-26 01:15:03 UTC (rev 183322)
</span><span class="lines">@@ -0,0 +1,672 @@
</span><ins>+/*
+ * 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.TabBar = class TabBar extends WebInspector.Object
+{
+ constructor(element, tabBarItems)
+ {
+ super();
+
+ this._element = element || document.createElement("div");
+ this._element.classList.add("tab-bar");
+ this._element.tabIndex = 0;
+
+ var topBorderElement = document.createElement("div");
+ topBorderElement.classList.add("top-border");
+ this._element.appendChild(topBorderElement);
+
+ this._element.addEventListener("mousedown", this._handleMouseDown.bind(this));
+ this._element.addEventListener("mouseleave", this._handleMouseLeave.bind(this));
+
+ this._tabBarItems = [];
+
+ if (tabBarItems) {
+ for (var tabBarItem in tabBarItems)
+ this.addTabBarItem(tabBarItem);
+ }
+ }
+
+ // Public
+
+ get newTabItem()
+ {
+ return this._newTabItem || null;
+ }
+
+ set newTabItem(newTabItem)
+ {
+ if (!this._handleNewTabMouseEnterListener)
+ this._handleNewTabMouseEnterListener = this._handleNewTabMouseEnter.bind(this);
+
+ if (this._newTabItem) {
+ this._newTabItem.element.classList.remove("new-tab-button");
+ this._newTabItem.element.removeEventListener("mouseenter", this._handleNewTabMouseEnterListener);
+ this.removeTabBarItem(this._newTabItem, true);
+ }
+
+ if (newTabItem) {
+ newTabItem.element.classList.add("new-tab-button");
+ newTabItem.element.addEventListener("mouseenter", this._handleNewTabMouseEnterListener);
+ this.addTabBarItem(newTabItem, true);
+ }
+
+ this._newTabItem = newTabItem || null;
+ }
+
+ addTabBarItem(tabBarItem, doNotAnimate)
+ {
+ return this.insertTabBarItem(tabBarItem, this._tabBarItems.length, doNotAnimate);
+ }
+
+ insertTabBarItem(tabBarItem, index, doNotAnimate)
+ {
+ console.assert(tabBarItem instanceof WebInspector.TabBarItem);
+ if (!(tabBarItem instanceof WebInspector.TabBarItem))
+ return null;
+
+ if (tabBarItem.parentTabBar === this)
+ return;
+
+ if (this._tabAnimatedClosedSinceMouseEnter) {
+ // Delay adding the new tab until we can expand the tabs after a closed tab.
+ this._finishExpandingTabsAfterClose().then(function() {
+ this.insertTabBarItem(tabBarItem, index, doNotAnimate);
+ }.bind(this));
+ return;
+ }
+
+ if (tabBarItem.parentTabBar)
+ tabBarItem.parentTabBar.removeTabBarItem(tabBarItem);
+
+ tabBarItem.parentTabBar = this;
+
+ var lastIndex = this._newTabItem ? this._tabBarItems.length - 1 : this._tabBarItems.length;
+ index = Math.max(0, Math.min(index, lastIndex));
+
+ if (this._element.classList.contains("animating")) {
+ requestAnimationFrame(removeStyles.bind(this));
+ doNotAnimate = true;
+ }
+
+ var beforeTabSizesAndPositions;
+ if (!doNotAnimate)
+ beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
+
+ this._tabBarItems.splice(index, 0, tabBarItem);
+
+ var nextSibling = this._tabBarItems[index + 1];
+ var nextSiblingElement = nextSibling ? nextSibling.element : (this._newTabItem ? this._newTabItem.element : null);
+
+ this._element.insertBefore(tabBarItem.element, nextSiblingElement);
+
+ this._element.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 (!doNotAnimate) {
+ var afterTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
+
+ this.updateLayout();
+
+ var previousTabBarItem = this._tabBarItems[this._tabBarItems.indexOf(tabBarItem) - 1] || null;
+ var 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.updateLayoutSoon();
+
+ this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemAdded, {tabBarItem});
+
+ return tabBarItem;
+ }
+
+ removeTabBarItem(tabBarItemOrIndex, doNotAnimate, doNotExpand)
+ {
+ var tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
+ if (!tabBarItem)
+ return null;
+
+ tabBarItem.parentTabBar = null;
+
+ if (tabBarItem === this._newTabItem)
+ this.newTabItem = null;
+
+ if (this._selectedTabBarItem === tabBarItem) {
+ var index = this._tabBarItems.indexOf(tabBarItem);
+ var nextTabBarItem = this._tabBarItems[index + 1];
+ if (!nextTabBarItem || nextTabBarItem.pinned)
+ nextTabBarItem = this._tabBarItems[index - 1];
+
+ this.selectedTabBarItem = nextTabBarItem;
+ }
+
+ if (this._element.classList.contains("animating")) {
+ requestAnimationFrame(removeStyles.bind(this));
+ doNotAnimate = true;
+ }
+
+ var beforeTabSizesAndPositions;
+ if (!doNotAnimate)
+ beforeTabSizesAndPositions = this._recordTabBarItemSizesAndPositions();
+
+ var wasLastNormalTab = this._tabBarItems.indexOf(tabBarItem) === (this._newTabItem ? this._tabBarItems.length - 2 : this._tabBarItems.length - 1);
+
+ this._tabBarItems.remove(tabBarItem);
+ tabBarItem.element.remove();
+
+ var hasMoreThanOneNormalTab = this._hasMoreThanOneNormalTab();
+ this._element.classList.toggle("single-tab", !hasMoreThanOneNormalTab);
+
+ if (!hasMoreThanOneNormalTab || wasLastNormalTab || !doNotExpand) {
+ if (!doNotAnimate) {
+ this._tabAnimatedClosedSinceMouseEnter = true;
+ this._finishExpandingTabsAfterClose(beforeTabSizesAndPositions);
+ } else
+ this.updateLayoutSoon();
+
+ this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemRemoved, {tabBarItem});
+
+ return tabBarItem;
+ }
+
+ var lastNormalTabBarItem;
+
+ function animateTabs()
+ {
+ this._element.classList.add("animating");
+ this._element.classList.add("closing-tab");
+
+ var left = 0;
+ for (var currentTabBarItem of this._tabBarItems) {
+ var sizeAndPosition = beforeTabSizesAndPositions.get(currentTabBarItem);
+
+ if (!currentTabBarItem.pinned) {
+ currentTabBarItem.element.style.left = 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 (!doNotAnimate) {
+ this._element.classList.add("static-layout");
+
+ this._tabAnimatedClosedSinceMouseEnter = true;
+
+ this._applyTabBarItemSizesAndPositions(beforeTabSizesAndPositions);
+
+ var removeStylesListener = removeStyles.bind(this);
+
+ requestAnimationFrame(animateTabs.bind(this));
+ } else
+ this.updateLayoutSoon();
+
+ this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemRemoved, {tabBarItem});
+
+ return tabBarItem;
+ }
+
+ updateLayoutSoon()
+ {
+ if (this._updateLayoutIdentifier)
+ return;
+
+ this._needsLayout = true;
+
+ function update()
+ {
+ this._updateLayoutIdentifier = undefined;
+
+ if (this._needsLayout)
+ this.updateLayout();
+ }
+
+ this._updateLayoutIdentifier = requestAnimationFrame(update.bind(this));
+ }
+
+ updateLayout()
+ {
+ if (this._updateLayoutIdentifier) {
+ cancelAnimationFrame(this._updateLayoutIdentifier);
+ this._updateLayoutIdentifier = undefined;
+ }
+
+ if (this._element.classList.contains("static-layout"))
+ return;
+
+ this._needsLayout = false;
+
+ this._element.classList.remove("hide-titles");
+ this._element.classList.remove("collapsed");
+
+ var firstNormalTabItem = null;
+ for (var tabItem of this._tabBarItems) {
+ if (tabItem.pinned)
+ continue;
+ firstNormalTabItem = tabItem;
+ break;
+ }
+
+ if (!firstNormalTabItem)
+ return;
+
+ if (firstNormalTabItem.element.offsetWidth >= 120)
+ return;
+
+ this._element.classList.add("collapsed");
+
+ if (firstNormalTabItem.element.offsetWidth >= 60)
+ return;
+
+ this._element.classList.add("hide-titles");
+ }
+
+ get selectedTabBarItem()
+ {
+ return this._selectedTabBarItem;
+ }
+
+ set selectedTabBarItem(tabBarItemOrIndex)
+ {
+ var tabBarItem = this._findTabBarItem(tabBarItemOrIndex);
+
+ if (this._selectedTabBarItem === tabBarItem)
+ return;
+
+ if (this._selectedTabBarItem)
+ this._selectedTabBarItem.selected = false;
+
+ this._selectedTabBarItem = tabBarItem || null;
+
+ if (this._selectedTabBarItem)
+ this._selectedTabBarItem.selected = true;
+
+ this.dispatchEventToListeners(WebInspector.TabBar.Event.TabBarItemSelected);
+ }
+
+ get tabBarItems()
+ {
+ return this._tabBarItems;
+ }
+
+ get element()
+ {
+ return this._element;
+ }
+
+ // Private
+
+ _findTabBarItem(tabBarItemOrIndex)
+ {
+ if (typeof tabBarItemOrIndex === "number")
+ return this._tabBarItems[tabBarItemOrIndex] || null;
+
+ if (tabBarItemOrIndex instanceof WebInspector.TabBarItem) {
+ if (this._tabBarItems.includes(tabBarItemOrIndex))
+ return tabBarItemOrIndex;
+ }
+
+ return null;
+ }
+
+ _hasMoreThanOneNormalTab()
+ {
+ var normalTabCount = 0;
+ for (var tabBarItem of this._tabBarItems) {
+ if (tabBarItem.pinned)
+ continue;
+ ++normalTabCount;
+ if (normalTabCount >= 2)
+ return true;
+ }
+
+ return false;
+ }
+
+ _recordTabBarItemSizesAndPositions()
+ {
+ var tabBarItemSizesAndPositions = new Map;
+
+ var 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);
+
+ 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 handle left mouse clicks.
+ if (event.button !== 0 || event.ctrlKey)
+ return;
+
+ var itemElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.TabBarItem.StyleClassName);
+ if (!itemElement)
+ return;
+
+ var tabBarItem = itemElement[WebInspector.TabBarItem.ElementReferenceSymbol];
+ if (!tabBarItem || tabBarItem === this._newTabItem)
+ return;
+
+ var closeButtonElement = event.target.enclosingNodeOrSelfWithClass(WebInspector.TabBarItem.CloseButtonStyleClassName);
+ if (closeButtonElement) {
+ this.removeTabBarItem(tabBarItem, false, true);
+ return;
+ }
+
+ this.selectedTabBarItem = tabBarItem;
+
+ if (tabBarItem.pinned || !this._hasMoreThanOneNormalTab())
+ return;
+
+ this._firstNormalTabItemIndex = 0;
+ for (var i = 0; i < this._tabBarItems.length; ++i) {
+ if (this._tabBarItems[i].pinned)
+ 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();
+ }
+
+ _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.getBoundingClientRect().width / 2);
+
+ var currentIndex = this._tabBarItems.indexOf(this._selectedTabBarItem);
+ var newIndex = currentIndex;
+
+ for (var 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;
+ }
+
+ newIndex = Math.max(this._firstNormalTabItemIndex, newIndex);
+ newIndex = Math.min(this._newTabItem ? this._tabBarItems.length - 2 : this._tabBarItems.length - 1, newIndex);
+
+ if (currentIndex === newIndex)
+ return;
+
+ this._tabBarItems.splice(currentIndex, 1);
+ this._tabBarItems.splice(newIndex, 0, this._selectedTabBarItem);
+
+ var nextSibling = this._tabBarItems[newIndex + 1];
+ var nextSiblingElement = nextSibling ? nextSibling.element : (this._newTabItem ? this._newTabItem.element : null);
+
+ 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.
+
+ var left = 0;
+ for (var tabBarItem of this._tabBarItems) {
+ if (tabBarItem !== this._selectedTabBarItem && tabBarItem !== this._newTabItem && 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 {
+ var left = 0;
+ for (var tabBarItem of this._tabBarItems) {
+ 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(WebInspector.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?
+ var barRect = this._element.getBoundingClientRect();
+ var newTabItemRect = this._newTabItem ? this._newTabItem.element.getBoundingClientRect() : null;
+ if (event.pageY > barRect.top && event.pageY < barRect.bottom && event.pageX > barRect.left && event.pageX < (newTabItemRect ? newTabItemRect.right : barRect.right))
+ return;
+
+ this._finishExpandingTabsAfterClose();
+ }
+
+ _handleNewTabMouseEnter(event)
+ {
+ if (!this._tabAnimatedClosedSinceMouseEnter || !this._element.classList.contains("static-layout") || this._element.classList.contains("animating"))
+ return;
+
+ this._finishExpandingTabsAfterClose();
+ }
+};
+
+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"
+};
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabBarItemjs"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TabBarItem.js (0 => 183322)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBarItem.js         (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBarItem.js        2015-04-26 01:15:03 UTC (rev 183322)
</span><span class="lines">@@ -0,0 +1,160 @@
</span><ins>+/*
+ * 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.TabBarItem = class TabBarItem extends WebInspector.Object
+{
+ constructor(image, title, pinned, representedObject)
+ {
+ super();
+
+ this._parentTabBar = null;
+
+ this._element = document.createElement("div");
+ this._element.classList.add(WebInspector.TabBarItem.StyleClassName);
+ if (pinned)
+ this._element.classList.add("pinned");
+ this._element[WebInspector.TabBarItem.ElementReferenceSymbol] = this;
+
+ if (!pinned) {
+ this._closeButtonElement = document.createElement("div");
+ this._closeButtonElement.classList.add(WebInspector.TabBarItem.CloseButtonStyleClassName);
+ this._closeButtonElement.title = WebInspector.UIString("Click to close this tab");
+ this._element.appendChild(this._closeButtonElement);
+
+ var flexSpaceElement = document.createElement("div");
+ flexSpaceElement.classList.add("flex-space");
+ this._element.appendChild(flexSpaceElement);
+ }
+
+ this._iconElement = document.createElement("img");
+ this._iconElement.classList.add("icon");
+ this._element.appendChild(this._iconElement);
+
+ if (!pinned) {
+ var flexSpaceElement = document.createElement("div");
+ flexSpaceElement.classList.add("flex-space");
+ this._element.appendChild(flexSpaceElement);
+ }
+
+ this.title = title;
+ this.image = image;
+ this.representedObject = representedObject;
+ }
+
+ // Public
+
+ get element()
+ {
+ return this._element;
+ }
+
+ get representedObject()
+ {
+ return this._representedObject;
+ }
+
+ set representedObject(representedObject)
+ {
+ this._representedObject = representedObject || null;
+ }
+
+ get parentTabBar()
+ {
+ return this._parentTabBar;
+ }
+
+ set parentTabBar(tabBar)
+ {
+ this._parentTabBar = tabBar || null;
+ }
+
+ get selected()
+ {
+ return this._element.classList.contains("selected");
+ }
+
+ set selected(selected)
+ {
+ this._element.classList.toggle("selected", selected);
+ }
+
+ get hideCloseButton()
+ {
+ return this._element.classList.contains("hide-close-button");
+ }
+
+ set hideCloseButton(hide)
+ {
+ this._element.classList.toggle("hide-close-button", hide);
+ }
+
+ get pinned()
+ {
+ return this._element.classList.contains("pinned");
+ }
+
+ get image()
+ {
+ return this._iconElement.src;
+ }
+
+ set image(url)
+ {
+ this._iconElement.src = url || "";
+ }
+
+ get title()
+ {
+ return this._element.title || "";
+ }
+
+ set title(title)
+ {
+ if (title && !this.pinned) {
+ this._titleElement = document.createElement("span");
+ this._titleElement.classList.add("title");
+
+ this._titleContentElement = document.createElement("span");
+ this._titleContentElement.classList.add("content");
+ this._titleElement.appendChild(this._titleContentElement);
+
+ this._titleContentElement.textContent = title;
+
+ this._element.insertBefore(this._titleElement, this._element.lastChild);
+ } else {
+ if (this._titleElement)
+ this._titleElement.remove();
+
+ this._titleContentElement = null;
+ this._titleElement = null;
+ }
+
+ this._element.title = title || "";
+ }
+};
+
+WebInspector.TabBarItem.StyleClassName = "item";
+WebInspector.TabBarItem.CloseButtonStyleClassName = "close";
+WebInspector.TabBarItem.ElementReferenceSymbol = Symbol("tab-bar-item");
</ins></span></pre>
</div>
</div>
</body>
</html>