Skip to content

Commit ca538b6

Browse files
committed
LibGUI: Add a simple GWidget class registry/factory
You can now register a GWidget subclass with REGISTER_GWIDGET(class) and it will be available for factory construction through the new GWidgetClassRegistration interface. To obtain a GWidgetClassRegistration for a given class name, you call GWidgetClassRegistration::find(class_name). You can also iterate over all the registered classes using GWCR::for_each(callback). This will be very useful for implementing a proper GUI designer, and also in the future for things like script bindings. NOTE: All of the registrations are done in GWidget.cpp at the moment since I ran into trouble with the fricken linker pruning the global constructors this mechanism relies on. :^)
1 parent a353d16 commit ca538b6

File tree

10 files changed

+109
-8
lines changed

10 files changed

+109
-8
lines changed

Libraries/LibGUI/GRadioButton.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1+
#include <LibDraw/GraphicsBitmap.h>
12
#include <LibGUI/GPainter.h>
23
#include <LibGUI/GRadioButton.h>
3-
#include <LibDraw/GraphicsBitmap.h>
44

55
static RefPtr<GraphicsBitmap> s_unfilled_circle_bitmap;
66
static RefPtr<GraphicsBitmap> s_filled_circle_bitmap;
77
static RefPtr<GraphicsBitmap> s_changing_filled_circle_bitmap;
88
static RefPtr<GraphicsBitmap> s_changing_unfilled_circle_bitmap;
99

10+
GRadioButton::GRadioButton(GWidget* parent)
11+
: GRadioButton({}, parent)
12+
{
13+
}
14+
1015
GRadioButton::GRadioButton(const StringView& text, GWidget* parent)
1116
: GAbstractButton(text, parent)
1217
{

Libraries/LibGUI/GRadioButton.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ class GRadioButton : public GAbstractButton {
1010
virtual void click() override;
1111

1212
protected:
13-
GRadioButton(const StringView& text, GWidget* parent);
13+
explicit GRadioButton(GWidget* parent);
14+
explicit GRadioButton(const StringView& text, GWidget* parent);
1415
virtual void paint_event(GPaintEvent&) override;
1516

1617
private:

Libraries/LibGUI/GScrollBar.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
#include <LibGUI/GPainter.h>
2-
#include <LibGUI/GScrollBar.h>
31
#include <LibDraw/CharacterBitmap.h>
42
#include <LibDraw/GraphicsBitmap.h>
53
#include <LibDraw/StylePainter.h>
4+
#include <LibGUI/GPainter.h>
5+
#include <LibGUI/GScrollBar.h>
66

77
static const char* s_up_arrow_bitmap_data = {
88
" "
@@ -57,6 +57,11 @@ static CharacterBitmap* s_down_arrow_bitmap;
5757
static CharacterBitmap* s_left_arrow_bitmap;
5858
static CharacterBitmap* s_right_arrow_bitmap;
5959

60+
GScrollBar::GScrollBar(GWidget* parent)
61+
: GScrollBar(Orientation::Vertical, parent)
62+
{
63+
}
64+
6065
GScrollBar::GScrollBar(Orientation orientation, GWidget* parent)
6166
: GWidget(parent)
6267
, m_orientation(orientation)
@@ -239,7 +244,7 @@ void GScrollBar::mousedown_event(GMouseEvent& event)
239244
return;
240245
}
241246
if (has_scrubber() && scrubber_rect().contains(event.position())) {
242-
m_scrubber_in_use = true;
247+
m_scrubber_in_use = true;
243248
m_scrubbing = true;
244249
m_scrub_start_value = value();
245250
m_scrub_origin = event.position();

Libraries/LibGUI/GScrollBar.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class GScrollBar final : public GWidget {
3838
};
3939

4040
private:
41+
explicit GScrollBar(GWidget* parent);
4142
explicit GScrollBar(Orientation, GWidget* parent);
4243

4344
virtual void paint_event(GPaintEvent&) override;

Libraries/LibGUI/GSlider.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
#include <LibGUI/GPainter.h>
33
#include <LibGUI/GSlider.h>
44

5+
GSlider::GSlider(GWidget* parent)
6+
: GSlider(Orientation::Horizontal, parent)
7+
{
8+
}
9+
510
GSlider::GSlider(Orientation orientation, GWidget* parent)
611
: GWidget(parent)
712
, m_orientation(orientation)

Libraries/LibGUI/GSlider.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ class GSlider : public GWidget {
4444
Function<void(int)> on_value_changed;
4545

4646
protected:
47-
GSlider(Orientation, GWidget*);
47+
explicit GSlider(GWidget*);
48+
explicit GSlider(Orientation, GWidget*);
4849

4950
virtual void paint_event(GPaintEvent&) override;
5051
virtual void mousedown_event(GMouseEvent&) override;

Libraries/LibGUI/GTextEditor.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@
1515

1616
//#define DEBUG_GTEXTEDITOR
1717

18+
GTextEditor::GTextEditor(GWidget* parent)
19+
: GTextEditor(Type::MultiLine, parent)
20+
{
21+
}
22+
1823
GTextEditor::GTextEditor(Type type, GWidget* parent)
1924
: GScrollableWidget(parent)
2025
, m_type(type)

Libraries/LibGUI/GTextEditor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,8 @@ class GTextEditor
102102
void set_cursor(const GTextPosition&);
103103

104104
protected:
105-
GTextEditor(Type, GWidget* parent);
105+
explicit GTextEditor(GWidget* parent);
106+
explicit GTextEditor(Type, GWidget* parent);
106107

107108
virtual void did_change_font() override;
108109
virtual void paint_event(GPaintEvent&) override;

Libraries/LibGUI/GWidget.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,59 @@
1212
#include <LibGUI/GWindowServerConnection.h>
1313
#include <unistd.h>
1414

15+
#include <LibGUI/GButton.h>
16+
#include <LibGUI/GCheckBox.h>
17+
#include <LibGUI/GGroupBox.h>
18+
#include <LibGUI/GLabel.h>
19+
#include <LibGUI/GRadioButton.h>
20+
#include <LibGUI/GScrollBar.h>
21+
#include <LibGUI/GSlider.h>
22+
#include <LibGUI/GSpinBox.h>
23+
#include <LibGUI/GTextBox.h>
24+
25+
REGISTER_GWIDGET(GButton)
26+
REGISTER_GWIDGET(GCheckBox)
27+
REGISTER_GWIDGET(GGroupBox)
28+
REGISTER_GWIDGET(GLabel)
29+
REGISTER_GWIDGET(GRadioButton)
30+
REGISTER_GWIDGET(GScrollBar)
31+
REGISTER_GWIDGET(GSlider)
32+
REGISTER_GWIDGET(GSpinBox)
33+
REGISTER_GWIDGET(GTextBox)
34+
REGISTER_GWIDGET(GWidget)
35+
36+
static HashMap<String, GWidgetClassRegistration*>& widget_classes()
37+
{
38+
static HashMap<String, GWidgetClassRegistration*>* map;
39+
if (!map)
40+
map = new HashMap<String, GWidgetClassRegistration*>;
41+
return *map;
42+
}
43+
44+
GWidgetClassRegistration::GWidgetClassRegistration(const String& class_name, Function<NonnullRefPtr<GWidget>(GWidget*)> factory)
45+
: m_class_name(class_name)
46+
, m_factory(move(factory))
47+
{
48+
widget_classes().set(class_name, this);
49+
}
50+
51+
GWidgetClassRegistration::~GWidgetClassRegistration()
52+
{
53+
ASSERT_NOT_REACHED();
54+
}
55+
56+
void GWidgetClassRegistration::for_each(Function<void(const GWidgetClassRegistration&)> callback)
57+
{
58+
for (auto& it : widget_classes()) {
59+
callback(*it.value);
60+
}
61+
}
62+
63+
const GWidgetClassRegistration* GWidgetClassRegistration::find(const String& class_name)
64+
{
65+
return widget_classes().get(class_name).value_or(nullptr);
66+
}
67+
1568
GWidget::GWidget(GWidget* parent)
1669
: CObject(parent, true)
1770
, m_font(Font::default_font())

Libraries/LibGUI/GWidget.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

3-
#include <AK/String.h>
43
#include <AK/Badge.h>
54
#include <AK/HashMap.h>
5+
#include <AK/String.h>
66
#include <LibCore/CElapsedTimer.h>
77
#include <LibCore/CObject.h>
88
#include <LibDraw/Color.h>
@@ -12,6 +12,10 @@
1212
#include <LibGUI/GEvent.h>
1313
#include <LibGUI/GShortcut.h>
1414

15+
#define REGISTER_GWIDGET(class_name) \
16+
extern GWidgetClassRegistration registration_##class_name; \
17+
GWidgetClassRegistration registration_##class_name(#class_name, [](GWidget* parent) { return class_name::construct(parent); });
18+
1519
class GraphicsBitmap;
1620
class GAction;
1721
class GLayout;
@@ -42,6 +46,26 @@ enum class VerticalDirection {
4246
Down
4347
};
4448

49+
class GWidget;
50+
51+
class GWidgetClassRegistration {
52+
AK_MAKE_NONCOPYABLE(GWidgetClassRegistration)
53+
AK_MAKE_NONMOVABLE(GWidgetClassRegistration)
54+
public:
55+
GWidgetClassRegistration(const String& class_name, Function<NonnullRefPtr<GWidget>(GWidget*)> factory);
56+
~GWidgetClassRegistration();
57+
58+
String class_name() const { return m_class_name; }
59+
NonnullRefPtr<GWidget> construct(GWidget* parent) const { return m_factory(parent); }
60+
61+
static void for_each(Function<void(const GWidgetClassRegistration&)>);
62+
static const GWidgetClassRegistration* find(const String& class_name);
63+
64+
private:
65+
String m_class_name;
66+
Function<NonnullRefPtr<GWidget>(GWidget*)> m_factory;
67+
};
68+
4569
class GWidget : public CObject {
4670
C_OBJECT(GWidget)
4771
public:

0 commit comments

Comments
 (0)