Refine editor window host structure and utility chrome

This commit is contained in:
2026-04-25 18:20:17 +08:00
parent 41b912933d
commit 7335def3fd
31 changed files with 241 additions and 61 deletions

View File

@@ -24,6 +24,7 @@ bool IsPointInsideRect(const UIRect& rect, const UIPoint& point) {
BorderlessWindowChromeLayout BuildBorderlessWindowChromeLayout(
const UIRect& titleBarRect,
float leadingOccupiedRight,
bool includePinButton,
const BorderlessWindowChromeMetrics& metrics) {
BorderlessWindowChromeLayout layout = {};
layout.titleBarRect = titleBarRect;
@@ -32,18 +33,30 @@ BorderlessWindowChromeLayout BuildBorderlessWindowChromeLayout(
}
const float buttonWidth = (std::max)(metrics.buttonWidth, 0.0f);
const float buttonX3 = titleBarRect.x + titleBarRect.width - metrics.buttonInsetX - buttonWidth;
const float buttonX2 = buttonX3 - buttonWidth;
const float buttonX1 = buttonX2 - buttonWidth;
const float rightEdge = titleBarRect.x + titleBarRect.width - metrics.buttonInsetX;
const float closeButtonX = rightEdge - buttonWidth;
const float maximizeButtonX = closeButtonX - buttonWidth;
const float minimizeButtonX = maximizeButtonX - buttonWidth;
const float pinButtonX = minimizeButtonX - buttonWidth;
layout.minimizeButtonRect = UIRect(buttonX1, titleBarRect.y, buttonWidth, titleBarRect.height);
layout.maximizeRestoreButtonRect = UIRect(buttonX2, titleBarRect.y, buttonWidth, titleBarRect.height);
layout.closeButtonRect = UIRect(buttonX3, titleBarRect.y, buttonWidth, titleBarRect.height);
if (includePinButton) {
layout.pinButtonRect = UIRect(pinButtonX, titleBarRect.y, buttonWidth, titleBarRect.height);
}
layout.minimizeButtonRect =
UIRect(minimizeButtonX, titleBarRect.y, buttonWidth, titleBarRect.height);
layout.maximizeRestoreButtonRect =
UIRect(maximizeButtonX, titleBarRect.y, buttonWidth, titleBarRect.height);
layout.closeButtonRect =
UIRect(closeButtonX, titleBarRect.y, buttonWidth, titleBarRect.height);
const float dragLeft =
(std::max)(titleBarRect.x, leadingOccupiedRight + metrics.dragPaddingLeft);
const float buttonClusterLeft =
includePinButton
? layout.pinButtonRect.x
: layout.minimizeButtonRect.x;
const float dragRight =
(std::max)(dragLeft, layout.minimizeButtonRect.x - metrics.dragPaddingRight);
(std::max)(dragLeft, buttonClusterLeft - metrics.dragPaddingRight);
layout.dragRect = UIRect(
dragLeft,
titleBarRect.y,
@@ -64,6 +77,9 @@ BorderlessWindowChromeHitTarget HitTestBorderlessWindowChrome(
if (IsPointInsideRect(layout.minimizeButtonRect, point)) {
return BorderlessWindowChromeHitTarget::MinimizeButton;
}
if (IsPointInsideRect(layout.pinButtonRect, point)) {
return BorderlessWindowChromeHitTarget::PinButton;
}
if (IsPointInsideRect(layout.dragRect, point)) {
return BorderlessWindowChromeHitTarget::DragRegion;
}
@@ -175,10 +191,45 @@ void AppendCloseGlyph(
thickness);
}
void AppendPinGlyph(
UIDrawList& drawList,
const UIRect& rect,
const UIColor& color,
float thickness) {
const float centerX = rect.x + rect.width * 0.5f;
const float centerY = rect.y + rect.height * 0.5f;
const float iconSize = ResolveGlyphBoxSize(rect, 0.34f, 10.0f);
const float headRadius = iconSize * 0.18f;
const float headCenterY = centerY - iconSize * 0.30f;
const float collarTopY = headCenterY + headRadius;
const float collarBottomY = collarTopY + iconSize * 0.12f;
const float shoulderHalfWidth = iconSize * 0.34f;
const float bodyBottomY = centerY + iconSize * 0.06f;
const float needleBottomY = centerY + iconSize * 0.44f;
drawList.AddFilledCircle(UIPoint(centerX, headCenterY), headRadius, color);
drawList.AddLine(
UIPoint(centerX, collarTopY),
UIPoint(centerX, collarBottomY),
color,
thickness);
drawList.AddFilledTriangle(
UIPoint(centerX - shoulderHalfWidth, collarBottomY),
UIPoint(centerX + shoulderHalfWidth, collarBottomY),
UIPoint(centerX, bodyBottomY),
color);
drawList.AddLine(
UIPoint(centerX, bodyBottomY),
UIPoint(centerX, needleBottomY),
color,
thickness);
}
UIColor ResolveButtonFillColor(
BorderlessWindowChromeHitTarget target,
const BorderlessWindowChromeState& state,
const BorderlessWindowChromePalette& palette) {
const BorderlessWindowChromePalette& palette,
bool topmostPinned) {
const bool hovered = state.hoveredTarget == target;
const bool pressed = state.pressedTarget == target;
if (target == BorderlessWindowChromeHitTarget::CloseButton) {
@@ -191,6 +242,11 @@ UIColor ResolveButtonFillColor(
return kTransparentColor;
}
if (target == BorderlessWindowChromeHitTarget::PinButton && topmostPinned &&
!hovered && !pressed) {
return palette.buttonActiveColor;
}
if (pressed) {
return palette.buttonPressedColor;
}
@@ -203,12 +259,17 @@ UIColor ResolveButtonFillColor(
UIColor ResolveIconColor(
BorderlessWindowChromeHitTarget target,
const BorderlessWindowChromeState& state,
const BorderlessWindowChromePalette& palette) {
const BorderlessWindowChromePalette& palette,
bool topmostPinned) {
if (target == BorderlessWindowChromeHitTarget::CloseButton &&
(state.hoveredTarget == target || state.pressedTarget == target)) {
return palette.closeIconHoverColor;
}
if (target == BorderlessWindowChromeHitTarget::PinButton && topmostPinned) {
return palette.iconActiveColor;
}
return palette.iconColor;
}
@@ -219,25 +280,34 @@ void AppendBorderlessWindowChrome(
const BorderlessWindowChromeLayout& layout,
const BorderlessWindowChromeState& state,
bool maximized,
bool topmostPinned,
const BorderlessWindowChromePalette& palette,
const BorderlessWindowChromeMetrics& metrics) {
const struct ButtonEntry {
BorderlessWindowChromeHitTarget target;
UIRect rect;
} buttons[] = {
{ BorderlessWindowChromeHitTarget::PinButton, layout.pinButtonRect },
{ BorderlessWindowChromeHitTarget::MinimizeButton, layout.minimizeButtonRect },
{ BorderlessWindowChromeHitTarget::MaximizeRestoreButton, layout.maximizeRestoreButtonRect },
{ BorderlessWindowChromeHitTarget::CloseButton, layout.closeButtonRect }
};
for (const ButtonEntry& button : buttons) {
const UIColor fill = ResolveButtonFillColor(button.target, state, palette);
if (button.rect.width <= 0.0f || button.rect.height <= 0.0f) {
continue;
}
const UIColor fill = ResolveButtonFillColor(button.target, state, palette, topmostPinned);
if (fill.a > 0.0f) {
drawList.AddFilledRect(button.rect, fill);
}
const UIColor iconColor = ResolveIconColor(button.target, state, palette);
const UIColor iconColor = ResolveIconColor(button.target, state, palette, topmostPinned);
switch (button.target) {
case BorderlessWindowChromeHitTarget::PinButton:
AppendPinGlyph(drawList, button.rect, iconColor, metrics.iconThickness);
break;
case BorderlessWindowChromeHitTarget::MinimizeButton:
AppendMinimizeGlyph(drawList, button.rect, iconColor, metrics.iconThickness);
break;