neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
element.hpp
Go to the documentation of this file.
1// element.hpp
2/*
3neoGFX Design Studio
4Copyright(C) 2020 Leigh Johnston
5
6This program is free software: you can redistribute it and / or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
23#include <algorithm>
24#include <boost/format.hpp>
29#include <neolib/task/event.hpp>
30#include <neogfx/core/units.hpp>
31#include <neogfx/app/app.hpp>
32#include <neogfx/app/action.hpp>
41
43{
44 struct user_interface {};
45
46 template <typename Type>
48 {
49 if constexpr (std::is_base_of_v<app, Type>)
50 return element_group::App;
51 else if constexpr (std::is_base_of_v<action, Type>)
53 else if constexpr (std::is_base_of_v<i_menu, Type>)
55 else if constexpr (std::is_base_of_v<i_widget, Type>)
57 else if constexpr (std::is_base_of_v<i_layout, Type>)
59 else if constexpr (std::is_base_of_v<i_project, Type>)
61 else if constexpr (std::is_base_of_v<user_interface, Type>)
63 else
65 }
66
67 template <typename BaseType>
69 {
70 public:
71 typedef BaseType base_type;
72 };
73
74 template <typename Type, typename Base = typename element_traits<Type>::base>
76 {
77 typedef element<Base> self_type;
79 public:
80 define_declared_event(ModeChanged, mode_changed)
81 define_declared_event(SelectionChanged, selection_changed)
83 public:
84 using typename i_element::no_parent;
85 using typename i_element::no_layout_item;
86 using typename i_element::no_caddy;
87 public:
88 typedef abstract_t<Base> abstract_type;
90 public:
91 element(i_element_library const& aLibrary, i_project& aProject, std::string const& aType, element_group aGroup = default_element_group<Type>()) :
92 iLibrary{ aLibrary },
93 iProject{ aProject },
94 iParent { nullptr },
95 iGroup{ aGroup },
96 iType{ aType }
97 {
98 }
99 element(i_element_library const& aLibrary, i_project& aProject, std::string const& aType, std::string const& aId, element_group aGroup = default_element_group<Type>()) :
100 iLibrary{ aLibrary },
101 iProject{ aProject },
102 iParent{ nullptr },
103 iGroup{ aGroup },
104 iType{ aType },
105 iId{ aId }
106 {
107 }
108 element(i_element_library const& aLibrary, i_element& aParent, std::string const& aType, element_group aGroup = default_element_group<Type>()) :
109 iLibrary{ aLibrary },
110 iProject{ aParent.project() },
111 iParent{ &aParent },
112 iGroup{ aGroup },
113 iType{ aType }
114 {
115 parent().add_child(*this);
116 }
117 element(i_element_library const& aLibrary, i_element& aParent, std::string const& aType, std::string const& aId, element_group aGroup = default_element_group<Type>()) :
118 iLibrary{ aLibrary },
119 iProject{ aParent.project() },
120 iParent{ &aParent },
121 iGroup{ aGroup },
122 iType{ aType },
123 iId{ aId }
124 {
125 parent().add_child(*this);
126 }
128 {
129 }
130 public:
131 i_element_library const& library() const override
132 {
133 return iLibrary;
134 }
135 i_project& project() const override
136 {
137 return iProject;
138 }
139 element_group group() const override
140 {
141 return iGroup;
142 }
143 neolib::i_string const& type() const override
144 {
145 return iType;
146 }
147 neolib::i_string const& id() const override
148 {
149 return iId;
150 }
151 public:
152 i_element const& root() const override
153 {
154 i_element const* e = this;
155 while (e->has_parent())
156 e = &e->parent();
157 return *e;
158 }
159 i_element& root() override
160 {
161 return const_cast<i_element&>(to_const(*this).root());
162 }
163 bool has_parent() const override
164 {
165 return iParent != nullptr;
166 }
167 i_element const& parent() const override
168 {
169 if (has_parent())
170 return *iParent;
171 throw no_parent();
172 }
173 i_element& parent() override
174 {
175 return const_cast<i_element&>(to_const(*this).parent());
176 }
177 void set_parent(i_element& aParent) override
178 {
179 iParent = &aParent;
180 }
181 children_t const& children() const override
182 {
183 return iChildren;
184 }
186 {
187 return iChildren;
188 }
189 void add_child(i_element& aChild) override
190 {
193 else
194 {
195 aChild.set_parent(parent());
196 parent().children().insert(std::prev(parent().children().end()), neolib::ref_ptr<i_element>{ &aChild });
197 }
198 }
199 void remove_child(i_element& aChild) override
200 {
201 auto existing = std::find_if(children().begin(), children().end(), [&](auto&& e) { return &*e == &aChild; });
202 if (existing != children().end())
203 children().erase(existing);
204 }
205 public:
207 {
208 DesignStudio::create_default_children<Type>(*this);
209 }
210 public:
211 bool needs_caddy() const override
212 {
214 }
215 bool has_caddy() const override
216 {
217 return iCaddy != nullptr;
218 }
219 i_element_caddy& caddy() const override
220 {
221 if (has_caddy())
222 return *iCaddy;
223 throw no_caddy();
224 }
225 void set_caddy(i_element_caddy& aCaddy) override
226 {
227 iCaddy = aCaddy;
228 }
229 bool has_layout_item() const override
230 {
231 return iLayoutItem != nullptr;
232 }
233 void create_layout_item(i_widget& aParent) override
234 {
235 if (!iLayoutItem)
236 {
237 if constexpr (std::is_base_of_v<i_widget, Type>)
238 {
239 if constexpr (std::is_constructible_v<Type, i_element&>)
240 iLayoutItem = make_ref<Type>(*this);
241 else if constexpr (std::is_constructible_v<Type, i_widget&, window_style>)
242 iLayoutItem = make_ref<Type>(aParent, (window_style::Default | window_style::Nested));
243 else if constexpr (std::is_constructible_v<Type, i_element&, i_widget&, window_style>)
244 iLayoutItem = make_ref<Type>(*this, aParent, (window_style::Default | window_style::Nested));
245 else if constexpr (std::is_constructible_v<Type, i_widget&, neolib::i_string const&, window_style>)
246 iLayoutItem = make_ref<Type>(aParent, iId.to_std_string(), (window_style::Default | window_style::Nested));
247 else if constexpr (std::is_constructible_v<Type, i_element&, i_widget&, neolib::i_string const&, window_style>)
248 iLayoutItem = make_ref<Type>(*this, aParent, iId.to_std_string(), (window_style::Default | window_style::Nested));
249 else if constexpr (std::is_constructible_v<Type, i_widget&, neolib::i_string const&>)
250 iLayoutItem = make_ref<Type>(aParent, iId.to_std_string());
251 else if constexpr (std::is_constructible_v<Type, i_element&, i_widget&, neolib::i_string const&>)
252 iLayoutItem = make_ref<Type>(*this, aParent, iId.to_std_string());
253 else if constexpr (std::is_constructible_v<Type, window_style>)
254 iLayoutItem = make_ref<Type>((window_style::Default | window_style::Nested));
255 else if constexpr (std::is_constructible_v<Type, i_element&, window_style>)
256 iLayoutItem = make_ref<Type>(*this, (window_style::Default | window_style::Nested));
257 else if constexpr (std::is_constructible_v<Type, neolib::i_string const&, window_style>)
258 iLayoutItem = make_ref<Type>(iId.to_std_string(), (window_style::Default | window_style::Nested));
259 else if constexpr (std::is_constructible_v<Type, i_widget&, neolib::i_string const&, window_style>)
260 iLayoutItem = make_ref<Type>(*this, iId.to_std_string(), (window_style::Default | window_style::Nested));
261 else if constexpr (std::is_constructible_v<Type, neolib::i_string const&>)
262 iLayoutItem = make_ref<Type>(iId.to_std_string());
263 else if constexpr (std::is_constructible_v<Type, i_element&, neolib::i_string const&>)
264 iLayoutItem = make_ref<Type>(*this, iId.to_std_string());
265 else if constexpr (std::is_default_constructible_v<Type>)
266 iLayoutItem = make_ref<Type>();
267 else
268 {
269 // todo: widget creation for the other widget types
270 }
271 if (std::is_same_v<Type, progress_bar>)
272 {
273 auto& progressBar = static_cast<progress_bar&>(iLayoutItem->as_widget());
274 progressBar.set_value(0.5);
275 progressBar.set_minimum(0.0);
276 progressBar.set_maximum(1.0);
277 }
278 if (iLayoutItem->is_widget() && iLayoutItem->as_widget().is_root() && iLayoutItem->as_widget().root().is_nested())
279 service<i_surface_manager>().nest_for(aParent, nest_type::Caddy).add(iLayoutItem->as_widget().root().native_window());
280 }
281 else if constexpr (std::is_base_of_v<i_layout, Type>)
282 {
283 if constexpr (std::is_constructible_v<Type, i_element&>)
284 iLayoutItem = make_ref<Type>(*this);
285 else
286 iLayoutItem = make_ref<Type>();
287 }
288 }
289 }
290 i_layout_item& layout_item() const override
291 {
292 if (iLayoutItem != nullptr)
293 return *iLayoutItem;
294 throw no_layout_item();
295 }
296 public:
297 element_mode mode() const override
298 {
299 return iMode;
300 }
301 void set_mode(element_mode aMode) override
302 {
303 if (iMode != aMode)
304 {
305 iMode = aMode;
306 if (mode() == element_mode::Edit)
307 {
308 root().visit([&](i_element& aElement)
309 {
310 if (&aElement != this && aElement.mode() == element_mode::Edit)
312 });
313 }
314 ModeChanged.trigger();
315 }
316 }
317 bool is_selected() const override
318 {
319 return iSelected;
320 }
321 void select(bool aSelected = true, bool aDeselectRest = true) override
322 {
323 if (iSelected != aSelected)
324 {
325 iSelected = aSelected;
326 SelectionChanged.trigger();
327 }
328 if (aDeselectRest)
329 {
330 root().visit([&](i_element& aElement)
331 {
332 if (&aElement != this && aElement.is_selected())
333 aElement.select(false, false);
334 });
335 }
336 }
337 private:
338 const i_element_library& iLibrary;
339 i_project& iProject;
340 i_element* iParent;
341 element_group iGroup;
342 neolib::string iType;
343 neolib::string iId;
344 children_t iChildren;
345 mutable ref_ptr<i_layout_item> iLayoutItem;
348 bool iSelected = false;
349 };
350}
i_element & root() override
Definition element.hpp:159
void set_caddy(i_element_caddy &aCaddy) override
Definition element.hpp:225
bool has_caddy() const override
Definition element.hpp:215
bool has_layout_item() const override
Definition element.hpp:229
i_element_library const & library() const override
Definition element.hpp:131
neolib::vector< ref_ptr< abstract_type > > children_t
Definition element.hpp:89
bool has_parent() const override
Definition element.hpp:163
element(i_element_library const &aLibrary, i_element &aParent, std::string const &aType, element_group aGroup=default_element_group< Type >())
Definition element.hpp:108
children_t const & children() const override
Definition element.hpp:181
i_element_caddy & caddy() const override
Definition element.hpp:219
neolib::i_string const & type() const override
Definition element.hpp:143
void set_parent(i_element &aParent) override
Definition element.hpp:177
i_element & parent() override
Definition element.hpp:173
void create_layout_item(i_widget &aParent) override
Definition element.hpp:233
element_mode mode() const override
Definition element.hpp:297
bool is_selected() const override
Definition element.hpp:317
void set_mode(element_mode aMode) override
Definition element.hpp:301
i_layout_item & layout_item() const override
Definition element.hpp:290
i_element const & parent() const override
Definition element.hpp:167
void create_default_children() override
Definition element.hpp:206
i_element const & root() const override
Definition element.hpp:152
void select(bool aSelected=true, bool aDeselectRest=true) override
Definition element.hpp:321
element(i_element_library const &aLibrary, i_project &aProject, std::string const &aType, std::string const &aId, element_group aGroup=default_element_group< Type >())
Definition element.hpp:99
i_project & project() const override
Definition element.hpp:135
abstract_t< Base > abstract_type
Definition element.hpp:88
element_group group() const override
Definition element.hpp:139
void add_child(i_element &aChild) override
Definition element.hpp:189
element(i_element_library const &aLibrary, i_element &aParent, std::string const &aType, std::string const &aId, element_group aGroup=default_element_group< Type >())
Definition element.hpp:117
children_t & children() override
Definition element.hpp:185
void remove_child(i_element &aChild) override
Definition element.hpp:199
element(i_element_library const &aLibrary, i_project &aProject, std::string const &aType, element_group aGroup=default_element_group< Type >())
Definition element.hpp:91
define_declared_event(ModeChanged, mode_changed) define_declared_event(SelectionChanged
neolib::i_string const & id() const override
Definition element.hpp:147
bool needs_caddy() const override
Definition element.hpp:211
virtual children_t const & children() const =0
virtual bool has_parent() const =0
virtual i_element const & parent() const =0
virtual void set_mode(element_mode aMode)=0
virtual void add_child(i_element &aChild)=0
virtual element_group group() const =0
virtual bool is_selected() const =0
void visit(std::function< void(i_element &)> aVisitor)
virtual void select(bool aSelected=true, bool aDeselectRest=true)=0
virtual void set_parent(i_element &aParent)=0
virtual element_mode mode() const =0
void set_value(scalar aValue) override
std::string to_std_string() const
Definition string.hpp:85
void push_back(abstract_value_type const &aValue) final
Definition vector.hpp:201
element_group default_element_group()
Definition element.hpp:47
it_type prev(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)
Definition plf_hive.h:98
#define define_declared_event(name, declName,...)
Definition event.hpp:195