diff --git a/Applications/VisualBuilder/Makefile b/Applications/VisualBuilder/Makefile index cacbff9524..205ab0e2b3 100644 --- a/Applications/VisualBuilder/Makefile +++ b/Applications/VisualBuilder/Makefile @@ -1,6 +1,8 @@ OBJS = \ VBForm.o \ VBWidget.o \ + VBWidgetRegistry.o \ + VBProperty.o \ main.o APP = VisualBuilder diff --git a/Applications/VisualBuilder/VBForm.cpp b/Applications/VisualBuilder/VBForm.cpp index d29b83d201..ebb04f49d8 100644 --- a/Applications/VisualBuilder/VBForm.cpp +++ b/Applications/VisualBuilder/VBForm.cpp @@ -17,24 +17,24 @@ VBForm::VBForm(const String& name, GWidget* parent) set_background_color(Color::LightGray); set_greedy_for_hits(true); - auto box1 = VBWidget::create(WidgetType::GSpinBox, *this); + auto box1 = VBWidget::create(VBWidgetType::GSpinBox, *this); box1->set_rect({ 10, 10, 81, 21 }); m_widgets.append(move(box1)); - auto box2 = VBWidget::create(WidgetType::GTextEditor, *this); + auto box2 = VBWidget::create(VBWidgetType::GTextEditor, *this); box2->set_rect({ 100, 100, 161, 161 }); m_widgets.append(move(box2)); - auto button1 = VBWidget::create(WidgetType::GButton, *this); + auto button1 = VBWidget::create(VBWidgetType::GButton, *this); button1->set_rect({ 200, 50, 81, 21 }); m_widgets.append(move(button1)); - auto groupbox1 = VBWidget::create(WidgetType::GGroupBox, *this); + auto groupbox1 = VBWidget::create(VBWidgetType::GGroupBox, *this); groupbox1->set_rect({ 300, 150, 161, 51 }); m_widgets.append(move(groupbox1)); } -void VBForm::insert_widget(WidgetType 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 } }); diff --git a/Applications/VisualBuilder/VBForm.h b/Applications/VisualBuilder/VBForm.h index 8e9d357541..0677a62a78 100644 --- a/Applications/VisualBuilder/VBForm.h +++ b/Applications/VisualBuilder/VBForm.h @@ -20,7 +20,7 @@ public: void set_should_snap_to_grip(bool snap) { m_should_snap_to_grid = snap; } bool should_snap_to_grid() const { return m_should_snap_to_grid; } - void insert_widget(WidgetType); + void insert_widget(VBWidgetType); protected: virtual void paint_event(GPaintEvent&) override; diff --git a/Applications/VisualBuilder/VBProperty.cpp b/Applications/VisualBuilder/VBProperty.cpp new file mode 100644 index 0000000000..bb0b3becfd --- /dev/null +++ b/Applications/VisualBuilder/VBProperty.cpp @@ -0,0 +1,11 @@ +#include "VBProperty.h" + +VBProperty::VBProperty(const String& name, const GVariant& value) + : m_name(name) + , m_value(value) +{ +} + +VBProperty::~VBProperty() +{ +} diff --git a/Applications/VisualBuilder/VBProperty.h b/Applications/VisualBuilder/VBProperty.h new file mode 100644 index 0000000000..74470ccf91 --- /dev/null +++ b/Applications/VisualBuilder/VBProperty.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class VBProperty { +public: + VBProperty(const String& name, const GVariant& value); + ~VBProperty(); + + String name() const { return m_name; } + + bool is_readonly() const { return m_readonly; } + void set_readonly(bool b) { m_readonly = b; } + +private: + String m_name; + GVariant m_value; + bool m_readonly { false }; +}; diff --git a/Applications/VisualBuilder/VBWidget.cpp b/Applications/VisualBuilder/VBWidget.cpp index 68e47b6c9f..34864d435a 100644 --- a/Applications/VisualBuilder/VBWidget.cpp +++ b/Applications/VisualBuilder/VBWidget.cpp @@ -1,68 +1,14 @@ #include "VBWidget.h" #include "VBForm.h" +#include "VBProperty.h" +#include "VBWidgetRegistry.h" #include -#include -#include -#include -#include -#include -#include -#include -#include -static GWidget* build_gwidget(WidgetType type, GWidget* parent) -{ - switch (type) { - case WidgetType::GWidget: - return new GWidget(parent); - case WidgetType::GScrollBar: - return new GScrollBar(Orientation::Vertical, parent); - case WidgetType::GGroupBox: - return new GGroupBox("groupbox_1", parent); - case WidgetType::GLabel: { - auto* label = new GLabel(parent); - label->set_text("label_1"); - return label; - } - case WidgetType::GButton: { - auto* button = new GButton(parent); - button->set_caption("button_1"); - return button; - } - case WidgetType::GSpinBox: { - auto* box = new GSpinBox(parent); - box->set_range(0, 100); - box->set_value(0); - return box; - } - case WidgetType::GTextEditor: { - auto* editor = new GTextEditor(GTextEditor::Type::MultiLine, parent); - editor->set_ruler_visible(false); - return editor; - } - case WidgetType::GProgressBar: { - auto* bar = new GProgressBar(parent); - bar->set_format(GProgressBar::Format::NoText); - bar->set_range(0, 100); - bar->set_value(50); - return bar; - } - case WidgetType::GCheckBox: { - auto* box = new GCheckBox(parent); - box->set_caption("checkbox_1"); - return box; - } - default: - ASSERT_NOT_REACHED(); - return nullptr; - } -} - -VBWidget::VBWidget(WidgetType type, VBForm& form) +VBWidget::VBWidget(VBWidgetType type, VBForm& form) : m_type(type) , m_form(form) { - m_gwidget = build_gwidget(type, &form); + m_gwidget = VBWidgetRegistry::build_gwidget(type, &form, m_properties); } VBWidget::~VBWidget() @@ -119,3 +65,10 @@ Direction VBWidget::grabber_at(const Point& position) const }); return found_grabber; } + +void VBWidget::for_each_property(Function callback) +{ + for (auto& it : m_properties) { + callback(*it.value); + } +} diff --git a/Applications/VisualBuilder/VBWidget.h b/Applications/VisualBuilder/VBWidget.h index 4fcc894f5e..179c87352e 100644 --- a/Applications/VisualBuilder/VBWidget.h +++ b/Applications/VisualBuilder/VBWidget.h @@ -4,10 +4,14 @@ #include #include #include +#include +#include +#include "VBWidgetType.h" class GPainter; class GWidget; class VBForm; +class VBProperty; enum class Direction { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft }; template @@ -23,22 +27,9 @@ inline void for_each_direction(Callback callback) callback(Direction::DownLeft); } -enum class WidgetType { - None, - GWidget, - GButton, - GLabel, - GSpinBox, - GTextEditor, - GProgressBar, - GCheckBox, - GScrollBar, - GGroupBox, -}; - class VBWidget : public Retainable, public Weakable { public: - static Retained create(WidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); } + static Retained create(VBWidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); } ~VBWidget(); bool is_selected() const; @@ -51,11 +42,17 @@ public: GWidget* gwidget() { return m_gwidget; } + const VBProperty* property_by_name(const String&) const; + VBProperty* property_by_name(const String&); + + void for_each_property(Function); + protected: - VBWidget(WidgetType, VBForm&); + VBWidget(VBWidgetType, VBForm&); private: - WidgetType m_type { WidgetType::None }; + VBWidgetType m_type { VBWidgetType::None }; VBForm& m_form; GWidget* m_gwidget { nullptr }; + HashMap> m_properties; }; diff --git a/Applications/VisualBuilder/VBWidgetRegistry.cpp b/Applications/VisualBuilder/VBWidgetRegistry.cpp new file mode 100644 index 0000000000..673dfa357c --- /dev/null +++ b/Applications/VisualBuilder/VBWidgetRegistry.cpp @@ -0,0 +1,87 @@ +#include "VBWidgetRegistry.h" +#include "VBProperty.h" +#include +#include +#include +#include +#include +#include +#include +#include + +static String to_class_name(VBWidgetType type) +{ + switch (type) { + case VBWidgetType::GWidget: return "GWidget"; + case VBWidgetType::GButton: return "GButton"; + case VBWidgetType::GLabel: return "GLabel"; + case VBWidgetType::GSpinBox: return "GSpinBox"; + case VBWidgetType::GTextEditor: return "GTextEditor"; + case VBWidgetType::GProgressBar: return "GProgressBar"; + case VBWidgetType::GCheckBox: return "GCheckBox"; + case VBWidgetType::GScrollBar: return "GScrollBar"; + case VBWidgetType::GGroupBox: return "GGroupBox"; + default: ASSERT_NOT_REACHED(); + } +} + +static GWidget* build_gwidget(VBWidgetType type, GWidget* parent) +{ + switch (type) { + case VBWidgetType::GWidget: + return new GWidget(parent); + case VBWidgetType::GScrollBar: + return new GScrollBar(Orientation::Vertical, parent); + case VBWidgetType::GGroupBox: + return new GGroupBox("groupbox_1", parent); + case VBWidgetType::GLabel: { + auto* label = new GLabel(parent); + label->set_text("label_1"); + return label; + } + case VBWidgetType::GButton: { + auto* button = new GButton(parent); + button->set_caption("button_1"); + return button; + } + case VBWidgetType::GSpinBox: { + auto* box = new GSpinBox(parent); + box->set_range(0, 100); + box->set_value(0); + return box; + } + case VBWidgetType::GTextEditor: { + auto* editor = new GTextEditor(GTextEditor::Type::MultiLine, parent); + editor->set_ruler_visible(false); + return editor; + } + case VBWidgetType::GProgressBar: { + auto* bar = new GProgressBar(parent); + bar->set_format(GProgressBar::Format::NoText); + bar->set_range(0, 100); + bar->set_value(50); + return bar; + } + case VBWidgetType::GCheckBox: { + auto* box = new GCheckBox(parent); + box->set_caption("checkbox_1"); + return box; + } + default: + ASSERT_NOT_REACHED(); + return nullptr; + } +} + + +GWidget* VBWidgetRegistry::build_gwidget(VBWidgetType type, GWidget* parent, HashMap>& 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)); + }; + add_property("ClassName", to_class_name(type), true); + return gwidget; +} diff --git a/Applications/VisualBuilder/VBWidgetRegistry.h b/Applications/VisualBuilder/VBWidgetRegistry.h new file mode 100644 index 0000000000..523e195647 --- /dev/null +++ b/Applications/VisualBuilder/VBWidgetRegistry.h @@ -0,0 +1,20 @@ +#pragma once + +#include "VBWidgetType.h" +#include +#include +#include + +class GWidget; +class VBProperty; + +class VBWidgetRegistry { +public: + template static void for_each_widget_type(Callback callback) + { + for (unsigned i = 1; i < (unsigned)VBWidgetType::__Count; ++i) + callback((VBWidgetType)i); + } + + static GWidget* build_gwidget(VBWidgetType, GWidget* parent, HashMap>&); +}; diff --git a/Applications/VisualBuilder/VBWidgetType.h b/Applications/VisualBuilder/VBWidgetType.h new file mode 100644 index 0000000000..6ca8a6f4b2 --- /dev/null +++ b/Applications/VisualBuilder/VBWidgetType.h @@ -0,0 +1,15 @@ +#pragma once + +enum class VBWidgetType { + None = 0, + GWidget, + GButton, + GLabel, + GSpinBox, + GTextEditor, + GProgressBar, + GCheckBox, + GScrollBar, + GGroupBox, + __Count +}; diff --git a/Applications/VisualBuilder/main.cpp b/Applications/VisualBuilder/main.cpp index e2f819f8fe..ef0a36e494 100644 --- a/Applications/VisualBuilder/main.cpp +++ b/Applications/VisualBuilder/main.cpp @@ -75,7 +75,7 @@ GWindow* make_toolbox_window() label_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/label.png")); label_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GLabel); + form->insert_widget(VBWidgetType::GLabel); }; auto* button_button = new GButton(widget); @@ -83,49 +83,49 @@ GWindow* make_toolbox_window() button_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/button.png")); button_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GButton); + form->insert_widget(VBWidgetType::GButton); }; auto* spinbox_button = new GButton(widget); spinbox_button->set_tooltip("GSpinBox"); spinbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/spinbox.png")); spinbox_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GSpinBox); + form->insert_widget(VBWidgetType::GSpinBox); }; auto* editor_button = new GButton(widget); editor_button->set_tooltip("GTextEditor"); editor_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/textbox.png")); editor_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GTextEditor); + form->insert_widget(VBWidgetType::GTextEditor); }; auto* progress_bar_button = new GButton(widget); progress_bar_button->set_tooltip("GProgressBar"); progress_bar_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/progressbar.png")); progress_bar_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GProgressBar); + form->insert_widget(VBWidgetType::GProgressBar); }; auto* checkbox_button = new GButton(widget); checkbox_button->set_tooltip("GCheckBox"); checkbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/checkbox.png")); checkbox_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GCheckBox); + form->insert_widget(VBWidgetType::GCheckBox); }; auto* scrollbar_button = new GButton(widget); scrollbar_button->set_tooltip("GScrollBar"); scrollbar_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/scrollbar.png")); scrollbar_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GScrollBar); + form->insert_widget(VBWidgetType::GScrollBar); }; auto* groupbox_button = new GButton(widget); groupbox_button->set_tooltip("GGroupBox"); groupbox_button->set_icon(GraphicsBitmap::load_from_file("/res/icons/vbwidgets/groupbox.png")); groupbox_button->on_click = [] (GButton&) { if (auto* form = VBForm::current()) - form->insert_widget(WidgetType::GGroupBox); + form->insert_widget(VBWidgetType::GGroupBox); }; return window; }