diff --git a/Applications/PaintBrush/Makefile b/Applications/PaintBrush/Makefile index 09dce440a1..0953e04f50 100644 --- a/Applications/PaintBrush/Makefile +++ b/Applications/PaintBrush/Makefile @@ -5,6 +5,7 @@ OBJS = \ Tool.o \ PenTool.o \ LineTool.o \ + RectangleTool.o \ EraseTool.o \ BucketTool.o \ ColorDialog.o \ diff --git a/Applications/PaintBrush/RectangleTool.cpp b/Applications/PaintBrush/RectangleTool.cpp new file mode 100644 index 0000000000..4f84a686f3 --- /dev/null +++ b/Applications/PaintBrush/RectangleTool.cpp @@ -0,0 +1,105 @@ +#include "RectangleTool.h" +#include "PaintableWidget.h" +#include +#include +#include +#include +#include + +RectangleTool::RectangleTool() +{ +} + +RectangleTool::~RectangleTool() +{ +} + +void RectangleTool::draw_using(Painter& painter) +{ + auto rect_to_draw = Rect::from_two_points(m_rectangle_start_position, m_rectangle_end_position); + switch (m_mode) { + case Mode::Fill: + painter.fill_rect(rect_to_draw, m_widget->color_for(m_drawing_button)); + break; + case Mode::Outline: + painter.draw_rect(rect_to_draw, m_widget->color_for(m_drawing_button)); + break; + case Mode::Gradient: + painter.fill_rect_with_gradient(rect_to_draw, m_widget->primary_color(), m_widget->secondary_color()); + break; + default: + ASSERT_NOT_REACHED(); + } +} + +void RectangleTool::on_mousedown(GMouseEvent& event) +{ + if (event.button() != GMouseButton::Left && event.button() != GMouseButton::Right) + return; + + if (m_drawing_button != GMouseButton::None) + return; + + m_drawing_button = event.button(); + m_rectangle_start_position = event.position(); + m_rectangle_end_position = event.position(); + m_widget->update(); +} + +void RectangleTool::on_mouseup(GMouseEvent& event) +{ + if (event.button() == m_drawing_button) { + GPainter painter(m_widget->bitmap()); + draw_using(painter); + m_drawing_button = GMouseButton::None; + m_widget->update(); + } +} + +void RectangleTool::on_mousemove(GMouseEvent& event) +{ + if (m_drawing_button == GMouseButton::None) + return; + + if (!m_widget->rect().contains(event.position())) + return; + + m_rectangle_end_position = event.position(); + m_widget->update(); +} + +void RectangleTool::on_second_paint(GPaintEvent& event) +{ + if (m_drawing_button == GMouseButton::None) + return; + + GPainter painter(*m_widget); + painter.add_clip_rect(event.rect()); + draw_using(painter); +} + +void RectangleTool::on_keydown(GKeyEvent& event) +{ + if (event.key() == Key_Escape && m_drawing_button != GMouseButton::None) { + m_drawing_button = GMouseButton::None; + m_widget->update(); + event.accept(); + } +} + +void RectangleTool::on_contextmenu(GContextMenuEvent& event) +{ + if (!m_context_menu) { + m_context_menu = GMenu::construct(); + m_context_menu->add_action(GAction::create("Fill", [this](auto&) { + m_mode = Mode::Fill; + })); + m_context_menu->add_action(GAction::create("Outline", [this](auto&) { + m_mode = Mode::Outline; + })); + m_context_menu->add_action(GAction::create("Gradient", [this](auto&) { + m_mode = Mode::Gradient; + })); + } + m_context_menu->popup(event.screen_position()); +} diff --git a/Applications/PaintBrush/RectangleTool.h b/Applications/PaintBrush/RectangleTool.h new file mode 100644 index 0000000000..36f2616855 --- /dev/null +++ b/Applications/PaintBrush/RectangleTool.h @@ -0,0 +1,36 @@ +#pragma once + +#include "Tool.h" +#include + +class GMenu; +class Painter; + +class RectangleTool final : public Tool { +public: + RectangleTool(); + virtual ~RectangleTool() override; + + virtual void on_mousedown(GMouseEvent&) override; + virtual void on_mousemove(GMouseEvent&) override; + virtual void on_mouseup(GMouseEvent&) override; + virtual void on_contextmenu(GContextMenuEvent&) override; + virtual void on_second_paint(GPaintEvent&) override; + virtual void on_keydown(GKeyEvent&) override; + +private: + enum class Mode { + Outline, + Fill, + Gradient, + }; + + virtual const char* class_name() const override { return "RectangleTool"; } + void draw_using(Painter& painter); + + GMouseButton m_drawing_button { GMouseButton::None }; + Point m_rectangle_start_position; + Point m_rectangle_end_position; + RefPtr m_context_menu; + Mode m_mode { Mode::Outline }; +}; diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp index 44be7121ba..a46a302838 100644 --- a/Applications/PaintBrush/ToolboxWidget.cpp +++ b/Applications/PaintBrush/ToolboxWidget.cpp @@ -5,6 +5,7 @@ #include "PaintableWidget.h" #include "PenTool.h" #include "PickerTool.h" +#include "RectangleTool.h" #include "SprayTool.h" #include #include @@ -70,6 +71,7 @@ ToolboxWidget::ToolboxWidget(GWidget* parent) add_tool("Color Picker", "picker", make()); add_tool("Erase", "eraser", make()); add_tool("Line", "line", make()); + add_tool("Rectangle", "rectangle", make()); } ToolboxWidget::~ToolboxWidget() diff --git a/Base/res/icons/paintbrush/rectangle.png b/Base/res/icons/paintbrush/rectangle.png new file mode 100644 index 0000000000..39d099c3c7 Binary files /dev/null and b/Base/res/icons/paintbrush/rectangle.png differ diff --git a/Libraries/LibDraw/Painter.h b/Libraries/LibDraw/Painter.h index 1e64557bf6..575f69373f 100644 --- a/Libraries/LibDraw/Painter.h +++ b/Libraries/LibDraw/Painter.h @@ -5,9 +5,9 @@ #include "Rect.h" #include "Size.h" #include +#include #include #include -#include class CharacterBitmap; class GlyphBitmap;