14#include "AUI/Traits/concepts.h"
17#include <AUI/Common/SharedPtr.h>
18#include <AUI/Common/ASignal.h>
19#include <AUI/Traits/members.h>
20#include <AUI/View/AView.h>
23template<
typename View,
typename FieldType>
35 static void(View::*getSetter())(
const FieldType& v) {
40template <
typename Model>
43template<
typename Model,
typename View,
typename ModelField,
typename Getter, aui::invocable<View*, const ModelField&> Setter>
48 std::decay_t<ModelField>(Model::*mField);
53 std::decay_t<ModelField>(Model::*field)):
54 mBinder(binder), mGetter(getter), setter(std::move(setter)), mField(field) {}
60 auto getSetterFunc()
const {
64 auto getField()
const {
68 auto getGetter()
const {
72template<
typename Model,
typename Data,
typename Projection>
77 Projection mProjection;
86 auto getField()
const {
90 Projection getProjection()
const {
157template <
typename Model>
160 using Observer = std::function<void(
const Model& model,
unsigned)>;
163 Model* mModel =
nullptr;
164 bool mOwning =
false;
166 void* mExcept =
nullptr;
191 template<
typename View,
typename ModelField,
typename SetterArg>
192 auto operator()(ModelField(Model::*field),
void(View::*setterFunc)(SetterArg)) {
194 return operator()<View, ModelField>(field, (
ASignal<ModelField>(View::*))
nullptr, setterFunc);
213 template<
typename ModelField,
typename SetterLambda>
214 auto operator()(ModelField(Model::*field), SetterLambda setterLambda) {
217 static_assert(std::is_reference_v<ViewReference>,
"View is expected to be a reference");
218 static_assert(aui::convertible_to<ModelField, DataArgument>,
"lambda's argument is expected to be constructible from ModelField");
219 using View = std::decay_t<ViewReference>;
220 return operator()<View, ModelField>(field, (
ASignal<ModelField>(View::*))
nullptr, [setterLambda = std::move(setterLambda)](View* view, DataArgument dataArgument) {
221 std::invoke(setterLambda, *view, std::forward<DataArgument>(dataArgument));
230 template<
typename View,
typename ModelField,
typename GetterRV, aui::invocable<View*, const ModelField&> Setter>
233 Setter setter = (
void(View::*)(
const ModelField&))
nullptr) {
243 template<
typename Data>
253 template<
typename Data, aui::invocable<Data> Projection>
257 const Model& getModel() const noexcept {
261 Model
const * operator->() const noexcept {
265 Model& getEditableModel() {
268 void setModel(
const Model& model) {
273 mModel =
new Model(model);
277 void setModel(Model* model) {
286 const void* getExclusion()
const {
290 void notifyUpdate(
void* except =
nullptr,
unsigned field = -1) {
292 for (
auto& applier : mLinkObservers) {
293 applier(*mModel, field);
298 template<
typename ModelField>
299 void notifyUpdate(ModelField(Model::*field)) {
305 notifyUpdate(
nullptr, c.i);
308 template<
typename ModelField, aui::convertible_to<ModelField> U>
309 void setValue(ModelField(Model::*field), U&& value) {
310 mModel->*field = std::move(value);
314 void addObserver(Observer applier) {
315 mLinkObservers << std::move(applier);
317 mLinkObservers.
last()(*mModel, -1);
321 template<aui::invocable T>
322 void addObserver(T&& applier) {
323 addObserver([applier = std::forward<T>(applier)](
const Model&,
unsigned) {
328 template<
typename ModelField,
typename FieldObserver>
329 void addObserverNoInitialCall(ModelField(Model::*field), FieldObserver&& observer) {
330 mLinkObservers << [observer = std::forward<FieldObserver>(observer), field](
const Model& model,
unsigned index) {
336 if (c.i == index || index == -1) {
337 observer(model.*field);
341 template<
typename ModelField,
typename FieldObserver>
342 void addObserver(ModelField(Model::*field), FieldObserver&& observer) {
343 addObserverNoInitialCall(field, std::forward<FieldObserver>(observer));
345 mLinkObservers.
last()(*mModel, -1);
357template<
typename Klass1,
typename View,
typename Model,
typename ModelField,
typename GetterRV,
typename SetterArg>
361 decltype(linker.getField()) p;
363 if (linker.getGetter()) {
364 AObject::connect(modelBinding.get()->*(linker.getGetter()), linker.getBinder(), [modelBinding, linker](
const GetterRV& data) {
365 AUI_ASSERTX(&linker.getBinder()->getEditableModel(),
"please setModel for ADataBinding");
366 modelBinding->setSignalsEnabled(false);
367 linker.getBinder()->getEditableModel().*(linker.getField()) = data;
369 c.p = linker.getField();
370 linker.getBinder()->notifyUpdate(modelBinding.get(), c.i);
371 modelBinding->setSignalsEnabled(true);
375 if constexpr (aui::convertible_to<
decltype(linker.getSetterFunc()),
bool>) {
376 if (!
bool(linker.getSetterFunc())) {
380 linker.getBinder()->addObserver([modelBinding, linker](
const Model& model,
unsigned field) {
382 c.p = linker.getField();
383 if (c.i == field || field == -1) {
384 if (modelBinding.get() != linker.getBinder()->getExclusion()) {
385 std::invoke(linker.getSetterFunc(), modelBinding.get(), model.*(linker.getField()));
394namespace aui::detail {
395 template<
typename ForcedClazz,
typename Type>
397 template<
typename... Args>
398 static Type(ForcedClazz::*with_args(std::tuple<Args...>))(Args...) {
404template<
typename View,
typename Model,
typename Data,
typename Projection>
408 constexpr bool is_default_projection = std::is_same_v<Projection, std::nullptr_t>;
409 using projection_deduced = std::conditional_t<is_default_projection, aui::identity, Projection>;
410 static_assert(std::is_invocable_v<projection_deduced, Data>,
"projection is expected to accept Data value from model");
411 using data_deduced = std::decay_t<std::invoke_result_t<projection_deduced, Data>>;
416 using setter_ret =
typename setter::return_t;
421 using pointer_to_setter =
decltype(my_pointer_to_member::with_args(std::declval<setter_args>()));
423 if constexpr (is_default_projection) {
431 AUI_ASSERTX(g !=
nullptr || s !=
nullptr,
"ADataBindingDefault is not defined for View, Data");
433 object && (*linker.getBinder())(linker.getField(), g, s);
435 object && (*linker.getBinder())(linker.getField(), [projection = linker.getProjection()](View& v,
const Data& d) {
437 std::invoke(s, &v, projection(d));
443template<
typename View>
452 static auto getSetter() {
453 return &AView::setVisibility;
Definition: ADataBinding.h:73
Definition: ADataBinding.h:44
Data binding implementation.
Definition: ADataBinding.h:158
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:231
auto operator()(ModelField(Model::*field), void(View::*setterFunc)(SetterArg))
Create a connection to setter only.
Definition: ADataBinding.h:192
auto operator()(ModelField(Model::*field), SetterLambda setterLambda)
Create a connection to specified lambda setter only.
Definition: ADataBinding.h:214
emits modelChanged
Data in the model has changed.
Definition: ADataBinding.h:354
auto operator()(Data(Model::*field))
Create a connection via ADataBindingDefault.
Definition: ADataBinding.h:244
ADataBindingLinker2< Model, Data, Projection > operator()(Data(Model::*field), Projection projection)
Create a connection via ADataBindingDefault and projection (setter only).
Definition: ADataBinding.h:254
A std::deque with AUI extensions.
Definition: ADeque.h:27
StoredType & last() noexcept
Definition: ADeque.h:164
A base object class.
Definition: AObject.h:49
An std::weak_ptr with AUI extensions.
Definition: SharedPtrTypes.h:177
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition: OSAndroid.cpp:29
#define emit
emits the specified signal in context of this object.
Definition: AObject.h:196
#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
static void setup(const _< View > &view)
Definition: ADataBinding.h:450
Definition: ADataBinding.h:24
static void setup(const _< View > &view)
Definition: ADataBinding.h:30
Definition: ADataBinding.h:396
Definition: parameter_pack.h:76