AUI Framework  develop
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-2024 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^(T&& t) const {
47 return asViewFactory()->operator()() ^ std::forward<T>(t);
48 }
49 template <typename T>
50 auto operator&(T&& t) const {
51 return asViewFactory()->operator()() & std::forward<T>(t);
52 }
53 template <typename T>
54 auto operator&&(T&& t) const {
55 return asViewFactory()->operator()() && std::forward<T>(t);
56 }
57 template <typename T>
58 auto operator+(T&& t) const {
59 return asViewFactory()->operator()() + std::forward<T>(t);
60 }
61
62 auto operator->() const { return asViewFactory()->operator()(); }
63
64 template <typename SignalField, typename Object, typename Function>
65 auto connect(SignalField&& signalField, Object&& object, Function&& function) {
66 return asViewFactory()->operator()().connect(
67 std::forward<SignalField>(signalField), std::forward<Object>(object), std::forward<Function>(function));
68 }
69
70 template <typename Object, typename Function>
71 auto clicked(Object&& object, Function&& function) {
72 return connect(&AView::clicked, std::forward<Object>(object), std::forward<Function>(function));
73 }
74
75 template <typename SignalField, typename Function>
76 auto connect(SignalField&& signalField, Function&& function) {
77 return asViewFactory()->operator()().connect(
78 std::forward<SignalField>(signalField), std::forward<Function>(function));
79 }
80
81private:
82 [[nodiscard]] ViewFactory* asViewFactory() const {
83 return const_cast<ViewFactory*>(static_cast<const ViewFactory*>(this));
84 }
85};
86
87template <typename Item>
88concept LayoutItemView = aui::convertible_to<Item, View>;
89template <typename Item>
90concept LayoutItemViewGroup = aui::convertible_to<Item, ViewGroup>;
91template <typename Item>
92concept LayoutItemViewFactory = aui::factory<Item, View>;
93
94template <typename Item>
95concept ValidLayoutItem = LayoutItemView<Item> || LayoutItemViewGroup<Item> || LayoutItemViewFactory<Item>;
96
97template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
98struct layouted_container_factory_impl {
99private:
100 AVector<View> mViews;
101
102public:
103 template <typename... Views>
104 layouted_container_factory_impl(Views&&... views) {
105 mViews.reserve(sizeof...(views));
106 static_assert(
107 (ValidLayoutItem<Views> && ...),
108 "One of the items passed to declarative container is not valid. "
109 "Please check your compiler's diagnostics on constraint satisfaction.");
110 aui::parameter_pack::for_each(
111 [this]<ValidLayoutItem Item>(Item&& item) {
112 constexpr bool isView = LayoutItemView<Item>;
113 constexpr bool isViewGroup = LayoutItemViewGroup<Item>;
114 constexpr bool isInvokable = LayoutItemViewFactory<Item>;
115
116 if constexpr (isViewGroup) {
117 auto asViewGroup = ViewGroup(item);
118 mViews << std::move(asViewGroup);
119 } else if constexpr (isView) {
120 auto asView = View(item);
121 mViews << std::move(asView);
122 } else if constexpr (isInvokable) {
123 mViews << item();
124 }
125 },
126 std::forward<Views>(views)...);
127 }
128
129 _<Container> operator()() {
130 auto c = _new<Container>();
131 if constexpr (!std::is_same_v<Layout, std::nullopt_t>) {
132 c->setLayout(std::make_unique<Layout>());
133 }
134 c->setViews(std::move(mViews));
135 return c;
136 }
137};
138
139template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
140struct layouted_container_factory_impl_with_expanding : layouted_container_factory_impl<Layout, Container> {
141public:
142 using layouted_container_factory_impl<Layout, Container>::layouted_container_factory_impl;
143
144 struct Expanding : view_helper<Expanding>, layouted_container_factory_impl<Layout, Container> {
145 public:
146 template <typename... Views>
147 Expanding(Views&&... views) : layouted_container_factory_impl<Layout>(std::forward<Views>(views)...) {}
148
149 _<Container> operator()() {
150 return layouted_container_factory_impl<Layout>::operator()() let { it->setExpanding(); };
151 }
152 };
153};
154
155template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
156struct layouted_container_factory
157 : view_helper<layouted_container_factory<Layout, Container>>,
158 layouted_container_factory_impl_with_expanding<Layout, Container> {
159 template <typename... Views>
160 layouted_container_factory(Views&&... views)
161 : layouted_container_factory_impl_with_expanding<Layout, Container>(std::forward<Views>(views)...) {}
162};
163
164} // namespace detail
165
169template <typename View>
170struct view : detail::view_helper<view<View>> {
171public:
172 template <typename... Args>
173 view(Args&&... args) : mView(_new<View>(std::forward<Args>(args)...)) {}
174
175 _<View>& operator()() { return mView; }
176
177 operator _<View>&() { return mView; }
178
179private:
180 _<View> mView;
181};
182
183static_assert(std::is_convertible_v<view<AView>, View>, "declarative view wrapper must be convertible to _<AView>");
184
185
189template <typename Layout, aui::derived_from<AViewContainer> Container = AViewContainer>
190using view_container_layout = detail::layouted_container_factory<Layout, Container>;
191
192} // namespace aui::ui_building
193
194namespace declarative {
195
213struct Style {
214public:
215 Style(std::initializer_list<Rule> rules) : mStylesheet(_new<AStylesheet>(AStylesheet(rules))) {}
216
217 Style& operator()(AVector<_<AView>> views) {
218 for (const auto& view : views) {
219 AUI_ASSERTX(view->extraStylesheet() == nullptr, "extra stylesheet already specified");
220 view->setExtraStylesheet(mStylesheet);
221 }
222 mViews = std::move(views);
223 return *this;
224 }
225
226 operator AVector<_<AView>>() noexcept { return std::move(mViews); }
227
228private:
229 _<AStylesheet> mStylesheet;
230 AVector<_<AView>> mViews;
231};
232} // 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:900
An std::weak_ptr with AUI extensions.
Definition SharedPtrTypes.h:178
class_of c
Selects views that are of the specified classes.
Definition class_of.h:84
API_AUI_CORE const ACommandLineArgs & args() noexcept
Definition OSAndroid.cpp:29
#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