diff --git a/Applications/VisualBuilder/Makefile b/Applications/VisualBuilder/Makefile index cea96f817c..cacbff9524 100644 --- a/Applications/VisualBuilder/Makefile +++ b/Applications/VisualBuilder/Makefile @@ -1,8 +1,6 @@ OBJS = \ VBForm.o \ VBWidget.o \ - VBButtonWidget.o \ - VBWidgetFactory.o \ main.o APP = VisualBuilder diff --git a/Applications/VisualBuilder/VBButtonWidget.cpp b/Applications/VisualBuilder/VBButtonWidget.cpp deleted file mode 100644 index d6dccc7731..0000000000 --- a/Applications/VisualBuilder/VBButtonWidget.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include "VBButtonWidget.h" -#include -#include - -VBButtonWidget::VBButtonWidget(VBForm& form) - : VBWidget(form) -{ -} - -VBButtonWidget::~VBButtonWidget() -{ -} - -void VBButtonWidget::paint(GPainter& painter) -{ - StylePainter::paint_button(painter, rect(), ButtonStyle::Normal, false); -} diff --git a/Applications/VisualBuilder/VBButtonWidget.h b/Applications/VisualBuilder/VBButtonWidget.h deleted file mode 100644 index 91a92905df..0000000000 --- a/Applications/VisualBuilder/VBButtonWidget.h +++ /dev/null @@ -1,15 +0,0 @@ -#pragma once - -#include "VBWidget.h" - -class VBButtonWidget : public VBWidget { -public: - static Retained create(VBForm& form) { return adopt(*new VBButtonWidget(form)); } - virtual ~VBButtonWidget() override; - - virtual void paint(GPainter&) override; - virtual const char* gwidget_name() const { return "GButton"; } - -private: - explicit VBButtonWidget(VBForm&); -}; diff --git a/Applications/VisualBuilder/VBForm.cpp b/Applications/VisualBuilder/VBForm.cpp index f07e22f278..a0f6e3946f 100644 --- a/Applications/VisualBuilder/VBForm.cpp +++ b/Applications/VisualBuilder/VBForm.cpp @@ -1,23 +1,24 @@ #include "VBForm.h" #include "VBWidget.h" -#include "VBWidgetFactory.h" #include VBForm::VBForm(const String& name, GWidget* parent) : GWidget(parent) + , m_name(name) { set_fill_with_background_color(true); set_background_color(Color::LightGray); + set_greedy_for_hits(true); - auto box1 = VBWidget::create(*this); - box1->set_rect({ 10, 10, 61, 41 }); + auto box1 = VBWidget::create(WidgetType::GSpinBox, *this); + box1->set_rect({ 10, 10, 61, 21 }); m_widgets.append(move(box1)); - auto box2 = VBWidget::create(*this); + auto box2 = VBWidget::create(WidgetType::GTextEditor, *this); box2->set_rect({ 100, 100, 161, 141 }); m_widgets.append(move(box2)); - auto button1 = VBWidgetFactory::create("GButton", *this); + auto button1 = VBWidget::create(WidgetType::GButton, *this); button1->set_rect({ 200, 50, 101, 21 }); m_widgets.append(move(button1)); } @@ -36,9 +37,14 @@ void VBForm::paint_event(GPaintEvent& event) painter.set_pixel({ x, y }, Color::Black); } } +} + +void VBForm::second_paint_event(GPaintEvent& event) +{ + GPainter painter(*this); + painter.add_clip_rect(event.rect()); for (auto& widget : m_widgets) { - widget->paint(painter); if (widget->is_selected()) { for_each_direction([&] (Direction direction) { painter.fill_rect(widget->grabber_rect(direction), Color::Black); diff --git a/Applications/VisualBuilder/VBForm.h b/Applications/VisualBuilder/VBForm.h index 79026a3ceb..b570425663 100644 --- a/Applications/VisualBuilder/VBForm.h +++ b/Applications/VisualBuilder/VBForm.h @@ -9,6 +9,9 @@ public: explicit VBForm(const String& name, GWidget* parent = nullptr); virtual ~VBForm() override; + String name() const { return m_name; } + void set_name(const String& name) { m_name = name; } + bool is_selected(const VBWidget&) const; VBWidget* widget_at(const Point&); @@ -17,6 +20,7 @@ public: protected: virtual void paint_event(GPaintEvent&) override; + virtual void second_paint_event(GPaintEvent&) override; virtual void mousedown_event(GMouseEvent&) override; virtual void mousemove_event(GMouseEvent&) override; virtual void mouseup_event(GMouseEvent&) override; diff --git a/Applications/VisualBuilder/VBWidget.cpp b/Applications/VisualBuilder/VBWidget.cpp index da54240889..40c1653e8e 100644 --- a/Applications/VisualBuilder/VBWidget.cpp +++ b/Applications/VisualBuilder/VBWidget.cpp @@ -1,16 +1,51 @@ #include "VBWidget.h" #include "VBForm.h" #include +#include +#include +#include +#include -VBWidget::VBWidget(VBForm& form) - : m_form(form) +static GWidget* build_gwidget(WidgetType type, GWidget* parent) { + switch (type) { + case WidgetType::GWidget: + return new GWidget(parent); + case WidgetType::GLabel: + return new GLabel(parent); + case WidgetType::GButton: + return new GButton(parent); + case WidgetType::GSpinBox: + return new GSpinBox(parent); + case WidgetType::GTextEditor: + return new GTextEditor(GTextEditor::Type::MultiLine, parent); + default: + ASSERT_NOT_REACHED(); + return nullptr; + } +} + +VBWidget::VBWidget(WidgetType type, VBForm& form) + : m_type(type) + , m_form(form) +{ + m_gwidget = build_gwidget(type, &form); } VBWidget::~VBWidget() { } +Rect VBWidget::rect() const +{ + return m_gwidget->relative_rect(); +} + +void VBWidget::set_rect(const Rect& rect) +{ + m_gwidget->set_relative_rect(rect); +} + bool VBWidget::is_selected() const { return m_form.is_selected(*this); @@ -22,21 +57,21 @@ Rect VBWidget::grabber_rect(Direction direction) const int half_grabber_size = grabber_size / 2; switch (direction) { case Direction::Left: - return { m_rect.x() - half_grabber_size, m_rect.center().y() - half_grabber_size, grabber_size, grabber_size }; + return { rect().x() - half_grabber_size, rect().center().y() - half_grabber_size, grabber_size, grabber_size }; case Direction::UpLeft: - return { m_rect.x() - half_grabber_size, m_rect.y() - half_grabber_size, grabber_size, grabber_size }; + return { rect().x() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size }; case Direction::Up: - return { m_rect.center().x() - half_grabber_size, m_rect.y() - half_grabber_size, grabber_size, grabber_size }; + return { rect().center().x() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size }; case Direction::UpRight: - return { m_rect.right() - half_grabber_size, m_rect.y() - half_grabber_size, grabber_size, grabber_size }; + return { rect().right() - half_grabber_size, rect().y() - half_grabber_size, grabber_size, grabber_size }; case Direction::Right: - return { m_rect.right() - half_grabber_size, m_rect.center().y() - half_grabber_size, grabber_size, grabber_size }; + return { rect().right() - half_grabber_size, rect().center().y() - half_grabber_size, grabber_size, grabber_size }; case Direction::DownLeft: - return { m_rect.x() - half_grabber_size, m_rect.bottom() - half_grabber_size, grabber_size, grabber_size }; + return { rect().x() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size }; case Direction::Down: - return { m_rect.center().x() - half_grabber_size, m_rect.bottom() - half_grabber_size, grabber_size, grabber_size }; + return { rect().center().x() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size }; case Direction::DownRight: - return { m_rect.right() - half_grabber_size, m_rect.bottom() - half_grabber_size, grabber_size, grabber_size }; + return { rect().right() - half_grabber_size, rect().bottom() - half_grabber_size, grabber_size, grabber_size }; default: ASSERT_NOT_REACHED(); } @@ -51,9 +86,3 @@ Direction VBWidget::grabber_at(const Point& position) const }); return found_grabber; } - -void VBWidget::paint(GPainter& painter) -{ - painter.fill_rect(m_rect, Color::White); - painter.draw_rect(m_rect, Color::Black); -} diff --git a/Applications/VisualBuilder/VBWidget.h b/Applications/VisualBuilder/VBWidget.h index 521ee87cd3..0e13c1f8c4 100644 --- a/Applications/VisualBuilder/VBWidget.h +++ b/Applications/VisualBuilder/VBWidget.h @@ -6,6 +6,7 @@ #include class GPainter; +class GWidget; class VBForm; enum class Direction { None, Left, UpLeft, Up, UpRight, Right, DownRight, Down, DownLeft }; @@ -22,27 +23,35 @@ inline void for_each_direction(Callback callback) callback(Direction::DownLeft); } +enum class WidgetType { + None, + GWidget, + GButton, + GLabel, + GSpinBox, + GTextEditor, +}; + class VBWidget : public Retainable, public Weakable { public: - static Retained create(VBForm& form) { return adopt(*new VBWidget(form)); } - virtual ~VBWidget(); + static Retained create(WidgetType type, VBForm& form) { return adopt(*new VBWidget(type, form)); } + ~VBWidget(); bool is_selected() const; - Rect rect() const { return m_rect; } - void set_rect(const Rect& rect) { m_rect = rect; } + Rect rect() const; + void set_rect(const Rect&); Rect grabber_rect(Direction) const; Direction grabber_at(const Point&) const; - virtual void paint(GPainter&); - - virtual const char* gwidget_name() const { return "GWidget"; } + GWidget* gwidget() { return m_gwidget; } protected: - explicit VBWidget(VBForm&); + VBWidget(WidgetType, VBForm&); private: + WidgetType m_type { WidgetType::None }; VBForm& m_form; - Rect m_rect; + GWidget* m_gwidget { nullptr }; }; diff --git a/Applications/VisualBuilder/VBWidgetFactory.cpp b/Applications/VisualBuilder/VBWidgetFactory.cpp deleted file mode 100644 index 83f2afa02f..0000000000 --- a/Applications/VisualBuilder/VBWidgetFactory.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "VBWidgetFactory.h" -#include "VBButtonWidget.h" - -Retained VBWidgetFactory::create(const String& widget_name, VBForm& form) -{ - if (widget_name == "GButton") - return VBButtonWidget::create(form); - return VBWidget::create(form); -} diff --git a/Applications/VisualBuilder/VBWidgetFactory.h b/Applications/VisualBuilder/VBWidgetFactory.h deleted file mode 100644 index 486887fd3c..0000000000 --- a/Applications/VisualBuilder/VBWidgetFactory.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -#include -#include - -class VBForm; -class VBWidget; - -class VBWidgetFactory { -public: - static Retained create(const String& widget_name, VBForm&); -}; diff --git a/Applications/VisualBuilder/main.cpp b/Applications/VisualBuilder/main.cpp index 0602b39ea6..f575b942c4 100644 --- a/Applications/VisualBuilder/main.cpp +++ b/Applications/VisualBuilder/main.cpp @@ -46,7 +46,7 @@ int main(int argc, char** argv) app.set_menubar(move(menubar)); auto* window = new GWindow; - window->set_title("Form1"); + window->set_title(form1->name()); window->set_rect(20, 200, 640, 400); window->set_main_widget(form1); window->set_should_exit_event_loop_on_close(true); diff --git a/LibGUI/GWidget.cpp b/LibGUI/GWidget.cpp index c52ca48acf..c1d2d272d4 100644 --- a/LibGUI/GWidget.cpp +++ b/LibGUI/GWidget.cpp @@ -115,6 +115,7 @@ void GWidget::handle_paint_event(GPaintEvent& event) child->event(local_event); } } + second_paint_event(event); } void GWidget::set_layout(OwnPtr&& layout) @@ -207,6 +208,10 @@ void GWidget::paint_event(GPaintEvent&) { } +void GWidget::second_paint_event(GPaintEvent&) +{ +} + void GWidget::show_event(GShowEvent&) { } @@ -282,6 +287,8 @@ Rect GWidget::screen_relative_rect() const GWidget::HitTestResult GWidget::hit_test(int x, int y) { + if (is_greedy_for_hits()) + return { this, x, y }; for (int i = children().size() - 1; i >= 0; --i) { if (!children()[i]->is_widget()) continue; diff --git a/LibGUI/GWidget.h b/LibGUI/GWidget.h index 0d322e4ab0..45e12535d2 100644 --- a/LibGUI/GWidget.h +++ b/LibGUI/GWidget.h @@ -56,6 +56,9 @@ public: virtual void leave_event(CEvent&); virtual void child_event(CChildEvent&) override; + // This is called after children have been painted. + virtual void second_paint_event(GPaintEvent&); + Rect relative_rect() const { return m_relative_rect; } Point relative_position() const { return m_relative_rect.location(); } @@ -147,6 +150,9 @@ public: bool spans_entire_window_horizontally() const; + bool is_greedy_for_hits() const { return m_greedy_for_hits; } + void set_greedy_for_hits(bool b) { m_greedy_for_hits = b; } + private: virtual bool is_widget() const final { return true; } @@ -173,6 +179,7 @@ private: bool m_fill_with_background_color { false }; bool m_visible { true }; + bool m_greedy_for_hits { false }; CElapsedTimer m_click_clock; };