瀏覽代碼

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.
Andreas Kling 5 年之前
父節點
當前提交
9acdf9bb0a
共有 3 個文件被更改,包括 23 次插入13 次删除
  1. 12 6
      DevTools/VisualBuilder/VBForm.cpp
  2. 9 5
      DevTools/VisualBuilder/VBWidget.cpp
  3. 2 2
      DevTools/VisualBuilder/VBWidget.h

+ 12 - 6
DevTools/VisualBuilder/VBForm.cpp

@@ -7,6 +7,7 @@
 #include <AK/StringBuilder.h>
 #include <AK/StringBuilder.h>
 #include <LibCore/CFile.h>
 #include <LibCore/CFile.h>
 #include <LibGUI/GAction.h>
 #include <LibGUI/GAction.h>
+#include <LibGUI/GBoxLayout.h>
 #include <LibGUI/GMenu.h>
 #include <LibGUI/GMenu.h>
 #include <LibGUI/GMessageBox.h>
 #include <LibGUI/GMessageBox.h>
 #include <LibGUI/GPainter.h>
 #include <LibGUI/GPainter.h>
@@ -47,8 +48,12 @@ void VBForm::context_menu_event(GContextMenuEvent& event)
 
 
 void VBForm::insert_widget(VBWidgetType type)
 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_next_insertion_position.move_by(m_grid_size, m_grid_size);
     m_widgets.append(move(widget));
     m_widgets.append(move(widget));
 }
 }
@@ -91,10 +96,10 @@ bool VBForm::is_selected(const VBWidget& widget) const
 
 
 VBWidget* VBForm::widget_at(const Point& position)
 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 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)
 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_object = widget_value.as_object();
         auto widget_class = widget_object.get("class").as_string();
         auto widget_class = widget_object.get("class").as_string();
         auto widget_type = widget_type_from_class_name(widget_class);
         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) {
         widget_object.for_each_member([&](auto& property_name, const JsonValue& property_value) {
             (void)property_name;
             (void)property_name;
             (void)property_value;
             (void)property_value;

+ 9 - 5
DevTools/VisualBuilder/VBWidget.cpp

@@ -15,12 +15,13 @@
 #include <LibGUI/GSpinBox.h>
 #include <LibGUI/GSpinBox.h>
 #include <LibGUI/GTextEditor.h>
 #include <LibGUI/GTextEditor.h>
 
 
-VBWidget::VBWidget(VBWidgetType type, VBForm& form)
+VBWidget::VBWidget(VBWidgetType type, VBForm& form, VBWidget* parent)
     : m_type(type)
     : m_type(type)
     , m_form(form)
     , m_form(form)
     , m_property_model(VBWidgetPropertyModel::create(*this))
     , 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);
     m_form.m_gwidget_map.set(m_gwidget, this);
     setup_properties();
     setup_properties();
 }
 }
@@ -34,14 +35,17 @@ VBWidget::~VBWidget()
 
 
 Rect VBWidget::rect() const
 Rect VBWidget::rect() const
 {
 {
-    return m_gwidget->relative_rect();
+    return m_gwidget->window_relative_rect();
 }
 }
 
 
 void VBWidget::set_rect(const Rect& rect)
 void VBWidget::set_rect(const Rect& rect)
 {
 {
-    if (rect == m_gwidget->relative_rect())
+    if (rect == m_gwidget->window_relative_rect())
         return;
         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();
     synchronize_properties();
 }
 }
 
 

+ 2 - 2
DevTools/VisualBuilder/VBWidget.h

@@ -45,7 +45,7 @@ class VBWidget : public RefCounted<VBWidget>
     friend class VBWidgetPropertyModel;
     friend class VBWidgetPropertyModel;
 
 
 public:
 public:
-    static NonnullRefPtr<VBWidget> create(VBWidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); }
+    static NonnullRefPtr<VBWidget> create(VBWidgetType type, VBForm& form, VBWidget* parent) { return adopt(*new VBWidget(type, form, parent)); }
     ~VBWidget();
     ~VBWidget();
 
 
     bool is_selected() const;
     bool is_selected() const;
@@ -73,7 +73,7 @@ public:
     void capture_transform_origin_rect();
     void capture_transform_origin_rect();
 
 
 private:
 private:
-    VBWidget(VBWidgetType, VBForm&);
+    VBWidget(VBWidgetType, VBForm&, VBWidget* parent);
 
 
     void add_property(const String& name, Function<GVariant(const GWidget&)>&& getter, Function<void(GWidget&, const GVariant&)>&& setter);
     void add_property(const String& name, Function<GVariant(const GWidget&)>&& getter, Function<void(GWidget&, const GVariant&)>&& setter);