Improve console scrolling

Moved auto scrolling logic to CTextLogger.
Removed redundant code in CTextLogger.
Added bool param to CTextLogger::RemoveLine to determine whether or not to lock the mutex (internal operations should not lock).
Fixed issue where scrolling with cursor is not possible when auto-scroll is set or ScrollY is towards its max.
Fixed copy button (copy all text in console via GUI, ctrl + a - ctrl + v alternative).
This commit is contained in:
Kawe Mazidjatari 2022-06-21 23:25:15 +02:00
parent a436b70601
commit 76ec4b8f4a
4 changed files with 41 additions and 65 deletions

View File

@ -31,8 +31,6 @@ CConsole::CConsole(void)
memset(m_szInputBuf, '\0', sizeof(m_szInputBuf));
m_nHistoryPos = -1;
m_bAutoScroll = true;
m_bScrollToBottom = false;
m_bInitialized = false;
m_pszConsoleTitle = "Console";
@ -231,9 +229,7 @@ void CConsole::BasePanel(void)
if (m_bCopyToClipBoard)
{
ImGui::LogToClipboard();
ImGui::LogFinish();
m_Logger.Copy(true);
m_bCopyToClipBoard = false;
}
@ -243,12 +239,6 @@ void CConsole::BasePanel(void)
m_nScrollBack = 0;
}
if (m_bScrollToBottom || (m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
{
ImGui::SetScrollHereY(1.0f);
m_bScrollToBottom = false;
}
///////////////////////////////////////////////////////////////////////
ImGui::EndChild();
ImGui::Separator();
@ -314,7 +304,7 @@ void CConsole::BasePanel(void)
//-----------------------------------------------------------------------------
void CConsole::OptionsPanel(void)
{
ImGui::Checkbox("Auto-Scroll", &m_bAutoScroll);
ImGui::Checkbox("Auto-Scroll", &m_Logger.m_bAutoScroll);
ImGui::SameLine();
ImGui::PushItemWidth(100);
@ -596,7 +586,7 @@ void CConsole::ProcessCommand(const char* pszCommand)
}
}
m_bScrollToBottom = true;
m_Logger.m_bScrollToBottom = true;
}
//-----------------------------------------------------------------------------

View File

@ -39,8 +39,6 @@ private:
bool m_bInitialized = false;
bool m_bDefaultTheme = false;
bool m_bReclaimFocus = false;
bool m_bAutoScroll = true;
bool m_bScrollToBottom = false;
bool m_bCopyToClipBoard = false;
bool m_bSuggestActive = false;

View File

@ -128,7 +128,6 @@ public:
int GetTotalFilterMatches() const;
int GetTotalLines() const { return (int)m_Lines.size(); }
bool IsOverwrite() const { return m_Overwrite; }
bool IsCursorPositionChanged() const { return m_bCursorPositionChanged; }
Coordinates GetCursorPosition() const { return GetActualCursorCoordinates(); }
@ -164,10 +163,10 @@ public:
void SelectAll();
bool HasSelection() const;
void RemoveLine(int aStart, int aEnd);
void RemoveLine(int aIndex);
void RemoveLine(int aStart, int aEnd, bool aInternal = false);
void RemoveLine(int aIndex, bool aInternal = false);
void Copy();
void Copy(bool aCopyAll = false);
private:
struct EditorState
@ -210,8 +209,6 @@ private:
std::mutex m_Mutex;
int m_nTabSize;
bool m_Overwrite;
bool m_bWithinRender;
bool m_bScrollToCursor;
float m_flTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
int m_nLeftMargin;
@ -231,5 +228,7 @@ private:
float m_flLastClick;
public:
bool m_bAutoScroll;
bool m_bScrollToBottom;
ImGuiTextFilter m_itFilter;
};

View File

@ -24,8 +24,8 @@ bool equals(InputIt1 first1, InputIt1 last1,
CTextLogger::CTextLogger()
: m_flLineSpacing(1.0f)
, m_nTabSize(4)
, m_Overwrite(false)
, m_bWithinRender(false)
, m_bAutoScroll(true)
, m_bScrollToBottom(true)
, m_bScrollToCursor(false)
, m_flTextStart(0.f)
, m_nLeftMargin(0)
@ -531,9 +531,10 @@ bool CTextLogger::IsOnWordBoundary(const Coordinates & aAt) const
return isspace(line[cindex].m_Char) != isspace(line[cindex - 1].m_Char);
}
void CTextLogger::RemoveLine(int aStart, int aEnd)
void CTextLogger::RemoveLine(int aStart, int aEnd, bool aInternal)
{
m_Mutex.lock();
if (!aInternal)
m_Mutex.lock();
assert(aEnd >= aStart);
assert(m_Lines.size() > (size_t)(aEnd - aStart));
@ -541,19 +542,22 @@ void CTextLogger::RemoveLine(int aStart, int aEnd)
m_Lines.erase(m_Lines.begin() + aStart, m_Lines.begin() + aEnd);
assert(!m_Lines.empty());
m_Mutex.unlock();
if (!aInternal)
m_Mutex.unlock();
}
void CTextLogger::RemoveLine(int aIndex)
void CTextLogger::RemoveLine(int aIndex, bool aInternal)
{
m_Mutex.lock();
if (!aInternal)
m_Mutex.lock();
assert(m_Lines.size() > 1);
m_Lines.erase(m_Lines.begin() + aIndex);
assert(!m_Lines.empty());
m_Mutex.unlock();
if (!aInternal)
m_Mutex.unlock();
}
CTextLogger::Line& CTextLogger::InsertLine(int aIndex)
@ -626,8 +630,6 @@ void CTextLogger::HandleKeyboardInputs()
MoveHome(shift);
else if (!ctrl && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_End)))
MoveEnd(shift);
else if (!ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
m_Overwrite ^= true;
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_Insert)))
Copy();
else if (ctrl && !shift && !alt && ImGui::IsKeyPressed(ImGui::GetKeyIndex(ImGuiKey_C)))
@ -718,8 +720,6 @@ void CTextLogger::HandleMouseInputs()
void CTextLogger::Render()
{
m_Mutex.lock();
m_bWithinRender = true;
m_bCursorPositionChanged = false;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, 0.0f));
@ -802,22 +802,6 @@ void CTextLogger::Render()
int cindex = GetCharacterIndex(m_State.m_CursorPosition);
float cx = TextDistanceToLineStart(m_State.m_CursorPosition);
if (m_Overwrite && cindex < (int)line.size())
{
Char c = line[cindex].m_Char;
if (c == '\t')
{
float x = (1.0f + std::floor((1.0f + cx) / (static_cast<float>(m_nTabSize) * spaceSize))) * (static_cast<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;
}
}
const ImVec2 cstart(textScreenPos.x + cx, lineStartScreenPos.y);
const ImVec2 cend(textScreenPos.x + cx + width, lineStartScreenPos.y + m_CharAdvance.y);
@ -908,19 +892,17 @@ void CTextLogger::Render()
ImGui::Dummy(ImVec2((longest + 2), m_Lines.size() * m_CharAdvance.y));
if (m_bScrollToCursor)
if (m_bScrollToBottom || (!m_bScrollToCursor && m_bAutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()))
{
EnsureCursorVisible();
ImGui::SetWindowFocus();
m_bScrollToCursor = false;
ImGui::SetScrollHereY(1.0f);
m_bScrollToBottom = false;
}
m_bScrollToCursor = false;
if (m_bHandleKeyboardInputs)
ImGui::PopAllowKeyboardFocus();
ImGui::PopStyleVar();
m_bWithinRender = false;
m_Mutex.unlock();
}
@ -1068,8 +1050,8 @@ void CTextLogger::MoveUp(int aAmount, bool aSelect)
}
else
m_InteractiveStart = m_InteractiveEnd = m_State.m_CursorPosition;
SetSelection(m_InteractiveStart, m_InteractiveEnd);
SetSelection(m_InteractiveStart, m_InteractiveEnd);
EnsureCursorVisible();
}
}
@ -1326,13 +1308,13 @@ bool CTextLogger::HasSelection() const
return m_State.m_SelectionEnd > m_State.m_SelectionStart;
}
void CTextLogger::Copy()
void CTextLogger::Copy(bool aCopyAll)
{
if (HasSelection())
if (!aCopyAll && HasSelection())
{
ImGui::SetClipboardText(GetSelectedText().c_str());
}
else
else if (!aCopyAll)
{
if (!m_Lines.empty())
{
@ -1344,6 +1326,16 @@ void CTextLogger::Copy()
ImGui::SetClipboardText(str.c_str());
}
}
else // Copy all lines to clipboard.
{
std::string str;
for (const Line& line: m_Lines)
{
for (const Glyph& g : line)
str.push_back(g.m_Char);
}
ImGui::SetClipboardText(str.c_str());
}
}
std::string CTextLogger::GetText() const
@ -1387,7 +1379,8 @@ std::string CTextLogger::GetTextFromLine(const Line& aLine) const
{
std::string result;
for (const Glyph& glyph : aLine)
result += glyph.m_Char;
result.push_back(glyph.m_Char);
return result;
}
@ -1443,11 +1436,7 @@ float CTextLogger::TextDistanceToLineStart(const Coordinates& aFrom) const
void CTextLogger::EnsureCursorVisible()
{
if (!m_bWithinRender)
{
m_bScrollToCursor = true;
return;
}
m_bScrollToCursor = true;
float scrollX = ImGui::GetScrollX();
float scrollY = ImGui::GetScrollY();