diff --git a/LibCore/CObject.h b/LibCore/CObject.h index 4f1281181289c3..92fe544edd906f 100644 --- a/LibCore/CObject.h +++ b/LibCore/CObject.h @@ -58,3 +58,20 @@ class CObject : public Weakable { bool m_widget { false }; Vector m_children; }; + +template inline bool is(const CObject&) { return false; } +template<> inline bool is(const CObject&) { return true; } + +template +inline T& to(CObject& object) +{ + ASSERT(is(object)); + return static_cast(object); +} + +template +inline const T& to(const CObject& object) +{ + ASSERT(is(object)); + return static_cast(object); +} diff --git a/LibGUI/GStackWidget.cpp b/LibGUI/GStackWidget.cpp index 4b7e2a2ec6a0ec..312938d66db43d 100644 --- a/LibGUI/GStackWidget.cpp +++ b/LibGUI/GStackWidget.cpp @@ -33,9 +33,9 @@ void GStackWidget::resize_event(GResizeEvent& event) void GStackWidget::child_event(CChildEvent& event) { - if (!event.child() || !event.child()->is_widget()) + if (!event.child() || !is(*event.child())) return GWidget::child_event(event); - auto& child = static_cast(*event.child()); + auto& child = to(*event.child()); if (event.type() == GEvent::ChildAdded) { if (!m_active_widget) set_active_widget(&child); @@ -44,12 +44,10 @@ void GStackWidget::child_event(CChildEvent& event) } else if (event.type() == GEvent::ChildRemoved) { if (m_active_widget == &child) { GWidget* new_active_widget = nullptr; - for (auto* new_child : children()) { - if (new_child->is_widget()) { - new_active_widget = static_cast(new_child); - break; - } - } + for_each_child_widget([&] (auto& new_child) { + new_active_widget = &new_child; + return IterationDecision::Abort; + }); set_active_widget(new_active_widget); } } diff --git a/LibGUI/GTabWidget.cpp b/LibGUI/GTabWidget.cpp index 62d6cd58e009b2..4aa94e4a6e2ff3 100644 --- a/LibGUI/GTabWidget.cpp +++ b/LibGUI/GTabWidget.cpp @@ -50,9 +50,9 @@ Rect GTabWidget::child_rect_for_size(const Size& size) const void GTabWidget::child_event(CChildEvent& event) { - if (!event.child() || !event.child()->is_widget()) + if (!event.child() || !is(*event.child())) return GWidget::child_event(event); - auto& child = static_cast(*event.child()); + auto& child = to(*event.child()); if (event.type() == GEvent::ChildAdded) { if (!m_active_widget) set_active_widget(&child); diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index 68cb7c29e7672f..8724ec2a08d0dc 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -26,13 +26,13 @@ GWidget::~GWidget() void GWidget::child_event(CChildEvent& event) { if (event.type() == GEvent::ChildAdded) { - if (event.child() && event.child()->is_widget() && layout()) - layout()->add_widget(static_cast(*event.child())); + if (event.child() && is(*event.child()) && layout()) + layout()->add_widget(to(*event.child())); } if (event.type() == GEvent::ChildRemoved) { if (layout()) { - if (event.child() && event.child()->is_widget()) - layout()->remove_widget(static_cast(*event.child())); + if (event.child() && is(*event.child())) + layout()->remove_widget(to(*event.child())); else invalidate_layout(); } @@ -321,9 +321,9 @@ Rect GWidget::screen_relative_rect() const GWidget* GWidget::child_at(const Point& point) const { for (int i = children().size() - 1; i >= 0; --i) { - if (!children()[i]->is_widget()) + if (!is(*children()[i])) continue; - auto& child = *(GWidget*)children()[i]; + auto& child = to(*children()[i]); if (!child.is_visible()) continue; if (child.relative_rect().contains(point)) diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h index 4b42245e96f4f8..6416145672a271 100644 --- a/LibGUI/GWidget.h +++ b/LibGUI/GWidget.h @@ -141,18 +141,8 @@ class GWidget : public CObject { void set_window(GWindow*); - GWidget* parent_widget() - { - if (parent() && parent()->is_widget()) - return static_cast(parent()); - return nullptr; - } - const GWidget* parent_widget() const - { - if (parent() && parent()->is_widget()) - return static_cast(parent()); - return nullptr; - } + GWidget* parent_widget(); + const GWidget* parent_widget() const; void set_fill_with_background_color(bool b) { m_fill_with_background_color = b; } bool fill_with_background_color() const { return m_fill_with_background_color; } @@ -189,8 +179,8 @@ class GWidget : public CObject { void for_each_child_widget(Callback callback) { for_each_child([&] (auto& child) { - if (child.is_widget()) - return callback(static_cast(child)); + if (is(child)) + return callback(to(child)); return IterationDecision::Continue; }); } @@ -233,3 +223,21 @@ class GWidget : public CObject { HashMap m_local_shortcut_actions; }; + +template<> inline bool is(const CObject& object) +{ + return object.is_widget(); +} + +inline GWidget* GWidget::parent_widget() +{ + if (parent() && is(*parent())) + return &to(*parent()); + return nullptr; +} +inline const GWidget* GWidget::parent_widget() const +{ + if (parent() && is(*parent())) + return &to(*parent()); + return nullptr; +}