diff options
author | Andreas Kling <kling@serenityos.org> | 2020-05-12 23:44:46 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-05-12 23:44:46 +0200 |
commit | 83d24dcb1d4d921c4d1c9f85ca97808b2a463b32 (patch) | |
tree | 6b2d88a0584d6dc4cccf718f3751f892a203f394 /Applications | |
parent | 7dd8f1b921c5c63c21415a6ded179134a18e1ae2 (diff) | |
download | serenity-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')
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); |