GMLCompiler: Add common pattern for a user-defined fallible initializer

Many widget classes need to run substantial initialization code after
they have been setup from GML. With this change, an
initialize_fallibles() function is called if available, allowing the
initialization to be invoked from the GML setup automatically. This
means that the GML-generated creation function can now be used directly
for many more cases, and reduces code duplication.
This commit is contained in:
kleines Filmröllchen 2024-01-25 14:11:38 +01:00 committed by Andrew Kaster
parent 8878e0c815
commit dec066fa5c
3 changed files with 24 additions and 0 deletions

View file

@ -50,3 +50,16 @@ From there, you can use `find_descendant_of_type_named` to select widgets from y
// MyApp::Widget::foo_bar
m_mem_add_button = *find_descendant_of_type_named<GUI::Button>("mem_add_button");
```
### `initialize` Pattern
Initialization, like adding models, attaching callbacks, etc., should be done in a member function with the signature:
```cpp
// MyApp::Widget
ErrorOr<void> initialize();
```
This initializer function, if it exists, will automatically be called after the structure of your widget was set up by the auto-generated GML code.
The only case where this function cannot be used is when your initialization requires additional parameters, like a GUI window. You may still consider moving as much initialization to the canonical function as possible.

View file

@ -334,6 +334,8 @@ static ErrorOr<void> generate_loader_for_object(GUI::GML::Object const& gml_obje
return {};
}));
TRY(append(generator, "TRY(::GUI::initialize(*@object_name@));"));
generator.append(TRY(String::repeated(' ', (indentation - 1) * 4)).bytes_as_string_view());
generator.appendln("}");

View file

@ -71,6 +71,15 @@ enum class AllowCallback {
Yes
};
template<typename T>
ALWAYS_INLINE ErrorOr<void> initialize(T& object)
{
if constexpr (requires { { object.initialize() } -> SameAs<ErrorOr<void>>; })
return object.initialize();
else
return {};
}
class Widget : public GUI::Object {
C_OBJECT(Widget)
public: