Browse Source

LibGUI+GMLPlayground: Replace text using ReplaceAllTextCommand

SimonFJ20 3 years ago
parent
commit
661e7d691e

+ 1 - 1
Userland/DevTools/Playground/main.cpp

@@ -227,7 +227,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
     TRY(edit_menu->try_add_action(GUI::Action::create("&Format GML", { Mod_Ctrl | Mod_Shift, Key_I }, [&](auto&) {
         auto formatted_gml_or_error = GUI::GML::format_gml(editor->text());
         if (!formatted_gml_or_error.is_error()) {
-            editor->set_text(formatted_gml_or_error.release_value());
+            editor->replace_all_text_while_keeping_undo_stack(formatted_gml_or_error.release_value());
         } else {
             GUI::MessageBox::show(
                 window,

+ 34 - 0
Userland/Libraries/LibGUI/TextDocument.cpp

@@ -884,6 +884,40 @@ void RemoveTextCommand::undo()
     m_document.set_all_cursors(new_cursor);
 }
 
+ReplaceAllTextCommand::ReplaceAllTextCommand(GUI::TextDocument& document, String const& text, GUI::TextRange const& range)
+    : TextDocumentUndoCommand(document)
+    , m_text(text)
+    , m_range(range)
+{
+}
+
+void ReplaceAllTextCommand::redo()
+{
+    m_document.remove(m_range);
+    m_document.set_all_cursors(m_range.start());
+    auto new_cursor = m_document.insert_at(m_range.start(), m_text, m_client);
+    m_range.set_end(new_cursor);
+    m_document.set_all_cursors(new_cursor);
+}
+
+void ReplaceAllTextCommand::undo()
+{
+    m_document.remove(m_range);
+    m_document.set_all_cursors(m_range.start());
+    auto new_cursor = m_document.insert_at(m_range.start(), m_text);
+    m_document.set_all_cursors(new_cursor);
+}
+
+bool ReplaceAllTextCommand::merge_with(GUI::Command const&)
+{
+    return false;
+}
+
+String ReplaceAllTextCommand::action_text() const
+{
+    return "Playground format text";
+}
+
 TextPosition TextDocument::insert_at(TextPosition const& position, StringView text, Client const* client)
 {
     TextPosition cursor = position;

+ 16 - 0
Userland/Libraries/LibGUI/TextDocument.h

@@ -236,4 +236,20 @@ private:
     TextRange m_range;
 };
 
+class ReplaceAllTextCommand : public GUI::TextDocumentUndoCommand {
+
+public:
+    ReplaceAllTextCommand(GUI::TextDocument& document, String const& text, GUI::TextRange const& range);
+    void redo() override;
+    void undo() override;
+    bool merge_with(GUI::Command const&) override;
+    String action_text() const override;
+    String const& text() const { return m_text; }
+    TextRange const& range() const { return m_range; }
+
+private:
+    String m_text;
+    GUI::TextRange m_range;
+};
+
 }

+ 13 - 0
Userland/Libraries/LibGUI/TextEditor.cpp

@@ -1446,6 +1446,19 @@ void TextEditor::insert_at_cursor_or_replace_selection(StringView text)
     }
 }
 
+void TextEditor::replace_all_text_while_keeping_undo_stack(StringView text)
+{
+    auto start = GUI::TextPosition(0, 0);
+    auto last_line_index = line_count() - 1;
+    auto end = GUI::TextPosition(last_line_index, line(last_line_index).length());
+    auto range = GUI::TextRange(start, end);
+    auto normalized_range = range.normalized();
+    execute<ReplaceAllTextCommand>(text, range);
+    did_change();
+    set_cursor(normalized_range.start());
+    update();
+}
+
 void TextEditor::cut()
 {
     if (!is_editable())

+ 1 - 0
Userland/Libraries/LibGUI/TextEditor.h

@@ -123,6 +123,7 @@ public:
     TextRange normalized_selection() const { return m_selection.normalized(); }
 
     void insert_at_cursor_or_replace_selection(StringView);
+    void replace_all_text_while_keeping_undo_stack(StringView text);
     bool write_to_file(String const& path);
     bool write_to_file(Core::File&);
     bool has_selection() const { return m_selection.is_valid(); }