diff --git a/Applications/PaintBrush/BucketTool.cpp b/Applications/PaintBrush/BucketTool.cpp new file mode 100644 index 0000000000..b19cf02c6b --- /dev/null +++ b/Applications/PaintBrush/BucketTool.cpp @@ -0,0 +1,15 @@ +#include "BucketTool.h" +#include + +BucketTool::BucketTool() +{ +} + +BucketTool::~BucketTool() +{ +} + +void BucketTool::on_mousedown(PaintableWidget&, GMouseEvent&) +{ + dbgprintf("FIXME: Implement BucketTool::on_mousedown\n"); +} diff --git a/Applications/PaintBrush/BucketTool.h b/Applications/PaintBrush/BucketTool.h new file mode 100644 index 0000000000..0c72c9e7f1 --- /dev/null +++ b/Applications/PaintBrush/BucketTool.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Tool.h" + +class BucketTool final : public Tool { +public: + BucketTool(); + virtual ~BucketTool() override; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) override; + +private: + virtual const char* class_name() const override { return "BucketTool"; } +}; diff --git a/Applications/PaintBrush/Makefile b/Applications/PaintBrush/Makefile index 260d0c6081..2146f55ab7 100644 --- a/Applications/PaintBrush/Makefile +++ b/Applications/PaintBrush/Makefile @@ -4,6 +4,9 @@ OBJS = \ PaintableWidget.o \ PaletteWidget.o \ ToolboxWidget.o \ + Tool.o \ + PenTool.o \ + BucketTool.o \ main.o APP = PaintBrush diff --git a/Applications/PaintBrush/PaintableWidget.cpp b/Applications/PaintBrush/PaintableWidget.cpp index 80d21fd707..02ddc2da01 100644 --- a/Applications/PaintBrush/PaintableWidget.cpp +++ b/Applications/PaintBrush/PaintableWidget.cpp @@ -1,10 +1,20 @@ #include "PaintableWidget.h" +#include "Tool.h" #include #include +static PaintableWidget* s_the; + +PaintableWidget& PaintableWidget::the() +{ + return *s_the; +} + PaintableWidget::PaintableWidget(GWidget* parent) : GWidget(parent) { + ASSERT(!s_the); + s_the = this; set_fill_with_background_color(true); set_background_color(Color::MidGray); m_bitmap = GraphicsBitmap::create(GraphicsBitmap::Format::RGB32, { 600, 400 }); @@ -33,37 +43,18 @@ Color PaintableWidget::color_for(const GMouseEvent& event) void PaintableWidget::mousedown_event(GMouseEvent& event) { - if (event.button() != GMouseButton::Left && event.button() != GMouseButton::Right) - return; - - GPainter painter(*m_bitmap); - painter.set_pixel(event.position(), color_for(event)); - update({ event.position(), { 1, 1 } }); - m_last_drawing_event_position = event.position(); + if (m_tool) + m_tool->on_mousedown(*this, event); } void PaintableWidget::mouseup_event(GMouseEvent& event) { - if (event.button() == GMouseButton::Left || event.button() == GMouseButton::Right) - m_last_drawing_event_position = { -1, -1 }; + if (m_tool) + m_tool->on_mouseup(*this, event); } void PaintableWidget::mousemove_event(GMouseEvent& event) { - if (!rect().contains(event.position())) - return; - - if (event.buttons() & GMouseButton::Left || event.buttons() & GMouseButton::Right) { - GPainter painter(*m_bitmap); - - if (m_last_drawing_event_position != Point(-1, -1)) { - painter.draw_line(m_last_drawing_event_position, event.position(), color_for(event)); - update(); - } else { - painter.set_pixel(event.position(), color_for(event)); - update({ event.position(), { 1, 1 } }); - } - - m_last_drawing_event_position = event.position(); - } + if (m_tool) + m_tool->on_mousemove(*this, event); } diff --git a/Applications/PaintBrush/PaintableWidget.h b/Applications/PaintBrush/PaintableWidget.h index c572500f2b..7734b60c24 100644 --- a/Applications/PaintBrush/PaintableWidget.h +++ b/Applications/PaintBrush/PaintableWidget.h @@ -2,8 +2,12 @@ #include +class Tool; + class PaintableWidget final : public GWidget { public: + static PaintableWidget& the(); + explicit PaintableWidget(GWidget* parent); virtual ~PaintableWidget() override; @@ -15,17 +19,24 @@ public: void set_primary_color(Color color) { m_primary_color = color; } void set_secondary_color(Color color) { m_secondary_color = color; } + void set_tool(Tool* tool) { m_tool = tool; } + Tool* tool() { return m_tool; } + + Color color_for(const GMouseEvent&); + + GraphicsBitmap& bitmap() { return *m_bitmap; } + const GraphicsBitmap& bitmap() const { return *m_bitmap; } + private: virtual void paint_event(GPaintEvent&) override; virtual void mousedown_event(GMouseEvent&) override; virtual void mouseup_event(GMouseEvent&) override; virtual void mousemove_event(GMouseEvent&) override; - Color color_for(const GMouseEvent&); - - Point m_last_drawing_event_position { -1, -1 }; RetainPtr m_bitmap; Color m_primary_color { Color::Black }; Color m_secondary_color { Color::White }; + + Tool* m_tool { nullptr }; }; diff --git a/Applications/PaintBrush/PenTool.cpp b/Applications/PaintBrush/PenTool.cpp new file mode 100644 index 0000000000..185ef430b5 --- /dev/null +++ b/Applications/PaintBrush/PenTool.cpp @@ -0,0 +1,48 @@ +#include "PenTool.h" +#include "PaintableWidget.h" +#include + +PenTool::PenTool() +{ +} + +PenTool::~PenTool() +{ +} + +void PenTool::on_mousedown(PaintableWidget& paintable_widget, GMouseEvent& event) +{ + if (event.button() != GMouseButton::Left && event.button() != GMouseButton::Right) + return; + + GPainter painter(paintable_widget.bitmap()); + painter.set_pixel(event.position(), paintable_widget.color_for(event)); + paintable_widget.update({ event.position(), { 1, 1 } }); + m_last_drawing_event_position = event.position(); +} + +void PenTool::on_mouseup(PaintableWidget&, GMouseEvent& event) +{ + if (event.button() == GMouseButton::Left || event.button() == GMouseButton::Right) + m_last_drawing_event_position = { -1, -1 }; +} + +void PenTool::on_mousemove(PaintableWidget& paintable_widget, GMouseEvent& event) +{ + if (!paintable_widget.rect().contains(event.position())) + return; + + if (event.buttons() & GMouseButton::Left || event.buttons() & GMouseButton::Right) { + GPainter painter(paintable_widget.bitmap()); + + if (m_last_drawing_event_position != Point(-1, -1)) { + painter.draw_line(m_last_drawing_event_position, event.position(), paintable_widget.color_for(event)); + paintable_widget.update(); + } else { + painter.set_pixel(event.position(), paintable_widget.color_for(event)); + paintable_widget.update({ event.position(), { 1, 1 } }); + } + + m_last_drawing_event_position = event.position(); + } +} diff --git a/Applications/PaintBrush/PenTool.h b/Applications/PaintBrush/PenTool.h new file mode 100644 index 0000000000..82c1ff2c07 --- /dev/null +++ b/Applications/PaintBrush/PenTool.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Tool.h" +#include + +class PenTool final : public Tool { +public: + PenTool(); + virtual ~PenTool() override; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) override; + virtual void on_mousemove(PaintableWidget&, GMouseEvent&) override; + virtual void on_mouseup(PaintableWidget&, GMouseEvent&) override; + +private: + virtual const char* class_name() const override { return "PenTool"; } + + Point m_last_drawing_event_position { -1, -1 }; +}; diff --git a/Applications/PaintBrush/Tool.cpp b/Applications/PaintBrush/Tool.cpp new file mode 100644 index 0000000000..52e711c48a --- /dev/null +++ b/Applications/PaintBrush/Tool.cpp @@ -0,0 +1,9 @@ +#include "Tool.h" + +Tool::Tool() +{ +} + +Tool::~Tool() +{ +} diff --git a/Applications/PaintBrush/Tool.h b/Applications/PaintBrush/Tool.h new file mode 100644 index 0000000000..c564cfb6a2 --- /dev/null +++ b/Applications/PaintBrush/Tool.h @@ -0,0 +1,18 @@ +#pragma once + +class GMouseEvent; +class PaintableWidget; + +class Tool { +public: + virtual ~Tool(); + + virtual const char* class_name() const = 0; + + virtual void on_mousedown(PaintableWidget&, GMouseEvent&) { } + virtual void on_mousemove(PaintableWidget&, GMouseEvent&) { } + virtual void on_mouseup(PaintableWidget&, GMouseEvent&) { } + +protected: + Tool(); +}; diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp index 8b8ef1410e..aabc1e64cb 100644 --- a/Applications/PaintBrush/ToolboxWidget.cpp +++ b/Applications/PaintBrush/ToolboxWidget.cpp @@ -1,7 +1,25 @@ #include "ToolboxWidget.h" +#include "BucketTool.h" +#include "PaintableWidget.h" +#include "PenTool.h" #include #include +class ToolButton final : public GButton { +public: + ToolButton(const String& name, GWidget* parent, OwnPtr&& tool) + : GButton(name, parent) + , m_tool(move(tool)) + { + } + + const Tool& tool() const { return *m_tool; } + Tool& tool() { return *m_tool; } + +private: + OwnPtr m_tool; +}; + ToolboxWidget::ToolboxWidget(GWidget* parent) : GFrame(parent) { @@ -18,17 +36,23 @@ ToolboxWidget::ToolboxWidget(GWidget* parent) set_layout(make(Orientation::Vertical)); layout()->set_margins({ 4, 4, 4, 4 }); - auto add_tool = [&] (const StringView& name) { - auto* button = new GButton(name, this); + auto add_tool = [&](const StringView& name, OwnPtr&& tool) { + auto* button = new ToolButton(name, this, move(tool)); button->set_size_policy(SizePolicy::Fill, SizePolicy::Fixed); button->set_preferred_size({ 0, 32 }); button->set_checkable(true); button->set_exclusive(true); + + button->on_checked = [button](auto checked) { + if (checked) + PaintableWidget::the().set_tool(&button->tool()); + else + PaintableWidget::the().set_tool(nullptr); + }; }; - add_tool("Pen"); - add_tool("Buck"); - add_tool("Pick"); + add_tool("Pen", make()); + add_tool("Buck", make()); } ToolboxWidget::~ToolboxWidget()