1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 03:35:09 +00:00

LibGUI: Let GTextEditor deal with its horizontal padding internally.

I originally wanted to have the padding concept in GScrollableWidget
but it's really finicky with the ruler and everything.
This commit is contained in:
Andreas Kling 2019-03-16 23:16:37 +01:00
parent 78039ef057
commit ec8bffb06d
4 changed files with 24 additions and 30 deletions

View file

@ -42,11 +42,11 @@ void GScrollableWidget::resize_event(GResizeEvent& event)
void GScrollableWidget::update_scrollbar_ranges() void GScrollableWidget::update_scrollbar_ranges()
{ {
int available_height = height() - m_size_occupied_by_fixed_elements.height() - height_occupied_by_horizontal_scrollbar(); int available_height = height() - m_size_occupied_by_fixed_elements.height() - height_occupied_by_horizontal_scrollbar();
int excess_height = max(0, (m_content_size.height() + m_padding.height() * 2) - available_height); int excess_height = max(0, m_content_size.height() - available_height);
m_vertical_scrollbar->set_range(0, excess_height); m_vertical_scrollbar->set_range(0, excess_height);
int available_width = width() - m_size_occupied_by_fixed_elements.width() - width_occupied_by_vertical_scrollbar(); int available_width = width() - m_size_occupied_by_fixed_elements.width() - width_occupied_by_vertical_scrollbar();
int excess_width = max(0, (m_content_size.width() + m_padding.height() * 2) - available_width); int excess_width = max(0, m_content_size.width() - available_width);
m_horizontal_scrollbar->set_range(0, excess_width); m_horizontal_scrollbar->set_range(0, excess_width);
m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step()); m_vertical_scrollbar->set_big_step(visible_content_rect().height() - m_vertical_scrollbar->step());
@ -68,14 +68,6 @@ void GScrollableWidget::set_size_occupied_by_fixed_elements(const Size& size)
update_scrollbar_ranges(); update_scrollbar_ranges();
} }
void GScrollableWidget::set_padding(const Size& size)
{
if (m_padding == size)
return;
m_padding = size;
update_scrollbar_ranges();
}
int GScrollableWidget::height_occupied_by_horizontal_scrollbar() const int GScrollableWidget::height_occupied_by_horizontal_scrollbar() const
{ {
return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0; return m_horizontal_scrollbar->is_visible() ? m_horizontal_scrollbar->height() : 0;
@ -91,8 +83,8 @@ Rect GScrollableWidget::visible_content_rect() const
return { return {
m_horizontal_scrollbar->value(), m_horizontal_scrollbar->value(),
m_vertical_scrollbar->value(), m_vertical_scrollbar->value(),
width() - width_occupied_by_vertical_scrollbar() - padding().width() * 2 - m_size_occupied_by_fixed_elements.width(), width() - width_occupied_by_vertical_scrollbar() - m_size_occupied_by_fixed_elements.width(),
height() - height_occupied_by_horizontal_scrollbar() - padding().height() * 2 - m_size_occupied_by_fixed_elements.height() height() - height_occupied_by_horizontal_scrollbar() - m_size_occupied_by_fixed_elements.height()
}; };
} }

View file

@ -8,19 +8,18 @@ class GScrollableWidget : public GWidget {
public: public:
virtual ~GScrollableWidget() override; virtual ~GScrollableWidget() override;
virtual const char* class_name() const override { return "GScrollableWidget"; }
Size content_size() const { return m_content_size; } Size content_size() const { return m_content_size; }
int content_width() const { return m_content_size.width(); } int content_width() const { return m_content_size.width(); }
int content_height() const { return m_content_size.height(); } int content_height() const { return m_content_size.height(); }
Size padding() const { return m_padding; }
Rect visible_content_rect() const; Rect visible_content_rect() const;
void scroll_into_view(const Rect&, Orientation); void scroll_into_view(const Rect&, Orientation);
void scroll_into_view(const Rect&, bool scroll_horizontally, bool scroll_vertically); void scroll_into_view(const Rect&, bool scroll_horizontally, bool scroll_vertically);
void set_scrollbars_enabled(bool);
bool is_scrollbars_enabled() const { return m_scrollbars_enabled; }
GScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; } GScrollBar& vertical_scrollbar() { return *m_vertical_scrollbar; }
const GScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; } const GScrollBar& vertical_scrollbar() const { return *m_vertical_scrollbar; }
GScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; } GScrollBar& horizontal_scrollbar() { return *m_horizontal_scrollbar; }
@ -28,15 +27,13 @@ public:
GWidget& corner_widget() { return *m_corner_widget; } GWidget& corner_widget() { return *m_corner_widget; }
const GWidget& corner_widget() const { return *m_corner_widget; } const GWidget& corner_widget() const { return *m_corner_widget; }
void set_scrollbars_enabled(bool); virtual const char* class_name() const override { return "GScrollableWidget"; }
bool is_scrollbars_enabled() const { return m_scrollbars_enabled; }
protected: protected:
explicit GScrollableWidget(GWidget* parent); explicit GScrollableWidget(GWidget* parent);
virtual void resize_event(GResizeEvent&) override; virtual void resize_event(GResizeEvent&) override;
void set_content_size(const Size&); void set_content_size(const Size&);
void set_size_occupied_by_fixed_elements(const Size&); void set_size_occupied_by_fixed_elements(const Size&);
void set_padding(const Size&);
int width_occupied_by_vertical_scrollbar() const; int width_occupied_by_vertical_scrollbar() const;
int height_occupied_by_horizontal_scrollbar() const; int height_occupied_by_horizontal_scrollbar() const;
@ -49,6 +46,5 @@ private:
GWidget* m_corner_widget { nullptr }; GWidget* m_corner_widget { nullptr };
Size m_content_size; Size m_content_size;
Size m_size_occupied_by_fixed_elements; Size m_size_occupied_by_fixed_elements;
Size m_padding;
bool m_scrollbars_enabled { true }; bool m_scrollbars_enabled { true };
}; };

View file

@ -13,7 +13,6 @@ GTextEditor::GTextEditor(Type type, GWidget* parent)
: GScrollableWidget(parent) : GScrollableWidget(parent)
, m_type(type) , m_type(type)
{ {
set_padding({ 3, 3 });
set_scrollbars_enabled(is_multi_line()); set_scrollbars_enabled(is_multi_line());
m_ruler_visible = is_multi_line(); m_ruler_visible = is_multi_line();
set_font(GFontDatabase::the().get_by_name("Csilla Thin")); set_font(GFontDatabase::the().get_by_name("Csilla Thin"));
@ -53,6 +52,7 @@ void GTextEditor::update_content_size()
int content_width = 0; int content_width = 0;
for (auto& line : m_lines) for (auto& line : m_lines)
content_width = max(line->width(font()), content_width); content_width = max(line->width(font()), content_width);
content_width += m_horizontal_content_padding * 2;
int content_height = line_count() * line_height(); int content_height = line_count() * line_height();
set_content_size({ content_width, content_height }); set_content_size({ content_width, content_height });
set_size_occupied_by_fixed_elements({ ruler_width(), 0 }); set_size_occupied_by_fixed_elements({ ruler_width(), 0 });
@ -62,7 +62,7 @@ GTextPosition GTextEditor::text_position_at(const Point& a_position) const
{ {
auto position = a_position; auto position = a_position;
position.move_by(horizontal_scrollbar().value(), vertical_scrollbar().value()); position.move_by(horizontal_scrollbar().value(), vertical_scrollbar().value());
position.move_by(-(padding().width() + ruler_width()), -padding().height()); position.move_by(-(m_horizontal_content_padding + ruler_width()), 0);
int line_index = position.y() / line_height(); int line_index = position.y() / line_height();
int column_index = position.x() / glyph_width(); int column_index = position.x() / glyph_width();
line_index = max(0, min(line_index, line_count() - 1)); line_index = max(0, min(line_index, line_count() - 1));
@ -133,7 +133,7 @@ Rect GTextEditor::ruler_content_rect(int line_index) const
if (!m_ruler_visible) if (!m_ruler_visible)
return { }; return { };
return { return {
0 - ruler_width() - padding().width() + horizontal_scrollbar().value(), 0 - ruler_width() + horizontal_scrollbar().value(),
line_index * line_height(), line_index * line_height(),
ruler_width(), ruler_width(),
line_height() line_height()
@ -158,7 +158,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
painter.save(); painter.save();
painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value()); painter.translate(-horizontal_scrollbar().value(), -vertical_scrollbar().value());
painter.translate(padding().width() + ruler_width(), padding().height()); painter.translate(ruler_width(), 0);
int exposed_width = max(content_width(), width()); int exposed_width = max(content_width(), width());
int first_visible_line = text_position_at(event.rect().top_left()).line(); int first_visible_line = text_position_at(event.rect().top_left()).line();
@ -194,7 +194,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
if (line_has_selection) { if (line_has_selection) {
int selection_start_column_on_line = selection.start().line() == i ? selection.start().column() : 0; int selection_start_column_on_line = selection.start().line() == i ? selection.start().column() : 0;
int selection_end_column_on_line = selection.end().line() == i ? selection.end().column() : line.length(); int selection_end_column_on_line = selection.end().line() == i ? selection.end().column() : line.length();
int selection_left = selection_start_column_on_line * font().glyph_width('x'); int selection_left = m_horizontal_content_padding + selection_start_column_on_line * font().glyph_width('x');
int selection_right = line_rect.left() + selection_end_column_on_line * font().glyph_width('x'); int selection_right = line_rect.left() + selection_end_column_on_line * font().glyph_width('x');
Rect selection_rect { selection_left, line_rect.y(), selection_right - selection_left, line_rect.height() }; Rect selection_rect { selection_left, line_rect.y(), selection_right - selection_left, line_rect.height() };
painter.fill_rect(selection_rect, Color::from_rgb(0x955233)); painter.fill_rect(selection_rect, Color::from_rgb(0x955233));
@ -457,13 +457,13 @@ Rect GTextEditor::cursor_content_rect() const
return { }; return { };
ASSERT(!m_lines.is_empty()); ASSERT(!m_lines.is_empty());
ASSERT(m_cursor.column() <= (current_line().length() + 1)); ASSERT(m_cursor.column() <= (current_line().length() + 1));
return { m_cursor.column() * glyph_width(), m_cursor.line() * line_height(), 1, line_height() }; return { m_horizontal_content_padding + m_cursor.column() * glyph_width(), m_cursor.line() * line_height(), 1, line_height() };
} }
Rect GTextEditor::line_widget_rect(int line_index) const Rect GTextEditor::line_widget_rect(int line_index) const
{ {
auto rect = line_content_rect(line_index); auto rect = line_content_rect(line_index);
rect.move_by(-(horizontal_scrollbar().value() - padding().width()), -(vertical_scrollbar().value() - padding().height())); rect.move_by(-(horizontal_scrollbar().value() - m_horizontal_content_padding), -(vertical_scrollbar().value()));
rect.set_width(rect.width() + 1); // Add 1 pixel for when the cursor is on the end. rect.set_width(rect.width() + 1); // Add 1 pixel for when the cursor is on the end.
rect.intersect(this->rect()); rect.intersect(this->rect());
// This feels rather hackish, but extend the rect to the edge of the content view: // This feels rather hackish, but extend the rect to the edge of the content view:
@ -473,13 +473,18 @@ Rect GTextEditor::line_widget_rect(int line_index) const
void GTextEditor::scroll_cursor_into_view() void GTextEditor::scroll_cursor_into_view()
{ {
scroll_into_view(cursor_content_rect(), true, true); auto rect = cursor_content_rect();
if (m_cursor.column() == 0)
rect.set_x(0);
else if (m_cursor.column() >= m_lines[m_cursor.line()]->length())
rect.set_x(m_lines[m_cursor.line()]->width(font()) + m_horizontal_content_padding * 2);
scroll_into_view(rect, true, true);
} }
Rect GTextEditor::line_content_rect(int line_index) const Rect GTextEditor::line_content_rect(int line_index) const
{ {
return { return {
0, m_horizontal_content_padding,
line_index * line_height(), line_index * line_height(),
content_width(), content_width(),
line_height() line_height()

View file

@ -157,7 +157,8 @@ private:
bool m_cursor_state { true }; bool m_cursor_state { true };
bool m_in_drag_select { false }; bool m_in_drag_select { false };
bool m_ruler_visible { true }; bool m_ruler_visible { true };
int m_line_spacing { 2 }; int m_line_spacing { 4 };
int m_soft_tab_width { 4 }; int m_soft_tab_width { 4 };
int m_horizontal_content_padding { 2 };
GTextRange m_selection; GTextRange m_selection;
}; };