summaryrefslogtreecommitdiff
path: root/Applications
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-05-12 23:44:46 +0200
committerAndreas Kling <kling@serenityos.org>2020-05-12 23:44:46 +0200
commit83d24dcb1d4d921c4d1c9f85ca97808b2a463b32 (patch)
tree6b2d88a0584d6dc4cccf718f3751f892a203f394 /Applications
parent7dd8f1b921c5c63c21415a6ded179134a18e1ae2 (diff)
downloadserenity-83d24dcb1d4d921c4d1c9f85ca97808b2a463b32.zip
PaintBrush: Port all the existing toolbox tools to the Layer world :^)
Many tools are not working perfectly right yet, but we'll fix them!
Diffstat (limited to 'Applications')
-rw-r--r--Applications/PaintBrush/BucketTool.cpp22
-rw-r--r--Applications/PaintBrush/BucketTool.h6
-rw-r--r--Applications/PaintBrush/EllipseTool.cpp28
-rw-r--r--Applications/PaintBrush/EllipseTool.h10
-rw-r--r--Applications/PaintBrush/EraseTool.cpp26
-rw-r--r--Applications/PaintBrush/EraseTool.h11
-rw-r--r--Applications/PaintBrush/ImageEditor.cpp52
-rw-r--r--Applications/PaintBrush/ImageEditor.h9
-rw-r--r--Applications/PaintBrush/LineTool.cpp36
-rw-r--r--Applications/PaintBrush/LineTool.h12
-rw-r--r--Applications/PaintBrush/PaintableWidget.cpp69
-rw-r--r--Applications/PaintBrush/PaintableWidget.h15
-rw-r--r--Applications/PaintBrush/PenTool.cpp28
-rw-r--r--Applications/PaintBrush/PenTool.h10
-rw-r--r--Applications/PaintBrush/PickerTool.cpp17
-rw-r--r--Applications/PaintBrush/PickerTool.h6
-rw-r--r--Applications/PaintBrush/RectangleTool.cpp35
-rw-r--r--Applications/PaintBrush/RectangleTool.h11
-rw-r--r--Applications/PaintBrush/SprayTool.cpp29
-rw-r--r--Applications/PaintBrush/SprayTool.h10
-rw-r--r--Applications/PaintBrush/Tool.cpp10
-rw-r--r--Applications/PaintBrush/Tool.h21
-rw-r--r--Applications/PaintBrush/ToolboxWidget.cpp10
-rw-r--r--Applications/PaintBrush/ToolboxWidget.h12
-rw-r--r--Applications/PaintBrush/main.cpp6
25 files changed, 302 insertions, 199 deletions
diff --git a/Applications/PaintBrush/BucketTool.cpp b/Applications/PaintBrush/BucketTool.cpp
index af5d4c410e..7c5bde56ec 100644
--- a/Applications/PaintBrush/BucketTool.cpp
+++ b/Applications/PaintBrush/BucketTool.cpp
@@ -25,12 +25,16 @@
*/
#include "BucketTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <AK/Queue.h>
#include <AK/SinglyLinkedList.h>
#include <LibGUI/Painter.h>
#include <LibGfx/Bitmap.h>
-#include <stdio.h>
+#include <LibGfx/Rect.h>
+
+namespace PaintBrush {
BucketTool::BucketTool()
{
@@ -57,7 +61,7 @@ static void flood_fill(Gfx::Bitmap& bitmap, const Gfx::Point& start_position, Co
if (bitmap.get_pixel<Gfx::BitmapFormat::RGBA32>(position.x(), position.y()) != target_color)
continue;
-
+
bitmap.set_pixel<Gfx::BitmapFormat::RGBA32>(position.x(), position.y(), fill_color);
if (position.x() != 0)
@@ -74,15 +78,17 @@ static void flood_fill(Gfx::Bitmap& bitmap, const Gfx::Point& start_position, Co
}
}
-void BucketTool::on_mousedown(GUI::MouseEvent& event)
+void BucketTool::on_mousedown(Layer& layer, GUI::MouseEvent& event)
{
- if (!m_widget->rect().contains(event.position()))
+ if (!layer.rect().contains(event.position()))
return;
- GUI::Painter painter(m_widget->bitmap());
- auto target_color = m_widget->bitmap().get_pixel(event.x(), event.y());
+ GUI::Painter painter(layer.bitmap());
+ auto target_color = layer.bitmap().get_pixel(event.x(), event.y());
- flood_fill(m_widget->bitmap(), event.position(), target_color, m_widget->color_for(event));
+ flood_fill(layer.bitmap(), event.position(), target_color, PaintableWidget::the().color_for(event));
+
+ m_editor->update();
+}
- m_widget->update();
}
diff --git a/Applications/PaintBrush/BucketTool.h b/Applications/PaintBrush/BucketTool.h
index fb52e9624e..8749025d1e 100644
--- a/Applications/PaintBrush/BucketTool.h
+++ b/Applications/PaintBrush/BucketTool.h
@@ -28,13 +28,17 @@
#include "Tool.h"
+namespace PaintBrush {
+
class BucketTool final : public Tool {
public:
BucketTool();
virtual ~BucketTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
private:
virtual const char* class_name() const override { return "BucketTool"; }
};
+
+}
diff --git a/Applications/PaintBrush/EllipseTool.cpp b/Applications/PaintBrush/EllipseTool.cpp
index b0f5f80b5a..661005bf2f 100644
--- a/Applications/PaintBrush/EllipseTool.cpp
+++ b/Applications/PaintBrush/EllipseTool.cpp
@@ -25,6 +25,8 @@
*/
#include "EllipseTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
@@ -32,6 +34,8 @@
#include <LibGfx/Rect.h>
#include <LibM/math.h>
+namespace PaintBrush {
+
EllipseTool::EllipseTool()
{
}
@@ -45,14 +49,14 @@ void EllipseTool::draw_using(GUI::Painter& painter)
auto ellipse_intersecting_rect = Gfx::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);
+ painter.draw_ellipse_intersecting(ellipse_intersecting_rect, PaintableWidget::the().color_for(m_drawing_button), m_thickness);
break;
default:
ASSERT_NOT_REACHED();
}
}
-void EllipseTool::on_mousedown(GUI::MouseEvent& event)
+void EllipseTool::on_mousedown(Layer&, GUI::MouseEvent& event)
{
if (event.button() != GUI::MouseButton::Left && event.button() != GUI::MouseButton::Right)
return;
@@ -63,29 +67,29 @@ void EllipseTool::on_mousedown(GUI::MouseEvent& event)
m_drawing_button = event.button();
m_ellipse_start_position = event.position();
m_ellipse_end_position = event.position();
- m_widget->update();
+ m_editor->update();
}
-void EllipseTool::on_mouseup(GUI::MouseEvent& event)
+void EllipseTool::on_mouseup(Layer& layer, GUI::MouseEvent& event)
{
if (event.button() == m_drawing_button) {
- GUI::Painter painter(m_widget->bitmap());
+ GUI::Painter painter(layer.bitmap());
draw_using(painter);
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
}
}
-void EllipseTool::on_mousemove(GUI::MouseEvent& event)
+void EllipseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event)
{
if (m_drawing_button == GUI::MouseButton::None)
return;
- if (!m_widget->rect().contains(event.position()))
+ if (!layer.rect().contains(event.position()))
return;
m_ellipse_end_position = event.position();
- m_widget->update();
+ m_editor->update();
}
void EllipseTool::on_second_paint(GUI::PaintEvent& event)
@@ -93,7 +97,7 @@ void EllipseTool::on_second_paint(GUI::PaintEvent& event)
if (m_drawing_button == GUI::MouseButton::None)
return;
- GUI::Painter painter(*m_widget);
+ GUI::Painter painter(*m_editor);
painter.add_clip_rect(event.rect());
draw_using(painter);
}
@@ -102,7 +106,7 @@ void EllipseTool::on_keydown(GUI::KeyEvent& event)
{
if (event.key() == Key_Escape && m_drawing_button != GUI::MouseButton::None) {
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
event.accept();
}
}
@@ -131,3 +135,5 @@ void EllipseTool::on_contextmenu(GUI::ContextMenuEvent& event)
}
m_context_menu->popup(event.screen_position());
}
+
+}
diff --git a/Applications/PaintBrush/EllipseTool.h b/Applications/PaintBrush/EllipseTool.h
index 7443d6578a..3638920bcd 100644
--- a/Applications/PaintBrush/EllipseTool.h
+++ b/Applications/PaintBrush/EllipseTool.h
@@ -30,14 +30,16 @@
#include <LibGfx/Point.h>
#include <LibGUI/ActionGroup.h>
+namespace PaintBrush {
+
class EllipseTool final : public Tool {
public:
EllipseTool();
virtual ~EllipseTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
- virtual void on_mouseup(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
virtual void on_second_paint(GUI::PaintEvent&) override;
virtual void on_keydown(GUI::KeyEvent&) override;
@@ -59,3 +61,5 @@ private:
GUI::ActionGroup m_thickness_actions;
Mode m_mode { Mode::Outline };
};
+
+}
diff --git a/Applications/PaintBrush/EraseTool.cpp b/Applications/PaintBrush/EraseTool.cpp
index 6b21a36116..e1aa1c913c 100644
--- a/Applications/PaintBrush/EraseTool.cpp
+++ b/Applications/PaintBrush/EraseTool.cpp
@@ -25,12 +25,16 @@
*/
#include "EraseTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
#include <LibGfx/Bitmap.h>
+namespace PaintBrush {
+
EraseTool::EraseTool()
{
}
@@ -49,26 +53,26 @@ Gfx::Rect EraseTool::build_rect(const Gfx::Point& pos, const Gfx::Rect& widget_r
return Gfx::Rect(ex - eraser_radius, ey - eraser_radius, eraser_size, eraser_size).intersected(widget_rect);
}
-void EraseTool::on_mousedown(GUI::MouseEvent& event)
+void EraseTool::on_mousedown(Layer& layer, GUI::MouseEvent& event)
{
if (event.button() != GUI::MouseButton::Left && event.button() != GUI::MouseButton::Right)
return;
- Gfx::Rect r = build_rect(event.position(), m_widget->bitmap().rect());
- GUI::Painter painter(m_widget->bitmap());
+ Gfx::Rect r = build_rect(event.position(), layer.rect());
+ GUI::Painter painter(layer.bitmap());
painter.clear_rect(r, get_color());
- m_widget->update();
+ m_editor->update();
}
-void EraseTool::on_mousemove(GUI::MouseEvent& event)
+void EraseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event)
{
- if (!m_widget->rect().contains(event.position()))
+ if (!m_editor->rect().contains(event.position()))
return;
if (event.buttons() & GUI::MouseButton::Left || event.buttons() & GUI::MouseButton::Right) {
- Gfx::Rect r = build_rect(event.position(), m_widget->bitmap().rect());
- GUI::Painter painter(m_widget->bitmap());
+ Gfx::Rect r = build_rect(event.position(), layer.rect());
+ GUI::Painter painter(layer.bitmap());
painter.clear_rect(r, get_color());
- m_widget->update();
+ m_editor->update();
}
}
@@ -106,6 +110,8 @@ void EraseTool::on_contextmenu(GUI::ContextMenuEvent& event)
Color EraseTool::get_color() const
{
if (m_use_secondary_color)
- return m_widget->secondary_color();
+ return PaintableWidget::the().secondary_color();
return Color(255, 255, 255, 0);
}
+
+}
diff --git a/Applications/PaintBrush/EraseTool.h b/Applications/PaintBrush/EraseTool.h
index bdbfcf21ec..8384b8e8fe 100644
--- a/Applications/PaintBrush/EraseTool.h
+++ b/Applications/PaintBrush/EraseTool.h
@@ -29,18 +29,21 @@
#include "Tool.h"
#include <LibGUI/ActionGroup.h>
#include <LibGfx/Point.h>
+#include <LibGfx/Forward.h>
+
+namespace PaintBrush {
class EraseTool final : public Tool {
public:
EraseTool();
virtual ~EraseTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
private:
- Color get_color() const;
+ Gfx::Color get_color() const;
virtual const char* class_name() const override { return "EraseTool"; }
Gfx::Rect build_rect(const Gfx::Point& pos, const Gfx::Rect& widget_rect);
RefPtr<GUI::Menu> m_context_menu;
@@ -49,3 +52,5 @@ private:
int m_thickness { 1 };
GUI::ActionGroup m_thickness_actions;
};
+
+}
diff --git a/Applications/PaintBrush/ImageEditor.cpp b/Applications/PaintBrush/ImageEditor.cpp
index b654b90eef..e49016a2d7 100644
--- a/Applications/PaintBrush/ImageEditor.cpp
+++ b/Applications/PaintBrush/ImageEditor.cpp
@@ -28,6 +28,7 @@
#include "Image.h"
#include "Layer.h"
#include "LayerModel.h"
+#include "Tool.h"
#include <LibGUI/Painter.h>
#include <LibGfx/Palette.h>
@@ -61,6 +62,43 @@ void ImageEditor::paint_event(GUI::PaintEvent& event)
}
}
+static GUI::MouseEvent event_adjusted_for_layer(const GUI::MouseEvent& original_event, const Layer& layer)
+{
+ auto position_in_active_layer_coordinates = original_event.position().translated(-layer.location());
+ dbg() << "adjusted: " << position_in_active_layer_coordinates;
+ return {
+ static_cast<GUI::Event::Type>(original_event.type()),
+ position_in_active_layer_coordinates, original_event.buttons(),
+ original_event.button(),
+ original_event.modifiers(),
+ original_event.wheel_delta()
+ };
+}
+
+void ImageEditor::mousedown_event(GUI::MouseEvent& event)
+{
+ if (!m_active_layer || !m_active_tool)
+ return;
+ auto layer_event = event_adjusted_for_layer(event, *m_active_layer);
+ m_active_tool->on_mousedown(*m_active_layer, layer_event);
+}
+
+void ImageEditor::mousemove_event(GUI::MouseEvent& event)
+{
+ if (!m_active_layer || !m_active_tool)
+ return;
+ auto layer_event = event_adjusted_for_layer(event, *m_active_layer);
+ m_active_tool->on_mousemove(*m_active_layer, layer_event);
+}
+
+void ImageEditor::mouseup_event(GUI::MouseEvent& event)
+{
+ if (!m_active_layer || !m_active_tool)
+ return;
+ auto layer_event = event_adjusted_for_layer(event, *m_active_layer);
+ m_active_tool->on_mouseup(*m_active_layer, layer_event);
+}
+
void ImageEditor::set_active_layer(Layer* layer)
{
if (m_active_layer == layer)
@@ -69,4 +107,18 @@ void ImageEditor::set_active_layer(Layer* layer)
update();
}
+void ImageEditor::set_active_tool(Tool* tool)
+{
+ if (m_active_tool == tool)
+ return;
+
+ if (m_active_tool)
+ m_active_tool->clear();
+
+ m_active_tool = tool;
+
+ if (m_active_tool)
+ m_active_tool->setup(*this);
+}
+
}
diff --git a/Applications/PaintBrush/ImageEditor.h b/Applications/PaintBrush/ImageEditor.h
index aa21c38901..c57599ee07 100644
--- a/Applications/PaintBrush/ImageEditor.h
+++ b/Applications/PaintBrush/ImageEditor.h
@@ -32,6 +32,7 @@ namespace PaintBrush {
class Image;
class Layer;
+class Tool;
class ImageEditor final : public GUI::Frame {
C_OBJECT(ImageEditor);
@@ -45,13 +46,21 @@ public:
Layer* active_layer() { return m_active_layer; }
void set_active_layer(Layer*);
+ Tool* active_tool() { return m_active_tool; }
+ void set_active_tool(Tool*);
+
private:
ImageEditor();
virtual void paint_event(GUI::PaintEvent&) override;
+ virtual void mousedown_event(GUI::MouseEvent&) override;
+ virtual void mousemove_event(GUI::MouseEvent&) override;
+ virtual void mouseup_event(GUI::MouseEvent&) override;
RefPtr<Image> m_image;
RefPtr<Layer> m_active_layer;
+
+ Tool* m_active_tool { nullptr };
};
}
diff --git a/Applications/PaintBrush/LineTool.cpp b/Applications/PaintBrush/LineTool.cpp
index f5efb126d0..e2a071334b 100644
--- a/Applications/PaintBrush/LineTool.cpp
+++ b/Applications/PaintBrush/LineTool.cpp
@@ -25,12 +25,16 @@
*/
#include "LineTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
#include <LibM/math.h>
+namespace PaintBrush {
+
static Gfx::Point constrain_line_angle(const Gfx::Point& start_pos, const Gfx::Point& end_pos, float angle_increment)
{
float current_angle = atan2(end_pos.y() - start_pos.y(), end_pos.x() - start_pos.x()) + M_PI * 2.;
@@ -52,7 +56,7 @@ LineTool::~LineTool()
{
}
-void LineTool::on_mousedown(GUI::MouseEvent& event)
+void LineTool::on_mousedown(Layer&, GUI::MouseEvent& event)
{
if (event.button() != GUI::MouseButton::Left && event.button() != GUI::MouseButton::Right)
return;
@@ -63,25 +67,25 @@ void LineTool::on_mousedown(GUI::MouseEvent& event)
m_drawing_button = event.button();
m_line_start_position = event.position();
m_line_end_position = event.position();
- m_widget->update();
+ m_editor->update();
}
-void LineTool::on_mouseup(GUI::MouseEvent& event)
+void LineTool::on_mouseup(Layer& layer, GUI::MouseEvent& event)
{
if (event.button() == m_drawing_button) {
- GUI::Painter painter(m_widget->bitmap());
- painter.draw_line(m_line_start_position, m_line_end_position, m_widget->color_for(m_drawing_button), m_thickness);
+ GUI::Painter painter(layer.bitmap());
+ painter.draw_line(m_line_start_position, m_line_end_position, PaintableWidget::the().color_for(m_drawing_button), m_thickness);
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
}
}
-void LineTool::on_mousemove(GUI::MouseEvent& event)
+void LineTool::on_mousemove(Layer&, GUI::MouseEvent& event)
{
if (m_drawing_button == GUI::MouseButton::None)
return;
- if (!m_widget->rect().contains(event.position()))
+ if (!m_editor->rect().contains(event.position()))
return;
if (!m_constrain_angle) {
@@ -90,7 +94,7 @@ void LineTool::on_mousemove(GUI::MouseEvent& event)
const float ANGLE_STEP = M_PI / 8.0f;
m_line_end_position = constrain_line_angle(m_line_start_position, event.position(), ANGLE_STEP);
}
- m_widget->update();
+ m_editor->update();
}
void LineTool::on_second_paint(GUI::PaintEvent& event)
@@ -98,22 +102,26 @@ void LineTool::on_second_paint(GUI::PaintEvent& event)
if (m_drawing_button == GUI::MouseButton::None)
return;
+ (void)event;
+
+#if 0
GUI::Painter painter(*m_widget);
painter.add_clip_rect(event.rect());
- painter.draw_line(m_line_start_position, m_line_end_position, m_widget->color_for(m_drawing_button), m_thickness);
+ painter.draw_line(m_line_start_position, m_line_end_position, m_editor->color_for(m_drawing_button), m_thickness);
+#endif
}
void LineTool::on_keydown(GUI::KeyEvent& event)
{
if (event.key() == Key_Escape && m_drawing_button != GUI::MouseButton::None) {
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
event.accept();
}
if (event.key() == Key_Shift) {
m_constrain_angle = true;
- m_widget->update();
+ m_editor->update();
event.accept();
}
}
@@ -122,7 +130,7 @@ void LineTool::on_keyup(GUI::KeyEvent& event)
{
if (event.key() == Key_Shift) {
m_constrain_angle = false;
- m_widget->update();
+ m_editor->update();
event.accept();
}
}
@@ -147,3 +155,5 @@ void LineTool::on_contextmenu(GUI::ContextMenuEvent& event)
}
m_context_menu->popup(event.screen_position());
}
+
+}
diff --git a/Applications/PaintBrush/LineTool.h b/Applications/PaintBrush/LineTool.h
index 06108aa18f..a30286ac5e 100644
--- a/Applications/PaintBrush/LineTool.h
+++ b/Applications/PaintBrush/LineTool.h
@@ -27,17 +27,19 @@
#pragma once
#include "Tool.h"
-#include <LibGfx/Point.h>
#include <LibGUI/ActionGroup.h>
+#include <LibGfx/Point.h>
+
+namespace PaintBrush {
class LineTool final : public Tool {
public:
LineTool();
virtual ~LineTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
- virtual void on_mouseup(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
virtual void on_second_paint(GUI::PaintEvent&) override;
virtual void on_keydown(GUI::KeyEvent&) override;
@@ -54,3 +56,5 @@ private:
int m_thickness { 1 };
bool m_constrain_angle { false };
};
+
+}
diff --git a/Applications/PaintBrush/PaintableWidget.cpp b/Applications/PaintBrush/PaintableWidget.cpp
index d1f21a532f..87b2fe701c 100644
--- a/Applications/PaintBrush/PaintableWidget.cpp
+++ b/Applications/PaintBrush/PaintableWidget.cpp
@@ -54,29 +54,6 @@ PaintableWidget::~PaintableWidget()
{
}
-void PaintableWidget::paint_event(GUI::PaintEvent& event)
-{
- GUI::Painter painter(*this);
-
- painter.add_clip_rect(event.rect());
- painter.fill_rect_with_checkerboard(m_bitmap->rect(), { 8, 8 }, palette().base().darkened(0.9), palette().base());
- painter.blit({ 0, 0 }, *m_bitmap, m_bitmap->rect());
-}
-
-void PaintableWidget::set_tool(Tool* tool)
-{
- if (m_tool)
- m_tool->clear();
- m_tool = tool;
- if (m_tool)
- m_tool->setup(*this);
-}
-
-Tool* PaintableWidget::tool()
-{
- return m_tool;
-}
-
Color PaintableWidget::color_for(GUI::MouseButton button) const
{
if (button == GUI::MouseButton::Left)
@@ -95,52 +72,6 @@ Color PaintableWidget::color_for(const GUI::MouseEvent& event) const
ASSERT_NOT_REACHED();
}
-void PaintableWidget::mousedown_event(GUI::MouseEvent& event)
-{
- if (event.button() == GUI::MouseButton::Left || event.button() == GUI::MouseButton::Right) {
- if (m_tool)
- m_tool->on_mousedown(event);
- }
- GUI::Widget::mousedown_event(event);
-}
-
-void PaintableWidget::mouseup_event(GUI::MouseEvent& event)
-{
- if (event.button() == GUI::MouseButton::Left || event.button() == GUI::MouseButton::Right) {
- if (m_tool)
- m_tool->on_mouseup(event);
- }
- GUI::Widget::mouseup_event(event);
-}
-
-void PaintableWidget::mousemove_event(GUI::MouseEvent& event)
-{
- if (m_tool)
- m_tool->on_mousemove(event);
- GUI::Widget::mousemove_event(event);
-}
-
-void PaintableWidget::second_paint_event(GUI::PaintEvent& event)
-{
- if (m_tool)
- m_tool->on_second_paint(event);
- GUI::Widget::second_paint_event(event);
-}
-
-void PaintableWidget::keydown_event(GUI::KeyEvent& event)
-{
- if (m_tool)
- m_tool->on_keydown(event);
- GUI::Widget::keydown_event(event);
-}
-
-void PaintableWidget::keyup_event(GUI::KeyEvent& event)
-{
- if (m_tool)
- m_tool->on_keyup(event);
- GUI::Widget::keyup_event(event);
-}
-
void PaintableWidget::set_primary_color(Color color)
{
if (m_primary_color == color)
diff --git a/Applications/PaintBrush/PaintableWidget.h b/Applications/PaintBrush/PaintableWidget.h
index 361eb86923..c3947c8542 100644
--- a/Applications/PaintBrush/PaintableWidget.h
+++ b/Applications/PaintBrush/PaintableWidget.h
@@ -27,7 +27,6 @@
#pragma once
#include <LibGUI/Widget.h>
-class Tool;
class PaintableWidget final : public GUI::Widget {
C_OBJECT(PaintableWidget)
@@ -42,9 +41,6 @@ public:
void set_primary_color(Color);
void set_secondary_color(Color);
- void set_tool(Tool* tool);
- Tool* tool();
-
Color color_for(const GUI::MouseEvent&) const;
Color color_for(GUI::MouseButton) const;
@@ -59,19 +55,8 @@ public:
private:
PaintableWidget();
- virtual bool accepts_focus() const override { return true; }
- virtual void paint_event(GUI::PaintEvent&) override;
- virtual void second_paint_event(GUI::PaintEvent&) override;
- virtual void mousedown_event(GUI::MouseEvent&) override;
- virtual void mouseup_event(GUI::MouseEvent&) override;
- virtual void mousemove_event(GUI::MouseEvent&) override;
- virtual void keydown_event(GUI::KeyEvent&) override;
- virtual void keyup_event(GUI::KeyEvent&) override;
-
RefPtr<Gfx::Bitmap> 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
index 05f1c602c7..2891bdba98 100644
--- a/Applications/PaintBrush/PenTool.cpp
+++ b/Applications/PaintBrush/PenTool.cpp
@@ -25,11 +25,15 @@
*/
#include "PenTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
+namespace PaintBrush {
+
PenTool::PenTool()
{
}
@@ -38,36 +42,36 @@ PenTool::~PenTool()
{
}
-void PenTool::on_mousedown(GUI::MouseEvent& event)
+void PenTool::on_mousedown(Layer& layer, GUI::MouseEvent& event)
{
if (event.button() != GUI::MouseButton::Left && event.button() != GUI::MouseButton::Right)
return;
- GUI::Painter painter(m_widget->bitmap());
- painter.draw_line(event.position(), event.position(), m_widget->color_for(event), m_thickness);
- m_widget->update();
+ GUI::Painter painter(layer.bitmap());
+ painter.draw_line(event.position(), event.position(), PaintableWidget::the().color_for(event), m_thickness);
+ m_editor->update();
m_last_drawing_event_position = event.position();
}
-void PenTool::on_mouseup(GUI::MouseEvent& event)
+void PenTool::on_mouseup(Layer&, GUI::MouseEvent& event)
{
if (event.button() == GUI::MouseButton::Left || event.button() == GUI::MouseButton::Right)
m_last_drawing_event_position = { -1, -1 };
}
-void PenTool::on_mousemove(GUI::MouseEvent& event)
+void PenTool::on_mousemove(Layer& layer, GUI::MouseEvent& event)
{
- if (!m_widget->rect().contains(event.position()))
+ if (!layer.rect().contains(event.position()))
return;
if (event.buttons() & GUI::MouseButton::Left || event.buttons() & GUI::MouseButton::Right) {
- GUI::Painter painter(m_widget->bitmap());
+ GUI::Painter painter(layer.bitmap());
if (m_last_drawing_event_position != Gfx::Point(-1, -1))
- painter.draw_line(m_last_drawing_event_position, event.position(), m_widget->color_for(event), m_thickness);
+ painter.draw_line(m_last_drawing_event_position, event.position(), PaintableWidget::the().color_for(event), m_thickness);
else
- painter.draw_line(event.position(), event.position(), m_widget->color_for(event), m_thickness);
- m_widget->update();
+ painter.draw_line(event.position(), event.position(), PaintableWidget::the().color_for(event), m_thickness);
+ m_editor->update();
m_last_drawing_event_position = event.position();
}
@@ -93,3 +97,5 @@ void PenTool::on_contextmenu(GUI::ContextMenuEvent& event)
}
m_context_menu->popup(event.screen_position());
}
+
+}
diff --git a/Applications/PaintBrush/PenTool.h b/Applications/PaintBrush/PenTool.h
index 6cf82d4356..b0c7c46f9a 100644
--- a/Applications/PaintBrush/PenTool.h
+++ b/Applications/PaintBrush/PenTool.h
@@ -30,14 +30,16 @@
#include <LibGfx/Point.h>
#include <LibGUI/ActionGroup.h>
+namespace PaintBrush {
+
class PenTool final : public Tool {
public:
PenTool();
virtual ~PenTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
- virtual void on_mouseup(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
private:
@@ -48,3 +50,5 @@ private:
int m_thickness { 1 };
GUI::ActionGroup m_thickness_actions;
};
+
+}
diff --git a/Applications/PaintBrush/PickerTool.cpp b/Applications/PaintBrush/PickerTool.cpp
index 7189c7d103..2994869dd8 100644
--- a/Applications/PaintBrush/PickerTool.cpp
+++ b/Applications/PaintBrush/PickerTool.cpp
@@ -25,8 +25,12 @@
*/
#include "PickerTool.h"
+#include "Layer.h"
+#include "PaintableWidget.h"
#include <LibGfx/Bitmap.h>
+namespace PaintBrush {
+
PickerTool::PickerTool()
{
}
@@ -35,14 +39,15 @@ PickerTool::~PickerTool()
{
}
-void PickerTool::on_mousedown(GUI::MouseEvent& event)
+void PickerTool::on_mousedown(Layer& layer, GUI::MouseEvent& event)
{
- ASSERT(m_widget);
- if (!m_widget->bitmap().rect().contains(event.position()))
+ if (!layer.rect().contains(event.position()))
return;
- auto color = m_widget->bitmap().get_pixel(event.position());
+ auto color = layer.bitmap().get_pixel(event.position());
if (event.button() == GUI::MouseButton::Left)
- m_widget->set_primary_color(color);
+ PaintableWidget::the().set_primary_color(color);
else if (event.button() == GUI::MouseButton::Right)
- m_widget->set_secondary_color(color);
+ PaintableWidget::the().set_secondary_color(color);
+}
+
}
diff --git a/Applications/PaintBrush/PickerTool.h b/Applications/PaintBrush/PickerTool.h
index 6ae0244b97..34e6afab24 100644
--- a/Applications/PaintBrush/PickerTool.h
+++ b/Applications/PaintBrush/PickerTool.h
@@ -28,14 +28,18 @@
#include "Tool.h"
+namespace PaintBrush {
+
class PickerTool final : public Tool {
public:
PickerTool();
virtual ~PickerTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
private:
virtual const char* class_name() const override { return "PickerTool"; }
};
+
+}
diff --git a/Applications/PaintBrush/RectangleTool.cpp b/Applications/PaintBrush/RectangleTool.cpp
index b6ae419ace..a7a30fa17a 100644
--- a/Applications/PaintBrush/RectangleTool.cpp
+++ b/Applications/PaintBrush/RectangleTool.cpp
@@ -25,13 +25,17 @@
*/
#include "RectangleTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
-#include <LibGfx/Rect.h>
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Painter.h>
+#include <LibGfx/Rect.h>
#include <LibM/math.h>
+namespace PaintBrush {
+
RectangleTool::RectangleTool()
{
}
@@ -45,20 +49,20 @@ void RectangleTool::draw_using(GUI::Painter& painter)
auto rect_to_draw = Gfx::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));
+ painter.fill_rect(rect_to_draw, PaintableWidget::the().color_for(m_drawing_button));
break;
case Mode::Outline:
- painter.draw_rect(rect_to_draw, m_widget->color_for(m_drawing_button));
+ painter.draw_rect(rect_to_draw, PaintableWidget::the().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());
+ painter.fill_rect_with_gradient(rect_to_draw, PaintableWidget::the().primary_color(), PaintableWidget::the().secondary_color());
break;
default:
ASSERT_NOT_REACHED();
}
}
-void RectangleTool::on_mousedown(GUI::MouseEvent& event)
+void RectangleTool::on_mousedown(Layer&, GUI::MouseEvent& event)
{
if (event.button() != GUI::MouseButton::Left && event.button() != GUI::MouseButton::Right)
return;
@@ -69,29 +73,29 @@ void RectangleTool::on_mousedown(GUI::MouseEvent& event)
m_drawing_button = event.button();
m_rectangle_start_position = event.position();
m_rectangle_end_position = event.position();
- m_widget->update();
+ m_editor->update();
}
-void RectangleTool::on_mouseup(GUI::MouseEvent& event)
+void RectangleTool::on_mouseup(Layer& layer, GUI::MouseEvent& event)
{
if (event.button() == m_drawing_button) {
- GUI::Painter painter(m_widget->bitmap());
+ GUI::Painter painter(layer.bitmap());
draw_using(painter);
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
}
}
-void RectangleTool::on_mousemove(GUI::MouseEvent& event)
+void RectangleTool::on_mousemove(Layer&, GUI::MouseEvent& event)
{
if (m_drawing_button == GUI::MouseButton::None)
return;
- if (!m_widget->rect().contains(event.position()))
+ if (!m_editor->rect().contains(event.position()))
return;
m_rectangle_end_position = event.position();
- m_widget->update();
+ m_editor->update();
}
void RectangleTool::on_second_paint(GUI::PaintEvent& event)
@@ -99,16 +103,19 @@ void RectangleTool::on_second_paint(GUI::PaintEvent& event)
if (m_drawing_button == GUI::MouseButton::None)
return;
+ (void)event;
+#if 0
GUI::Painter painter(*m_widget);
painter.add_clip_rect(event.rect());
draw_using(painter);
+#endif
}
void RectangleTool::on_keydown(GUI::KeyEvent& event)
{
if (event.key() == Key_Escape && m_drawing_button != GUI::MouseButton::None) {
m_drawing_button = GUI::MouseButton::None;
- m_widget->update();
+ m_editor->update();
event.accept();
}
}
@@ -129,3 +136,5 @@ void RectangleTool::on_contextmenu(GUI::ContextMenuEvent& event)
}
m_context_menu->popup(event.screen_position());
}
+
+}
diff --git a/Applications/PaintBrush/RectangleTool.h b/Applications/PaintBrush/RectangleTool.h
index c63c59c6fc..71871b4cb3 100644
--- a/Applications/PaintBrush/RectangleTool.h
+++ b/Applications/PaintBrush/RectangleTool.h
@@ -28,15 +28,18 @@
#include "Tool.h"
#include <LibGfx/Point.h>
+#include <LibGUI/Forward.h>
+
+namespace PaintBrush {
class RectangleTool final : public Tool {
public:
RectangleTool();
virtual ~RectangleTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
- virtual void on_mouseup(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
virtual void on_second_paint(GUI::PaintEvent&) override;
virtual void on_keydown(GUI::KeyEvent&) override;
@@ -57,3 +60,5 @@ private:
RefPtr<GUI::Menu> m_context_menu;
Mode m_mode { Mode::Outline };
};
+
+}
diff --git a/Applications/PaintBrush/SprayTool.cpp b/Applications/PaintBrush/SprayTool.cpp
index 0f5031c03f..ff668002ba 100644
--- a/Applications/PaintBrush/SprayTool.cpp
+++ b/Applications/PaintBrush/SprayTool.cpp
@@ -25,15 +25,19 @@
*/
#include "SprayTool.h"
+#include "ImageEditor.h"
+#include "Layer.h"
#include "PaintableWidget.h"
#include <AK/Queue.h>
#include <AK/SinglyLinkedList.h>
-#include <LibGUI/Painter.h>
#include <LibGUI/Action.h>
#include <LibGUI/Menu.h>
+#include <LibGUI/Painter.h>
#include <LibGfx/Bitmap.h>
-#include <stdio.h>
#include <LibM/math.h>
+#include <stdio.h>
+
+namespace PaintBrush {
SprayTool::SprayTool()
{
@@ -55,10 +59,14 @@ static double nrand()
void SprayTool::paint_it()
{
- GUI::Painter painter(m_widget->bitmap());
- auto& bitmap = m_widget->bitmap();
+ auto* layer = m_editor->active_layer();
+ if (!layer)
+ return;
+
+ auto& bitmap = layer->bitmap();
+ GUI::Painter painter(bitmap);
ASSERT(bitmap.bpp() == 32);
- m_widget->update();
+ m_editor->update();
const double minimal_radius = 10;
const double base_radius = minimal_radius * m_thickness;
for (int i = 0; i < 100 + (nrand() * 800); i++) {
@@ -74,18 +82,18 @@ void SprayTool::paint_it()
}
}
-void SprayTool::on_mousedown(GUI::MouseEvent& event)
+void SprayTool::on_mousedown(Layer&, GUI::MouseEvent& event)
{
- if (!m_widget->rect().contains(event.position()))
+ if (!m_editor->rect().contains(event.position()))
return;
- m_color = m_widget->color_for(event);
+ m_color = PaintableWidget::the().color_for(event);
m_last_pos = event.position();
m_timer->start();
paint_it();
}
-void SprayTool::on_mousemove(GUI::MouseEvent& event)
+void SprayTool::on_mousemove(Layer&, GUI::MouseEvent& event)
{
m_last_pos = event.position();
if (m_timer->is_active()) {
@@ -94,7 +102,7 @@ void SprayTool::on_mousemove(GUI::MouseEvent& event)
}
}
-void SprayTool::on_mouseup(GUI::MouseEvent&)
+void SprayTool::on_mouseup(Layer&, GUI::MouseEvent&)
{
m_timer->stop();
}
@@ -120,3 +128,4 @@ void SprayTool::on_contextmenu(GUI::ContextMenuEvent& event)
m_context_menu->popup(event.screen_position());
}
+}
diff --git a/Applications/PaintBrush/SprayTool.h b/Applications/PaintBrush/SprayTool.h
index 18d78f0250..d5e4564f9d 100644
--- a/Applications/PaintBrush/SprayTool.h
+++ b/Applications/PaintBrush/SprayTool.h
@@ -31,14 +31,16 @@
#include <LibGUI/ActionGroup.h>
#include <LibGUI/Painter.h>
+namespace PaintBrush {
+
class SprayTool final : public Tool {
public:
SprayTool();
virtual ~SprayTool() override;
- virtual void on_mousedown(GUI::MouseEvent&) override;
- virtual void on_mouseup(GUI::MouseEvent&) override;
- virtual void on_mousemove(GUI::MouseEvent&) override;
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) override;
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) override;
virtual void on_contextmenu(GUI::ContextMenuEvent&) override;
private:
@@ -51,3 +53,5 @@ private:
GUI::ActionGroup m_thickness_actions;
int m_thickness { 1 };
};
+
+}
diff --git a/Applications/PaintBrush/Tool.cpp b/Applications/PaintBrush/Tool.cpp
index 9c5171a548..68c2270b9d 100644
--- a/Applications/PaintBrush/Tool.cpp
+++ b/Applications/PaintBrush/Tool.cpp
@@ -25,6 +25,9 @@
*/
#include "Tool.h"
+#include "ImageEditor.h"
+
+namespace PaintBrush {
Tool::Tool()
{
@@ -33,3 +36,10 @@ Tool::Tool()
Tool::~Tool()
{
}
+
+void Tool::setup(ImageEditor& editor)
+{
+ m_editor = editor.make_weak_ptr();
+}
+
+}
diff --git a/Applications/PaintBrush/Tool.h b/Applications/PaintBrush/Tool.h
index 24fbde83a8..2ef8a0920c 100644
--- a/Applications/PaintBrush/Tool.h
+++ b/Applications/PaintBrush/Tool.h
@@ -26,7 +26,12 @@
#pragma once
-#include "PaintableWidget.h"
+#include <LibGUI/Event.h>
+
+namespace PaintBrush {
+
+class ImageEditor;
+class Layer;
class Tool {
public:
@@ -34,18 +39,20 @@ public:
virtual const char* class_name() const = 0;
- virtual void on_mousedown(GUI::MouseEvent&) {}
- virtual void on_mousemove(GUI::MouseEvent&) {}
- virtual void on_mouseup(GUI::MouseEvent&) {}
+ virtual void on_mousedown(Layer&, GUI::MouseEvent&) {}
+ virtual void on_mousemove(Layer&, GUI::MouseEvent&) {}
+ virtual void on_mouseup(Layer&, GUI::MouseEvent&) {}
virtual void on_contextmenu(GUI::ContextMenuEvent&) {}
virtual void on_second_paint(GUI::PaintEvent&) {}
virtual void on_keydown(GUI::KeyEvent&) {}
virtual void on_keyup(GUI::KeyEvent&) {}
- void clear() { m_widget = nullptr; }
- void setup(PaintableWidget& widget) { m_widget = widget.make_weak_ptr(); }
+ void clear() { m_editor = nullptr; }
+ void setup(ImageEditor&);
protected:
Tool();
- WeakPtr<PaintableWidget> m_widget;
+ WeakPtr<ImageEditor> m_editor;
};
+
+}
diff --git a/Applications/PaintBrush/ToolboxWidget.cpp b/Applications/PaintBrush/ToolboxWidget.cpp
index 4af60eac01..9dda50ea2f 100644
--- a/Applications/PaintBrush/ToolboxWidget.cpp
+++ b/Applications/PaintBrush/ToolboxWidget.cpp
@@ -37,6 +37,8 @@
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
+namespace PaintBrush {
+
class ToolButton final : public GUI::Button {
C_OBJECT(ToolButton)
public:
@@ -82,11 +84,11 @@ ToolboxWidget::ToolboxWidget()
button.set_icon(Gfx::Bitmap::load_from_file(String::format("/res/icons/paintbrush/%s.png", icon_name.to_string().characters())));
- button.on_checked = [button = &button](auto checked) {
+ button.on_checked = [this, button = &button](auto checked) {
if (checked)
- PaintableWidget::the().set_tool(&button->tool());
+ on_tool_selection(&button->tool());
else
- PaintableWidget::the().set_tool(nullptr);
+ on_tool_selection(nullptr);
};
};
@@ -103,3 +105,5 @@ ToolboxWidget::ToolboxWidget()
ToolboxWidget::~ToolboxWidget()
{
}
+
+}
diff --git a/Applications/PaintBrush/ToolboxWidget.h b/Applications/PaintBrush/ToolboxWidget.h
index 7c15a6f596..561951742e 100644
--- a/Applications/PaintBrush/ToolboxWidget.h
+++ b/Applications/PaintBrush/ToolboxWidget.h
@@ -28,9 +28,19 @@
#include <LibGUI/Frame.h>
+namespace PaintBrush {
+
+class Tool;
+
class ToolboxWidget final : public GUI::Frame {
C_OBJECT(ToolboxWidget)
public:
- explicit ToolboxWidget();
virtual ~ToolboxWidget() override;
+
+ Function<void(Tool*)> on_tool_selection;
+
+private:
+ explicit ToolboxWidget();
};
+
+}
diff --git a/Applications/PaintBrush/main.cpp b/Applications/PaintBrush/main.cpp
index 27b01e098c..7532d54c4e 100644
--- a/Applications/PaintBrush/main.cpp
+++ b/Applications/PaintBrush/main.cpp
@@ -67,7 +67,7 @@ int main(int argc, char** argv)
horizontal_container.set_layout<GUI::HorizontalBoxLayout>();
horizontal_container.layout()->set_spacing(0);
- horizontal_container.add<ToolboxWidget>();
+ auto& toolbox = horizontal_container.add<PaintBrush::ToolboxWidget>();
auto& vertical_container = horizontal_container.add<GUI::Widget>();
vertical_container.set_layout<GUI::VerticalBoxLayout>();
@@ -76,6 +76,10 @@ int main(int argc, char** argv)
auto& image_editor = vertical_container.add<PaintBrush::ImageEditor>();
image_editor.set_focus(true);
+ toolbox.on_tool_selection = [&](auto* tool) {
+ image_editor.set_active_tool(tool);
+ };
+
auto& paintable_widget = vertical_container.add<PaintableWidget>();
paintable_widget.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fixed);
paintable_widget.set_preferred_size(0, 0);