1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-16 07:04:58 +00:00

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. :^)
This commit is contained in:
Andreas Kling 2019-11-10 10:58:03 +01:00
parent a353d16ff4
commit ca538b6cee
10 changed files with 109 additions and 8 deletions

View file

@ -12,6 +12,59 @@
#include <LibGUI/GWindowServerConnection.h>
#include <unistd.h>
#include <LibGUI/GButton.h>
#include <LibGUI/GCheckBox.h>
#include <LibGUI/GGroupBox.h>
#include <LibGUI/GLabel.h>
#include <LibGUI/GRadioButton.h>
#include <LibGUI/GScrollBar.h>
#include <LibGUI/GSlider.h>
#include <LibGUI/GSpinBox.h>
#include <LibGUI/GTextBox.h>
REGISTER_GWIDGET(GButton)
REGISTER_GWIDGET(GCheckBox)
REGISTER_GWIDGET(GGroupBox)
REGISTER_GWIDGET(GLabel)
REGISTER_GWIDGET(GRadioButton)
REGISTER_GWIDGET(GScrollBar)
REGISTER_GWIDGET(GSlider)
REGISTER_GWIDGET(GSpinBox)
REGISTER_GWIDGET(GTextBox)
REGISTER_GWIDGET(GWidget)
static HashMap<String, GWidgetClassRegistration*>& widget_classes()
{
static HashMap<String, GWidgetClassRegistration*>* map;
if (!map)
map = new HashMap<String, GWidgetClassRegistration*>;
return *map;
}
GWidgetClassRegistration::GWidgetClassRegistration(const String& class_name, Function<NonnullRefPtr<GWidget>(GWidget*)> factory)
: m_class_name(class_name)
, m_factory(move(factory))
{
widget_classes().set(class_name, this);
}
GWidgetClassRegistration::~GWidgetClassRegistration()
{
ASSERT_NOT_REACHED();
}
void GWidgetClassRegistration::for_each(Function<void(const GWidgetClassRegistration&)> callback)
{
for (auto& it : widget_classes()) {
callback(*it.value);
}
}
const GWidgetClassRegistration* GWidgetClassRegistration::find(const String& class_name)
{
return widget_classes().get(class_name).value_or(nullptr);
}
GWidget::GWidget(GWidget* parent)
: CObject(parent, true)
, m_font(Font::default_font())