Переглянути джерело

GTextEditor: Start working on editing, starting with inserting newlines.

Andreas Kling 6 роки тому
батько
коміт
8425ea971a
3 змінених файлів з 36 додано та 11 видалено
  1. 14 0
      AK/Vector.h
  2. 19 8
      LibGUI/GTextEditor.cpp
  3. 3 3
      LibGUI/GTextEditor.h

+ 14 - 0
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) {

+ 19 - 8
LibGUI/GTextEditor.cpp

@@ -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

+ 3 - 3
LibGUI/GTextEditor.h

@@ -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()]; }
-    const Line& current_line() const { 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()]; }
     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 };