Symphony Of Empires
widget.hpp
Go to the documentation of this file.
1 // Symphony of Empires
2 // Copyright (C) 2021, Symphony of Empires contributors
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <https://www.gnu.org/licenses/>.
16 //
17 // ----------------------------------------------------------------------------
18 // Name:
19 // eng3d/ui/widget.hpp
20 //
21 // Abstract:
22 // Declares the base widget class for other widgets to derive from
23 // do not use this widget directly, instead use one of the many derivates
24 // unless you're making a new widget type.
25 // ----------------------------------------------------------------------------
26 
27 #pragma once
28 
29 #include <cstddef>
30 #include <deque>
31 #include <functional>
32 #include <vector>
33 #include <string>
34 #include <memory>
35 #include <new>
36 #include <algorithm>
37 
38 #include <glm/vec2.hpp>
39 
40 #include "eng3d/ttf.hpp"
41 #include "eng3d/rectangle.hpp"
42 #include "eng3d/color.hpp"
43 #include "eng3d/utils.hpp"
44 
45 namespace Eng3D {
46  class Texture;
47 }
48 
49 namespace UI {
52  enum class Origin {
53  CENTER,
56  UPPER_LEFT,
59  LOWER_LEFT,
71  };
72 
76  enum class WidgetType {
77  DIV,
78  BUTTON,
79  INPUT,
80  WINDOW,
81  TOOLTIP,
82  LABEL,
83  IMAGE,
84  CHART,
85  CHECKBOX,
86  PIE_CHART,
87  BAR_CHART,
89  SLIDER,
90  GROUP,
91  SCROLLBAR,
92  TABLE,
93  TABLE_ROW,
96  };
97 
100  enum class Flex {
101  NONE,
102  ROW,
103  COLUMN,
104  };
105 
108  enum class FlexJustify {
109  START,
110  END,
112  SPACE_AROUND,
113  };
114 
115  enum class Align {
116  START,
117  END,
118  CENTER,
119  };
120 
121  enum class Overflow {
122  CLAMP,
123  WRAP
124  };
125 
129  class ChartData {
130  public:
131  ChartData(float _num, std::string _info, Eng3D::Color _color)
132  : num{ _num },
133  info{ _info },
134  color{ _color }
135  {
136 
137  }
138  ChartData(float _num, std::string _info, uint32_t rgb)
139  : num{ _num },
140  info{ _info },
141  color{ Eng3D::Color::rgb32(rgb) }
142  {
143 
144  }
145  ~ChartData() = default;
146  float num;
147  std::string info; // Used for tooltips
149  };
150 
153  class Border {
154  public:
155  std::shared_ptr<Eng3D::Texture> texture = nullptr;
156  glm::ivec2 size;
157  glm::ivec2 texture_size;
158  glm::ivec2 offset = glm::ivec2(0, 0);
159 
160  Border() = default;
161  Border(std::shared_ptr<Eng3D::Texture> _texture, glm::ivec2 _size, glm::ivec2 _texture_size, glm::ivec2 _offset = glm::ivec2(0))
162  : texture{ _texture },
163  size{ _size },
164  texture_size{ _texture_size },
165  offset{ _offset }
166  {
167 
168  };
169  };
170 
171  class Context;
172  class Tooltip;
176  class Widget {
177  void recalc_child_pos();
178  void draw_border(Eng3D::Rect viewport);
179 
182  inline void notice_death() {
183  if(!this->dead_child) {
184  this->dead_child = true;
185  if(this->parent)
186  this->parent->notice_death();
187  }
188  }
189 
190  bool need_recalc = false; // Managing widgets outside of window bounds
191  bool is_eval = true; // Determining if evaluable or not
192  std::string text_str;
193  bool is_clickable = false; // Drawing hover effects on clickable child widgets
194  bool dead = false;
195  bool dead_child = false;
196  protected:
197  void draw_rectangle(int x, int y, unsigned w, unsigned h, Eng3D::Rect viewport, const Eng3D::Texture* tex);
198  void draw_rect(const Eng3D::Texture* tex, Eng3D::Rect rect_pos, Eng3D::Rect rect_tex, Eng3D::Rect viewport);
199  bool clickable_effect = true;
200  public:
201  Widget() = default;
202  Widget(Widget* parent, int x, int y, unsigned w, unsigned h, WidgetType type);
203  Widget(Widget* parent, int x, int y, unsigned w, unsigned h, WidgetType type, std::shared_ptr<Eng3D::Texture> tex);
204  Widget(const Widget&) = default;
205  Widget(Widget&&) noexcept = default;
206 #ifndef _MSC_VER // MSVSC hates multiple definitions for movables
207  Widget& operator=(Widget&) noexcept = default;
208 #endif
209  Widget& operator=(const Widget&) = default;
210  virtual ~Widget();
211 
214  constexpr void move_by(const glm::ivec2 offset) {
215  this->x += offset.x;
216  this->y += offset.y;
217  }
218 
219  void add_child(UI::Widget& child);
220 
221  template<typename T, typename ... Targs>
222  T& make_widget(Targs&& ...args)
223  {
224  auto p = new T(std::forward<decltype(args)>(args)..., this);
225  return *p;
226  }
227 
228  virtual void on_render(Context&, Eng3D::Rect viewport);
229  virtual void set_text(const std::string& text);
230  virtual void set_tooltip(UI::Tooltip* tooltip);
231  virtual void set_tooltip(const std::string& text);
232  virtual void set_tooltip(std::function<std::string()> tooltip_text_creator);
233  glm::ivec2 get_y_bounds() const;
234  void scroll(int y);
235 
236  constexpr void set_y(int _y) {
237  this->y = _y;
238  if(this->parent)
239  this->y += this->parent->scrolled_y;
240  }
241 
242  constexpr void above_of(const UI::Widget& rhs) {
243  this->y = rhs.y - this->height;
244  }
245 
246  constexpr void below_of(const UI::Widget& rhs) {
247  this->y = rhs.y + rhs.height;
248  }
249 
250  constexpr void left_side_of(const UI::Widget& rhs) {
251  this->x = rhs.x - this->width;
252  }
253 
254  constexpr void right_side_of(const UI::Widget& rhs) {
255  this->x = rhs.x + rhs.width;
256  }
257 
259  virtual void set_on_click(std::function<void(UI::Widget&)> _on_click) {
260  this->on_click = _on_click;
261  }
262 
264  virtual void set_on_each_tick(std::function<void(UI::Widget&)> _on_each_tick) {
265  this->on_each_tick = _on_each_tick;
266  }
267 
268  virtual void set_on_drag(std::function<void(glm::ivec2, glm::ivec2)> _on_drag) {
269  this->on_drag = _on_drag;
270  }
271 
275  template<typename F>
276  inline void sort_children(F&& comp) {
277  std::sort(this->children.begin(), this->children.end(), comp);
278  this->need_recalc = true;
279  }
280 
283  inline void kill() {
284  this->dead = true;
285  this->kill_children();
286  this->notice_death();
287  }
288 
289  inline void kill_children() {
290  for(auto& child : this->children)
291  child->kill();
292  }
293 
294  inline size_t max_height() const {
295  size_t cnt = 0;
296  for(auto& child : this->children)
297  cnt += child->height;
298  return cnt;
299  }
300 
301  // If the widget can't be moved when scrolling
302  bool is_pinned = false;
303  bool is_render = true;
304 
305  // If you can move the children by scrolling
306  bool is_scroll = false;
307 
308  uint32_t is_hover = 0;
309  bool is_float = false;
310  bool is_fullscreen = false;
311  bool is_transparent = false;
312  bool managed = true; // Can be destroyed by the UI manager, if false it has to be manually deleted
313 
314  UI::Widget* parent = nullptr;
315  std::vector<std::unique_ptr<UI::Widget>> children;
316 
317  bool have_shadow = false;
319 
321 
322  int x = 0, y = 0;
323  glm::ivec2 padding{ 0 };
324 
325  size_t width = 0, height = 0;
326 
327  std::shared_ptr<Eng3D::Texture> current_texture;
328  std::shared_ptr<Eng3D::Texture> text_texture;
333  std::shared_ptr<Eng3D::TrueType::Font> font;
336 
341  size_t flex_gap = 0;
342 
343  UI::Tooltip* tooltip = nullptr;
344  std::function<UI::Tooltip*()> tooltip_creator;
345 
346  void* user_data = nullptr;
347 
348  std::function<void(glm::ivec2 mouse_pos, glm::ivec2 mouse_delta)> on_drag;
349  std::function<void(UI::Widget&)> on_update;
350  std::function<void(UI::Widget&)> on_click;
351  std::function<void(UI::Widget&)> on_click_outside;
352  std::function<void(UI::Widget&)> on_each_tick;
353  std::function<void(UI::Widget&, int i)> on_pos_recalc;
354  std::function<void(UI::Widget&, glm::ivec2 mouse_pos, glm::ivec2 widget_pos)> on_hover;
355 
356  // Used by lua to call closures upon one of these callbacks, note that
357  // the C++ callback part will be replaced by the lua driver, you can't mix C++ and Lua
358  // callbacks on the same widget!
360 
362  int dpad_index = 0;
363 
365  int scrolled_y = 0;
366 
367  friend class Context;
368  };
369 }
Border class that defines the texture and size of borders of the widgets.
Definition: widget.hpp:153
glm::ivec2 texture_size
Definition: widget.hpp:157
glm::ivec2 size
Definition: widget.hpp:156
std::shared_ptr< Eng3D::Texture > texture
Definition: widget.hpp:155
Border()=default
glm::ivec2 offset
Definition: widget.hpp:158
Border(std::shared_ptr< Eng3D::Texture > _texture, glm::ivec2 _size, glm::ivec2 _texture_size, glm::ivec2 _offset=glm::ivec2(0))
Definition: widget.hpp:161
Generalized chart data, used mostly by chart widgets, however it's not specific to any widget.
Definition: widget.hpp:129
~ChartData()=default
ChartData(float _num, std::string _info, Eng3D::Color _color)
Definition: widget.hpp:131
Eng3D::Color color
Definition: widget.hpp:148
ChartData(float _num, std::string _info, uint32_t rgb)
Definition: widget.hpp:138
std::string info
Definition: widget.hpp:147
The UI context that handles all the ui widgets.
Definition: ui.hpp:63
Tooltip widget, used entirely for hovering purpouses, don't use any other widget for hovering unless ...
Definition: tooltip.hpp:38
The master widget all the other widgets inherit from, do not use directly instead use one of the many...
Definition: widget.hpp:176
UI::Border border
Definition: widget.hpp:334
void add_child(UI::Widget &child)
Adds a children to the widget.
Definition: widget.cpp:427
UI::Align flex_align
Definition: widget.hpp:339
void sort_children(F &&comp)
Sort the children of this widget.
Definition: widget.hpp:276
void draw_rectangle(int x, int y, unsigned w, unsigned h, Eng3D::Rect viewport, const Eng3D::Texture *tex)
Definition: widget.cpp:221
int lua_on_each_tick
Definition: widget.hpp:359
std::function< void(UI::Widget &)> on_click
Definition: widget.hpp:350
int lua_on_click_outside
Definition: widget.hpp:359
T & make_widget(Targs &&...args)
Definition: widget.hpp:222
std::function< void(UI::Widget &)> on_update
Definition: widget.hpp:349
constexpr void below_of(const UI::Widget &rhs)
Definition: widget.hpp:246
UI::Overflow overflow
Definition: widget.hpp:340
std::shared_ptr< Eng3D::Texture > text_texture
Definition: widget.hpp:328
void * user_data
Definition: widget.hpp:346
void scroll(int y)
Scrolls all the children of this widget by a factor of y.
Definition: widget.cpp:497
constexpr void set_y(int _y)
Definition: widget.hpp:236
virtual void set_on_click(std::function< void(UI::Widget &)> _on_click)
Sets the on_click function of this widget.
Definition: widget.hpp:259
constexpr void left_side_of(const UI::Widget &rhs)
Definition: widget.hpp:250
bool managed
Definition: widget.hpp:312
UI::Origin origin
Definition: widget.hpp:318
bool is_float
Definition: widget.hpp:309
void draw_rect(const Eng3D::Texture *tex, Eng3D::Rect rect_pos, Eng3D::Rect rect_tex, Eng3D::Rect viewport)
Definition: widget.cpp:90
int lua_on_update
Definition: widget.hpp:359
virtual void set_tooltip(UI::Tooltip *tooltip)
Set the tooltip to be shown when this widget is hovered, overrides the previous tooltip.
Definition: widget.cpp:458
Eng3D::Color background_color
Definition: widget.hpp:335
constexpr void above_of(const UI::Widget &rhs)
Definition: widget.hpp:242
std::function< void(UI::Widget &, glm::ivec2 mouse_pos, glm::ivec2 widget_pos)> on_hover
Definition: widget.hpp:354
UI::Align text_align_y
Definition: widget.hpp:330
bool clickable_effect
Definition: widget.hpp:199
int text_offset_y
Definition: widget.hpp:329
bool is_scroll
Definition: widget.hpp:306
int text_offset_x
Definition: widget.hpp:329
Widget(Widget &&) noexcept=default
std::function< void(glm::ivec2 mouse_pos, glm::ivec2 mouse_delta)> on_drag
Definition: widget.hpp:348
std::vector< std::unique_ptr< UI::Widget > > children
Definition: widget.hpp:315
Widget(const Widget &)=default
std::function< UI::Tooltip *()> tooltip_creator
Definition: widget.hpp:344
size_t width
Definition: widget.hpp:325
constexpr void right_side_of(const UI::Widget &rhs)
Definition: widget.hpp:254
std::function< void(UI::Widget &)> on_click_outside
Definition: widget.hpp:351
virtual void set_on_drag(std::function< void(glm::ivec2, glm::ivec2)> _on_drag)
Definition: widget.hpp:268
bool is_fullscreen
Definition: widget.hpp:310
virtual ~Widget()
Definition: widget.cpp:83
virtual void on_render(Context &, Eng3D::Rect viewport)
Definition: widget.cpp:229
UI::Align text_align_x
Definition: widget.hpp:331
std::shared_ptr< Eng3D::Texture > current_texture
Definition: widget.hpp:327
virtual void set_on_each_tick(std::function< void(UI::Widget &)> _on_each_tick)
Sets the on_each_tick function of this widget.
Definition: widget.hpp:264
UI::Flex flex
Definition: widget.hpp:337
void kill()
Kills the current widget, setting it up for deletion when dead widgets are cleared by the UI context.
Definition: widget.hpp:283
Eng3D::Color text_color
Definition: widget.hpp:332
bool is_pinned
Definition: widget.hpp:302
bool have_shadow
Definition: widget.hpp:317
size_t flex_gap
Definition: widget.hpp:341
glm::ivec2 padding
Definition: widget.hpp:323
UI::FlexJustify flex_justify
Definition: widget.hpp:338
size_t max_height() const
Definition: widget.hpp:294
bool is_transparent
Definition: widget.hpp:311
glm::ivec2 get_y_bounds() const
Obtains the height of the top and bottom overflow in widget That is the space that the children of th...
Definition: widget.cpp:483
std::function< void(UI::Widget &)> on_each_tick
Definition: widget.hpp:352
std::function< void(UI::Widget &, int i)> on_pos_recalc
Definition: widget.hpp:353
Widget()=default
std::shared_ptr< Eng3D::TrueType::Font > font
Definition: widget.hpp:333
Widget & operator=(Widget &) noexcept=default
Widget & operator=(const Widget &)=default
virtual void set_text(const std::string &text)
Generates text for the widget and overrides the current text texture.
Definition: widget.cpp:445
size_t height
Definition: widget.hpp:325
int lua_on_click
Definition: widget.hpp:359
uint32_t is_hover
Definition: widget.hpp:308
UI::Tooltip * tooltip
Definition: widget.hpp:343
int scrolled_y
Total amount of scroll.
Definition: widget.hpp:365
bool is_render
Definition: widget.hpp:303
UI::WidgetType type
Definition: widget.hpp:320
constexpr void move_by(const glm::ivec2 offset)
Moves a widget by x and y.
Definition: widget.hpp:214
int dpad_index
Index for select_dpad_ui_widget, 0 means index=Auto (first to last)
Definition: widget.hpp:362
UI::Widget * parent
Definition: widget.hpp:314
void kill_children()
Definition: widget.hpp:289
WidgetType
The type of the widget, some widgets share types between them to keep simplicity.
Definition: widget.hpp:76
Flex
Ordering mode for flex.
Definition: widget.hpp:100
FlexJustify
Justification alignment for flex.
Definition: widget.hpp:108
Origin
The origin of the widget.
Definition: widget.hpp:52
@ LOWER_MIDDLE_SCREEN
@ MIDDLE_RIGHT_SCREEN
@ UPPER_MIDDLE_SCREEN
@ UPPER_RIGHT_SCREEN
@ MIDDLE_LEFT_SCREEN
@ LOWER_RIGHT_SCREEN
Overflow
Definition: widget.hpp:121
Align
Definition: widget.hpp:115
Primitive color type used through the engine.
Definition: color.hpp:32