FontEditor: Add a ListView to sort glyphs by their Unicode block

This commit is contained in:
thankyouverycool 2022-02-13 15:18:39 -05:00 committed by Tim Flynn
parent 6704bc0072
commit aefb2bcf43
Notes: sideshowbarker 2024-07-17 18:45:32 +09:00
4 changed files with 210 additions and 151 deletions

View file

@ -9,6 +9,7 @@
#include "GlyphEditorWidget.h"
#include "NewFontDialog.h"
#include <AK/StringBuilder.h>
#include <AK/StringUtils.h>
#include <Applications/FontEditor/FontEditorWindowGML.h>
#include <LibConfig/Client.h>
#include <LibDesktop/Launcher.h>
@ -24,6 +25,7 @@
#include <LibGUI/InputBox.h>
#include <LibGUI/ItemListModel.h>
#include <LibGUI/Label.h>
#include <LibGUI/ListView.h>
#include <LibGUI/Menu.h>
#include <LibGUI/Menubar.h>
#include <LibGUI/MessageBox.h>
@ -39,7 +41,6 @@
#include <LibGfx/Palette.h>
#include <LibGfx/TextDirection.h>
#include <LibUnicode/CharacterTypes.h>
#include <stdlib.h>
static constexpr int s_pangram_count = 8;
static char const* pangrams[s_pangram_count] = {
@ -132,6 +133,7 @@ FontEditorWidget::FontEditorWidget()
m_baseline_spinbox = *find_descendant_of_type_named<GUI::SpinBox>("baseline_spinbox");
m_fixed_width_checkbox = *find_descendant_of_type_named<GUI::CheckBox>("fixed_width_checkbox");
m_font_metadata_groupbox = *find_descendant_of_type_named<GUI::GroupBox>("font_metadata_groupbox");
m_unicode_block_listview = *find_descendant_of_type_named<GUI::ListView>("unicode_block_listview");
m_glyph_editor_widget = m_glyph_editor_container->add<GlyphEditorWidget>();
m_glyph_map_widget = glyph_map_container.add<GUI::GlyphMapWidget>();
@ -210,11 +212,19 @@ FontEditorWidget::FontEditorWidget()
});
m_show_metadata_action->set_checked(true);
m_show_metadata_action->set_status_tip("Show or hide metadata about the current font");
m_show_unicode_blocks_action = GUI::Action::create_checkable("&Unicode Blocks", { Mod_Ctrl, Key_U }, [&](auto& action) {
set_show_unicode_blocks(action.is_checked());
});
m_show_unicode_blocks_action->set_checked(true);
m_show_unicode_blocks_action->set_status_tip("Show or hide the Unicode block list");
m_go_to_glyph_action = GUI::Action::create("&Go to Glyph...", { Mod_Ctrl, Key_G }, Gfx::Bitmap::try_load_from_file("/res/icons/16x16/go-to.png").release_value_but_fixme_should_propagate_errors(), [&](auto&) {
String input;
if (GUI::InputBox::show(window(), input, "Hexadecimal:", "Go to Glyph") == GUI::InputBox::ExecOK && !input.is_empty()) {
int code_point = strtoul(&input[0], nullptr, 16);
code_point = clamp(code_point, 0x0000, 0x10FFFF);
if (GUI::InputBox::show(window(), input, "Hexadecimal:", "Go to glyph") == GUI::InputBox::ExecOK && !input.is_empty()) {
auto maybe_code_point = AK::StringUtils::convert_to_uint_from_hex(input);
if (!maybe_code_point.has_value())
return;
auto code_point = maybe_code_point.value();
code_point = clamp(code_point, m_range.first, m_range.last);
m_glyph_map_widget->set_focus(true);
m_glyph_map_widget->set_active_glyph(code_point);
m_glyph_map_widget->scroll_to_glyph(code_point);
@ -424,6 +434,25 @@ FontEditorWidget::FontEditorWidget()
did_modify_font();
};
auto unicode_blocks = Unicode::block_display_names();
m_unicode_block_listview->on_activation = [this, unicode_blocks](auto& index) {
if (index.row() > 0)
m_range = unicode_blocks[index.row() - 1].code_point_range;
else
m_range = { 0x0000, 0x10FFFF };
m_glyph_map_widget->set_active_range(m_range);
};
m_unicode_block_list.append("Show All");
for (auto& block : unicode_blocks)
m_unicode_block_list.append(block.display_name);
m_unicode_block_model = GUI::ItemListModel<String>::create(m_unicode_block_list);
m_unicode_block_listview->set_model(*m_unicode_block_model);
m_unicode_block_listview->set_activates_on_selection(true);
m_unicode_block_listview->horizontal_scrollbar().set_visible(false);
m_unicode_block_listview->set_cursor(m_unicode_block_model->index(0, 0), GUI::AbstractView::SelectionUpdate::Set);
GUI::Application::the()->on_action_enter = [this](GUI::Action& action) {
auto text = action.status_tip();
if (text.is_empty())
@ -543,6 +572,7 @@ void FontEditorWidget::initialize_menubar(GUI::Window& window)
view_menu.add_action(*m_open_preview_action);
view_menu.add_separator();
view_menu.add_action(*m_show_metadata_action);
view_menu.add_action(*m_show_unicode_blocks_action);
view_menu.add_separator();
auto& scale_menu = view_menu.add_submenu("&Scale");
scale_menu.add_action(*m_scale_five_action);
@ -579,6 +609,14 @@ void FontEditorWidget::set_show_font_metadata(bool show)
m_font_metadata_groupbox->set_visible(m_font_metadata);
}
void FontEditorWidget::set_show_unicode_blocks(bool show)
{
if (m_unicode_blocks == show)
return;
m_unicode_blocks = show;
m_unicode_block_listview->set_visible(m_unicode_blocks);
}
bool FontEditorWidget::open_file(String const& path)
{
auto bitmap_font = Gfx::BitmapFont::load_from_file(path);

View file

@ -35,7 +35,10 @@ public:
void initialize_menubar(GUI::Window&);
bool is_showing_font_metadata() { return m_font_metadata; }
void set_show_font_metadata(bool b);
void set_show_font_metadata(bool);
bool is_showing_unicode_blocks() { return m_unicode_blocks; }
void set_show_unicode_blocks(bool);
Function<void()> on_initialize;
@ -87,6 +90,7 @@ private:
RefPtr<GUI::Action> m_open_preview_action;
RefPtr<GUI::Action> m_show_metadata_action;
RefPtr<GUI::Action> m_show_unicode_blocks_action;
GUI::ActionGroup m_glyph_editor_scale_actions;
RefPtr<GUI::Action> m_scale_five_action;
@ -119,9 +123,14 @@ private:
RefPtr<GUI::TextBox> m_family_textbox;
RefPtr<GUI::CheckBox> m_fixed_width_checkbox;
RefPtr<GUI::GroupBox> m_font_metadata_groupbox;
RefPtr<GUI::ListView> m_unicode_block_listview;
RefPtr<GUI::Model> m_unicode_block_model;
String m_path;
Vector<String> m_font_weight_list;
Vector<String> m_font_slope_list;
Vector<String> m_unicode_block_list;
bool m_font_metadata { true };
bool m_unicode_blocks { true };
Unicode::CodePointRange m_range { 0x0000, 0x10FFFF };
};

View file

@ -58,159 +58,171 @@
spacing: 6
}
@GUI::Widget {
name: "glyph_map_container"
layout: @GUI::VerticalBoxLayout {}
}
@GUI::GroupBox {
name: "font_metadata_groupbox"
title: "Metadata"
shrink_to_fit: true
layout: @GUI::VerticalBoxLayout {
margins: [6, 6, 6, 6]
}
@GUI::HorizontalSplitter {
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
layout: @GUI::VerticalBoxLayout {}
@GUI::Label {
name: "name_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Name:"
@GUI::Widget {
name: "glyph_map_container"
layout: @GUI::VerticalBoxLayout {}
}
@GUI::TextBox {
name: "name_textbox"
@GUI::GroupBox {
name: "font_metadata_groupbox"
title: "Metadata"
shrink_to_fit: true
layout: @GUI::VerticalBoxLayout {
margins: [6, 6, 6, 6]
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "name_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Name:"
}
@GUI::TextBox {
name: "name_textbox"
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "family_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Family:"
}
@GUI::TextBox {
name: "family_textbox"
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "weight_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Weight:"
}
@GUI::ComboBox {
name: "weight_combobox"
model_only: true
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "slope_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Slope:"
}
@GUI::ComboBox {
name: "slope_combobox"
model_only: true
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "presentation_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Presentation size:"
}
@GUI::SpinBox {
name: "presentation_spinbox"
min: 0
max: 255
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "mean_line_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Mean line:"
}
@GUI::SpinBox {
name: "mean_line_spinbox"
min: 0
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "baseline_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Baseline:"
}
@GUI::SpinBox {
name: "baseline_spinbox"
min: 0
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "spacing_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Glyph spacing:"
}
@GUI::SpinBox {
name: "spacing_spinbox"
min: 0
max: 255
}
@GUI::CheckBox {
name: "fixed_width_checkbox"
text: "Fixed width"
autosize: true
}
}
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "family_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Family:"
}
@GUI::TextBox {
name: "family_textbox"
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "weight_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Weight:"
}
@GUI::ComboBox {
name: "weight_combobox"
model_only: true
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "slope_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Slope:"
}
@GUI::ComboBox {
name: "slope_combobox"
model_only: true
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "presentation_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Presentation size:"
}
@GUI::SpinBox {
name: "presentation_spinbox"
min: 0
max: 255
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "mean_line_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Mean line:"
}
@GUI::SpinBox {
name: "mean_line_spinbox"
min: 0
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "baseline_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Baseline:"
}
@GUI::SpinBox {
name: "baseline_spinbox"
min: 0
}
}
@GUI::Widget {
fixed_height: 22
layout: @GUI::HorizontalBoxLayout {}
@GUI::Label {
name: "spacing_label"
fixed_width: 100
text_alignment: "CenterLeft"
text: "Glyph spacing:"
}
@GUI::SpinBox {
name: "spacing_spinbox"
min: 0
max: 255
}
@GUI::CheckBox {
name: "fixed_width_checkbox"
text: "Fixed width"
autosize: true
}
@GUI::ListView {
name: "unicode_block_listview"
max_width: 175
}
}
}

View file

@ -41,7 +41,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto window = TRY(GUI::Window::try_create());
window->set_icon(app_icon.bitmap_for_size(16));
window->resize(440, 470);
window->resize(640, 470);
auto font_editor = TRY(window->try_set_main_widget<FontEditorWidget>());
font_editor->initialize_menubar(*window);