#include #include #include #include namespace XCEngine::UI::Editor::Widgets { namespace { using ::XCEngine::UI::UIDrawList; using ::XCEngine::UI::UIPoint; using ::XCEngine::UI::UIRect; UIEditorTextFieldMetrics ResolveMetrics(const UIEditorTextFieldMetrics& metrics) { const auto& tokens = GetUIEditorInspectorFieldStyleTokens(); UIEditorTextFieldMetrics resolved = metrics; if (AreUIEditorFieldMetricsEqual(metrics.controlTrailingInset, 8.0f)) { resolved.controlTrailingInset = tokens.controlTrailingInset; } if (AreUIEditorFieldMetricsEqual(metrics.valueBoxMinWidth, 96.0f)) { resolved.valueBoxMinWidth = tokens.controlMinWidth; } return resolved; } UIEditorTextFieldPalette ResolvePalette(const UIEditorTextFieldPalette& palette) { const auto& tokens = GetUIEditorInspectorFieldStyleTokens(); UIEditorTextFieldPalette resolved = palette; if (AreUIEditorFieldColorsEqual(palette.rowHoverColor, ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f))) { resolved.rowHoverColor = tokens.rowHoverColor; } if (AreUIEditorFieldColorsEqual(palette.rowActiveColor, ::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f))) { resolved.rowActiveColor = tokens.rowActiveColor; } if (AreUIEditorFieldColorsEqual(palette.valueBoxColor, ::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f))) { resolved.valueBoxColor = tokens.controlColor; } if (AreUIEditorFieldColorsEqual(palette.valueBoxHoverColor, ::XCEngine::UI::UIColor(0.21f, 0.21f, 0.21f, 1.0f))) { resolved.valueBoxHoverColor = tokens.controlHoverColor; } if (AreUIEditorFieldColorsEqual(palette.valueBoxEditingColor, ::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f))) { resolved.valueBoxEditingColor = tokens.controlEditingColor; } if (AreUIEditorFieldColorsEqual(palette.readOnlyColor, ::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f))) { resolved.readOnlyColor = tokens.controlReadOnlyColor; } if (AreUIEditorFieldColorsEqual(palette.controlBorderColor, ::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f))) { resolved.controlBorderColor = tokens.controlBorderColor; } if (AreUIEditorFieldColorsEqual( palette.controlFocusedBorderColor, ::XCEngine::UI::UIColor(0.46f, 0.46f, 0.46f, 1.0f))) { resolved.controlFocusedBorderColor = tokens.controlFocusedBorderColor; } if (AreUIEditorFieldColorsEqual(palette.labelColor, ::XCEngine::UI::UIColor(0.80f, 0.80f, 0.80f, 1.0f))) { resolved.labelColor = tokens.labelColor; } if (AreUIEditorFieldColorsEqual(palette.valueColor, ::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f))) { resolved.valueColor = tokens.valueColor; } if (AreUIEditorFieldColorsEqual( palette.readOnlyValueColor, ::XCEngine::UI::UIColor(0.62f, 0.62f, 0.62f, 1.0f))) { resolved.readOnlyValueColor = tokens.readOnlyValueColor; } return resolved; } ::XCEngine::UI::UIColor ResolveRowFillColor( const UIEditorTextFieldState& state, const UIEditorTextFieldPalette& palette) { if (state.activeTarget != UIEditorTextFieldHitTargetKind::None) { return palette.rowActiveColor; } if (state.hoveredTarget != UIEditorTextFieldHitTargetKind::None) { return palette.rowHoverColor; } return palette.surfaceColor; } ::XCEngine::UI::UIColor ResolveValueFillColor( const UIEditorTextFieldSpec& spec, const UIEditorTextFieldState& state, const UIEditorTextFieldPalette& palette) { if (spec.readOnly) { return palette.readOnlyColor; } if (state.editing) { return palette.valueBoxEditingColor; } if (state.hoveredTarget == UIEditorTextFieldHitTargetKind::ValueBox) { return palette.valueBoxHoverColor; } return palette.valueBoxColor; } } // namespace bool IsUIEditorTextFieldPointInside( const UIRect& rect, const UIPoint& point) { return point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height; } UIEditorTextFieldLayout BuildUIEditorTextFieldLayout( const UIRect& bounds, const UIEditorTextFieldSpec&, const UIEditorTextFieldMetrics& metrics) { const UIEditorTextFieldMetrics resolvedMetrics = ResolveMetrics(metrics); const UIEditorFieldRowLayout hostLayout = BuildUIEditorFieldRowLayout( bounds, resolvedMetrics.valueBoxMinWidth, UIEditorFieldRowLayoutMetrics { resolvedMetrics.rowHeight, resolvedMetrics.horizontalPadding, resolvedMetrics.labelControlGap, resolvedMetrics.controlColumnStart, resolvedMetrics.controlTrailingInset, resolvedMetrics.controlInsetY, }); UIEditorTextFieldLayout layout = {}; layout.bounds = hostLayout.bounds; layout.labelRect = hostLayout.labelRect; layout.controlRect = hostLayout.controlRect; layout.valueRect = layout.controlRect; return layout; } UIEditorTextFieldHitTarget HitTestUIEditorTextField( const UIEditorTextFieldLayout& layout, const UIPoint& point) { if (IsUIEditorTextFieldPointInside(layout.valueRect, point)) { return { UIEditorTextFieldHitTargetKind::ValueBox }; } if (IsUIEditorTextFieldPointInside(layout.bounds, point)) { return { UIEditorTextFieldHitTargetKind::Row }; } return {}; } void AppendUIEditorTextFieldBackground( UIDrawList& drawList, const UIEditorTextFieldLayout& layout, const UIEditorTextFieldSpec& spec, const UIEditorTextFieldState& state, const UIEditorTextFieldPalette& palette, const UIEditorTextFieldMetrics& metrics) { const UIEditorTextFieldPalette resolvedPalette = ResolvePalette(palette); const UIEditorTextFieldMetrics resolvedMetrics = ResolveMetrics(metrics); const auto rowFillColor = ResolveRowFillColor(state, resolvedPalette); if (rowFillColor.a > 0.0f) { drawList.AddFilledRect(layout.bounds, rowFillColor, resolvedMetrics.cornerRounding); } const auto rowBorderColor = state.focused ? resolvedPalette.focusedBorderColor : resolvedPalette.borderColor; if (rowBorderColor.a > 0.0f) { drawList.AddRectOutline( layout.bounds, rowBorderColor, state.focused ? resolvedMetrics.focusedBorderThickness : resolvedMetrics.borderThickness, resolvedMetrics.cornerRounding); } drawList.AddFilledRect( layout.valueRect, ResolveValueFillColor(spec, state, resolvedPalette), resolvedMetrics.valueBoxRounding); drawList.AddRectOutline( layout.valueRect, state.editing ? resolvedPalette.controlFocusedBorderColor : resolvedPalette.controlBorderColor, state.editing ? resolvedMetrics.focusedBorderThickness : resolvedMetrics.borderThickness, resolvedMetrics.valueBoxRounding); } void AppendUIEditorTextFieldForeground( UIDrawList& drawList, const UIEditorTextFieldLayout& layout, const UIEditorTextFieldSpec& spec, const UIEditorTextFieldState& state, const UIEditorTextFieldPalette& palette, const UIEditorTextFieldMetrics& metrics) { const UIEditorTextFieldPalette resolvedPalette = ResolvePalette(palette); const UIEditorTextFieldMetrics resolvedMetrics = ResolveMetrics(metrics); drawList.PushClipRect(ResolveUIEditorTextClipRect(layout.labelRect, resolvedMetrics.labelFontSize)); drawList.AddText( UIPoint( layout.labelRect.x, ResolveUIEditorTextTop(layout.labelRect, resolvedMetrics.labelFontSize, resolvedMetrics.labelTextInsetY)), spec.label, resolvedPalette.labelColor, resolvedMetrics.labelFontSize); drawList.PopClipRect(); drawList.PushClipRect(ResolveUIEditorTextClipRect(layout.valueRect, resolvedMetrics.valueFontSize)); drawList.AddText( UIPoint( layout.valueRect.x + resolvedMetrics.valueTextInsetX, ResolveUIEditorTextTop(layout.valueRect, resolvedMetrics.valueFontSize, resolvedMetrics.valueTextInsetY)), state.editing ? state.displayText : spec.value, spec.readOnly ? resolvedPalette.readOnlyValueColor : resolvedPalette.valueColor, resolvedMetrics.valueFontSize); drawList.PopClipRect(); } void AppendUIEditorTextField( UIDrawList& drawList, const UIRect& bounds, const UIEditorTextFieldSpec& spec, const UIEditorTextFieldState& state, const UIEditorTextFieldPalette& palette, const UIEditorTextFieldMetrics& metrics) { const UIEditorTextFieldMetrics resolvedMetrics = ResolveMetrics(metrics); const UIEditorTextFieldPalette resolvedPalette = ResolvePalette(palette); const UIEditorTextFieldLayout layout = BuildUIEditorTextFieldLayout(bounds, spec, resolvedMetrics); AppendUIEditorTextFieldBackground(drawList, layout, spec, state, resolvedPalette, resolvedMetrics); AppendUIEditorTextFieldForeground(drawList, layout, spec, state, resolvedPalette, resolvedMetrics); } } // namespace XCEngine::UI::Editor::Widgets