2026-04-15 08:24:06 +08:00
|
|
|
#include "ProjectPanelSupport.h"
|
2026-04-11 20:20:30 +08:00
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
|
|
|
namespace XCEngine::UI::Editor::App {
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
using namespace ProjectPanelSupport;
|
2026-04-11 20:20:30 +08:00
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::Initialize(const std::filesystem::path& repoRoot) {
|
2026-04-12 11:12:27 +08:00
|
|
|
m_browserModel.Initialize(repoRoot);
|
2026-04-11 20:20:30 +08:00
|
|
|
SyncCurrentFolderSelection();
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::SetBuiltInIcons(const BuiltInIcons* icons) {
|
2026-04-11 22:14:02 +08:00
|
|
|
m_icons = icons;
|
2026-04-12 11:12:27 +08:00
|
|
|
m_browserModel.SetFolderIcon(ResolveFolderIcon(m_icons));
|
|
|
|
|
SyncCurrentFolderSelection();
|
2026-04-11 22:14:02 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::SetTextMeasurer(const UIEditorTextMeasurer* textMeasurer) {
|
2026-04-11 20:20:30 +08:00
|
|
|
m_textMeasurer = textMeasurer;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::ResetInteractionState() {
|
2026-04-14 16:19:23 +08:00
|
|
|
m_treeInteractionState = {};
|
|
|
|
|
m_treeFrame = {};
|
|
|
|
|
m_frameEvents.clear();
|
|
|
|
|
m_layout = {};
|
|
|
|
|
m_hoveredAssetItemId.clear();
|
|
|
|
|
m_lastPrimaryClickedAssetId.clear();
|
|
|
|
|
m_hoveredBreadcrumbIndex = kInvalidLayoutIndex;
|
|
|
|
|
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
|
|
|
|
m_visible = false;
|
|
|
|
|
m_splitterHovered = false;
|
|
|
|
|
m_splitterDragging = false;
|
|
|
|
|
m_requestPointerCapture = false;
|
|
|
|
|
m_requestPointerRelease = false;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
ProjectPanel::CursorKind ProjectPanel::GetCursorKind() const {
|
2026-04-11 20:20:30 +08:00
|
|
|
return (m_splitterHovered || m_splitterDragging) ? CursorKind::ResizeEW : CursorKind::Arrow;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
bool ProjectPanel::WantsHostPointerCapture() const {
|
2026-04-11 20:20:30 +08:00
|
|
|
return m_requestPointerCapture;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
bool ProjectPanel::WantsHostPointerRelease() const {
|
2026-04-11 20:20:30 +08:00
|
|
|
return m_requestPointerRelease;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
bool ProjectPanel::HasActivePointerCapture() const {
|
2026-04-11 20:20:30 +08:00
|
|
|
return m_splitterDragging;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
const std::vector<ProjectPanel::Event>& ProjectPanel::GetFrameEvents() const {
|
2026-04-11 22:31:14 +08:00
|
|
|
return m_frameEvents;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
const ProjectPanel::FolderEntry* ProjectPanel::FindFolderEntry(std::string_view itemId) const {
|
2026-04-12 11:12:27 +08:00
|
|
|
return m_browserModel.FindFolderEntry(itemId);
|
2026-04-11 20:20:30 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
const ProjectPanel::AssetEntry* ProjectPanel::FindAssetEntry(std::string_view itemId) const {
|
2026-04-12 11:12:27 +08:00
|
|
|
return m_browserModel.FindAssetEntry(itemId);
|
2026-04-11 22:31:14 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
const UIEditorPanelContentHostPanelState* ProjectPanel::FindMountedProjectPanel(
|
2026-04-11 20:20:30 +08:00
|
|
|
const UIEditorPanelContentHostFrame& contentHostFrame) const {
|
|
|
|
|
for (const UIEditorPanelContentHostPanelState& panelState : contentHostFrame.panelStates) {
|
|
|
|
|
if (panelState.panelId == kProjectPanelId && panelState.mounted) {
|
|
|
|
|
return &panelState;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::SyncCurrentFolderSelection() {
|
2026-04-12 11:12:27 +08:00
|
|
|
const std::string& currentFolderId = m_browserModel.GetCurrentFolderId();
|
|
|
|
|
if (currentFolderId.empty()) {
|
|
|
|
|
m_folderSelection.ClearSelection();
|
2026-04-11 20:20:30 +08:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 11:12:27 +08:00
|
|
|
const std::vector<std::string> ancestorFolderIds =
|
|
|
|
|
m_browserModel.CollectCurrentFolderAncestorIds();
|
|
|
|
|
for (const std::string& ancestorFolderId : ancestorFolderIds) {
|
|
|
|
|
m_folderExpansion.Expand(ancestorFolderId);
|
2026-04-11 20:20:30 +08:00
|
|
|
}
|
2026-04-12 11:12:27 +08:00
|
|
|
m_folderSelection.SetSelection(currentFolderId);
|
2026-04-11 20:20:30 +08:00
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
bool ProjectPanel::NavigateToFolder(std::string_view itemId, EventSource source) {
|
2026-04-12 11:12:27 +08:00
|
|
|
if (!m_browserModel.NavigateToFolder(itemId)) {
|
2026-04-11 22:31:14 +08:00
|
|
|
return false;
|
2026-04-11 20:20:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
SyncCurrentFolderSelection();
|
|
|
|
|
m_assetSelection.ClearSelection();
|
|
|
|
|
m_hoveredAssetItemId.clear();
|
|
|
|
|
m_lastPrimaryClickedAssetId.clear();
|
2026-04-12 11:12:27 +08:00
|
|
|
EmitEvent(EventKind::FolderNavigated, source, FindFolderEntry(m_browserModel.GetCurrentFolderId()));
|
2026-04-11 22:31:14 +08:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::EmitEvent(
|
2026-04-11 22:31:14 +08:00
|
|
|
EventKind kind,
|
|
|
|
|
EventSource source,
|
|
|
|
|
const FolderEntry* folder) {
|
|
|
|
|
if (kind == EventKind::None || folder == nullptr) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Event event = {};
|
|
|
|
|
event.kind = kind;
|
|
|
|
|
event.source = source;
|
|
|
|
|
event.itemId = folder->itemId;
|
|
|
|
|
event.absolutePath = folder->absolutePath;
|
2026-04-12 11:12:27 +08:00
|
|
|
event.displayName = folder->label;
|
2026-04-11 22:31:14 +08:00
|
|
|
event.directory = true;
|
|
|
|
|
m_frameEvents.push_back(std::move(event));
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::EmitEvent(
|
2026-04-11 22:31:14 +08:00
|
|
|
EventKind kind,
|
|
|
|
|
EventSource source,
|
|
|
|
|
const AssetEntry* asset) {
|
|
|
|
|
if (kind == EventKind::None) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Event event = {};
|
|
|
|
|
event.kind = kind;
|
|
|
|
|
event.source = source;
|
|
|
|
|
if (asset != nullptr) {
|
|
|
|
|
event.itemId = asset->itemId;
|
|
|
|
|
event.absolutePath = asset->absolutePath;
|
|
|
|
|
event.displayName = asset->displayName;
|
|
|
|
|
event.directory = asset->directory;
|
|
|
|
|
}
|
|
|
|
|
m_frameEvents.push_back(std::move(event));
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-15 08:24:06 +08:00
|
|
|
void ProjectPanel::EmitSelectionClearedEvent(EventSource source) {
|
2026-04-11 22:31:14 +08:00
|
|
|
Event event = {};
|
|
|
|
|
event.kind = EventKind::AssetSelectionCleared;
|
|
|
|
|
event.source = source;
|
|
|
|
|
m_frameEvents.push_back(std::move(event));
|
2026-04-11 20:20:30 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace XCEngine::UI::Editor::App
|