#include #include #include "engine/core/gui/uiComponent/layout/LayoutEngine.h" using namespace LayoutEngine; using Catch::Matchers::WithinAbs; const float EPS = 0.001f; static NodeLayout makeNode(float x, float y, float w, float h) { NodeLayout n; n.layoutStyle.width = { w, SizeUnit::Percent }; n.layoutStyle.height = { h, SizeUnit::Percent }; n.layoutStyle.margin.left = { x, SizeUnit::Percent }; n.layoutStyle.margin.top = { y, SizeUnit::Percent }; return n; } static Dimensions screen800x600() { return { 0.f, 0.f, 1.0f, 1.0f }; } // ── Basisfälle ─────────────────────────────────────────────────────────────── TEST_CASE("SizeUnit::Pixels wird korrekt normalisiert", "[layout][pixels]") { NodeLayout root; root.layoutStyle.width = { 400.f, SizeUnit::Pixels }; root.layoutStyle.height = { 300.f, SizeUnit::Pixels }; auto result = compute(root, screen800x600(), 800.f, 600.f); REQUIRE_THAT(result.self.width, WithinAbs(0.5f, EPS)); // 400/800 REQUIRE_THAT(result.self.height, WithinAbs(0.5f, EPS)); // 300/600 } TEST_CASE("Eigene Dimensionen werden korrekt berechnet", "[layout][self]") { NodeLayout root = makeNode(0.1f, 0.2f, 0.5f, 0.4f); auto result = compute(root, screen800x600(), 800.f, 600.f); REQUIRE_THAT(result.self.x, WithinAbs(0.1f, EPS)); REQUIRE_THAT(result.self.y, WithinAbs(0.2f, EPS)); REQUIRE_THAT(result.self.width, WithinAbs(0.5f, EPS)); REQUIRE_THAT(result.self.height, WithinAbs(0.4f, EPS)); } TEST_CASE("Kein Kind → leere children-Liste", "[layout][children]") { NodeLayout root = makeNode(0.f, 0.f, 0.5f, 0.5f); auto result = compute(root, screen800x600(), 800.f, 600.f); REQUIRE(result.children.empty()); } // ── JustifyContent ─────────────────────────────────────────────────────────── TEST_CASE("JustifyContent::Start – Kinder beginnen bei 0", "[layout][justify]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Row; root.layoutStyle.justifyContent = JustifyContent::Start; root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f)); root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f)); auto result = compute(root, screen800x600(), 800.f, 600.f); REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.0f, EPS)); REQUIRE_THAT(result.children[1].self.x, WithinAbs(0.2f, EPS)); } TEST_CASE("JustifyContent::Center – Kind horizontal zentriert", "[layout][justify]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Row; root.layoutStyle.justifyContent = JustifyContent::Center; root.children.push_back(makeNode(0.f, 0.f, 0.4f, 1.0f)); auto result = compute(root, screen800x600(), 800.f, 600.f); // remaining = 1.0 - 0.4 = 0.6 → offset = 0.3 REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.3f, EPS)); } TEST_CASE("JustifyContent::SpaceBetween – Gap korrekt verteilt", "[layout][justify]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Row; root.layoutStyle.justifyContent = JustifyContent::SpaceBetween; root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f)); root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f)); root.children.push_back(makeNode(0.f, 0.f, 0.2f, 1.0f)); auto result = compute(root, screen800x600(), 800.f, 600.f); // remaining = 1.0 - 0.6 = 0.4, gap = 0.2 REQUIRE_THAT(result.children[0].self.x, WithinAbs(0.0f, EPS)); REQUIRE_THAT(result.children[1].self.x, WithinAbs(0.4f, EPS)); REQUIRE_THAT(result.children[2].self.x, WithinAbs(0.8f, EPS)); } // ── AlignItems ─────────────────────────────────────────────────────────────── TEST_CASE("AlignItems::Center – Kind vertikal zentriert (Row)", "[layout][align]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Row; root.layoutStyle.alignItems = AlignItems::Center; root.children.push_back(makeNode(0.f, 0.f, 0.5f, 0.4f)); auto result = compute(root, screen800x600(), 800.f, 600.f); // remaining = 1.0 - 0.4 = 0.6 → y = 0.3 REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.3f, EPS)); } TEST_CASE("AlignItems::End – Kind am unteren Rand (Row)", "[layout][align]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Row; root.layoutStyle.alignItems = AlignItems::End; root.children.push_back(makeNode(0.f, 0.f, 0.5f, 0.4f)); auto result = compute(root, screen800x600(), 800.f, 600.f); // remaining = 1.0 - 0.4 = 0.6 → y = 0.6 REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.6f, EPS)); } // ── FlexDirection::Column ──────────────────────────────────────────────────── TEST_CASE("Column: Kinder werden vertikal gestapelt", "[layout][column]") { NodeLayout root = makeNode(0.f, 0.f, 1.0f, 1.0f); root.layoutStyle.flexDirection = FlexDirection::Column; root.layoutStyle.justifyContent = JustifyContent::Start; root.children.push_back(makeNode(0.f, 0.f, 1.0f, 0.3f)); root.children.push_back(makeNode(0.f, 0.f, 1.0f, 0.3f)); auto result = compute(root, screen800x600(), 800.f, 600.f); REQUIRE_THAT(result.children[0].self.y, WithinAbs(0.0f, EPS)); REQUIRE_THAT(result.children[1].self.y, WithinAbs(0.3f, EPS)); }