Skip to content
Permalink
Browse files
Web Inspector: Elements Tab: add a navigation item to control what ba…
…dges are shown

https://bugs.webkit.org/show_bug.cgi?id=243858

Reviewed by Patrick Angle.

This will allow us to add more badges (e.g. "Scroll", "Events", etc.) without overloading the DOM
tree with too many badges, as developers can turn off ones they do not find useful.

* Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.js:
(WI.DOMTreeContentView):
(WI.DOMTreeContentView.prototype.get navigationItems):
(WI.DOMTreeContentView.prototype.attached):
(WI.DOMTreeContentView.prototype.detached):
(WI.DOMTreeContentView.prototype._populateConfigureDOMTreeBadgesNavigationItemContextMenu): Added.
* Source/WebInspectorUI/UserInterface/Views/DOMTreeContentView.css:
(.item.button.text-only.configure-dom-tree-badges): Added.
(.item.button.text-only.configure-dom-tree-badges:hover): Added.
The "Badges" navigation item will show a contextmenu containing checkbox items for each type of DOM
tree badge. If any badges are selected, the navigation item is considered activated. Currently there
are only two badges: "flex" and "grid".

* Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.js:
(WI.DOMTreeElement):
(WI.DOMTreeElement.prototype.onattach):
(WI.DOMTreeElement.prototype.ondetach):
(WI.DOMTreeElement.prototype.insertChildElement):
(WI.DOMTreeElement.prototype.updateTitle):
(WI.DOMTreeElement.prototype._createBadge): Added.
(WI.DOMTreeElement.prototype._createBadges): Added.
(WI.DOMTreeElement.prototype._updateBadges): Added.
(WI.DOMTreeElement.prototype._handleLayoutFlagsChanged):
(WI.DOMTreeElement.prototype._handleShownDOMTreeBadgesChanged): Added.
(WI.DOMTreeElement.prototype._updateLayoutBadge): Deleted.
(WI.DOMTreeElement.prototype._updateLayoutBadgeStatus): Deleted.
* Source/WebInspectorUI/UserInterface/Views/DOMTreeElement.css:
(.tree-outline.dom .badge): Renamed from `.tree-outline.dom .layout-badge`.
(.tree-outline.dom .badge.activated): Renamed from `.tree-outline.dom .layout-badge.activated`.
(body:not(.window-inactive, .window-docked-inactive) .tree-outline.dom:focus-within li.selected .badge): Renamed from `body:not(.window-inactive, .window-docked-inactive) .tree-outline.dom:focus-within li.selected .layout-badge`.
(@media (prefers-color-scheme: dark) .tree-outline.dom .badge): Renamed from `@media (prefers-color-scheme: dark) .tree-outline.dom .layout-badge`.
Rework how badges are created to first check that the desired badge is allowed based on the current
selections from the above navigation item. Also don't assume that there is only one badge.

* Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.js:
(WI.DOMTreeOutline.prototype.update):
Add a `showBadges` constructor option that controls whether any child `WI.DOMTreeElement` will even
try to create a badge. This ensures that badges are only created in the DOM tree in the Elements Tab.

* Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js:
(WI.HierarchicalPathNavigationItem.prototype.update):
Drive-by: Use `.width` instead of `.element.realOffsetWidth` as the former includes any CSS margins.

* Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.js:
(WI.ButtonNavigationItem.prototype.get totalMargin):
(WI.ButtonNavigationItem.prototype.get textMargin): Added.
* Source/WebInspectorUI/UserInterface/Views/ButtonNavigationItem.css:
(.navigation-bar .item.button.text-only):
* Source/WebInspectorUI/UserInterface/Views/TextToggleButtonNavigationItem.js:
(WI.TextToggleButtonNavigationItem.prototype.get textMargin): Added.
* Source/WebInspectorUI/UserInterface/Views/TextToggleButtonNavigationItem.css:
(.navigation-bar .item.text-toggle.button.text-only):
(.navigation-bar .item.text-toggle.button.text-only:not(:hover, .selected)): Added.
Drive-by: Decrease text toggle `margin` and `padding` to better match text button.

* Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js:
(WI.TimelineOverview):
* Source/WebInspectorUI/UserInterface/Views/TimelineOverview.css:
(.navigation-bar.timelines .item.text.enabled-timelines): Added.
* Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.js:
(WI.AuditNavigationSidebarPanel.prototype.showDefaultContentView):
(WI.AuditNavigationSidebarPanel.prototype.initialLayout):
* Source/WebInspectorUI/UserInterface/Views/AuditNavigationSidebarPanel.css:
(.content-view.audit .message-text-view .navigation-item-help:is(.start-editing-audits, .stop-editing-audits) .navigation-bar): Deleted.
* Source/WebInspectorUI/UserInterface/Views/Main.css:
(.navigation-item-help > .navigation-bar):
Drive-by: Add an icon for all other text buttons.

* Source/WebInspectorUI/UserInterface/Views/TextNavigationItem.css:
(.navigation-bar .item:first-child.text): Added.
(.navigation-bar .item:last-child.text): Added.
Drive-by: Don't add so much padding if the text is at the beginning/end of the `WI.NavigationBar`.

* Source/WebInspectorUI/UserInterface/Base/Utilities.js:
(Array.prototype.toggleIncludes):
* LayoutTests/inspector/unit-tests/array-utilities.html:
* LayoutTests/inspector/unit-tests/array-utilities-expected.txt:
Drive-by: Allow not passing a `force`, which behaves like a flip-flop.

* Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js:

Canonical link: https://commits.webkit.org/253579@main
  • Loading branch information
dcrousso committed Aug 19, 2022
1 parent 26e467e commit 5c3f6f4a6d39f6ff0fd12999c8ba73abe94d0124
Show file tree
Hide file tree
Showing 20 changed files with 206 additions and 83 deletions.
@@ -142,6 +142,8 @@ PASS: toggleIncludes of an existing item with force true should have no effect.
PASS: toggleIncludes of an existing item with force false should remove the item.
PASS: toggleIncludes of a nonexistent item with force true should add the item.
PASS: toggleIncludes of a nonexistent item with force false should have no effect.
PASS: toggleIncludes with no 'force' should add the item if it's not present.
PASS: toggleIncludes with no 'force' should remove the item if it's present.

-- Running test case: Array.prototype.insertAtIndex
PASS: insertAtIndex with index unspecified should insert at the beginning.
@@ -309,6 +309,12 @@
arr4.toggleIncludes(4, false);
InspectorTest.expectShallowEqual(arr4, [1, 2, 3], "toggleIncludes of a nonexistent item with force false should have no effect.");

let arr5 = [1, 2, 3];
arr5.toggleIncludes(4);
InspectorTest.expectShallowEqual(arr5, [1, 2, 3, 4], "toggleIncludes with no 'force' should add the item if it's not present.");
arr5.toggleIncludes(4);
InspectorTest.expectShallowEqual(arr5, [1, 2, 3], "toggleIncludes with no 'force' should remove the item if it's present.");

return true;
}
});
@@ -232,6 +232,8 @@ localizedStrings["Average: %s"] = "Average: %s";
localizedStrings["BMP"] = "BMP";
localizedStrings["Back (%s)"] = "Back (%s)";
localizedStrings["Backtrace"] = "Backtrace";
/* Label for navigation item that controls what badges are shown in the main DOM tree. */
localizedStrings["Badges @ Elements Tab"] = "Badges";
localizedStrings["Basic"] = "Basic";
/* Section title for basic font properties. */
localizedStrings["Basic Properties @ Font Details Sidebar Section"] = "Basic Properties";
@@ -321,6 +323,7 @@ localizedStrings["Child"] = "Child";
localizedStrings["Child Layers"] = "Child Layers";
localizedStrings["Child added to "] = "Child added to ";
localizedStrings["Children"] = "Children";
localizedStrings["Choose which badges are shown in the DOM tree"] = "Choose which badges are shown in the DOM tree";
localizedStrings["Cipher"] = "Cipher";
localizedStrings["Clamp to sRGB"] = "Clamp to sRGB";
localizedStrings["Classes"] = "Classes";
@@ -629,6 +632,8 @@ localizedStrings["Enable paint flashing"] = "Enable paint flashing";
localizedStrings["Enable source maps"] = "Enable source maps";
localizedStrings["Enable:"] = "Enable:";
localizedStrings["Enabled"] = "Enabled";
/* Label for column showing the list of enabled timelines. */
localizedStrings["Enabled Timelines @ Timelines Tab"] = "Enabled Timelines";
localizedStrings["Encoded"] = "Encoded";
localizedStrings["Encoding"] = "Encoding";
localizedStrings["Energy Impact"] = "Energy Impact";
@@ -759,7 +759,8 @@ Object.defineProperty(Array.prototype, "toggleIncludes",
value(value, force)
{
let exists = this.includes(value);
if (exists === !!force)

if (force !== undefined && exists === !!force)
return;

if (exists)
@@ -58,10 +58,6 @@
border-bottom: 1px solid var(--border-color);
}

.content-view.audit .message-text-view .navigation-item-help:is(.start-editing-audits, .stop-editing-audits) .navigation-bar {
--navigation-item-help-navigation-bar-vertical-align: 0.5px;
}

.content-view.tab.audit .content-view > .audit-version {
position: absolute;
right: 0;
@@ -59,7 +59,7 @@ WI.AuditNavigationSidebarPanel = class AuditNavigationSidebarPanel extends WI.Na
createAuditHelpElement.classList.add("create-audit");
contentPlaceholder.appendChild(createAuditHelpElement);

let stopEditingAuditsNavigationItem = new WI.ButtonNavigationItem("stop-editing-audits", WI.UIString("Done"));
let stopEditingAuditsNavigationItem = new WI.ButtonNavigationItem("stop-editing-audits", WI.UIString("Done"), "Images/Pencil.svg", 16, 16);
stopEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);

let stopEditingAuditsHelpElement = WI.createNavigationItemHelp(WI.UIString("Press %s to stop editing audits."), stopEditingAuditsNavigationItem);
@@ -86,7 +86,7 @@ WI.AuditNavigationSidebarPanel = class AuditNavigationSidebarPanel extends WI.Na
importAuditHelpElement.classList.add("import-audit");
contentPlaceholder.appendChild(importAuditHelpElement);

let startEditingAuditsNavigationItem = new WI.ButtonNavigationItem("start-editing-audits", WI.UIString("Edit"));
let startEditingAuditsNavigationItem = new WI.ButtonNavigationItem("start-editing-audits", WI.UIString("Edit"), "Images/Pencil.svg", 16, 16);
startEditingAuditsNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);

let startEditingAuditsHelpElement = WI.createNavigationItemHelp(hasEnabledAudit ? WI.UIString("Press %s to start editing audits.") : WI.UIString("Press %s to enable audits."), startEditingAuditsNavigationItem);
@@ -154,7 +154,7 @@ WI.AuditNavigationSidebarPanel = class AuditNavigationSidebarPanel extends WI.Na

this.addSubview(controlsNavigationBar);

this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done"));
this._editButtonNavigationItem = new WI.ActivateButtonNavigationItem("edit-audits", WI.UIString("Edit"), WI.UIString("Done"), "Images/Pencil.svg", 16, 16);
this._editButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleEditButtonNavigationItemClicked, this);
this.filterBar.addFilterNavigationItem(this._editButtonNavigationItem);

@@ -55,8 +55,8 @@
}

.navigation-bar .item.button.text-only {
padding: 1px 8px 3px;
margin: 0 2px; /* WI.ButtonNavigationItem.prototype.get totalMargin */
padding: 1px 4px 3px;
margin: 0 2px; /* WI.ButtonNavigationItem.prototype.get textMargin */

height: initial;
line-height: 11px;
@@ -163,10 +163,14 @@ WI.ButtonNavigationItem = class ButtonNavigationItem extends WI.NavigationItem

get totalMargin()
{
let totalMargin = super.totalMargin;
return super.totalMargin + this.textMargin;
}

get textMargin()
{
if (this._buttonStyle === ButtonNavigationItem.Style.Text)
return totalMargin + 4; /* .navigation-bar .item.button.text-only */
return totalMargin;
return 4; /* .navigation-bar .item.button.text-only */
return 0;
}

get additionalClassNames()
@@ -23,6 +23,14 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/

.item.button.text-only.configure-dom-tree-badges {
border-color: var(--border-color);
}

.item.button.text-only.configure-dom-tree-badges:hover {
background-color: var(--background-color-alternate);
}

.content-view.dom-tree {
overflow: auto;
}
@@ -31,6 +31,14 @@ WI.DOMTreeContentView = class DOMTreeContentView extends WI.ContentView

super(representedObject);

// COMPATIBILITY (macOS 12.0, iOS 15.0): CSS.nodeLayoutContextTypeChanged did not exist yet.
// COMPATIBILITY (macOS 13.0, iOS 16.0): CSS.nodeLayoutContextTypeChanged was renamed/expanded to CSS.nodeLayoutFlagsChanged.
this._configureDOMTreeBadgesNavigationItem = new WI.ButtonNavigationItem("configure-dom-tree-badges", WI.UIString("Badges", "Badges @ Elements Tab", "Label for navigation item that controls what badges are shown in the main DOM tree."));
this._configureDOMTreeBadgesNavigationItem.tooltip = WI.UIString("Choose which badges are shown in the DOM tree");
this._configureDOMTreeBadgesNavigationItem.enabled = InspectorBackend.hasEvent("CSS.nodeLayoutFlagsChanged") || InspectorBackend.hasEvent("CSS.nodeLayoutContextTypeChanged");
this._configureDOMTreeBadgesNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
WI.addMouseDownContextMenuHandlers(this._configureDOMTreeBadgesNavigationItem.element, this._populateConfigureDOMTreeBadgesNavigationItemContextMenu.bind(this));

// COMPATIBILITY (iOS 12)
WI.settings.showRulers.addEventListener(WI.Setting.Event.Changed, this._showRulersChanged, this);
this._showRulersButtonNavigationItem = new WI.ActivateButtonNavigationItem("show-rulers", WI.UIString("Show rulers"), WI.UIString("Hide rulers"), "Images/Rulers.svg", 16, 16);
@@ -63,7 +71,7 @@ WI.DOMTreeContentView = class DOMTreeContentView extends WI.ContentView
this.element.classList.add("dom-tree");
this.element.addEventListener("click", this._mouseWasClicked.bind(this), false);

this._domTreeOutline = new WI.DOMTreeOutline({omitRootDOMNode: true, excludeRevealElementContextMenu: true, showInspectedNode: true});
this._domTreeOutline = new WI.DOMTreeOutline({omitRootDOMNode: true, excludeRevealElementContextMenu: true, showInspectedNode: true, showBadges: true});
this._domTreeOutline.allowsEmptySelection = false;
this._domTreeOutline.allowsMultipleSelection = true;
this._domTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._domTreeElementAdded, this);
@@ -108,6 +116,7 @@ WI.DOMTreeContentView = class DOMTreeContentView extends WI.ContentView
get navigationItems()
{
return [
this._configureDOMTreeBadgesNavigationItem,
this._showRulersButtonNavigationItem,
this._showPrintStylesButtonNavigationItem,
this._forceAppearanceButtonNavigationItem,
@@ -492,6 +501,28 @@ WI.DOMTreeContentView = class DOMTreeContentView extends WI.ContentView
selectNode.call(this);
}

_populateConfigureDOMTreeBadgesNavigationItemContextMenu(contextMenu)
{
if (!this._configureDOMTreeBadgesNavigationItem.enabled)
return;

// COMPATIBILITY (iOS 14.5): `DOM.showGridOverlay` did not exist yet.
if (InspectorBackend.hasCommand("DOM.showGridOverlay")) {
contextMenu.appendCheckboxItem(WI.unlocalizedString("grid"), () => {
WI.settings.enabledDOMTreeBadgeTypes.value.toggleIncludes(WI.DOMTreeElement.BadgeType.Grid);
WI.settings.enabledDOMTreeBadgeTypes.save();
}, WI.settings.enabledDOMTreeBadgeTypes.value.includes(WI.DOMTreeElement.BadgeType.Grid));
}

// COMPATIBILITY (macOS 13.0, iOS 16.0): `DOM.showFlexOverlay` did not exist yet.
if (InspectorBackend.hasCommand("DOM.showFlexOverlay")) {
contextMenu.appendCheckboxItem(WI.unlocalizedString("flex"), () => {
WI.settings.enabledDOMTreeBadgeTypes.value.toggleIncludes(WI.DOMTreeElement.BadgeType.Flex);
WI.settings.enabledDOMTreeBadgeTypes.save();
}, WI.settings.enabledDOMTreeBadgeTypes.value.includes(WI.DOMTreeElement.BadgeType.Flex));
}
}

_domTreeElementAdded(event)
{
if (!this._pendingBreakpointNodes.size)
@@ -23,7 +23,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/

.tree-outline.dom .layout-badge {
.tree-outline.dom .badge {
/* Using sans-serif San Francisco font here creates a badge 1px taller than the selected
area. Use the same monospace font as the rest of the DOM tree outline. */

@@ -38,19 +38,19 @@
box-shadow: 0 0 1px hsla(0, 0%, 0%, 0.5);
}

.tree-outline.dom .layout-badge.activated {
.tree-outline.dom .badge.activated {
background: var(--glyph-color-active);
color: white;
}

body:not(.window-inactive, .window-docked-inactive) .tree-outline.dom:focus-within li.selected .layout-badge {
body:not(.window-inactive, .window-docked-inactive) .tree-outline.dom:focus-within li.selected .badge {
/* Override `li.selected * {color: inherited}` from DOMTreeOutline.css */
color: var(--text-color);
}


@media (prefers-color-scheme: dark) {
.tree-outline.dom .layout-badge {
.tree-outline.dom .badge {
background: hsla(0, 0%, 30%, 0.8);
border-color: hsla(0, 0%, 100%, 0.1);
}

0 comments on commit 5c3f6f4

Please sign in to comment.