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 {
198template <
typename Model>
199class [[deprecated(
"consider using AProperty and signal/slot connections instead")]] ADataBinding:
public AObject {
201 using Observer = std::function<void(
const Model& model,
unsigned)>;
204 Model* mModel =
nullptr;
205 bool mOwning =
false;
207 void* mExcept =
nullptr;
211 ADataBinding() =
default;
212 explicit ADataBinding(
const Model& m)
216 explicit ADataBinding(Model* m)
221 virtual ~ADataBinding() {
232 template<
typename View,
typename ModelField,
typename SetterArg>
233 auto operator()(ModelField(Model::*field),
void(View::*setterFunc)(SetterArg)) {
235 return operator()<View, ModelField>(field, (
ASignal<ModelField>(View::*))
nullptr, setterFunc);
254 template<
typename ModelField,
typename SetterLambda>
255 auto operator()(ModelField(Model::*field), SetterLambda setterLambda) {
256 using lambda_args =
typename aui::lambda_info<SetterLambda>::args;
258 static_assert(std::is_reference_v<ViewReference>,
"View is expected to be a reference");
260 using View = std::decay_t<ViewReference>;
261 return operator()<View, ModelField>(field, (
ASignal<ModelField>(View::*))
nullptr, [setterLambda = std::move(setterLambda)](View* view, DataArgument dataArgument) {
262 std::invoke(setterLambda, *view, std::forward<DataArgument>(dataArgument));
273 template<
typename View,
typename ModelField,
typename GetterRV, aui::invocable<View*, const ModelField&> Setter>
276 Setter setter = (
void(View::*)(
const ModelField&))
nullptr) {
286 template<
typename Data>
296 template<
typename Data, aui::invocable<Data> Projection>
300 const Model& getModel() const noexcept {
304 Model
const * operator->() const noexcept {
308 Model& getEditableModel() {
311 void setModel(
const Model& model) {
316 mModel =
new Model(model);
320 void setModel(Model* model) {
329 const void* getExclusion()
const {
333 void notifyUpdate(
void* except =
nullptr,
unsigned field = -1) {
335 for (
auto& applier : mLinkObservers) {
336 applier(*mModel, field);
341 template<
typename ModelField>
342 void notifyUpdate(ModelField(Model::*field)) {
348 notifyUpdate(
nullptr,
c.i);
351 template<
typename ModelField, aui::convertible_to<ModelField> U>
352 void setValue(ModelField(Model::*field), U&& value) {
353 mModel->*field = std::move(value);
357 void addObserver(Observer applier) {
358 mLinkObservers << std::move(applier);
360 mLinkObservers.
last()(*mModel, -1);
364 template<aui::invocable T>
365 void addObserver(T&& applier) {
366 addObserver([applier = std::forward<T>(applier)](
const Model&,
unsigned) {
371 template<
typename ModelField,
typename FieldObserver>
372 void addObserverNoInitialCall(ModelField(Model::*field), FieldObserver&& observer) {
373 mLinkObservers << [observer = std::forward<FieldObserver>(observer), field](
const Model& model,
unsigned index) {
379 if (
c.i == index || index == -1) {
380 observer(model.*field);
384 template<
typename ModelField,
typename FieldObserver>
385 void addObserver(ModelField(Model::*field), FieldObserver&& observer) {
386 addObserverNoInitialCall(field, std::forward<FieldObserver>(observer));
388 mLinkObservers.
last()(*mModel, -1);
400template<
typename Klass1,
typename View,
typename Model,
typename ModelField,
typename GetterRV,
typename SetterArg>
404 decltype(linker.getField()) p;
406 if (linker.getGetter()) {
407 AObject::connect(modelBinding.get()->*(linker.getGetter()), linker.getBinder(), [modelBinding, linker](
const GetterRV& data) {
408 AUI_ASSERTX(&linker.getBinder()->getEditableModel(),
"please setModel for ADataBinding");
409 modelBinding->setSignalsEnabled(false);
410 linker.getBinder()->getEditableModel().*(linker.getField()) = data;
412 c.p = linker.getField();
413 linker.getBinder()->notifyUpdate(modelBinding.get(), c.i);
414 modelBinding->setSignalsEnabled(true);
419 if (!
bool(linker.getSetterFunc())) {
423 linker.getBinder()->addObserver([modelBinding, linker](
const Model& model,
unsigned field) {
425 c.p = linker.getField();
426 if (
c.i == field || field == -1) {
427 if (modelBinding.get() != linker.getBinder()->getExclusion()) {
428 std::invoke(linker.getSetterFunc(), modelBinding.get(), model.*(linker.getField()));
437namespace aui::detail {
438 template<
typename ForcedClazz,
typename Type>
439 struct pointer_to_member {
440 template<
typename... Args>
441 static Type(ForcedClazz::*with_args(std::tuple<Args...>))(Args...) {
447template<
typename View,
typename Model,
typename Data,
typename Projection>
451 constexpr bool is_default_projection = std::is_same_v<Projection, std::nullptr_t>;
452 using projection_deduced = std::conditional_t<is_default_projection, aui::identity, Projection>;
453 static_assert(std::is_invocable_v<projection_deduced, Data>,
"projection is expected to accept Data value from model");
454 using data_deduced = std::decay_t<std::invoke_result_t<projection_deduced, Data>>;
459 using setter_ret =
typename setter::return_t;
460 using setter_args =
typename setter::args;
462 using my_pointer_to_member =
typename aui::detail::pointer_to_member<View, setter_ret>;
464 using pointer_to_setter =
decltype(my_pointer_to_member::with_args(std::declval<setter_args>()));
466 if constexpr (is_default_projection) {
479 AUI_ASSERTX(g !=
nullptr || s !=
nullptr,
"ADataBindingDefault is not defined for View, Data");
481 object && (*linker.getBinder())(linker.getField(), g, s);
483 object && (*linker.getBinder())(linker.getField(), [projection = linker.getProjection()](View& v,
const Data& d) {
484 auto s = static_cast<pointer_to_setter>(ADataBindingDefault<View, data_deduced>::getSetter());
485 std::invoke(s, &v, projection(d));
491template<
typename View>
501 return &AView::setVisibility;
505template <
typename Object, APropertyReadable Connectable>
511 requires { { Binding::property(
object) } ->
AAnyProperty; } ||
513 "ADataBindingDefault is required to have property() function to return any property or slot def; either "
514 "define proper ADataBindingDefault specialization or explicitly specify the destination property.");
516 requires { { Binding::setup(
object) }; },
517 "ADataBindingDefault is required to have setup(const _<Object>&) function; either define proper "
518 "ADataBindingDefault specialization or explicitly specify the destination property.");
519 Binding::setup(
object);
525template<
typename Object, APropertyWritable Connectable>
529 static_assert(
requires {
531 },
"ADataBindingDefault is required to have property() function to return any property; either define proper "
532 "ADataBindingDefault specialization or explicitly specify the destination property.");
534 requires { { Binding::setup(
object) }; },
535 "ADataBindingDefault is required to have setup(const _<Object>&) function; either define proper "
536 "ADataBindingDefault specialization or explicitly specify the destination property.");
537 Binding::setup(
object);
543template <AAnyProperty Lhs,
typename Destination>
546 Destination destinationPointerToMember;
547 explicit Binding(Lhs sourceProperty, Destination destinationPointerToMember)
548 : sourceProperty(sourceProperty), destinationPointerToMember(destinationPointerToMember) {}
551template <AAnyProperty Property,
typename Destination>
552inline decltype(
auto)
operator>(Property&& sourceProperty, Destination&& rhs) {
556template <
typename Object, APropertyReadable Property,
typename Destination>
560 { std::invoke(binding.destinationPointerToMember, *
object) } ->
AAnyProperty;
563 AObject::connect(binding.sourceProperty, std::invoke(binding.destinationPointerToMember, *
object));
567template <
typename Object, APropertyWritable Property,
typename Destination>
571 { std::invoke(binding.destinationPointerToMember, *
object) } ->
AAnyProperty;
574 AObject::biConnect(binding.sourceProperty, std::invoke(binding.destinationPointerToMember, *
object));
579template <
typename Object, APropertyReadable Property,
typename Destination>
582 { binding.destinationPointerToMember } ->
aui::invocable<Object&,
decltype(*binding.sourceProperty)>;
586 binding.sourceProperty,
object.get(),
587 [
object =
object.get(), wrapped = std::move(binding.destinationPointerToMember)](
588 const std::decay_t<
decltype(*binding.sourceProperty)>& i) { std::invoke(wrapped, *object, i); });
592template <
typename Object, APropertyWritable Property,
typename Destination>
595 { binding.destinationPointerToMember } ->
aui::invocable<Object&,
decltype(*binding.sourceProperty)>;
599 binding.sourceProperty,
object.get(),
600 [
object =
object.get(), wrapped = std::move(binding.destinationPointerToMember)](
601 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:199
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:274
auto operator()(ModelField(Model::*field), void(View::*setterFunc)(SetterArg))
Create a connection to setter only.
Definition ADataBinding.h:233
auto operator()(ModelField(Model::*field), SetterLambda setterLambda)
Create a connection to specified lambda setter only.
Definition ADataBinding.h:255
emits modelChanged
Data in the model has changed.
Definition ADataBinding.h:397
auto operator()(Data(Model::*field))
Create a connection via ADataBindingDefault.
Definition ADataBinding.h:287
ADataBindingLinker2< Model, Data, Projection > operator()(Data(Model::*field), Projection projection)
Create a connection via ADataBindingDefault and projection (setter only).
Definition ADataBinding.h:297
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.
Definition ALayoutInflater.cpp:20
Base class of all UI objects.
Definition AView.h:78
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:178
Definition concepts.h:223
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:135
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:348
#define emit
emits the specified signal in context of this object.
Definition AObject.h:310
static void connect(const Signal &signal, Object *object, Function &&function)
Connects signal to the slot of the specified object.
Definition AObject.h:65
#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:230
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:498
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:544
Definition parameter_pack.h:76