mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
* Fixed bug where attempting to select text, while auto scroll is disabled, and entries are being removed, while entries are also being added, causes the start of the selection to not adjust with the number of lines being removed, which then causes it to move with the deletion.
238 lines
6.9 KiB
C++
238 lines
6.9 KiB
C++
#pragma once
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
#include <array>
|
|
#include <memory>
|
|
#include <unordered_set>
|
|
#include <unordered_map>
|
|
#include <map>
|
|
#include <regex>
|
|
#include <thread>
|
|
#include <mutex>
|
|
#include "imgui.h"
|
|
|
|
struct ConLog_t
|
|
{
|
|
ConLog_t(const std::string& svConLog, const ImVec4& imColor)
|
|
{
|
|
m_svConLog = svConLog;
|
|
m_imColor = imColor;
|
|
}
|
|
std::string m_svConLog;
|
|
ImVec4 m_imColor;
|
|
};
|
|
|
|
class CTextLogger
|
|
{
|
|
public:
|
|
|
|
enum class SelectionMode
|
|
{
|
|
Normal,
|
|
Word,
|
|
Line
|
|
};
|
|
|
|
// 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 m_nLine, m_nColumn;
|
|
Coordinates() : m_nLine(0), m_nColumn(0) {}
|
|
Coordinates(int aLine, int aColumn) : m_nLine(aLine), m_nColumn(aColumn)
|
|
{
|
|
assert(aLine >= 0);
|
|
assert(aColumn >= 0);
|
|
}
|
|
static Coordinates Invalid() { static Coordinates invalid(-1, -1); return invalid; }
|
|
|
|
bool operator ==(const Coordinates& o) const
|
|
{
|
|
return
|
|
m_nLine == o.m_nLine &&
|
|
m_nColumn == o.m_nColumn;
|
|
}
|
|
|
|
bool operator !=(const Coordinates& o) const
|
|
{
|
|
return
|
|
m_nLine != o.m_nLine ||
|
|
m_nColumn != o.m_nColumn;
|
|
}
|
|
|
|
bool operator <(const Coordinates& o) const
|
|
{
|
|
if (m_nLine != o.m_nLine)
|
|
return m_nLine < o.m_nLine;
|
|
return m_nColumn < o.m_nColumn;
|
|
}
|
|
|
|
bool operator >(const Coordinates& o) const
|
|
{
|
|
if (m_nLine != o.m_nLine)
|
|
return m_nLine > o.m_nLine;
|
|
return m_nColumn > o.m_nColumn;
|
|
}
|
|
|
|
bool operator <=(const Coordinates& o) const
|
|
{
|
|
if (m_nLine != o.m_nLine)
|
|
return m_nLine < o.m_nLine;
|
|
return m_nColumn <= o.m_nColumn;
|
|
}
|
|
|
|
bool operator >=(const Coordinates& o) const
|
|
{
|
|
if (m_nLine != o.m_nLine)
|
|
return m_nLine > o.m_nLine;
|
|
return m_nColumn >= o.m_nColumn;
|
|
}
|
|
};
|
|
|
|
typedef std::string String;
|
|
typedef uint8_t Char;
|
|
|
|
struct Glyph
|
|
{
|
|
Char m_Char;
|
|
ImVec4 m_Color = ImVec4(0.23f, 0.47f, 0.85f, 1.00f);
|
|
|
|
Glyph(Char aChar, ImVec4 aColor = ImVec4(0.80f, 0.80f, 0.80f, 1.00f)) : m_Char(aChar), m_Color(aColor) {}
|
|
};
|
|
|
|
typedef std::vector<Glyph> Line;
|
|
typedef std::vector<Line> Lines;
|
|
|
|
CTextLogger();
|
|
~CTextLogger();
|
|
|
|
void Render();
|
|
void Copy(bool aCopyAll = false);
|
|
|
|
void SetText(const ConLog_t& aText);
|
|
std::string GetText() const;
|
|
|
|
void SetTextLines(const std::vector<ConLog_t>& aLines);
|
|
std::vector<std::string> GetTextLines() const;
|
|
|
|
ImGuiTextFilter GetFilter() const { return m_itFilter; };
|
|
std::string GetSelectedText() const;
|
|
std::string GetCurrentLineText() const;
|
|
std::string GetTextFromLine(const Line& aLine) const;
|
|
|
|
int GetTotalFilterMatches() const;
|
|
int GetTotalLines() const { return (int)m_Lines.size(); }
|
|
|
|
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
|
|
|
|
void MoveCursor(int aLines, bool aForward = true);
|
|
void SetCursorPosition(const Coordinates& aPosition);
|
|
|
|
inline void SetHandleMouseInputs (bool aValue){ m_bHandleMouseInputs = aValue;}
|
|
inline bool IsHandleMouseInputsEnabled() const { return m_bHandleKeyboardInputs; }
|
|
|
|
inline void SetHandleKeyboardInputs (bool aValue){ m_bHandleKeyboardInputs = aValue;}
|
|
inline bool IsHandleKeyboardInputsEnabled() const { return m_bHandleKeyboardInputs; }
|
|
|
|
inline void SetShowWhitespaces(bool aValue) { m_bShowWhiteSpaces = aValue; }
|
|
inline bool IsShowingWhitespaces() const { return m_bShowWhiteSpaces; }
|
|
|
|
void SetTabSize(int aValue);
|
|
inline int GetTabSize() const { return m_nTabSize; }
|
|
|
|
void InsertText(const ConLog_t& 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 MoveSelection(int aLines, bool aForward = true);
|
|
|
|
void RemoveLine(int aStart, int aEnd);
|
|
void RemoveLine(int aIndex);
|
|
|
|
private:
|
|
struct LoggerState_t
|
|
{
|
|
Coordinates m_SelectionStart;
|
|
Coordinates m_SelectionEnd;
|
|
Coordinates m_CursorPosition;
|
|
};
|
|
|
|
float TextDistanceToLineStart(const Coordinates& aFrom) const;
|
|
void EnsureCursorVisible();
|
|
int GetPageSize() const;
|
|
std::string GetText(const Coordinates& aStart, const Coordinates& aEnd) const;
|
|
Coordinates GetActualLastLineCoordinates() 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, ImVec4 aColor);
|
|
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;
|
|
Line& InsertLine(int aIndex);
|
|
std::string GetWordUnderCursor() const;
|
|
std::string GetWordAt(const Coordinates& aCoords) const;
|
|
ImU32 GetGlyphColor(const Glyph& aGlyph) const;
|
|
|
|
void HandleKeyboardInputs(bool bHoveredScrollbar, bool bActiveScrollbar);
|
|
void HandleMouseInputs(bool bHoveredScrollbar, bool bActiveScrollbar);
|
|
|
|
public:
|
|
bool m_bAutoScroll;
|
|
bool m_bScrollToBottom;
|
|
bool m_bScrollToCursor;
|
|
bool m_bScrolledToMax;
|
|
private:
|
|
bool m_bHandleKeyboardInputs;
|
|
bool m_bHandleMouseInputs;
|
|
bool m_bWithinLoggingRect;
|
|
bool m_bShowWhiteSpaces;
|
|
bool m_bLinesOffsetForward;
|
|
int m_nLinesOffsetAmount;
|
|
int m_nTabSize;
|
|
int m_nLeftMargin;
|
|
int m_nColorRangeMin;
|
|
int m_nColorRangeMax;
|
|
float m_flTextStart; // position (in pixels) where a code line starts relative to the left of the TextLogger.
|
|
float m_flLineSpacing;
|
|
double m_flLastClick;
|
|
uint64_t m_nStartTime;
|
|
|
|
SelectionMode m_SelectionMode;
|
|
Coordinates m_InteractiveStart;
|
|
Coordinates m_InteractiveEnd;
|
|
ImVec2 m_CharAdvance;
|
|
|
|
Lines m_Lines;
|
|
LoggerState_t m_State;
|
|
std::string m_svLineBuffer;
|
|
public:
|
|
ImGuiTextFilter m_itFilter;
|
|
};
|