void EnsureMenuAndInputIsVisible(IConsole console, int tooltipLineCount) { var bottom = this.Top + this.Rows + tooltipLineCount; if (bottom > console.BufferHeight) { var toScroll = bottom - console.BufferHeight; console.ScrollBuffer(toScroll); Singleton._initialY -= toScroll; this.Top -= toScroll; var point = Singleton.ConvertOffsetToPoint(Singleton._current); Singleton.PlaceCursor(point.X, point.Y); } }
protected void MoveCursorToStartDrawingPosition(IConsole console) { // Calculate the coord to place the cursor at the end of current input. Point bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length); // Top must be initialized before any possible adjustion by 'AdjustForPossibleScroll' or 'AdjustForActualScroll', // otherwise its value would be corrupted and cause rendering issue. Top = bufferEndPoint.Y + 1; if (bufferEndPoint.Y == console.BufferHeight) { // The input happens to end at the very last cell of the current buffer, so 'bufferEndPoint' is pointing to // the first cell at one line below the current buffer, and thus we need to scroll up the buffer. console.SetCursorPosition(console.BufferWidth - 1, console.BufferHeight - 1); // We scroll the buffer by 2 lines here, so the cursor is placed at the start of the first line after 'bufferEndPoint'. MoveCursorDown(2); bufferEndPoint.Y -= 2; AdjustForActualScroll(2); } else { // Move the cursor to the end of our input. console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y); // Move cursor to the start of the first line after our input (after 'bufferEndPoint'). AdjustForPossibleScroll(1); MoveCursorDown(1); } }
void EnsureMenuAndInputIsVisible(IConsole console, int tooltipLineCount) { // The +1 lets us write a newline after the last row, which isn't strictly necessary // It does help with: // * Console selecting multiple lines of text // * Adds a little extra space underneath the menu var bottom = this.Top + this.Rows + tooltipLineCount + 1; if (bottom > console.BufferHeight) { var toScroll = bottom - console.BufferHeight; console.ScrollBuffer(toScroll); Singleton._initialY -= toScroll; this.Top -= toScroll; var point = Singleton.ConvertOffsetToPoint(Singleton._current); Singleton.PlaceCursor(point.X, point.Y); } }
public void DrawMenu(Menu previousMenu, bool menuSelect) { IConsole console = Singleton._console; if (menuSelect) { console.CursorVisible = false; SaveCursor(); } // Move cursor to the start of the first line after our input. var bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length); console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y); // Top must be initialized before calling AdjustForPossibleScroll, otherwise // on the last line of the buffer, the scroll operation causes Top to point // past the buffer, which in turn causes the menu to be printed twice. this.Top = bufferEndPoint.Y + 1; AdjustForPossibleScroll(1); MoveCursorDown(1); var bufferWidth = console.BufferWidth; var columnWidth = this.ColumnWidth; var items = this.MenuItems; for (var row = 0; row < this.Rows; row++) { var cells = 0; for (var col = 0; col < this.Columns; col++) { var index = row + (this.Rows * col); if (index >= items.Count) { break; } console.Write(GetMenuItem(items[index].ListItemText, columnWidth)); cells += columnWidth; } // Make sure we always write out exactly 1 buffer width to erase anything // from a previous menu. if (cells < bufferWidth) { // 'BlankRestOfLine' erases rest of the current line, but the cursor is not moved. console.BlankRestOfLine(); } // Explicit newline so consoles see each row as distinct lines, but skip the // last line so we don't scroll. if (row != (this.Rows - 1) || !menuSelect) { AdjustForPossibleScroll(1); MoveCursorDown(1); } } bool extraPreRowsCleared = false; if (previousMenu != null) { if (Rows < previousMenu.Rows + previousMenu.ToolTipLines) { // If the last menu row took the whole buffer width, then the cursor could be pushed to the // beginning of the next line in the legacy console host (NOT in modern terminals such as // Windows Terminal, VSCode Terminal, or virtual-terminal-enabled console host). In such a // case, there is no need to move the cursor to the next line. // // If that is not the case, namely 'CursorLeft != 0', then the rest of the last menu row was // erased, but the cursor was not moved to the next line, so we will move the cursor. if (console.CursorLeft != 0) { // There are lines from the previous rendering that need to be cleared, // so we are sure there is no need to scroll. MoveCursorDown(1); } Singleton.WriteBlankLines(previousMenu.Rows + previousMenu.ToolTipLines - Rows); extraPreRowsCleared = true; } } // if the menu has moved, we need to clear the lines under it if (bufferEndPoint.Y < PreviousTop) { // In either of the following two cases, we will need to move the cursor to the next line: // - if extra rows from previous menu were cleared, then we know the current line was erased // but the cursor was not moved to the next line. // - if 'CursorLeft != 0', then the rest of the last menu row was erased, but the cursor // was not moved to the next line. if (extraPreRowsCleared || console.CursorLeft != 0) { // There are lines from the previous rendering that need to be cleared, // so we are sure there is no need to scroll. MoveCursorDown(1); } Singleton.WriteBlankLines(PreviousTop - bufferEndPoint.Y); } PreviousTop = bufferEndPoint.Y; if (menuSelect) { RestoreCursor(); console.CursorVisible = true; } }
public void DrawMenu(Menu previousMenu, bool menuSelect) { IConsole console = Singleton._console; if (menuSelect) { console.CursorVisible = false; SaveCursor(); } // Move cursor to the start of the first line after our input. var bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length); console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y); AdjustForPossibleScroll(1); MoveCursorDown(1); this.Top = bufferEndPoint.Y + 1; var bufferWidth = console.BufferWidth; var columnWidth = this.ColumnWidth; var items = this.MenuItems; for (var row = 0; row < this.Rows; row++) { var cells = 0; for (var col = 0; col < this.Columns; col++) { var index = row + (this.Rows * col); if (index >= items.Count) { break; } console.Write(GetMenuItem(items[index].ListItemText, columnWidth)); cells += columnWidth; } // Make sure we always write out exactly 1 buffer width to erase anything // from a previous menu. if (cells < bufferWidth) { console.BlankRestOfLine(); } // Explicit newline so consoles see each row as distinct lines, but skip the // last line so we don't scroll. if (row != (this.Rows - 1) || !menuSelect) { AdjustForPossibleScroll(1); MoveCursorDown(1); } } if (previousMenu != null) { if (Rows < previousMenu.Rows + previousMenu.ToolTipLines) { Singleton.WriteBlankLines(previousMenu.Rows + previousMenu.ToolTipLines - Rows); } } // if the menu has moved, we need to clear the lines under it if (bufferEndPoint.Y < PreviousTop) { console.BlankRestOfLine(); Singleton.WriteBlankLines(PreviousTop - bufferEndPoint.Y); } PreviousTop = bufferEndPoint.Y; if (menuSelect) { RestoreCursor(); console.CursorVisible = true; } }
public void DrawMenu(Menu previousMenu, bool menuSelect) { IConsole console = Singleton._console; if (menuSelect) { console.CursorVisible = false; SaveCursor(); } // Move cursor to the start of the first line after our input. var bufferEndPoint = Singleton.ConvertOffsetToPoint(Singleton._buffer.Length); console.SetCursorPosition(bufferEndPoint.X, bufferEndPoint.Y); // Top must be initialized before calling AdjustForPossibleScroll, otherwise // on the last line of the buffer, the scroll operation causes Top to point // past the buffer, which in turn causes the menu to be printed twice. this.Top = bufferEndPoint.Y + 1; AdjustForPossibleScroll(1); MoveCursorDown(1); var bufferWidth = console.BufferWidth; var columnWidth = this.ColumnWidth; var items = this.MenuItems; for (var row = 0; row < this.Rows; row++) { var cells = 0; for (var col = 0; col < this.Columns; col++) { var index = row + (this.Rows * col); if (index >= items.Count) { break; } console.Write(GetMenuItem(items[index].ListItemText, columnWidth)); cells += columnWidth; } // Make sure we always write out exactly 1 buffer width to erase anything // from a previous menu. if (cells < bufferWidth) { // 'BlankRestOfLine' erases rest of the current line, but the cursor is not moved. console.BlankRestOfLine(); } // Explicit newline so consoles see each row as distinct lines, but skip the // last line so we don't scroll. if (row != (this.Rows - 1) || !menuSelect) { AdjustForPossibleScroll(1); MoveCursorDown(1); } } if (previousMenu != null) { if (Rows < previousMenu.Rows + previousMenu.ToolTipLines) { // Rest of the current line was erased, but the cursor was not moved to the next line. if (console.CursorLeft != 0) { // There are lines from the previous rendering that need to be cleared, // so we are sure there is no need to scroll. MoveCursorDown(1); } Singleton.WriteBlankLines(previousMenu.Rows + previousMenu.ToolTipLines - Rows); } } // if the menu has moved, we need to clear the lines under it if (bufferEndPoint.Y < PreviousTop) { console.BlankRestOfLine(); Singleton.WriteBlankLines(PreviousTop - bufferEndPoint.Y); } PreviousTop = bufferEndPoint.Y; if (menuSelect) { RestoreCursor(); console.CursorVisible = true; } }