neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
i_property.hpp
Go to the documentation of this file.
1// i_property.hpp
2/*
3 neogfx C++ App/Game Engine
4 Copyright (c) 2018, 2020 Leigh Johnston. All Rights Reserved.
5
6 This program is free software: you can redistribute it and / or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#pragma once
21
22#include <neogfx/neogfx.hpp>
23#include <type_traits>
24#include <neolib/core/any.hpp>
30#include <neogfx/core/event.hpp>
33
34namespace neogfx
35{
36 template <typename R, typename... Args>
38 template <typename R, class C, typename... Args>
39 struct callable_function_cracker<R(C::*)(Args...) const>
40 {
41 typedef R(C::* callable_type)(Args...) const;
42 typedef R return_type;
43 typedef C class_type;
44 };
45 template <typename R, class C, typename... Args>
46 struct callable_function_cracker<R(C::*)(Args...)>
47 {
48 typedef R(C::* callable_type)(Args...);
49 typedef R return_type;
50 typedef C class_type;
51 };
52
54
55 // todo: move to neolib::plugin_variant when geometry types are abstractable
57 void*,
58 bool,
59 char,
60 int32_t,
61 uint32_t,
62 int64_t,
63 uint64_t,
64 float,
65 double,
66 string,
67 mat33,
68 size,
69 point,
70 rect,
73
74 template <typename T>
76 {
77 static constexpr bool is_custom_type = false;
78 };
79
80 template <typename T> struct variant_type_for { typedef custom_type type; };
81 template <typename T> struct variant_type_for<T*> { typedef void* type; };
82
83 class i_property;
84
86 {
87 public:
88 virtual ~i_property_delegate() = default;
89 public:
90 virtual property_variant get(const i_property& aProperty) const = 0;
91 public:
92 virtual const void* data() const = 0;
93 virtual void* data() = 0;
94 };
95
97 {
98 public:
99 virtual ~i_property_owner() = default;
100 public:
101 virtual void property_changed(i_property& aProperty) = 0;
102 public:
103 virtual const i_properties& properties() const = 0;
104 virtual i_properties& properties() = 0;
105 };
106
107 class i_animator;
108 class i_transition;
109
111 {
112 template <typename, typename>
113 friend class property_delegate;
114 // types
115 public:
117 // events
118 public:
119 declare_event(property_changed, const property_variant&)
120 declare_event(property_changed_from_to, const property_variant&, const property_variant&)
121 // exceptions
122 public:
123 struct no_calculator : std::logic_error { no_calculator() : std::logic_error("neogfx::i_property::no_calculator") {} };
124 struct no_delegate : std::logic_error { no_delegate() : std::logic_error("neogfx::i_property::no_delegate") {} };
125 struct no_new_value : std::logic_error { no_new_value() : std::logic_error("neogfx::i_property::no_new_value") {} };
126 // construction
127 public:
128 virtual ~i_property() = default;
129 // object
130 public:
131 virtual i_property_owner& owner() const = 0;
132 // operations
133 public:
134 virtual const i_string& name() const = 0;
135 virtual const std::type_info& type() const = 0;
136 virtual const std::type_info& category() const = 0;
137 virtual bool optional() const = 0;
138 virtual property_variant get_as_variant() const = 0;
139 virtual void set_from_variant(const property_variant& aValue) = 0;
140 virtual bool read_only() const = 0;
141 virtual void set_read_only(bool aReadOnly) = 0;
142 virtual bool transition_set() const = 0;
143 virtual i_transition& transition() const = 0;
144 virtual void set_transition(i_animator& aAnimator, easing aEasingFunction, double aDuration, bool aEnabled = true) = 0;
145 virtual void clear_transition() = 0;
146 virtual bool transition_suppressed() const = 0;
147 virtual void suppress_transition(bool aSuppress) = 0;
148 virtual bool has_delegate() const = 0;
149 virtual i_property_delegate const& delegate() const = 0;
151 virtual void set_delegate(i_property_delegate& aDelegate) = 0;
152 virtual void unset_delegate() = 0;
153 // implementation
154 protected:
155 virtual const void* data() const = 0;
156 virtual void* data() = 0;
157 virtual void*const* calculator_function() const = 0;
158 // helpers
159 public:
160 template <typename T>
161 const T& get() const
162 {
163 return *static_cast<const T*>(data());
164 }
165 template <typename T>
166 T& get()
167 {
168 return *static_cast<T*>(data());
169 }
170 template <typename Context, typename Callable, typename... Args>
171 auto calculate(Args&&... aArgs) const
172 {
173 // why? because we have to type-erase to support plugins and std::function can't be passed across a plugin boundary.
174 auto const calculator = *reinterpret_cast<Callable const*>(calculator_function());
175 if constexpr(std::is_convertible_v<const Context&, const i_property_owner&>)
176 return (static_cast<const Context&>(owner()).*calculator)(std::forward<Args>(aArgs)...);
177 else
178 return (dynamic_cast<const Context&>(owner()).*calculator)(std::forward<Args>(aArgs)...);
179 }
180 };
181
182 template <typename T, typename Getter = std::function<T()>>
184 {
185 public:
186 typedef T value_type;
187 public:
188 property_delegate(i_property& aSubject, i_property& aProxy, Getter aGetter) :
189 iSubject{ aSubject }, iProxy{ aProxy }, iGetter{ aGetter }
190 {
191 subject().set_delegate(*this);
192 }
197 public:
198 property_variant get(i_property const&) const override
199 {
200 if constexpr (neolib::is_optional_v<T>)
201 {
202 auto const& ov = iGetter();
203 return ov != std::nullopt ? property_variant{ *ov } : property_variant{};
204 }
205 else
206 return iGetter();
207 }
208 public:
209 const void* data() const override
210 {
211 return proxy().data();
212 }
213 void* data() override
214 {
215 return proxy().data();
216 }
217 public:
218 i_property const & subject() const
219 {
220 return iSubject;
221 }
223 {
224 return iSubject;
225 }
226 i_property const& proxy() const
227 {
228 return iProxy;
229 }
231 {
232 return iProxy;
233 }
234 private:
235 i_property& iSubject;
236 i_property& iProxy;
237 Getter iGetter;
238 };
239
240 template <typename PropertyOwner>
241 inline i_property& get_property(PropertyOwner& Owner, std::string const& aPropertyName)
242 {
243 return *static_cast<i_property_owner&>(Owner).properties().property_map().find(string{ aPropertyName })->second();
244 }
245
247 {
248 public:
250 iProperty{ aProperty }, iWasSuppressed{ aProperty.transition_suppressed() }
251 {
252 iProperty.suppress_transition(true);
253 }
255 {
256 iProperty.suppress_transition(iWasSuppressed);
257 }
258 private:
259 i_property& iProperty;
260 bool iWasSuppressed;
261 };
262
264 {
265 public:
267 iProperty{ aProperty }, iWasReadOnly{ aProperty.read_only() }
268 {
269 iProperty.set_read_only(true);
270 }
272 {
273 iProperty.set_read_only(iWasReadOnly);
274 }
275 private:
276 i_property& iProperty;
277 bool iWasReadOnly;
278 };
279}
280
virtual property_variant get(const i_property &aProperty) const =0
virtual void * data()=0
virtual ~i_property_delegate()=default
virtual const void * data() const =0
virtual ~i_property_owner()=default
virtual const i_properties & properties() const =0
virtual void property_changed(i_property &aProperty)=0
virtual i_properties & properties()=0
virtual void set_delegate(i_property_delegate &aDelegate)=0
virtual const std::type_info & category() const =0
virtual const void * data() const =0
virtual const i_string & name() const =0
virtual void suppress_transition(bool aSuppress)=0
virtual i_property_owner & owner() const =0
virtual void set_transition(i_animator &aAnimator, easing aEasingFunction, double aDuration, bool aEnabled=true)=0
virtual ~i_property()=default
virtual void * data()=0
virtual const std::type_info & type() const =0
virtual void *const * calculator_function() const =0
virtual bool transition_suppressed() const =0
const T & get() const
virtual bool transition_set() const =0
declare_event(property_changed, const property_variant &) declare_event(property_changed_from_to
virtual void set_read_only(bool aReadOnly)=0
i_property abstract_type
virtual void unset_delegate()=0
auto calculate(Args &&... aArgs) const
virtual i_property_delegate & delegate()=0
virtual bool has_delegate() const =0
virtual property_variant get_as_variant() const =0
virtual bool read_only() const =0
virtual void clear_transition()=0
virtual void set_from_variant(const property_variant &aValue)=0
virtual bool optional() const =0
virtual i_transition & transition() const =0
virtual i_property_delegate const & delegate() const =0
property_delegate(i_property &aSubject, i_property &aProxy, Getter aGetter)
i_property const & proxy() const
i_property const & subject() const
void * data() override
const void * data() const override
property_variant get(i_property const &) const override
scoped_property_read_only(i_property &aProperty)
scoped_property_transition_suppression(i_property &aProperty)
basic_box_areas< double > box_areas
neolib::any custom_type
gui_rect rect
i_property & get_property(PropertyOwner &Owner, std::string const &aPropertyName)
basic_point< coordinate > point
basic_size< coordinate > size
matrix33 mat33
ref_ptr< ConcreteType > make_ref(Args &&... args)
#define declare_event(declName,...)
Definition i_event.hpp:305
static constexpr bool is_custom_type