diff options
author | Andrew Kaster <andrewdkaster@gmail.com> | 2021-01-01 00:46:51 -0700 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-01-01 14:45:09 +0100 |
commit | 5b03a0867ffd044c965d9914655546cb7fd3d15b (patch) | |
tree | b3beb394763bcc3a32f87fdd7d4de0f53784e0fc /Libraries/LibCore | |
parent | 350d4d3543a0acca95877c7cec72c1eaca34513f (diff) | |
download | serenity-5b03a0867ffd044c965d9914655546cb7fd3d15b.zip |
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.
Diffstat (limited to 'Libraries/LibCore')
-rw-r--r-- | Libraries/LibCore/Object.h | 45 |
1 files 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<typename T, typename Callback> - void for_each_child_of_type(Callback callback); + void for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>::value; + + template<typename T> + T* find_child_of_type_named(const String&) requires IsBaseOf<Object, T>::value; + + template<typename T> + T* find_descendant_of_type_named(const String&) requires IsBaseOf<Object, T>::value; bool is_ancestor_of(const Object&) const; @@ -181,13 +187,44 @@ struct Formatter<Core::Object> : Formatter<StringView> { namespace Core { template<typename T, typename Callback> -inline void Object::for_each_child_of_type(Callback callback) +inline void Object::for_each_child_of_type(Callback callback) requires IsBaseOf<Object, T>::value +{ + for_each_child([&](auto& child) { + if (auto* child_as_t = dynamic_cast<T*>(&child); child_as_t) + return callback(*child_as_t); + return IterationDecision::Continue; + }); +} + +template<typename T> +T* Object::find_child_of_type_named(const String& name) requires IsBaseOf<Object, T>::value +{ + T* found_child = nullptr; + for_each_child_of_type<T>([&](auto& child) { + if (child.name() == name) { + found_child = &child; + return IterationDecision::Break; + } + return IterationDecision::Continue; + }); + + return found_child; +} + +template<typename T> +T* Object::find_descendant_of_type_named(const String& name) requires IsBaseOf<Object, T>::value { + auto* this_as_t = dynamic_cast<T*>(this); + if (this_as_t && this->name() == name) + return this_as_t; + T* found_child = nullptr; for_each_child([&](auto& child) { - if (is<T>(child)) - return callback(downcast<T>(child)); + found_child = child.template find_descendant_of_type_named<T>(name); + if (found_child) + return IterationDecision::Break; return IterationDecision::Continue; }); + return found_child; } const LogStream& operator<<(const LogStream&, const Object&); |