summaryrefslogtreecommitdiff
path: root/Userland/Applications/FontEditor
diff options
context:
space:
mode:
authorthankyouverycool <66646555+thankyouverycool@users.noreply.github.com>2021-04-22 14:12:53 -0400
committerAndreas Kling <kling@serenityos.org>2021-04-23 11:08:11 +0200
commit44cd121e30959efb7bdfd6de9440164b9fd7b955 (patch)
tree98454bf797fabfe018da633ae9ebd64875ef94a7 /Userland/Applications/FontEditor
parent2785e12b767c8021e9dbf3383cfab2e2b5a5a30f (diff)
downloadserenity-44cd121e30959efb7bdfd6de9440164b9fd7b955.zip
FontEditor: Add undo and redo commands
Diffstat (limited to 'Userland/Applications/FontEditor')
-rw-r--r--Userland/Applications/FontEditor/CMakeLists.txt1
-rw-r--r--Userland/Applications/FontEditor/FontEditor.cpp61
-rw-r--r--Userland/Applications/FontEditor/FontEditor.h13
-rw-r--r--Userland/Applications/FontEditor/GlyphEditorWidget.cpp9
-rw-r--r--Userland/Applications/FontEditor/GlyphEditorWidget.h1
-rw-r--r--Userland/Applications/FontEditor/UndoGlyph.h65
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;
+};