refactor(new_editor/app): reorganize host structure and add smoke test
This commit is contained in:
162
new_editor/app/Features/Project/ProjectPanelLayout.cpp
Normal file
162
new_editor/app/Features/Project/ProjectPanelLayout.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
#include "ProjectPanelSupport.h"
|
||||
|
||||
namespace XCEngine::UI::Editor::App {
|
||||
|
||||
using namespace ProjectPanelSupport;
|
||||
|
||||
ProjectPanel::Layout ProjectPanel::BuildLayout(const UIRect& bounds) const {
|
||||
Layout layout = {};
|
||||
const auto& assetEntries = m_browserModel.GetAssetEntries();
|
||||
const std::vector<ProjectBrowserModel::BreadcrumbSegment> breadcrumbSegments =
|
||||
m_browserModel.BuildBreadcrumbSegments();
|
||||
const float dividerThickness = ResolveUIEditorDockHostMetrics().splitterMetrics.thickness;
|
||||
layout.bounds = UIRect(
|
||||
bounds.x,
|
||||
bounds.y,
|
||||
ClampNonNegative(bounds.width),
|
||||
ClampNonNegative(bounds.height));
|
||||
|
||||
const float leftWidth = ClampNavigationWidth(m_navigationWidth, layout.bounds.width);
|
||||
layout.leftPaneRect = UIRect(
|
||||
layout.bounds.x,
|
||||
layout.bounds.y,
|
||||
leftWidth,
|
||||
layout.bounds.height);
|
||||
layout.dividerRect = UIRect(
|
||||
layout.leftPaneRect.x + layout.leftPaneRect.width,
|
||||
layout.bounds.y,
|
||||
dividerThickness,
|
||||
layout.bounds.height);
|
||||
layout.rightPaneRect = UIRect(
|
||||
layout.dividerRect.x + layout.dividerRect.width,
|
||||
layout.bounds.y,
|
||||
ClampNonNegative(layout.bounds.width - layout.leftPaneRect.width - layout.dividerRect.width),
|
||||
layout.bounds.height);
|
||||
|
||||
layout.treeRect = UIRect(
|
||||
layout.leftPaneRect.x,
|
||||
layout.leftPaneRect.y + kTreeTopPadding,
|
||||
layout.leftPaneRect.width,
|
||||
ClampNonNegative(layout.leftPaneRect.height - kTreeTopPadding));
|
||||
|
||||
layout.browserHeaderRect = UIRect(
|
||||
layout.rightPaneRect.x,
|
||||
layout.rightPaneRect.y,
|
||||
layout.rightPaneRect.width,
|
||||
(std::min)(kBrowserHeaderHeight, layout.rightPaneRect.height));
|
||||
layout.browserBodyRect = UIRect(
|
||||
layout.rightPaneRect.x,
|
||||
layout.browserHeaderRect.y + layout.browserHeaderRect.height,
|
||||
layout.rightPaneRect.width,
|
||||
ClampNonNegative(layout.rightPaneRect.height - layout.browserHeaderRect.height));
|
||||
layout.gridRect = UIRect(
|
||||
layout.browserBodyRect.x + kGridInsetX,
|
||||
layout.browserBodyRect.y + kGridInsetY,
|
||||
ClampNonNegative(layout.browserBodyRect.width - kGridInsetX * 2.0f),
|
||||
ClampNonNegative(layout.browserBodyRect.height - kGridInsetY * 2.0f));
|
||||
|
||||
const float breadcrumbRowHeight = kHeaderFontSize + kBreadcrumbItemPaddingY * 2.0f;
|
||||
const float breadcrumbY =
|
||||
layout.browserHeaderRect.y + std::floor((layout.browserHeaderRect.height - breadcrumbRowHeight) * 0.5f);
|
||||
const float headerRight =
|
||||
layout.browserHeaderRect.x + layout.browserHeaderRect.width - kHeaderHorizontalPadding;
|
||||
float nextItemX = layout.browserHeaderRect.x + kHeaderHorizontalPadding;
|
||||
for (std::size_t index = 0u; index < breadcrumbSegments.size(); ++index) {
|
||||
if (index > 0u) {
|
||||
const float separatorWidth = MeasureTextWidth(m_textMeasurer, ">", kHeaderFontSize);
|
||||
if (nextItemX < headerRight && separatorWidth > 0.0f) {
|
||||
layout.breadcrumbItems.push_back({
|
||||
">",
|
||||
{},
|
||||
UIRect(
|
||||
nextItemX,
|
||||
breadcrumbY,
|
||||
ClampNonNegative((std::min)(separatorWidth, headerRight - nextItemX)),
|
||||
breadcrumbRowHeight),
|
||||
true,
|
||||
false,
|
||||
false
|
||||
});
|
||||
}
|
||||
nextItemX += separatorWidth + kBreadcrumbSpacing;
|
||||
}
|
||||
|
||||
const ProjectBrowserModel::BreadcrumbSegment& segment = breadcrumbSegments[index];
|
||||
const float labelWidth = MeasureTextWidth(m_textMeasurer, segment.label, kHeaderFontSize);
|
||||
const float itemWidth = labelWidth + kBreadcrumbItemPaddingX * 2.0f;
|
||||
const float availableWidth = headerRight - nextItemX;
|
||||
if (availableWidth <= 0.0f) {
|
||||
break;
|
||||
}
|
||||
|
||||
layout.breadcrumbItems.push_back({
|
||||
segment.label,
|
||||
segment.targetFolderId,
|
||||
UIRect(
|
||||
nextItemX,
|
||||
breadcrumbY,
|
||||
ClampNonNegative((std::min)(itemWidth, availableWidth)),
|
||||
breadcrumbRowHeight),
|
||||
false,
|
||||
!segment.current,
|
||||
segment.current
|
||||
});
|
||||
nextItemX += itemWidth + kBreadcrumbSpacing;
|
||||
}
|
||||
|
||||
const float effectiveTileWidth = kGridTileWidth + kGridTileGapX;
|
||||
int columnCount = effectiveTileWidth > 0.0f
|
||||
? static_cast<int>((layout.gridRect.width + kGridTileGapX) / effectiveTileWidth)
|
||||
: 1;
|
||||
if (columnCount < 1) {
|
||||
columnCount = 1;
|
||||
}
|
||||
|
||||
layout.assetTiles.reserve(assetEntries.size());
|
||||
for (std::size_t index = 0; index < assetEntries.size(); ++index) {
|
||||
const int column = static_cast<int>(index % static_cast<std::size_t>(columnCount));
|
||||
const int row = static_cast<int>(index / static_cast<std::size_t>(columnCount));
|
||||
const float tileX = layout.gridRect.x + static_cast<float>(column) * (kGridTileWidth + kGridTileGapX);
|
||||
const float tileY = layout.gridRect.y + static_cast<float>(row) * (kGridTileHeight + kGridTileGapY);
|
||||
|
||||
AssetTileLayout tile = {};
|
||||
tile.itemIndex = index;
|
||||
tile.tileRect = UIRect(tileX, tileY, kGridTileWidth, kGridTileHeight);
|
||||
tile.previewRect = UIRect(
|
||||
tile.tileRect.x + (tile.tileRect.width - kGridPreviewWidth) * 0.5f,
|
||||
tile.tileRect.y + 6.0f,
|
||||
kGridPreviewWidth,
|
||||
kGridPreviewHeight);
|
||||
tile.labelRect = UIRect(
|
||||
tile.tileRect.x + 4.0f,
|
||||
tile.previewRect.y + tile.previewRect.height + 8.0f,
|
||||
tile.tileRect.width - 8.0f,
|
||||
18.0f);
|
||||
layout.assetTiles.push_back(tile);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
std::size_t ProjectPanel::HitTestBreadcrumbItem(const UIPoint& point) const {
|
||||
for (std::size_t index = 0u; index < m_layout.breadcrumbItems.size(); ++index) {
|
||||
const BreadcrumbItemLayout& item = m_layout.breadcrumbItems[index];
|
||||
if (!item.separator && ContainsPoint(item.rect, point)) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return kInvalidLayoutIndex;
|
||||
}
|
||||
|
||||
std::size_t ProjectPanel::HitTestAssetTile(const UIPoint& point) const {
|
||||
for (const AssetTileLayout& tile : m_layout.assetTiles) {
|
||||
if (ContainsPoint(tile.tileRect, point)) {
|
||||
return tile.itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return kInvalidLayoutIndex;
|
||||
}
|
||||
|
||||
} // namespace XCEngine::UI::Editor::App
|
||||
Reference in New Issue
Block a user