Expand XCUI layout lab editor widgets
This commit is contained in:
@@ -11,6 +11,11 @@
|
||||
<Token name="space.stack" type="float" value="12" />
|
||||
<Token name="space.cardInset" type="float" value="12" />
|
||||
<Token name="radius.card" type="float" value="10" />
|
||||
<Token name="size.listItemHeight" type="float" value="60" />
|
||||
<Token name="size.treeItemHeight" type="float" value="30" />
|
||||
<Token name="size.treeIndent" type="float" value="18" />
|
||||
<Token name="size.fieldRowHeight" type="float" value="32" />
|
||||
<Token name="size.propertySectionHeight" type="float" value="156" />
|
||||
<Token name="font.title" type="float" value="16" />
|
||||
<Token name="font.body" type="float" value="13" />
|
||||
</Theme>
|
||||
|
||||
@@ -7,37 +7,89 @@
|
||||
title="XCUI Layout Lab"
|
||||
subtitle="Resource-driven row / column / overlay stress." />
|
||||
<Row id="mainRow" height="stretch" gap="14">
|
||||
<Column id="leftColumn" width="0.28" gap="12">
|
||||
<Card id="leftTop" height="stretch" title="Left Column" subtitle="Stack item 1" />
|
||||
<Card id="leftBottom" height="stretch" title="Left Column" subtitle="Stack item 2" />
|
||||
<Column id="leftRail" width="272" gap="10">
|
||||
<Card
|
||||
id="toolShelf"
|
||||
height="62"
|
||||
tone="accent-alt"
|
||||
title="Tool Shelf"
|
||||
subtitle="Scene, asset, and play-mode actions." />
|
||||
<ScrollView id="assetList" height="stretch" padding="10" gap="8" scrollY="132">
|
||||
<Card
|
||||
id="assetListHeader"
|
||||
height="54"
|
||||
tone="accent-alt"
|
||||
title="Project Browser"
|
||||
subtitle="Pinned filters and import shortcuts." />
|
||||
<TreeView id="projectTree" height="156" padding="8" gap="6">
|
||||
<TreeItem id="treeAssetsRoot" title="Assets" subtitle="Workspace root" />
|
||||
<TreeItem id="treeScenes" title="Scenes" subtitle="4 authored scenes" indent="1" />
|
||||
<TreeItem id="treeMaterials" title="Materials" subtitle="Shared lookdev library" indent="1" />
|
||||
<TreeItem id="treeCharacters" title="Characters" subtitle="Prefab variants" indent="1" />
|
||||
<TreeItem id="treeUi" title="UI" subtitle="Runtime atlas + themes" indent="1" />
|
||||
</TreeView>
|
||||
<ListView id="recentAssetList" height="360" padding="8" gap="6">
|
||||
<ListItem id="assetMaterials" title="Materials_Master" subtitle="14 assets selected" />
|
||||
<ListItem id="assetTerrain" title="Terrain_Cliffs_04" subtitle="Texture2D -4096 x 4096" />
|
||||
<ListItem id="assetLighting" title="Lighting_GlobalRig" subtitle="Prefab -Directional setup" />
|
||||
<ListItem id="assetCharacter" title="Hero_Character_Controller" subtitle="Prefab -Animation graph bound" />
|
||||
<ListItem id="assetUiAtlas" title="UI_RuntimeAtlas" subtitle="SpriteAtlas -83 packed sprites" />
|
||||
</ListView>
|
||||
</ScrollView>
|
||||
</Column>
|
||||
<Overlay id="centerOverlay" width="0.42">
|
||||
<Column id="centerColumn" width="stretch" gap="10">
|
||||
<Card
|
||||
id="overlayBase"
|
||||
title="Center Overlay"
|
||||
subtitle="Base layer filling the entire region." />
|
||||
id="viewportToolbar"
|
||||
height="62"
|
||||
title="Viewport Toolbar"
|
||||
subtitle="Gizmos, snap presets, camera bookmarks." />
|
||||
<Overlay id="viewportOverlay" height="stretch">
|
||||
<Card
|
||||
id="viewportBase"
|
||||
title="Scene Viewport"
|
||||
subtitle="Primary preview surface with composition overlays." />
|
||||
<Card
|
||||
id="viewportBadge"
|
||||
x="18"
|
||||
y="18"
|
||||
width="224"
|
||||
height="68"
|
||||
tone="accent-alt"
|
||||
title="Selection Overlay"
|
||||
subtitle="Bounds, pivots, nav markers." />
|
||||
<Card
|
||||
id="viewportInspectorBubble"
|
||||
x="0.58"
|
||||
y="0.54"
|
||||
width="0.32"
|
||||
height="88"
|
||||
tone="accent-alt"
|
||||
title="Context Bubble"
|
||||
subtitle="Inline quick edit affordance." />
|
||||
</Overlay>
|
||||
</Column>
|
||||
<Column id="inspectorColumn" width="320" gap="10">
|
||||
<Card
|
||||
id="overlayNorth"
|
||||
x="18"
|
||||
y="18"
|
||||
width="0.42"
|
||||
height="72"
|
||||
tone="accent-alt"
|
||||
title="Overlay A"
|
||||
subtitle="Floating note" />
|
||||
<Card
|
||||
id="overlayCenter"
|
||||
x="0.28"
|
||||
y="0.45"
|
||||
width="0.44"
|
||||
height="86"
|
||||
tone="accent-alt"
|
||||
title="Overlay B"
|
||||
subtitle="Centered overlay layer" />
|
||||
</Overlay>
|
||||
<Column id="rightColumn" width="stretch" gap="12">
|
||||
<Card id="rightTop" height="stretch" title="Right Column" subtitle="Another stacked column" />
|
||||
<Card id="rightBottom" height="stretch" title="Right Column" subtitle="Pairs with the overlay stage" />
|
||||
id="inspectorSummary"
|
||||
height="88"
|
||||
title="Inspector Summary"
|
||||
subtitle="Transform, renderer, and prefab overrides." />
|
||||
<ScrollView id="inspectorSections" height="stretch" padding="10" gap="8" scrollY="52">
|
||||
<PropertySection id="inspectorTransform" height="156" title="Transform" subtitle="Position / rotation / scale">
|
||||
<FieldRow id="fieldPosition" title="Position" subtitle="0.0, 1.5, 0.0" />
|
||||
<FieldRow id="fieldRotation" title="Rotation" subtitle="0.0, 42.0, 0.0" />
|
||||
<FieldRow id="fieldScale" title="Scale" subtitle="1.0, 1.0, 1.0" />
|
||||
</PropertySection>
|
||||
<PropertySection id="inspectorMesh" height="156" title="Mesh Renderer" subtitle="Materials, shadow flags, probes">
|
||||
<FieldRow id="fieldMaterial" title="Material" subtitle="M_StylizedTerrain" />
|
||||
<FieldRow id="fieldShadows" title="Cast Shadows" subtitle="On" />
|
||||
<FieldRow id="fieldProbe" title="Light Probe" subtitle="Blend Probes" />
|
||||
</PropertySection>
|
||||
<PropertySection id="inspectorMetadata" height="132" title="Metadata" subtitle="Tags, labels, import provenance">
|
||||
<FieldRow id="fieldTags" title="Tags" subtitle="Gameplay, Hero, Traversal" />
|
||||
<FieldRow id="fieldImportedBy" title="Imported By" subtitle="Asset pipeline v2" />
|
||||
</PropertySection>
|
||||
</ScrollView>
|
||||
</Column>
|
||||
</Row>
|
||||
<Overlay id="footerOverlay" height="146">
|
||||
|
||||
@@ -60,6 +60,7 @@ struct LayoutNode {
|
||||
std::string gapAttr = {};
|
||||
std::string paddingAttr = {};
|
||||
std::string scrollYAttr = {};
|
||||
std::string indentAttr = {};
|
||||
std::size_t parentIndex = kInvalidIndex;
|
||||
std::vector<std::size_t> children = {};
|
||||
UIRect rect = {};
|
||||
@@ -287,6 +288,30 @@ bool IsScrollViewTag(const std::string& tagName) {
|
||||
return tagName == "ScrollView";
|
||||
}
|
||||
|
||||
bool IsTreeViewTag(const std::string& tagName) {
|
||||
return tagName == "TreeView";
|
||||
}
|
||||
|
||||
bool IsTreeItemTag(const std::string& tagName) {
|
||||
return tagName == "TreeItem";
|
||||
}
|
||||
|
||||
bool IsListViewTag(const std::string& tagName) {
|
||||
return tagName == "ListView";
|
||||
}
|
||||
|
||||
bool IsListItemTag(const std::string& tagName) {
|
||||
return tagName == "ListItem";
|
||||
}
|
||||
|
||||
bool IsPropertySectionTag(const std::string& tagName) {
|
||||
return tagName == "PropertySection";
|
||||
}
|
||||
|
||||
bool IsFieldRowTag(const std::string& tagName) {
|
||||
return tagName == "FieldRow";
|
||||
}
|
||||
|
||||
float ResolveScalar(
|
||||
const std::string& text,
|
||||
float referenceValue,
|
||||
@@ -417,6 +442,7 @@ void BuildNodesRecursive(
|
||||
layoutNode.gapAttr = GetAttributeValue(node, "gap");
|
||||
layoutNode.paddingAttr = GetAttributeValue(node, "padding");
|
||||
layoutNode.scrollYAttr = GetAttributeValue(node, "scrollY");
|
||||
layoutNode.indentAttr = GetAttributeValue(node, "indent");
|
||||
layoutNode.parentIndex = parentIndex;
|
||||
layoutNode.depth = depth;
|
||||
|
||||
@@ -458,6 +484,12 @@ float ResolvePadding(const LayoutNode& node, const Style::UITheme& theme) {
|
||||
ResolveFloatToken(theme, "space.outer", 18.0f));
|
||||
}
|
||||
|
||||
if (IsTreeViewTag(node.tagName) ||
|
||||
IsListViewTag(node.tagName) ||
|
||||
IsPropertySectionTag(node.tagName)) {
|
||||
return ResolveFloatToken(theme, "space.cardInset", 12.0f);
|
||||
}
|
||||
|
||||
return node.tagName == "View"
|
||||
? ResolveFloatToken(theme, "space.outer", 18.0f)
|
||||
: 0.0f;
|
||||
@@ -480,10 +512,44 @@ float ResolveListItemHeight(const Style::UITheme& theme) {
|
||||
return ResolveFloatToken(theme, "size.listItemHeight", 60.0f);
|
||||
}
|
||||
|
||||
float ResolveTreeIndent(const LayoutNode& node, const Style::UITheme& theme) {
|
||||
float indentLevel = 0.0f;
|
||||
if (!node.indentAttr.empty()) {
|
||||
TryParseFloat(node.indentAttr, indentLevel);
|
||||
}
|
||||
|
||||
return (std::max)(0.0f, indentLevel) *
|
||||
ResolveFloatToken(theme, "size.treeIndent", 18.0f);
|
||||
}
|
||||
|
||||
float ResolveFieldRowHeight(const Style::UITheme& theme) {
|
||||
return ResolveFloatToken(theme, "size.fieldRowHeight", 32.0f);
|
||||
}
|
||||
|
||||
UIRect GetContentRect(const LayoutNode& node, const Style::UITheme& theme) {
|
||||
return InsetRect(node.rect, ResolvePadding(node, theme));
|
||||
}
|
||||
|
||||
float ResolveDefaultHeight(const LayoutNode& node, const Style::UITheme& theme) {
|
||||
if (IsTreeItemTag(node.tagName)) {
|
||||
return ResolveFloatToken(theme, "size.treeItemHeight", 28.0f);
|
||||
}
|
||||
|
||||
if (IsListItemTag(node.tagName)) {
|
||||
return ResolveListItemHeight(theme);
|
||||
}
|
||||
|
||||
if (IsFieldRowTag(node.tagName)) {
|
||||
return ResolveFieldRowHeight(theme);
|
||||
}
|
||||
|
||||
if (IsPropertySectionTag(node.tagName)) {
|
||||
return ResolveFloatToken(theme, "size.propertySectionHeight", 148.0f);
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
void LayoutNodeTree(RuntimeBuildContext& state, std::size_t nodeIndex);
|
||||
|
||||
void LayoutColumnChildren(RuntimeBuildContext& state, std::size_t nodeIndex) {
|
||||
@@ -505,7 +571,10 @@ void LayoutColumnChildren(RuntimeBuildContext& state, std::size_t nodeIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resolvedHeights[childOffset] = ResolveScalar(child.heightAttr, contentRect.height, 0.0f);
|
||||
resolvedHeights[childOffset] = ResolveScalar(
|
||||
child.heightAttr,
|
||||
contentRect.height,
|
||||
ResolveDefaultHeight(child, state.theme));
|
||||
fixedHeight += resolvedHeights[childOffset];
|
||||
}
|
||||
|
||||
@@ -608,10 +677,15 @@ void LayoutScrollViewChildren(RuntimeBuildContext& state, std::size_t nodeIndex)
|
||||
float cursorY = contentRect.y - scrollOffset;
|
||||
for (std::size_t childIndex : node.children) {
|
||||
LayoutNode& child = state.nodes[childIndex];
|
||||
const float childHeight =
|
||||
!IsStretch(child.heightAttr)
|
||||
? ResolveScalar(child.heightAttr, contentRect.height, defaultItemHeight)
|
||||
: defaultItemHeight;
|
||||
const float defaultHeight = ResolveDefaultHeight(child, state.theme);
|
||||
const float childHeight = child.heightAttr.empty()
|
||||
? (defaultHeight > 0.0f ? defaultHeight : defaultItemHeight)
|
||||
: (!IsStretch(child.heightAttr)
|
||||
? ResolveScalar(
|
||||
child.heightAttr,
|
||||
contentRect.height,
|
||||
defaultHeight > 0.0f ? defaultHeight : defaultItemHeight)
|
||||
: defaultItemHeight);
|
||||
const float childWidth =
|
||||
!IsStretch(child.widthAttr)
|
||||
? (std::min)(
|
||||
@@ -628,7 +702,11 @@ void LayoutNodeTree(RuntimeBuildContext& state, std::size_t nodeIndex) {
|
||||
const LayoutNode& node = state.nodes[nodeIndex];
|
||||
state.rectsById[node.id] = node.rect;
|
||||
|
||||
if (node.tagName == "View" || node.tagName == "Column") {
|
||||
if (node.tagName == "View" ||
|
||||
node.tagName == "Column" ||
|
||||
IsTreeViewTag(node.tagName) ||
|
||||
IsListViewTag(node.tagName) ||
|
||||
IsPropertySectionTag(node.tagName)) {
|
||||
LayoutColumnChildren(state, nodeIndex);
|
||||
} else if (node.tagName == "Row") {
|
||||
LayoutRowChildren(state, nodeIndex);
|
||||
@@ -652,7 +730,9 @@ void DrawNode(
|
||||
"color.panel",
|
||||
Color(0.07f, 0.10f, 0.14f, 1.0f));
|
||||
drawList.AddFilledRect(node.rect, ToUIColor(panelColor), 0.0f);
|
||||
} else if (IsScrollViewTag(node.tagName)) {
|
||||
} else if (IsScrollViewTag(node.tagName) ||
|
||||
IsTreeViewTag(node.tagName) ||
|
||||
IsListViewTag(node.tagName)) {
|
||||
const Color surfaceColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.scroll.surface",
|
||||
@@ -664,6 +744,44 @@ void DrawNode(
|
||||
const float rounding = ResolveFloatToken(state.theme, "radius.card", 10.0f);
|
||||
drawList.AddFilledRect(node.rect, ToUIColor(surfaceColor), rounding);
|
||||
drawList.AddRectOutline(node.rect, ToUIColor(borderColor), 1.0f, rounding);
|
||||
} else if (IsPropertySectionTag(node.tagName)) {
|
||||
const Color sectionColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.card",
|
||||
Color(0.12f, 0.17f, 0.23f, 1.0f));
|
||||
const Color borderColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.border",
|
||||
Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const Color textColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text",
|
||||
Color(0.95f, 0.97f, 1.0f, 1.0f));
|
||||
const Color mutedColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text.muted",
|
||||
Color(0.72f, 0.79f, 0.86f, 1.0f));
|
||||
const float rounding = ResolveFloatToken(state.theme, "radius.card", 10.0f);
|
||||
const float inset = ResolveFloatToken(state.theme, "space.cardInset", 12.0f);
|
||||
const float titleFont = ResolveFloatToken(state.theme, "font.title", 16.0f);
|
||||
const float bodyFont = ResolveFloatToken(state.theme, "font.body", 13.0f);
|
||||
|
||||
drawList.AddFilledRect(node.rect, ToUIColor(sectionColor), rounding);
|
||||
drawList.AddRectOutline(node.rect, ToUIColor(borderColor), 1.0f, rounding);
|
||||
if (!node.title.empty()) {
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + inset, node.rect.y + inset),
|
||||
node.title,
|
||||
ToUIColor(textColor),
|
||||
titleFont);
|
||||
}
|
||||
if (!node.subtitle.empty()) {
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + inset, node.rect.y + inset + titleFont + 6.0f),
|
||||
node.subtitle,
|
||||
ToUIColor(mutedColor),
|
||||
bodyFont);
|
||||
}
|
||||
} else if (node.tagName == "Card") {
|
||||
const Color cardColor = ResolveColorToken(
|
||||
state.theme,
|
||||
@@ -713,9 +831,82 @@ void DrawNode(
|
||||
2.0f,
|
||||
rounding);
|
||||
}
|
||||
} else if (IsTreeItemTag(node.tagName) || IsListItemTag(node.tagName)) {
|
||||
const bool hovered = node.id == hoveredId;
|
||||
const Color rowColor = hovered
|
||||
? ResolveColorToken(state.theme, "color.card.alt", Color(0.20f, 0.27f, 0.34f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.card", Color(0.12f, 0.17f, 0.23f, 1.0f));
|
||||
const Color borderColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.border",
|
||||
Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const Color textColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text",
|
||||
Color(0.95f, 0.97f, 1.0f, 1.0f));
|
||||
const Color mutedColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text.muted",
|
||||
Color(0.72f, 0.79f, 0.86f, 1.0f));
|
||||
const float inset = ResolveFloatToken(state.theme, "space.cardInset", 12.0f);
|
||||
const float titleFont = ResolveFloatToken(state.theme, "font.body", 13.0f);
|
||||
const float bodyFont = ResolveFloatToken(state.theme, "font.body", 13.0f);
|
||||
const float rounding = ResolveFloatToken(state.theme, "radius.card", 10.0f);
|
||||
const float indent = IsTreeItemTag(node.tagName) ? ResolveTreeIndent(node, state.theme) : 0.0f;
|
||||
|
||||
drawList.AddFilledRect(node.rect, ToUIColor(rowColor), rounding);
|
||||
drawList.AddRectOutline(node.rect, ToUIColor(borderColor), 1.0f, rounding);
|
||||
if (IsTreeItemTag(node.tagName)) {
|
||||
drawList.AddFilledRect(
|
||||
UIRect(node.rect.x + inset + indent - 8.0f, node.rect.y + 11.0f, 4.0f, 4.0f),
|
||||
ToUIColor(textColor),
|
||||
2.0f);
|
||||
}
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + inset + indent, node.rect.y + 8.0f),
|
||||
node.title,
|
||||
ToUIColor(textColor),
|
||||
titleFont);
|
||||
if (!node.subtitle.empty()) {
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + inset + indent, node.rect.y + 8.0f + titleFont + 4.0f),
|
||||
node.subtitle,
|
||||
ToUIColor(mutedColor),
|
||||
bodyFont);
|
||||
}
|
||||
} else if (IsFieldRowTag(node.tagName)) {
|
||||
const bool hovered = node.id == hoveredId;
|
||||
const Color textColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text",
|
||||
Color(0.95f, 0.97f, 1.0f, 1.0f));
|
||||
const Color mutedColor = ResolveColorToken(
|
||||
state.theme,
|
||||
"color.text.muted",
|
||||
Color(0.72f, 0.79f, 0.86f, 1.0f));
|
||||
const Color lineColor = hovered
|
||||
? ResolveColorToken(state.theme, "color.accent", Color(0.30f, 0.46f, 0.58f, 1.0f))
|
||||
: ResolveColorToken(state.theme, "color.border", Color(0.24f, 0.34f, 0.43f, 1.0f));
|
||||
const float inset = ResolveFloatToken(state.theme, "space.cardInset", 12.0f);
|
||||
const float fontSize = ResolveFloatToken(state.theme, "font.body", 13.0f);
|
||||
|
||||
drawList.AddRectOutline(node.rect, ToUIColor(lineColor), 1.0f, 6.0f);
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + inset, node.rect.y + 8.0f),
|
||||
node.title,
|
||||
ToUIColor(textColor),
|
||||
fontSize);
|
||||
drawList.AddText(
|
||||
UIPoint(node.rect.x + node.rect.width * 0.54f, node.rect.y + 8.0f),
|
||||
node.subtitle,
|
||||
ToUIColor(mutedColor),
|
||||
fontSize);
|
||||
}
|
||||
|
||||
const bool clipsChildren = IsScrollViewTag(node.tagName);
|
||||
const bool clipsChildren =
|
||||
IsScrollViewTag(node.tagName) ||
|
||||
IsTreeViewTag(node.tagName) ||
|
||||
IsListViewTag(node.tagName);
|
||||
if (clipsChildren) {
|
||||
drawList.PushClipRect(GetContentRect(node, state.theme));
|
||||
}
|
||||
@@ -734,7 +925,9 @@ bool IsPointInsideNodeClipping(
|
||||
std::size_t currentIndex = nodeIndex;
|
||||
while (currentIndex != kInvalidIndex) {
|
||||
const LayoutNode& currentNode = state.nodes[currentIndex];
|
||||
if (IsScrollViewTag(currentNode.tagName) &&
|
||||
if ((IsScrollViewTag(currentNode.tagName) ||
|
||||
IsTreeViewTag(currentNode.tagName) ||
|
||||
IsListViewTag(currentNode.tagName)) &&
|
||||
!ContainsPoint(GetContentRect(currentNode, state.theme), point)) {
|
||||
return false;
|
||||
}
|
||||
@@ -751,7 +944,12 @@ std::size_t HitTest(
|
||||
int bestDepth = -1;
|
||||
for (std::size_t index = 0; index < state.nodes.size(); ++index) {
|
||||
const LayoutNode& node = state.nodes[index];
|
||||
if (node.tagName != "Card" ||
|
||||
const bool hoverable =
|
||||
node.tagName == "Card" ||
|
||||
IsTreeItemTag(node.tagName) ||
|
||||
IsListItemTag(node.tagName) ||
|
||||
IsFieldRowTag(node.tagName);
|
||||
if (!hoverable ||
|
||||
!ContainsPoint(node.rect, point) ||
|
||||
!IsPointInsideNodeClipping(state, index, point)) {
|
||||
continue;
|
||||
@@ -890,6 +1088,18 @@ const XCUILayoutLabFrameResult& XCUILayoutLabRuntime::Update(const XCUILayoutLab
|
||||
++state.frameResult.stats.overlayCount;
|
||||
} else if (IsScrollViewTag(node.tagName)) {
|
||||
++state.frameResult.stats.scrollViewCount;
|
||||
} else if (IsTreeViewTag(node.tagName)) {
|
||||
++state.frameResult.stats.treeViewCount;
|
||||
} else if (IsTreeItemTag(node.tagName)) {
|
||||
++state.frameResult.stats.treeItemCount;
|
||||
} else if (IsListViewTag(node.tagName)) {
|
||||
++state.frameResult.stats.listViewCount;
|
||||
} else if (IsListItemTag(node.tagName)) {
|
||||
++state.frameResult.stats.listItemCount;
|
||||
} else if (IsPropertySectionTag(node.tagName)) {
|
||||
++state.frameResult.stats.propertySectionCount;
|
||||
} else if (IsFieldRowTag(node.tagName)) {
|
||||
++state.frameResult.stats.fieldRowCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,12 @@ struct XCUILayoutLabFrameStats {
|
||||
std::size_t columnCount = 0;
|
||||
std::size_t overlayCount = 0;
|
||||
std::size_t scrollViewCount = 0;
|
||||
std::size_t treeViewCount = 0;
|
||||
std::size_t treeItemCount = 0;
|
||||
std::size_t listViewCount = 0;
|
||||
std::size_t listItemCount = 0;
|
||||
std::size_t propertySectionCount = 0;
|
||||
std::size_t fieldRowCount = 0;
|
||||
std::string hoveredElementId = {};
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user