impr: Make scrolling in pattern editor feel less janky (#2009)
I have implemented a fix that makes the scrollbars behave like they do in VScode. Vertically you can scroll past the end of the file until only the last line can be seen at the top. The horizontal bar behaves as if every line was the same length which is the length of the longest line in the file. Not only this creates a better user experience, but it also fixes the annoying flicker that occurs when scrolling through large files. Also, I have switched all the old draw calls to render text to regular TextUnformatted calls which adds extra stability to the resulting display. To implement the behavior I added a dummy widget with the desired dimensions.
This commit is contained in:
parent
fd46d85762
commit
b446d7fd4a
@ -559,6 +559,7 @@ private:
|
||||
int GetCharacterColumn(int aLine, int aIndex) const;
|
||||
int GetLineCharacterCount(int aLine) const;
|
||||
int Utf8CharsToBytes(const Coordinates &aCoordinates) const;
|
||||
int GetLongestLineLength() const;
|
||||
unsigned long long GetLineByteCount(int aLine) const;
|
||||
int GetStringCharacterCount(std::string str) const;
|
||||
int GetLineMaxColumn(int aLine) const;
|
||||
@ -595,6 +596,7 @@ private:
|
||||
bool mScrollToTop;
|
||||
bool mTextChanged;
|
||||
bool mColorizerEnabled;
|
||||
float mLongest;
|
||||
float mTextStart; // position (in pixels) where a code line starts relative to the left of the TextEditor.
|
||||
int mLeftMargin;
|
||||
bool mCursorPositionChanged;
|
||||
|
@ -846,6 +846,20 @@ void TextEditor::HandleMouseInputs() {
|
||||
}
|
||||
}
|
||||
|
||||
int TextEditor::GetLongestLineLength() const {
|
||||
int result = 0;
|
||||
for (int i = 0; i < (int)mLines.size(); i++)
|
||||
result = std::max(result, GetLineCharacterCount(i));
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void TextUnformattedColoredAt(const ImVec2 &pos, const ImU32 &color, const char *text) {
|
||||
ImGui::SetCursorScreenPos(pos);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,color);
|
||||
ImGui::TextUnformatted(text);
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
void TextEditor::Render() {
|
||||
/* Compute mCharAdvance regarding scaled font size (Ctrl + mouse wheel)*/
|
||||
const float fontSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, "#", nullptr, nullptr).x;
|
||||
@ -881,6 +895,7 @@ void TextEditor::Render() {
|
||||
auto lineNo = (int)(std::floor(scrollY / mCharAdvance.y));
|
||||
auto globalLineMax = (int)mLines.size();
|
||||
auto lineMax = std::max(0, std::min((int)mLines.size() - 1, lineNo + (int)std::ceil((scrollY + contentSize.y) / mCharAdvance.y)));
|
||||
mLongest = GetLongestLineLength() * mCharAdvance.x;
|
||||
|
||||
// Deduce mTextStart by evaluating mLines size (global lineMax) plus two spaces as text width
|
||||
char buf[16];
|
||||
@ -930,7 +945,7 @@ void TextEditor::Render() {
|
||||
snprintf(buf, 16, "%d ", lineNo + 1);
|
||||
|
||||
auto lineNoWidth = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, buf, nullptr, nullptr).x;
|
||||
drawList->AddText(ImVec2(lineStartScreenPos.x + mTextStart - lineNoWidth, lineStartScreenPos.y), mPalette[(int)PaletteIndex::LineNumber], buf);
|
||||
TextUnformattedColoredAt(ImVec2(lineStartScreenPos.x + mTextStart - lineNoWidth, lineStartScreenPos.y),mPalette[(int) PaletteIndex::LineNumber],buf);
|
||||
}
|
||||
|
||||
// Draw breakpoints
|
||||
@ -1040,7 +1055,7 @@ void TextEditor::Render() {
|
||||
|
||||
if ((color != prevColor || glyph.mChar == '\t' || glyph.mChar == ' ') && !mLineBuffer.empty()) {
|
||||
const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y);
|
||||
drawList->AddText(newOffset, prevColor, mLineBuffer.c_str());
|
||||
TextUnformattedColoredAt(newOffset, prevColor, mLineBuffer.c_str());
|
||||
auto textSize = ImGui::GetFont()->CalcTextSizeA(ImGui::GetFontSize(), FLT_MAX, -1.0f, mLineBuffer.c_str(), nullptr, nullptr);
|
||||
bufferOffset.x += textSize.x;
|
||||
mLineBuffer.clear();
|
||||
@ -1112,7 +1127,7 @@ void TextEditor::Render() {
|
||||
|
||||
if (!mLineBuffer.empty()) {
|
||||
const ImVec2 newOffset(textScreenPos.x + bufferOffset.x, textScreenPos.y + bufferOffset.y);
|
||||
drawList->AddText(newOffset, prevColor, mLineBuffer.c_str());
|
||||
TextUnformattedColoredAt(newOffset, prevColor, mLineBuffer.c_str());
|
||||
mLineBuffer.clear();
|
||||
}
|
||||
|
||||
@ -1123,7 +1138,7 @@ void TextEditor::Render() {
|
||||
|
||||
}
|
||||
|
||||
ImGui::Dummy(ImVec2((longest + 2), mLines.size() * mCharAdvance.y));
|
||||
ImGui::Dummy(ImVec2(mLongest, (globalLineMax - lineMax - 2) * mCharAdvance.y + ImGui::GetCurrentWindow()->InnerClipRect.GetHeight()));
|
||||
|
||||
if (mScrollToCursor) {
|
||||
EnsureCursorVisible();
|
||||
|
Loading…
x
Reference in New Issue
Block a user