AUI Framework  develop
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
APropertyDef.h
    1#pragma once
    2
    3#include <AUI/Common/detail/property.h>
    4
   20template <
   22typename SignalArg>
   23struct APropertyDef {
   27    const M* base;
   28    using Model = M;
   29
   33    Getter get;
   34
   50    Setter set;
   51    using GetterReturnT = decltype(std::invoke(get, base));
   52    using Underlying = std::decay_t<GetterReturnT>;
   53
   58    static_assert(aui::same_as<Underlying , std::decay_t<SignalArg>>, "different getter result and signal arg?");
   59
   60    // this ctor effectively prohibits designated initialization, i.e., this one is not possible:
   61    //
   62    // auto size() const {
   63    //     return APropertyDef {
   64    //         .base = this,
   65    //         .get = &AView::mSize,
   66    //         .set = &AView::setSize,
   67    //         .changed = mSizeChanged,
   68    //     };
   69    // }
   70    //
   71    // deduction in designated initializers is relatively recent feature.
   72    APropertyDef(const M* base, Getter get, Setter set, const emits<SignalArg>& changed)
   73        : base(base), get(std::move(get)), set(std::move(set)), changed(changed) {}
   74
   75    template <aui::convertible_to<Underlying> U>
   76    APropertyDef& operator=(U&& u) {
   77        std::invoke(set, *const_cast<Model*>(base), std::forward<U>(u));
   78        return *this;
   79    }
   80
   81    [[nodiscard]]
   82    GetterReturnT value() const noexcept {
   83        return std::invoke(get, base);
   84    }
   85
   86    [[nodiscard]]
   87    GetterReturnT operator*() const noexcept {
   88        return std::invoke(get, base);
   89    }
   90
   91    [[nodiscard]]
   92    const Underlying* operator->() const noexcept {
   93        return &std::invoke(get, base);
   94    }
   95
   96    [[nodiscard]] operator GetterReturnT() const noexcept { return std::invoke(get, base); }
   97
   98    [[nodiscard]]
   99    M* boundObject() const {
  100        return const_cast<M*>(base);
  101    }
  102
  106    template <aui::invocable<const Underlying&> Projection>
  107    [[nodiscard]]
  108    auto readProjected(Projection&& projection) noexcept {
  109        return aui::detail::property::makeReadonlyProjection(std::move(*this), std::forward<Projection>(projection));
  110    }
  111
  115    template <
  116        aui::invocable<const Underlying&> ProjectionRead,
  118    [[nodiscard]]
  119    auto biProjected(ProjectionRead&& projectionRead, ProjectionWrite&& projectionWrite) noexcept {
  120        return aui::detail::property::makeBidirectionalProjection(
  121            std::move(*this), std::forward<ProjectionRead>(projectionRead),
  122            std::forward<ProjectionWrite>(projectionWrite));
  123    }
  124
  128    template <aui::detail::property::ProjectionBidirectional<Underlying> Projection>
  129    [[nodiscard]]
  130    auto biProjected(Projection&& projectionBidirectional) noexcept {
  131        return aui::detail::property::makeBidirectionalProjection(std::move(*this), projectionBidirectional);
  132    };
  133
  138        return { std::move(*this) };
  139    }
  140
  144    void notify() {
  145        if (changed.hasOutgoingConnections()) {
  146            emit changed(this->value());
  147        }
  148    }
  149
  150private:
  151    friend class AObject;
  155    [[nodiscard]]
  156    auto assignment() noexcept {
  157        return aui::detail::property::makeAssignment(std::move(*this));
  158    }
  159};
  160
  161// implementation of property modifier for APropertyDef (in comparison to AProperty) has to call getter, store a copy
  162// within PropertyModifier and call setter upon destruction.
  163// this behaviour described here - https://aui-framework.github.io/develop/structAPropertyDef.html#declaration
  164template <
  166    typename SignalArg>
  167class aui::PropertyModifier<APropertyDef<M, Getter, Setter, SignalArg>> {
  168public:
  169    using Property = APropertyDef<M, Getter, Setter, SignalArg>;
  170    using Underlying = std::decay_t<typename Property::Underlying>;
  171    PropertyModifier(Property owner): mOwner(std::move(owner)), mCopyOfValue(*mOwner) {}
  172    ~PropertyModifier() {
  173        mOwner = std::move(mCopyOfValue); // calls setter
  174    }
  175
  176    [[nodiscard]]
  177    Underlying& value() const noexcept {
  178        return mCopyOfValue;
  179    }
  180
  181    [[nodiscard]]
  182    Underlying* operator->() const noexcept {
  183        return &value();
  184    }
  185
  186private:
  187    Property mOwner;
  188    mutable Underlying mCopyOfValue;
  189};
A base object class.
Definition AObject.h:39
Temporary transparent object that gains write access to underlying property's value,...
Definition PropertyModifier.h:26
Invokable concept.
Definition concepts.h:37
Definition concepts.h:70
ASignal< Args... > emits
A signal declaration.
Definition ASignal.h:577
#define emit
emits the specified signal in context of this object.
Definition AObject.h:344
Property implementation to use with custom getter/setter.
Definition APropertyDef.h:23
void notify()
Notify observers that a change was occurred (no preconditions).
Definition APropertyDef.h:144
const M * base
AObject which this property belongs to.
Definition APropertyDef.h:27
Getter get
Getter. Can be pointer-to-member(function or field) or lambda.
Definition APropertyDef.h:33
aui::PropertyModifier< APropertyDef > writeScope() noexcept
Definition APropertyDef.h:137
Setter set
Setter. Can be pointer-to-member(function or field) or lambda.
Definition APropertyDef.h:50
auto biProjected(ProjectionRead &&projectionRead, ProjectionWrite &&projectionWrite) noexcept
Makes a bidirectional projection of this property.
Definition APropertyDef.h:119
const emits< SignalArg > & changed
Reference to underlying signal emitting on value changes.
Definition APropertyDef.h:57
auto biProjected(Projection &&projectionBidirectional) noexcept
Makes a bidirectional projection of this property (by a single aui::lambda_overloaded).
Definition APropertyDef.h:130
auto readProjected(Projection &&projection) noexcept
Makes a readonly projection of this property.
Definition APropertyDef.h:108