Symphony Of Empires
scrollbar.cpp
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/scrollbar.cpp
20 //
21 // Abstract:
22 // Does some important stuff.
23 // ----------------------------------------------------------------------------
24 
25 #include "eng3d/ui/scrollbar.hpp"
26 #include "eng3d/ui/button.hpp"
27 #include "eng3d/ui/ui.hpp"
28 #include "eng3d/state.hpp"
29 #include "eng3d/texture.hpp"
30 #include "eng3d/log.hpp"
31 
33  : UI::Widget(_parent, _x, _y, _parent->width, 0, UI::WidgetType::SCROLLBAR_THUMB)
34 {
35  auto& s = Eng3D::State::get_instance();
36  this->set_on_drag([this](glm::ivec2 start_pos, glm::ivec2 current_pos) {
37  assert(this->parent != nullptr);
38  if(this->parent->parent != nullptr) {
39  const auto y_bounds = this->parent->parent->get_y_bounds();
40  const float parent_height = glm::max(static_cast<float>(y_bounds.y - y_bounds.x), 1.f);
41  const auto scrolled = this->parent->parent->scrolled_y;
42  if (start_pos == current_pos) {
43  this->start_drag_scroll = scrolled;
44  }
45  const float y_diff = current_pos.y - start_pos.y;
46 
47  const auto btn_height = 20;
48  // The height of the track (scrollbar excluding buttons)
49  const float track_height = this->parent->height - btn_height * 3;
50  const auto ratio = (-y_diff / track_height) * parent_height;
51  this->parent->parent->scroll(start_drag_scroll - scrolled + ratio);
52  static_cast<UI::Scrollbar*>(this->parent)->update_thumb();
53  }
54  });
55 
56  // Only set so we get the free UI hints
57  this->set_on_click([this](UI::Widget&) { });
58  this->current_texture = s.tex_man.load(s.package_man.get_unique("gfx/scrollbar_drag.png"));
59 }
60 
61 UI::Scrollbar::Scrollbar(int _x, int _y, unsigned h, UI::Widget* _parent)
62  : UI::Widget(_parent, _x, _y, 20, h, UI::WidgetType::SCROLLBAR)
63 {
64  auto& s = Eng3D::State::get_instance();
65  this->current_texture = s.tex_man.load(s.package_man.get_unique("gfx/scrollbar.png"));
66 
67  this->is_pinned = true;
68  //this->flex = UI::Flex::COLUMN;
69  //this->flex_justify = UI::FlexJustify::SPACE_BETWEEN;
70 
71  auto& up_btn = this->make_widget<UI::Button>(0, 0, 20, 20);
72  up_btn.set_on_click([this](UI::Widget&) {
73  if(this->parent) {
74  const auto y_bounds = this->parent->get_y_bounds();
75  const float ratio = static_cast<float>(y_bounds.y - y_bounds.x) / static_cast<float>(this->height);
76  this->parent->scroll(16 * ratio);
77  this->update_thumb();
78  }
79  });
80  up_btn.current_texture = s.tex_man.load(s.package_man.get_unique("gfx/scrollbar_up.png"));
81 
82  auto& down_btn = this->make_widget<UI::Button>(0, this->height - 20, 20, 20);
83  down_btn.set_on_click([this](UI::Widget&) {
84  if(this->parent) {
85  const auto y_bounds = this->parent->get_y_bounds();
86  const float ratio = static_cast<float>(y_bounds.y - y_bounds.x) / static_cast<float>(this->height);
87  this->parent->scroll(-16 * ratio);
88  this->update_thumb();
89  }
90  });
91  down_btn.current_texture = s.tex_man.load(s.package_man.get_unique("gfx/scrollbar_down.png"));
92 
93  this->thumb_btn = &this->make_widget<UI::ScrollbarThumb>(0, 0);
94  this->update_thumb();
95 }
96 
99  const auto y_bounds = this->parent->get_y_bounds();
100  const float parent_height = glm::max(static_cast<float>(y_bounds.y - y_bounds.x), 1.f);
101  const auto btn_height = 20;
102  // The height of the track (scrollbar excluding up and down buttons)
103  const float track_height = this->height - btn_height * 2;
104  // 0 to 1 of how much the parent was scrolled relative to it's max scrolling/height
105  const auto scrolled = glm::abs<float>(this->parent->scrolled_y) / parent_height;
106  this->thumb_btn->set_y(btn_height + scrolled * (track_height - btn_height));
107  this->thumb_btn->height = btn_height;
108 }
static State & get_instance()
Definition: state.cpp:514
Scrollbar widget.
Definition: scrollbar.hpp:43
Scrollbar(int x, int y, unsigned h, UI::Widget *parent=nullptr)
Definition: scrollbar.cpp:61
void update_thumb()
Updates the thumb position in respect to the current scroll positioning of the parent.
Definition: scrollbar.cpp:98
ScrollbarThumb(int x, int y, UI::Widget *parent=nullptr)
Definition: scrollbar.cpp:32
The master widget all the other widgets inherit from, do not use directly instead use one of the many...
Definition: widget.hpp:176
void scroll(int y)
Scrolls all the children of this widget by a factor of y.
Definition: widget.cpp:497
virtual void set_on_click(std::function< void(UI::Widget &)> _on_click)
Sets the on_click function of this widget.
Definition: widget.hpp:259
virtual void set_on_drag(std::function< void(glm::ivec2, glm::ivec2)> _on_drag)
Definition: widget.hpp:268
std::shared_ptr< Eng3D::Texture > current_texture
Definition: widget.hpp:327
bool is_pinned
Definition: widget.hpp:302
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
size_t height
Definition: widget.hpp:325
int scrolled_y
Total amount of scroll.
Definition: widget.hpp:365
UI::Widget * parent
Definition: widget.hpp:314
WidgetType
The type of the widget, some widgets share types between them to keep simplicity.
Definition: widget.hpp:76