10static int roundi(
float v)
12 return (
int)floorf(v + 0.5f);
15GuiLayout::GuiLayout() :
17 userFixedW(0), userFixedH(0), assignedW(0), assignedH(0), naturalW(0), naturalH(0), dirty(true), settled(false)
30 entries.push_back(en);
39 entries.push_back(en);
48 entries.push_back(en);
60 return setPadding(horizontal, vertical, horizontal, vertical);
65 padding = GuiInsets(left, top, right, bottom);
99 userFixedW = w < 0 ? 0 : w;
100 userFixedH = h < 0 ? 0 : h;
120 for(
size_t i = 0; i < entries.size(); i++)
122 if(entries[i].e == e)
124 entries.erase(entries.begin() + i);
133void GuiLayout::syncEntries()
139 for(
const Entry& en : entries)
153 for(
size_t i = 0; i < entries.size();)
155 if(entries[i].e && !this->
find(entries[i].e))
156 entries.erase(entries.begin() + i), dirty =
true;
163 for(
const Entry& en : entries)
164 if(en.e == child) { known =
true;
break; }
169 entries.push_back(en);
180 for(
Entry& en : entries)
185 std::vector<Entry*>&
visible = visibleScratch;
187 bool changed = dirty;
188 for(
Entry& en : entries)
190 const bool shown = !en.e || en.e->isVisible();
191 if(shown != en.lastVisible)
194 en.lastVisible = shown;
202 en.e->getNaturalSize(w, h);
203 if(en.haveAssigned && w == en.assignedW && h == en.assignedH)
213 en.haveAssigned =
false;
215 if(w != en.lastW || h != en.lastH)
231 naturalW = roundi(fit.width);
232 naturalH = roundi(fit.height);
235 if(assignedW > 0 || assignedH > 0)
236 res = this->
solve(visible, (
float)(assignedW > 0 ? assignedW : userFixedW), (
float)(assignedH > 0 ? assignedH : userFixedH));
237 width = roundi(res.width);
238 height = roundi(res.height);
240 for(
size_t i = 0; i <
visible.size() && i < res.rects.size(); i++)
246 const GuiRect& r = res.rects[i];
247 const int w = roundi(r.
w), h = roundi(r.
h);
248 if(w != en.natW || h != en.
natH)
253 en.haveAssigned =
true;
256 else if(en.haveAssigned)
259 en.haveAssigned =
false;
296 assignedW = w < 0 ? 0 : w;
297 assignedH = h < 0 ? 0 : h;
308 child->collectNavigable(out);
320 spec.padding = padding;
322 spec.fixedW = fixedW;
324 spec.justify = justify;
325 spec.alignItems = alignItems;
327 std::vector<GuiStackItem> items(
visible.size());
328 for(
size_t i = 0; i <
visible.size(); i++)
331 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
333 items[i].grow = en.item.growWeight;
334 items[i].useContainerAlign = !en.item.hasAlignV;
335 items[i].align = en.item.alignV;
349 spec.padding = padding;
351 spec.fixedW = fixedW;
353 spec.justify = justify;
354 spec.alignItems = alignItems;
356 std::vector<GuiStackItem> items(
visible.size());
357 for(
size_t i = 0; i <
visible.size(); i++)
360 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
362 items[i].grow = en.item.growWeight;
363 items[i].useContainerAlign = !en.item.hasAlignH;
364 items[i].align = en.item.alignH;
377 spec.columns = columns;
378 spec.padding = padding;
379 spec.spacingX = spacingX;
380 spec.spacingY = spacingY;
381 spec.fixedW = fixedW;
384 std::vector<GuiGridItem> items(
visible.size());
385 for(
size_t i = 0; i <
visible.size(); i++)
388 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
389 else items[i].w = items[i].h = en.
gapSize;
390 if(en.item.hasAlignH) items[i].alignH = en.item.alignH;
391 if(en.item.hasAlignV) items[i].alignV = en.item.alignV;
404 spec.padding = padding;
405 spec.fixedW = fixedW;
408 std::vector<GuiOverlayItem> items;
409 for(
size_t i = 0; i <
visible.size(); i++)
413 it.w = (float)en.natW;
414 it.h = (float)en.
natH;
416 if(en.item.hasAlignH) it.alignH = en.item.alignH;
417 if(en.item.hasAlignV) it.alignV = en.item.alignV;
Umbrella header for the platform-agnostic libgui core.
GuiColumn(int w=0, int h=0)
GuiLayoutResult solve(const std::vector< Entry * > &visible, float fixedW, float fixedH) override
Works out the container size and each visible entry's rectangle (what a subclass does)
bool isVisible()
Checks whether or not the element is visible.
int height
Element height.
bool visible
Visibility of the element.
virtual void layout()
Brings the element's own layout up to date.
virtual void setLayoutPosition(int x, int y)
Places the element so its top-left corner is at (x, y) relative to its parent's top-left (default: LE...
virtual void setLayoutSize(int w, int h)
Gives the element a size chosen by a container (default: sets width and height)
GuiLayoutResult solve(const std::vector< Entry * > &visible, float fixedW, float fixedH) override
Works out the container size and each visible entry's rectangle (what a subclass does)
GuiGrid(int columns, int w=0, int h=0)
Base of the layout containers. Not used directly; see GuiRow, GuiColumn, GuiGrid, GuiOverlay.
void clear()
Removes every child.
void remove(GuiElement *e) override
Removes the specified child.
GuiLayout & add(GuiElement *e, const GuiItem &item=GuiItem())
Adds a child. Children are laid out in the order they are added.
void collectNavigable(std::vector< GuiElement * > &out) override
Appends the elements that selection can move between (default: this element; layout containers add th...
GuiLayout & size(int w, int h)
Short names for the setters above, for reading a layout top to bottom: ui.row().size(568,...
void layout() override
Brings the element's own layout up to date.
GuiLayout & addSpace(float weight=1.0f)
Adds flexible empty space that takes a share of what is left over, for example to push one child to e...
GuiLayout & setFixedSize(int w, int h)
Fixes the container's size (0 on an axis = fit the content)
GuiLayout & setSpacing(float s)
Sets the gap between neighbouring children (a grid uses both numbers)
void getNaturalSize(int &w, int &h) override
Layout protocol: how a layout container (GuiRow, GuiColumn, GuiGrid, GuiOverlay) asks about and arran...
GuiLayout & setAlignItems(LAYOUT_ALIGN a)
Sets the default alignment of children across the main axis.
void update(InputController *c) override
Called constantly to allow the element to respond to the current input data.
void draw() override
Called constantly to redraw the element.
void invalidate()
Forces layout to run again.
GuiLayout & addGap(float size)
Adds a fixed gap along a row's width or a column's height.
GuiLayout & setPadding(float all)
Sets the space between the container's edge and its children.
virtual GuiLayoutResult solve(const std::vector< Entry * > &visible, float fixedW, float fixedH)=0
Works out the container size and each visible entry's rectangle (what a subclass does)
GuiLayout & setJustify(LAYOUT_JUSTIFY j)
Sets how leftover space along the main axis is spent when no child grows.
void setLayoutSize(int w, int h) override
Gives the element a size chosen by a container (default: sets width and height)
GuiOverlay(int w=0, int h=0)
GuiLayoutResult solve(const std::vector< Entry * > &visible, float fixedW, float fixedH) override
Works out the container size and each visible entry's rectangle (what a subclass does)
GuiLayoutResult solve(const std::vector< Entry * > &visible, float fixedW, float fixedH) override
Works out the container size and each visible entry's rectangle (what a subclass does)
void append(GuiElement *e)
Appends a GuiElement to the GuiWindow.
bool find(GuiElement *e)
Looks for the specified GuiElement.
void removeAll()
Removes all GuiElements.
void draw()
Draws all the elements in this GuiWindow.
void update(InputController *c)
Updates the window and all elements contains within Allows the GuiWindow and all elements to respond ...
void remove(GuiElement *e)
Removes the specified GuiElement from the GuiWindow.
std::vector< GuiElement * > _elements
Contains all elements within the GuiWindow.
LAYOUT_ALIGN
How an item sits across the main direction of a stack, or inside a grid cell.
GuiLayoutResult GuiSolveGrid(const GuiGridSpec &spec, const std::vector< GuiGridItem > &items)
Lays items out in rows.
GuiLayoutResult GuiSolveStack(const GuiStackSpec &spec, const std::vector< GuiStackItem > &items)
Lays items out along one axis.
GuiLayoutResult GuiSolveOverlay(const GuiOverlaySpec &spec, const std::vector< GuiOverlayItem > &items)
Stacks items on top of each other in one box.
LAYOUT_JUSTIFY
How leftover space along a stack's main direction is spent (when no item grows).
Rules for a grid, filled row by row.
float fixedH
Container size; 0 = fit.
The solver's answer: the container's size and each item's rectangle.
A child (or gap) and what layout knows about it.
int natH
Natural size, as measured this pass.
int baseH
Natural size before layout resized it.
int assignedH
Size layout last gave it.
float gapSize
Fixed size of a gap.
GuiElement * e
The child; null for a gap or flexible space.
bool background
Fills the whole box, ignores padding, and does not count toward the fit size.
Rules for an overlay: children share one box.
float fixedH
Container size; 0 = fit.
An axis-aligned rectangle (top-left origin) in design-canvas pixels.
Rules for a row or column.
float spacing
Gap between neighbouring items.
bool vertical
true = column, false = row.
float fixedH
Container size; 0 = fit.