From dec066fa5cf5cf9466399426e937862d796f146e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Thu, 25 Jan 2024 14:11:38 +0100 Subject: [PATCH] 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. --- Base/usr/share/man/man5/GML/Usage.md | 13 +++++++++++++ .../Lagom/Tools/CodeGenerators/GMLCompiler/main.cpp | 2 ++ Userland/Libraries/LibGUI/Widget.h | 9 +++++++++ 3 files changed, 24 insertions(+) diff --git a/Base/usr/share/man/man5/GML/Usage.md b/Base/usr/share/man/man5/GML/Usage.md index d9d176b6bf..9d23f0e8e9 100644 --- a/Base/usr/share/man/man5/GML/Usage.md +++ b/Base/usr/share/man/man5/GML/Usage.md @@ -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("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 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. diff --git a/Meta/Lagom/Tools/CodeGenerators/GMLCompiler/main.cpp b/Meta/Lagom/Tools/CodeGenerators/GMLCompiler/main.cpp index c45b1a7e41..c66ca158b4 100644 --- a/Meta/Lagom/Tools/CodeGenerators/GMLCompiler/main.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/GMLCompiler/main.cpp @@ -334,6 +334,8 @@ static ErrorOr 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("}"); diff --git a/Userland/Libraries/LibGUI/Widget.h b/Userland/Libraries/LibGUI/Widget.h index 642128c9b4..5fc9606a1c 100644 --- a/Userland/Libraries/LibGUI/Widget.h +++ b/Userland/Libraries/LibGUI/Widget.h @@ -71,6 +71,15 @@ enum class AllowCallback { Yes }; +template +ALWAYS_INLINE ErrorOr initialize(T& object) +{ + if constexpr (requires { { object.initialize() } -> SameAs>; }) + return object.initialize(); + else + return {}; +} + class Widget : public GUI::Object { C_OBJECT(Widget) public: