1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 13:57:35 +00:00

FontEditor: Inherit GlyphMapWidget from ScrollableWidget

This makes it easier to work in FontEditor at low resolution.
Previously glyph map resized itself and the parent window to
accomodate fonts, which isn't ideal. Users typically control
window size/position after launch; widgets have to make do.
This commit is contained in:
thankyouverycool 2021-04-06 11:58:08 -04:00 committed by Andreas Kling
parent e8c1288e2c
commit d115b29a5b
2 changed files with 50 additions and 20 deletions

View file

@ -29,26 +29,36 @@
#include <LibGfx/BitmapFont.h> #include <LibGfx/BitmapFont.h>
#include <LibGfx/Palette.h> #include <LibGfx/Palette.h>
GlyphMapWidget::GlyphMapWidget(Gfx::BitmapFont& mutable_font) GlyphMapWidget::GlyphMapWidget()
: m_font(mutable_font)
{ {
m_glyph_count = mutable_font.glyph_count();
set_relative_rect({ 0, 0, preferred_width(), preferred_height() });
set_focus_policy(GUI::FocusPolicy::StrongFocus); set_focus_policy(GUI::FocusPolicy::StrongFocus);
horizontal_scrollbar().set_visible(false);
} }
GlyphMapWidget::~GlyphMapWidget() 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) 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().max_glyph_width() + m_horizontal_spacing,
font().glyph_height() + 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) void GlyphMapWidget::update_glyph(int glyph)
@ -84,10 +94,11 @@ void GlyphMapWidget::paint_event(GUI::PaintEvent& event)
GUI::Frame::paint_event(event); GUI::Frame::paint_event(event);
GUI::Painter painter(*this); GUI::Painter painter(*this);
painter.add_clip_rect(widget_inner_rect());
painter.add_clip_rect(event.rect()); painter.add_clip_rect(event.rect());
painter.set_font(font()); 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) { for (int glyph = 0; glyph < m_glyph_count; ++glyph) {
Gfx::IntRect outer_rect = get_outer_rect(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 (event.key() == KeyCode::Key_Up) {
if (selected_glyph() >= m_columns) { if (selected_glyph() >= m_columns) {
set_selected_glyph(selected_glyph() - m_columns); set_selected_glyph(selected_glyph() - m_columns);
scroll_to_glyph(selected_glyph());
return; return;
} }
} }
if (event.key() == KeyCode::Key_Down) { if (event.key() == KeyCode::Key_Down) {
if (selected_glyph() < m_glyph_count - m_columns) { if (selected_glyph() < m_glyph_count - m_columns) {
set_selected_glyph(selected_glyph() + m_columns); set_selected_glyph(selected_glyph() + m_columns);
scroll_to_glyph(selected_glyph());
return; return;
} }
} }
if (event.key() == KeyCode::Key_Left) { if (event.key() == KeyCode::Key_Left) {
if (selected_glyph() > 0) { if (selected_glyph() > 0) {
set_selected_glyph(selected_glyph() - 1); set_selected_glyph(selected_glyph() - 1);
scroll_to_glyph(selected_glyph());
return; return;
} }
} }
if (event.key() == KeyCode::Key_Right) { if (event.key() == KeyCode::Key_Right) {
if (selected_glyph() < m_glyph_count - 1) { if (selected_glyph() < m_glyph_count - 1) {
set_selected_glyph(selected_glyph() + 1); set_selected_glyph(selected_glyph() + 1);
scroll_to_glyph(selected_glyph());
return; return;
} }
} }
if (event.ctrl() && event.key() == KeyCode::Key_Home) { if (event.ctrl() && event.key() == KeyCode::Key_Home) {
set_selected_glyph(0); set_selected_glyph(0);
scroll_to_glyph(selected_glyph());
return; return;
} }
if (event.ctrl() && event.key() == KeyCode::Key_End) { if (event.ctrl() && event.key() == KeyCode::Key_End) {
set_selected_glyph(m_glyph_count - 1); set_selected_glyph(m_glyph_count - 1);
scroll_to_glyph(selected_glyph());
return; return;
} }
if (!event.ctrl() && event.key() == KeyCode::Key_Home) { if (!event.ctrl() && event.key() == KeyCode::Key_Home) {
@ -166,3 +183,16 @@ void GlyphMapWidget::keydown_event(GUI::KeyEvent& event)
return; 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);
}

View file

@ -26,25 +26,22 @@
#pragma once #pragma once
#include <AK/Function.h> #include <LibGUI/ScrollableWidget.h>
#include <AK/StdLibExtras.h>
#include <LibGUI/Frame.h>
#include <LibGfx/BitmapFont.h> #include <LibGfx/BitmapFont.h>
class GlyphMapWidget final : public GUI::Frame { class GlyphMapWidget final : public GUI::ScrollableWidget {
C_OBJECT(GlyphMapWidget) C_OBJECT(GlyphMapWidget)
public: public:
virtual ~GlyphMapWidget() override; virtual ~GlyphMapWidget() override;
void initialize(Gfx::BitmapFont&);
int selected_glyph() const { return m_selected_glyph; } int selected_glyph() const { return m_selected_glyph; }
void set_selected_glyph(int); 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 columns() const { return m_columns; }
int preferred_width() const;
int preferred_height() const;
Gfx::BitmapFont& font() { return *m_font; } Gfx::BitmapFont& font() { return *m_font; }
const Gfx::BitmapFont& font() const { return *m_font; } const Gfx::BitmapFont& font() const { return *m_font; }
@ -53,16 +50,19 @@ public:
Function<void(int)> on_glyph_selected; Function<void(int)> on_glyph_selected;
private: private:
explicit GlyphMapWidget(Gfx::BitmapFont&); GlyphMapWidget();
virtual void paint_event(GUI::PaintEvent&) override; virtual void paint_event(GUI::PaintEvent&) override;
virtual void mousedown_event(GUI::MouseEvent&) override; virtual void mousedown_event(GUI::MouseEvent&) override;
virtual void keydown_event(GUI::KeyEvent&) override; virtual void keydown_event(GUI::KeyEvent&) override;
virtual void resize_event(GUI::ResizeEvent&) override;
Gfx::IntRect get_outer_rect(int glyph) const; Gfx::IntRect get_outer_rect(int glyph) const;
void scroll_to_glyph(int glyph);
RefPtr<Gfx::BitmapFont> m_font; RefPtr<Gfx::BitmapFont> m_font;
int m_glyph_count; int m_glyph_count { 384 };
int m_columns { 32 }; int m_columns { 32 };
int m_rows { 12 };
int m_horizontal_spacing { 2 }; int m_horizontal_spacing { 2 };
int m_vertical_spacing { 2 }; int m_vertical_spacing { 2 };
int m_selected_glyph { 0 }; int m_selected_glyph { 0 };