diff --git a/TextEditor.cpp b/TextEditor.cpp index 02966f0b..a0fa2868 100644 --- a/TextEditor.cpp +++ b/TextEditor.cpp @@ -48,6 +48,7 @@ TextEditor::TextEditor() , mIgnoreImGuiChild(false) , mShowWhitespaces(true) , mStartTime(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()) + , mExternalUndoBuffer(nullptr) { SetPalette(GetDarkPalette()); SetLanguageDefinition(LanguageDefinition::HLSL()); @@ -319,6 +320,16 @@ void TextEditor::AddUndo(UndoRecord& aValue) mUndoBuffer.resize((size_t)(mUndoIndex + 1)); mUndoBuffer.back() = aValue; ++mUndoIndex; + + // If a custom undo buffer is set we send the undo value on it + if ( mExternalUndoBuffer != nullptr) { + mExternalUndoBuffer->AddUndo(aValue); + } +} + +void TextEditor::SetExternalUndoBuffer(ExternalUndoBufferInterface* aExternalUndoBuffer) +{ + this->mExternalUndoBuffer = aExternalUndoBuffer; } TextEditor::Coordinates TextEditor::ScreenPosToCoordinates(const ImVec2& aPosition) const @@ -1418,6 +1429,16 @@ void TextEditor::SetSelectionEnd(const Coordinates & aPosition) std::swap(mState.mSelectionStart, mState.mSelectionEnd); } +const TextEditor::Coordinates TextEditor::GetSelectionStart() const +{ + return mState.mSelectionStart; +} + +const TextEditor::Coordinates TextEditor::GetSelectionEnd() const +{ + return mState.mSelectionEnd; +} + void TextEditor::SetSelection(const Coordinates & aStart, const Coordinates & aEnd, SelectionMode aMode) { auto oldSelStart = mState.mSelectionStart; @@ -1461,25 +1482,46 @@ void TextEditor::SetTabSize(int aValue) mTabSize = std::max(0, std::min(32, aValue)); } -void TextEditor::InsertText(const std::string & aValue) +void TextEditor::InsertText(const std::string & aValue, bool aSelect) { - InsertText(aValue.c_str()); + InsertText(aValue.c_str(), aSelect); } -void TextEditor::InsertText(const char * aValue) +void TextEditor::InsertText(const char * aValue, bool aSelect) { if (aValue == nullptr) return; + // Prepare the undo record + UndoRecord u; + u.mBefore = mState; + + if (HasSelection()) + { + u.mRemoved = GetSelectedText(); + u.mRemovedStart = mState.mSelectionStart; + u.mRemovedEnd = mState.mSelectionEnd; + DeleteSelection(); + } + + u.mAdded = aValue; + u.mAddedStart = GetActualCursorCoordinates(); + + // Insert text auto pos = GetActualCursorCoordinates(); auto start = std::min(pos, mState.mSelectionStart); int totalLines = pos.mLine - start.mLine; totalLines += InsertTextAt(pos, aValue); - SetSelection(pos, pos); + SetSelection( std::min(u.mBefore.mSelectionStart, u.mBefore.mCursorPosition) , pos); SetCursorPosition(pos); Colorize(start.mLine - 1, totalLines + 2); + + // Finish the undorecord and add it to the buffer + u.mAddedEnd = GetActualCursorCoordinates(); + u.mAfter = mState; + AddUndo(u); } void TextEditor::DeleteSelection() @@ -1907,6 +1949,7 @@ bool TextEditor::HasSelection() const return mState.mSelectionEnd > mState.mSelectionStart; } + void TextEditor::Copy() { if (HasSelection()) @@ -2479,6 +2522,18 @@ TextEditor::UndoRecord::UndoRecord( assert(mRemovedStart <= mRemovedEnd); } +TextEditor::UndoRecord::UndoRecord(UndoRecord& undoRecord) + : mAdded(undoRecord.mAdded) + , mAddedStart(undoRecord.mAddedStart) + , mAddedEnd(undoRecord.mAddedEnd) + , mRemoved(undoRecord.mRemoved) + , mRemovedStart(undoRecord.mRemovedStart) + , mRemovedEnd(undoRecord.mRemovedEnd) + , mBefore(undoRecord.mBefore) + , mAfter(undoRecord.mAfter) { + +} + void TextEditor::UndoRecord::Undo(TextEditor * aEditor) { if (!mAdded.empty()) diff --git a/TextEditor.h b/TextEditor.h index bd52e131..a8e7811b 100644 --- a/TextEditor.h +++ b/TextEditor.h @@ -182,6 +182,56 @@ class TextEditor static const LanguageDefinition& Lua(); }; + struct EditorState + { + Coordinates mSelectionStart; + Coordinates mSelectionEnd; + Coordinates mCursorPosition; + }; + + class UndoRecord + { + public: + UndoRecord() {} + ~UndoRecord() {} + + UndoRecord( + const std::string& aAdded, + const TextEditor::Coordinates aAddedStart, + const TextEditor::Coordinates aAddedEnd, + + const std::string& aRemoved, + const TextEditor::Coordinates aRemovedStart, + const TextEditor::Coordinates aRemovedEnd, + + TextEditor::EditorState& aBefore, + TextEditor::EditorState& aAfter); + + UndoRecord(UndoRecord& undoRecord); + + void Undo(TextEditor* aEditor); + void Redo(TextEditor* aEditor); + + std::string mAdded; + Coordinates mAddedStart; + Coordinates mAddedEnd; + + std::string mRemoved; + Coordinates mRemovedStart; + Coordinates mRemovedEnd; + + EditorState mBefore; + EditorState mAfter; + }; + + class ExternalUndoBufferInterface + { + public: + virtual void AddUndo(UndoRecord&) = 0; + }; + + typedef std::vector UndoBuffer; + TextEditor(); ~TextEditor(); @@ -233,8 +283,8 @@ class TextEditor void SetTabSize(int aValue); inline int GetTabSize() const { return mTabSize; } - void InsertText(const std::string& aValue); - void InsertText(const char* aValue); + void InsertText(const std::string& aValue, bool aSelect = false); + void InsertText(const char* aValue, bool aSelect = false); void MoveUp(int aAmount = 1, bool aSelect = false); void MoveDown(int aAmount = 1, bool aSelect = false); @@ -247,6 +297,8 @@ class TextEditor void SetSelectionStart(const Coordinates& aPosition); void SetSelectionEnd(const Coordinates& aPosition); + const Coordinates GetSelectionStart()const; + const Coordinates GetSelectionEnd()const; void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal); void SelectWordUnderCursor(); void SelectAll(); @@ -261,6 +313,7 @@ class TextEditor bool CanRedo() const; void Undo(int aSteps = 1); void Redo(int aSteps = 1); + void SetExternalUndoBuffer(ExternalUndoBufferInterface*); static const Palette& GetDarkPalette(); static const Palette& GetLightPalette(); @@ -269,48 +322,6 @@ class TextEditor private: typedef std::vector> RegexList; - struct EditorState - { - Coordinates mSelectionStart; - Coordinates mSelectionEnd; - Coordinates mCursorPosition; - }; - - class UndoRecord - { - public: - UndoRecord() {} - ~UndoRecord() {} - - UndoRecord( - const std::string& aAdded, - const TextEditor::Coordinates aAddedStart, - const TextEditor::Coordinates aAddedEnd, - - const std::string& aRemoved, - const TextEditor::Coordinates aRemovedStart, - const TextEditor::Coordinates aRemovedEnd, - - TextEditor::EditorState& aBefore, - TextEditor::EditorState& aAfter); - - void Undo(TextEditor* aEditor); - void Redo(TextEditor* aEditor); - - std::string mAdded; - Coordinates mAddedStart; - Coordinates mAddedEnd; - - std::string mRemoved; - Coordinates mRemovedStart; - Coordinates mRemovedEnd; - - EditorState mBefore; - EditorState mAfter; - }; - - typedef std::vector UndoBuffer; - void ProcessInputs(); void Colorize(int aFromLine = 0, int aCount = -1); void ColorizeRange(int aFromLine = 0, int aToLine = 0); @@ -353,6 +364,7 @@ class TextEditor EditorState mState; UndoBuffer mUndoBuffer; int mUndoIndex; + ExternalUndoBufferInterface* mExternalUndoBuffer; int mTabSize; bool mOverwrite;