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:
parent
ba4a726e8b
commit
f52e66ceda
11 changed files with 193 additions and 88 deletions
|
@ -1,6 +1,8 @@
|
|||
OBJS = \
|
||||
VBForm.o \
|
||||
VBWidget.o \
|
||||
VBWidgetRegistry.o \
|
||||
VBProperty.o \
|
||||
main.o
|
||||
|
||||
APP = VisualBuilder
|
||||
|
|
|
@ -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 } });
|
||||
|
|
|
@ -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;
|
||||
|
|
11
Applications/VisualBuilder/VBProperty.cpp
Normal file
11
Applications/VisualBuilder/VBProperty.cpp
Normal file
|
@ -0,0 +1,11 @@
|
|||
#include "VBProperty.h"
|
||||
|
||||
VBProperty::VBProperty(const String& name, const GVariant& value)
|
||||
: m_name(name)
|
||||
, m_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
VBProperty::~VBProperty()
|
||||
{
|
||||
}
|
20
Applications/VisualBuilder/VBProperty.h
Normal file
20
Applications/VisualBuilder/VBProperty.h
Normal 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 };
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
87
Applications/VisualBuilder/VBWidgetRegistry.cpp
Normal file
87
Applications/VisualBuilder/VBWidgetRegistry.cpp
Normal 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;
|
||||
}
|
20
Applications/VisualBuilder/VBWidgetRegistry.h
Normal file
20
Applications/VisualBuilder/VBWidgetRegistry.h
Normal 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>>&);
|
||||
};
|
15
Applications/VisualBuilder/VBWidgetType.h
Normal file
15
Applications/VisualBuilder/VBWidgetType.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
enum class VBWidgetType {
|
||||
None = 0,
|
||||
GWidget,
|
||||
GButton,
|
||||
GLabel,
|
||||
GSpinBox,
|
||||
GTextEditor,
|
||||
GProgressBar,
|
||||
GCheckBox,
|
||||
GScrollBar,
|
||||
GGroupBox,
|
||||
__Count
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue