LibCore+LibGUI: Switch to using AK::is and AK::downcast

This commit is contained in:
Andreas Kling 2020-07-26 17:16:35 +02:00
parent 71556e39a4
commit e0b8b4ac67
14 changed files with 341 additions and 98 deletions

View file

@ -42,7 +42,7 @@ void InspectorWidget::set_inspected_node(Web::Node* node)
{
m_document->set_inspected_node(node);
if (node && node->is_element()) {
auto& element = Web::to<Web::Element>(*node);
auto& element = downcast<Web::Element>(*node);
if (element.resolved_style()) {
m_style_table_view->set_model(Web::StylePropertiesModel::create(*element.resolved_style()));
m_computed_style_table_view->set_model(Web::StylePropertiesModel::create(*element.computed_style()));

View file

@ -55,8 +55,6 @@ private:
RefPtr<Editor> m_editor;
};
template<>
inline bool Core::is<EditorWrapper>(const Core::Object& object)
{
return !strcmp(object.class_name(), "EditorWrapper");
}
AK_BEGIN_TYPE_TRAITS(EditorWrapper)
static bool is_type(const Core::Object& object) { return !strcmp(object.class_name(), "EditorWrapper"); }
AK_END_TYPE_TRAITS()

View file

@ -31,6 +31,7 @@
#include <AK/Noncopyable.h>
#include <AK/NonnullRefPtrVector.h>
#include <AK/String.h>
#include <AK/TypeCasts.h>
#include <AK/Weakable.h>
#include <LibCore/Forward.h>
@ -147,8 +148,8 @@ protected:
// NOTE: You may get child events for children that are not yet fully constructed!
virtual void child_event(ChildEvent&);
virtual void did_begin_inspection() {}
virtual void did_end_inspection() {}
virtual void did_begin_inspection() { }
virtual void did_end_inspection() { }
private:
Object* m_parent { nullptr };
@ -159,29 +160,15 @@ private:
NonnullRefPtrVector<Object> m_children;
};
template<typename T>
inline bool is(const Object&) { return false; }
template<typename T>
inline T& to(Object& object)
{
ASSERT(is<typename RemoveConst<T>::Type>(object));
return static_cast<T&>(object);
}
template<typename T>
inline const T& to(const Object& object)
{
ASSERT(is<typename RemoveConst<T>::Type>(object));
return static_cast<const T&>(object);
}
namespace Core {
template<typename T, typename Callback>
inline void Object::for_each_child_of_type(Callback callback)
{
for_each_child([&](auto& child) {
if (is<T>(child))
return callback(to<T>(child));
return callback(downcast<T>(child));
return IterationDecision::Continue;
});
}

View file

@ -91,10 +91,6 @@ private:
}
template<>
inline bool Core::is<GUI::AbstractButton>(const Core::Object& object)
{
if (!is<GUI::Widget>(object))
return false;
return to<GUI::Widget>(object).is_abstract_button();
}
AK_BEGIN_TYPE_TRAITS(GUI::AbstractButton)
static bool is_type(const Core::Object& object) { return is<GUI::Widget>(object) && downcast<GUI::Widget>(object).is_abstract_button(); }
AK_END_TYPE_TRAITS()

View file

@ -152,9 +152,9 @@ Action::Action(const StringView& text, const Shortcut& shortcut, RefPtr<Gfx::Bit
, m_shortcut(shortcut)
, m_checkable(checkable)
{
if (parent && Core::is<Widget>(*parent)) {
if (parent && is<Widget>(*parent)) {
m_scope = ShortcutScope::WidgetLocal;
} else if (parent && Core::is<Window>(*parent)) {
} else if (parent && is<Window>(*parent)) {
m_scope = ShortcutScope::WindowLocal;
} else {
m_scope = ShortcutScope::ApplicationGlobal;

View file

@ -42,23 +42,23 @@
namespace GUI {
namespace CommonActions {
NonnullRefPtr<Action> make_open_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_save_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_undo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_redo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_cut_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_copy_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_paste_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_delete_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_front_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_fullscreen_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_quit_action(Function<void(Action&)>);
NonnullRefPtr<Action> make_go_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_forward_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_home_action(Function<void(Action&)> callback, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_reload_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_select_all_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_open_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_save_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_undo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_redo_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_cut_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_copy_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_paste_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_delete_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_front_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_move_to_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_fullscreen_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_quit_action(Function<void(Action&)>);
NonnullRefPtr<Action> make_go_back_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_forward_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_go_home_action(Function<void(Action&)> callback, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_reload_action(Function<void(Action&)>, Core::Object* parent = nullptr);
NonnullRefPtr<Action> make_select_all_action(Function<void(Action&)>, Core::Object* parent = nullptr);
};
class Action final : public Core::Object {
@ -168,8 +168,6 @@ private:
}
template<>
inline bool Core::is<GUI::Action>(const Core::Object& object)
{
return object.is_action();
}
AK_BEGIN_TYPE_TRAITS(GUI::Action)
static bool is_type(const Core::Object& object) { return object.is_action(); }
AK_END_TYPE_TRAITS()

View file

@ -74,7 +74,7 @@ void RadioButton::for_each_in_group(Callback callback)
if (!parent())
return;
parent()->for_each_child_of_type<RadioButton>([&](auto& child) {
return callback(static_cast<RadioButton&>(child));
return callback(downcast<RadioButton>(child));
});
}

View file

@ -55,10 +55,6 @@ private:
}
template<>
inline bool Core::is<GUI::RadioButton>(const Core::Object& object)
{
if (!is<GUI::Widget>(object))
return false;
return to<GUI::Widget>(object).is_radio_button();
}
AK_BEGIN_TYPE_TRAITS(GUI::RadioButton)
static bool is_type(const Core::Object& object) { return is<GUI::Widget>(object) && downcast<GUI::Widget>(object).is_radio_button(); }
AK_END_TYPE_TRAITS()

View file

@ -63,9 +63,9 @@ void StackWidget::resize_event(ResizeEvent& event)
void StackWidget::child_event(Core::ChildEvent& event)
{
if (!event.child() || !Core::is<Widget>(*event.child()))
if (!event.child() || !is<Widget>(*event.child()))
return Widget::child_event(event);
auto& child = Core::to<Widget>(*event.child());
auto& child = downcast<Widget>(*event.child());
if (event.type() == Event::ChildAdded) {
if (!m_active_widget)
set_active_widget(&child);

View file

@ -102,9 +102,9 @@ Gfx::IntRect TabWidget::child_rect_for_size(const Gfx::IntSize& size) const
void TabWidget::child_event(Core::ChildEvent& event)
{
if (!event.child() || !Core::is<Widget>(*event.child()))
if (!event.child() || !is<Widget>(*event.child()))
return Widget::child_event(event);
auto& child = Core::to<Widget>(*event.child());
auto& child = downcast<Widget>(*event.child());
if (event.type() == Event::ChildAdded) {
if (!m_active_widget)
set_active_widget(&child);

View file

@ -109,24 +109,24 @@ Widget::~Widget()
void Widget::child_event(Core::ChildEvent& event)
{
if (event.type() == Event::ChildAdded) {
if (event.child() && Core::is<Widget>(*event.child()) && layout()) {
if (event.child() && is<Widget>(*event.child()) && layout()) {
if (event.insertion_before_child() && event.insertion_before_child()->is_widget())
layout()->insert_widget_before(Core::to<Widget>(*event.child()), Core::to<Widget>(*event.insertion_before_child()));
layout()->insert_widget_before(downcast<Widget>(*event.child()), downcast<Widget>(*event.insertion_before_child()));
else
layout()->add_widget(Core::to<Widget>(*event.child()));
layout()->add_widget(downcast<Widget>(*event.child()));
}
if (window() && event.child() && Core::is<Widget>(*event.child()))
window()->did_add_widget({}, Core::to<Widget>(*event.child()));
if (window() && event.child() && is<Widget>(*event.child()))
window()->did_add_widget({}, downcast<Widget>(*event.child()));
}
if (event.type() == Event::ChildRemoved) {
if (layout()) {
if (event.child() && Core::is<Widget>(*event.child()))
layout()->remove_widget(Core::to<Widget>(*event.child()));
if (event.child() && is<Widget>(*event.child()))
layout()->remove_widget(downcast<Widget>(*event.child()));
else
invalidate_layout();
}
if (window() && event.child() && Core::is<Widget>(*event.child()))
window()->did_remove_widget({}, Core::to<Widget>(*event.child()));
if (window() && event.child() && is<Widget>(*event.child()))
window()->did_remove_widget({}, downcast<Widget>(*event.child()));
update();
}
return Core::Object::child_event(event);
@ -470,9 +470,9 @@ Gfx::IntRect Widget::screen_relative_rect() const
Widget* Widget::child_at(const Gfx::IntPoint& point) const
{
for (int i = children().size() - 1; i >= 0; --i) {
if (!Core::is<Widget>(children()[i]))
if (!is<Widget>(children()[i]))
continue;
auto& child = Core::to<Widget>(children()[i]);
auto& child = downcast<Widget>(children()[i]);
if (!child.is_visible())
continue;
if (child.content_rect().contains(point))

View file

@ -40,12 +40,6 @@
extern WidgetClassRegistration registration_##class_name; \
WidgetClassRegistration registration_##class_name(#class_name, []() { return class_name::construct(); });
template<>
inline bool Core::is<GUI::Widget>(const Core::Object& object)
{
return object.is_widget();
}
namespace GUI {
enum class SizePolicy {
@ -249,8 +243,8 @@ public:
void for_each_child_widget(Callback callback)
{
for_each_child([&](auto& child) {
if (Core::is<Widget>(child))
return callback(Core::to<Widget>(child));
if (is<Widget>(child))
return callback(downcast<Widget>(child));
return IterationDecision::Continue;
});
}
@ -278,9 +272,9 @@ public:
protected:
Widget();
virtual void custom_layout() {}
virtual void did_change_font() {}
virtual void did_layout() {}
virtual void custom_layout() { }
virtual void did_change_font() { }
virtual void did_layout() { }
virtual void paint_event(PaintEvent&);
virtual void resize_event(ResizeEvent&);
virtual void show_event(ShowEvent&);
@ -347,14 +341,18 @@ private:
inline Widget* Widget::parent_widget()
{
if (parent() && Core::is<Widget>(*parent()))
return &Core::to<Widget>(*parent());
if (parent() && is<Widget>(*parent()))
return &downcast<Widget>(*parent());
return nullptr;
}
inline const Widget* Widget::parent_widget() const
{
if (parent() && Core::is<Widget>(*parent()))
return &Core::to<const Widget>(*parent());
if (parent() && is<Widget>(*parent()))
return &downcast<const Widget>(*parent());
return nullptr;
}
}
AK_BEGIN_TYPE_TRAITS(GUI::Widget)
static bool is_type(const Core::Object& object) { return object.is_widget(); }
AK_END_TYPE_TRAITS()

View file

@ -266,8 +266,6 @@ private:
}
template<>
inline bool Core::is<GUI::Window>(const Core::Object& object)
{
return object.is_window();
}
AK_BEGIN_TYPE_TRAITS(GUI::Window)
static bool is_type(const Core::Object& object) { return object.is_window(); }
AK_END_TYPE_TRAITS()

View file

@ -0,0 +1,272 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <AK/Function.h>
#include <AK/String.h>
#include <AK/WeakPtr.h>
#include <LibCore/Object.h>
#include <LibGUI/Forward.h>
#include <LibGUI/WindowType.h>
#include <LibGfx/Color.h>
#include <LibGfx/Forward.h>
#include <LibGfx/Rect.h>
namespace GUI {
enum class StandardCursor {
None = 0,
Arrow,
IBeam,
ResizeHorizontal,
ResizeVertical,
ResizeDiagonalTLBR,
ResizeDiagonalBLTR,
ResizeColumn,
ResizeRow,
Hand,
Help,
Drag,
Move,
Wait,
};
class Window : public Core::Object {
C_OBJECT(Window)
public:
virtual ~Window() override;
static Window* from_window_id(int);
bool is_modal() const { return m_modal; }
void set_modal(bool);
bool is_fullscreen() const { return m_fullscreen; }
void set_fullscreen(bool);
bool is_maximized() const;
bool is_frameless() const { return m_frameless; }
void set_frameless(bool frameless) { m_frameless = frameless; }
bool is_resizable() const { return m_resizable; }
void set_resizable(bool resizable) { m_resizable = resizable; }
bool is_minimizable() const { return m_minimizable; }
void set_minimizable(bool minimizable) { m_minimizable = minimizable; }
void set_double_buffering_enabled(bool);
void set_has_alpha_channel(bool);
void set_opacity(float);
void set_window_type(WindowType);
int window_id() const { return m_window_id; }
String title() const;
void set_title(const StringView&);
Color background_color() const { return m_background_color; }
void set_background_color(Color color) { m_background_color = color; }
enum class CloseRequestDecision {
StayOpen,
Close,
};
Function<CloseRequestDecision()> on_close_request;
Function<void(bool is_active_input)> on_active_input_change;
Function<void(const bool is_active)> on_activity_change;
int x() const { return rect().x(); }
int y() const { return rect().y(); }
int width() const { return rect().width(); }
int height() const { return rect().height(); }
Gfx::IntRect rect() const;
Gfx::IntSize size() const { return rect().size(); }
void set_rect(const Gfx::IntRect&);
void set_rect(int x, int y, int width, int height) { set_rect({ x, y, width, height }); }
Gfx::IntPoint position() const { return rect().location(); }
void move_to(int x, int y) { move_to({ x, y }); }
void move_to(const Gfx::IntPoint& point) { set_rect({ point, size() }); }
void resize(int width, int height) { resize({ width, height }); }
void resize(const Gfx::IntSize& size) { set_rect({ position(), size }); }
virtual void event(Core::Event&) override;
bool is_visible() const;
bool is_active() const { return m_is_active; }
bool is_active_input() const { return m_is_active_input; }
bool is_accessory() const { return m_accessory; }
void set_accessory(bool accessory) { m_accessory = accessory; }
void show();
void hide();
virtual void close();
void move_to_front();
void start_wm_resize();
Widget* main_widget() { return m_main_widget; }
const Widget* main_widget() const { return m_main_widget; }
void set_main_widget(Widget*);
template<class T, class... Args>
inline T& set_main_widget(Args&&... args)
{
auto widget = T::construct(forward<Args>(args)...);
set_main_widget(widget.ptr());
return *widget;
}
Widget* focused_widget() { return m_focused_widget; }
const Widget* focused_widget() const { return m_focused_widget; }
void set_focused_widget(Widget*);
void update();
void update(const Gfx::IntRect&);
void set_global_cursor_tracking_widget(Widget*);
Widget* global_cursor_tracking_widget() { return m_global_cursor_tracking_widget.ptr(); }
const Widget* global_cursor_tracking_widget() const { return m_global_cursor_tracking_widget.ptr(); }
void set_automatic_cursor_tracking_widget(Widget*);
Widget* automatic_cursor_tracking_widget() { return m_automatic_cursor_tracking_widget.ptr(); }
const Widget* automatic_cursor_tracking_widget() const { return m_automatic_cursor_tracking_widget.ptr(); }
Widget* hovered_widget() { return m_hovered_widget.ptr(); }
const Widget* hovered_widget() const { return m_hovered_widget.ptr(); }
void set_hovered_widget(Widget*);
Gfx::Bitmap* front_bitmap() { return m_front_bitmap.ptr(); }
Gfx::Bitmap* back_bitmap() { return m_back_bitmap.ptr(); }
Gfx::IntSize size_increment() const { return m_size_increment; }
void set_size_increment(const Gfx::IntSize&);
Gfx::IntSize base_size() const { return m_base_size; }
void set_base_size(const Gfx::IntSize&);
void set_override_cursor(StandardCursor);
void set_override_cursor(const Gfx::Bitmap&);
void set_icon(const Gfx::Bitmap*);
void apply_icon();
const Gfx::Bitmap* icon() const { return m_icon.ptr(); }
Vector<Widget*> focusable_widgets() const;
virtual void save_to(AK::JsonObject&) override;
void schedule_relayout();
static void for_each_window(Badge<WindowServerConnection>, Function<void(Window&)>);
static void update_all_windows(Badge<WindowServerConnection>);
void notify_state_changed(Badge<WindowServerConnection>, bool minimized, bool occluded);
virtual bool is_visible_for_timer_purposes() const override { return m_visible_for_timer_purposes; }
Action* action_for_key_event(const KeyEvent&);
void did_add_widget(Badge<Widget>, Widget&);
void did_remove_widget(Badge<Widget>, Widget&);
Window* find_parent_window();
void set_progress(int);
protected:
Window(Core::Object* parent = nullptr);
virtual void wm_event(WMEvent&);
private:
virtual bool is_window() const override final { return true; }
void handle_drop_event(DropEvent&);
void handle_mouse_event(MouseEvent&);
void handle_multi_paint_event(MultiPaintEvent&);
void handle_key_event(KeyEvent&);
void handle_resize_event(ResizeEvent&);
void handle_input_entered_or_left_event(Core::Event&);
void handle_became_active_or_inactive_event(Core::Event&);
void handle_close_request();
void handle_theme_change_event(ThemeChangeEvent&);
void handle_drag_move_event(DragEvent&);
void handle_left_event();
void server_did_destroy();
RefPtr<Gfx::Bitmap> create_backing_bitmap(const Gfx::IntSize&);
RefPtr<Gfx::Bitmap> create_shared_bitmap(Gfx::BitmapFormat, const Gfx::IntSize&);
void set_current_backing_bitmap(Gfx::Bitmap&, bool flush_immediately = false);
void flip(const Vector<Gfx::IntRect, 32>& dirty_rects);
void force_update();
RefPtr<Gfx::Bitmap> m_front_bitmap;
RefPtr<Gfx::Bitmap> m_back_bitmap;
RefPtr<Gfx::Bitmap> m_icon;
RefPtr<Gfx::Bitmap> m_custom_cursor;
int m_window_id { 0 };
float m_opacity_when_windowless { 1.0f };
RefPtr<Widget> m_main_widget;
WeakPtr<Widget> m_focused_widget;
WeakPtr<Widget> m_global_cursor_tracking_widget;
WeakPtr<Widget> m_automatic_cursor_tracking_widget;
WeakPtr<Widget> m_hovered_widget;
Gfx::IntRect m_rect_when_windowless;
String m_title_when_windowless;
Vector<Gfx::IntRect, 32> m_pending_paint_event_rects;
Gfx::IntSize m_size_increment;
Gfx::IntSize m_base_size;
Color m_background_color { Color::WarmGray };
WindowType m_window_type { WindowType::Normal };
StandardCursor m_override_cursor { StandardCursor::None };
bool m_is_active { false };
bool m_is_active_input { false };
bool m_has_alpha_channel { false };
bool m_double_buffering_enabled { true };
bool m_modal { false };
bool m_resizable { true };
bool m_minimizable { true };
bool m_fullscreen { false };
bool m_frameless { false };
bool m_layout_pending { false };
bool m_visible_for_timer_purposes { true };
bool m_visible { false };
bool m_accessory { false };
};
}
template<>
inline bool Core::is<GUI::Window>(const Core::Object& object)
{
return object.is_window();
}