AUI Framework  master
Cross-platform base for C++ UI apps
Loading...
Searching...
No Matches
Declarative.h
    1/*
    2 * AUI Framework - Declarative UI toolkit for modern C++20
    3 * Copyright (C) 2020-2025 Alex2772 and Contributors
    4 *
    5 * SPDX-License-Identifier: MPL-2.0
    6 *
    7 * This Source Code Form is subject to the terms of the Mozilla Public
    8 * License, v. 2.0. If a copy of the MPL was not distributed with this
    9 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
   10 */
   11
   12#pragma once
   13
   14#include <AUI/View/AViewContainer.h>
   15#include <AUI/Util/kAUI.h>
   16#include <AUI/Traits/callables.h>
   17#include <AUI/Traits/parameter_pack.h>
   18#include <AUI/ASS/ASS.h>
   19
   20namespace aui::ui_building {
   21
   22using View = _<AView>;
   23using ViewContainer = _<AViewContainer>;
   24using ViewGroup = AVector<_<AView>>;
   25using ViewOrViewGroup = std::variant<_<AView>, AVector<_<AView>>>;
   26
   27namespace detail {
   28template <typename ViewFactory>
   29struct view_helper {
   30public:
   31    view_helper() {}
   32
   33    operator View() const { return asViewFactory()->operator()(); }
   34    operator ViewContainer() const { return asViewFactory()->operator()(); }
   35    auto operator<<(const AString& assEntry) const { return asViewFactory()->operator()() << assEntry; }
   36    template <typename T>
   37    auto operator^(const T& t) const {
   38        return asViewFactory()->operator()() ^ t;
   39    }
   40    template <typename T>
   41    auto operator+(const T& t) const {
   42        return asViewFactory()->operator()() + t;
   43    }
   44
   45    template <typename T>
   46    auto operator&(const T& t) const {
   47        return asViewFactory()->operator()() & t;
   48    }
   49
   50    template <typename T>
   51    auto operator|(const T& t) const {
   52        return asViewFactory()->operator()() | t;
   53    }
   54
   55    template <typename T>
   56    auto operator^(T&& t) const {
   57        return asViewFactory()->operator()() ^ std::forward<T>(t);
   58    }
   59    template <typename T>
   60    auto operator&(T&& t) const {
   61        return asViewFactory()->operator()() & std::forward<T>(t);
   62    }
   63    template <typename T>
   64    auto operator&&(T&& t) const {
   65        return asViewFactory()->operator()() && std::forward<T>(t);
   66    }
   67    template <typename T>
   68    auto operator+(T&& t) const {
   69        return asViewFactory()->operator()() + std::forward<T>(t);
   70    }
   71
   72    auto operator->() const { return asViewFactory()->operator()(); }
   73
   74    template <typename SignalField, typename Object, typename Function>
   75    auto connect(SignalField&& signalField, Object&& object, Function&& function) {
   76        return asViewFactory()->operator()().connect(
   77            std::forward<SignalField>(signalField), std::forward<Object>(object), std::forward<Function>(function));
   78    }
   79
   80    template <typename Object, typename Function>
   81    auto clicked(Object&& object, Function&& function) {
   82        return connect(&AView::clicked, std::forward<Object>(object), std::forward<Function>(function));
   83    }
   84
   85    template <typename SignalField, typename Function>
   86    auto connect(SignalField&& signalField, Function&& function) {
   87        return asViewFactory()->operator()().connect(
   88            std::forward<SignalField>(signalField), std::forward<Function>(function));
   89    }
   90
   91private:
   92    [[nodiscard]] ViewFactory* asViewFactory() const {
   93        return const_cast<ViewFactory*>(static_cast<const ViewFactory*>(this));
   94    }
   95};
   96
   97template <typename Item>
   98concept LayoutItemView = aui::convertible_to<Item, View>;
   99template <typename Item>
  100concept LayoutItemViewGroup = aui::convertible_to<Item, ViewGroup>;
  101template <typename Item>
  102concept LayoutItemViewFactory = aui::factory<Item, View>;
  103
  104template <typename Item>
  105concept ValidLayoutItem = LayoutItemView<Item> || LayoutItemViewGroup<Item> || LayoutItemViewFactory<Item>;
  106
  107template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
  108struct layouted_container_factory_impl {
  109private:
  110    AVector<View> mViews;
  111
  112public:
  113    template <typename... Views>
  114    layouted_container_factory_impl(Views&&... views) {
  115        mViews.reserve(sizeof...(views));
  116        static_assert(
  117            (ValidLayoutItem<Views> && ...),
  118            "One of the items passed to declarative container is not valid. "
  119            "Please check your compiler's diagnostics on constraint satisfaction.");
  120        aui::parameter_pack::for_each(
  121            [this]<ValidLayoutItem Item>(Item&& item) {
  122                constexpr bool isView = LayoutItemView<Item>;
  123                constexpr bool isViewGroup = LayoutItemViewGroup<Item>;
  124                constexpr bool isInvokable = LayoutItemViewFactory<Item>;
  125
  126                if constexpr (isViewGroup) {
  127                    auto asViewGroup = ViewGroup(item);
  128                    mViews << std::move(asViewGroup);
  129                } else if constexpr (isView) {
  130                    auto asView = View(item);
  131                    mViews << std::move(asView);
  132                } else if constexpr (isInvokable) {
  133                    mViews << item();
  134                }
  135            },
  136            std::forward<Views>(views)...);
  137    }
  138
  139    _<Container> operator()() {
  140        auto c = _new<Container>();
  141        if constexpr (!std::is_same_v<Layout, std::nullopt_t>) {
  142            c->setLayout(std::make_unique<Layout>());
  143        }
  144        c->setViews(std::move(mViews));
  145        return c;
  146    }
  147};
  148
  149template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
  150struct layouted_container_factory_impl_with_expanding : layouted_container_factory_impl<Layout, Container> {
  151public:
  152    using layouted_container_factory_impl<Layout, Container>::layouted_container_factory_impl;
  153
  154    struct Expanding : view_helper<Expanding>, layouted_container_factory_impl<Layout, Container> {
  155    public:
  156        template <typename... Views>
  157        Expanding(Views&&... views) : layouted_container_factory_impl<Layout>(std::forward<Views>(views)...) {}
  158
  159        _<Container> operator()() {
  160            return layouted_container_factory_impl<Layout>::operator()() let { it->setExpanding(); };
  161        }
  162    };
  163};
  164
  165template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
  166struct layouted_container_factory
  167  : view_helper<layouted_container_factory<Layout, Container>>,
  168    layouted_container_factory_impl_with_expanding<Layout, Container> {
  169    template <typename... Views>
  170    layouted_container_factory(Views&&... views)
  171      : layouted_container_factory_impl_with_expanding<Layout, Container>(std::forward<Views>(views)...) {}
  172};
  173
  174}   // namespace detail
  175
  179template <typename View>
  180struct view : detail::view_helper<view<View>> {
  181public:
  182    template <typename... Args>
  183    view(Args&&... args) : mView(_new<View>(std::forward<Args>(args)...)) {}
  184
  185    _<View>& operator()() { return mView; }
  186
  187    operator _<View>&() { return mView; }
  188
  189private:
  190    _<View> mView;
  191};
  192
  193static_assert(std::is_convertible_v<view<AView>, View>,
  194             "====================> AUI: declarative view wrapper (declarative::view) must be convertible to _<AView>");
  195
  196
  200template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
  201using view_container_layout = detail::layouted_container_factory<Layout, Container>;
  202
  203}   // namespace aui::ui_building
  204
  205namespace declarative {
  206
  224struct Style {
  225public:
  226    Style(std::initializer_list<Rule> rules) : mStylesheet(_new<AStylesheet>(AStylesheet(rules))) {}
  227
  228    Style& operator()(AVector<_<AView>> views) {
  229        for (const auto& view : views) {
  230            AUI_ASSERTX(view->extraStylesheet() == nullptr, "extra stylesheet already specified");
  231            view->setExtraStylesheet(mStylesheet);
  232        }
  233        mViews = std::move(views);
  234        return *this;
  235    }
  236
  237    operator AVector<_<AView>>() noexcept { return std::move(mViews); }
  238
  239private:
  240    _<AStylesheet> mStylesheet;
  241    AVector<_<AView>> mViews;
  242};
  243}   // namespace declarative
Definition AStylesheet.h:21
A std::vector with AUI extensions.
Definition AVector.h:39
emits clicked
Left mouse button clicked.
Definition AView.h:933
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:179
class_of c
Selects views that are of the specified classes.
Definition class_of.h:84
API_AUI_CORE const ACommandLineArgs & args() noexcept
#define let
Performs multiple operations on a single object without repeating its name (in place) This function c...
Definition kAUI.h:262
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74