1 /**
2     Log list
3 
4     Copyright: (c) Enalye 2017
5     License: Zlib
6     Authors: Enalye
7 */
8 
9 module atelier.ui.list.loglist;
10 
11 import std.conv : to;
12 import atelier.core, atelier.render, atelier.common;
13 import atelier.ui.gui_element, atelier.ui.layout, atelier.ui.slider;
14 
15 private class LogContainer : GuiElement {
16     public {
17         LogLayout layout;
18     }
19 
20     this(Vec2f newSize) {
21         isLocked = true;
22         layout = new LogLayout;
23         size(newSize);
24         appendChild(layout);
25         hasCanvas(true);
26     }
27 
28     override void draw() {
29         layout.draw();
30     }
31 }
32 
33 class LogList : GuiElement {
34     protected {
35         LogContainer _container;
36         Slider _slider;
37         Vec2f _lastMousePos = Vec2f.zero;
38         uint _idElementSelected = 0u;
39     }
40 
41     @property {
42         uint selected() const {
43             return _idElementSelected;
44         }
45 
46         /// The list of all its children.
47         override const(GuiElement[]) children() const {
48             return _container.layout.children;
49         }
50         /// Ditto
51         override GuiElement[] children() {
52             return _container.layout.children;
53         }
54 
55         /// Return the first child gui.
56         override GuiElement firstChild() {
57             return _container.layout.firstChild;
58         }
59 
60         /// Return the last child gui.
61         override GuiElement lastChild() {
62             return _container.layout.lastChild;
63         }
64 
65         /// The number of children it currently has.
66         override size_t childCount() const {
67             return _container.layout.childCount;
68         }
69     }
70 
71     this(Vec2f newSize) {
72         isLocked = true;
73         _slider = new VScrollbar;
74         _slider.value01 = 1f;
75         _container = new LogContainer(newSize);
76 
77         super.appendChild(_slider);
78         super.appendChild(_container);
79 
80         size(newSize);
81         position(Vec2f.zero);
82     }
83 
84     override void onEvent(Event event) {
85         super.onEvent(event);
86         if (event.type == Event.Type.mouseDown || event.type == Event.Type.mouseUp
87                 || event.type == Event.Type.mouseUpdate) {
88             _lastMousePos = event.mouse.position;
89             if (_slider.isInside(event.mouse.position))
90                 _slider.onEvent(event);
91             else if (event.type == Event.Type.mouseDown) {
92                 auto widgets = _container.layout.children;
93                 foreach (size_t id, const GuiElement widget; widgets) {
94                     if (widget.isHovered)
95                         _idElementSelected = cast(uint) id;
96                 }
97             }
98         }
99         if (!isOnInteractableGuiElement(_lastMousePos) && event.type == Event.Type.mouseWheel)
100             _slider.onEvent(event);
101     }
102 
103     override void onPosition() {
104         _slider.position = center - Vec2f((size.x - _slider.size.x) / 2f, 0f) + size / 2f;
105         _container.position = center + Vec2f(_slider.size.x / 2f, 0f) + size / 2f;
106     }
107 
108     override void onSize() {
109         _slider.size = Vec2f(10f, size.y);
110         _container.size = Vec2f(size.x - _slider.size.x, size.y);
111         _container.canvas.renderSize = _container.size.to!Vec2i;
112         onPosition();
113     }
114 
115     override void update(float deltaTime) {
116         _slider.update(deltaTime);
117         float min = _container.canvas.size.y / 2f;
118         float max = _container.layout.size.y - _container.canvas.size.y / 2f;
119         float exceedingHeight = _container.layout.size.y - _container.canvas.size.y;
120 
121         if (exceedingHeight < 0f) {
122             _slider.max = 0;
123             _slider.step = 0;
124         }
125         else {
126             _slider.max = exceedingHeight / (_container.canvas.size.y / 50f);
127             _slider.step = to!uint(_slider.max);
128         }
129         _container.canvas.position = Vec2f(0f, lerp(min, max, _slider.offset));
130     }
131 
132     private void repositionContainer() {
133         _container.layout.position = Vec2f(5f + _container.layout.size.x / 2f - _container.size.x / 2f,
134                 _container.layout.size.y / 2f);
135     }
136 
137     override void prependChild(GuiElement gui) {
138         _container.layout.prependChild(gui);
139         repositionContainer();
140     }
141 
142     override void appendChild(GuiElement gui) {
143         _container.layout.appendChild(gui);
144         repositionContainer();
145     }
146 
147     override void removeChildren() {
148         _container.layout.removeChildren();
149         repositionContainer();
150     }
151 
152     override void removeChild(size_t id) {
153         _container.layout.removeChild(id);
154         repositionContainer();
155     }
156 
157     override void removeChild(GuiElement gui) {
158         _container.layout.removeChild(gui);
159         repositionContainer();
160     }
161 }