Reimplement text filter

Could be better at some point, currently removes anything not matching criteria resulting in gaps.
But on the other side it might be good as the location of all occurrences are known (should make it easier to see when it is logged during the process).

Revisit in the future.
This commit is contained in:
Kawe Mazidjatari 2022-06-20 20:21:52 +02:00
parent 0de09217bc
commit da299a002c
4 changed files with 174 additions and 138 deletions

View File

@ -218,7 +218,7 @@ void CConsole::BasePanel(void)
}
ImGui::SameLine();
m_itFilter.Draw("Filter | ", flFooterWidthReserve - 500);
m_Logger.m_itFilter.Draw("Filter | ", flFooterWidthReserve - 500);
ImGui::SameLine();
ImGui::Text(m_szSummary);
@ -806,7 +806,7 @@ void CConsole::AddLog(const ImVec4& color, const char* fmt, ...) IM_FMTARGS(2)
//-----------------------------------------------------------------------------
void CConsole::ClearLog(void)
{
m_Logger.RemoveLine(0, m_Logger.GetTotalLines());
m_Logger.RemoveLine(0, m_Logger.GetTotalLines() - 1);
}
//-----------------------------------------------------------------------------

View File

@ -36,7 +36,6 @@ private:
int m_nHistoryPos = -1;
int m_nScrollBack = 0;
float m_flFadeAlpha = 0.f;
ImGuiTextFilter m_itFilter;
bool m_bInitialized = false;
bool m_bDefaultTheme = false;
bool m_bReclaimFocus = false;

View File

@ -120,12 +120,15 @@ public:
void SetTextLines(const std::vector<CConLog>& aLines);
std::vector<std::string> GetTextLines() const;
ImGuiTextFilter GetFilter() const { return m_itFilter; };
std::string GetSelectedText() const;
std::string GetCurrentLineText()const;
std::string GetCurrentLineText() const;
std::string GetTextFromLine(const Line& aLine) const;
int GetTotalFilterMatches() const;
int GetTotalLines() const { return (int)m_Lines.size(); }
bool IsOverwrite() const { return m_Overwrite; }
bool IsOverwrite() const { return m_Overwrite; }
bool IsCursorPositionChanged() const { return m_bCursorPositionChanged; }
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
@ -167,7 +170,6 @@ public:
void Copy();
private:
struct EditorState
{
Coordinates m_SelectionStart;
@ -226,6 +228,8 @@ private:
Coordinates m_InteractiveEnd;
std::string m_svLineBuffer;
uint64_t m_nStartTime;
float m_flLastClick;
public:
ImGuiTextFilter m_itFilter;
};

View File

@ -739,166 +739,168 @@ void CTextLogger::Render()
auto lineMax = std::max(0, std::min((int)m_Lines.size() - 1, lineNo + (int)floor((scrollY + contentSize.y) / m_CharAdvance.y)));
//m_flTextStart = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x + m_nLeftMargin;
if (!m_Lines.empty())
{
float spaceSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, " ", nullptr, nullptr).x;
while (lineNo <= lineMax)
{
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x, cursorScreenPos.y + lineNo * m_CharAdvance.y);
ImVec2 textScreenPos = ImVec2(lineStartScreenPos.x + m_flTextStart, lineStartScreenPos.y);
auto& line = m_Lines[lineNo];
longest = std::max(m_flTextStart + TextDistanceToLineStart(Coordinates(lineNo, GetLineMaxColumn(lineNo))), longest);
auto columnNo = 0;
Coordinates lineStartCoord(lineNo, 0);
Coordinates lineEndCoord(lineNo, GetLineMaxColumn(lineNo));
// Draw selection for the current line
float sstart = -1.0f;
float ssend = -1.0f;
assert(m_State.m_SelectionStart <= m_State.m_SelectionEnd);
if (m_State.m_SelectionStart <= lineEndCoord)
sstart = m_State.m_SelectionStart > lineStartCoord ? TextDistanceToLineStart(m_State.m_SelectionStart) : 0.0f;
if (m_State.m_SelectionEnd > lineStartCoord)
ssend = TextDistanceToLineStart(m_State.m_SelectionEnd < lineEndCoord ? m_State.m_SelectionEnd : lineEndCoord);
if (m_State.m_SelectionEnd.m_nLine > lineNo)
ssend += m_CharAdvance.x;
if (sstart != -1 && ssend != -1 && sstart < ssend)
if (m_itFilter.PassFilter(GetTextFromLine(line).c_str()))
{
ImVec2 vstart(lineStartScreenPos.x + m_flTextStart + sstart, lineStartScreenPos.y);
ImVec2 vend(lineStartScreenPos.x + m_flTextStart + ssend, lineStartScreenPos.y + m_CharAdvance.y);
drawList->AddRectFilled(vstart, vend, ImGui::GetColorU32(ImGuiCol_TextSelectedBg));
}
ImVec2 lineStartScreenPos = ImVec2(cursorScreenPos.x, cursorScreenPos.y + lineNo * m_CharAdvance.y);
ImVec2 textScreenPos = ImVec2(lineStartScreenPos.x + m_flTextStart, lineStartScreenPos.y);
if (m_State.m_CursorPosition.m_nLine == lineNo)
{
bool focused = ImGui::IsWindowFocused();
ImVec2 start = ImVec2(lineStartScreenPos.x + scrollX, lineStartScreenPos.y);
longest = std::max(m_flTextStart + TextDistanceToLineStart(Coordinates(lineNo, GetLineMaxColumn(lineNo))), longest);
auto columnNo = 0;
Coordinates lineStartCoord(lineNo, 0);
Coordinates lineEndCoord(lineNo, GetLineMaxColumn(lineNo));
// Highlight the current line (where the cursor is)
//if (!HasSelection())
//{
// auto end = ImVec2(start.x + contentSize.x + scrollX, start.y + m_CharAdvance.y);
// drawList->AddRectFilled(start, end, 0x80a06020);
// drawList->AddRect(start, end, 0x80a06020, 1.0f);
//}
// Draw selection for the current line
float sstart = -1.0f;
float ssend = -1.0f;
// Render the cursor
if (focused)
assert(m_State.m_SelectionStart <= m_State.m_SelectionEnd);
if (m_State.m_SelectionStart <= lineEndCoord)
sstart = m_State.m_SelectionStart > lineStartCoord ? TextDistanceToLineStart(m_State.m_SelectionStart) : 0.0f;
if (m_State.m_SelectionEnd > lineStartCoord)
ssend = TextDistanceToLineStart(m_State.m_SelectionEnd < lineEndCoord ? m_State.m_SelectionEnd : lineEndCoord);
if (m_State.m_SelectionEnd.m_nLine > lineNo)
ssend += m_CharAdvance.x;
if (sstart != -1 && ssend != -1 && sstart < ssend)
{
auto timeEnd = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
auto elapsed = timeEnd - m_nStartTime;
if (elapsed > 400)
{
float width = 1.0f;
auto cindex = GetCharacterIndex(m_State.m_CursorPosition);
float cx = TextDistanceToLineStart(m_State.m_CursorPosition);
ImVec2 vstart(lineStartScreenPos.x + m_flTextStart + sstart, lineStartScreenPos.y);
ImVec2 vend(lineStartScreenPos.x + m_flTextStart + ssend, lineStartScreenPos.y + m_CharAdvance.y);
drawList->AddRectFilled(vstart, vend, ImGui::GetColorU32(ImGuiCol_TextSelectedBg));
}
if (m_Overwrite && cindex < (int)line.size())
if (m_State.m_CursorPosition.m_nLine == lineNo)
{
bool focused = ImGui::IsWindowFocused();
ImVec2 start = ImVec2(lineStartScreenPos.x + scrollX, lineStartScreenPos.y);
// Highlight the current line (where the cursor is)
//if (!HasSelection())
//{
// auto end = ImVec2(start.x + contentSize.x + scrollX, start.y + m_CharAdvance.y);
// drawList->AddRectFilled(start, end, 0x80a06020);
// drawList->AddRect(start, end, 0x80a06020, 1.0f);
//}
// Render the cursor
if (focused)
{
auto timeEnd = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
auto elapsed = timeEnd - m_nStartTime;
if (elapsed > 400)
{
auto c = line[cindex].m_Char;
if (c == '\t')
float width = 1.0f;
auto cindex = GetCharacterIndex(m_State.m_CursorPosition);
float cx = TextDistanceToLineStart(m_State.m_CursorPosition);
if (m_Overwrite && cindex < (int)line.size())
{
auto x = (1.0f + std::floor((1.0f + cx) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize);
width = x - cx;
}
else
{
char buf2[2];
buf2[0] = line[cindex].m_Char;
buf2[1] = '\0';
width = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf2).x;
auto c = line[cindex].m_Char;
if (c == '\t')
{
auto x = (1.0f + std::floor((1.0f + cx) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize);
width = x - cx;
}
else
{
char buf2[2];
buf2[0] = line[cindex].m_Char;
buf2[1] = '\0';
width = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf2).x;
}
}
ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y);
ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y);
drawList->AddRectFilled(cstart, cend, 0xffe0e0e0);
if (elapsed > 800)
m_nStartTime = timeEnd;
}
ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y);
ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y);
drawList->AddRectFilled(cstart, cend, 0xffe0e0e0);
if (elapsed > 800)
m_nStartTime = timeEnd;
}
}
}
// Render colorized text
//auto prevColor = GetGlyphColor(line[0]);
ImVec2 bufferOffset;
// Render colorized text
//auto prevColor = GetGlyphColor(line[0]);
ImVec2 bufferOffset;
for (size_t i = 0; i < line.size();)
{
auto& glyph = line[i];
auto color = GetGlyphColor(glyph);
for (size_t i = 0; i < line.size();)
{
auto& glyph = line[i];
auto color = GetGlyphColor(glyph);
if ((glyph.m_Char == '\t' || glyph.m_Char == '\n' || glyph.m_Char == ' ') && !m_svLineBuffer.empty())
if ((glyph.m_Char == '\t' || glyph.m_Char == '\n' || glyph.m_Char == ' ') && !m_svLineBuffer.empty())
{
const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y);
drawList->AddText(newOffset, color, m_svLineBuffer.c_str());
auto textSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, m_svLineBuffer.c_str(), nullptr, nullptr);
bufferOffset.x += textSize.x;
m_svLineBuffer.clear();
}
if (glyph.m_Char == '\t' || glyph.m_Char == '\n')
{
auto oldX = bufferOffset.x;
bufferOffset.x = (1.0f + std::floor((1.0f + bufferOffset.x) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize);
++i;
if (m_bShowWhiteSpaces)
{
const auto s = ImGui::GetFontSize();
const auto x1 = textScreenPos.x + oldX + 1.0f;
const auto x2 = textScreenPos.x + bufferOffset.x - 1.0f;
const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f;
const ImVec2 p1(x1, y);
const ImVec2 p2(x2, y);
const ImVec2 p3(x2 - s * 0.2f, y - s * 0.2f);
const ImVec2 p4(x2 - s * 0.2f, y + s * 0.2f);
drawList->AddLine(p1, p2, 0x90909090);
drawList->AddLine(p2, p3, 0x90909090);
drawList->AddLine(p2, p4, 0x90909090);
}
}
else if (glyph.m_Char == ' ')
{
if (m_bShowWhiteSpaces)
{
const auto s = ImGui::GetFontSize();
const auto x = textScreenPos.x + bufferOffset.x + spaceSize * 0.5f;
const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f;
drawList->AddCircleFilled(ImVec2(x, y), 1.5f, 0x80808080, 4);
}
bufferOffset.x += spaceSize;
i++;
}
else
{
m_svLineBuffer.push_back(line[i++].m_Char);
//auto l = UTF8CharLength(glyph.m_Char); // !TODO: (this currently causes crashes)
//while (l-- > 0)
//{
// m_svLineBuffer.push_back(line[i++].m_Char);
//}
}
++columnNo;
}
if (!m_svLineBuffer.empty())
{
const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y);
drawList->AddText(newOffset, color, m_svLineBuffer.c_str());
auto textSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, m_svLineBuffer.c_str(), nullptr, nullptr);
bufferOffset.x += textSize.x;
drawList->AddText(newOffset, 0xffffffff, m_svLineBuffer.c_str()); // COLOR (obtain from glyph?)
m_svLineBuffer.clear();
}
if (glyph.m_Char == '\t' || glyph.m_Char == '\n')
{
auto oldX = bufferOffset.x;
bufferOffset.x = (1.0f + std::floor((1.0f + bufferOffset.x) / (float(m_nTabSize) * spaceSize))) * (float(m_nTabSize) * spaceSize);
++i;
if (m_bShowWhiteSpaces)
{
const auto s = ImGui::GetFontSize();
const auto x1 = textScreenPos.x + oldX + 1.0f;
const auto x2 = textScreenPos.x + bufferOffset.x - 1.0f;
const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f;
const ImVec2 p1(x1, y);
const ImVec2 p2(x2, y);
const ImVec2 p3(x2 - s * 0.2f, y - s * 0.2f);
const ImVec2 p4(x2 - s * 0.2f, y + s * 0.2f);
drawList->AddLine(p1, p2, 0x90909090);
drawList->AddLine(p2, p3, 0x90909090);
drawList->AddLine(p2, p4, 0x90909090);
}
}
else if (glyph.m_Char == ' ')
{
if (m_bShowWhiteSpaces)
{
const auto s = ImGui::GetFontSize();
const auto x = textScreenPos.x + bufferOffset.x + spaceSize * 0.5f;
const auto y = textScreenPos.y + bufferOffset.y + s * 0.5f;
drawList->AddCircleFilled(ImVec2(x, y), 1.5f, 0x80808080, 4);
}
bufferOffset.x += spaceSize;
i++;
}
else
{
m_svLineBuffer.push_back(line[i++].m_Char);
//auto l = UTF8CharLength(glyph.m_Char); // !TODO: (this currently causes crashes)
//while (l-- > 0)
//{
// m_svLineBuffer.push_back(line[i++].m_Char);
//}
}
++columnNo;
}
if (!m_svLineBuffer.empty())
{
const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y);
drawList->AddText(newOffset, 0xffffffff, m_svLineBuffer.c_str()); // COLOR (obtain from glyph?)
m_svLineBuffer.clear();
}
++lineNo;
if (m_itFilter.IsActive() && m_itFilter.PassFilter(GetTextFromLine(line).c_str()))
++lineNo;
else /*if (!m_itFilter.IsActive())*/
++lineNo;
}
}
ImGui::Dummy(ImVec2((longest + 2), m_Lines.size() * m_CharAdvance.y));
if (m_bScrollToCursor)
@ -1372,6 +1374,37 @@ std::string CTextLogger::GetCurrentLineText()const
Coordinates(m_State.m_CursorPosition.m_nLine, lineLength));
}
std::string CTextLogger::GetTextFromLine(const Line& aLine) const
{
std::string result;
for (size_t i = 0; i < aLine.size(); i++)
{
result += (aLine[i].m_Char);
}
return result;
}
int CTextLogger::GetTotalFilterMatches() const
{
if (!m_itFilter.IsActive())
return static_cast<int>(m_Lines.size());
int result = 0;
for (size_t i = 0; i < m_Lines.size(); i++)
{
std::string svLineBuffer;
for (size_t j = 0; j < m_Lines[i].size(); j++)
{
svLineBuffer += m_Lines[i][j].m_Char;
}
if (m_itFilter.PassFilter(svLineBuffer.c_str()))
{
result++;
}
}
return result;
}
float CTextLogger::TextDistanceToLineStart(const Coordinates& aFrom) const
{
auto& line = m_Lines[aFrom.m_nLine];