Skip to content

Commit

Permalink
Merge #3514 Rewrap ConsoleUI textbox for scrollbar and resize
Browse files Browse the repository at this point in the history
  • Loading branch information
DasSkelett committed Jan 19, 2022
2 parents 76f2511 + 6f54fc1 commit 19af3dd
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ All notable changes to this project will be documented in this file.
- [GUI] Use CRLF for resx files (#3471 by: HebaruSan; reviewed: DasSkelett)
- [Core] Case insensitive installed file lookup on Windows (#3479 by: HebaruSan; reviewed: DasSkelett)
- [Core] Properly determine the game when cloning instances (#3478 by: DasSkelett; reviewed: HebaruSan)
- [ConsoleUI] Rewrap ConsoleUI textbox for scrollbar and resize (#3514 by: HebaruSan; reviewed: DasSkelett)

### Internal

Expand Down
62 changes: 50 additions & 12 deletions ConsoleUI/Toolkit/ConsoleTextBox.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public ConsoleTextBox(
align = ta;
getFgColor = fgFunc;
getBgColor = bgFunc;
prevTextW = r - l + 1;
}

/// <summary>
Expand All @@ -39,9 +40,20 @@ public ConsoleTextBox(
/// <param name="line">String to add</param>
public void AddLine(string line)
{
lines.Add(line);
int w = GetRight() - GetLeft() + 1 + (needScroll ? -1 : 0);
// AddRange isn't thread-safe, it temporarily pads with nulls
foreach (string subLine in Formatting.WordWrap(line, GetRight() - GetLeft() + 1)) {
lines.Add(subLine);
foreach (string subLine in Formatting.WordWrap(line, w)) {
displayLines.Add(subLine);
}
if (!needScroll) {
int h = GetBottom() - GetTop() + 1;
if (displayLines.Count > h) {
// We just crossed over from non-scrollbar to scrollbar,
// re-wrap the whole display including this line
needScroll = true;
rewrapLines();
}
}
if (scrollToBottom) {
ScrollToBottom();
Expand All @@ -50,6 +62,24 @@ public void AddLine(string line)
}
}

private void rewrapLines()
{
int w = GetRight() - GetLeft() + 1 + (needScroll ? -1 : 0);
prevTextW = w;
int h = GetBottom() - GetTop() + 1;
float scrollFrac = displayLines.Count > h
? (float)topLine / ((float)displayLines.Count - h)
: 0;
displayLines.Clear();
foreach (string line in lines) {
foreach (string subLine in Formatting.WordWrap(line, w)) {
displayLines.Add(subLine);
}
}
topLine = (int)Math.Max(0,
scrollFrac * (displayLines.Count - h));
}

/// <summary>
/// Scroll the text box to the top
/// </summary>
Expand All @@ -64,7 +94,7 @@ public void ScrollToTop()
public void ScrollToBottom()
{
int h = GetBottom() - GetTop() + 1;
topLine = lines.Count - h;
topLine = displayLines.Count - h;
}

/// <summary>
Expand All @@ -85,7 +115,7 @@ public void ScrollDown(int? howFar = null)
{
int h = GetBottom() - GetTop() + 1;
int diff = howFar ?? h;
if (topLine + diff <= lines.Count - h) {
if (topLine + diff <= displayLines.Count - h) {
topLine += diff;
} else {
ScrollToBottom();
Expand All @@ -101,9 +131,14 @@ public override void Draw(ConsoleTheme theme, bool focused)
{
int l = GetLeft();
int h = GetBottom() - GetTop() + 1;
int index = lines.Count < h ? 0 : topLine;
int index = displayLines.Count < h ? 0 : topLine;
// Chop one col off the right if we need a scrollbar
int w = GetRight() - l + 1 + (lines.Count > h ? -1 : 0);
int w = GetRight() - l + 1 + (needScroll ? -1 : 0);

if (w != prevTextW) {
// Width changed since last time, re-do the word wrap
rewrapLines();
}

if (getBgColor != null) {
Console.BackgroundColor = getBgColor(theme);
Expand All @@ -117,16 +152,16 @@ public override void Draw(ConsoleTheme theme, bool focused)
}
for (int y = GetTop(); y <= GetBottom(); ++y, ++index) {
Console.SetCursorPosition(l, y);
if (index < lines.Count) {
if (index < displayLines.Count) {
switch (align) {
case TextAlign.Left:
Console.Write(lines[index].PadRight(w));
Console.Write(displayLines[index].PadRight(w));
break;
case TextAlign.Center:
Console.Write(ScreenObject.PadCenter(lines[index], w));
Console.Write(ScreenObject.PadCenter(displayLines[index], w));
break;
case TextAlign.Right:
Console.Write(lines[index].PadLeft(w));
Console.Write(displayLines[index].PadLeft(w));
break;
}
} else {
Expand All @@ -135,11 +170,11 @@ public override void Draw(ConsoleTheme theme, bool focused)
}

// Scrollbar
if (lines.Count > h) {
if (needScroll) {
DrawScrollbar(
theme,
GetRight(), GetTop(), GetBottom(),
GetTop() + 1 + (h - 3) * topLine / (lines.Count - h)
GetTop() + 1 + (h - 3) * topLine / (displayLines.Count - h)
);
}
}
Expand Down Expand Up @@ -215,10 +250,13 @@ public void AddScrollBindings(ScreenContainer cont, bool drawMore = false)
/// </summary>
public override bool Focusable() { return false; }

private bool needScroll = false;
private int prevTextW;
private bool scrollToBottom;
private int topLine;
private TextAlign align;
private SynchronizedCollection<string> lines = new SynchronizedCollection<string>();
private SynchronizedCollection<string> displayLines = new SynchronizedCollection<string>();
private Func<ConsoleTheme, ConsoleColor> getBgColor;
private Func<ConsoleTheme, ConsoleColor> getFgColor;
}
Expand Down

0 comments on commit 19af3dd

Please sign in to comment.