dlxjj/imradv3
0263
1#pragma once2 3#include <string>4#include <vector>5#include <array>6#include <memory>7#include <unordered_set>8#include <unordered_map>9#include <map>10#include <regex>11#include "imgui.h"12 13#include "../nlohmann_json/json.hpp"14using json = nlohmann::json;15 16//#include "../MessageQueue.h"17 18class TextEditor19{20public:21 enum class PaletteIndex22 {23 Default,24 Keyword,25 Number,26 String,27 CharLiteral,28 Punctuation,29 Preprocessor,30 Identifier,31 KnownIdentifier,32 PreprocIdentifier,33 Comment,34 MultiLineComment,35 Background,36 Cursor,37 Selection,38 ErrorMarker,39 Breakpoint,40 LineNumber,41 CurrentLineFill,42 CurrentLineFillInactive,43 CurrentLineEdge,44 Max45 };46 47 enum class SelectionMode48 {49 Normal,50 Word,51 Line52 };53 54 struct Rectangle {55 ImVec2 position; // 矩形位置56 ImVec2 size; // 矩形大小57 bool isDragging; // 是否正在拖动58 bool isHovered; // 是否悬停59 ImColor color; // 矩形颜色60 ImTextureID texture; // 背景纹理61 bool hasTexture; // 是否有纹理62 63 Rectangle() : position(0, 0), size(100, 50), isDragging(false),64 isHovered(false), color(ImColor(200, 200, 200, 40)),65 texture(ImTextureID(0)), hasTexture(false) {66 }67 68 void SetTexture(ImTextureID texture) {69 this->texture = texture;70 this->hasTexture = this->texture != (ImTextureID)0;71 }72 };73 74 struct Breakpoint75 {76 int mLine;77 bool mEnabled;78 std::string mCondition;79 80 Breakpoint()81 : mLine(-1)82 , mEnabled(false)83 {}84 };85 86 // Represents a character coordinate from the user's point of view,87 // i. e. consider an uniform grid (assuming fixed-width font) on the88 // screen as it is rendered, and each cell has its own coordinate, starting from 0.89 // Tabs are counted as [1..mTabSize] count empty spaces, depending on90 // how many space is necessary to reach the next tab stop.91 // For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4,92 // because it is rendered as " ABC" on the screen.93 struct Coordinates94 {95 int mLine, mColumn;96 Coordinates() : mLine(0), mColumn(0) {}97 Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)98 {99 assert(aLine >= 0);100 assert(aColumn >= 0);101 }102 static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }103 104 bool operator ==(const Coordinates& o) const105 {106 return107 mLine == o.mLine &&108 mColumn == o.mColumn;109 }110 111 bool operator !=(const Coordinates& o) const112 {113 return114 mLine != o.mLine ||115 mColumn != o.mColumn;116 }117 118 bool operator <(const Coordinates& o) const119 {120 if (mLine != o.mLine)121 return mLine < o.mLine;122 return mColumn < o.mColumn;123 }124 125 bool operator >(const Coordinates& o) const126 {127 if (mLine != o.mLine)128 return mLine > o.mLine;129 return mColumn > o.mColumn;130 }131 132 bool operator <=(const Coordinates& o) const133 {134 if (mLine != o.mLine)135 return mLine < o.mLine;136 return mColumn <= o.mColumn;137 }138 139 bool operator >=(const Coordinates& o) const140 {141 if (mLine != o.mLine)142 return mLine > o.mLine;143 return mColumn >= o.mColumn;144 }145 };146 147 struct Identifier148 {149 Coordinates mLocation;150 std::string mDeclaration;151 };152 153 typedef std::string String;154 typedef std::unordered_map<std::string, Identifier> Identifiers;155 typedef std::unordered_set<std::string> Keywords;156 typedef std::map<int, std::string> ErrorMarkers;157 typedef std::unordered_set<int> Breakpoints;158 typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;159 typedef uint8_t Char;160 161 struct Glyph162 {163 Char mChar = '\0';164 char mUtf8Char[7] = {0}; // 完整的UTF-8字符165 PaletteIndex mColorIndex = PaletteIndex::Default;166 bool mComment : 1;167 bool mMultiLineComment : 1;168 bool mPreprocessor : 1;169 170 // 字符在图片上的坐标和宽高171 int x;172 int y;173 int w;174 int h;175 char mImageMD5[33] = { 0 };176 177 Glyph():mChar('\0'), mComment(false), mMultiLineComment(false), mPreprocessor(false), x(-1), y(-1), w(-1), h(-1) {};178 179 Glyph(char aChar) :mChar(aChar), mComment(false), mMultiLineComment(false), mPreprocessor(false), x(-1), y(-1), w(-1), h(-1) {};180 181 Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),182 mComment(false), mMultiLineComment(false), mPreprocessor(false), x(-1), y(-1), w(-1), h(-1) {}183 184 Glyph(Char aChar, PaletteIndex aColorIndex, int x_, int y_, int w_, int h_, const char* md5="") : mChar(aChar), mColorIndex(aColorIndex), x(x_), y(y_), w(w_), h(h_),185 mComment(false), mMultiLineComment(false), mPreprocessor(false) {186 if (md5 && strlen(md5) == 32) {187 sprintf(mImageMD5, "%s", md5);188 }189 }190 };191 192 typedef std::vector<Glyph> Line;193 typedef std::vector<Line> Lines;194 195 struct LanguageDefinition196 {197 typedef std::pair<std::string, PaletteIndex> TokenRegexString;198 typedef std::vector<TokenRegexString> TokenRegexStrings;199 typedef bool(*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex);200 201 std::string mName;202 Keywords mKeywords;203 Identifiers mIdentifiers;204 Identifiers mPreprocIdentifiers;205 std::string mCommentStart, mCommentEnd, mSingleLineComment;206 char mPreprocChar;207 bool mAutoIndentation;208 209 TokenizeCallback mTokenize;210 211 TokenRegexStrings mTokenRegexStrings;212 213 bool mCaseSensitive;214 215 LanguageDefinition()216 : mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)217 {218 }219 220 static const LanguageDefinition& CPlusPlus();221 static const LanguageDefinition& HLSL();222 static const LanguageDefinition& GLSL();223 static const LanguageDefinition& C();224 static const LanguageDefinition& SQL();225 static const LanguageDefinition& AngelScript();226 static const LanguageDefinition& Lua();227 };228 229 TextEditor(ImTextureID texture=(ImTextureID)0);230 ~TextEditor();231 232 void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);233 const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }234 235 const Palette& GetPalette() const { return mPaletteBase; }236 void SetPalette(const Palette& aValue);237 238 void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }239 void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }240 241 void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);242 void SetText(const std::string& aText);243 void SetText(const json& jsn, const std::string& md5);244 std::string GetText() const;245 246 void SetTextLines(const std::vector<std::string>& aLines);247 std::vector<std::string> GetTextLines() const;248 249 std::string GetSelectedText() const;250 std::string GetCurrentLineText()const;251 252 int GetTotalLines() const { return (int)mLines.size(); }253 bool IsOverwrite() const { return mOverwrite; }254 255 void SetReadOnly(bool aValue);256 bool IsReadOnly() const { return mReadOnly; }257 bool IsTextChanged() const { return mTextChanged; }258 bool IsCursorPositionChanged() const { return mCursorPositionChanged; }259 260 bool IsColorizerEnabled() const { return mColorizerEnabled; }261 void SetColorizerEnable(bool aValue);262 263 Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }264 void SetCursorPosition(const Coordinates& aPosition);265 266 inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}267 inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }268 269 inline void SetHandleKeyboardInputs (bool aValue){ mHandleKeyboardInputs = aValue;}270 inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }271 272 inline void SetImGuiChildIgnored (bool aValue){ mIgnoreImGuiChild = aValue;}273 inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }274 275 inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }276 inline bool IsShowingWhitespaces() const { return mShowWhitespaces; }277 278 void SetTabSize(int aValue);279 inline int GetTabSize() const { return mTabSize; }280 281 void InsertText(const std::string& aValue);282 void InsertText(const char* aValue);283 284 void MoveUp(int aAmount = 1, bool aSelect = false);285 void MoveDown(int aAmount = 1, bool aSelect = false);286 void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);287 void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);288 void MoveTop(bool aSelect = false);289 void MoveBottom(bool aSelect = false);290 void MoveHome(bool aSelect = false);291 void MoveEnd(bool aSelect = false);292 293 void SetSelectionStart(const Coordinates& aPosition);294 void SetSelectionEnd(const Coordinates& aPosition);295 void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);296 void SelectWordUnderCursor();297 void SelectAll();298 bool HasSelection() const;299 300 void Copy();301 void Cut();302 void Paste();303 void Delete();304 305 bool CanUndo() const;306 bool CanRedo() const;307 void Undo(int aSteps = 1);308 void Redo(int aSteps = 1);309 310 Glyph GetCharactersAroundCursor() const;311 312 //void SetMessageQueue(MessageQueue* queue);313 314 static const Palette& GetDarkPalette();315 static const Palette& GetLightPalette();316 static const Palette& GetRetroBluePalette();317 318private:319 typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList;320 321 //MessageQueue* mMessageQueue = nullptr;322 323 Rectangle mRect;324 325 struct EditorState326 {327 Coordinates mSelectionStart;328 Coordinates mSelectionEnd;329 Coordinates mCursorPosition;330 };331 332 class UndoRecord333 {334 public:335 UndoRecord() {}336 ~UndoRecord() {}337 338 UndoRecord(339 const std::string& aAdded,340 const TextEditor::Coordinates aAddedStart,341 const TextEditor::Coordinates aAddedEnd,342 343 const std::string& aRemoved,344 const TextEditor::Coordinates aRemovedStart,345 const TextEditor::Coordinates aRemovedEnd,346 347 TextEditor::EditorState& aBefore,348 TextEditor::EditorState& aAfter);349 350 void Undo(TextEditor* aEditor);351 void Redo(TextEditor* aEditor);352 353 std::string mAdded;354 Coordinates mAddedStart;355 Coordinates mAddedEnd;356 357 std::string mRemoved;358 Coordinates mRemovedStart;359 Coordinates mRemovedEnd;360 361 EditorState mBefore;362 EditorState mAfter;363 };364 365 typedef std::vector<UndoRecord> UndoBuffer;366 367 void ProcessInputs();368 void Colorize(int aFromLine = 0, int aCount = -1);369 void ColorizeRange(int aFromLine = 0, int aToLine = 0);370 void ColorizeInternal();371 float TextDistanceToLineStart(const Coordinates& aFrom) const;372 void EnsureCursorVisible();373 int GetPageSize() const;374 std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;375 Coordinates GetActualCursorCoordinates() const;376 Coordinates SanitizeCoordinates(const Coordinates& aValue) const;377 void Advance(Coordinates& aCoordinates) const;378 void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);379 int InsertTextAt(Coordinates& aWhere, const char* aValue);380 void AddUndo(UndoRecord& aValue);381 Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;382 Coordinates FindWordStart(const Coordinates& aFrom) const;383 Coordinates FindWordEnd(const Coordinates& aFrom) const;384 Coordinates FindNextWord(const Coordinates& aFrom) const;385 int GetCharacterIndex(const Coordinates& aCoordinates) const;386 int GetCharacterColumn(int aLine, int aIndex) const;387 int GetLineCharacterCount(int aLine) const;388 int GetLineMaxColumn(int aLine) const;389 bool IsOnWordBoundary(const Coordinates& aAt) const;390 void RemoveLine(int aStart, int aEnd);391 void RemoveLine(int aIndex);392 Line& InsertLine(int aIndex);393 void EnterCharacter(ImWchar aChar, bool aShift);394 void Backspace();395 void DeleteSelection();396 std::string GetWordUnderCursor() const;397 std::string GetWordAt(const Coordinates& aCoords) const;398 ImU32 GetGlyphColor(const Glyph& aGlyph) const;399 400 void HandleKeyboardInputs();401 void HandleMouseInputs();402 void Render();403 404 float mLineSpacing;405 Lines mLines;406 EditorState mState;407 UndoBuffer mUndoBuffer;408 int mUndoIndex;409 410 int mTabSize;411 bool mOverwrite;412 bool mReadOnly;413 bool mWithinRender;414 bool mScrollToCursor;415 bool mScrollToTop;416 bool mTextChanged;417 bool mColorizerEnabled;418 float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.419 int mLeftMargin;420 bool mCursorPositionChanged;421 int mColorRangeMin, mColorRangeMax;422 SelectionMode mSelectionMode;423 bool mHandleKeyboardInputs;424 bool mHandleMouseInputs;425 bool mIgnoreImGuiChild;426 bool mShowWhitespaces;427 428 Palette mPaletteBase;429 Palette mPalette;430 LanguageDefinition mLanguageDefinition;431 RegexList mRegexList;432 433 bool mCheckComments;434 Breakpoints mBreakpoints;435 ErrorMarkers mErrorMarkers;436 ImVec2 mCharAdvance;437 Coordinates mInteractiveStart, mInteractiveEnd;438 std::string mLineBuffer;439 uint64_t mStartTime;440 441 float mLastClick;442};443 