Title: [290112] trunk/Source/WebCore
Revision
290112
Author
[email protected]
Date
2022-02-17 21:21:37 -0800 (Thu, 17 Feb 2022)

Log Message

Web Inspector: [Flexbox] Add indicators for layout context in element tooltips
https://bugs.webkit.org/show_bug.cgi?id=236738

Reviewed by Devin Rousso.

* en.lproj/Localizable.strings:
* inspector/InspectorOverlay.cpp:
(WebCore::rendererIsFlexboxItem):
(WebCore::rendererIsGridItem):
(WebCore::InspectorOverlay::drawElementTitle):
- Add new `Flex Item`, `Flex`, `Grid Item`, and `Grid` bubblea to element tooltips to allow provide more
context about layout while selecting nodes on a page.
- Move the role into its own bubble with special color (based on the previous coloring of the `Role` text).

* inspector/InspectorOverlayLabel.cpp:
(WebCore::InspectorOverlayLabel::draw):
* inspector/InspectorOverlayLabel.h:
(WebCore::InspectorOverlayLabel::Content::encode const):
(WebCore::InspectorOverlayLabel::Content::decode):
(WebCore::InspectorOverlayLabel::Content::Decoration::encode const):
(WebCore::InspectorOverlayLabel::Content::Decoration::decode):
- Add the concept of text decoration (currently just bordered text).
- Create an intermediate `ComputedContentRun` to hold the intermediate representation of content with the
computed attributes of each piece of text. This allows us to better scale with the addition of the new text
decorations and other configuration properties instead of having to create even more Vectors of things that need
to be kept in sync with each other.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (290111 => 290112)


--- trunk/Source/WebCore/ChangeLog	2022-02-18 04:52:02 UTC (rev 290111)
+++ trunk/Source/WebCore/ChangeLog	2022-02-18 05:21:37 UTC (rev 290112)
@@ -1,3 +1,32 @@
+2022-02-17  Patrick Angle  <[email protected]>
+
+        Web Inspector: [Flexbox] Add indicators for layout context in element tooltips
+        https://bugs.webkit.org/show_bug.cgi?id=236738
+
+        Reviewed by Devin Rousso.
+
+        * en.lproj/Localizable.strings:
+        * inspector/InspectorOverlay.cpp:
+        (WebCore::rendererIsFlexboxItem):
+        (WebCore::rendererIsGridItem):
+        (WebCore::InspectorOverlay::drawElementTitle):
+        - Add new `Flex Item`, `Flex`, `Grid Item`, and `Grid` bubblea to element tooltips to allow provide more
+        context about layout while selecting nodes on a page.
+        - Move the role into its own bubble with special color (based on the previous coloring of the `Role` text).
+
+        * inspector/InspectorOverlayLabel.cpp:
+        (WebCore::InspectorOverlayLabel::draw):
+        * inspector/InspectorOverlayLabel.h:
+        (WebCore::InspectorOverlayLabel::Content::encode const):
+        (WebCore::InspectorOverlayLabel::Content::decode):
+        (WebCore::InspectorOverlayLabel::Content::Decoration::encode const):
+        (WebCore::InspectorOverlayLabel::Content::Decoration::decode):
+        - Add the concept of text decoration (currently just bordered text).
+        - Create an intermediate `ComputedContentRun` to hold the intermediate representation of content with the
+        computed attributes of each piece of text. This allows us to better scale with the addition of the new text
+        decorations and other configuration properties instead of having to create even more Vectors of things that need
+        to be kept in sync with each other.
+
 2022-02-17  Simon Fraser  <[email protected]>
 
         Crash under ScrollingCoordinatorMac::hasNodeWithAnimatedScrollChanged()

Modified: trunk/Source/WebCore/en.lproj/Localizable.strings (290111 => 290112)


--- trunk/Source/WebCore/en.lproj/Localizable.strings	2022-02-18 04:52:02 UTC (rev 290111)
+++ trunk/Source/WebCore/en.lproj/Localizable.strings	2022-02-18 05:21:37 UTC (rev 290112)
@@ -478,6 +478,12 @@
 /* Default application name for Open With context menu */
 "Finder" = "Finder";
 
+/* Inspector element selection tooltip text for Flexbox containers. */
+"Flex (Inspector Element Selection)" = "Flex";
+
+/* Inspector element selection tooltip text for items inside a Flexbox Container. */
+"Flex Item (Inspector Element Selection)" = "Flex Item";
+
 /* Font context sub-menu item */
 "Font" = "Font";
 
@@ -502,6 +508,12 @@
 /* Google Safe Browsing */
 "Google Safe Browsing" = "Google Safe Browsing";
 
+/* Inspector element selection tooltip text for Grid containers. */
+"Grid (Inspector Element Selection)" = "Grid";
+
+/* Inspector element selection tooltip text for items inside a Grid Container. */
+"Grid Item (Inspector Element Selection)" = "Grid Item";
+
 /* accessibility role description for web area */
 "HTML content" = "HTML content";
 

Modified: trunk/Source/WebCore/inspector/InspectorOverlay.cpp (290111 => 290112)


--- trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2022-02-18 04:52:02 UTC (rev 290111)
+++ trunk/Source/WebCore/inspector/InspectorOverlay.cpp	2022-02-18 05:21:37 UTC (rev 290112)
@@ -56,6 +56,7 @@
 #include "IntPoint.h"
 #include "IntRect.h"
 #include "IntSize.h"
+#include "LocalizedStrings.h"
 #include "Node.h"
 #include "NodeList.h"
 #include "NodeRenderStyle.h"
@@ -1019,6 +1020,22 @@
     }
 }
 
+static bool rendererIsFlexboxItem(RenderObject& renderer)
+{
+    if (auto* parentFlexRenderer = dynamicDowncast<RenderFlexibleBox>(renderer.parent()))
+        return !parentFlexRenderer->orderIterator().shouldSkipChild(renderer);
+
+    return false;
+}
+
+static bool rendererIsGridItem(RenderObject& renderer)
+{
+    if (is<RenderGrid>(renderer.parent()))
+        return !renderer.isOutOfFlowPositioned() && !renderer.isExcludedFromNormalLayout();
+
+    return false;
+}
+
 Path InspectorOverlay::drawElementTitle(GraphicsContext& context, Node& node, const InspectorOverlay::Highlight::Bounds& bounds)
 {
     if (bounds.isEmpty())
@@ -1072,6 +1089,18 @@
         elementHeight = String::number(boundingBox.height());
     }
 
+    Vector<String> layoutContextBubbleStrings;
+    
+    if (rendererIsFlexboxItem(*renderer))
+        layoutContextBubbleStrings.append(WEB_UI_STRING_KEY("Flex Item", "Flex Item (Inspector Element Selection)", "Inspector element selection tooltip text for items inside a Flexbox Container."));
+    else if (rendererIsGridItem(*renderer))
+        layoutContextBubbleStrings.append(WEB_UI_STRING_KEY("Grid Item", "Grid Item (Inspector Element Selection)", "Inspector element selection tooltip text for items inside a Grid Container."));
+
+    if (is<RenderFlexibleBox>(renderer))
+        layoutContextBubbleStrings.append(WEB_UI_STRING_KEY("Flex", "Flex (Inspector Element Selection)", "Inspector element selection tooltip text for Flexbox containers."));
+    else if (is<RenderGrid>(renderer))
+        layoutContextBubbleStrings.append(WEB_UI_STRING_KEY("Grid", "Grid (Inspector Element Selection)", "Inspector element selection tooltip text for Grid containers."));
+
     // Need to enable AX to get the computed role.
     if (!WebCore::AXObjectCache::accessibilityEnabled())
         WebCore::AXObjectCache::enableAccessibility();
@@ -1085,7 +1114,8 @@
     constexpr auto elementTitleTagColor = SRGBA<uint8_t> { 136, 18, 128 }; // Keep this in sync with XMLViewer.css (.tag)
     constexpr auto elementTitleAttributeValueColor = SRGBA<uint8_t> { 26, 26, 166 }; // Keep this in sync with XMLViewer.css (.attribute-value)
     constexpr auto elementTitleAttributeNameColor = SRGBA<uint8_t> { 153, 69, 0 }; // Keep this in sync with XMLViewer.css (.attribute-name)
-    constexpr auto elementTitleRoleColor = SRGBA<uint8_t> { 170, 13, 145 };
+    constexpr auto elementTitleRoleBubbleColor = SRGBA<uint8_t> { 170, 13, 145, 48 };
+    constexpr auto elementTitleLayoutBubbleColor = Color::gray.colorWithAlphaByte(64);
 
     Vector<InspectorOverlayLabel::Content> labelContents = {
         { elementTagName, elementTitleTagColor },
@@ -1098,9 +1128,19 @@
         { "px"_s, Color::darkGray },
     };
 
-    if (!elementRole.isEmpty()) {
-        labelContents.append({ "\nRole "_s, elementTitleRoleColor });
-        labelContents.append({ elementRole, Color::black });
+    if (!elementRole.isEmpty() || !layoutContextBubbleStrings.isEmpty()) {
+        labelContents.append({ "\n"_s, Color::black });
+
+        if (!elementRole.isEmpty())
+            labelContents.append({ makeString("Role: "_s, elementRole), Color::black, { InspectorOverlayLabel::Content::Decoration::Type::Bordered, elementTitleRoleBubbleColor } });
+
+        auto isFirstBubble = elementRole.isEmpty();
+        for (auto& layoutContextBubbleString : layoutContextBubbleStrings) {
+            if (!isFirstBubble)
+                labelContents.append({ "  "_s, Color::black });
+            labelContents.append({ layoutContextBubbleString, Color::black, { InspectorOverlayLabel::Content::Decoration::Type::Bordered, elementTitleLayoutBubbleColor } });
+            isFirstBubble = false;
+        }
     }
 
     FrameView* pageView = m_page.mainFrame().view();

Modified: trunk/Source/WebCore/inspector/InspectorOverlayLabel.cpp (290111 => 290112)


--- trunk/Source/WebCore/inspector/InspectorOverlayLabel.cpp	2022-02-18 04:52:02 UTC (rev 290111)
+++ trunk/Source/WebCore/inspector/InspectorOverlayLabel.cpp	2022-02-18 05:21:37 UTC (rev 290112)
@@ -29,6 +29,7 @@
 #include "config.h"
 #include "InspectorOverlayLabel.h"
 
+#include "FloatRoundedRect.h"
 #include "FloatSize.h"
 #include "FontCascade.h"
 #include "FontCascadeDescription.h"
@@ -39,6 +40,8 @@
 
 static constexpr float labelPadding = 4;
 static constexpr float labelArrowSize = 6;
+static constexpr float labelAdditionalLineSpacing = 1;
+static constexpr float labelContentDecorationBorderedLeadingAndTrailingPadding = 1;
 
 InspectorOverlayLabel::InspectorOverlayLabel(Vector<Content>&& contents, FloatPoint location, Color backgroundColor, Arrow arrow)
     : m_contents(WTFMove(contents))
@@ -193,6 +196,14 @@
     return path;
 }
 
+struct ComputedContentRun {
+    TextRun textRun;
+    Color textColor;
+    InspectorOverlayLabel::Content::Decoration decoration;
+    bool startsNewLine;
+    float computedWidth;
+};
+
 Path InspectorOverlayLabel::draw(GraphicsContext& context, float maximumLineWidth)
 {
     constexpr UChar ellipsis = 0x2026;
@@ -201,10 +212,8 @@
     float lineHeight = font.metricsOfPrimaryFont().floatHeight();
     float lineDescent = font.metricsOfPrimaryFont().floatDescent();
 
-    Vector<TextRun> textRuns;
-    Vector<Color> textColors;
-    Vector<float> textWidths;
-    Vector<size_t> lineStartIndexes;
+    Vector<ComputedContentRun> computedContentRuns;
+
     float longestLineWidth = 0;
     int currentLine = 0;
 
@@ -211,17 +220,17 @@
     float currentLineWidth = 0;
     for (auto content : m_contents) {
         auto lines = content.text.splitAllowingEmptyEntries('\n');
+
+        ASSERT(content.decoration.type == Content::Decoration::Type::None || lines.size() <= 1);
+
         for (size_t i = 0; i < lines.size(); ++i) {
-            if (i) {
-                lineStartIndexes.append(textRuns.size());
+            auto startsNewLine = !!i;
+            if (startsNewLine) {
                 currentLineWidth = 0;
                 ++currentLine;
             }
 
             auto text = lines[i];
-            if (text.isEmpty())
-                continue;
-
             auto textRun = TextRun(text);
             float textWidth = font.width(textRun);
 
@@ -235,9 +244,7 @@
                 }
             }
 
-            textRuns.append(WTFMove(textRun));
-            textColors.append(content.textColor);
-            textWidths.append(textWidth);
+            computedContentRuns.append({ textRun, content.textColor, content.decoration, startsNewLine, textWidth });
 
             currentLineWidth += textWidth;
             if (currentLineWidth > longestLineWidth)
@@ -245,7 +252,7 @@
         }
     }
 
-    float totalTextHeight = lineHeight * (currentLine + 1);
+    float totalTextHeight = (lineHeight * (currentLine + 1)) + (currentLine * labelAdditionalLineSpacing);
 
     FloatPoint textPosition;
     switch (m_arrow.direction) {
@@ -325,16 +332,42 @@
 
     int line = 0;
     float xOffset = 0;
-    for (size_t i = 0; i < textRuns.size(); ++i) {
-        if (lineStartIndexes.contains(i)) {
+    float yOffset = 0;
+    for (auto& computedContentRun : computedContentRuns) {
+        if (computedContentRun.startsNewLine) {
             xOffset = 0;
             ++line;
+            yOffset += lineHeight + labelAdditionalLineSpacing;
         }
 
-        context.setFillColor(textColors[i]);
-        context.drawText(font, textRuns[i], textPosition + FloatPoint(xOffset, line * lineHeight));
+        switch (computedContentRun.decoration.type) {
+        case Content::Decoration::Type::Bordered: {
+            auto backgroundRect = FloatRoundedRect({
+                textPosition.x() + xOffset - labelContentDecorationBorderedLeadingAndTrailingPadding,
+                textPosition.y() + yOffset - lineHeight + lineDescent,
+                computedContentRun.computedWidth + (labelContentDecorationBorderedLeadingAndTrailingPadding * 2),
+                lineHeight,
+            }, FloatRoundedRect::Radii(2));
 
-        xOffset += textWidths[i];
+            Path backgroundPath;
+            backgroundPath.addRoundedRect(backgroundRect);
+
+            context.setFillColor(computedContentRun.decoration.color);
+            context.setStrokeColor(computedContentRun.decoration.color.darkened());
+
+            context.fillPath(backgroundPath);
+            context.strokePath(backgroundPath);
+            break;
+        }
+
+        case Content::Decoration::Type::None:
+            break;
+        }
+
+        context.setFillColor(computedContentRun.textColor);
+        context.drawText(font, computedContentRun.textRun, textPosition + FloatPoint(xOffset, yOffset));
+
+        xOffset += computedContentRun.computedWidth;
     }
 
     return labelPath;
@@ -367,7 +400,7 @@
         }
     }
 
-    float totalTextHeight = lineHeight * (currentLine + 1);
+    float totalTextHeight = (lineHeight * (currentLine + 1)) + (currentLine * labelAdditionalLineSpacing);
 
     switch (direction) {
     case Arrow::Direction::Down:

Modified: trunk/Source/WebCore/inspector/InspectorOverlayLabel.h (290111 => 290112)


--- trunk/Source/WebCore/inspector/InspectorOverlayLabel.h	2022-02-18 04:52:02 UTC (rev 290111)
+++ trunk/Source/WebCore/inspector/InspectorOverlayLabel.h	2022-02-18 05:21:37 UTC (rev 290112)
@@ -79,8 +79,24 @@
     struct Content {
         WTF_MAKE_STRUCT_FAST_ALLOCATED;
 
+        struct Decoration {
+            enum class Type : uint8_t {
+                None,
+                Bordered,
+            };
+
+            Type type;
+            Color color;
+
+#if PLATFORM(IOS_FAMILY)
+            template<class Encoder> void encode(Encoder&) const;
+            template<class Decoder> static std::optional<InspectorOverlayLabel::Content::Decoration> decode(Decoder&);
+#endif
+        };
+
         String text;
         Color textColor;
+        Decoration decoration { Decoration::Type::None, Color::transparentBlack };
 
 #if PLATFORM(IOS_FAMILY)
         template<class Encoder> void encode(Encoder&) const;
@@ -173,6 +189,7 @@
 {
     encoder << text;
     encoder << textColor;
+    encoder << decoration;
 }
 
 template<class Decoder> std::optional<InspectorOverlayLabel::Content> InspectorOverlayLabel::Content::decode(Decoder& decoder)
@@ -187,9 +204,35 @@
     if (!textColor)
         return std::nullopt;
 
-    return { { *text, *textColor } };
+    std::optional<Decoration> decoration;
+    decoder >> decoration;
+    if (!decoration)
+        return std::nullopt;
+
+    return { { *text, *textColor, *decoration } };
 }
 
+template<class Encoder> void InspectorOverlayLabel::Content::Decoration::encode(Encoder& encoder) const
+{
+    encoder << type;
+    encoder << color;
+}
+
+template<class Decoder> std::optional<InspectorOverlayLabel::Content::Decoration> InspectorOverlayLabel::Content::Decoration::decode(Decoder& decoder)
+{
+    std::optional<Type> type;
+    decoder >> type;
+    if (!type)
+        return std::nullopt;
+
+    std::optional<Color> color;
+    decoder >> color;
+    if (!color)
+        return std::nullopt;
+
+    return { { *type, *color } };
+}
+
 #endif
 
 } // namespace WebCore
@@ -217,4 +260,12 @@
     >;
 };
 
+template<> struct EnumTraits<WebCore::InspectorOverlayLabel::Content::Decoration::Type> {
+    using values = EnumValues<
+        WebCore::InspectorOverlayLabel::Content::Decoration::Type,
+        WebCore::InspectorOverlayLabel::Content::Decoration::Type::None,
+        WebCore::InspectorOverlayLabel::Content::Decoration::Type::Bordered
+    >;
+};
+
 }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to