diff --git a/LibGUI/GTextEditor.cpp b/LibGUI/GTextEditor.cpp index 77ebe37b37..70a53c0643 100644 --- a/LibGUI/GTextEditor.cpp +++ b/LibGUI/GTextEditor.cpp @@ -86,15 +86,21 @@ int GTextEditor::content_width() const return max_width; } -void GTextEditor::mousedown_event(GMouseEvent& event) +GTextPosition GTextEditor::text_position_at(const Point& a_position) const { - auto position = event.position(); + auto position = a_position; position.move_by(m_horizontal_scrollbar->value(), m_vertical_scrollbar->value()); position.move_by(-padding(), -padding()); int line_index = position.y() / line_height(); int column_index = position.x() / glyph_width(); + line_index = min(line_index, line_count() - 1); column_index = min(column_index, m_lines[line_index].length()); - set_cursor(line_index, column_index); + return { line_index, column_index }; +} + +void GTextEditor::mousedown_event(GMouseEvent& event) +{ + set_cursor(text_position_at(event.position())); } void GTextEditor::paint_event(GPaintEvent& event) @@ -106,7 +112,10 @@ void GTextEditor::paint_event(GPaintEvent& event) painter.translate(padding(), padding()); int exposed_width = max(content_width(), width()); - for (int i = 0; i < line_count(); ++i) { + int first_visible_line = text_position_at(event.rect().top_left()).line(); + int last_visible_line = text_position_at(event.rect().bottom_right()).line(); + + for (int i = first_visible_line; i <= last_visible_line; ++i) { auto& line = m_lines[i]; auto line_rect = line_content_rect(i); line_rect.set_width(exposed_width); @@ -258,10 +267,15 @@ void GTextEditor::update_cursor() void GTextEditor::set_cursor(int line, int column) { - if (m_cursor.line() == line && m_cursor.column() == column) + set_cursor({ line, column }); +} + +void GTextEditor::set_cursor(const GTextPosition& position) +{ + if (m_cursor == position) return; auto old_cursor_line_rect = line_widget_rect(m_cursor.line()); - m_cursor = GTextPosition(line, column); + m_cursor = position; m_cursor_state = true; scroll_cursor_into_view(); update(old_cursor_line_rect); diff --git a/LibGUI/GTextEditor.h b/LibGUI/GTextEditor.h index d56a898a6e..98bb8320b8 100644 --- a/LibGUI/GTextEditor.h +++ b/LibGUI/GTextEditor.h @@ -23,6 +23,8 @@ public: void set_line(int line) { m_line = line; } void set_column(int column) { m_column = column; } + bool operator==(const GTextPosition& other) const { return m_line == other.m_line && m_column == other.m_column; } + private: int m_line { -1 }; int m_column { -1 }; @@ -57,8 +59,6 @@ private: virtual void timer_event(GTimerEvent&) override; virtual bool accepts_focus() const override { return true; } - void insert_at_cursor(char); - class Line { public: Line(); @@ -79,8 +79,11 @@ private: Rect cursor_content_rect() const; void update_cursor(); void set_cursor(int line, int column); + void set_cursor(const GTextPosition&); Line& current_line() { return m_lines[m_cursor.line()]; } const Line& current_line() const { return m_lines[m_cursor.line()]; } + GTextPosition text_position_at(const Point&) const; + void insert_at_cursor(char); GScrollBar* m_vertical_scrollbar { nullptr }; GScrollBar* m_horizontal_scrollbar { nullptr };