163 lines
6.3 KiB
C++
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
|