Title: [212582] trunk/Source/WebInspectorUI
Revision
212582
Author
bb...@apple.com
Date
2017-02-17 14:54:55 -0800 (Fri, 17 Feb 2017)

Log Message

Web Inspector: RTL: add TabBar support for RTL layout
https://bugs.webkit.org/show_bug.cgi?id=168446

Reviewed by Matt Baker.

There are two types of changes needed:
 - Flip leading and trailing borders and margins for the tab items.
 - Enumerate tabs in reverse order when performing manual layout.

Along the way, I added some color variables local to TabBar.css to
reduce the number of redundant border-style and color declarations.

* UserInterface/Base/Main.js:
Change this to resolvedLayoutDirection(), and resolve "System" to "ltr" or "rtl".
This makes it suitable for use in manual layout without worrying about "System".
Fix the one existing use-site to not do its own resolution of "System".

* UserInterface/Views/TabBar.css:
Define commonly used colors and border styles and adopt var() usages.
Flip borders that should vary in RTL vs LTR, but not all of them. In
many cases, the border is not direction-dependent and looks the same
on both sides. Also, no need to swap animated properties as all manual
layout is done from the left edge.

(.tab-bar):
(body.window-inactive .tab-bar):
(.tab-bar > .top-border):
(body.window-inactive .tab-bar > .top-border):
(.tab-bar > .item):
(body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),):
(body[dir=rtl] .tab-bar > :nth-child(n + 2 of .item),):
(.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover):
(body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,):
(body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,):
(body.window-inactive .tab-bar > .item):
(body[dir=ltr].window-inactive .tab-bar > .item):
(body[dir=rtl].window-inactive .tab-bar > .item):
(.tab-bar > .item > .close):
(body[dir=ltr] .tab-bar > .item > .close):
(body[dir=rtl] .tab-bar > .item > .close):
(.tab-bar > .item:not(.pinned) > .flex-space:last-child):
(body[dir=ltr] .tab-bar > .item:not(.pinned) > .flex-space:last-child):
(body[dir=rtl] .tab-bar > .item:not(.pinned) > .flex-space:last-child):
(.tab-bar > .item > .title):
(body[dir=ltr] .tab-bar > .item > .title):
(body[dir=rtl] .tab-bar > .item > .title):
(.tab-bar.collapsed > .item > .close):
(body[dir=ltr] .tab-bar.collapsed > .item > .close):
(body[dir=rtl] .tab-bar.collapsed > .item > .close):

* UserInterface/Views/TabBar.js:
When doing manual layout, keep doing calculations with respect to the left edge
and keep the list of tab items in logical (LTR) order, as in the DOM. But, when
manually positioning tab items for RTL layout direction, reverse the tab items
so that it matches the screen/layout order of the flipped flexbox items.

(WebInspector.TabBar.prototype.insertTabBarItem):
(WebInspector.TabBar.prototype.removeTabBarItem.animateTabs):
In RTL, put extra space after closing a tab to the left of normal tabs. This
matches the behavior of LTR, but requires some additional measurement since we
still position tabs using `left` and can't simply infer the leftover space.

(WebInspector.TabBar.prototype._tabBarItemsFromLeftToRight): Added.
(WebInspector.TabBar.prototype._handleMouseMoved):
(WebInspector.TabBar.prototype._handleMouseUp):

Modified Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (212581 => 212582)


--- trunk/Source/WebInspectorUI/ChangeLog	2017-02-17 22:51:12 UTC (rev 212581)
+++ trunk/Source/WebInspectorUI/ChangeLog	2017-02-17 22:54:55 UTC (rev 212582)
@@ -1,3 +1,71 @@
+2017-02-17  Brian Burg  <bb...@apple.com>
+
+        Web Inspector: RTL: add TabBar support for RTL layout
+        https://bugs.webkit.org/show_bug.cgi?id=168446
+
+        Reviewed by Matt Baker.
+
+        There are two types of changes needed:
+         - Flip leading and trailing borders and margins for the tab items.
+         - Enumerate tabs in reverse order when performing manual layout.
+
+        Along the way, I added some color variables local to TabBar.css to
+        reduce the number of redundant border-style and color declarations.
+
+        * UserInterface/Base/Main.js:
+        Change this to resolvedLayoutDirection(), and resolve "System" to "ltr" or "rtl".
+        This makes it suitable for use in manual layout without worrying about "System".
+        Fix the one existing use-site to not do its own resolution of "System".
+
+        * UserInterface/Views/TabBar.css:
+        Define commonly used colors and border styles and adopt var() usages.
+        Flip borders that should vary in RTL vs LTR, but not all of them. In
+        many cases, the border is not direction-dependent and looks the same
+        on both sides. Also, no need to swap animated properties as all manual
+        layout is done from the left edge.
+
+        (.tab-bar):
+        (body.window-inactive .tab-bar):
+        (.tab-bar > .top-border):
+        (body.window-inactive .tab-bar > .top-border):
+        (.tab-bar > .item):
+        (body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),):
+        (body[dir=rtl] .tab-bar > :nth-child(n + 2 of .item),):
+        (.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover):
+        (body[dir=ltr] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,):
+        (body[dir=rtl] .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover,):
+        (body.window-inactive .tab-bar > .item):
+        (body[dir=ltr].window-inactive .tab-bar > .item):
+        (body[dir=rtl].window-inactive .tab-bar > .item):
+        (.tab-bar > .item > .close):
+        (body[dir=ltr] .tab-bar > .item > .close):
+        (body[dir=rtl] .tab-bar > .item > .close):
+        (.tab-bar > .item:not(.pinned) > .flex-space:last-child):
+        (body[dir=ltr] .tab-bar > .item:not(.pinned) > .flex-space:last-child):
+        (body[dir=rtl] .tab-bar > .item:not(.pinned) > .flex-space:last-child):
+        (.tab-bar > .item > .title):
+        (body[dir=ltr] .tab-bar > .item > .title):
+        (body[dir=rtl] .tab-bar > .item > .title):
+        (.tab-bar.collapsed > .item > .close):
+        (body[dir=ltr] .tab-bar.collapsed > .item > .close):
+        (body[dir=rtl] .tab-bar.collapsed > .item > .close):
+
+        * UserInterface/Views/TabBar.js:
+        When doing manual layout, keep doing calculations with respect to the left edge
+        and keep the list of tab items in logical (LTR) order, as in the DOM. But, when
+        manually positioning tab items for RTL layout direction, reverse the tab items
+        so that it matches the screen/layout order of the flipped flexbox items.
+
+        (WebInspector.TabBar.prototype.insertTabBarItem):
+        (WebInspector.TabBar.prototype.removeTabBarItem.animateTabs):
+        In RTL, put extra space after closing a tab to the left of normal tabs. This
+        matches the behavior of LTR, but requires some additional measurement since we
+        still position tabs using `left` and can't simply infer the leftover space.
+
+        (WebInspector.TabBar.prototype._tabBarItemsFromLeftToRight): Added.
+        (WebInspector.TabBar.prototype._handleMouseMoved):
+        (WebInspector.TabBar.prototype._handleMouseUp):
+
 2017-02-17  Devin Rousso  <dcrousso+web...@gmail.com>
 
         Web Inspector: Zoom level UI out of sync with setting value

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (212581 => 212582)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2017-02-17 22:51:12 UTC (rev 212581)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2017-02-17 22:54:55 UTC (rev 212582)
@@ -243,13 +243,8 @@
     }
 
     document.body.classList.add(this.debuggableType);
+    document.body.setAttribute("dir", this.resolvedLayoutDirection());
 
-    let layoutDirection = WebInspector.settings.layoutDirection.value;
-    if (layoutDirection === WebInspector.LayoutDirection.System)
-        layoutDirection = InspectorFrontendHost.userInterfaceLayoutDirection();
-
-    document.body.setAttribute("dir", layoutDirection);
-
     function setTabSize() {
         document.body.style.tabSize = WebInspector.settings.tabSize.value;
     }
@@ -2144,11 +2139,15 @@
     WebInspector.settings.zoomFactor.value = InspectorFrontendHost.zoomFactor();
 };
 
-WebInspector.getLayoutDirection = function()
+WebInspector.resolvedLayoutDirection = function()
 {
-    return WebInspector.settings.layoutDirection.value;
-};
+    let layoutDirection = WebInspector.settings.layoutDirection.value;
+    if (layoutDirection === WebInspector.LayoutDirection.System)
+        layoutDirection = InspectorFrontendHost.userInterfaceLayoutDirection();
 
+    return layoutDirection;
+}
+
 WebInspector.setLayoutDirection = function(value)
 {
     if (!Object.values(WebInspector.LayoutDirection).includes(value))

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css (212581 => 212582)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css	2017-02-17 22:51:12 UTC (rev 212581)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.css	2017-02-17 22:54:55 UTC (rev 212582)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-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
@@ -34,7 +34,7 @@
     justify-content: space-between;
     flex-wrap: wrap;
 
-    border-bottom: 1px solid hsl(0, 0%, 65%);
+    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%;
@@ -43,13 +43,21 @@
     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-color: hsl(0, 0%, 85%);
+    --tab-item-extra-light-border-color: hsl(0, 0%, 92%);
+
+    --tab-item-medium-border-style: 1px solid var(--tab-item-medium-border-color);
+    --tab-item-light-border-style: 1px solid var(--tab-item-light-border-color);
 }
 
 body.window-inactive .tab-bar {
-    border-bottom-color: hsl(0, 0%, 85%);
+    border-bottom-color: var(--tab-item-light-border-color);
 
     background-image: none !important;
-    background-color: hsl(0, 0%, 92%) !important;
+    background-color: var(--tab-item-extra-light-border-color) !important;
 }
 
 .tab-bar > .top-border {
@@ -59,13 +67,13 @@
     right: 0;
     height: 1px;
 
-    background-color: hsl(0, 0%, 65%);
+    background-color: var(--tab-item-medium-border-color);
 
     z-index: 0;
 }
 
 body.window-inactive .tab-bar > .top-border {
-    background-color: hsl(0, 0%, 85%);
+    background-color: var(--tab-item-light-border-color);
 }
 
 .tab-bar > .item {
@@ -86,7 +94,7 @@
     background-image: linear-gradient(to bottom, hsl(0, 0%, 78%), hsl(0, 0%, 72%));
     background-size: 100% 200%;
 
-    border-top: 1px solid hsl(0, 0%, 65%);
+    border-top: var(--tab-item-medium-border-style);
 
     height: 100%;
     line-height: 15px;
@@ -98,11 +106,16 @@
     /* transition-delay: 50ms; */
 }
 
-.tab-bar > :nth-child(n + 2 of .item),
-.tab-bar.dragging-tab > .item.selected {
-    border-left: 1px solid hsl(0, 0%, 65%);
+body[dir=ltr] .tab-bar > :nth-child(n + 2 of .item),
+body[dir=ltr] .tab-bar.dragging-tab > .item.selected {
+    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 {
+    border-right: var(--tab-item-medium-border-style);
+}
+
 .tab-bar > .item.pinned {
     width: 24px;
     flex: none;
@@ -117,24 +130,36 @@
 
 .tab-bar:not(.animating) > .item:not(.selected, .disabled):hover {
     background-position: 0 100%;
-    border-top-color: hsl(0, 0%, 59%);
-    border-left-color: hsl(0, 0%, 59%);
+    border-top-color: var(--tab-item-dark-border-color);
 }
 
-.tab-bar:not(.animating) > .item:not(.selected, .disabled):hover + .item {
-    border-left-color: hsl(0, 0%, 59%);
+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 {
+    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 {
+    border-right-color: var(--tab-item-dark-border-color);
+}
+
 body.window-inactive .tab-bar > .item {
-    border-left-color: hsl(0, 0%, 85%) !important;
-    border-top-color: hsl(0, 0%, 85%) !important;
+    border-top-color: var(--tab-item-light-border-color) !important;
 
     background-image: none !important;
-    background-color: hsl(0, 0%, 92%) !important;
+    background-color: var(--tab-item-extra-light-border-color) !important;
 
     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 {
     background-image: none !important;
     background-color: hsl(0, 0%, 96%) !important;
@@ -154,13 +179,21 @@
     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;
+
+    --tab-item-close-button-margin-end: 4px;
 }
 
+body[dir=ltr] .tab-bar > .item > .close {
+    margin-right: var(--tab-item-close-button-margin-end);
+}
+
+body[dir=rtl] .tab-bar > .item > .close {
+    margin-left: var(--tab-item-close-button-margin-end);
+}
+
 body:not(.window-inactive) .tab-bar > .item:hover > .close {
     opacity: 0.6;
 }
@@ -187,9 +220,17 @@
 }
 
 .tab-bar > .item:not(.pinned) > .flex-space:last-child {
-    margin-right: 16px;
+    --tab-item-unpinned-trailing-flex-space-margin-end: 16px;
 }
 
+body[dir=ltr] .tab-bar > .item:not(.pinned) > .flex-space:last-child {
+    margin-right: var(--tab-item-unpinned-trailing-flex-space-margin-end);
+}
+
+body[dir=rtl] .tab-bar > .item:not(.pinned) > .flex-space:last-child {
+    margin-left: var(--tab-item-unpinned-trailing-flex-space-margin-end);
+}
+
 .tab-bar > .item > .icon {
     width: 16px;
     height: 16px;
@@ -222,8 +263,6 @@
 }
 
 .tab-bar > .item > .title {
-    margin-left: 6px;
-
     color: hsla(0, 0%, 0%, 0.55);
 
     display: flex;
@@ -230,8 +269,18 @@
 
     min-width: 0;
     max-width: 400px;
+
+    --tab-item-title-margin-start: 6px;
 }
 
+body[dir=ltr] .tab-bar > .item > .title {
+    margin-left: var(--tab-item-title-margin-start);
+}
+
+body[dir=rtl] .tab-bar > .item > .title {
+    margin-right: var(--tab-item-title-margin-start);
+}
+
 .tab-bar > .item > .title > .content {
     min-width: 0;
     width: 100%;
@@ -258,9 +307,17 @@
 
 .tab-bar.collapsed > .item > .close {
     display: none;
-    margin-right: 0;
+    --tab-item-close-button-margin-end: 0;
 }
 
+body[dir=ltr] .tab-bar.collapsed > .item > .close {
+    margin-right: var(--tab-item-close-button-margin-end);
+}
+
+body[dir=rtl] .tab-bar.collapsed > .item > .close {
+    margin-left: var(--tab-item-close-button-margin-end);
+}
+
 .tab-bar.hide-titles > .item > .title {
     display: none;
 }
@@ -305,13 +362,13 @@
 .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 hsl(0, 0%, 65%);
+    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 {
-    border-right-color: hsl(0, 0%, 85%) !important;
+    border-right-color: var(--tab-item-light-border-color) !important;
 }
 
 .tab-bar.dragging-tab > .item.selected {

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js (212581 => 212582)


--- trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js	2017-02-17 22:51:12 UTC (rev 212581)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabBar.js	2017-02-17 22:54:55 UTC (rev 212582)
@@ -143,8 +143,9 @@
 
             this.updateLayout();
 
-            var previousTabBarItem = this._tabBarItems[this._tabBarItems.indexOf(tabBarItem) - 1] || null;
-            var previousTabBarItemSizeAndPosition = previousTabBarItem ? beforeTabSizesAndPositions.get(previousTabBarItem) : null;
+            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});
@@ -233,12 +234,22 @@
             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);
+            // 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 (WebInspector.resolvedLayoutDirection() === WebInspector.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 WebInspector.PinnedTabBarItem)) {
-                    currentTabBarItem.element.style.left = left + "px";
+                    currentTabBarItem.element.style.left = extraSpaceBetweenNormalAndPinnedTabs + left + "px";
                     left += sizeAndPosition.width;
                     lastNormalTabBarItem = currentTabBarItem;
                 } else
@@ -410,6 +421,11 @@
 
     // Private
 
+    _tabBarItemsFromLeftToRight()
+    {
+        return WebInspector.resolvedLayoutDirection() === WebInspector.LayoutDirection.LTR ? this._tabBarItems : this._tabBarItems.slice().reverse();
+    }
+
     _findTabBarItem(tabBarItemOrIndex)
     {
         if (typeof tabBarItemOrIndex === "number")
@@ -665,7 +681,7 @@
         // 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._tabBarItems) {
+        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);
@@ -685,8 +701,8 @@
             this.element.classList.remove("static-layout");
             this._clearTabBarItemSizesAndPositions();
         } else {
-            var left = 0;
-            for (var tabBarItem of this._tabBarItems) {
+            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);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to