1 /** 2 * Copyright: Enalye 3 * License: Zlib 4 * Authors: Enalye 5 */ 6 module atelier.ui.container.gridcontainer; 7 8 import std.conv : to; 9 import std.algorithm.comparison : max; 10 import atelier.render, atelier.core, atelier.common; 11 import atelier.ui.gui_element; 12 13 /// Grid container. \ 14 /// Align its children left-to-right then top-to-bottom without changing their size. \ 15 /// Resized automatically to fits its children. 16 class GridContainer : GuiElement { 17 protected { 18 Vec2f _spacing = Vec2f.zero; 19 uint _maxElementsPerLine = 4u; 20 } 21 22 @property { 23 /// Space between each child. 24 Vec2f spacing() const { 25 return _spacing; 26 } 27 /// Ditto 28 Vec2f spacing(Vec2f newPadding) { 29 _spacing = newPadding; 30 resize(); 31 return _spacing; 32 } 33 34 /// The number of children per line. 35 uint maxElementsPerLine() const { 36 return _maxElementsPerLine; 37 } 38 /// Ditto 39 uint maxElementsPerLine(uint maxElementsPerLine_) { 40 _maxElementsPerLine = maxElementsPerLine_; 41 resize(); 42 return _maxElementsPerLine; 43 } 44 } 45 46 /// Ctor 47 this() { 48 } 49 50 override void appendChild(GuiElement gui) { 51 gui.setAlign(GuiAlignX.left, GuiAlignY.top); 52 super.appendChild(gui); 53 resize(); 54 } 55 56 override void update(float deltatime) { 57 resize(); 58 } 59 60 override void onSize() { 61 resize(); 62 } 63 64 private bool _isResizeCalled; 65 protected void resize() { 66 if (_isResizeCalled) 67 return; 68 _isResizeCalled = true; 69 70 if (!_children.length) { 71 size = Vec2f.zero; 72 _isResizeCalled = false; 73 return; 74 } 75 Vec2f[] lineSizes; 76 uint xCount, i; 77 Vec2f lineSize = Vec2f.zero, totalSize = Vec2f.zero; 78 foreach (GuiElement gui; _children) { 79 lineSize.x += gui.scaledSize.x + _spacing.x; 80 lineSize.y = max(lineSize.y, gui.scaledSize.y); 81 xCount++; 82 i++; 83 if (xCount == _maxElementsPerLine || i == _children.length) { 84 lineSizes ~= lineSize; 85 totalSize.x = max(totalSize.x, lineSize.x); 86 totalSize.y += lineSize.y + _spacing.y; 87 lineSize = Vec2f.zero; 88 xCount = 0u; 89 } 90 } 91 size = totalSize + _spacing; 92 Vec2f currentPosition = _spacing; 93 xCount = 0u; 94 uint yCount; 95 foreach (GuiElement gui; _children) { 96 gui.setAlign(GuiAlignX.left, GuiAlignY.top); 97 gui.position = currentPosition; 98 currentPosition += Vec2f(gui.scaledSize.x + _spacing.x, 0f); 99 xCount++; 100 if (xCount == _maxElementsPerLine) { 101 currentPosition.x = _spacing.x; 102 currentPosition.y += lineSizes[yCount].y + _spacing.y; 103 yCount++; 104 xCount = 0u; 105 } 106 } 107 _isResizeCalled = false; 108 } 109 }