mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:48:14 +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:
parent
a353d16ff4
commit
ca538b6cee
10 changed files with 109 additions and 8 deletions
|
@ -1,12 +1,17 @@
|
||||||
|
#include <LibDraw/GraphicsBitmap.h>
|
||||||
#include <LibGUI/GPainter.h>
|
#include <LibGUI/GPainter.h>
|
||||||
#include <LibGUI/GRadioButton.h>
|
#include <LibGUI/GRadioButton.h>
|
||||||
#include <LibDraw/GraphicsBitmap.h>
|
|
||||||
|
|
||||||
static RefPtr<GraphicsBitmap> s_unfilled_circle_bitmap;
|
static RefPtr<GraphicsBitmap> s_unfilled_circle_bitmap;
|
||||||
static RefPtr<GraphicsBitmap> s_filled_circle_bitmap;
|
static RefPtr<GraphicsBitmap> s_filled_circle_bitmap;
|
||||||
static RefPtr<GraphicsBitmap> s_changing_filled_circle_bitmap;
|
static RefPtr<GraphicsBitmap> s_changing_filled_circle_bitmap;
|
||||||
static RefPtr<GraphicsBitmap> s_changing_unfilled_circle_bitmap;
|
static RefPtr<GraphicsBitmap> s_changing_unfilled_circle_bitmap;
|
||||||
|
|
||||||
|
GRadioButton::GRadioButton(GWidget* parent)
|
||||||
|
: GRadioButton({}, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GRadioButton::GRadioButton(const StringView& text, GWidget* parent)
|
GRadioButton::GRadioButton(const StringView& text, GWidget* parent)
|
||||||
: GAbstractButton(text, parent)
|
: GAbstractButton(text, parent)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,8 @@ public:
|
||||||
virtual void click() override;
|
virtual void click() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GRadioButton(const StringView& text, GWidget* parent);
|
explicit GRadioButton(GWidget* parent);
|
||||||
|
explicit GRadioButton(const StringView& text, GWidget* parent);
|
||||||
virtual void paint_event(GPaintEvent&) override;
|
virtual void paint_event(GPaintEvent&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#include <LibGUI/GPainter.h>
|
|
||||||
#include <LibGUI/GScrollBar.h>
|
|
||||||
#include <LibDraw/CharacterBitmap.h>
|
#include <LibDraw/CharacterBitmap.h>
|
||||||
#include <LibDraw/GraphicsBitmap.h>
|
#include <LibDraw/GraphicsBitmap.h>
|
||||||
#include <LibDraw/StylePainter.h>
|
#include <LibDraw/StylePainter.h>
|
||||||
|
#include <LibGUI/GPainter.h>
|
||||||
|
#include <LibGUI/GScrollBar.h>
|
||||||
|
|
||||||
static const char* s_up_arrow_bitmap_data = {
|
static const char* s_up_arrow_bitmap_data = {
|
||||||
" "
|
" "
|
||||||
|
@ -57,6 +57,11 @@ static CharacterBitmap* s_down_arrow_bitmap;
|
||||||
static CharacterBitmap* s_left_arrow_bitmap;
|
static CharacterBitmap* s_left_arrow_bitmap;
|
||||||
static CharacterBitmap* s_right_arrow_bitmap;
|
static CharacterBitmap* s_right_arrow_bitmap;
|
||||||
|
|
||||||
|
GScrollBar::GScrollBar(GWidget* parent)
|
||||||
|
: GScrollBar(Orientation::Vertical, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GScrollBar::GScrollBar(Orientation orientation, GWidget* parent)
|
GScrollBar::GScrollBar(Orientation orientation, GWidget* parent)
|
||||||
: GWidget(parent)
|
: GWidget(parent)
|
||||||
, m_orientation(orientation)
|
, m_orientation(orientation)
|
||||||
|
@ -239,7 +244,7 @@ void GScrollBar::mousedown_event(GMouseEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (has_scrubber() && scrubber_rect().contains(event.position())) {
|
if (has_scrubber() && scrubber_rect().contains(event.position())) {
|
||||||
m_scrubber_in_use = true;
|
m_scrubber_in_use = true;
|
||||||
m_scrubbing = true;
|
m_scrubbing = true;
|
||||||
m_scrub_start_value = value();
|
m_scrub_start_value = value();
|
||||||
m_scrub_origin = event.position();
|
m_scrub_origin = event.position();
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
explicit GScrollBar(GWidget* parent);
|
||||||
explicit GScrollBar(Orientation, GWidget* parent);
|
explicit GScrollBar(Orientation, GWidget* parent);
|
||||||
|
|
||||||
virtual void paint_event(GPaintEvent&) override;
|
virtual void paint_event(GPaintEvent&) override;
|
||||||
|
|
|
@ -2,6 +2,11 @@
|
||||||
#include <LibGUI/GPainter.h>
|
#include <LibGUI/GPainter.h>
|
||||||
#include <LibGUI/GSlider.h>
|
#include <LibGUI/GSlider.h>
|
||||||
|
|
||||||
|
GSlider::GSlider(GWidget* parent)
|
||||||
|
: GSlider(Orientation::Horizontal, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GSlider::GSlider(Orientation orientation, GWidget* parent)
|
GSlider::GSlider(Orientation orientation, GWidget* parent)
|
||||||
: GWidget(parent)
|
: GWidget(parent)
|
||||||
, m_orientation(orientation)
|
, m_orientation(orientation)
|
||||||
|
|
|
@ -44,7 +44,8 @@ public:
|
||||||
Function<void(int)> on_value_changed;
|
Function<void(int)> on_value_changed;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GSlider(Orientation, GWidget*);
|
explicit GSlider(GWidget*);
|
||||||
|
explicit GSlider(Orientation, GWidget*);
|
||||||
|
|
||||||
virtual void paint_event(GPaintEvent&) override;
|
virtual void paint_event(GPaintEvent&) override;
|
||||||
virtual void mousedown_event(GMouseEvent&) override;
|
virtual void mousedown_event(GMouseEvent&) override;
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
|
|
||||||
//#define DEBUG_GTEXTEDITOR
|
//#define DEBUG_GTEXTEDITOR
|
||||||
|
|
||||||
|
GTextEditor::GTextEditor(GWidget* parent)
|
||||||
|
: GTextEditor(Type::MultiLine, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
GTextEditor::GTextEditor(Type type, GWidget* parent)
|
GTextEditor::GTextEditor(Type type, GWidget* parent)
|
||||||
: GScrollableWidget(parent)
|
: GScrollableWidget(parent)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
|
|
|
@ -102,7 +102,8 @@ public:
|
||||||
void set_cursor(const GTextPosition&);
|
void set_cursor(const GTextPosition&);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GTextEditor(Type, GWidget* parent);
|
explicit GTextEditor(GWidget* parent);
|
||||||
|
explicit GTextEditor(Type, GWidget* parent);
|
||||||
|
|
||||||
virtual void did_change_font() override;
|
virtual void did_change_font() override;
|
||||||
virtual void paint_event(GPaintEvent&) override;
|
virtual void paint_event(GPaintEvent&) override;
|
||||||
|
|
|
@ -12,6 +12,59 @@
|
||||||
#include <LibGUI/GWindowServerConnection.h>
|
#include <LibGUI/GWindowServerConnection.h>
|
||||||
#include <unistd.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)
|
GWidget::GWidget(GWidget* parent)
|
||||||
: CObject(parent, true)
|
: CObject(parent, true)
|
||||||
, m_font(Font::default_font())
|
, m_font(Font::default_font())
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/Badge.h>
|
#include <AK/Badge.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <LibCore/CElapsedTimer.h>
|
#include <LibCore/CElapsedTimer.h>
|
||||||
#include <LibCore/CObject.h>
|
#include <LibCore/CObject.h>
|
||||||
#include <LibDraw/Color.h>
|
#include <LibDraw/Color.h>
|
||||||
|
@ -12,6 +12,10 @@
|
||||||
#include <LibGUI/GEvent.h>
|
#include <LibGUI/GEvent.h>
|
||||||
#include <LibGUI/GShortcut.h>
|
#include <LibGUI/GShortcut.h>
|
||||||
|
|
||||||
|
#define REGISTER_GWIDGET(class_name) \
|
||||||
|
extern GWidgetClassRegistration registration_##class_name; \
|
||||||
|
GWidgetClassRegistration registration_##class_name(#class_name, [](GWidget* parent) { return class_name::construct(parent); });
|
||||||
|
|
||||||
class GraphicsBitmap;
|
class GraphicsBitmap;
|
||||||
class GAction;
|
class GAction;
|
||||||
class GLayout;
|
class GLayout;
|
||||||
|
@ -42,6 +46,26 @@ enum class VerticalDirection {
|
||||||
Down
|
Down
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class GWidget;
|
||||||
|
|
||||||
|
class GWidgetClassRegistration {
|
||||||
|
AK_MAKE_NONCOPYABLE(GWidgetClassRegistration)
|
||||||
|
AK_MAKE_NONMOVABLE(GWidgetClassRegistration)
|
||||||
|
public:
|
||||||
|
GWidgetClassRegistration(const String& class_name, Function<NonnullRefPtr<GWidget>(GWidget*)> factory);
|
||||||
|
~GWidgetClassRegistration();
|
||||||
|
|
||||||
|
String class_name() const { return m_class_name; }
|
||||||
|
NonnullRefPtr<GWidget> construct(GWidget* parent) const { return m_factory(parent); }
|
||||||
|
|
||||||
|
static void for_each(Function<void(const GWidgetClassRegistration&)>);
|
||||||
|
static const GWidgetClassRegistration* find(const String& class_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
String m_class_name;
|
||||||
|
Function<NonnullRefPtr<GWidget>(GWidget*)> m_factory;
|
||||||
|
};
|
||||||
|
|
||||||
class GWidget : public CObject {
|
class GWidget : public CObject {
|
||||||
C_OBJECT(GWidget)
|
C_OBJECT(GWidget)
|
||||||
public:
|
public:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue