summaryrefslogtreecommitdiff
path: root/Applications
diff options
context:
space:
mode:
authorShannon Booth <shannon.ml.booth@gmail.com>2019-12-27 11:24:13 +1300
committerAndreas Kling <awesomekling@gmail.com>2019-12-27 00:52:17 +0100
commitc85bdff57a1f6d3c47c804dda46e22bd14e93888 (patch)
tree7620e289a004becc4d12c8995450f97c93339555 /Applications
parent123b5c9d34b8b47cd9912a03404863b4a2f7c4ed (diff)
downloadserenity-c85bdff57a1f6d3c47c804dda46e22bd14e93888.zip
PaintBrush: Add an "ellipse tool"
The tool currently supports drawing an elliptical line of a specified thickness. Further improvements can include adding a fill mode, and holding down shift to draw a perfect circle. Closes #375.
Diffstat (limited to 'Applications')
-rw-r--r--Applications/PaintBrush/EllipseTool.cpp106
-rw-r--r--Applications/PaintBrush/EllipseTool.h36
-rw-r--r--Applications/PaintBrush/Makefile1
-rw-r--r--Applications/PaintBrush/ToolboxWidget.cpp2
4 files changed, 145 insertions, 0 deletions
diff --git a/Applications/PaintBrush/EllipseTool.cpp b/Applications/PaintBrush/EllipseTool.cpp
new file mode 100644
index 0000000000..9e87812f5e
--- /dev/null
+++ b/Applications/PaintBrush/EllipseTool.cpp
@@ -0,0 +1,106 @@
+#include "EllipseTool.h"
+#include "PaintableWidget.h"
+#include <LibDraw/Rect.h>
+#include <LibGUI/GAction.h>
+#include <LibGUI/GMenu.h>
+#include <LibGUI/GPainter.h>
+#include <LibM/math.h>
+
+EllipseTool::EllipseTool()
+{
+}
+
+EllipseTool::~EllipseTool()
+{
+}
+
+void EllipseTool::draw_using(Painter& painter)
+{
+ auto ellipse_intersecting_rect = Rect::from_two_points(m_ellipse_start_position, m_ellipse_end_position);
+ switch (m_mode) {
+ case Mode::Outline:
+ painter.draw_ellipse_intersecting(ellipse_intersecting_rect, m_widget->color_for(m_drawing_button), m_thickness);
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void EllipseTool::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_ellipse_start_position = event.position();
+ m_ellipse_end_position = event.position();
+ m_widget->update();
+}
+
+void EllipseTool::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 EllipseTool::on_mousemove(GMouseEvent& event)
+{
+ if (m_drawing_button == GMouseButton::None)
+ return;
+
+ if (!m_widget->rect().contains(event.position()))
+ return;
+
+ m_ellipse_end_position = event.position();
+ m_widget->update();
+}
+
+void EllipseTool::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 EllipseTool::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 EllipseTool::on_contextmenu(GContextMenuEvent& event)
+{
+ if (!m_context_menu) {
+ m_context_menu = GMenu::construct();
+ m_context_menu->add_action(GAction::create("Outline", [this](auto&) {
+ m_mode = Mode::Outline;
+ }));
+ m_context_menu->add_separator();
+ m_context_menu->add_action(GAction::create("1", [this](auto&) {
+ m_thickness = 1;
+ }));
+ m_context_menu->add_action(GAction::create("2", [this](auto&) {
+ m_thickness = 2;
+ }));
+ m_context_menu->add_action(GAction::create("3", [this](auto&) {
+ m_thickness = 3;
+ }));
+ m_context_menu->add_action(GAction::create("4", [this](auto&) {
+ m_thickness = 4;
+ }));
+ }
+ m_context_menu->popup(event.screen_position());
+}
diff --git a/Applications/PaintBrush/EllipseTool.h b/Applications/PaintBrush/EllipseTool.h
new file mode 100644
index 0000000000..bc2f59782b
--- /dev/null
+++ b/Applications/PaintBrush/EllipseTool.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "Tool.h"
+#include <LibDraw/Point.h>
+
+class GMenu;
+class Painter;
+
+class EllipseTool final : public Tool {
+public:
+ EllipseTool();
+ virtual ~EllipseTool() 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,
+ // FIXME: Add Mode::Fill
+ };
+
+ virtual const char* class_name() const override { return "EllipseTool"; }
+ void draw_using(Painter& painter);
+
+ GMouseButton m_drawing_button { GMouseButton::None };
+ Point m_ellipse_start_position;
+ Point m_ellipse_end_position;
+ RefPtr<GMenu> m_context_menu;
+ int m_thickness { 1 };
+ Mode m_mode { Mode::Outline };
+};
diff --git a/Applications/PaintBrush/Makefile b/Applications/PaintBrush/Makefile
index 0953e04f50..29534b135f 100644
--- a/Applications/PaintBrush/Makefile
+++ b/Applications/PaintBrush/Makefile
@@ -6,6 +6,7 @@ OBJS = \
PenTool.o \
LineTool.o \
RectangleTool.o \
+ EllipseTool.o \
EraseTool.o \
BucketTool.o \
ColorDialog.o \
diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp
index a46a302838..9627a88b13 100644
--- a/Applications/PaintBrush/ToolboxWidget.cpp
+++ b/Applications/PaintBrush/ToolboxWidget.cpp
@@ -1,5 +1,6 @@
#include "ToolboxWidget.h"
#include "BucketTool.h"
+#include "EllipseTool.h"
#include "EraseTool.h"
#include "LineTool.h"
#include "PaintableWidget.h"
@@ -72,6 +73,7 @@ ToolboxWidget::ToolboxWidget(GWidget* parent)
add_tool("Erase", "eraser", make<EraseTool>());
add_tool("Line", "line", make<LineTool>());
add_tool("Rectangle", "rectangle", make<RectangleTool>());
+ add_tool("Ellipse", "circle", make<EllipseTool>());
}
ToolboxWidget::~ToolboxWidget()