PixelPaint: Move title and path from Image to ImageEditor

As noted in the latest hacking video, it doesn't seem to make much
sense to store the title and path in the image itself. These fields
have now been moved to the actual ImageEditor itself.

This allows some nice simplicfications, including getting rid of the
`image_did_change_title` hook of ImageClient (which was just a way to
report back to the editor that the title had changed).
This commit is contained in:
Mustafa Quraish 2022-01-04 21:42:26 -05:00 committed by Andreas Kling
parent 0b43a92eed
commit 2440d2c2fe
Notes: sideshowbarker 2024-07-17 21:37:42 +09:00
6 changed files with 45 additions and 56 deletions

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -13,7 +13,6 @@
#include <AK/JsonObject.h> #include <AK/JsonObject.h>
#include <AK/JsonObjectSerializer.h> #include <AK/JsonObjectSerializer.h>
#include <AK/JsonValue.h> #include <AK/JsonValue.h>
#include <AK/LexicalPath.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <LibCore/MappedFile.h> #include <LibCore/MappedFile.h>
#include <LibGUI/Painter.h> #include <LibGUI/Painter.h>
@ -36,8 +35,7 @@ ErrorOr<NonnullRefPtr<Image>> Image::try_create_with_size(Gfx::IntSize const& si
} }
Image::Image(Gfx::IntSize const& size) Image::Image(Gfx::IntSize const& size)
: m_title("Untitled") : m_size(size)
, m_size(size)
{ {
} }
@ -468,19 +466,6 @@ void ImageUndoCommand::redo()
undo(); undo();
} }
void Image::set_title(String title)
{
m_title = move(title);
for (auto* client : m_clients)
client->image_did_change_title(m_title);
}
void Image::set_path(String path)
{
m_path = move(path);
set_title(LexicalPath::basename(m_path));
}
void Image::flip(Gfx::Orientation orientation) void Image::flip(Gfx::Orientation orientation)
{ {
for (auto& layer : m_layers) { for (auto& layer : m_layers) {

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -38,7 +38,6 @@ public:
virtual void image_did_change(Gfx::IntRect const&) { } virtual void image_did_change(Gfx::IntRect const&) { }
virtual void image_did_change_rect(Gfx::IntRect const&) { } virtual void image_did_change_rect(Gfx::IntRect const&) { }
virtual void image_select_layer(Layer*) { } virtual void image_select_layer(Layer*) { }
virtual void image_did_change_title(String const&) { }
protected: protected:
virtual ~ImageClient() = default; virtual ~ImageClient() = default;
@ -93,12 +92,6 @@ public:
size_t index_of(Layer const&) const; size_t index_of(Layer const&) const;
String const& path() const { return m_path; }
void set_path(String);
String const& title() const { return m_title; }
void set_title(String);
void flip(Gfx::Orientation orientation); void flip(Gfx::Orientation orientation);
void rotate(Gfx::RotationDirection direction); void rotate(Gfx::RotationDirection direction);
void crop(Gfx::IntRect const& rect); void crop(Gfx::IntRect const& rect);
@ -112,9 +105,6 @@ private:
void did_change_rect(Gfx::IntRect const& modified_rect = {}); void did_change_rect(Gfx::IntRect const& modified_rect = {});
void did_modify_layer_stack(); void did_modify_layer_stack();
String m_path;
String m_title;
Gfx::IntSize m_size; Gfx::IntSize m_size;
NonnullRefPtrVector<Layer> m_layers; NonnullRefPtrVector<Layer> m_layers;

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org>
* Copyright (c) 2021, David Isaksson <davidisaksson93@gmail.com> * Copyright (c) 2021, David Isaksson <davidisaksson93@gmail.com>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -12,6 +12,7 @@
#include "Layer.h" #include "Layer.h"
#include "Tools/MoveTool.h" #include "Tools/MoveTool.h"
#include "Tools/Tool.h" #include "Tools/Tool.h"
#include <AK/LexicalPath.h>
#include <LibConfig/Client.h> #include <LibConfig/Client.h>
#include <LibGUI/Command.h> #include <LibGUI/Command.h>
#include <LibGUI/Painter.h> #include <LibGUI/Painter.h>
@ -23,6 +24,7 @@ namespace PixelPaint {
ImageEditor::ImageEditor(NonnullRefPtr<Image> image) ImageEditor::ImageEditor(NonnullRefPtr<Image> image)
: m_image(move(image)) : m_image(move(image))
, m_title("Untitled")
, m_selection(*this) , m_selection(*this)
{ {
set_focus_policy(GUI::FocusPolicy::StrongFocus); set_focus_policy(GUI::FocusPolicy::StrongFocus);
@ -78,6 +80,19 @@ bool ImageEditor::redo()
return true; return true;
} }
void ImageEditor::set_title(String title)
{
m_title = move(title);
if (on_title_change)
on_title_change(m_title);
}
void ImageEditor::set_path(String path)
{
m_path = move(path);
set_title(LexicalPath::basename(m_path));
}
void ImageEditor::paint_event(GUI::PaintEvent& event) void ImageEditor::paint_event(GUI::PaintEvent& event)
{ {
GUI::Frame::paint_event(event); GUI::Frame::paint_event(event);
@ -678,12 +693,6 @@ void ImageEditor::image_did_change_rect(Gfx::IntRect const& new_image_rect)
update(m_editor_image_rect); update(m_editor_image_rect);
} }
void ImageEditor::image_did_change_title(String const& path)
{
if (on_image_title_change)
on_image_title_change(path);
}
void ImageEditor::image_select_layer(Layer* layer) void ImageEditor::image_select_layer(Layer* layer)
{ {
set_active_layer(layer); set_active_layer(layer);

View file

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org> * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
@ -45,6 +45,12 @@ public:
auto& undo_stack() { return m_undo_stack; } auto& undo_stack() { return m_undo_stack; }
String const& path() const { return m_path; }
void set_path(String);
String const& title() const { return m_title; }
void set_title(String);
void add_guide(NonnullRefPtr<Guide> guide) { m_guides.append(guide); } void add_guide(NonnullRefPtr<Guide> guide) { m_guides.append(guide); }
void remove_guide(Guide const& guide) void remove_guide(Guide const& guide)
{ {
@ -90,7 +96,7 @@ public:
Function<void(Layer*)> on_active_layer_change; Function<void(Layer*)> on_active_layer_change;
Function<void(String const&)> on_image_title_change; Function<void(String const&)> on_title_change;
Function<void(Gfx::IntPoint const&)> on_image_mouse_position_change; Function<void(Gfx::IntPoint const&)> on_image_mouse_position_change;
@ -139,7 +145,6 @@ private:
virtual void image_did_change(Gfx::IntRect const&) override; virtual void image_did_change(Gfx::IntRect const&) override;
virtual void image_did_change_rect(Gfx::IntRect const&) override; virtual void image_did_change_rect(Gfx::IntRect const&) override;
virtual void image_select_layer(Layer*) override; virtual void image_select_layer(Layer*) override;
virtual void image_did_change_title(String const&) override;
GUI::MouseEvent event_adjusted_for_layer(GUI::MouseEvent const&, Layer const&) const; GUI::MouseEvent event_adjusted_for_layer(GUI::MouseEvent const&, Layer const&) const;
GUI::MouseEvent event_with_pan_and_scale_applied(GUI::MouseEvent const&) const; GUI::MouseEvent event_with_pan_and_scale_applied(GUI::MouseEvent const&) const;
@ -155,6 +160,9 @@ private:
RefPtr<Layer> m_active_layer; RefPtr<Layer> m_active_layer;
GUI::UndoStack m_undo_stack; GUI::UndoStack m_undo_stack;
String m_path;
String m_title;
NonnullRefPtrVector<Guide> m_guides; NonnullRefPtrVector<Guide> m_guides;
bool m_show_guides { true }; bool m_show_guides { true };
bool m_show_rulers { true }; bool m_show_rulers { true };

View file

@ -1,6 +1,6 @@
/* /*
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2021, Mustafa Quraish <mustafa@serenityos.org> * Copyright (c) 2021-2022, Mustafa Quraish <mustafa@serenityos.org>
* Copyright (c) 2021-2022, Tobias Christiansen <tobyase@serenityos.org> * Copyright (c) 2021-2022, Tobias Christiansen <tobyase@serenityos.org>
* *
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
@ -108,10 +108,11 @@ void MainWidget::initialize_menubar(GUI::Window& window)
auto bg_layer = PixelPaint::Layer::try_create_with_size(*image, image->size(), "Background").release_value_but_fixme_should_propagate_errors(); auto bg_layer = PixelPaint::Layer::try_create_with_size(*image, image->size(), "Background").release_value_but_fixme_should_propagate_errors();
image->add_layer(*bg_layer); image->add_layer(*bg_layer);
bg_layer->bitmap().fill(Color::White); bg_layer->bitmap().fill(Color::White);
auto image_title = dialog->image_name().trim_whitespace();
image->set_title(image_title.is_empty() ? "Untitled" : image_title);
create_new_editor(*image); auto& editor = create_new_editor(*image);
auto image_title = dialog->image_name().trim_whitespace();
editor.set_title(image_title.is_empty() ? "Untitled" : image_title);
m_layer_list_widget->set_image(image); m_layer_list_widget->set_image(image);
m_layer_list_widget->set_selected_layer(bg_layer); m_layer_list_widget->set_selected_layer(bg_layer);
} }
@ -142,7 +143,7 @@ void MainWidget::initialize_menubar(GUI::Window& window)
GUI::MessageBox::show_error(&window, String::formatted("Could not save {}: {}", *save_result.chosen_file, result.error())); GUI::MessageBox::show_error(&window, String::formatted("Could not save {}: {}", *save_result.chosen_file, result.error()));
return; return;
} }
editor->image().set_path(*save_result.chosen_file); editor->set_path(*save_result.chosen_file);
editor->undo_stack().set_current_unmodified(); editor->undo_stack().set_current_unmodified();
}); });
@ -150,11 +151,11 @@ void MainWidget::initialize_menubar(GUI::Window& window)
auto* editor = current_image_editor(); auto* editor = current_image_editor();
if (!editor) if (!editor)
return; return;
if (editor->image().path().is_empty()) { if (editor->path().is_empty()) {
m_save_image_as_action->activate(); m_save_image_as_action->activate();
return; return;
} }
auto response = FileSystemAccessClient::Client::the().request_file(window.window_id(), editor->image().path(), Core::OpenMode::Truncate | Core::OpenMode::WriteOnly); auto response = FileSystemAccessClient::Client::the().request_file(window.window_id(), editor->path(), Core::OpenMode::Truncate | Core::OpenMode::WriteOnly);
if (response.error != 0) if (response.error != 0)
return; return;
auto result = editor->save_project_to_fd_and_close(*response.fd); auto result = editor->save_project_to_fd_and_close(*response.fd);
@ -709,7 +710,8 @@ void MainWidget::open_image_fd(int fd, String const& path)
} }
auto& image = *m_loader.release_image(); auto& image = *m_loader.release_image();
create_new_editor(image); auto& editor = create_new_editor(image);
editor.set_path(path);
m_layer_list_widget->set_image(&image); m_layer_list_widget->set_image(&image);
} }
@ -738,9 +740,10 @@ void MainWidget::create_image_from_clipboard()
auto image = PixelPaint::Image::try_create_with_size(bitmap->size()).release_value_but_fixme_should_propagate_errors(); auto image = PixelPaint::Image::try_create_with_size(bitmap->size()).release_value_but_fixme_should_propagate_errors();
auto layer = PixelPaint::Layer::try_create_with_bitmap(image, *bitmap, "Pasted layer").release_value_but_fixme_should_propagate_errors(); auto layer = PixelPaint::Layer::try_create_with_bitmap(image, *bitmap, "Pasted layer").release_value_but_fixme_should_propagate_errors();
image->add_layer(*layer); image->add_layer(*layer);
image->set_title("Untitled");
create_new_editor(*image); auto& editor = create_new_editor(*image);
editor.set_title("Untitled");
m_layer_list_widget->set_image(image); m_layer_list_widget->set_image(image);
m_layer_list_widget->set_selected_layer(layer); m_layer_list_widget->set_selected_layer(layer);
} }
@ -752,7 +755,7 @@ bool MainWidget::request_close()
VERIFY(current_image_editor()); VERIFY(current_image_editor());
auto result = GUI::MessageBox::ask_about_unsaved_changes(window(), current_image_editor()->image().path(), current_image_editor()->undo_stack().last_unmodified_timestamp()); auto result = GUI::MessageBox::ask_about_unsaved_changes(window(), current_image_editor()->path(), current_image_editor()->undo_stack().last_unmodified_timestamp());
if (result == GUI::MessageBox::ExecYes) { if (result == GUI::MessageBox::ExecYes) {
m_save_image_action->activate(); m_save_image_action->activate();
@ -783,7 +786,7 @@ ImageEditor& MainWidget::create_new_editor(NonnullRefPtr<Image> image)
m_layer_properties_widget->set_layer(layer); m_layer_properties_widget->set_layer(layer);
}; };
image_editor.on_image_title_change = [&](auto const& title) { image_editor.on_title_change = [&](auto const& title) {
m_tab_widget->set_tab_title(image_editor, title); m_tab_widget->set_tab_title(image_editor, title);
}; };
@ -809,9 +812,6 @@ ImageEditor& MainWidget::create_new_editor(NonnullRefPtr<Image> image)
m_show_rulers_action->set_checked(show_rulers); m_show_rulers_action->set_checked(show_rulers);
}; };
// NOTE: We invoke the above hook directly here to make sure the tab title is set up.
image_editor.on_image_title_change(image->title());
image_editor.on_scale_changed = [this](float scale) { image_editor.on_scale_changed = [this](float scale) {
m_zoom_combobox->set_text(String::formatted("{}%", roundf(scale * 100))); m_zoom_combobox->set_text(String::formatted("{}%", roundf(scale * 100)));
}; };

View file

@ -35,7 +35,6 @@ ErrorOr<void> ProjectLoader::try_load_from_fd_and_close(int fd, StringView path)
auto bitmap = TRY(Image::try_decode_bitmap(mapped_file->bytes())); auto bitmap = TRY(Image::try_decode_bitmap(mapped_file->bytes()));
auto image = TRY(Image::try_create_from_bitmap(move(bitmap))); auto image = TRY(Image::try_create_from_bitmap(move(bitmap)));
image->set_path(path);
m_image = image; m_image = image;
return {}; return {};
} }
@ -44,8 +43,6 @@ ErrorOr<void> ProjectLoader::try_load_from_fd_and_close(int fd, StringView path)
auto& json = json_or_error.value().as_object(); auto& json = json_or_error.value().as_object();
auto image = TRY(Image::try_create_from_pixel_paint_json(json)); auto image = TRY(Image::try_create_from_pixel_paint_json(json));
image->set_path(path);
if (json.has("guides")) if (json.has("guides"))
m_json_metadata = json.get("guides").as_array(); m_json_metadata = json.get("guides").as_array();