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
Notes: sideshowbarker 2024-07-19 06:08:07 +09:00
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));
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());
GUI::Painter painter(layer.bitmap());
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&)
@ -68,7 +68,7 @@ void EraseTool::on_mousemove(Layer& layer, GUI::MouseEvent& event, GUI::MouseEve
Gfx::Rect r = build_rect(event.position(), layer.rect());
GUI::Painter painter(layer.bitmap());
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);
}
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:
virtual void image_did_add_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> {
@ -72,9 +73,13 @@ public:
void add_client(ImageClient&);
void remove_client(ImageClient&);
void layer_did_modify_bitmap(Badge<Layer>, const Layer&);
private:
explicit Image(const Gfx::Size&);
void did_change();
size_t index_of(const Layer&) const;
Gfx::Size m_size;

View file

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

View file

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

View file

@ -25,6 +25,7 @@
*/
#include "Layer.h"
#include "Image.h"
#include <LibGfx/Bitmap.h>
namespace PixelPaint {
@ -46,4 +47,9 @@ Layer::Layer(const Gfx::Size& size, const String& name)
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 {
class Image;
class Layer : public RefCounted<Layer> {
AK_MAKE_NONCOPYABLE(Layer);
AK_MAKE_NONMOVABLE(Layer);
@ -55,6 +57,8 @@ public:
const String& name() const { return m_name; }
void set_name(const String& name) { m_name = name; }
void did_modify_bitmap(Image&);
private:
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();
}
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);
}

View file

@ -52,7 +52,7 @@ private:
virtual void image_did_add_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();

View file

@ -77,7 +77,7 @@ void LineTool::on_mouseup(Layer& layer, GUI::MouseEvent& event, GUI::MouseEvent&
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);
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());
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();
}
@ -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);
else
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();
}

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);
draw_using(painter, rect);
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;
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&)