From 5b03a0867ffd044c965d9914655546cb7fd3d15b Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Fri, 1 Jan 2021 00:46:51 -0700 Subject: [PATCH] LibCore: Add typed find_child and find_descendant helpers to Object These look a lot like the parallel functionality in GUI::Widget :). These use dynamic_cast now, to make use of that RTTI we just added. --- Libraries/LibCore/Object.h | 45 ++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/Libraries/LibCore/Object.h b/Libraries/LibCore/Object.h index de1a5f77de..eaaded970a 100644 --- a/Libraries/LibCore/Object.h +++ b/Libraries/LibCore/Object.h @@ -91,7 +91,13 @@ public: } template - void for_each_child_of_type(Callback callback); + void for_each_child_of_type(Callback callback) requires IsBaseOf::value; + + template + T* find_child_of_type_named(const String&) requires IsBaseOf::value; + + template + T* find_descendant_of_type_named(const String&) requires IsBaseOf::value; bool is_ancestor_of(const Object&) const; @@ -181,15 +187,46 @@ struct Formatter : Formatter { namespace Core { template -inline void Object::for_each_child_of_type(Callback callback) +inline void Object::for_each_child_of_type(Callback callback) requires IsBaseOf::value { for_each_child([&](auto& child) { - if (is(child)) - return callback(downcast(child)); + if (auto* child_as_t = dynamic_cast(&child); child_as_t) + return callback(*child_as_t); return IterationDecision::Continue; }); } +template +T* Object::find_child_of_type_named(const String& name) requires IsBaseOf::value +{ + T* found_child = nullptr; + for_each_child_of_type([&](auto& child) { + if (child.name() == name) { + found_child = &child; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + + return found_child; +} + +template +T* Object::find_descendant_of_type_named(const String& name) requires IsBaseOf::value +{ + auto* this_as_t = dynamic_cast(this); + if (this_as_t && this->name() == name) + return this_as_t; + T* found_child = nullptr; + for_each_child([&](auto& child) { + found_child = child.template find_descendant_of_type_named(name); + if (found_child) + return IterationDecision::Break; + return IterationDecision::Continue; + }); + return found_child; +} + const LogStream& operator<<(const LogStream&, const Object&); #define REGISTER_INT_PROPERTY(property_name, getter, setter) \