diff options
author | thankyouverycool <66646555+thankyouverycool@users.noreply.github.com> | 2021-04-22 14:12:53 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-23 11:08:11 +0200 |
commit | 44cd121e30959efb7bdfd6de9440164b9fd7b955 (patch) | |
tree | 98454bf797fabfe018da633ae9ebd64875ef94a7 /Userland/Applications/FontEditor | |
parent | 2785e12b767c8021e9dbf3383cfab2e2b5a5a30f (diff) | |
download | serenity-44cd121e30959efb7bdfd6de9440164b9fd7b955.zip |
FontEditor: Add undo and redo commands
Diffstat (limited to 'Userland/Applications/FontEditor')
-rw-r--r-- | Userland/Applications/FontEditor/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Applications/FontEditor/FontEditor.cpp | 61 | ||||
-rw-r--r-- | Userland/Applications/FontEditor/FontEditor.h | 13 | ||||
-rw-r--r-- | Userland/Applications/FontEditor/GlyphEditorWidget.cpp | 9 | ||||
-rw-r--r-- | Userland/Applications/FontEditor/GlyphEditorWidget.h | 1 | ||||
-rw-r--r-- | Userland/Applications/FontEditor/UndoGlyph.h | 65 |
6 files changed, 149 insertions, 1 deletions
diff --git a/Userland/Applications/FontEditor/CMakeLists.txt b/Userland/Applications/FontEditor/CMakeLists.txt index 80d30b66b6..69f67b12ab 100644 --- a/Userland/Applications/FontEditor/CMakeLists.txt +++ b/Userland/Applications/FontEditor/CMakeLists.txt @@ -12,6 +12,7 @@ set(SOURCES NewFontDialog.cpp NewFontDialogPage1GML.h NewFontDialogPage2GML.h + UndoGlyph.h ) serenity_app(FontEditor ICON app-font-editor) diff --git a/Userland/Applications/FontEditor/FontEditor.cpp b/Userland/Applications/FontEditor/FontEditor.cpp index 7c02daeb89..cd25307adb 100644 --- a/Userland/Applications/FontEditor/FontEditor.cpp +++ b/Userland/Applications/FontEditor/FontEditor.cpp @@ -236,6 +236,14 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::BitmapFont>&& m_glyph_editor_width_spinbox->set_value(glyph_width); m_glyph_editor_present_checkbox->set_checked(glyph_width > 0); }); + m_undo_action = GUI::CommonActions::make_undo_action([&](auto&) { + undo(); + }); + m_undo_action->set_enabled(false); + m_redo_action = GUI::CommonActions::make_redo_action([&](auto&) { + redo(); + }); + m_redo_action->set_enabled(false); m_open_preview_action = GUI::Action::create("&Preview Font", { Mod_Ctrl, Key_P }, Gfx::Bitmap::load_from_file("/res/icons/16x16/find.png"), [&](auto&) { if (!m_font_preview_window) m_font_preview_window = create_font_preview_window(*this); @@ -259,6 +267,9 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::BitmapFont>&& toolbar.add_action(*m_paste_action); toolbar.add_action(*m_delete_action); toolbar.add_separator(); + toolbar.add_action(*m_undo_action); + toolbar.add_action(*m_redo_action); + toolbar.add_separator(); toolbar.add_action(*m_open_preview_action); m_scale_five_action = GUI::Action::create_checkable("500%", { Mod_Ctrl, Key_1 }, [&](auto&) { @@ -297,7 +308,16 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::BitmapFont>&& update_demo(); }; - m_glyph_map_widget->on_glyph_selected = [&](int glyph) { + m_glyph_editor_widget->on_undo_event = [this](bool finalize) { + m_undo_stack->push(make<GlyphUndoCommand>(*m_undo_glyph)); + if (finalize) + m_undo_stack->finalize_current_combo(); + did_change_undo_stack(); + }; + + m_glyph_map_widget->on_glyph_selected = [&, update_statusbar](int glyph) { + if (m_undo_glyph) + m_undo_glyph->set_code_point(glyph); m_glyph_editor_widget->set_glyph(glyph); auto glyph_width = m_edited_font->raw_glyph_width(m_glyph_map_widget->selected_glyph()); m_glyph_editor_width_spinbox->set_value(glyph_width); @@ -447,6 +467,10 @@ void FontEditorWidget::initialize(const String& path, RefPtr<Gfx::BitmapFont>&& m_glyph_map_widget->scroll_to_glyph(m_glyph_map_widget->selected_glyph()); }); + m_undo_stack = make<GUI::UndoStack>(); + m_undo_glyph = adopt(*new UndoGlyph(m_glyph_map_widget->selected_glyph(), *m_edited_font)); + did_change_undo_stack(); + if (on_initialize) on_initialize(); } @@ -464,6 +488,9 @@ void FontEditorWidget::initialize_menubar(GUI::Menubar& menubar) })); auto& edit_menu = menubar.add_menu("&Edit"); + edit_menu.add_action(*m_undo_action); + edit_menu.add_action(*m_redo_action); + edit_menu.add_separator(); edit_menu.add_action(*m_cut_action); edit_menu.add_action(*m_copy_action); edit_menu.add_action(*m_paste_action); @@ -504,3 +531,35 @@ void FontEditorWidget::set_show_font_metadata(bool show) m_font_metadata = show; m_font_metadata_groupbox->set_visible(m_font_metadata); } + +void FontEditorWidget::undo() +{ + if (!m_undo_stack->can_undo()) + return; + m_undo_stack->undo(); + did_change_undo_stack(); + + m_glyph_editor_widget->update(); + m_glyph_map_widget->update(); + if (m_font_preview_window) + m_font_preview_window->update(); +} + +void FontEditorWidget::redo() +{ + if (!m_undo_stack->can_redo()) + return; + m_undo_stack->redo(); + did_change_undo_stack(); + + m_glyph_editor_widget->update(); + m_glyph_map_widget->update(); + if (m_font_preview_window) + m_font_preview_window->update(); +} + +void FontEditorWidget::did_change_undo_stack() +{ + m_undo_action->set_enabled(m_undo_stack->can_undo()); + m_redo_action->set_enabled(m_undo_stack->can_redo()); +} diff --git a/Userland/Applications/FontEditor/FontEditor.h b/Userland/Applications/FontEditor/FontEditor.h index faabc62151..0e407a6786 100644 --- a/Userland/Applications/FontEditor/FontEditor.h +++ b/Userland/Applications/FontEditor/FontEditor.h @@ -6,6 +6,9 @@ #pragma once +#include "UndoGlyph.h" +#include <LibGUI/ActionGroup.h> +#include <LibGUI/UndoStack.h> #include <LibGUI/Widget.h> #include <LibGfx/BitmapFont.h> @@ -31,6 +34,11 @@ public: private: FontEditorWidget(const String& path, RefPtr<Gfx::BitmapFont>&&); + + void undo(); + void redo(); + void did_change_undo_stack(); + RefPtr<Gfx::BitmapFont> m_edited_font; RefPtr<GlyphMapWidget> m_glyph_map_widget; @@ -46,6 +54,11 @@ private: RefPtr<GUI::Action> m_paste_action; RefPtr<GUI::Action> m_delete_action; + RefPtr<GUI::Action> m_undo_action; + RefPtr<GUI::Action> m_redo_action; + RefPtr<UndoGlyph> m_undo_glyph; + OwnPtr<GUI::UndoStack> m_undo_stack; + RefPtr<GUI::Action> m_open_preview_action; RefPtr<GUI::Action> m_show_metadata_action; diff --git a/Userland/Applications/FontEditor/GlyphEditorWidget.cpp b/Userland/Applications/FontEditor/GlyphEditorWidget.cpp index 6a86f4a491..48f278933c 100644 --- a/Userland/Applications/FontEditor/GlyphEditorWidget.cpp +++ b/Userland/Applications/FontEditor/GlyphEditorWidget.cpp @@ -34,10 +34,14 @@ void GlyphEditorWidget::set_glyph(int glyph) void GlyphEditorWidget::delete_glyph() { + if (on_undo_event) + on_undo_event(false); auto bitmap = font().glyph(m_glyph).glyph_bitmap(); for (int x = 0; x < bitmap.width(); x++) for (int y = 0; y < bitmap.height(); y++) bitmap.set_bit_at(x, y, false); + if (on_undo_event) + on_undo_event(true); if (on_glyph_altered) on_glyph_altered(m_glyph); update(); @@ -82,6 +86,9 @@ void GlyphEditorWidget::paste_glyph() if (!mime_type.starts_with("glyph/")) return; + if (on_undo_event) + on_undo_event(false); + auto byte_buffer = GUI::Clipboard::the().data(); auto buffer_height = GUI::Clipboard::the().data_and_type().metadata.get("height").value().to_int(); auto buffer_width = GUI::Clipboard::the().data_and_type().metadata.get("width").value().to_int(); @@ -102,6 +109,8 @@ void GlyphEditorWidget::paste_glyph() bitmap.set_bit_at(x, y, bits[x][y]); } } + if (on_undo_event) + on_undo_event(true); if (on_glyph_altered) on_glyph_altered(m_glyph); update(); diff --git a/Userland/Applications/FontEditor/GlyphEditorWidget.h b/Userland/Applications/FontEditor/GlyphEditorWidget.h index 0fa62b9ac7..b64f4d8e06 100644 --- a/Userland/Applications/FontEditor/GlyphEditorWidget.h +++ b/Userland/Applications/FontEditor/GlyphEditorWidget.h @@ -35,6 +35,7 @@ public: void set_scale(int scale); Function<void(int)> on_glyph_altered; + Function<void(bool finalize)> on_undo_event; private: GlyphEditorWidget() {}; diff --git a/Userland/Applications/FontEditor/UndoGlyph.h b/Userland/Applications/FontEditor/UndoGlyph.h new file mode 100644 index 0000000000..c09e51d254 --- /dev/null +++ b/Userland/Applications/FontEditor/UndoGlyph.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibGUI/Command.h> +#include <LibGUI/UndoStack.h> +#include <LibGfx/BitmapFont.h> + +class UndoGlyph : public RefCounted<UndoGlyph> { +public: + explicit UndoGlyph(const size_t code_point, const Gfx::BitmapFont& font) + : m_code_point(code_point) + , m_font(font) + { + } + RefPtr<UndoGlyph> save_state() const + { + auto state = adopt(*new UndoGlyph(m_code_point, *m_font)); + auto glyph = font().glyph(m_code_point).glyph_bitmap(); + for (int x = 0; x < glyph.width(); x++) + for (int y = 0; y < glyph.height(); y++) + state->m_bits[x][y] = glyph.bit_at(x, y); + return state; + } + void restore_state(const UndoGlyph& state) const + { + auto bitmap = font().glyph(state.m_code_point).glyph_bitmap(); + for (int x = 0; x < bitmap.width(); x++) + for (int y = 0; y < bitmap.height(); y++) + bitmap.set_bit_at(x, y, state.m_bits[x][y]); + } + void set_code_point(size_t point) { m_code_point = point; } + void set_font(Gfx::BitmapFont& font) { m_font = font; } + const Gfx::BitmapFont& font() const { return *m_font; } + +private: + size_t m_code_point; + RefPtr<Gfx::BitmapFont> m_font; + u8 m_bits[32][36] = {}; +}; + +class GlyphUndoCommand : public GUI::Command { +public: + GlyphUndoCommand(UndoGlyph& glyph) + : m_state(glyph.save_state()) + , m_undo_glyph(glyph) + { + } + virtual void undo() override + { + m_undo_glyph.restore_state(*m_state); + } + virtual void redo() override + { + undo(); + } + +private: + RefPtr<UndoGlyph> m_state; + UndoGlyph& m_undo_glyph; +}; |