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;
293 assignedW = w < 0 ? 0 : w;
294 assignedH = h < 0 ? 0 : h;
303 child->collectNavigable(out);
315 spec.padding = padding;
317 spec.fixedW = fixedW;
319 spec.justify = justify;
320 spec.alignItems = alignItems;
322 std::vector<GuiStackItem> items(
visible.size());
323 for(
size_t i = 0; i <
visible.size(); i++)
326 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
328 items[i].grow = en.item.growWeight;
329 items[i].useContainerAlign = !en.item.hasAlignV;
330 items[i].align = en.item.alignV;
344 spec.padding = padding;
346 spec.fixedW = fixedW;
348 spec.justify = justify;
349 spec.alignItems = alignItems;
351 std::vector<GuiStackItem> items(
visible.size());
352 for(
size_t i = 0; i <
visible.size(); i++)
355 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
357 items[i].grow = en.item.growWeight;
358 items[i].useContainerAlign = !en.item.hasAlignH;
359 items[i].align = en.item.alignH;
372 spec.columns = columns;
373 spec.padding = padding;
374 spec.spacingX = spacingX;
375 spec.spacingY = spacingY;
376 spec.fixedW = fixedW;
379 std::vector<GuiGridItem> items(
visible.size());
380 for(
size_t i = 0; i <
visible.size(); i++)
383 if(en.
e) { items[i].w = (float)en.natW; items[i].h = (float)en.
natH; }
384 else items[i].w = items[i].h = en.
gapSize;
385 if(en.item.hasAlignH) items[i].alignH = en.item.alignH;
386 if(en.item.hasAlignV) items[i].alignV = en.item.alignV;
399 spec.padding = padding;
400 spec.fixedW = fixedW;
403 std::vector<GuiOverlayItem> items;
404 for(
size_t i = 0; i <
visible.size(); i++)
408 it.w = (float)en.natW;
409 it.h = (float)en.
natH;
411 if(en.item.hasAlignH) it.alignH = en.item.alignH;
412 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)
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.