From 9acdf9bb0a75b3ecba1cdadd784df09f40276c07 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 17 Sep 2019 21:00:11 +0200 Subject: [PATCH] VisualBuilder: Support nested widgets This patch makes it possible to put widgets inside one another. The way you do this right now is by having a (single) widget selected when you insert a new widget. The new widget then becomes a child of the selected widget. (In the future we'll make it possible to drag widgets into each other, and things like that.) I've also changed the grabber coordinates to be window-relative instead of parent-relative in order to simplify things for myself. Maybe that's not the ideal design and we can revisit that. --- DevTools/VisualBuilder/VBForm.cpp | 18 ++++++++++++------ DevTools/VisualBuilder/VBWidget.cpp | 14 +++++++++----- DevTools/VisualBuilder/VBWidget.h | 4 ++-- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/DevTools/VisualBuilder/VBForm.cpp b/DevTools/VisualBuilder/VBForm.cpp index cb7f140b71..94cd141856 100644 --- a/DevTools/VisualBuilder/VBForm.cpp +++ b/DevTools/VisualBuilder/VBForm.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -47,8 +48,12 @@ void VBForm::context_menu_event(GContextMenuEvent& event) void VBForm::insert_widget(VBWidgetType type) { - auto widget = VBWidget::create(type, *this); - widget->set_rect({ m_next_insertion_position, { m_grid_size * 10 + 1, m_grid_size * 5 + 1 } }); + auto* insertion_parent = single_selected_widget(); + auto widget = VBWidget::create(type, *this, insertion_parent); + Point insertion_position = m_next_insertion_position; + if (insertion_parent) + insertion_position.move_by(insertion_parent->gwidget()->window_relative_rect().location()); + widget->set_rect({ insertion_position, { m_grid_size * 10 + 1, m_grid_size * 5 + 1 } }); m_next_insertion_position.move_by(m_grid_size, m_grid_size); m_widgets.append(move(widget)); } @@ -91,10 +96,10 @@ bool VBForm::is_selected(const VBWidget& widget) const VBWidget* VBForm::widget_at(const Point& position) { - auto* gwidget = child_at(position); - if (!gwidget) + auto result = hit_test(position, GWidget::ShouldRespectGreediness::No); + if (!result.widget) return nullptr; - return m_gwidget_map.get(gwidget).value_or(nullptr); + return m_gwidget_map.get(result.widget).value_or(nullptr); } void VBForm::grabber_mousedown_event(GMouseEvent& event, Direction grabber) @@ -323,7 +328,8 @@ void VBForm::load_from_file(const String& path) auto& widget_object = widget_value.as_object(); auto widget_class = widget_object.get("class").as_string(); auto widget_type = widget_type_from_class_name(widget_class); - auto vbwidget = VBWidget::create(widget_type, *this); + // FIXME: Construct VBWidget within the right parent.. + auto vbwidget = VBWidget::create(widget_type, *this, nullptr); widget_object.for_each_member([&](auto& property_name, const JsonValue& property_value) { (void)property_name; (void)property_value; diff --git a/DevTools/VisualBuilder/VBWidget.cpp b/DevTools/VisualBuilder/VBWidget.cpp index a3de2ac241..2450d7e5a7 100644 --- a/DevTools/VisualBuilder/VBWidget.cpp +++ b/DevTools/VisualBuilder/VBWidget.cpp @@ -15,12 +15,13 @@ #include #include -VBWidget::VBWidget(VBWidgetType type, VBForm& form) +VBWidget::VBWidget(VBWidgetType type, VBForm& form, VBWidget* parent) : m_type(type) , m_form(form) , m_property_model(VBWidgetPropertyModel::create(*this)) { - m_gwidget = VBWidgetRegistry::build_gwidget(*this, type, &form, m_properties); + auto* widget_parent = parent ? parent->gwidget() : &form; + m_gwidget = VBWidgetRegistry::build_gwidget(*this, type, widget_parent, m_properties); m_form.m_gwidget_map.set(m_gwidget, this); setup_properties(); } @@ -34,14 +35,17 @@ VBWidget::~VBWidget() Rect VBWidget::rect() const { - return m_gwidget->relative_rect(); + return m_gwidget->window_relative_rect(); } void VBWidget::set_rect(const Rect& rect) { - if (rect == m_gwidget->relative_rect()) + if (rect == m_gwidget->window_relative_rect()) return; - m_gwidget->set_relative_rect(rect); + auto new_window_relative_rect = rect; + if (m_gwidget->parent()) + new_window_relative_rect.move_by(-m_gwidget->parent_widget()->window_relative_rect().location()); + m_gwidget->set_relative_rect(new_window_relative_rect); synchronize_properties(); } diff --git a/DevTools/VisualBuilder/VBWidget.h b/DevTools/VisualBuilder/VBWidget.h index 8c17e77d0d..67f9b67a84 100644 --- a/DevTools/VisualBuilder/VBWidget.h +++ b/DevTools/VisualBuilder/VBWidget.h @@ -45,7 +45,7 @@ class VBWidget : public RefCounted friend class VBWidgetPropertyModel; public: - static NonnullRefPtr create(VBWidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); } + static NonnullRefPtr create(VBWidgetType type, VBForm& form, VBWidget* parent) { return adopt(*new VBWidget(type, form, parent)); } ~VBWidget(); bool is_selected() const; @@ -73,7 +73,7 @@ public: void capture_transform_origin_rect(); private: - VBWidget(VBWidgetType, VBForm&); + VBWidget(VBWidgetType, VBForm&, VBWidget* parent); void add_property(const String& name, Function&& getter, Function&& setter);