]> git.localhorst.tv Git - blobs.git/blob - src/ui/widgets.cpp
cleaned up ui a little
[blobs.git] / src / ui / widgets.cpp
1 #include "Label.hpp"
2 #include "Panel.hpp"
3 #include "Widget.hpp"
4
5 #include "../app/Assets.hpp"
6 #include "../graphics/Font.hpp"
7 #include "../graphics/Viewport.hpp"
8
9 #include <glm/gtx/transform.hpp>
10
11
12 namespace blobs {
13 namespace ui {
14
15 Label::Label(const graphics::Font &f)
16 : font(&f)
17 , text()
18 , tex()
19 , fg_color(0.0f, 0.0f, 0.0f, 1.0f)
20 , bg_color(0.0f, 0.0f, 0.0f, 0.0f)
21 , dirty(true) {
22 }
23
24 Label::~Label() {
25 }
26
27 Label &Label::Text(const std::string &t) {
28         if (text != t) {
29                 dirty = true;
30         }
31         text = t;
32         return *this;
33 }
34
35 Label &Label::Font(const graphics::Font &f) {
36         if (font != &f) {
37                 dirty = true;
38         }
39         font = &f;
40         return *this;
41 }
42
43 Label &Label::Foreground(const glm::vec4 &c) {
44         fg_color = c;
45         return *this;
46 }
47
48 Label &Label::Background(const glm::vec4 &c) {
49         bg_color = c;
50         return *this;
51 }
52
53 glm::vec2 Label::Size() {
54         if (text.empty()) {
55                 return glm::vec2(0.0f);
56         }
57         Update();
58         return tex.Size();
59 }
60
61 void Label::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
62         Update();
63         glm::vec2 size = Size();
64
65         assets.shaders.alpha_sprite.Activate();
66         assets.shaders.alpha_sprite.SetM(glm::translate(AlignedPosition())
67                 * glm::scale(glm::vec3(size.x, size.y, 1.0f)));
68         assets.shaders.alpha_sprite.SetTexture(tex);
69         assets.shaders.alpha_sprite.SetFgColor(fg_color);
70         assets.shaders.alpha_sprite.SetBgColor(bg_color);
71         assets.shaders.alpha_sprite.DrawRect();
72 }
73
74 void Label::Update() {
75         if (!dirty) return;
76         font->Render(text, tex);
77         dirty = false;
78 }
79
80
81 Panel::Panel()
82 : widgets()
83 , bg_color(0.0f, 0.0f, 0.0f, 0.0f)
84 , padding(0.0f)
85 , spacing(0.0f)
86 , dir(VERTICAL)
87 , size(0.0f, 0.0f) {
88 }
89
90 Panel::~Panel() {
91 }
92
93 Panel &Panel::Add(Widget *w) {
94         std::unique_ptr<Widget> widget(w);
95         glm::vec2 wsize = widget->Size();
96         if (dir == HORIZONTAL) {
97                 size.x += wsize.x;
98                 size.y = std::max(size.y, wsize.y);
99         } else {
100                 size.x = std::max(size.x, wsize.x);
101                 size.y += wsize.y;
102         }
103         widgets.emplace_back(std::move(widget));
104         return *this;
105 }
106
107 Panel &Panel::Background(const glm::vec4 &c) {
108         bg_color = c;
109         return *this;
110 }
111
112 Panel &Panel::Padding(const glm::vec2 &p) {
113         padding = p;
114         return *this;
115 }
116
117 Panel &Panel::Spacing(float s) {
118         spacing = s;
119         return *this;
120 }
121
122 Panel &Panel::Direction(Dir d) {
123         dir = d;
124         Relayout();
125         return *this;
126 }
127
128 glm::vec2 Panel::Size() {
129         return 2.0f * padding + glm::vec2(0.0f, (widgets.size() - 1) * spacing) + size;
130 }
131
132 void Panel::Relayout() {
133         size = glm::vec2(0.0f);
134         if (dir == HORIZONTAL) {
135                 for (auto &w : widgets) {
136                         glm::vec2 wsize = w->Size();
137                         size.x += wsize.x;
138                         size.y = std::max(size.y, wsize.y);
139                 }
140         } else {
141                 for (auto &w : widgets) {
142                         glm::vec2 wsize = w->Size();
143                         size.x = std::max(size.x, wsize.x);
144                         size.y += wsize.y;
145                 }
146         }
147 }
148
149 void Panel::Draw(app::Assets &assets, graphics::Viewport &viewport) noexcept {
150         if (bg_color.a > 0.0f) {
151                 glm::vec2 fullsize = Size();
152                 assets.shaders.plain_color.Activate();
153                 assets.shaders.plain_color.SetM(glm::translate(AlignedPosition())
154                         * glm::scale(glm::vec3(fullsize.x, fullsize.y, 1.0f)));
155                 assets.shaders.plain_color.SetColor(bg_color);
156                 assets.shaders.plain_color.DrawRect();
157         }
158
159         glm::vec3 cursor = TopLeft();
160         cursor.x += padding.x;
161         cursor.y += padding.y;
162         cursor.z -= 1.0f;
163         for (auto &w : widgets) {
164                 w->Position(cursor).Origin(Gravity::NORTH_WEST);
165                 w->Draw(assets, viewport);
166                 cursor[dir] += w->Size()[dir] + spacing;
167         }
168 }
169
170
171 Widget::Widget()
172 : pos(0.0f)
173 , origin(Gravity::CENTER) {
174 }
175
176 Widget::~Widget() {
177 }
178
179 glm::vec3 Widget::AlignedPosition() noexcept {
180         return align(origin, Size(), pos);
181 }
182
183 glm::vec3 Widget::TopLeft() noexcept {
184         glm::vec2 size = Size();
185         return align(origin, size, pos) - glm::vec3(size * 0.5f, 0.0f);
186 }
187
188 }
189 }