diff --git a/Userland/Applications/FontEditor/GlyphMapWidget.cpp b/Userland/Applications/FontEditor/GlyphMapWidget.cpp index ed6a65493f..28b9119934 100644 --- a/Userland/Applications/FontEditor/GlyphMapWidget.cpp +++ b/Userland/Applications/FontEditor/GlyphMapWidget.cpp @@ -29,26 +29,36 @@ #include #include -GlyphMapWidget::GlyphMapWidget(Gfx::BitmapFont& mutable_font) - : m_font(mutable_font) +GlyphMapWidget::GlyphMapWidget() { - m_glyph_count = mutable_font.glyph_count(); - set_relative_rect({ 0, 0, preferred_width(), preferred_height() }); set_focus_policy(GUI::FocusPolicy::StrongFocus); + horizontal_scrollbar().set_visible(false); } GlyphMapWidget::~GlyphMapWidget() { } -int GlyphMapWidget::preferred_width() const +void GlyphMapWidget::initialize(Gfx::BitmapFont& mutable_font) { - return columns() * (font().max_glyph_width() + m_horizontal_spacing) + 2 + frame_thickness() * 2; + if (m_font == mutable_font) + return; + m_font = mutable_font; + m_glyph_count = mutable_font.glyph_count(); + vertical_scrollbar().set_step(font().glyph_height() + m_vertical_spacing); } -int GlyphMapWidget::preferred_height() const +void GlyphMapWidget::resize_event(GUI::ResizeEvent& event) { - return rows() * (font().glyph_height() + m_vertical_spacing) + 2 + frame_thickness() * 2; + int event_width = event.size().width() - this->vertical_scrollbar().width() - (frame_thickness() * 2) - m_horizontal_spacing; + m_columns = max(event_width / (font().max_glyph_width() + m_horizontal_spacing), 1); + m_rows = ceil_div(m_glyph_count, m_columns); + + int content_width = columns() * (font().max_glyph_width() + m_horizontal_spacing); + int content_height = rows() * (font().glyph_height() + m_vertical_spacing) + frame_thickness(); + set_content_size({ content_width, content_height }); + + ScrollableWidget::resize_event(event); } void GlyphMapWidget::set_selected_glyph(int glyph) @@ -71,7 +81,7 @@ Gfx::IntRect GlyphMapWidget::get_outer_rect(int glyph) const font().max_glyph_width() + m_horizontal_spacing, font().glyph_height() + m_horizontal_spacing } - .translated(frame_thickness(), frame_thickness()); + .translated(frame_thickness() - horizontal_scrollbar().value(), frame_thickness() - vertical_scrollbar().value()); } void GlyphMapWidget::update_glyph(int glyph) @@ -84,10 +94,11 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event) GUI::Frame::paint_event(event); GUI::Painter painter(*this); + painter.add_clip_rect(widget_inner_rect()); painter.add_clip_rect(event.rect()); painter.set_font(font()); - painter.fill_rect(frame_inner_rect(), palette().base()); + painter.fill_rect(widget_inner_rect(), palette().base()); for (int glyph = 0; glyph < m_glyph_count; ++glyph) { Gfx::IntRect outer_rect = get_outer_rect(glyph); @@ -125,33 +136,39 @@ void GlyphMapWidget::keydown_event(GUI::KeyEvent& event) if (event.key() == KeyCode::Key_Up) { if (selected_glyph() >= m_columns) { set_selected_glyph(selected_glyph() - m_columns); + scroll_to_glyph(selected_glyph()); return; } } if (event.key() == KeyCode::Key_Down) { if (selected_glyph() < m_glyph_count - m_columns) { set_selected_glyph(selected_glyph() + m_columns); + scroll_to_glyph(selected_glyph()); return; } } if (event.key() == KeyCode::Key_Left) { if (selected_glyph() > 0) { set_selected_glyph(selected_glyph() - 1); + scroll_to_glyph(selected_glyph()); return; } } if (event.key() == KeyCode::Key_Right) { if (selected_glyph() < m_glyph_count - 1) { set_selected_glyph(selected_glyph() + 1); + scroll_to_glyph(selected_glyph()); return; } } if (event.ctrl() && event.key() == KeyCode::Key_Home) { set_selected_glyph(0); + scroll_to_glyph(selected_glyph()); return; } if (event.ctrl() && event.key() == KeyCode::Key_End) { set_selected_glyph(m_glyph_count - 1); + scroll_to_glyph(selected_glyph()); return; } if (!event.ctrl() && event.key() == KeyCode::Key_Home) { @@ -166,3 +183,16 @@ void GlyphMapWidget::keydown_event(GUI::KeyEvent& event) return; } } + +void GlyphMapWidget::scroll_to_glyph(int glyph) +{ + int row = glyph / columns(); + int column = glyph % columns(); + auto scroll_rect = Gfx::IntRect { + column * (font().max_glyph_width() + m_horizontal_spacing) + 1, + row * (font().glyph_height() + m_vertical_spacing) + 1, + font().max_glyph_width() + m_horizontal_spacing, + font().glyph_height() + m_horizontal_spacing + }; + scroll_into_view(scroll_rect, true, true); +} diff --git a/Userland/Applications/FontEditor/GlyphMapWidget.h b/Userland/Applications/FontEditor/GlyphMapWidget.h index 2c8443a251..45cf3357f9 100644 --- a/Userland/Applications/FontEditor/GlyphMapWidget.h +++ b/Userland/Applications/FontEditor/GlyphMapWidget.h @@ -26,25 +26,22 @@ #pragma once -#include -#include -#include +#include #include -class GlyphMapWidget final : public GUI::Frame { +class GlyphMapWidget final : public GUI::ScrollableWidget { C_OBJECT(GlyphMapWidget) public: virtual ~GlyphMapWidget() override; + void initialize(Gfx::BitmapFont&); + int selected_glyph() const { return m_selected_glyph; } void set_selected_glyph(int); - int rows() const { return ceil_div(m_glyph_count, m_columns); } + int rows() const { return m_rows; } int columns() const { return m_columns; } - int preferred_width() const; - int preferred_height() const; - Gfx::BitmapFont& font() { return *m_font; } const Gfx::BitmapFont& font() const { return *m_font; } @@ -53,16 +50,19 @@ public: Function on_glyph_selected; private: - explicit GlyphMapWidget(Gfx::BitmapFont&); + GlyphMapWidget(); virtual void paint_event(GUI::PaintEvent&) override; virtual void mousedown_event(GUI::MouseEvent&) override; virtual void keydown_event(GUI::KeyEvent&) override; + virtual void resize_event(GUI::ResizeEvent&) override; Gfx::IntRect get_outer_rect(int glyph) const; + void scroll_to_glyph(int glyph); RefPtr m_font; - int m_glyph_count; + int m_glyph_count { 384 }; int m_columns { 32 }; + int m_rows { 12 }; int m_horizontal_spacing { 2 }; int m_vertical_spacing { 2 }; int m_selected_glyph { 0 };