summaryrefslogtreecommitdiff
path: root/Libraries/LibCore
diff options
context:
space:
mode:
authorAndrew Kaster <andrewdkaster@gmail.com>2021-01-01 00:46:51 -0700
committerAndreas Kling <kling@serenityos.org>2021-01-01 14:45:09 +0100
commit5b03a0867ffd044c965d9914655546cb7fd3d15b (patch)
treeb3beb394763bcc3a32f87fdd7d4de0f53784e0fc /Libraries/LibCore
parent350d4d3543a0acca95877c7cec72c1eaca34513f (diff)
downloadserenity-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.h45
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&);