| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- //https://github.com/BalazsJako/ImGuiColorTextEdit
- #pragma once
- #include <string>
- #include <vector>
- #include <array>
- #include <memory>
- #include <unordered_set>
- #include <unordered_map>
- #include <map>
- #include <regex>
- #include "imgui.h"
- class TextEditor
- {
- public:
- enum class PaletteIndex
- {
- Default,
- Keyword,
- Number,
- String,
- CharLiteral,
- Punctuation,
- Preprocessor,
- Identifier,
- KnownIdentifier,
- PreprocIdentifier,
- Comment,
- MultiLineComment,
- Background,
- Cursor,
- Selection,
- ErrorMarker,
- Breakpoint,
- LineNumber,
- CurrentLineFill,
- CurrentLineFillInactive,
- CurrentLineEdge,
- Max
- };
- enum class SelectionMode
- {
- Normal,
- Word,
- Line
- };
- struct Breakpoint
- {
- int mLine;
- bool mEnabled;
- std::string mCondition;
- Breakpoint()
- : mLine(-1)
- , mEnabled(false)
- {}
- };
- // Represents a character coordinate from the user's point of view,
- // i. e. consider an uniform grid (assuming fixed-width font) on the
- // screen as it is rendered, and each cell has its own coordinate, starting from 0.
- // Tabs are counted as [1..mTabSize] count empty spaces, depending on
- // how many space is necessary to reach the next tab stop.
- // For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4,
- // because it is rendered as " ABC" on the screen.
- struct Coordinates
- {
- int mLine, mColumn;
- Coordinates() : mLine(0), mColumn(0) {}
- Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
- {
- assert(aLine >= 0);
- assert(aColumn >= 0);
- }
- static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
- bool operator ==(const Coordinates& o) const
- {
- return
- mLine == o.mLine &&
- mColumn == o.mColumn;
- }
- bool operator !=(const Coordinates& o) const
- {
- return
- mLine != o.mLine ||
- mColumn != o.mColumn;
- }
- bool operator <(const Coordinates& o) const
- {
- if (mLine != o.mLine)
- return mLine < o.mLine;
- return mColumn < o.mColumn;
- }
- bool operator >(const Coordinates& o) const
- {
- if (mLine != o.mLine)
- return mLine > o.mLine;
- return mColumn > o.mColumn;
- }
- bool operator <=(const Coordinates& o) const
- {
- if (mLine != o.mLine)
- return mLine < o.mLine;
- return mColumn <= o.mColumn;
- }
- bool operator >=(const Coordinates& o) const
- {
- if (mLine != o.mLine)
- return mLine > o.mLine;
- return mColumn >= o.mColumn;
- }
- };
- struct Identifier
- {
- Coordinates mLocation;
- std::string mDeclaration;
- };
- typedef std::string String;
- typedef std::unordered_map<std::string, Identifier> Identifiers;
- typedef std::unordered_set<std::string> Keywords;
- typedef std::map<int, std::string> ErrorMarkers;
- typedef std::unordered_set<int> Breakpoints;
- typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
- typedef uint8_t Char;
- struct Glyph
- {
- Char mChar;
- PaletteIndex mColorIndex = PaletteIndex::Default;
- bool mComment : 1;
- bool mMultiLineComment : 1;
- bool mPreprocessor : 1;
- Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),
- mComment(false), mMultiLineComment(false), mPreprocessor(false) {}
- };
- typedef std::vector<Glyph> Line;
- typedef std::vector<Line> Lines;
- struct LanguageDefinition
- {
- typedef std::pair<std::string, PaletteIndex> TokenRegexString;
- typedef std::vector<TokenRegexString> TokenRegexStrings;
- typedef bool(*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex);
- std::string mName;
- Keywords mKeywords;
- Identifiers mIdentifiers;
- Identifiers mPreprocIdentifiers;
- std::string mCommentStart, mCommentEnd, mSingleLineComment;
- char mPreprocChar;
- bool mAutoIndentation;
- TokenizeCallback mTokenize;
- TokenRegexStrings mTokenRegexStrings;
- bool mCaseSensitive;
- LanguageDefinition()
- : mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
- {
- }
- static const LanguageDefinition& CPlusPlus();
- static const LanguageDefinition& HLSL();
- static const LanguageDefinition& GLSL();
- static const LanguageDefinition& C();
- static const LanguageDefinition& SQL();
- static const LanguageDefinition& AngelScript();
- static const LanguageDefinition& Lua();
- };
- TextEditor();
- ~TextEditor();
- void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
- const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
- const Palette& GetPalette() const { return mPaletteBase; }
- void SetPalette(const Palette& aValue);
- void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
- void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
- void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
- void SetText(const std::string& aText);
- std::string GetText() const;
- void SetTextLines(const std::vector<std::string>& aLines);
- std::vector<std::string> GetTextLines() const;
- std::string GetSelectedText() const;
- std::string GetCurrentLineText()const;
- int GetTotalLines() const { return (int)mLines.size(); }
- bool IsOverwrite() const { return mOverwrite; }
- void SetReadOnly(bool aValue);
- bool IsReadOnly() const { return mReadOnly; }
- bool IsTextChanged() const { return mTextChanged; }
- bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
- bool IsColorizerEnabled() const { return mColorizerEnabled; }
- void SetColorizerEnable(bool aValue);
- Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
- void SetCursorPosition(const Coordinates& aPosition);
- inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}
- inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
- inline void SetHandleKeyboardInputs (bool aValue){ mHandleKeyboardInputs = aValue;}
- inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }
- inline void SetImGuiChildIgnored (bool aValue){ mIgnoreImGuiChild = aValue;}
- inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }
- inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }
- inline bool IsShowingWhitespaces() const { return mShowWhitespaces; }
- void SetTabSize(int aValue);
- inline int GetTabSize() const { return mTabSize; }
- void InsertText(const std::string& aValue);
- void InsertText(const char* aValue);
- void MoveUp(int aAmount = 1, bool aSelect = false);
- void MoveDown(int aAmount = 1, bool aSelect = false);
- void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
- void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
- void MoveTop(bool aSelect = false);
- void MoveBottom(bool aSelect = false);
- void MoveHome(bool aSelect = false);
- void MoveEnd(bool aSelect = false);
- void SetSelectionStart(const Coordinates& aPosition);
- void SetSelectionEnd(const Coordinates& aPosition);
- void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
- void SelectWordUnderCursor();
- void SelectAll();
- bool HasSelection() const;
- void Copy();
- void Cut();
- void Paste();
- void Delete();
- bool CanUndo() const;
- bool CanRedo() const;
- void Undo(int aSteps = 1);
- void Redo(int aSteps = 1);
- static const Palette& GetDarkPalette();
- static const Palette& GetLightPalette();
- static const Palette& GetRetroBluePalette();
- private:
- typedef std::vector<std::pair<std::regex, PaletteIndex>> 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<UndoRecord> UndoBuffer;
- void ProcessInputs();
- void Colorize(int aFromLine = 0, int aCount = -1);
- void ColorizeRange(int aFromLine = 0, int aToLine = 0);
- void ColorizeInternal();
- float TextDistanceToLineStart(const Coordinates& aFrom) const;
- void EnsureCursorVisible();
- int GetPageSize() const;
- std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
- Coordinates GetActualCursorCoordinates() const;
- Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
- void Advance(Coordinates& aCoordinates) const;
- void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);
- int InsertTextAt(Coordinates& aWhere, const char* aValue);
- void AddUndo(UndoRecord& aValue);
- Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;
- Coordinates FindWordStart(const Coordinates& aFrom) const;
- Coordinates FindWordEnd(const Coordinates& aFrom) const;
- Coordinates FindNextWord(const Coordinates& aFrom) const;
- int GetCharacterIndex(const Coordinates& aCoordinates) const;
- int GetCharacterColumn(int aLine, int aIndex) const;
- int GetLineCharacterCount(int aLine) const;
- int GetLineMaxColumn(int aLine) const;
- bool IsOnWordBoundary(const Coordinates& aAt) const;
- void RemoveLine(int aStart, int aEnd);
- void RemoveLine(int aIndex);
- Line& InsertLine(int aIndex);
- void EnterCharacter(ImWchar aChar, bool aShift);
- void Backspace();
- void DeleteSelection();
- std::string GetWordUnderCursor() const;
- std::string GetWordAt(const Coordinates& aCoords) const;
- ImU32 GetGlyphColor(const Glyph& aGlyph) const;
- void HandleKeyboardInputs();
- void HandleMouseInputs();
- void Render();
- float mLineSpacing;
- Lines mLines;
- EditorState mState;
- UndoBuffer mUndoBuffer;
- int mUndoIndex;
- int mTabSize;
- bool mOverwrite;
- bool mReadOnly;
- bool mWithinRender;
- bool mScrollToCursor;
- bool mScrollToTop;
- bool mTextChanged;
- bool mColorizerEnabled;
- float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
- int mLeftMargin;
- bool mCursorPositionChanged;
- int mColorRangeMin, mColorRangeMax;
- SelectionMode mSelectionMode;
- bool mHandleKeyboardInputs;
- bool mHandleMouseInputs;
- bool mIgnoreImGuiChild;
- bool mShowWhitespaces;
- Palette mPaletteBase;
- Palette mPalette;
- LanguageDefinition mLanguageDefinition;
- RegexList mRegexList;
- bool mCheckComments;
- Breakpoints mBreakpoints;
- ErrorMarkers mErrorMarkers;
- ImVec2 mCharAdvance;
- Coordinates mInteractiveStart, mInteractiveEnd;
- std::string mLineBuffer;
- uint64_t mStartTime;
- float mLastClick;
- };
|