소스 검색

GTextEditor: Add very basic automatic indentation.

This is off by default, but enabled by TextEditor. It simply inserts the
same number of leading spaces as the previous line when hitting Enter. :^)
Andreas Kling 6 년 전
부모
커밋
71770e000b
5개의 변경된 파일38개의 추가작업 그리고 2개의 파일을 삭제
  1. 2 0
      AK/AKString.h
  2. 10 0
      AK/String.cpp
  3. 1 0
      Applications/TextEditor/main.cpp
  4. 20 2
      LibGUI/GTextEditor.cpp
  5. 5 0
      LibGUI/GTextEditor.h

+ 2 - 0
AK/AKString.h

@@ -61,6 +61,8 @@ public:
     {
     }
 
+    static String repeated(char, int count);
+
     int to_int(bool& ok) const;
     unsigned to_uint(bool& ok) const;
 

+ 10 - 0
AK/String.cpp

@@ -166,4 +166,14 @@ bool String::ends_with(const String& str) const
     return !memcmp(characters() + (length() - str.length()), str.characters(), str.length());
 }
 
+String String::repeated(char ch, int count)
+{
+    if (!count)
+        return empty();
+    char* buffer;
+    auto impl = StringImpl::create_uninitialized(count, buffer);
+    memset(buffer, ch, count);
+    return *impl;
+}
+
 }

+ 1 - 0
Applications/TextEditor/main.cpp

@@ -25,6 +25,7 @@ int main(int argc, char** argv)
     auto* toolbar = new GToolBar(widget);
     auto* text_editor = new GTextEditor(GTextEditor::MultiLine, widget);
     text_editor->set_ruler_visible(true);
+    text_editor->set_automatic_indentation_enabled(true);
     auto* statusbar = new GStatusBar(widget);
 
     text_editor->on_cursor_change = [statusbar, text_editor] {

+ 20 - 2
LibGUI/GTextEditor.cpp

@@ -562,10 +562,23 @@ void GTextEditor::insert_at_cursor(char ch)
             return;
         }
         if (at_tail || at_head) {
-            m_lines.insert(m_cursor.line() + (at_tail ? 1 : 0), make<Line>());
+            String new_line_contents;
+            if (m_automatic_indentation_enabled && at_tail) {
+                int leading_spaces = 0;
+                auto& old_line = *m_lines[m_cursor.line()];
+                for (int i = 0; i < old_line.length(); ++i) {
+                    if (old_line.characters()[i] == ' ')
+                        ++leading_spaces;
+                    else
+                        break;
+                }
+                if (leading_spaces)
+                    new_line_contents = String::repeated(' ', leading_spaces);
+            }
+            m_lines.insert(m_cursor.line() + (at_tail ? 1 : 0), make<Line>(new_line_contents));
             update();
             did_change();
-            set_cursor(m_cursor.line() + 1, 0);
+            set_cursor(m_cursor.line() + 1, m_lines[m_cursor.line() + 1]->length());
             return;
         }
         auto new_line = make<Line>();
@@ -709,6 +722,11 @@ GTextEditor::Line::Line()
     clear();
 }
 
+GTextEditor::Line::Line(const String& text)
+{
+    set_text(text);
+}
+
 void GTextEditor::Line::clear()
 {
     m_text.clear();

+ 5 - 0
LibGUI/GTextEditor.h

@@ -70,6 +70,9 @@ public:
     GTextEditor(Type, GWidget* parent);
     virtual ~GTextEditor() override;
 
+    bool is_automatic_indentation() const { return m_automatic_indentation_enabled; }
+    void set_automatic_indentation_enabled(bool enabled) { m_automatic_indentation_enabled = enabled; }
+
     TextAlignment text_alignment() const { return m_text_alignment; }
     void set_text_alignment(TextAlignment);
 
@@ -145,6 +148,7 @@ private:
         friend class GTextEditor;
     public:
         Line();
+        explicit Line(const String&);
 
         const char* characters() const { return m_text.data(); }
         int length() const { return m_text.size() - 1; }
@@ -191,6 +195,7 @@ private:
     bool m_in_drag_select { false };
     bool m_ruler_visible { false };
     bool m_have_pending_change_notification { false };
+    bool m_automatic_indentation_enabled { false };
     int m_line_spacing { 4 };
     int m_soft_tab_width { 4 };
     int m_horizontal_content_padding { 2 };