mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 04:48:14 +00:00
GTextEditor: Start working on editing, starting with inserting newlines.
This commit is contained in:
parent
b4df33e453
commit
8425ea971a
3 changed files with 36 additions and 11 deletions
14
AK/Vector.h
14
AK/Vector.h
|
@ -159,6 +159,20 @@ public:
|
||||||
m_impl->remove(index);
|
m_impl->remove(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void insert(int index, T&& value)
|
||||||
|
{
|
||||||
|
ASSERT(index <= size());
|
||||||
|
if (index == size())
|
||||||
|
return append(move(value));
|
||||||
|
ensure_capacity(size() + 1);
|
||||||
|
++m_impl->m_size;
|
||||||
|
for (int i = size() - 1; i > index; --i) {
|
||||||
|
new (m_impl->slot(i)) T(move(m_impl->at(i - 1)));
|
||||||
|
m_impl->at(i - 1).~T();
|
||||||
|
}
|
||||||
|
new (m_impl->slot(index)) T(move(value));
|
||||||
|
}
|
||||||
|
|
||||||
Vector& operator=(const Vector<T>& other)
|
Vector& operator=(const Vector<T>& other)
|
||||||
{
|
{
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
|
|
|
@ -36,9 +36,9 @@ void GTextEditor::set_text(const String& text)
|
||||||
|
|
||||||
auto add_line = [&] (int current_position) {
|
auto add_line = [&] (int current_position) {
|
||||||
int line_length = current_position - start_of_current_line;
|
int line_length = current_position - start_of_current_line;
|
||||||
Line line;
|
auto line = make<Line>();
|
||||||
if (line_length)
|
if (line_length)
|
||||||
line.set_text(text.substring(start_of_current_line, current_position - start_of_current_line));
|
line->set_text(text.substring(start_of_current_line, current_position - start_of_current_line));
|
||||||
m_lines.append(move(line));
|
m_lines.append(move(line));
|
||||||
start_of_current_line = current_position + 1;
|
start_of_current_line = current_position + 1;
|
||||||
};
|
};
|
||||||
|
@ -82,7 +82,7 @@ int GTextEditor::content_width() const
|
||||||
// FIXME: Cache this somewhere.
|
// 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);
|
||||||
return max_width;
|
return max_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ GTextPosition GTextEditor::text_position_at(const Point& a_position) const
|
||||||
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 = min(line_index, line_count() - 1);
|
line_index = min(line_index, line_count() - 1);
|
||||||
column_index = min(column_index, m_lines[line_index].length());
|
column_index = min(column_index, m_lines[line_index]->length());
|
||||||
return { line_index, column_index };
|
return { line_index, column_index };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ void GTextEditor::paint_event(GPaintEvent& event)
|
||||||
int last_visible_line = text_position_at(event.rect().bottom_right()).line();
|
int last_visible_line = text_position_at(event.rect().bottom_right()).line();
|
||||||
|
|
||||||
for (int i = first_visible_line; i <= last_visible_line; ++i) {
|
for (int i = first_visible_line; i <= last_visible_line; ++i) {
|
||||||
auto& line = m_lines[i];
|
auto& line = *m_lines[i];
|
||||||
auto line_rect = line_content_rect(i);
|
auto line_rect = line_content_rect(i);
|
||||||
line_rect.set_width(exposed_width);
|
line_rect.set_width(exposed_width);
|
||||||
if (i == m_cursor.line() && is_focused())
|
if (i == m_cursor.line() && is_focused())
|
||||||
|
@ -142,7 +142,7 @@ void GTextEditor::keydown_event(GKeyEvent& event)
|
||||||
if (!event.modifiers() && event.key() == KeyCode::Key_Up) {
|
if (!event.modifiers() && event.key() == KeyCode::Key_Up) {
|
||||||
if (m_cursor.line() > 0) {
|
if (m_cursor.line() > 0) {
|
||||||
int new_line = m_cursor.line() - 1;
|
int new_line = m_cursor.line() - 1;
|
||||||
int new_column = min(m_cursor.column(), m_lines[new_line].length());
|
int new_column = min(m_cursor.column(), m_lines[new_line]->length());
|
||||||
set_cursor(new_line, new_column);
|
set_cursor(new_line, new_column);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -150,7 +150,7 @@ void GTextEditor::keydown_event(GKeyEvent& event)
|
||||||
if (!event.modifiers() && event.key() == KeyCode::Key_Down) {
|
if (!event.modifiers() && event.key() == KeyCode::Key_Down) {
|
||||||
if (m_cursor.line() < (m_lines.size() - 1)) {
|
if (m_cursor.line() < (m_lines.size() - 1)) {
|
||||||
int new_line = m_cursor.line() + 1;
|
int new_line = m_cursor.line() + 1;
|
||||||
int new_column = min(m_cursor.column(), m_lines[new_line].length());
|
int new_column = min(m_cursor.column(), m_lines[new_line]->length());
|
||||||
set_cursor(new_line, new_column);
|
set_cursor(new_line, new_column);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
@ -182,7 +182,7 @@ void GTextEditor::keydown_event(GKeyEvent& event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (event.ctrl() && event.key() == KeyCode::Key_End) {
|
if (event.ctrl() && event.key() == KeyCode::Key_End) {
|
||||||
set_cursor(line_count() - 1, m_lines[line_count() - 1].length());
|
set_cursor(line_count() - 1, m_lines[line_count() - 1]->length());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,6 +194,17 @@ void GTextEditor::keydown_event(GKeyEvent& event)
|
||||||
|
|
||||||
void GTextEditor::insert_at_cursor(char ch)
|
void GTextEditor::insert_at_cursor(char ch)
|
||||||
{
|
{
|
||||||
|
bool at_head = m_cursor.column() == 0;
|
||||||
|
bool at_tail = m_cursor.column() == current_line().length();
|
||||||
|
if (ch == '\n') {
|
||||||
|
if (at_tail || at_head) {
|
||||||
|
m_lines.insert(m_cursor.line() + (at_tail ? 1 : 0), make<Line>());
|
||||||
|
update_scrollbar_ranges();
|
||||||
|
set_cursor(m_cursor.line() + 1, 0);
|
||||||
|
update();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rect GTextEditor::visible_content_rect() const
|
Rect GTextEditor::visible_content_rect() const
|
||||||
|
|
|
@ -80,15 +80,15 @@ private:
|
||||||
void update_cursor();
|
void update_cursor();
|
||||||
void set_cursor(int line, int column);
|
void set_cursor(int line, int column);
|
||||||
void set_cursor(const GTextPosition&);
|
void set_cursor(const GTextPosition&);
|
||||||
Line& current_line() { return m_lines[m_cursor.line()]; }
|
Line& current_line() { return *m_lines[m_cursor.line()]; }
|
||||||
const Line& current_line() const { return m_lines[m_cursor.line()]; }
|
const Line& current_line() const { return *m_lines[m_cursor.line()]; }
|
||||||
GTextPosition text_position_at(const Point&) const;
|
GTextPosition text_position_at(const Point&) const;
|
||||||
void insert_at_cursor(char);
|
void insert_at_cursor(char);
|
||||||
|
|
||||||
GScrollBar* m_vertical_scrollbar { nullptr };
|
GScrollBar* m_vertical_scrollbar { nullptr };
|
||||||
GScrollBar* m_horizontal_scrollbar { nullptr };
|
GScrollBar* m_horizontal_scrollbar { nullptr };
|
||||||
|
|
||||||
Vector<Line> m_lines;
|
Vector<OwnPtr<Line>> m_lines;
|
||||||
GTextPosition m_cursor;
|
GTextPosition m_cursor;
|
||||||
bool m_cursor_state { true };
|
bool m_cursor_state { true };
|
||||||
int m_line_spacing { 2 };
|
int m_line_spacing { 2 };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue