mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-12-04 05:20:30 +00:00
FontEditor: Allow application to launch without a font
Since LibFSAC requires a reified window before loading a font, it makes sense to have a safe null state for the app. This lets us stay alive after a failed file request on startup, handle failure at any point during initialization, and claw back memory from all our font RefPtrs. A default startup font or none at all can now be set in FontEditor.ini
This commit is contained in:
parent
aaf60053f1
commit
7fa8fae786
Notes:
sideshowbarker
2024-07-17 05:01:20 +09:00
Author: https://github.com/thankyouverycool Commit: https://github.com/SerenityOS/serenity/commit/7fa8fae786 Pull-request: https://github.com/SerenityOS/serenity/pull/18764 Reviewed-by: https://github.com/caoimhebyrne ✅
5 changed files with 127 additions and 20 deletions
2
Base/home/anon/.config/FontEditor.ini
Normal file
2
Base/home/anon/.config/FontEditor.ini
Normal file
|
@ -0,0 +1,2 @@
|
|||
[Defaults]
|
||||
Font=/res/fonts/KaticaRegular10.font
|
|
@ -23,10 +23,13 @@
|
|||
|
||||
@FontEditor::GlyphEditorWidget {
|
||||
name: "glyph_editor_widget"
|
||||
visible: false
|
||||
}
|
||||
|
||||
@GUI::Widget {
|
||||
name: "width_control_container"
|
||||
preferred_height: "shrink"
|
||||
visible: false
|
||||
layout: @GUI::VerticalBoxLayout {}
|
||||
|
||||
@GUI::SpinBox {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "GlyphEditorWidget.h"
|
||||
#include "NewFontDialog.h"
|
||||
#include <AK/Array.h>
|
||||
#include <AK/ScopeGuard.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/StringUtils.h>
|
||||
|
@ -230,9 +231,9 @@ ErrorOr<void> MainWidget::create_actions()
|
|||
m_show_unicode_blocks_action = GUI::Action::create_checkable("&Unicode Blocks", { Mod_Ctrl, Key_U }, [this](auto& action) {
|
||||
m_unicode_block_container->set_visible(action.is_checked());
|
||||
if (action.is_checked())
|
||||
m_search_textbox->set_focus(true);
|
||||
m_search_textbox->set_focus(m_initialized);
|
||||
else
|
||||
m_glyph_map_widget->set_focus(true);
|
||||
m_glyph_map_widget->set_focus(m_initialized);
|
||||
Config::write_bool("FontEditor"sv, "Layout"sv, "ShowUnicodeBlocks"sv, action.is_checked());
|
||||
});
|
||||
m_show_unicode_blocks_action->set_checked(show_unicode_blocks);
|
||||
|
@ -463,6 +464,7 @@ ErrorOr<void> MainWidget::create_widgets()
|
|||
m_font_metadata_groupbox = find_descendant_of_type_named<GUI::GroupBox>("font_metadata_groupbox");
|
||||
m_unicode_block_container = find_descendant_of_type_named<GUI::Widget>("unicode_block_container");
|
||||
m_toolbar_container = find_descendant_of_type_named<GUI::ToolbarContainer>("toolbar_container");
|
||||
m_width_control_container = find_descendant_of_type_named<GUI::Widget>("width_control_container");
|
||||
|
||||
m_glyph_map_widget = find_descendant_of_type_named<GUI::GlyphMapWidget>("glyph_map_widget");
|
||||
m_glyph_editor_widget = find_descendant_of_type_named<GlyphEditorWidget>("glyph_editor_widget");
|
||||
|
@ -637,19 +639,24 @@ ErrorOr<void> MainWidget::initialize(StringView path, RefPtr<Gfx::BitmapFont>&&
|
|||
if (m_font == mutable_font)
|
||||
return {};
|
||||
|
||||
TRY(m_glyph_map_widget->initialize(mutable_font));
|
||||
ScopeGuard reset_on_error([&] {
|
||||
if (!m_initialized)
|
||||
reset();
|
||||
});
|
||||
|
||||
m_initialized = false;
|
||||
m_path = TRY(String::from_utf8(path));
|
||||
m_font = move(mutable_font);
|
||||
|
||||
TRY(m_glyph_map_widget->initialize(m_font));
|
||||
auto active_glyph = m_glyph_map_widget->active_glyph();
|
||||
m_glyph_map_widget->set_focus(true);
|
||||
m_glyph_map_widget->scroll_to_glyph(active_glyph);
|
||||
|
||||
auto selection = m_glyph_map_widget->selection().normalized();
|
||||
m_undo_selection = TRY(try_make_ref_counted<UndoSelection>(selection.start(), selection.size(), active_glyph, *mutable_font, *m_glyph_map_widget));
|
||||
m_undo_selection = TRY(try_make_ref_counted<UndoSelection>(selection.start(), selection.size(), active_glyph, *m_font, *m_glyph_map_widget));
|
||||
m_undo_stack->clear();
|
||||
|
||||
m_path = TRY(String::from_utf8(path));
|
||||
m_font = mutable_font;
|
||||
|
||||
if (m_preview_label)
|
||||
m_preview_label->set_font(*m_font);
|
||||
|
||||
|
@ -692,6 +699,9 @@ ErrorOr<void> MainWidget::initialize(StringView path, RefPtr<Gfx::BitmapFont>&&
|
|||
window()->set_modified(false);
|
||||
update_title();
|
||||
update_statusbar();
|
||||
set_actions_enabled(true);
|
||||
set_widgets_enabled(true);
|
||||
m_initialized = true;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -881,6 +891,9 @@ void MainWidget::did_modify_font()
|
|||
|
||||
void MainWidget::update_statusbar()
|
||||
{
|
||||
if (!m_font)
|
||||
return;
|
||||
|
||||
if (!m_statusbar->is_visible())
|
||||
return;
|
||||
|
||||
|
@ -1073,4 +1086,88 @@ void MainWidget::show_error(Error error, StringView action, StringView basename)
|
|||
(void)GUI::MessageBox::try_show_error(window(), maybe_message.release_value());
|
||||
}
|
||||
|
||||
void MainWidget::reset()
|
||||
{
|
||||
VERIFY(window());
|
||||
|
||||
m_initialized = false;
|
||||
m_font = nullptr;
|
||||
m_path = {};
|
||||
m_undo_selection = nullptr;
|
||||
m_undo_stack->clear();
|
||||
|
||||
(void)m_glyph_map_widget->initialize(nullptr);
|
||||
m_glyph_editor_widget->initialize(nullptr);
|
||||
|
||||
if (m_font_preview_window)
|
||||
m_font_preview_window->close();
|
||||
if (m_preview_label)
|
||||
m_preview_label->set_font(nullptr);
|
||||
|
||||
m_name_textbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_family_textbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_slope_combobox->set_text({}, GUI::AllowCallback::No);
|
||||
m_weight_combobox->set_text({}, GUI::AllowCallback::No);
|
||||
m_presentation_spinbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_baseline_spinbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_mean_line_spinbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_spacing_spinbox->set_text({}, GUI::AllowCallback::No);
|
||||
m_fixed_width_checkbox->set_checked(false, GUI::AllowCallback::No);
|
||||
m_statusbar->set_text(0, {});
|
||||
m_statusbar->set_text(1, {});
|
||||
|
||||
window()->set_modified(false);
|
||||
window()->set_title("Font Editor");
|
||||
set_actions_enabled(false);
|
||||
set_widgets_enabled(false);
|
||||
set_focus(true);
|
||||
}
|
||||
|
||||
void MainWidget::set_actions_enabled(bool enabled)
|
||||
{
|
||||
m_save_action->set_enabled(enabled);
|
||||
m_save_as_action->set_enabled(enabled);
|
||||
|
||||
m_cut_action->set_enabled(enabled);
|
||||
m_copy_action->set_enabled(enabled);
|
||||
m_paste_action->set_enabled(enabled && GUI::Clipboard::the().fetch_mime_type() == "glyph/x-fonteditor");
|
||||
m_delete_action->set_enabled(enabled);
|
||||
|
||||
m_copy_text_action->set_enabled(enabled);
|
||||
m_select_all_action->set_enabled(enabled);
|
||||
|
||||
m_go_to_glyph_action->set_enabled(enabled);
|
||||
m_previous_glyph_action->set_enabled(enabled);
|
||||
m_next_glyph_action->set_enabled(enabled);
|
||||
|
||||
m_move_glyph_action->set_enabled(enabled);
|
||||
m_paint_glyph_action->set_enabled(enabled);
|
||||
|
||||
m_flip_horizontal_action->set_enabled(enabled);
|
||||
m_flip_vertical_action->set_enabled(enabled);
|
||||
m_rotate_clockwise_action->set_enabled(enabled);
|
||||
m_rotate_counterclockwise_action->set_enabled(enabled);
|
||||
|
||||
m_open_preview_action->set_enabled(enabled);
|
||||
m_highlight_modifications_action->set_enabled(enabled);
|
||||
m_show_system_emoji_action->set_enabled(enabled);
|
||||
|
||||
m_scale_five_action->set_enabled(enabled);
|
||||
m_scale_ten_action->set_enabled(enabled);
|
||||
m_scale_fifteen_action->set_enabled(enabled);
|
||||
}
|
||||
|
||||
void MainWidget::set_widgets_enabled(bool enabled)
|
||||
{
|
||||
m_font_metadata_groupbox->set_enabled(enabled);
|
||||
m_unicode_block_container->set_enabled(enabled);
|
||||
m_width_control_container->set_enabled(enabled);
|
||||
m_width_control_container->set_visible(enabled);
|
||||
|
||||
m_glyph_map_widget->set_enabled(enabled);
|
||||
m_glyph_editor_widget->set_enabled(enabled);
|
||||
m_glyph_editor_widget->set_visible(enabled);
|
||||
m_statusbar->segment(1).set_visible(enabled);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,6 +29,9 @@ public:
|
|||
|
||||
virtual ~MainWidget() override = default;
|
||||
|
||||
void show_error(Error, StringView action, StringView basename = {});
|
||||
void reset();
|
||||
|
||||
ErrorOr<void> initialize(StringView path, RefPtr<Gfx::BitmapFont>&&);
|
||||
ErrorOr<void> initialize_menubar(GUI::Window&);
|
||||
|
||||
|
@ -61,6 +64,8 @@ private:
|
|||
void update_title();
|
||||
|
||||
void set_scale_and_save(i32);
|
||||
void set_actions_enabled(bool);
|
||||
void set_widgets_enabled(bool);
|
||||
|
||||
ErrorOr<void> copy_selected_glyphs();
|
||||
ErrorOr<void> cut_selected_glyphs();
|
||||
|
@ -70,8 +75,6 @@ private:
|
|||
void push_undo();
|
||||
void reset_selection_and_push_undo();
|
||||
|
||||
void show_error(Error, StringView action, StringView basename = {});
|
||||
|
||||
RefPtr<GUI::GlyphMapWidget> m_glyph_map_widget;
|
||||
RefPtr<GlyphEditorWidget> m_glyph_editor_widget;
|
||||
|
||||
|
@ -122,6 +125,7 @@ private:
|
|||
RefPtr<GUI::Statusbar> m_statusbar;
|
||||
RefPtr<GUI::ToolbarContainer> m_toolbar_container;
|
||||
RefPtr<GUI::Widget> m_unicode_block_container;
|
||||
RefPtr<GUI::Widget> m_width_control_container;
|
||||
RefPtr<GUI::ComboBox> m_weight_combobox;
|
||||
RefPtr<GUI::ComboBox> m_slope_combobox;
|
||||
RefPtr<GUI::SpinBox> m_spacing_spinbox;
|
||||
|
@ -150,6 +154,7 @@ private:
|
|||
Vector<String> m_font_slope_list;
|
||||
Vector<String> m_unicode_block_list;
|
||||
Unicode::CodePointRange m_range { 0x0000, 0x10FFFF };
|
||||
bool m_initialized { false };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include <LibGUI/Application.h>
|
||||
#include <LibGUI/Icon.h>
|
||||
#include <LibGUI/Window.h>
|
||||
#include <LibGfx/Font/BitmapFont.h>
|
||||
#include <LibMain/Main.h>
|
||||
|
||||
ErrorOr<int> serenity_main(Main::Arguments arguments)
|
||||
|
@ -47,6 +46,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
auto font_editor = TRY(window->set_main_widget<FontEditor::MainWidget>());
|
||||
TRY(font_editor->initialize_menubar(*window));
|
||||
font_editor->reset();
|
||||
|
||||
window->on_close_request = [&]() -> GUI::Window::CloseRequestDecision {
|
||||
if (font_editor->request_close())
|
||||
|
@ -56,16 +56,16 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
|
|||
|
||||
window->show();
|
||||
|
||||
auto path_to_load = path.is_empty() ? "/res/fonts/KaticaRegular10.font"sv : path;
|
||||
auto file = TRY(FileSystemAccessClient::Client::the().request_file_read_only_approved(window, path_to_load));
|
||||
|
||||
if (!path.is_empty()) {
|
||||
TRY(font_editor->open_file(file.filename(), file.release_stream()));
|
||||
} else {
|
||||
auto mapped_file = TRY(Core::MappedFile::map_from_file(file.release_stream(), path_to_load));
|
||||
auto mutable_font = TRY(TRY(Gfx::BitmapFont::try_load_from_mapped_file(mapped_file))->unmasked_character_set());
|
||||
TRY(font_editor->initialize({}, move(mutable_font)));
|
||||
}
|
||||
auto default_path = TRY(String::from_deprecated_string(Config::read_string("FontEditor"sv, "Defaults"sv, "Font"sv, {})));
|
||||
auto path_to_load = path.is_empty() ? default_path : path;
|
||||
auto open_or_error = [&]() -> ErrorOr<void> {
|
||||
if (path_to_load.is_empty())
|
||||
return {};
|
||||
auto file = TRY(FileSystemAccessClient::Client::the().request_file_read_only_approved(window, path_to_load));
|
||||
return TRY(font_editor->open_file(path, file.release_stream()));
|
||||
}();
|
||||
if (open_or_error.is_error())
|
||||
font_editor->show_error(open_or_error.release_error(), "Opening"sv, path_to_load);
|
||||
|
||||
return app->exec();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue