1 /** 
2  * Copyright: Enalye
3  * License: Zlib
4  * Authors: Enalye
5  */
6 module atelier.ui.container.vcontainer;
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 /// Vertical container. \
14 /// Align its children vertically without changing their size. \
15 /// Resized automatically to fits its children.
16 class VContainer : GuiElement {
17     protected {
18         Vec2f _spacing = Vec2f.zero;
19         GuiAlignX _childAlignX = GuiAlignX.center;
20         float _minimalWidth = 0f;
21     }
22 
23     @property {
24         Vec2f spacing() const {
25             return _spacing;
26         }
27 
28         Vec2f spacing(Vec2f newPadding) {
29             _spacing = newPadding;
30             resize();
31             return _spacing;
32         }
33 
34         float minimalWidth() const {
35             return _minimalWidth;
36         }
37 
38         float minimalWidth(float newMinimalWidth) {
39             _minimalWidth = newMinimalWidth;
40             resize();
41             return _minimalWidth;
42         }
43     }
44 
45     /// Ctor
46     this() {
47     }
48 
49     override void appendChild(GuiElement gui) {
50         gui.setAlign(_childAlignX, GuiAlignY.top);
51         super.appendChild(gui);
52         resize();
53     }
54 
55     void setChildAlign(GuiAlignX childAlignX) {
56         _childAlignX = childAlignX;
57         resize();
58     }
59 
60     override void update(float deltatime) {
61         resize();
62     }
63 
64     override void onSize() {
65         resize();
66     }
67 
68     private bool _isResizeCalled;
69     protected void resize() {
70         if (_isResizeCalled)
71             return;
72         _isResizeCalled = true;
73 
74         if (!_children.length) {
75             size = Vec2f.zero;
76             _isResizeCalled = false;
77             return;
78         }
79 
80         Vec2f totalSize = Vec2f(_minimalWidth, 0f);
81         foreach (GuiElement gui; _children) {
82             totalSize.y += gui.scaledSize.y + _spacing.y;
83             totalSize.x = max(totalSize.x, gui.scaledSize.x);
84         }
85         size = totalSize + Vec2f(_spacing.x * 2f, _spacing.y);
86         Vec2f currentPosition = _spacing;
87         foreach (GuiElement gui; _children) {
88             gui.setAlign(_childAlignX, GuiAlignY.top);
89             gui.position = currentPosition;
90             currentPosition = currentPosition + Vec2f(0f, gui.scaledSize.y + _spacing.y);
91         }
92         _isResizeCalled = false;
93     }
94 }