32 float cachedWidth = 0;
33 float cachedHeight = 0;
34 float explicitWidth = 0;
35 float explicitHeight = 0;
37 std::vector<Widget*> children;
44 float paddingLeft = 8.0f;
45 float paddingRight = 8.0f;
46 float paddingTop = 8.0f;
47 float paddingBottom = 8.0f;
49 sf::Color backgroundColor = sf::Color(0, 0, 0, 0);
50 sf::RectangleShape backgroundShape;
54 static std::string normalize(std::string value) {
55 std::transform(value.begin(), value.end(), value.begin(),
56 [](
unsigned char c) { return static_cast<char>(std::tolower(c)); });
60 static StackJustify parseJustifyOrFallback(
const std::string& value) {
61 const std::string normalized = normalize(value);
67 std::cerr <<
"[Velvet][Stack] Unsupported justify value: '" << value
68 <<
"'. Falling back to 'start'.\n";
72 static StackAlign parseAlignOrFallback(
const std::string& value) {
73 const std::string normalized = normalize(value);
79 std::cerr <<
"\033[33mWarning: Invalid style property: '" << value <<
"'\033[0m" << std::endl;
83 void draw(sf::RenderWindow& window)
override {
84 if (backgroundColor.a > 0) {
85 window.draw(backgroundShape);
87 for (
Widget* child : children) {
88 child->render(window);
92 void update(sf::RenderWindow& window)
override {
94 recalculateChildPositions();
100 float getContentMainSize() {
101 if (children.empty())
return 0;
104 for (
Widget* child : children) {
105 const sf::Vector2f dims = child->getDimensions();
109 total += gap *
static_cast<float>(children.size() - 1);
113 void recalculateCachedDimensions() {
117 for (
Widget* child : children) {
118 const sf::Vector2f dims = child->getDimensions();
120 cachedWidth += dims.x;
121 cachedHeight = std::max(cachedHeight, dims.y);
123 cachedHeight += dims.y;
124 cachedWidth = std::max(cachedWidth, dims.x);
128 if (!children.empty()) {
130 cachedWidth += gap *
static_cast<float>(children.size() - 1);
132 cachedHeight += gap *
static_cast<float>(children.size() - 1);
136 float calculateStartOffset(
float available,
float content)
const {
137 if (available <= content)
return 0;
139 const float remaining = available - content;
146 float calculateCrossOffset(
float available,
float content)
const {
147 if (available <= content)
return 0;
149 const float remaining = available - content;
156 void recalculateChildPositions() {
157 recalculateCachedDimensions();
159 const float contentMain = getContentMainSize();
160 const float availableMain =
162 const float startMain = calculateStartOffset(availableMain, contentMain);
165 ? xPos + paddingLeft + startMain
166 : yPos + paddingTop + startMain;
168 for (
Widget* child : children) {
169 const sf::Vector2f dims = child->getDimensions();
172 const float crossOffset = calculateCrossOffset(explicitHeight, dims.y);
173 child->setPosition(pos, yPos + paddingTop + crossOffset);
176 const float crossOffset = calculateCrossOffset(explicitWidth, dims.x);
177 child->setPosition(xPos + paddingLeft + crossOffset, pos);
182 const float totalWidth = std::max(cachedWidth, explicitWidth) + paddingLeft + paddingRight;
183 const float totalHeight = std::max(cachedHeight, explicitHeight) + paddingTop + paddingBottom;
184 backgroundShape.setPosition(xPos, yPos);
185 backgroundShape.setSize(sf::Vector2f(totalWidth, totalHeight));
186 backgroundShape.setFillColor(backgroundColor);
198 void render(sf::RenderWindow& window)
override {
209 children.push_back(widget);
216 template<
typename... Ts>
217 void add(Ts&&... widgets) {
218 (add_widget(std::forward<Ts>(widgets)), ...);
230 if (xPos !=
x || yPos !=
y) {
242 std::max(cachedWidth, explicitWidth) + paddingLeft + paddingRight,
243 std::max(cachedHeight, explicitHeight) + paddingTop + paddingBottom
250 void handleEvent(
const sf::Event& event, sf::RenderWindow &window)
override {
251 for (
Widget* child : children) {
252 child->handleEvent(event, window);
275 if (justify != value) {
292 if (align != value) {
309 if (explicitWidth != width || explicitHeight != height) {
310 explicitWidth = width;
311 explicitHeight = height;
320 if (explicitWidth != width) {
321 explicitWidth = width;
330 if (explicitHeight != height) {
331 explicitHeight = height;
352 paddingLeft = horizontal;
353 paddingRight = horizontal;
355 paddingTop = vertical;
356 paddingBottom = vertical;
368 void setPadding(
float left,
float right,
float top,
float bottom) {
370 paddingRight = right;
372 paddingBottom = bottom;
381 if (backgroundColor.r != color.r || backgroundColor.g != color.g ||
382 backgroundColor.b != color.b || backgroundColor.a != color.a) {
383 backgroundColor = color;
384 backgroundShape.setFillColor(backgroundColor);
void setPadding(float left, float right, float top, float bottom)
Set side-specific padding.
Definition Stack.hpp:368