mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +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
	
	 Andreas Kling
						Andreas Kling