MCRO
C++23 utilities for Unreal Engine.
Loading...
Searching...
No Matches
Slate.h
Go to the documentation of this file.
1/** @noop License Comment
2 * @file
3 * @copyright
4 * This Source Code is subject to the terms of the Mozilla Public License, v2.0.
5 * If a copy of the MPL was not distributed with this file You can obtain one at
6 * https://mozilla.org/MPL/2.0/
7 *
8 * @author David Mórász
9 * @date 2025
10 */
11
12#pragma once
13
14#include "CoreMinimal.h"
15#include "Mcro/FunctionTraits.h"
16
17/** Extra functionalities for general Slate programming chores, including enhancements of the Slate declarative syntax */
18namespace Mcro::Slate
19{
20 using namespace Mcro::FunctionTraits;
21
22 /** Constraining given type to a Slate widget */
23 template <typename T>
24 concept CWidget = CDerivedFrom<T, SWidget>;
25
26 /** Constraining given type to a slot of a widget */
27 template <typename T>
28 concept CSlot = CDerivedFrom<T, FSlotBase>;
29
30 /** Constraining given type to either a slot or a widget */
31 template <typename T>
33
34 /** Constraining given type to the arguments of either a widget or a slot */
35 template <typename T>
36 concept CWidgetOrSlotArguments = CSameAsDecayed<T, typename T::WidgetArgsType>;
37
38 /** Constraining given type to the arguments of a widget */
39 template <typename T>
40 concept CWidgetArguments = requires(typename T::WidgetType& t) { t; };
41
42 /** Constraining given type to the arguments of a slot */
43 template <typename T>
44 concept CSlotArguments = CDerivedFrom<T, FSlotBase::FSlotArguments>
45 && requires(T& args)
46 {
47 args.GetSlot();
48 }
49 ;
50
51 /** Constraining given type to a widget which can receive slots */
52 template <typename T>
53 concept CWidgetWithSlots = requires(typename T::FSlot&)
54 {
55 T::Slot();
56 };
57
58 template <typename T>
59 struct TArgumentsOf_S {};
60
61 template <CWidget T>
62 struct TArgumentsOf_S<T>
63 {
64 using Type = typename T::FArguments;
65 };
66
67 template <CSlot T>
69 {
70 using Type = typename T::FSlotArguments;
71 };
72
73 /** Get the type of arguments from either a widget or a slot type (FArguments or FSlotArguments) */
74 template <typename T>
76
77 /**
78 * Alias for an attribute block function which takes in reference of FArguments or FSlotArguments and returns the
79 * same reference but presumably setting some Slate attributes before that. This is useful for modularizing the
80 * Slate declarative syntax.
81 */
82 template <CWidgetOrSlot T>
83 using TAttributeBlock = TUniqueFunction<TArgumentsOf<T>&(TArgumentsOf<T>&)>;
84
85 /** Same as TAttributeBlock but allows to make copies of the functor */
86 template <CWidgetOrSlot T>
87 using TAttributeBlockCopyable = TFunction<TArgumentsOf<T>&(TArgumentsOf<T>&)>;
88
89 /** An attribute block which does nothing */
90 template <CWidgetOrSlot T>
91 TAttributeBlock<T> InertAttributeBlock = [](TArgumentsOf<T>& args) -> auto& { return args; };
92
93 /**
94 * The "append attribute block" operator which allows pre-defined "blocks of slate attributes" naturally fit inside
95 * the Slate declarative syntax. Traditionally repeated structures in Slate were expressed as either explicit
96 * mutations on widgets after they were created or as entirely separate compound widgets. Either way breaks the
97 * flow of the declarative syntax and makes using Slate sometimes pretty clunky. This operator aims to make widget
98 * composition more comfortable.
99 *
100 * @tparam Arguments Right hand side FArguments or FSlotArguments
101 * @tparam AttrBlock The type of the attribute block function
102 * @param args l-value reference right hand side FArguments or FSlotArguments
103 * @param attributes An attribute block function
104 * @return The same reference as args or a new slot if that has been added inside the attribute block
105 */
106 template <CWidgetOrSlotArguments Arguments, CFunctionLike AttrBlock>
107 requires (
109 && CSameAs<Arguments&, TFunction_Arg<AttrBlock, 0>>
110 )
111 TFunction_Return<AttrBlock> operator / (Arguments& args, const AttrBlock& attributes)
112 {
113 return attributes(args);
114 }
115
116 /**
117 * The "append attribute block" operator which allows pre-defined "blocks of slate attributes" naturally fit inside
118 * the Slate declarative syntax. Traditionally repeated structures in Slate were expressed as either explicit
119 * mutations on widgets after they were created or as entirely separate compound widgets. Either way breaks the
120 * flow of the declarative syntax and makes using Slate sometimes pretty clunky. This operator aims to make widget
121 * composition more comfortable.
122 *
123 * @tparam Arguments Right hand side FArguments or FSlotArguments
124 * @tparam AttrBlock The type of the attribute block function
125 * @param args r-value reference right hand side FArguments or FSlotArguments
126 * @param attributes An attribute block function
127 * @return The same reference as args or a new slot if that has been added inside the attribute block
128 */
129 template <CWidgetOrSlotArguments Arguments, CFunctionLike AttrBlock>
130 requires (
132 && CSameAs<Arguments&, TFunction_Arg<AttrBlock, 0>>
133 )
134 TFunction_Return<AttrBlock> operator / (Arguments&& args, const AttrBlock& attributes)
135 {
136 return attributes(args);
137 }
138
139 /**
140 * Add multiple slots at the same time with the declarative syntax derived from an input data array.
141 *
142 * @code
143 * void SMyWidget::Construct(const FArguments& args)
144 * {
145 * using namespace Mcro::Slate;
146 *
147 * ChildSlot
148 * [
149 * SNew(SVerticalBox)
150 * + TSlots(args._DataArray, [](const FMyData& data)
151 * {
152 * FText dataText = FText::FromString(data.ToString());
153 * return SVerticalBox::Slot()
154 * . HAlign(HAlign_Fill)
155 * . AutoHeight()
156 * [
157 * SNew(STextBlock)
158 * . Text(dataText)
159 * ];
160 * })
161 * + SVerticalBox::Slot()
162 * . HAlign(HAlign_Fill)
163 * . AutoHeight()
164 * [
165 * SNew(STextBlock)
166 * . Text(INVTEXT("Footer after the list of data"))
167 * ]
168 * ];
169 * }
170 * @endcode
171 */
172 template <
173 CRange Range,
174 CFunctionLike Transform,
175 CFunctionLike OnEmpty = TUniqueFunction<TFunction_Return<Transform>()>,
176 CSlotArguments SlotArguments = TFunction_Return<Transform>
177 >
178 requires (TFunction_ArgCount<Transform> == 1)
179 struct TSlots
180 {
181 TSlots(const Range& range, Transform&& transform, TOptional<OnEmpty>&& onEmpty = {})
182 : RangeRef(range)
183 , TransformStorage(MoveTemp(transform))
184 , OnEmptyStorage(MoveTemp(onEmpty))
185 {}
186
187 TSlots(const TSlots&) = delete;
188 TSlots(TSlots&& o) noexcept
189 : RangeRef(o.RangeRef),
190 TransformStorage(MoveTemp(o.TransformStorage)),
191 OnEmptyStorage(MoveTemp(o.OnEmptyStorage))
192 {
193 }
194
195 TSlots& operator=(const TSlots&) = delete;
196 TSlots& operator=(TSlots&& o) noexcept
197 {
198 if (this == &o)
199 return *this;
200 RangeRef = o.RangeRef;
201 TransformStorage = MoveTemp(o.TransformStorage);
202 OnEmptyStorage = MoveTemp(o.OnEmptyStorage);
203 return *this;
204 }
205
206 template <CWidgetArguments Arguments>
207 void Append(Arguments& args)
208 {
209 if (RangeRef.begin() == RangeRef.end() && OnEmptyStorage.IsSet())
210 {
211 args + OnEmptyStorage.GetValue()();
212 return;
213 }
214
215 for (auto it = RangeRef.begin(); it != RangeRef.end(); ++it)
216 args + TransformStorage(*it);
217 }
218
219 private:
220 const Range& RangeRef;
221 Transform TransformStorage;
222 TOptional<OnEmpty> OnEmptyStorage;
223 };
224
225 template <
226 CRange Range,
227 CFunctionLike Transform,
228 CFunctionLike OnEmpty,
229 CSlotArguments SlotArguments,
230 CWidgetArguments Arguments
231 >
233 {
234 slots.Append(args);
235 return args;
236 }
237
238 MCRO_API EVisibility IsVisible(bool visible, EVisibility hiddenState = EVisibility::Collapsed);
239}
typename TFunctionTraits< std::decay_t< T > >::Return TFunction_Return
constexpr size_t TFunction_ArgCount
TUniqueFunction< TArgumentsOf< T > &(TArgumentsOf< T > &)> TAttributeBlock
Definition Slate.h:83
MCRO_API EVisibility IsVisible(bool visible, EVisibility hiddenState=EVisibility::Collapsed)
Arguments & operator+(Arguments &args, TSlots< Range, Transform, OnEmpty, SlotArguments > &&slots)
Definition Slate.h:232
typename TArgumentsOf_S< T >::Type TArgumentsOf
Definition Slate.h:75
TFunction< TArgumentsOf< T > &(TArgumentsOf< T > &)> TAttributeBlockCopyable
Definition Slate.h:87
TAttributeBlock< T > InertAttributeBlock
Definition Slate.h:91
typename T::FArguments Type
Definition Slate.h:64
TSlots & operator=(TSlots &&o) noexcept
Definition Slate.h:196
TSlots & operator=(const TSlots &)=delete
TSlots(const Range &range, Transform &&transform, TOptional< OnEmpty > &&onEmpty={})
Definition Slate.h:181
TSlots(TSlots &&o) noexcept
Definition Slate.h:188
TSlots(const TSlots &)=delete
void Append(Arguments &args)
Definition Slate.h:207