Files
XCEngine/new_editor/app/Features/Project/ProjectPanelLayout.cpp

163 lines
6.3 KiB
C++

#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