mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 08:38:12 +00:00
GTextEditor: Improvements to cursor rendering.
The view now scrolls along with you as you move the cursor around.
This commit is contained in:
parent
dff57909a7
commit
1ac71d1fb1
4 changed files with 31 additions and 27 deletions
|
@ -104,6 +104,7 @@ int main(int argc, char** argv)
|
||||||
window->set_rect(20, 200, 640, 400);
|
window->set_rect(20, 200, 640, 400);
|
||||||
window->set_main_widget(widget);
|
window->set_main_widget(widget);
|
||||||
window->set_should_exit_app_on_close(true);
|
window->set_should_exit_app_on_close(true);
|
||||||
|
text_editor->set_focus(true);
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
|
|
@ -74,6 +74,7 @@ void GTextEditor::update_scrollbar_ranges()
|
||||||
|
|
||||||
int GTextEditor::content_width() const
|
int GTextEditor::content_width() const
|
||||||
{
|
{
|
||||||
|
// FIXME: Cache this somewhere.
|
||||||
int max_width = 0;
|
int max_width = 0;
|
||||||
for (auto& line : m_lines)
|
for (auto& line : m_lines)
|
||||||
max_width = max(line.width(font()), max_width);
|
max_width = max(line.width(font()), max_width);
|
||||||
|
@ -103,8 +104,10 @@ void GTextEditor::paint_event(GPaintEvent& event)
|
||||||
painter.draw_text(line_rect, line.text(), TextAlignment::CenterLeft, Color::Black);
|
painter.draw_text(line_rect, line.text(), TextAlignment::CenterLeft, Color::Black);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_focused() && m_cursor_state)
|
if (is_focused() && m_cursor_state) {
|
||||||
|
dbgprintf("draw cursor @ %s (xlated %s, clip %s)\n", cursor_content_rect().to_string().characters(), cursor_content_rect().translated(painter.translation()).to_string().characters(), painter.clip_rect().to_string().characters());
|
||||||
painter.fill_rect(cursor_content_rect(), Color::Red);
|
painter.fill_rect(cursor_content_rect(), Color::Red);
|
||||||
|
}
|
||||||
|
|
||||||
painter.translate(-padding(), -padding());
|
painter.translate(-padding(), -padding());
|
||||||
painter.translate(m_horizontal_scrollbar->value(), m_vertical_scrollbar->value());
|
painter.translate(m_horizontal_scrollbar->value(), m_vertical_scrollbar->value());
|
||||||
|
@ -174,50 +177,46 @@ Rect GTextEditor::cursor_content_rect() const
|
||||||
return { x, m_cursor.line() * line_height(), 1, line_height() };
|
return { x, m_cursor.line() * line_height(), 1, line_height() };
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect GTextEditor::cursor_widget_rect() const
|
|
||||||
{
|
|
||||||
ASSERT(m_horizontal_scrollbar);
|
|
||||||
ASSERT(m_vertical_scrollbar);
|
|
||||||
auto rect = cursor_content_rect();
|
|
||||||
return rect.translated(-(m_horizontal_scrollbar->value() - padding()), -(m_vertical_scrollbar->value() - padding()));
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect GTextEditor::line_widget_rect(int line_index) const
|
Rect GTextEditor::line_widget_rect(int line_index) const
|
||||||
{
|
{
|
||||||
ASSERT(m_horizontal_scrollbar);
|
ASSERT(m_horizontal_scrollbar);
|
||||||
ASSERT(m_vertical_scrollbar);
|
ASSERT(m_vertical_scrollbar);
|
||||||
auto rect = line_content_rect(line_index);
|
auto rect = line_content_rect(line_index);
|
||||||
return rect.translated(-(m_horizontal_scrollbar->value() - padding()), -(m_vertical_scrollbar->value() - padding()));
|
rect.move_by(-(m_horizontal_scrollbar->value() - padding()), -(m_vertical_scrollbar->value() - padding()));
|
||||||
|
rect.intersect(this->rect());
|
||||||
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GTextEditor::scroll_into_view(const GTextPosition& position, Orientation orientation)
|
void GTextEditor::scroll_cursor_into_view()
|
||||||
{
|
{
|
||||||
auto visible_content_rect = this->visible_content_rect();
|
auto visible_content_rect = this->visible_content_rect();
|
||||||
auto rect = line_content_rect(position.line());
|
auto rect = cursor_content_rect();
|
||||||
|
|
||||||
|
if (visible_content_rect.is_empty())
|
||||||
|
return;
|
||||||
|
|
||||||
if (visible_content_rect.contains(rect))
|
if (visible_content_rect.contains(rect))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (orientation == Orientation::Vertical) {
|
if (rect.top() < visible_content_rect.top())
|
||||||
if (rect.top() < visible_content_rect.top())
|
m_vertical_scrollbar->set_value(rect.top());
|
||||||
m_vertical_scrollbar->set_value(rect.top());
|
else if (rect.bottom() > visible_content_rect.bottom())
|
||||||
else if (rect.bottom() > visible_content_rect.bottom())
|
m_vertical_scrollbar->set_value(rect.bottom() - visible_content_rect.height());
|
||||||
m_vertical_scrollbar->set_value(rect.bottom() - visible_content_rect.height());
|
|
||||||
} else {
|
if (rect.left() < visible_content_rect.left())
|
||||||
if (rect.left() < visible_content_rect.left())
|
m_horizontal_scrollbar->set_value(rect.left());
|
||||||
m_horizontal_scrollbar->set_value(rect.left());
|
else if (rect.right() > visible_content_rect.right())
|
||||||
else if (rect.right() > visible_content_rect.right())
|
m_horizontal_scrollbar->set_value(rect.right() - visible_content_rect.width());
|
||||||
m_horizontal_scrollbar->set_value(rect.right() - visible_content_rect.width());
|
|
||||||
}
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect GTextEditor::line_content_rect(int line_index) const
|
Rect GTextEditor::line_content_rect(int line_index) const
|
||||||
{
|
{
|
||||||
auto& line = m_lines[line_index];
|
|
||||||
return {
|
return {
|
||||||
0,
|
0,
|
||||||
line_index * line_height(),
|
line_index * line_height(),
|
||||||
line.width(font()),
|
content_width(),
|
||||||
line_height()
|
line_height()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -225,7 +224,9 @@ Rect GTextEditor::line_content_rect(int line_index) const
|
||||||
void GTextEditor::update_cursor()
|
void GTextEditor::update_cursor()
|
||||||
{
|
{
|
||||||
auto rect = line_widget_rect(m_cursor.line());
|
auto rect = line_widget_rect(m_cursor.line());
|
||||||
|
dbgprintf("update_cursor: line_widget_rect: %s", rect.to_string().characters());
|
||||||
rect.set_width(width());
|
rect.set_width(width());
|
||||||
|
dbgprintf(", adjusted: %s\n", rect.to_string().characters());
|
||||||
update(rect);
|
update(rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +238,7 @@ void GTextEditor::set_cursor(int line, int column)
|
||||||
m_cursor = GTextPosition(line, column);
|
m_cursor = GTextPosition(line, column);
|
||||||
m_cursor_state = true;
|
m_cursor_state = true;
|
||||||
update_cursor();
|
update_cursor();
|
||||||
|
scroll_cursor_into_view();
|
||||||
if (on_cursor_change)
|
if (on_cursor_change)
|
||||||
on_cursor_change(*this);
|
on_cursor_change(*this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
void set_text(const String&);
|
void set_text(const String&);
|
||||||
int content_width() const;
|
int content_width() const;
|
||||||
Rect visible_content_rect() const;
|
Rect visible_content_rect() const;
|
||||||
void scroll_into_view(const GTextPosition&, Orientation);
|
void scroll_cursor_into_view();
|
||||||
int line_count() const { return m_lines.size(); }
|
int line_count() const { return m_lines.size(); }
|
||||||
int line_spacing() const { return m_line_spacing; }
|
int line_spacing() const { return m_line_spacing; }
|
||||||
int line_height() const { return font().glyph_height() + m_line_spacing; }
|
int line_height() const { return font().glyph_height() + m_line_spacing; }
|
||||||
|
@ -59,7 +59,6 @@ private:
|
||||||
Rect line_content_rect(int item_index) const;
|
Rect line_content_rect(int item_index) const;
|
||||||
Rect line_widget_rect(int line_index) const;
|
Rect line_widget_rect(int line_index) const;
|
||||||
Rect cursor_content_rect() const;
|
Rect cursor_content_rect() const;
|
||||||
Rect cursor_widget_rect() const;
|
|
||||||
void update_cursor();
|
void update_cursor();
|
||||||
void set_cursor(int line, int column);
|
void set_cursor(int line, int column);
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
void translate(int dx, int dy) { m_translation.move_by(dx, dy); }
|
void translate(int dx, int dy) { m_translation.move_by(dx, dy); }
|
||||||
void translate(const Point& delta) { m_translation.move_by(delta); }
|
void translate(const Point& delta) { m_translation.move_by(delta); }
|
||||||
|
|
||||||
|
Point translation() const { return m_translation; }
|
||||||
|
|
||||||
GraphicsBitmap* target() { return m_target.ptr(); }
|
GraphicsBitmap* target() { return m_target.ptr(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue