lxgui
Loading...
Searching...
No Matches
gui_frame_renderer.cpp
1#include "lxgui/gui_frame_renderer.hpp"
2
3#include "lxgui/gui_frame.hpp"
4#include "lxgui/gui_out.hpp"
5#include "lxgui/utils_range.hpp"
6#include "lxgui/utils_string.hpp"
7
8namespace lxgui::gui {
9
10template<typename T>
11void check_sorted(const T& list) {
12 gui::out << "----------" << std::endl;
13 for (auto iter = list.begin(); iter != list.end(); ++iter) {
14 gui::out << " - " << (*iter)->get_name() << ": "
15 << utils::to_string((*iter)->get_effective_strata()) << ", "
16 << (*iter)->get_level() << std::endl;
17
18 if (iter != list.begin()) {
19 gui::out << " is greater than last? " << list.comparator()(*(iter - 1), *iter)
20 << std::endl;
21 }
22 }
23 gui::out << "----------" << std::endl;
24
25 if (!std::is_sorted(list.begin(), list.end(), list.comparator())) {
26 throw gui::exception("frame_renderer", "Frame list not sorted!!");
27 }
28}
29
30struct strata_comparator {
31 bool operator()(strata s1, strata s2) const {
32 using int_type = std::underlying_type_t<strata>;
33 const auto strata_id1 = static_cast<int_type>(s1);
34 const auto strata_id2 = static_cast<int_type>(s2);
35 return strata_id1 < strata_id2;
36 }
37
38 bool operator()(const frame* f1, strata s2) const {
39 return operator()(f1->get_effective_strata(), s2);
40 }
41
42 bool operator()(strata s1, const frame* f2) const {
43 return operator()(s1, f2->get_effective_strata());
44 }
45
46 bool operator()(const frame* f1, const frame* f2) const {
47 return operator()(f1->get_effective_strata(), f2->get_effective_strata());
48 }
49};
50
52 using int_type = std::underlying_type_t<strata>;
53 const auto strata_id1 = static_cast<int_type>(f1->get_effective_strata());
54 const auto strata_id2 = static_cast<int_type>(f2->get_effective_strata());
55
56 if (strata_id1 < strata_id2)
57 return true;
58 if (strata_id1 > strata_id2)
59 return false;
60
61 const auto level1 = f1->get_level();
62 const auto level2 = f2->get_level();
63
64 if (level1 < level2)
65 return true;
66 if (level1 > level2)
67 return false;
68
69 return f1 < f2;
70}
71
73 for (std::size_t i = 0; i < strata_list_.size(); ++i) {
74 strata_list_[i].id = static_cast<strata>(i);
75 }
76}
77
79 strata_list_[static_cast<std::size_t>(strata_id)].redraw_flag = true;
80}
81
82void frame_renderer::notify_rendered_frame(const utils::observer_ptr<frame>& obj, bool rendered) {
83 if (!obj)
84 return;
85
86 if (rendered) {
87 auto [iter, inserted] = sorted_frame_list_.insert(obj.get());
88 if (!inserted) {
89 throw gui::exception("frame_renderer", "Frame was already in this renderer");
90 }
91 } else {
92 auto iter = sorted_frame_list_.find(obj.get());
93 if (iter == sorted_frame_list_.end()) {
94 throw gui::exception("frame_renderer", "Could not find frame in this renderer");
95 }
96
98 }
99
100 for (std::size_t i = 0; i < strata_list_.size(); ++i) {
101 strata_list_[i].range = get_strata_range_(static_cast<strata>(i));
102 }
103
104 const auto strata_id = obj->get_effective_strata();
105
106 frame_list_updated_ = true;
108}
109
111 const utils::observer_ptr<frame>& /*obj*/, strata old_strata_id, strata new_strata_id) {
112
113 std::stable_sort(
115
116 for (std::size_t i = 0; i < strata_list_.size(); ++i) {
117 strata_list_[i].range = get_strata_range_(static_cast<strata>(i));
118 }
119
120 frame_list_updated_ = true;
121 notify_strata_needs_redraw(old_strata_id);
122 notify_strata_needs_redraw(new_strata_id);
123}
124
125std::pair<std::size_t, std::size_t> frame_renderer::get_strata_range_(strata strata_id) const {
126 auto range = std::equal_range(
127 sorted_frame_list_.begin(), sorted_frame_list_.end(), strata_id, strata_comparator{});
128
129 return {range.first - sorted_frame_list_.begin(), range.second - sorted_frame_list_.begin()};
130}
131
133 const utils::observer_ptr<frame>& obj, int /*old_level*/, int /*new_level*/) {
134
135 const auto strata_id = obj->get_effective_strata();
136
137 auto& strata_obj = strata_list_[static_cast<std::size_t>(strata_id)];
138
139 auto begin = sorted_frame_list_.begin() + strata_obj.range.first;
140 auto last = sorted_frame_list_.begin() + strata_obj.range.second;
141
142 std::stable_sort(begin, last, sorted_frame_list_.comparator());
143
144 frame_list_updated_ = true;
146}
147
148utils::observer_ptr<const frame>
149frame_renderer::find_topmost_frame(const std::function<bool(const frame&)>& predicate) const {
150 // Iterate through the frames in reverse order from rendering (frame on top goes first)
151 for (const auto* obj : utils::range::reverse(sorted_frame_list_)) {
152 if (obj->is_visible()) {
153 if (auto topmost = obj->find_topmost_frame(predicate))
154 return topmost;
155 }
156 }
157
158 return nullptr;
159}
160
162 auto range = strata_list_[static_cast<std::size_t>(strata_id)].range;
163 auto begin = sorted_frame_list_.begin() + range.first;
164 auto last = sorted_frame_list_.begin() + range.second;
165
166 if (last != begin) {
167 --last;
168 return (*last)->get_level();
169 }
170
171 return 0;
172}
173
174void frame_renderer::render_strata_(const strata_data& strata_obj) const {
175 auto begin = sorted_frame_list_.begin() + strata_obj.range.first;
176 auto end = sorted_frame_list_.begin() + strata_obj.range.second;
177
178 for (auto iter = begin; iter != end; ++iter) {
179 (*iter)->render();
180 }
181}
182
187
191
195
196} // namespace lxgui::gui
Exception to be thrown by GUI code.
virtual void notify_strata_changed(const utils::observer_ptr< frame > &obj, strata old_strata_id, strata new_strata_id)
Tells this renderer that a frame has changed strata.
virtual void notify_strata_needs_redraw(strata strata_id)
Tells this renderer that one of its region requires redraw.
int get_highest_level(strata strata_id) const
Returns the highest level on the provided strata.
virtual void notify_level_changed(const utils::observer_ptr< frame > &obj, int old_level, int new_level)
Tells this renderer that a frame has changed level.
void render_strata_(const strata_data &strata_obj) const
std::array< strata_data, num_strata > strata_list_
virtual void notify_rendered_frame(const utils::observer_ptr< frame > &obj, bool rendered)
Tells this renderer that it should (or not) render another frame.
utils::observer_ptr< const frame > find_topmost_frame(const std::function< bool(const frame &)> &predicate) const
Find the top-most frame matching the provided predicate.
std::pair< std::size_t, std::size_t > get_strata_range_(strata strata_id) const
frame_renderer()
Default constructor.
A region that can contain other regions and react to events.
int get_level() const
Returns this frame's level.
strata get_effective_strata() const
Returns this frame's effective strata.
iterator find(const Key &k)
Find an object in this vector by its key. The key can be a copy of the element itself,...
iterator erase(iterator iter)
Erase an element from this vector.
std::pair< iterator, bool > insert(U &&t)
Insert the provided object in the vector, only if no object exists with the same key.
Cmp & comparator()
Return the comparator object.
std::ostream out
void check_sorted(const T &list)
range_impl::reverse_range< T > reverse(T &container)
Reverse traversal.
bool operator()(const frame *f1, const frame *f2) const
Contains frames sorted by level.
std::pair< std::size_t, std::size_t > range