From 707bfe848d95a89d53b02f971afbf82782f9d6a9 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Thu, 11 Apr 2019 21:41:09 +0200 Subject: [PATCH] VisualBuilder: Add a table view with the selected widget's properties. --- Applications/VisualBuilder/Makefile | 1 + Applications/VisualBuilder/VBForm.cpp | 4 ++ Applications/VisualBuilder/VBForm.h | 2 + Applications/VisualBuilder/VBProperty.h | 1 + Applications/VisualBuilder/VBWidget.cpp | 4 +- Applications/VisualBuilder/VBWidget.h | 7 ++- .../VisualBuilder/VBWidgetPropertyModel.cpp | 52 +++++++++++++++++++ .../VisualBuilder/VBWidgetPropertyModel.h | 30 +++++++++++ .../VisualBuilder/VBWidgetRegistry.cpp | 4 +- Applications/VisualBuilder/VBWidgetRegistry.h | 2 +- Applications/VisualBuilder/main.cpp | 12 ++++- 11 files changed, 113 insertions(+), 6 deletions(-) create mode 100644 Applications/VisualBuilder/VBWidgetPropertyModel.cpp create mode 100644 Applications/VisualBuilder/VBWidgetPropertyModel.h diff --git a/Applications/VisualBuilder/Makefile b/Applications/VisualBuilder/Makefile index 205ab0e2b3..53b796ee35 100644 --- a/Applications/VisualBuilder/Makefile +++ b/Applications/VisualBuilder/Makefile @@ -2,6 +2,7 @@ OBJS = \ VBForm.o \ VBWidget.o \ VBWidgetRegistry.o \ + VBWidgetPropertyModel.o \ VBProperty.o \ main.o diff --git a/Applications/VisualBuilder/VBForm.cpp b/Applications/VisualBuilder/VBForm.cpp index ebb04f49d8..74987910af 100644 --- a/Applications/VisualBuilder/VBForm.cpp +++ b/Applications/VisualBuilder/VBForm.cpp @@ -105,6 +105,8 @@ void VBForm::mousedown_event(GMouseEvent& event) if (!widget) { if (m_selected_widget) { m_selected_widget = nullptr; + if (on_widget_selected) + on_widget_selected(nullptr); update(); } return; @@ -113,6 +115,8 @@ void VBForm::mousedown_event(GMouseEvent& event) m_selected_widget = widget->make_weak_ptr(); m_transform_event_origin = event.position(); m_transform_widget_origin_rect = widget->rect(); + if (on_widget_selected) + on_widget_selected(widget); update(); } } diff --git a/Applications/VisualBuilder/VBForm.h b/Applications/VisualBuilder/VBForm.h index 0677a62a78..10d858157d 100644 --- a/Applications/VisualBuilder/VBForm.h +++ b/Applications/VisualBuilder/VBForm.h @@ -22,6 +22,8 @@ public: void insert_widget(VBWidgetType); + Function on_widget_selected; + protected: virtual void paint_event(GPaintEvent&) override; virtual void second_paint_event(GPaintEvent&) override; diff --git a/Applications/VisualBuilder/VBProperty.h b/Applications/VisualBuilder/VBProperty.h index 74470ccf91..25df176ce3 100644 --- a/Applications/VisualBuilder/VBProperty.h +++ b/Applications/VisualBuilder/VBProperty.h @@ -9,6 +9,7 @@ public: ~VBProperty(); String name() const { return m_name; } + const GVariant& value() const { return m_value; } bool is_readonly() const { return m_readonly; } void set_readonly(bool b) { m_readonly = b; } diff --git a/Applications/VisualBuilder/VBWidget.cpp b/Applications/VisualBuilder/VBWidget.cpp index 34864d435a..42b986d37b 100644 --- a/Applications/VisualBuilder/VBWidget.cpp +++ b/Applications/VisualBuilder/VBWidget.cpp @@ -2,11 +2,13 @@ #include "VBForm.h" #include "VBProperty.h" #include "VBWidgetRegistry.h" +#include "VBWidgetPropertyModel.h" #include VBWidget::VBWidget(VBWidgetType type, VBForm& form) : m_type(type) , m_form(form) + , m_property_model(VBWidgetPropertyModel::create(*this)) { m_gwidget = VBWidgetRegistry::build_gwidget(type, &form, m_properties); } @@ -69,6 +71,6 @@ Direction VBWidget::grabber_at(const Point& position) const void VBWidget::for_each_property(Function callback) { for (auto& it : m_properties) { - callback(*it.value); + callback(*it); } } diff --git a/Applications/VisualBuilder/VBWidget.h b/Applications/VisualBuilder/VBWidget.h index 179c87352e..9abeb9e8c7 100644 --- a/Applications/VisualBuilder/VBWidget.h +++ b/Applications/VisualBuilder/VBWidget.h @@ -12,6 +12,7 @@ class GPainter; class GWidget; class VBForm; class VBProperty; +class VBWidgetPropertyModel; enum class Direction { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft }; template @@ -28,6 +29,7 @@ inline void for_each_direction(Callback callback) } class VBWidget : public Retainable, public Weakable { + friend class VBWidgetPropertyModel; public: static Retained create(VBWidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); } ~VBWidget(); @@ -47,6 +49,8 @@ public: void for_each_property(Function); + VBWidgetPropertyModel& property_model() { return *m_property_model; } + protected: VBWidget(VBWidgetType, VBForm&); @@ -54,5 +58,6 @@ private: VBWidgetType m_type { VBWidgetType::None }; VBForm& m_form; GWidget* m_gwidget { nullptr }; - HashMap> m_properties; + Vector> m_properties; + Retained m_property_model; }; diff --git a/Applications/VisualBuilder/VBWidgetPropertyModel.cpp b/Applications/VisualBuilder/VBWidgetPropertyModel.cpp new file mode 100644 index 0000000000..456f4a4f56 --- /dev/null +++ b/Applications/VisualBuilder/VBWidgetPropertyModel.cpp @@ -0,0 +1,52 @@ +#include "VBWidgetPropertyModel.h" +#include "VBWidget.h" +#include "VBProperty.h" + +VBWidgetPropertyModel::VBWidgetPropertyModel(VBWidget& widget) + : m_widget(widget) +{ +} + +VBWidgetPropertyModel::~VBWidgetPropertyModel() +{ + ASSERT_NOT_REACHED(); +} + +int VBWidgetPropertyModel::row_count(const GModelIndex&) const +{ + dbgprintf("row count: %d\n", m_widget.m_properties.size()); + return m_widget.m_properties.size(); +} + +String VBWidgetPropertyModel::column_name(int column) const +{ + switch (column) { + case Column::Name: return "Name"; + case Column::Value: return "Value"; + default: ASSERT_NOT_REACHED(); + } +} + +GModel::ColumnMetadata VBWidgetPropertyModel::column_metadata(int column) const +{ + UNUSED_PARAM(column); + return { 100, TextAlignment::CenterLeft }; +} + +GVariant VBWidgetPropertyModel::data(const GModelIndex& index, Role role) const +{ + if (role == Role::Display) { + dbgprintf("Accessing prop #%d (size=%d) column %d\n", index.row(), m_widget.m_properties.size(), index.column()); + auto& property = *m_widget.m_properties[index.row()]; + auto value = property.value(); + dbgprintf("value type=%u\n", (unsigned)value.type()); + dbgprintf("value impl=%x\n", (unsigned)value.to_string().impl()); + dbgprintf("value len=%x\n", (unsigned)value.to_string().impl()->length()); + dbgprintf("for value='%s'\n", value.to_string().characters()); + switch (index.column()) { + case Column::Name: return property.name(); + case Column::Value: return property.value(); + } + } + return { }; +} diff --git a/Applications/VisualBuilder/VBWidgetPropertyModel.h b/Applications/VisualBuilder/VBWidgetPropertyModel.h new file mode 100644 index 0000000000..4b712e9660 --- /dev/null +++ b/Applications/VisualBuilder/VBWidgetPropertyModel.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +class VBWidget; +class VBProperty; + +class VBWidgetPropertyModel : public GModel { +public: + enum Column { + Name = 0, + Value, + __Count + }; + + static Retained create(VBWidget& widget) { return adopt(*new VBWidgetPropertyModel(widget)); } + virtual ~VBWidgetPropertyModel() override; + + virtual int row_count(const GModelIndex&) const override; + virtual int column_count(const GModelIndex&) const override { return Column::__Count; } + virtual String column_name(int column) const override; + virtual ColumnMetadata column_metadata(int column) const override; + virtual GVariant data(const GModelIndex&, Role = Role::Display) const override; + virtual void update() override { } + +private: + explicit VBWidgetPropertyModel(VBWidget&); + + VBWidget& m_widget; +}; diff --git a/Applications/VisualBuilder/VBWidgetRegistry.cpp b/Applications/VisualBuilder/VBWidgetRegistry.cpp index 673dfa357c..0cd75e451e 100644 --- a/Applications/VisualBuilder/VBWidgetRegistry.cpp +++ b/Applications/VisualBuilder/VBWidgetRegistry.cpp @@ -74,13 +74,13 @@ static GWidget* build_gwidget(VBWidgetType type, GWidget* parent) } -GWidget* VBWidgetRegistry::build_gwidget(VBWidgetType type, GWidget* parent, HashMap>& properties) +GWidget* VBWidgetRegistry::build_gwidget(VBWidgetType type, GWidget* parent, Vector>& properties) { auto* gwidget = ::build_gwidget(type, parent); auto add_property = [&properties] (const String& name, const GVariant& value, bool is_readonly) { auto property = make(name, value); property->set_readonly(is_readonly); - properties.set(name, move(property)); + properties.append(move(property)); }; add_property("ClassName", to_class_name(type), true); return gwidget; diff --git a/Applications/VisualBuilder/VBWidgetRegistry.h b/Applications/VisualBuilder/VBWidgetRegistry.h index 523e195647..d89611f2c8 100644 --- a/Applications/VisualBuilder/VBWidgetRegistry.h +++ b/Applications/VisualBuilder/VBWidgetRegistry.h @@ -16,5 +16,5 @@ public: callback((VBWidgetType)i); } - static GWidget* build_gwidget(VBWidgetType, GWidget* parent, HashMap>&); + static GWidget* build_gwidget(VBWidgetType, GWidget* parent, Vector>&); }; diff --git a/Applications/VisualBuilder/main.cpp b/Applications/VisualBuilder/main.cpp index ef0a36e494..a7cb966964 100644 --- a/Applications/VisualBuilder/main.cpp +++ b/Applications/VisualBuilder/main.cpp @@ -5,8 +5,10 @@ #include #include #include +#include #include "VBForm.h" #include "VBWidget.h" +#include "VBWidgetPropertyModel.h" #include #include #include @@ -15,11 +17,18 @@ static GWindow* make_toolbox_window(); static GWindow* make_properties_window(); +GTableView* g_property_table_view; + int main(int argc, char** argv) { GApplication app(argc, argv); + auto* propbox = make_properties_window(); + auto* form1 = new VBForm("Form1"); + form1->on_widget_selected = [] (VBWidget* widget) { + g_property_table_view->set_model(widget ? &widget->property_model() : nullptr); + }; auto menubar = make(); auto app_menu = make("Visual Builder"); @@ -53,7 +62,6 @@ int main(int argc, char** argv) auto* toolbox = make_toolbox_window(); toolbox->show(); - auto* propbox = make_properties_window(); propbox->show(); return app.exec(); @@ -141,5 +149,7 @@ GWindow* make_properties_window() widget->set_layout(make(Orientation::Vertical)); window->set_main_widget(widget); + g_property_table_view = new GTableView(widget); + return window; }