mirror of
https://github.com/daveallie/crosspoint-reader.git
synced 2026-02-05 07:07:38 +03:00
feat: add valign and halign to stack elements
This commit is contained in:
parent
5e9e53cc13
commit
999e60b75e
@ -12,9 +12,13 @@ namespace ThemeEngine {
|
|||||||
// --- HStack: Horizontal Stack Layout ---
|
// --- HStack: Horizontal Stack Layout ---
|
||||||
// Children are arranged horizontally with optional spacing
|
// Children are arranged horizontally with optional spacing
|
||||||
class HStack : public Container {
|
class HStack : public Container {
|
||||||
|
public:
|
||||||
|
enum class VAlign { Top, Center, Bottom };
|
||||||
|
|
||||||
|
private:
|
||||||
int spacing = 0; // Gap between children
|
int spacing = 0; // Gap between children
|
||||||
int padding = 0; // Internal padding
|
int padding = 0; // Internal padding
|
||||||
bool centerVertical = false;
|
VAlign vAlign = VAlign::Top;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HStack(const std::string& id) : Container(id) {}
|
HStack(const std::string& id) : Container(id) {}
|
||||||
@ -29,8 +33,18 @@ class HStack : public Container {
|
|||||||
padding = p;
|
padding = p;
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
void setCenterVertical(bool c) {
|
void setVAlign(VAlign a) {
|
||||||
centerVertical = c;
|
vAlign = a;
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
void setVAlignFromString(const std::string& s) {
|
||||||
|
if (s == "center" || s == "Center") {
|
||||||
|
vAlign = VAlign::Center;
|
||||||
|
} else if (s == "bottom" || s == "Bottom") {
|
||||||
|
vAlign = VAlign::Bottom;
|
||||||
|
} else {
|
||||||
|
vAlign = VAlign::Top;
|
||||||
|
}
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,12 +62,29 @@ class HStack : public Container {
|
|||||||
int childW = child->getAbsW();
|
int childW = child->getAbsW();
|
||||||
int childH = child->getAbsH();
|
int childH = child->getAbsH();
|
||||||
|
|
||||||
// Re-layout with proper position
|
// Extract child's own Y offset (from first layout pass)
|
||||||
|
int childYOffset = child->getAbsY() - (absY + padding);
|
||||||
|
|
||||||
|
// Calculate base position based on vertical alignment
|
||||||
int childY = absY + padding;
|
int childY = absY + padding;
|
||||||
if (centerVertical && childH < availableH) {
|
if (childH < availableH) {
|
||||||
childY = absY + padding + (availableH - childH) / 2;
|
switch (vAlign) {
|
||||||
|
case VAlign::Center:
|
||||||
|
childY = absY + padding + (availableH - childH) / 2;
|
||||||
|
break;
|
||||||
|
case VAlign::Bottom:
|
||||||
|
childY = absY + padding + (availableH - childH);
|
||||||
|
break;
|
||||||
|
case VAlign::Top:
|
||||||
|
default:
|
||||||
|
childY = absY + padding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add child's own Y offset to the calculated position
|
||||||
|
childY += childYOffset;
|
||||||
|
|
||||||
child->layout(context, currentX, childY, childW, childH);
|
child->layout(context, currentX, childY, childW, childH);
|
||||||
currentX += childW + spacing;
|
currentX += childW + spacing;
|
||||||
availableW -= (childW + spacing);
|
availableW -= (childW + spacing);
|
||||||
@ -65,9 +96,13 @@ class HStack : public Container {
|
|||||||
// --- VStack: Vertical Stack Layout ---
|
// --- VStack: Vertical Stack Layout ---
|
||||||
// Children are arranged vertically with optional spacing
|
// Children are arranged vertically with optional spacing
|
||||||
class VStack : public Container {
|
class VStack : public Container {
|
||||||
|
public:
|
||||||
|
enum class HAlign { Left, Center, Right };
|
||||||
|
|
||||||
|
private:
|
||||||
int spacing = 0;
|
int spacing = 0;
|
||||||
int padding = 0;
|
int padding = 0;
|
||||||
bool centerHorizontal = false;
|
HAlign hAlign = HAlign::Left;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VStack(const std::string& id) : Container(id) {}
|
VStack(const std::string& id) : Container(id) {}
|
||||||
@ -82,8 +117,18 @@ class VStack : public Container {
|
|||||||
padding = p;
|
padding = p;
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
void setCenterHorizontal(bool c) {
|
void setHAlign(HAlign a) {
|
||||||
centerHorizontal = c;
|
hAlign = a;
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
void setHAlignFromString(const std::string& s) {
|
||||||
|
if (s == "center" || s == "Center") {
|
||||||
|
hAlign = HAlign::Center;
|
||||||
|
} else if (s == "right" || s == "Right") {
|
||||||
|
hAlign = HAlign::Right;
|
||||||
|
} else {
|
||||||
|
hAlign = HAlign::Left;
|
||||||
|
}
|
||||||
markDirty();
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +145,29 @@ class VStack : public Container {
|
|||||||
int childW = child->getAbsW();
|
int childW = child->getAbsW();
|
||||||
int childH = child->getAbsH();
|
int childH = child->getAbsH();
|
||||||
|
|
||||||
|
// Extract child's own X offset (from first layout pass)
|
||||||
|
int childXOffset = child->getAbsX() - (absX + padding);
|
||||||
|
|
||||||
|
// Calculate base position based on horizontal alignment
|
||||||
int childX = absX + padding;
|
int childX = absX + padding;
|
||||||
if (centerHorizontal && childW < availableW) {
|
if (childW < availableW) {
|
||||||
childX = absX + padding + (availableW - childW) / 2;
|
switch (hAlign) {
|
||||||
|
case HAlign::Center:
|
||||||
|
childX = absX + padding + (availableW - childW) / 2;
|
||||||
|
break;
|
||||||
|
case HAlign::Right:
|
||||||
|
childX = absX + padding + (availableW - childW);
|
||||||
|
break;
|
||||||
|
case HAlign::Left:
|
||||||
|
default:
|
||||||
|
childX = absX + padding;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add child's own X offset to the calculated position
|
||||||
|
childX += childXOffset;
|
||||||
|
|
||||||
child->layout(context, childX, currentY, childW, childH);
|
child->layout(context, childX, currentY, childW, childH);
|
||||||
currentY += childH + spacing;
|
currentY += childH + spacing;
|
||||||
availableH -= (childH + spacing);
|
availableH -= (childH + spacing);
|
||||||
|
|||||||
@ -382,8 +382,8 @@ void List::draw(const GfxRenderer& renderer, const ThemeContext& context) {
|
|||||||
int currentX = absX;
|
int currentX = absX;
|
||||||
int currentY = absY;
|
int currentY = absY;
|
||||||
|
|
||||||
// For grid, calculate item width based on columns
|
// For grid, calculate item width based on columns only if not explicitly set
|
||||||
if (layoutMode == LayoutMode::Grid && columns > 1) {
|
if (layoutMode == LayoutMode::Grid && columns > 1 && itemWidth == 0) {
|
||||||
int totalSpacing = (columns - 1) * spacing;
|
int totalSpacing = (columns - 1) * spacing;
|
||||||
itemW = (absW - totalSpacing) / columns;
|
itemW = (absW - totalSpacing) / columns;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,13 +144,13 @@ void ThemeManager::applyProperties(UIElement* elem, const std::map<std::string,
|
|||||||
} else if (elemType == UIElement::ElementType::List) {
|
} else if (elemType == UIElement::ElementType::List) {
|
||||||
static_cast<List*>(elem)->setSpacing(parseIntSafe(val));
|
static_cast<List*>(elem)->setSpacing(parseIntSafe(val));
|
||||||
}
|
}
|
||||||
} else if (key == "CenterVertical") {
|
} else if (key == "VAlign") {
|
||||||
if (elemType == UIElement::ElementType::HStack) {
|
if (elemType == UIElement::ElementType::HStack) {
|
||||||
static_cast<HStack*>(elem)->setCenterVertical(val == "true" || val == "1");
|
static_cast<HStack*>(elem)->setVAlignFromString(val);
|
||||||
}
|
}
|
||||||
} else if (key == "CenterHorizontal") {
|
} else if (key == "HAlign") {
|
||||||
if (elemType == UIElement::ElementType::VStack) {
|
if (elemType == UIElement::ElementType::VStack) {
|
||||||
static_cast<VStack*>(elem)->setCenterHorizontal(val == "true" || val == "1");
|
static_cast<VStack*>(elem)->setHAlignFromString(val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user