SatDump 2.0.0-alpha-76a915210
Loading...
Searching...
No Matches
TextEditor.h
1#pragma once
2
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/imgui.h"
12
13class TextEditor
14{
15public:
16 enum class PaletteIndex
17 {
18 Default,
19 Keyword,
20 Number,
21 String,
22 CharLiteral,
23 Punctuation,
24 Preprocessor,
26 KnownIdentifier,
27 PreprocIdentifier,
28 Comment,
29 MultiLineComment,
30 Background,
31 Cursor,
32 Selection,
33 ErrorMarker,
35 LineNumber,
36 CurrentLineFill,
37 CurrentLineFillInactive,
38 CurrentLineEdge,
39 Max
40 };
41
42 enum class SelectionMode
43 {
44 Normal,
45 Word,
46 Line
47 };
48
49 struct Breakpoint
50 {
51 int mLine;
52 bool mEnabled;
53 std::string mCondition;
54
55 Breakpoint()
56 : mLine(-1)
57 , mEnabled(false)
58 {}
59 };
60
61 // Represents a character coordinate from the user's point of view,
62 // i. e. consider an uniform grid (assuming fixed-width font) on the
63 // screen as it is rendered, and each cell has its own coordinate, starting from 0.
64 // Tabs are counted as [1..mTabSize] count empty spaces, depending on
65 // how many space is necessary to reach the next tab stop.
66 // For example, coordinate (1, 5) represents the character 'B' in a line "\tABC", when mTabSize = 4,
67 // because it is rendered as " ABC" on the screen.
68 struct Coordinates
69 {
70 int mLine, mColumn;
71 Coordinates() : mLine(0), mColumn(0) {}
72 Coordinates(int aLine, int aColumn) : mLine(aLine), mColumn(aColumn)
73 {
74 assert(aLine >= 0);
75 assert(aColumn >= 0);
76 }
77 static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
78
79 bool operator ==(const Coordinates& o) const
80 {
81 return
82 mLine == o.mLine &&
83 mColumn == o.mColumn;
84 }
85
86 bool operator !=(const Coordinates& o) const
87 {
88 return
89 mLine != o.mLine ||
90 mColumn != o.mColumn;
91 }
92
93 bool operator <(const Coordinates& o) const
94 {
95 if (mLine != o.mLine)
96 return mLine < o.mLine;
97 return mColumn < o.mColumn;
98 }
99
100 bool operator >(const Coordinates& o) const
101 {
102 if (mLine != o.mLine)
103 return mLine > o.mLine;
104 return mColumn > o.mColumn;
105 }
106
107 bool operator <=(const Coordinates& o) const
108 {
109 if (mLine != o.mLine)
110 return mLine < o.mLine;
111 return mColumn <= o.mColumn;
112 }
113
114 bool operator >=(const Coordinates& o) const
115 {
116 if (mLine != o.mLine)
117 return mLine > o.mLine;
118 return mColumn >= o.mColumn;
119 }
120 };
121
123 {
124 Coordinates mLocation;
125 std::string mDeclaration;
126 };
127
128 typedef std::string String;
129 typedef std::unordered_map<std::string, Identifier> Identifiers;
130 typedef std::unordered_set<std::string> Keywords;
131 typedef std::map<int, std::string> ErrorMarkers;
132 typedef std::unordered_set<int> Breakpoints;
133 typedef std::array<ImU32, (unsigned)PaletteIndex::Max> Palette;
134 typedef uint8_t Char;
135
136 struct Glyph
137 {
138 Char mChar;
139 PaletteIndex mColorIndex = PaletteIndex::Default;
140 bool mComment : 1;
141 bool mMultiLineComment : 1;
142 bool mPreprocessor : 1;
143
144 Glyph(Char aChar, PaletteIndex aColorIndex) : mChar(aChar), mColorIndex(aColorIndex),
145 mComment(false), mMultiLineComment(false), mPreprocessor(false) {}
146 };
147
148 typedef std::vector<Glyph> Line;
149 typedef std::vector<Line> Lines;
150
151 struct LanguageDefinition
152 {
153 typedef std::pair<std::string, PaletteIndex> TokenRegexString;
154 typedef std::vector<TokenRegexString> TokenRegexStrings;
155 typedef bool(*TokenizeCallback)(const char * in_begin, const char * in_end, const char *& out_begin, const char *& out_end, PaletteIndex & paletteIndex);
156
157 std::string mName;
158 Keywords mKeywords;
159 Identifiers mIdentifiers;
160 Identifiers mPreprocIdentifiers;
161 std::string mCommentStart, mCommentEnd, mSingleLineComment;
162 char mPreprocChar;
163 bool mAutoIndentation;
164
165 TokenizeCallback mTokenize;
166
167 TokenRegexStrings mTokenRegexStrings;
168
169 bool mCaseSensitive;
170
171 LanguageDefinition()
172 : mPreprocChar('#'), mAutoIndentation(true), mTokenize(nullptr), mCaseSensitive(true)
173 {
174 }
175
176 static const LanguageDefinition& CPlusPlus();
177 static const LanguageDefinition& HLSL();
178 static const LanguageDefinition& GLSL();
179 static const LanguageDefinition& C();
180 static const LanguageDefinition& SQL();
181 static const LanguageDefinition& AngelScript();
182 static const LanguageDefinition& Lua();
183 };
184
185 TextEditor();
186 ~TextEditor();
187
188 void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
189 const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
190
191 const Palette& GetPalette() const { return mPaletteBase; }
192 void SetPalette(const Palette& aValue);
193
194 void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
195 void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
196
197 void Render(const char* aTitle, const ImVec2& aSize = ImVec2(), bool aBorder = false);
198 void SetText(const std::string& aText);
199 std::string GetText() const;
200
201 void SetTextLines(const std::vector<std::string>& aLines);
202 std::vector<std::string> GetTextLines() const;
203
204 std::string GetSelectedText() const;
205 std::string GetCurrentLineText()const;
206
207 int GetTotalLines() const { return (int)mLines.size(); }
208 bool IsOverwrite() const { return mOverwrite; }
209
210 void SetReadOnly(bool aValue);
211 bool IsReadOnly() const { return mReadOnly; }
212 bool IsTextChanged() const { return mTextChanged; }
213 bool IsCursorPositionChanged() const { return mCursorPositionChanged; }
214
215 bool IsColorizerEnabled() const { return mColorizerEnabled; }
216 void SetColorizerEnable(bool aValue);
217
218 Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
219 void SetCursorPosition(const Coordinates& aPosition);
220
221 inline void SetHandleMouseInputs (bool aValue){ mHandleMouseInputs = aValue;}
222 inline bool IsHandleMouseInputsEnabled() const { return mHandleKeyboardInputs; }
223
224 inline void SetHandleKeyboardInputs (bool aValue){ mHandleKeyboardInputs = aValue;}
225 inline bool IsHandleKeyboardInputsEnabled() const { return mHandleKeyboardInputs; }
226
227 inline void SetImGuiChildIgnored (bool aValue){ mIgnoreImGuiChild = aValue;}
228 inline bool IsImGuiChildIgnored() const { return mIgnoreImGuiChild; }
229
230 inline void SetShowWhitespaces(bool aValue) { mShowWhitespaces = aValue; }
231 inline bool IsShowingWhitespaces() const { return mShowWhitespaces; }
232
233 void SetTabSize(int aValue);
234 inline int GetTabSize() const { return mTabSize; }
235
236 void InsertText(const std::string& aValue);
237 void InsertText(const char* aValue);
238
239 void MoveUp(int aAmount = 1, bool aSelect = false);
240 void MoveDown(int aAmount = 1, bool aSelect = false);
241 void MoveLeft(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
242 void MoveRight(int aAmount = 1, bool aSelect = false, bool aWordMode = false);
243 void MoveTop(bool aSelect = false);
244 void MoveBottom(bool aSelect = false);
245 void MoveHome(bool aSelect = false);
246 void MoveEnd(bool aSelect = false);
247
248 void SetSelectionStart(const Coordinates& aPosition);
249 void SetSelectionEnd(const Coordinates& aPosition);
250 void SetSelection(const Coordinates& aStart, const Coordinates& aEnd, SelectionMode aMode = SelectionMode::Normal);
251 void SelectWordUnderCursor();
252 void SelectAll();
253 bool HasSelection() const;
254
255 void Copy();
256 void Cut();
257 void Paste();
258 void Delete();
259
260 bool CanUndo() const;
261 bool CanRedo() const;
262 void Undo(int aSteps = 1);
263 void Redo(int aSteps = 1);
264
265 static const Palette& GetDarkPalette();
266 static const Palette& GetLightPalette();
267 static const Palette& GetRetroBluePalette();
268
269private:
270 typedef std::vector<std::pair<std::regex, PaletteIndex>> RegexList;
271
272 struct EditorState
273 {
274 Coordinates mSelectionStart;
275 Coordinates mSelectionEnd;
276 Coordinates mCursorPosition;
277 };
278
279 class UndoRecord
280 {
281 public:
282 UndoRecord() {}
283 ~UndoRecord() {}
284
285 UndoRecord(
286 const std::string& aAdded,
287 const TextEditor::Coordinates aAddedStart,
288 const TextEditor::Coordinates aAddedEnd,
289
290 const std::string& aRemoved,
291 const TextEditor::Coordinates aRemovedStart,
292 const TextEditor::Coordinates aRemovedEnd,
293
294 TextEditor::EditorState& aBefore,
295 TextEditor::EditorState& aAfter);
296
297 void Undo(TextEditor* aEditor);
298 void Redo(TextEditor* aEditor);
299
300 std::string mAdded;
301 Coordinates mAddedStart;
302 Coordinates mAddedEnd;
303
304 std::string mRemoved;
305 Coordinates mRemovedStart;
306 Coordinates mRemovedEnd;
307
308 EditorState mBefore;
309 EditorState mAfter;
310 };
311
312 typedef std::vector<UndoRecord> UndoBuffer;
313
314 void ProcessInputs();
315 void Colorize(int aFromLine = 0, int aCount = -1);
316 void ColorizeRange(int aFromLine = 0, int aToLine = 0);
317 void ColorizeInternal();
318 float TextDistanceToLineStart(const Coordinates& aFrom) const;
319 void EnsureCursorVisible();
320 int GetPageSize() const;
321 std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
322 Coordinates GetActualCursorCoordinates() const;
323 Coordinates SanitizeCoordinates(const Coordinates& aValue) const;
324 void Advance(Coordinates& aCoordinates) const;
325 void DeleteRange(const Coordinates& aStart, const Coordinates& aEnd);
326 int InsertTextAt(Coordinates& aWhere, const char* aValue);
327 void AddUndo(UndoRecord& aValue);
328 Coordinates ScreenPosToCoordinates(const ImVec2& aPosition) const;
329 Coordinates FindWordStart(const Coordinates& aFrom) const;
330 Coordinates FindWordEnd(const Coordinates& aFrom) const;
331 Coordinates FindNextWord(const Coordinates& aFrom) const;
332 int GetCharacterIndex(const Coordinates& aCoordinates) const;
333 int GetCharacterColumn(int aLine, int aIndex) const;
334 int GetLineCharacterCount(int aLine) const;
335 int GetLineMaxColumn(int aLine) const;
336 bool IsOnWordBoundary(const Coordinates& aAt) const;
337 void RemoveLine(int aStart, int aEnd);
338 void RemoveLine(int aIndex);
339 Line& InsertLine(int aIndex);
340 void EnterCharacter(ImWchar aChar, bool aShift);
341 void Backspace();
342 void DeleteSelection();
343 std::string GetWordUnderCursor() const;
344 std::string GetWordAt(const Coordinates& aCoords) const;
345 ImU32 GetGlyphColor(const Glyph& aGlyph) const;
346
347 void HandleKeyboardInputs();
348 void HandleMouseInputs();
349 void Render();
350
351 float mLineSpacing;
352 Lines mLines;
353 EditorState mState;
354 UndoBuffer mUndoBuffer;
355 int mUndoIndex;
356
357 int mTabSize;
358 bool mOverwrite;
359 bool mReadOnly;
360 bool mWithinRender;
361 bool mScrollToCursor;
362 bool mScrollToTop;
363 bool mTextChanged;
364 bool mColorizerEnabled;
365 float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
366 int mLeftMargin;
367 bool mCursorPositionChanged;
368 int mColorRangeMin, mColorRangeMax;
369 SelectionMode mSelectionMode;
370 bool mHandleKeyboardInputs;
371 bool mHandleMouseInputs;
372 bool mIgnoreImGuiChild;
373 bool mShowWhitespaces;
374
375 Palette mPaletteBase;
376 Palette mPalette;
377 LanguageDefinition mLanguageDefinition;
378 RegexList mRegexList;
379
380 bool mCheckComments;
381 Breakpoints mBreakpoints;
382 ErrorMarkers mErrorMarkers;
383 ImVec2 mCharAdvance;
384 Coordinates mInteractiveStart, mInteractiveEnd;
385 std::string mLineBuffer;
386 uint64_t mStartTime;
387
388 float mLastClick;
389};
Definition TextEditor.h:50
Definition TextEditor.h:69
Definition TextEditor.h:137
Definition TextEditor.h:123
Definition TextEditor.h:152