From 4cecd7900036554c7d153ca8b876bbc49b3bd31f Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 14 Jun 2021 17:45:59 +0200 Subject: [PATCH] PixelPaint: Draw the current editor selection as marching ants This patch moves the marching ants painting code to Selection and unifies the timer mechanism so that all marching ants are synchronized which looks neat. :^) --- .../Applications/PixelPaint/ImageEditor.cpp | 1 + .../PixelPaint/RectangleSelectTool.cpp | 41 +----------------- .../PixelPaint/RectangleSelectTool.h | 4 -- .../Applications/PixelPaint/Selection.cpp | 43 ++++++++++++++++++- Userland/Applications/PixelPaint/Selection.h | 8 +++- 5 files changed, 51 insertions(+), 46 deletions(-) diff --git a/Userland/Applications/PixelPaint/ImageEditor.cpp b/Userland/Applications/PixelPaint/ImageEditor.cpp index b4a543a2472..2d4d8e7a42c 100644 --- a/Userland/Applications/PixelPaint/ImageEditor.cpp +++ b/Userland/Applications/PixelPaint/ImageEditor.cpp @@ -20,6 +20,7 @@ namespace PixelPaint { ImageEditor::ImageEditor() : m_undo_stack(make()) + , m_selection(*this) { set_focus_policy(GUI::FocusPolicy::StrongFocus); } diff --git a/Userland/Applications/PixelPaint/RectangleSelectTool.cpp b/Userland/Applications/PixelPaint/RectangleSelectTool.cpp index 820bb4219f6..832765dc2d8 100644 --- a/Userland/Applications/PixelPaint/RectangleSelectTool.cpp +++ b/Userland/Applications/PixelPaint/RectangleSelectTool.cpp @@ -5,26 +5,14 @@ */ #include "RectangleSelectTool.h" -#include "Image.h" #include "ImageEditor.h" #include "Layer.h" -#include #include namespace PixelPaint { -constexpr int marching_ant_length = 4; - RectangleSelectTool::RectangleSelectTool() { - m_marching_ants_timer = Core::Timer::create_repeating(80, [this] { - if (!m_editor) - return; - ++m_marching_ants_offset; - m_marching_ants_offset %= marching_ant_length; - m_editor->update(); - }); - m_marching_ants_timer->start(); } RectangleSelectTool::~RectangleSelectTool() @@ -63,33 +51,6 @@ void RectangleSelectTool::on_mouseup(Layer&, GUI::MouseEvent&, GUI::MouseEvent& m_editor->selection().set(rect_in_image); } -void RectangleSelectTool::draw_marching_ants(Gfx::Painter& painter, Gfx::IntRect const& rect) const -{ - int offset = m_marching_ants_offset; - - auto draw_pixel = [&](int x, int y) { - if ((offset % marching_ant_length) != 0) - painter.set_pixel(x, y, Color::Black); - offset++; - }; - - // Top line - for (int x = rect.left(); x <= rect.right(); ++x) - draw_pixel(x, rect.top()); - - // Right line - for (int y = rect.top() + 1; y <= rect.bottom(); ++y) - draw_pixel(rect.right(), y); - - // Bottom line - for (int x = rect.right() - 1; x >= rect.left(); --x) - draw_pixel(x, rect.bottom()); - - // Left line - for (int y = rect.bottom() - 1; y > rect.top(); --y) - draw_pixel(rect.left(), y); -} - void RectangleSelectTool::on_second_paint(Layer const&, GUI::PaintEvent& event) { if (!m_selecting) @@ -101,7 +62,7 @@ void RectangleSelectTool::on_second_paint(Layer const&, GUI::PaintEvent& event) auto rect_in_image = Gfx::IntRect::from_two_points(m_selection_start, m_selection_end); auto rect_in_editor = m_editor->image_rect_to_editor_rect(rect_in_image); - draw_marching_ants(painter, rect_in_editor.to_type()); + m_editor->selection().draw_marching_ants(painter, rect_in_editor.to_type()); } } diff --git a/Userland/Applications/PixelPaint/RectangleSelectTool.h b/Userland/Applications/PixelPaint/RectangleSelectTool.h index 6011d2f199b..2bfe4324b95 100644 --- a/Userland/Applications/PixelPaint/RectangleSelectTool.h +++ b/Userland/Applications/PixelPaint/RectangleSelectTool.h @@ -21,13 +21,9 @@ public: virtual void on_second_paint(Layer const&, GUI::PaintEvent&) override; private: - void draw_marching_ants(Gfx::Painter&, Gfx::IntRect const&) const; - bool m_selecting { false }; Gfx::IntPoint m_selection_start; Gfx::IntPoint m_selection_end; - RefPtr m_marching_ants_timer; - int m_marching_ants_offset { 0 }; }; } diff --git a/Userland/Applications/PixelPaint/Selection.cpp b/Userland/Applications/PixelPaint/Selection.cpp index db93e751f06..6e645e9ddb2 100644 --- a/Userland/Applications/PixelPaint/Selection.cpp +++ b/Userland/Applications/PixelPaint/Selection.cpp @@ -10,9 +10,50 @@ namespace PixelPaint { +constexpr int marching_ant_length = 4; + void Selection::paint(Gfx::Painter& painter, ImageEditor const& editor) { - painter.draw_rect(editor.image_rect_to_editor_rect(m_rect).to_type(), Color::Magenta); + draw_marching_ants(painter, editor.image_rect_to_editor_rect(m_rect).to_type()); +} + +Selection::Selection(ImageEditor& editor) + : m_editor(editor) +{ + m_marching_ants_timer = Core::Timer::create_repeating(80, [this] { + ++m_marching_ants_offset; + m_marching_ants_offset %= marching_ant_length; + if (!is_empty()) + m_editor.update(); + }); + m_marching_ants_timer->start(); +} + +void Selection::draw_marching_ants(Gfx::Painter& painter, Gfx::IntRect const& rect) const +{ + int offset = m_marching_ants_offset; + + auto draw_pixel = [&](int x, int y) { + if ((offset % marching_ant_length) != 0) + painter.set_pixel(x, y, Color::Black); + offset++; + }; + + // Top line + for (int x = rect.left(); x <= rect.right(); ++x) + draw_pixel(x, rect.top()); + + // Right line + for (int y = rect.top() + 1; y <= rect.bottom(); ++y) + draw_pixel(rect.right(), y); + + // Bottom line + for (int x = rect.right() - 1; x >= rect.left(); --x) + draw_pixel(x, rect.bottom()); + + // Left line + for (int y = rect.bottom() - 1; y > rect.top(); --y) + draw_pixel(rect.left(), y); } } diff --git a/Userland/Applications/PixelPaint/Selection.h b/Userland/Applications/PixelPaint/Selection.h index e852f07da41..1322a145639 100644 --- a/Userland/Applications/PixelPaint/Selection.h +++ b/Userland/Applications/PixelPaint/Selection.h @@ -6,6 +6,7 @@ #pragma once +#include #include namespace PixelPaint { @@ -15,7 +16,7 @@ class ImageEditor; // Coordinates are image-relative. class Selection { public: - Selection() { } + explicit Selection(ImageEditor&); bool is_empty() const { return m_rect.is_empty(); } void clear() { m_rect = {}; } @@ -23,8 +24,13 @@ public: void paint(Gfx::Painter&, ImageEditor const&); + void draw_marching_ants(Gfx::Painter&, Gfx::IntRect const&) const; + private: + ImageEditor& m_editor; Gfx::IntRect m_rect; + RefPtr m_marching_ants_timer; + int m_marching_ants_offset { 0 }; }; }