1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-22 19:25:07 +00:00

VisualBuilder: Add a widget registry and a property class.

I need somewhere to centralize the knowledge about the different widget
types available. And VBProperty represents a property key/value of arbitrary
type (it uses a GVariant for the value.)
This commit is contained in:
Andreas Kling 2019-04-11 16:13:19 +02:00
parent ba4a726e8b
commit f52e66ceda
11 changed files with 193 additions and 88 deletions

View file

@ -1,6 +1,8 @@
OBJS = \
VBForm.o \
VBWidget.o \
VBWidgetRegistry.o \
VBProperty.o \
main.o
APP = VisualBuilder

View file

@ -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 } });

View file

@ -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;

View file

@ -0,0 +1,11 @@
#include "VBProperty.h"
VBProperty::VBProperty(const String& name, const GVariant& value)
: m_name(name)
, m_value(value)
{
}
VBProperty::~VBProperty()
{
}

View file

@ -0,0 +1,20 @@
#pragma once
#include <AK/AKString.h>
#include <LibGUI/GVariant.h>
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 };
};

View file

@ -1,68 +1,14 @@
#include "VBWidget.h"
#include "VBForm.h"
#include "VBProperty.h"
#include "VBWidgetRegistry.h"
#include <LibGUI/GPainter.h>
#include <LibGUI/GLabel.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GTextEditor.h>
#include <LibGUI/GProgressBar.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GGroupBox.h>
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<void(VBProperty&)> callback)
{
for (auto& it : m_properties) {
callback(*it.value);
}
}

View file

@ -4,10 +4,14 @@
#include <AK/Retainable.h>
#include <AK/Retained.h>
#include <AK/Weakable.h>
#include <AK/HashMap.h>
#include <AK/Function.h>
#include "VBWidgetType.h"
class GPainter;
class GWidget;
class VBForm;
class VBProperty;
enum class Direction { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft };
template<typename Callback>
@ -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<VBWidget>, public Weakable<VBWidget> {
public:
static Retained<VBWidget> create(WidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); }
static Retained<VBWidget> 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<void(VBProperty&)>);
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<String, OwnPtr<VBProperty>> m_properties;
};

View file

@ -0,0 +1,87 @@
#include "VBWidgetRegistry.h"
#include "VBProperty.h"
#include <LibGUI/GLabel.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GTextEditor.h>
#include <LibGUI/GProgressBar.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GGroupBox.h>
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<String, OwnPtr<VBProperty>>& properties)
{
auto* gwidget = ::build_gwidget(type, parent);
auto add_property = [&properties] (const String& name, const GVariant& value, bool is_readonly) {
auto property = make<VBProperty>(name, value);
property->set_readonly(is_readonly);
properties.set(name, move(property));
};
add_property("ClassName", to_class_name(type), true);
return gwidget;
}

View file

@ -0,0 +1,20 @@
#pragma once
#include "VBWidgetType.h"
#include <AK/HashMap.h>
#include <AK/OwnPtr.h>
#include <AK/AKString.h>
class GWidget;
class VBProperty;
class VBWidgetRegistry {
public:
template<typename Callback> 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<String, OwnPtr<VBProperty>>&);
};

View file

@ -0,0 +1,15 @@
#pragma once
enum class VBWidgetType {
None = 0,
GWidget,
GButton,
GLabel,
GSpinBox,
GTextEditor,
GProgressBar,
GCheckBox,
GScrollBar,
GGroupBox,
__Count
};

View file

@ -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;
}