Files
XCEngine/editor/src/Fields/UIEditorBoolField.cpp
2026-04-25 16:46:01 +08:00

135 lines
4.7 KiB
C++

#include <XCEditor/Fields/UIEditorBoolField.h>
#include <XCEditor/Widgets/UIEditorFieldRowLayout.h>
#include <XCEditor/Widgets/UIEditorTextLayout.h>
#include <algorithm>
namespace XCEngine::UI::Editor::Widgets {
namespace {
float ClampNonNegative(float value) {
return (std::max)(0.0f, value);
}
bool ContainsPoint(const ::XCEngine::UI::UIRect& rect, const ::XCEngine::UI::UIPoint& point) {
return point.x >= rect.x &&
point.x <= rect.x + rect.width &&
point.y >= rect.y &&
point.y <= rect.y + rect.height;
}
void AppendCheckMark(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& rect,
const ::XCEngine::UI::UIColor& color) {
const float size = (std::min)(rect.width, rect.height);
const float pad = (std::max)(size * 0.22f, 2.0f);
const ::XCEngine::UI::UIPoint a(rect.x + pad, rect.y + size * 0.56f);
const ::XCEngine::UI::UIPoint b(rect.x + size * 0.44f, rect.y + size - pad);
const ::XCEngine::UI::UIPoint c(rect.x + size - pad, rect.y + pad);
drawList.AddLine(a, b, color, 2.0f);
drawList.AddLine(b, c, color, 2.0f);
}
} // namespace
UIEditorBoolFieldLayout BuildUIEditorBoolFieldLayout(
const ::XCEngine::UI::UIRect& bounds,
const UIEditorBoolFieldSpec&,
const UIEditorBoolFieldMetrics& metrics) {
const UIEditorFieldRowLayout hostLayout = BuildUIEditorFieldRowLayout(
bounds,
metrics.checkboxSize,
UIEditorFieldRowLayoutMetrics {
metrics.rowHeight,
metrics.horizontalPadding,
metrics.labelControlGap,
metrics.controlColumnStart,
metrics.controlMinWidth,
metrics.controlTrailingInset,
0.0f,
});
UIEditorBoolFieldLayout layout = {};
layout.bounds = hostLayout.bounds;
layout.labelRect = hostLayout.labelRect;
layout.controlRect = hostLayout.controlRect;
layout.checkboxRect = ::XCEngine::UI::UIRect(
layout.controlRect.x,
layout.bounds.y + ClampNonNegative((layout.bounds.height - metrics.checkboxSize) * 0.5f),
metrics.checkboxSize,
metrics.checkboxSize);
layout.checkmarkRect = layout.checkboxRect;
return layout;
}
UIEditorBoolFieldHitTarget HitTestUIEditorBoolField(
const UIEditorBoolFieldLayout& layout,
const ::XCEngine::UI::UIPoint& point) {
if (!ContainsPoint(layout.bounds, point)) {
return {};
}
if (ContainsPoint(layout.controlRect, point)) {
return { UIEditorBoolFieldHitTargetKind::Checkbox };
}
return { UIEditorBoolFieldHitTargetKind::Row };
}
void AppendUIEditorBoolFieldBackground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorBoolFieldLayout& layout,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldState& state,
const UIEditorBoolFieldPalette& palette,
const UIEditorBoolFieldMetrics& metrics) {
const bool checkboxHovered = state.hoveredTarget == UIEditorBoolFieldHitTargetKind::Checkbox;
const ::XCEngine::UI::UIColor checkboxColor =
spec.readOnly
? palette.checkboxReadOnlyColor
: (checkboxHovered ? palette.checkboxHoverColor : palette.checkboxColor);
drawList.AddFilledRect(layout.checkboxRect, checkboxColor, metrics.checkboxRounding);
drawList.AddRectOutline(
layout.checkboxRect,
palette.checkboxBorderColor,
metrics.borderThickness,
metrics.checkboxRounding);
}
void AppendUIEditorBoolFieldForeground(
::XCEngine::UI::UIDrawList& drawList,
const UIEditorBoolFieldLayout& layout,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldPalette& palette,
const UIEditorBoolFieldMetrics& metrics) {
drawList.PushClipRect(ResolveUIEditorTextClipRect(layout.labelRect, metrics.labelFontSize));
drawList.AddText(
::XCEngine::UI::UIPoint(
layout.labelRect.x,
ResolveUIEditorTextTop(layout.labelRect, metrics.labelFontSize, metrics.labelTextInsetY)),
spec.label,
palette.labelColor,
metrics.labelFontSize);
drawList.PopClipRect();
if (spec.value) {
AppendCheckMark(drawList, layout.checkmarkRect, palette.checkboxMarkColor);
}
}
void AppendUIEditorBoolField(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& bounds,
const UIEditorBoolFieldSpec& spec,
const UIEditorBoolFieldState& state,
const UIEditorBoolFieldPalette& palette,
const UIEditorBoolFieldMetrics& metrics) {
const UIEditorBoolFieldLayout layout = BuildUIEditorBoolFieldLayout(bounds, spec, metrics);
AppendUIEditorBoolFieldBackground(drawList, layout, spec, state, palette, metrics);
AppendUIEditorBoolFieldForeground(drawList, layout, spec, palette, metrics);
}
} // namespace XCEngine::UI::Editor::Widgets