14#include "AUI/Traits/concepts.h"
15#include "ALayoutInflater.h"
18#include <AUI/Common/SharedPtr.h>
19#include <AUI/Common/ASignal.h>
20#include <AUI/Traits/members.h>
21#include <AUI/View/AViewContainer.h>
36template<
typename View,
typename FieldType>
54 [[deprecated(
"ADataBinding is deprecated. Please use Property System to bind values")]]
62 [[deprecated(
"ADataBinding is deprecated. Please use Property System to bind values")]]
63 static void(View::*
getSetter())(
const FieldType& v) {
68template<aui::derived_from<AViewContainer> Container>
74 [&container = *container](
const _<AView>& viewToInflate) {
81template <
typename Model>
84template<
typename Model,
typename View,
typename ModelField,
typename Getter, aui::invocable<View*, const ModelField&> Setter>
85class ADataBindingLinker {
89 std::decay_t<ModelField>(Model::*mField);
94 std::decay_t<ModelField>(Model::*field)):
95 mBinder(binder), mGetter(getter), setter(std::move(setter)), mField(field) {}
101 auto getSetterFunc()
const {
105 auto getField()
const {
109 auto getGetter()
const {
113template<
typename Model,
typename Data,
typename Projection>
114class ADataBindingLinker2 {
117 Data(Model::*mField);
118 Projection mProjection;
121 ADataBindingLinker2(
ADataBinding<Model>* binder, Data(Model::*field), Projection projection =
nullptr) : mBinder(binder), mField(field), mProjection(std::move(projection)) {}
127 auto getField()
const {
131 Projection getProjection()
const {
199template <
typename Model>
200class [[deprecated(
"consider using AProperty and signal/slot connections instead")]] ADataBinding:
public AObject {
202 using Observer = std::function<void(
const Model& model,
unsigned)>;
205 Model* mModel =
nullptr;
206 bool mOwning =
false;
208 void* mExcept =
nullptr;
212 ADataBinding() =
default;
213 explicit ADataBinding(
const Model& m)
217 explicit ADataBinding(Model* m)
222 virtual ~ADataBinding() {
233 template<
typename View,
typename ModelField,
typename SetterArg>
234 auto operator()(ModelField(Model::*field),
void(View::*setterFunc)(SetterArg)) {
236 return operator()<View, ModelField>(field, (ASignal<ModelField>(View::*))
nullptr, setterFunc);
255 template<
typename ModelField,
typename SetterLambda>
256 auto operator()(ModelField(Model::*field), SetterLambda setterLambda) {
257 using lambda_args =
typename aui::lambda_info<SetterLambda>::args;
259 static_assert(std::is_reference_v<ViewReference>,
"View is expected to be a reference");
261 using View = std::decay_t<ViewReference>;
262 return operator()<View, ModelField>(field, (ASignal<ModelField>(View::*))
nullptr, [setterLambda = std::move(setterLambda)](View* view, DataArgument dataArgument) {
263 std::invoke(setterLambda, *view, std::forward<DataArgument>(dataArgument));
274 template<
typename View,
typename ModelField,
typename GetterRV, aui::invocable<View*, const ModelField&> Setter>
276 ASignal<GetterRV>(View::*getter),
277 Setter setter = (
void(View::*)(
const ModelField&))
nullptr) {
287 template<
typename Data>
297 template<
typename Data, aui::invocable<Data> Projection>
301 const Model& getModel() const noexcept {
305 Model
const * operator->() const noexcept {
309 Model& getEditableModel() {
312 void setModel(
const Model& model) {
317 mModel =
new Model(model);
321 void setModel(Model* model) {
330 const void* getExclusion()
const {
334 void notifyUpdate(
void* except =
nullptr,
unsigned field = -1) {
336 for (
auto& applier : mLinkObservers) {
337 applier(*mModel, field);
342 template<
typename ModelField>
343 void notifyUpdate(ModelField(Model::*field)) {
349 notifyUpdate(
nullptr,
c.i);
352 template<
typename ModelField, aui::convertible_to<ModelField> U>
353 void setValue(ModelField(Model::*field), U&& value) {
354 mModel->*field = std::move(value);
358 void addObserver(Observer applier) {
359 mLinkObservers << std::move(applier);
361 mLinkObservers.
last()(*mModel, -1);
365 template<aui::invocable T>
366 void addObserver(T&& applier) {
367 addObserver([applier = std::forward<T>(applier)](
const Model&,
unsigned) {
372 template<
typename ModelField,
typename FieldObserver>
373 void addObserverNoInitialCall(ModelField(Model::*field), FieldObserver&& observer) {
374 mLinkObservers << [observer = std::forward<FieldObserver>(observer), field](
const Model& model,
unsigned index) {
380 if (
c.i == index || index == -1) {
381 observer(model.*field);
385 template<
typename ModelField,
typename FieldObserver>
386 void addObserver(ModelField(Model::*field), FieldObserver&& observer) {
387 addObserverNoInitialCall(field, std::forward<FieldObserver>(observer));
389 mLinkObservers.
last()(*mModel, -1);
401template<
typename Klass1,
typename View,
typename Model,
typename ModelField,
typename GetterRV,
typename SetterArg>
405 decltype(linker.getField()) p;
407 if (linker.getGetter()) {
408 AObject::connect(modelBinding.get()->*(linker.getGetter()), linker.getBinder(), [modelBinding, linker](
const GetterRV& data) {
409 AUI_ASSERTX(&linker.getBinder()->getEditableModel(),
"please setModel for ADataBinding");
410 modelBinding->setSignalsEnabled(false);
411 linker.getBinder()->getEditableModel().*(linker.getField()) = data;
413 c.p = linker.getField();
414 linker.getBinder()->notifyUpdate(modelBinding.get(), c.i);
415 modelBinding->setSignalsEnabled(true);
420 if (!
bool(linker.getSetterFunc())) {
424 linker.getBinder()->addObserver([modelBinding, linker](
const Model& model,
unsigned field) {
426 c.p = linker.getField();
427 if (
c.i == field || field == -1) {
428 if (modelBinding.get() != linker.getBinder()->getExclusion()) {
429 std::invoke(linker.getSetterFunc(), modelBinding.get(), model.*(linker.getField()));
438namespace aui::detail {
439 template<
typename ForcedClazz,
typename Type>
440 struct pointer_to_member {
441 template<
typename... Args>
442 static Type(ForcedClazz::*with_args(std::tuple<Args...>))(Args...) {
448template<
typename View,
typename Model,
typename Data,
typename Projection>
452 constexpr bool is_default_projection = std::is_same_v<Projection, std::nullptr_t>;
453 using projection_deduced = std::conditional_t<is_default_projection, aui::identity, Projection>;
454 static_assert(std::is_invocable_v<projection_deduced, Data>,
"projection is expected to accept Data value from model");
455 using data_deduced = std::decay_t<std::invoke_result_t<projection_deduced, Data>>;
460 using setter_ret =
typename setter::return_t;
461 using setter_args =
typename setter::args;
463 using my_pointer_to_member =
typename aui::detail::pointer_to_member<View, setter_ret>;
465 using pointer_to_setter =
decltype(my_pointer_to_member::with_args(std::declval<setter_args>()));
467 if constexpr (is_default_projection) {
480 AUI_ASSERTX(g !=
nullptr || s !=
nullptr,
"ADataBindingDefault is not defined for View, Data");
482 object && (*linker.getBinder())(linker.getField(), g, s);
484 object && (*linker.getBinder())(linker.getField(), [projection = linker.getProjection()](View& v,
const Data& d) {
485 auto s = static_cast<pointer_to_setter>(ADataBindingDefault<View, data_deduced>::getSetter());
486 std::invoke(s, &v, projection(d));
492template<
typename View>
502 return &AView::setVisibility;
506template <
typename Object, APropertyReadable Connectable>
512 requires { { Binding::property(
object) } ->
AAnyProperty; } ||
514 "ADataBindingDefault is required to have property() function to return any property or slot def; either "
515 "define proper ADataBindingDefault specialization or explicitly specify the destination property.");
517 requires { { Binding::setup(
object) }; },
518 "ADataBindingDefault is required to have setup(const _<Object>&) function; either define proper "
519 "ADataBindingDefault specialization or explicitly specify the destination property.");
520 Binding::setup(
object);
526template<
typename Object, APropertyWritable Connectable>
530 static_assert(
requires {
532 },
"ADataBindingDefault is required to have property() function to return any property; either define proper "
533 "ADataBindingDefault specialization or explicitly specify the destination property.");
535 requires { { Binding::setup(
object) }; },
536 "ADataBindingDefault is required to have setup(const _<Object>&) function; either define proper "
537 "ADataBindingDefault specialization or explicitly specify the destination property.");
538 Binding::setup(
object);
544template <AAnyProperty Lhs,
typename Destination>
547 Destination destinationPointerToMember;
548 explicit Binding(Lhs sourceProperty, Destination destinationPointerToMember)
549 : sourceProperty(sourceProperty), destinationPointerToMember(destinationPointerToMember) {}
552template <AAnyProperty Property,
typename Destination>
553inline decltype(
auto)
operator>(Property&& sourceProperty, Destination&& rhs) {
557template <
typename Object, APropertyReadable Property,
typename Destination>
561 { std::invoke(binding.destinationPointerToMember, *
object) } ->
AAnyProperty;
564 AObject::connect(binding.sourceProperty, std::invoke(binding.destinationPointerToMember, *
object));
568template <
typename Object, APropertyWritable Property,
typename Destination>
572 { std::invoke(binding.destinationPointerToMember, *
object) } ->
AAnyProperty;
575 AObject::biConnect(binding.sourceProperty, std::invoke(binding.destinationPointerToMember, *
object));
580template <
typename Object, APropertyReadable Property,
typename Destination>
583 { binding.destinationPointerToMember } ->
aui::invocable<Object&,
decltype(*binding.sourceProperty)>;
587 binding.sourceProperty,
object.get(),
588 [
object =
object.get(), wrapped = std::move(binding.destinationPointerToMember)](
589 const std::decay_t<
decltype(*binding.sourceProperty)>& i) { std::invoke(wrapped, *object, i); });
593template <
typename Object, APropertyWritable Property,
typename Destination>
596 { binding.destinationPointerToMember } ->
aui::invocable<Object&,
decltype(*binding.sourceProperty)>;
600 binding.sourceProperty,
object.get(),
601 [
object =
object.get(), wrapped = std::move(binding.destinationPointerToMember)](
602 const std::decay_t<
decltype(*binding.sourceProperty)>& i) { std::invoke(wrapped, *object, i); });
Definition ADataBinding.h:114
Definition ADataBinding.h:85
Data binding implementation.
Definition ADataBinding.h:200
auto operator()(ModelField(Model::*field), ASignal< GetterRV >(View::*getter), Setter setter=(void(View::*)(const ModelField &)) nullptr)
Create a connection to specified pointer-to-member-field signal and pointer-to-member-function setter...
Definition ADataBinding.h:275
auto operator()(ModelField(Model::*field), void(View::*setterFunc)(SetterArg))
Create a connection to setter only.
Definition ADataBinding.h:234
auto operator()(ModelField(Model::*field), SetterLambda setterLambda)
Create a connection to specified lambda setter only.
Definition ADataBinding.h:256
emits modelChanged
Data in the model has changed.
Definition ADataBinding.h:398
auto operator()(Data(Model::*field))
Create a connection via ADataBindingDefault.
Definition ADataBinding.h:288
ADataBindingLinker2< Model, Data, Projection > operator()(Data(Model::*field), Projection projection)
Create a connection via ADataBindingDefault and projection (setter only).
Definition ADataBinding.h:298
A std::deque with AUI extensions.
Definition ADeque.h:27
StoredType & last() noexcept
Definition ADeque.h:164
static void inflate(aui::no_escape< AViewContainer > root, const _< AView > &view)
Wraps view with root using Stacked layout and expanding.
Base class of all UI objects.
Definition AView.h:78
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
Definition concepts.h:226
Invokable concept.
Definition concepts.h:37
class_of c
Selects views that are of the specified classes.
Definition class_of.h:84
static void biConnect(PropertySource &&propertySource, PropertyDestination &&propertyDestination)
Connects source property to the destination property and opposite (bidirectionally).
Definition AObject.h:156
static decltype(auto) connect(const Signal &signal, Object *object, Function &&function)
Connects signal to the slot of the specified object.
Definition AObject.h:86
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:572
#define emit
emits the specified signal in context of this object.
Definition AObject.h:343
#define AUI_ASSERT(condition)
Asserts that the passed condition evaluates to true.
Definition Assert.h:55
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74
Definition concepts.h:233
Defines how View handles properties of FieldType type.
Definition ADataBinding.h:37
static void(View::*)(const FieldType &v) getSetter()
Returns setter for ADataBinding (deprecated)
Definition ADataBinding.h:63
static void setup(const _< View > &view)
Called then view linked with field.
Definition ADataBinding.h:43
static void setup(const _< View > &view)
Definition ADataBinding.h:499
static auto property(const _< View > &view)
Returns property definition for FieldType.
Definition ADataBinding.h:49
static ASignal< FieldType >View::* getGetter()
Returns getter for ADataBinding (deprecated)
Definition ADataBinding.h:55
Definition concepts.h:188
Definition ADataBinding.h:545
Pointer to member type (not value) introspection.
Definition members.h:48
Definition parameter_pack.h:76