diff options
-rw-r--r-- | Userland/Libraries/LibGUI/TextDocument.cpp | 29 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextDocument.h | 12 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.cpp | 21 | ||||
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.h | 1 |
4 files changed, 63 insertions, 0 deletions
diff --git a/Userland/Libraries/LibGUI/TextDocument.cpp b/Userland/Libraries/LibGUI/TextDocument.cpp index cc0f60d1ad..c58f667708 100644 --- a/Userland/Libraries/LibGUI/TextDocument.cpp +++ b/Userland/Libraries/LibGUI/TextDocument.cpp @@ -959,6 +959,35 @@ void IndentSelection::undo() m_document.set_all_cursors(m_range.start()); } +UnindentSelection::UnindentSelection(TextDocument& document, size_t tab_width, TextRange const& range) + : TextDocumentUndoCommand(document) + , m_tab_width(tab_width) + , m_range(range) +{ +} + +void UnindentSelection::redo() +{ + for (size_t i = m_range.start().line(); i <= m_range.end().line(); i++) { + if (m_document.line(i).leading_spaces() >= m_tab_width) + m_document.remove({ { i, 0 }, { i, m_tab_width } }); + else + m_document.remove({ { i, 0 }, { i, m_document.line(i).leading_spaces() } }); + } + + m_document.set_all_cursors(m_range.start()); +} + +void UnindentSelection::undo() +{ + auto const tab = String::repeated(' ', m_tab_width); + + for (size_t i = m_range.start().line(); i <= m_range.end().line(); i++) + m_document.insert_at({ i, 0 }, tab, m_client); + + m_document.set_all_cursors(m_range.start()); +} + TextPosition TextDocument::insert_at(TextPosition const& position, StringView text, Client const* client) { TextPosition cursor = position; diff --git a/Userland/Libraries/LibGUI/TextDocument.h b/Userland/Libraries/LibGUI/TextDocument.h index 32b28e3292..0af3140d31 100644 --- a/Userland/Libraries/LibGUI/TextDocument.h +++ b/Userland/Libraries/LibGUI/TextDocument.h @@ -271,4 +271,16 @@ private: TextRange m_range; }; +class UnindentSelection : public TextDocumentUndoCommand { +public: + UnindentSelection(TextDocument&, size_t tab_width, TextRange const&); + virtual void undo() override; + virtual void redo() override; + TextRange const& range() const { return m_range; } + +private: + size_t m_tab_width { 0 }; + TextRange m_range; +}; + } diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp index f61aabff25..698935fe75 100644 --- a/Userland/Libraries/LibGUI/TextEditor.cpp +++ b/Userland/Libraries/LibGUI/TextEditor.cpp @@ -869,6 +869,10 @@ void TextEditor::keydown_event(KeyEvent& event) if (event.key() == KeyCode::Key_Tab) { if (has_selection()) { + if (event.modifiers() == Mod_Shift) { + unindent_selection(); + return; + } if (is_indenting_selection()) { indent_selection(); return; @@ -988,6 +992,23 @@ void TextEditor::indent_selection() } } +void TextEditor::unindent_selection() +{ + auto const selection_start = m_selection.start() > m_selection.end() ? m_selection.end() : m_selection.start(); + auto const selection_end = m_selection.end() > m_selection.start() ? m_selection.end() : m_selection.start(); + + if (current_line().first_non_whitespace_column() != 0) { + if (current_line().first_non_whitespace_column() > m_soft_tab_width && selection_start.column() != 0) { + m_selection.set_start({ selection_start.line(), selection_start.column() - m_soft_tab_width }); + m_selection.set_end({ selection_end.line(), selection_end.column() - m_soft_tab_width }); + } else if (selection_start.column() != 0) { + m_selection.set_start({ selection_start.line(), selection_start.column() - current_line().leading_spaces() }); + m_selection.set_end({ selection_end.line(), selection_end.column() - current_line().leading_spaces() }); + } + execute<UnindentSelection>(m_soft_tab_width, TextRange(selection_start, selection_end)); + } +} + void TextEditor::delete_previous_word() { TextRange to_erase(document().first_word_before(m_cursor, true), m_cursor); diff --git a/Userland/Libraries/LibGUI/TextEditor.h b/Userland/Libraries/LibGUI/TextEditor.h index 53865c831d..518730dd0e 100644 --- a/Userland/Libraries/LibGUI/TextEditor.h +++ b/Userland/Libraries/LibGUI/TextEditor.h @@ -153,6 +153,7 @@ public: virtual void redo(); bool is_indenting_selection(); void indent_selection(); + void unindent_selection(); Function<void()> on_change; Function<void(bool modified)> on_modified_change; |