Refine editor tree alignment and project panel events
This commit is contained in:
@@ -328,6 +328,65 @@ std::string DescribeInputEventType(const UIInputEvent& event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DescribeProjectPanelEvent(const App::ProductProjectPanel::Event& event) {
|
||||||
|
std::ostringstream stream = {};
|
||||||
|
switch (event.kind) {
|
||||||
|
case App::ProductProjectPanel::EventKind::AssetSelected:
|
||||||
|
stream << "AssetSelected";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventKind::AssetSelectionCleared:
|
||||||
|
stream << "AssetSelectionCleared";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventKind::FolderNavigated:
|
||||||
|
stream << "FolderNavigated";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventKind::AssetOpened:
|
||||||
|
stream << "AssetOpened";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventKind::ContextMenuRequested:
|
||||||
|
stream << "ContextMenuRequested";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventKind::None:
|
||||||
|
default:
|
||||||
|
stream << "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << " source=";
|
||||||
|
switch (event.source) {
|
||||||
|
case App::ProductProjectPanel::EventSource::Tree:
|
||||||
|
stream << "Tree";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::Breadcrumb:
|
||||||
|
stream << "Breadcrumb";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::GridPrimary:
|
||||||
|
stream << "GridPrimary";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::GridDoubleClick:
|
||||||
|
stream << "GridDoubleClick";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::GridSecondary:
|
||||||
|
stream << "GridSecondary";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::Background:
|
||||||
|
stream << "Background";
|
||||||
|
break;
|
||||||
|
case App::ProductProjectPanel::EventSource::None:
|
||||||
|
default:
|
||||||
|
stream << "None";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!event.itemId.empty()) {
|
||||||
|
stream << " item=" << event.itemId;
|
||||||
|
}
|
||||||
|
if (!event.displayName.empty()) {
|
||||||
|
stream << " label=" << event.displayName;
|
||||||
|
}
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<UIInputEvent> FilterShellInputEventsForHostedContentCapture(
|
std::vector<UIInputEvent> FilterShellInputEventsForHostedContentCapture(
|
||||||
const std::vector<UIInputEvent>& inputEvents) {
|
const std::vector<UIInputEvent>& inputEvents) {
|
||||||
std::vector<UIInputEvent> filteredEvents = {};
|
std::vector<UIInputEvent> filteredEvents = {};
|
||||||
@@ -568,6 +627,11 @@ void Application::RenderFrame() {
|
|||||||
hostedContentEvents,
|
hostedContentEvents,
|
||||||
!m_shellFrame.result.workspaceInputSuppressed,
|
!m_shellFrame.result.workspaceInputSuppressed,
|
||||||
m_workspaceController.GetWorkspace().activePanelId == "project");
|
m_workspaceController.GetWorkspace().activePanelId == "project");
|
||||||
|
for (const App::ProductProjectPanel::Event& event : m_projectPanel.GetFrameEvents()) {
|
||||||
|
LogRuntimeTrace("project", DescribeProjectPanelEvent(event));
|
||||||
|
m_lastStatus = "Project";
|
||||||
|
m_lastMessage = DescribeProjectPanelEvent(event);
|
||||||
|
}
|
||||||
ApplyHostedContentCaptureRequests();
|
ApplyHostedContentCaptureRequests();
|
||||||
ApplyCurrentCursor();
|
ApplyCurrentCursor();
|
||||||
const UIEditorShellComposeModel shellComposeModel =
|
const UIEditorShellComposeModel shellComposeModel =
|
||||||
|
|||||||
@@ -405,6 +405,10 @@ bool ProductProjectPanel::HasActivePointerCapture() const {
|
|||||||
return m_splitterDragging;
|
return m_splitterDragging;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ProductProjectPanel::Event>& ProductProjectPanel::GetFrameEvents() const {
|
||||||
|
return m_frameEvents;
|
||||||
|
}
|
||||||
|
|
||||||
const ProductProjectPanel::FolderEntry* ProductProjectPanel::FindFolderEntry(
|
const ProductProjectPanel::FolderEntry* ProductProjectPanel::FindFolderEntry(
|
||||||
std::string_view itemId) const {
|
std::string_view itemId) const {
|
||||||
for (const FolderEntry& entry : m_folderEntries) {
|
for (const FolderEntry& entry : m_folderEntries) {
|
||||||
@@ -416,6 +420,17 @@ const ProductProjectPanel::FolderEntry* ProductProjectPanel::FindFolderEntry(
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ProductProjectPanel::AssetEntry* ProductProjectPanel::FindAssetEntry(
|
||||||
|
std::string_view itemId) const {
|
||||||
|
for (const AssetEntry& entry : m_assetEntries) {
|
||||||
|
if (entry.itemId == itemId) {
|
||||||
|
return &entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
const UIEditorPanelContentHostPanelState* ProductProjectPanel::FindMountedProjectPanel(
|
const UIEditorPanelContentHostPanelState* ProductProjectPanel::FindMountedProjectPanel(
|
||||||
const UIEditorPanelContentHostFrame& contentHostFrame) const {
|
const UIEditorPanelContentHostFrame& contentHostFrame) const {
|
||||||
for (const UIEditorPanelContentHostPanelState& panelState : contentHostFrame.panelStates) {
|
for (const UIEditorPanelContentHostPanelState& panelState : contentHostFrame.panelStates) {
|
||||||
@@ -656,9 +671,9 @@ void ProductProjectPanel::SyncCurrentFolderSelection() {
|
|||||||
m_folderSelection.SetSelection(m_currentFolderId);
|
m_folderSelection.SetSelection(m_currentFolderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProductProjectPanel::NavigateToFolder(std::string_view itemId) {
|
bool ProductProjectPanel::NavigateToFolder(std::string_view itemId, EventSource source) {
|
||||||
if (itemId.empty() || FindFolderEntry(itemId) == nullptr || itemId == m_currentFolderId) {
|
if (itemId.empty() || FindFolderEntry(itemId) == nullptr || itemId == m_currentFolderId) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_currentFolderId = std::string(itemId);
|
m_currentFolderId = std::string(itemId);
|
||||||
@@ -667,6 +682,53 @@ void ProductProjectPanel::NavigateToFolder(std::string_view itemId) {
|
|||||||
m_hoveredAssetItemId.clear();
|
m_hoveredAssetItemId.clear();
|
||||||
m_lastPrimaryClickedAssetId.clear();
|
m_lastPrimaryClickedAssetId.clear();
|
||||||
RefreshAssetList();
|
RefreshAssetList();
|
||||||
|
EmitEvent(EventKind::FolderNavigated, source, FindFolderEntry(m_currentFolderId));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProductProjectPanel::EmitEvent(
|
||||||
|
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;
|
||||||
|
event.displayName = PathToUtf8String(folder->absolutePath.filename());
|
||||||
|
event.directory = true;
|
||||||
|
m_frameEvents.push_back(std::move(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProductProjectPanel::EmitEvent(
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProductProjectPanel::EmitSelectionClearedEvent(EventSource source) {
|
||||||
|
Event event = {};
|
||||||
|
event.kind = EventKind::AssetSelectionCleared;
|
||||||
|
event.source = source;
|
||||||
|
m_frameEvents.push_back(std::move(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProductProjectPanel::RefreshAssetList() {
|
void ProductProjectPanel::RefreshAssetList() {
|
||||||
@@ -720,6 +782,7 @@ void ProductProjectPanel::RefreshAssetList() {
|
|||||||
|
|
||||||
void ProductProjectPanel::ResetTransientFrames() {
|
void ProductProjectPanel::ResetTransientFrames() {
|
||||||
m_treeFrame = {};
|
m_treeFrame = {};
|
||||||
|
m_frameEvents.clear();
|
||||||
m_layout = {};
|
m_layout = {};
|
||||||
m_hoveredAssetItemId.clear();
|
m_hoveredAssetItemId.clear();
|
||||||
m_hoveredBreadcrumbIndex = kInvalidLayoutIndex;
|
m_hoveredBreadcrumbIndex = kInvalidLayoutIndex;
|
||||||
@@ -735,6 +798,7 @@ void ProductProjectPanel::Update(
|
|||||||
bool panelActive) {
|
bool panelActive) {
|
||||||
m_requestPointerCapture = false;
|
m_requestPointerCapture = false;
|
||||||
m_requestPointerRelease = false;
|
m_requestPointerRelease = false;
|
||||||
|
m_frameEvents.clear();
|
||||||
|
|
||||||
const UIEditorPanelContentHostPanelState* panelState =
|
const UIEditorPanelContentHostPanelState* panelState =
|
||||||
FindMountedProjectPanel(contentHostFrame);
|
FindMountedProjectPanel(contentHostFrame);
|
||||||
@@ -779,7 +843,7 @@ void ProductProjectPanel::Update(
|
|||||||
if (m_treeFrame.result.selectionChanged &&
|
if (m_treeFrame.result.selectionChanged &&
|
||||||
!m_treeFrame.result.selectedItemId.empty() &&
|
!m_treeFrame.result.selectedItemId.empty() &&
|
||||||
m_treeFrame.result.selectedItemId != m_currentFolderId) {
|
m_treeFrame.result.selectedItemId != m_currentFolderId) {
|
||||||
NavigateToFolder(m_treeFrame.result.selectedItemId);
|
NavigateToFolder(m_treeFrame.result.selectedItemId, EventSource::Tree);
|
||||||
m_layout = BuildLayout(panelState->bounds);
|
m_layout = BuildLayout(panelState->bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -823,39 +887,35 @@ void ProductProjectPanel::Update(
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case UIInputEventType::PointerButtonDown:
|
case UIInputEventType::PointerButtonDown:
|
||||||
if (event.pointerButton != ::XCEngine::UI::UIPointerButton::Left) {
|
if (event.pointerButton == ::XCEngine::UI::UIPointerButton::Left) {
|
||||||
break;
|
if (ContainsPoint(m_layout.dividerRect, event.position)) {
|
||||||
}
|
m_splitterDragging = true;
|
||||||
|
m_splitterHovered = true;
|
||||||
|
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
||||||
|
m_requestPointerCapture = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ContainsPoint(m_layout.dividerRect, event.position)) {
|
m_pressedBreadcrumbIndex = HitTestBreadcrumbItem(event.position);
|
||||||
m_splitterDragging = true;
|
|
||||||
m_splitterHovered = true;
|
|
||||||
m_pressedBreadcrumbIndex = kInvalidLayoutIndex;
|
|
||||||
m_requestPointerCapture = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_pressedBreadcrumbIndex = HitTestBreadcrumbItem(event.position);
|
if (!ContainsPoint(m_layout.gridRect, event.position)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ContainsPoint(m_layout.gridRect, event.position)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
const std::size_t hitIndex = HitTestAssetTile(event.position);
|
const std::size_t hitIndex = HitTestAssetTile(event.position);
|
||||||
if (hitIndex >= m_assetEntries.size()) {
|
if (hitIndex >= m_assetEntries.size()) {
|
||||||
m_assetSelection.ClearSelection();
|
if (m_assetSelection.HasSelection()) {
|
||||||
|
m_assetSelection.ClearSelection();
|
||||||
|
EmitSelectionClearedEvent(EventSource::Background);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const AssetEntry& assetEntry = m_assetEntries[hitIndex];
|
const AssetEntry& assetEntry = m_assetEntries[hitIndex];
|
||||||
const bool alreadySelected = m_assetSelection.IsSelected(assetEntry.itemId);
|
const bool alreadySelected = m_assetSelection.IsSelected(assetEntry.itemId);
|
||||||
m_assetSelection.SetSelection(assetEntry.itemId);
|
const bool selectionChanged = m_assetSelection.SetSelection(assetEntry.itemId);
|
||||||
|
if (selectionChanged) {
|
||||||
if (!assetEntry.directory) {
|
EmitEvent(EventKind::AssetSelected, EventSource::GridPrimary, &assetEntry);
|
||||||
m_lastPrimaryClickedAssetId = assetEntry.itemId;
|
|
||||||
m_lastPrimaryClickTimeMs = GetTickCount64();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::uint64_t nowMs = GetTickCount64();
|
const std::uint64_t nowMs = GetTickCount64();
|
||||||
@@ -873,9 +933,30 @@ void ProductProjectPanel::Update(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NavigateToFolder(assetEntry.itemId);
|
if (assetEntry.directory) {
|
||||||
m_layout = BuildLayout(panelState->bounds);
|
NavigateToFolder(assetEntry.itemId, EventSource::GridDoubleClick);
|
||||||
m_hoveredAssetItemId.clear();
|
m_layout = BuildLayout(panelState->bounds);
|
||||||
|
m_hoveredAssetItemId.clear();
|
||||||
|
} else {
|
||||||
|
EmitEvent(EventKind::AssetOpened, EventSource::GridDoubleClick, &assetEntry);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.pointerButton == ::XCEngine::UI::UIPointerButton::Right &&
|
||||||
|
ContainsPoint(m_layout.gridRect, event.position)) {
|
||||||
|
const std::size_t hitIndex = HitTestAssetTile(event.position);
|
||||||
|
if (hitIndex >= m_assetEntries.size()) {
|
||||||
|
EmitEvent(EventKind::ContextMenuRequested, EventSource::Background, static_cast<const AssetEntry*>(nullptr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AssetEntry& assetEntry = m_assetEntries[hitIndex];
|
||||||
|
if (!m_assetSelection.IsSelected(assetEntry.itemId)) {
|
||||||
|
m_assetSelection.SetSelection(assetEntry.itemId);
|
||||||
|
EmitEvent(EventKind::AssetSelected, EventSource::GridSecondary, &assetEntry);
|
||||||
|
}
|
||||||
|
EmitEvent(EventKind::ContextMenuRequested, EventSource::GridSecondary, &assetEntry);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -900,7 +981,7 @@ void ProductProjectPanel::Update(
|
|||||||
const BreadcrumbItemLayout& item =
|
const BreadcrumbItemLayout& item =
|
||||||
m_layout.breadcrumbItems[releasedBreadcrumbIndex];
|
m_layout.breadcrumbItems[releasedBreadcrumbIndex];
|
||||||
if (item.clickable) {
|
if (item.clickable) {
|
||||||
NavigateToFolder(item.targetFolderId);
|
NavigateToFolder(item.targetFolderId, EventSource::Breadcrumb);
|
||||||
m_layout = BuildLayout(panelState->bounds);
|
m_layout = BuildLayout(panelState->bounds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,34 @@ public:
|
|||||||
ResizeEW
|
ResizeEW
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class EventKind : std::uint8_t {
|
||||||
|
None = 0,
|
||||||
|
AssetSelected,
|
||||||
|
AssetSelectionCleared,
|
||||||
|
FolderNavigated,
|
||||||
|
AssetOpened,
|
||||||
|
ContextMenuRequested
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EventSource : std::uint8_t {
|
||||||
|
None = 0,
|
||||||
|
Tree,
|
||||||
|
Breadcrumb,
|
||||||
|
GridPrimary,
|
||||||
|
GridDoubleClick,
|
||||||
|
GridSecondary,
|
||||||
|
Background
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
EventKind kind = EventKind::None;
|
||||||
|
EventSource source = EventSource::None;
|
||||||
|
std::string itemId = {};
|
||||||
|
std::filesystem::path absolutePath = {};
|
||||||
|
std::string displayName = {};
|
||||||
|
bool directory = false;
|
||||||
|
};
|
||||||
|
|
||||||
void Initialize(const std::filesystem::path& repoRoot);
|
void Initialize(const std::filesystem::path& repoRoot);
|
||||||
void SetBuiltInIcons(const ProductBuiltInIcons* icons);
|
void SetBuiltInIcons(const ProductBuiltInIcons* icons);
|
||||||
void SetTextMeasurer(const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer);
|
void SetTextMeasurer(const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer);
|
||||||
@@ -39,6 +67,7 @@ public:
|
|||||||
bool WantsHostPointerCapture() const;
|
bool WantsHostPointerCapture() const;
|
||||||
bool WantsHostPointerRelease() const;
|
bool WantsHostPointerRelease() const;
|
||||||
bool HasActivePointerCapture() const;
|
bool HasActivePointerCapture() const;
|
||||||
|
const std::vector<Event>& GetFrameEvents() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FolderEntry {
|
struct FolderEntry {
|
||||||
@@ -83,6 +112,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
const FolderEntry* FindFolderEntry(std::string_view itemId) const;
|
const FolderEntry* FindFolderEntry(std::string_view itemId) const;
|
||||||
|
const AssetEntry* FindAssetEntry(std::string_view itemId) const;
|
||||||
const UIEditorPanelContentHostPanelState* FindMountedProjectPanel(
|
const UIEditorPanelContentHostPanelState* FindMountedProjectPanel(
|
||||||
const UIEditorPanelContentHostFrame& contentHostFrame) const;
|
const UIEditorPanelContentHostFrame& contentHostFrame) const;
|
||||||
Layout BuildLayout(const ::XCEngine::UI::UIRect& bounds) const;
|
Layout BuildLayout(const ::XCEngine::UI::UIRect& bounds) const;
|
||||||
@@ -93,7 +123,10 @@ private:
|
|||||||
void EnsureValidCurrentFolder();
|
void EnsureValidCurrentFolder();
|
||||||
void ExpandFolderAncestors(std::string_view itemId);
|
void ExpandFolderAncestors(std::string_view itemId);
|
||||||
void SyncCurrentFolderSelection();
|
void SyncCurrentFolderSelection();
|
||||||
void NavigateToFolder(std::string_view itemId);
|
bool NavigateToFolder(std::string_view itemId, EventSource source = EventSource::None);
|
||||||
|
void EmitEvent(EventKind kind, EventSource source, const FolderEntry* folder);
|
||||||
|
void EmitEvent(EventKind kind, EventSource source, const AssetEntry* asset);
|
||||||
|
void EmitSelectionClearedEvent(EventSource source);
|
||||||
void ResetTransientFrames();
|
void ResetTransientFrames();
|
||||||
|
|
||||||
std::filesystem::path m_assetsRootPath = {};
|
std::filesystem::path m_assetsRootPath = {};
|
||||||
@@ -107,6 +140,7 @@ private:
|
|||||||
::XCEngine::UI::Widgets::UISelectionModel m_assetSelection = {};
|
::XCEngine::UI::Widgets::UISelectionModel m_assetSelection = {};
|
||||||
UIEditorTreeViewInteractionState m_treeInteractionState = {};
|
UIEditorTreeViewInteractionState m_treeInteractionState = {};
|
||||||
UIEditorTreeViewInteractionFrame m_treeFrame = {};
|
UIEditorTreeViewInteractionFrame m_treeFrame = {};
|
||||||
|
std::vector<Event> m_frameEvents = {};
|
||||||
Layout m_layout = {};
|
Layout m_layout = {};
|
||||||
std::string m_currentFolderId = {};
|
std::string m_currentFolderId = {};
|
||||||
std::string m_hoveredAssetItemId = {};
|
std::string m_hoveredAssetItemId = {};
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ inline Widgets::UIEditorTreeViewMetrics BuildProductTreeViewMetrics() {
|
|||||||
metrics.disclosureLabelGap = 2.0f;
|
metrics.disclosureLabelGap = 2.0f;
|
||||||
metrics.iconExtent = 18.0f;
|
metrics.iconExtent = 18.0f;
|
||||||
metrics.iconLabelGap = 2.0f;
|
metrics.iconLabelGap = 2.0f;
|
||||||
|
metrics.iconInsetY = -1.0f;
|
||||||
metrics.labelInsetY = 0.0f;
|
metrics.labelInsetY = 0.0f;
|
||||||
metrics.cornerRounding = 0.0f;
|
metrics.cornerRounding = 0.0f;
|
||||||
metrics.borderThickness = 0.0f;
|
metrics.borderThickness = 0.0f;
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ struct UIEditorTreeViewMetrics {
|
|||||||
float disclosureLabelGap = 6.0f;
|
float disclosureLabelGap = 6.0f;
|
||||||
float iconExtent = 18.0f;
|
float iconExtent = 18.0f;
|
||||||
float iconLabelGap = 2.0f;
|
float iconLabelGap = 2.0f;
|
||||||
|
float iconInsetY = 0.0f;
|
||||||
float labelInsetY = 6.0f;
|
float labelInsetY = 6.0f;
|
||||||
float cornerRounding = 6.0f;
|
float cornerRounding = 6.0f;
|
||||||
float borderThickness = 1.0f;
|
float borderThickness = 1.0f;
|
||||||
|
|||||||
@@ -27,9 +27,12 @@ float ResolveTreeViewRowHeight(
|
|||||||
return item.desiredHeight > 0.0f ? item.desiredHeight : metrics.rowHeight;
|
return item.desiredHeight > 0.0f ? item.desiredHeight : metrics.rowHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
float ResolveTextTop(const ::XCEngine::UI::UIRect& rect, float fontSize) {
|
float ResolveTextTop(
|
||||||
|
const ::XCEngine::UI::UIRect& rect,
|
||||||
|
float fontSize,
|
||||||
|
float insetY) {
|
||||||
const float lineHeight = fontSize * 1.6f;
|
const float lineHeight = fontSize * 1.6f;
|
||||||
return rect.y + std::floor((rect.height - lineHeight) * 0.5f);
|
return rect.y + std::floor((rect.height - lineHeight) * 0.5f) + insetY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AppendDisclosureArrow(
|
void AppendDisclosureArrow(
|
||||||
@@ -217,7 +220,7 @@ UIEditorTreeViewLayout BuildUIEditorTreeViewLayout(
|
|||||||
const float contentStartX = disclosureRect.x + metrics.disclosureExtent + metrics.disclosureLabelGap;
|
const float contentStartX = disclosureRect.x + metrics.disclosureExtent + metrics.disclosureLabelGap;
|
||||||
const ::XCEngine::UI::UIRect iconRect(
|
const ::XCEngine::UI::UIRect iconRect(
|
||||||
hasLeadingIcon ? contentStartX : 0.0f,
|
hasLeadingIcon ? contentStartX : 0.0f,
|
||||||
rowRect.y + (rowRect.height - iconExtent) * 0.5f,
|
rowRect.y + (rowRect.height - iconExtent) * 0.5f + metrics.iconInsetY,
|
||||||
hasLeadingIcon ? iconExtent : 0.0f,
|
hasLeadingIcon ? iconExtent : 0.0f,
|
||||||
hasLeadingIcon ? iconExtent : 0.0f);
|
hasLeadingIcon ? iconExtent : 0.0f);
|
||||||
const float labelStartX =
|
const float labelStartX =
|
||||||
@@ -322,7 +325,7 @@ void AppendUIEditorTreeViewForeground(
|
|||||||
drawList.AddText(
|
drawList.AddText(
|
||||||
::XCEngine::UI::UIPoint(
|
::XCEngine::UI::UIPoint(
|
||||||
layout.labelRects[visibleOffset].x,
|
layout.labelRects[visibleOffset].x,
|
||||||
ResolveTextTop(layout.labelRects[visibleOffset], kTreeFontSize)),
|
ResolveTextTop(layout.labelRects[visibleOffset], kTreeFontSize, metrics.labelInsetY)),
|
||||||
item.label,
|
item.label,
|
||||||
palette.textColor,
|
palette.textColor,
|
||||||
kTreeFontSize);
|
kTreeFontSize);
|
||||||
|
|||||||
Reference in New Issue
Block a user