mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 12:23:15 +00:00
GMLCompiler+LibGUI: Add support for object properties and undo hack
Previously the GML compiler did not support object properties such as `content_widget: @GUI::Widget{}` for GUI::ScrollableContainerWidget; this commit adds support for such properties by simply calling `set_<key>(<TProperty>&)` on the object. This commit also removes the previous hack where ScrollableContainerWidget was special-cased to have its singular child used as the content widget; the only GML file using this behaviour was also changed to be in line with 'proper' GML as handled by the GML Playground.
This commit is contained in:
parent
5c17b61378
commit
f3a4118aee
|
@ -313,6 +313,29 @@ static ErrorOr<void> generate_loader_for_object(GUI::GML::Object const& gml_obje
|
||||||
}));
|
}));
|
||||||
generator.appendln("");
|
generator.appendln("");
|
||||||
|
|
||||||
|
// Object properties
|
||||||
|
size_t current_object_property_index = 0;
|
||||||
|
auto next_object_property_name = [&]() {
|
||||||
|
return String::formatted("{}_property_{}", object_name, current_object_property_index++);
|
||||||
|
};
|
||||||
|
TRY(gml_object.try_for_each_object_property([&](StringView key, NonnullRefPtr<GUI::GML::Object> value) -> ErrorOr<void> {
|
||||||
|
if (key == "layout"sv)
|
||||||
|
return {}; // Layout is handled separately.
|
||||||
|
|
||||||
|
auto property_generator = generator.fork();
|
||||||
|
auto property_variable_name = TRY(next_object_property_name());
|
||||||
|
property_generator.set("property_variable_name", property_variable_name.bytes_as_string_view());
|
||||||
|
property_generator.set("property_class_name", value->name());
|
||||||
|
property_generator.set("key", key);
|
||||||
|
TRY(append(property_generator, "RefPtr<::@property_class_name@> @property_variable_name@;"));
|
||||||
|
TRY(generate_loader_for_object(*value, property_generator.fork(), property_variable_name, indentation + 1, UseObjectConstructor::Yes));
|
||||||
|
|
||||||
|
// Set the property on the object.
|
||||||
|
TRY(append(property_generator, "@object_name@->set_@key@(*@property_variable_name@);"));
|
||||||
|
property_generator.appendln("");
|
||||||
|
return {};
|
||||||
|
}));
|
||||||
|
|
||||||
// Layout
|
// Layout
|
||||||
if (gml_object.layout_object() != nullptr) {
|
if (gml_object.layout_object() != nullptr) {
|
||||||
TRY(append(generator, "RefPtr<GUI::Layout> layout;"));
|
TRY(append(generator, "RefPtr<GUI::Layout> layout;"));
|
||||||
|
@ -340,10 +363,9 @@ static ErrorOr<void> generate_loader_for_object(GUI::GML::Object const& gml_obje
|
||||||
TRY(append(child_generator, "RefPtr<::@child_class_name@> @child_variable_name@;"));
|
TRY(append(child_generator, "RefPtr<::@child_class_name@> @child_variable_name@;"));
|
||||||
TRY(generate_loader_for_object(child, child_generator.fork(), child_variable_name, indentation + 1, UseObjectConstructor::Yes));
|
TRY(generate_loader_for_object(child, child_generator.fork(), child_variable_name, indentation + 1, UseObjectConstructor::Yes));
|
||||||
|
|
||||||
// Handle the current two special cases of child adding.
|
// Handle the current special case of child adding.
|
||||||
if (gml_object.name() == "GUI::ScrollableContainerWidget"sv)
|
// FIXME: This should be using the proper API for handling object properties.
|
||||||
TRY(append(child_generator, "static_ptr_cast<GUI::ScrollableContainerWidget>(@object_name@)->set_widget(@child_variable_name@);"));
|
if (gml_object.name() == "GUI::TabWidget"sv)
|
||||||
else if (gml_object.name() == "GUI::TabWidget"sv)
|
|
||||||
TRY(append(child_generator, "static_ptr_cast<GUI::TabWidget>(@object_name@)->add_widget(*@child_variable_name@);"));
|
TRY(append(child_generator, "static_ptr_cast<GUI::TabWidget>(@object_name@)->add_widget(*@child_variable_name@);"));
|
||||||
else
|
else
|
||||||
TRY(append(child_generator, "TRY(@object_name@->try_add_child(*@child_variable_name@));"));
|
TRY(append(child_generator, "TRY(@object_name@->try_add_child(*@child_variable_name@));"));
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
@GUI::ScrollableContainerWidget {
|
@GUI::ScrollableContainerWidget {
|
||||||
name: "scrollable_container"
|
name: "scrollable_container"
|
||||||
|
|
||||||
@GUI::Widget {
|
content_widget: @GUI::Widget {
|
||||||
name: "emojis"
|
name: "emojis"
|
||||||
layout: @GUI::VerticalBoxLayout {}
|
layout: @GUI::VerticalBoxLayout {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -188,6 +188,18 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Callback>
|
||||||
|
void for_each_object_property(Callback callback) const
|
||||||
|
{
|
||||||
|
for (auto const& child : m_properties) {
|
||||||
|
if (is<KeyValuePair>(child)) {
|
||||||
|
auto const& property = static_cast<KeyValuePair const&>(*child);
|
||||||
|
if (is<Object>(property.value().ptr()))
|
||||||
|
callback(property.key(), static_ptr_cast<Object>(property.value()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<FallibleFunction<StringView, NonnullRefPtr<JsonValueNode>> Callback>
|
template<FallibleFunction<StringView, NonnullRefPtr<JsonValueNode>> Callback>
|
||||||
ErrorOr<void> try_for_each_property(Callback callback) const
|
ErrorOr<void> try_for_each_property(Callback callback) const
|
||||||
{
|
{
|
||||||
|
@ -201,6 +213,19 @@ public:
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<FallibleFunction<StringView, NonnullRefPtr<Object>> Callback>
|
||||||
|
ErrorOr<void> try_for_each_object_property(Callback callback) const
|
||||||
|
{
|
||||||
|
for (auto const& child : m_properties) {
|
||||||
|
if (is<KeyValuePair>(child)) {
|
||||||
|
auto const& property = static_cast<KeyValuePair const&>(*child);
|
||||||
|
if (is<Object>(property.value().ptr()))
|
||||||
|
TRY(callback(property.key(), static_ptr_cast<Object>(property.value())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void for_each_child_object(Callback callback) const
|
void for_each_child_object(Callback callback) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,9 @@ public:
|
||||||
GUI::Widget* widget() { return m_widget; }
|
GUI::Widget* widget() { return m_widget; }
|
||||||
GUI::Widget const* widget() const { return m_widget; }
|
GUI::Widget const* widget() const { return m_widget; }
|
||||||
|
|
||||||
|
// GMLCompiler support for the `content_widget` object property.
|
||||||
|
void set_content_widget(GUI::Widget& widget) { set_widget(&widget); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void did_scroll() override;
|
virtual void did_scroll() override;
|
||||||
virtual void resize_event(GUI::ResizeEvent&) override;
|
virtual void resize_event(GUI::ResizeEvent&) override;
|
||||||
|
|
Loading…
Reference in a new issue