1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:57:45 +00:00

PixelPaint: Have layers and images send out notifications on changes

We use this to automatically update the thumbnail in LayerListWidget
when you draw into a layer. We also use it to repaint the ImageEditor
when the image changes somehow. :^)
This commit is contained in:
Andreas Kling 2020-05-25 22:49:50 +02:00
parent de85cd0907
commit dc3de47b03
14 changed files with 53 additions and 12 deletions

View file

@ -87,7 +87,7 @@ void BucketTool::on_mousedown(Layer& layer, GUI::MouseEvent& event, GUI::MouseEv
flood_fill(layer.bitmap(), event.position(), target_color, m_editor->color_for(event)); flood_fill(layer.bitmap(), event.position(), target_color, m_editor->color_for(event));
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
} }
} }

View file

@ -59,7 +59,7 @@ void EraseTool::on_mousedown(Layer& layer, GUI::MouseEvent& event, GUI::MouseEve
Gfx::Rect r = build_rect(event.position(), layer.rect()); Gfx::Rect r = build_rect(event.position(), layer.rect());
GUI::Painter painter(layer.bitmap()); GUI::Painter painter(layer.bitmap());
painter.clear_rect(r, get_color()); painter.clear_rect(r, get_color());
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
} }
void EraseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent&) void EraseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent&)
@ -68,7 +68,7 @@ void EraseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event, GUI::MouseEve
Gfx::Rect r = build_rect(event.position(), layer.rect()); Gfx::Rect r = build_rect(event.position(), layer.rect());
GUI::Painter painter(layer.bitmap()); GUI::Painter painter(layer.bitmap());
painter.clear_rect(r, get_color()); painter.clear_rect(r, get_color());
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
} }
} }

View file

@ -146,4 +146,19 @@ void Image::remove_client(ImageClient& client)
m_clients.remove(&client); m_clients.remove(&client);
} }
void Image::layer_did_modify_bitmap(Badge<Layer>, const Layer& layer)
{
auto layer_index = index_of(layer);
for (auto* client : m_clients)
client->image_did_modify_layer(layer_index);
did_change();
}
void Image::did_change()
{
for (auto* client : m_clients)
client->image_did_change();
}
} }

View file

@ -44,7 +44,8 @@ class ImageClient {
public: public:
virtual void image_did_add_layer(size_t) { } virtual void image_did_add_layer(size_t) { }
virtual void image_did_remove_layer(size_t) { } virtual void image_did_remove_layer(size_t) { }
virtual void image_did_update_layer(size_t) { } virtual void image_did_modify_layer(size_t) { }
virtual void image_did_change() { }
}; };
class Image : public RefCounted<Image> { class Image : public RefCounted<Image> {
@ -72,9 +73,13 @@ public:
void add_client(ImageClient&); void add_client(ImageClient&);
void remove_client(ImageClient&); void remove_client(ImageClient&);
void layer_did_modify_bitmap(Badge<Layer>, const Layer&);
private: private:
explicit Image(const Gfx::Size&); explicit Image(const Gfx::Size&);
void did_change();
size_t index_of(const Layer&) const; size_t index_of(const Layer&) const;
Gfx::Size m_size; Gfx::Size m_size;

View file

@ -353,4 +353,9 @@ void ImageEditor::relayout()
update(); update();
} }
void ImageEditor::image_did_change()
{
update();
}
} }

View file

@ -26,16 +26,18 @@
#pragma once #pragma once
#include "Image.h"
#include <LibGUI/Frame.h> #include <LibGUI/Frame.h>
#include <LibGfx/FloatPoint.h> #include <LibGfx/FloatPoint.h>
namespace PixelPaint { namespace PixelPaint {
class Image;
class Layer; class Layer;
class Tool; class Tool;
class ImageEditor final : public GUI::Frame { class ImageEditor final
: public GUI::Frame
, public ImageClient {
C_OBJECT(ImageEditor); C_OBJECT(ImageEditor);
public: public:
@ -91,6 +93,8 @@ private:
virtual void context_menu_event(GUI::ContextMenuEvent&) override; virtual void context_menu_event(GUI::ContextMenuEvent&) override;
virtual void resize_event(GUI::ResizeEvent&) override; virtual void resize_event(GUI::ResizeEvent&) override;
virtual void image_did_change() override;
GUI::MouseEvent event_adjusted_for_layer(const GUI::MouseEvent&, const Layer&) const; GUI::MouseEvent event_adjusted_for_layer(const GUI::MouseEvent&, const Layer&) const;
GUI::MouseEvent event_with_pan_and_scale_applied(const GUI::MouseEvent&) const; GUI::MouseEvent event_with_pan_and_scale_applied(const GUI::MouseEvent&) const;

View file

@ -25,6 +25,7 @@
*/ */
#include "Layer.h" #include "Layer.h"
#include "Image.h"
#include <LibGfx/Bitmap.h> #include <LibGfx/Bitmap.h>
namespace PixelPaint { namespace PixelPaint {
@ -46,4 +47,9 @@ Layer::Layer(const Gfx::Size& size, const String& name)
m_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA32, size); m_bitmap = Gfx::Bitmap::create(Gfx::BitmapFormat::RGBA32, size);
} }
void Layer::did_modify_bitmap(Image& image)
{
image.layer_did_modify_bitmap({}, *this);
}
} }

View file

@ -33,6 +33,8 @@
namespace PixelPaint { namespace PixelPaint {
class Image;
class Layer : public RefCounted<Layer> { class Layer : public RefCounted<Layer> {
AK_MAKE_NONCOPYABLE(Layer); AK_MAKE_NONCOPYABLE(Layer);
AK_MAKE_NONMOVABLE(Layer); AK_MAKE_NONMOVABLE(Layer);
@ -55,6 +57,8 @@ public:
const String& name() const { return m_name; } const String& name() const { return m_name; }
void set_name(const String& name) { m_name = name; } void set_name(const String& name) { m_name = name; }
void did_modify_bitmap(Image&);
private: private:
explicit Layer(const Gfx::Size&, const String& name); explicit Layer(const Gfx::Size&, const String& name);

View file

@ -125,7 +125,7 @@ void LayerListWidget::image_did_remove_layer(size_t layer_index)
relayout_gadgets(); relayout_gadgets();
} }
void LayerListWidget::image_did_update_layer(size_t layer_index) void LayerListWidget::image_did_modify_layer(size_t layer_index)
{ {
update(m_gadgets[layer_index].rect); update(m_gadgets[layer_index].rect);
} }

View file

@ -52,7 +52,7 @@ private:
virtual void image_did_add_layer(size_t) override; virtual void image_did_add_layer(size_t) override;
virtual void image_did_remove_layer(size_t) override; virtual void image_did_remove_layer(size_t) override;
virtual void image_did_update_layer(size_t); virtual void image_did_modify_layer(size_t);
void relayout_gadgets(); void relayout_gadgets();

View file

@ -77,7 +77,7 @@ void LineTool::on_mouseup(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent&
GUI::Painter painter(layer.bitmap()); GUI::Painter painter(layer.bitmap());
painter.draw_line(m_line_start_position, m_line_end_position, m_editor->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);
m_drawing_button = GUI::MouseButton::None; m_drawing_button = GUI::MouseButton::None;
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
} }
} }

View file

@ -48,7 +48,7 @@ void PenTool::on_mousedown(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent
GUI::Painter painter(layer.bitmap()); GUI::Painter painter(layer.bitmap());
painter.draw_line(event.position(), event.position(), m_editor->color_for(event), m_thickness); painter.draw_line(event.position(), event.position(), m_editor->color_for(event), m_thickness);
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
m_last_drawing_event_position = event.position(); m_last_drawing_event_position = event.position();
} }
@ -68,7 +68,7 @@ void PenTool::on_mousemove(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent
painter.draw_line(m_last_drawing_event_position, event.position(), m_editor->color_for(event), m_thickness); painter.draw_line(m_last_drawing_event_position, event.position(), m_editor->color_for(event), m_thickness);
else else
painter.draw_line(event.position(), event.position(), m_editor->color_for(event), m_thickness); painter.draw_line(event.position(), event.position(), m_editor->color_for(event), m_thickness);
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
m_last_drawing_event_position = event.position(); m_last_drawing_event_position = event.position();
} }

View file

@ -81,7 +81,7 @@ void RectangleTool::on_mouseup(Layer& layer, GUI::MouseEvent& event, GUI::MouseE
auto rect = Gfx::Rect::from_two_points(m_rectangle_start_position, m_rectangle_end_position); auto rect = Gfx::Rect::from_two_points(m_rectangle_start_position, m_rectangle_end_position);
draw_using(painter, rect); draw_using(painter, rect);
m_drawing_button = GUI::MouseButton::None; m_drawing_button = GUI::MouseButton::None;
m_editor->update(); layer.did_modify_bitmap(*m_editor->image());
} }
} }

View file

@ -79,6 +79,8 @@ void SprayTool::paint_it()
continue; continue;
bitmap.set_pixel<Gfx::BitmapFormat::RGB32>(xpos, ypos, m_color); bitmap.set_pixel<Gfx::BitmapFormat::RGB32>(xpos, ypos, m_color);
} }
layer->did_modify_bitmap(*m_editor->image());
} }
void SprayTool::on_mousedown(Layer&, GUI::MouseEvent& event, GUI::MouseEvent&) void SprayTool::on_mousedown(Layer&, GUI::MouseEvent& event, GUI::MouseEvent&)