You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.4 KiB

using System.Runtime.InteropServices.Marshalling;
using Mindmagma.Curses;
namespace ANSI_Fahrplan.UiElements;
public class InputBox {
public delegate void InputCompleted (string input);
public void RequestInput (nint screen, InputHandler inputHandler, InputCompleted callback, string question) {
const int boxPaddingTop = 1;
const int boxPaddingSides = 2;
const int boxPaddingBottom = 2;
const int boxMarginTopBottom = 1;
const int boxMarginSides = 2;
NCurses.GetMaxYX (screen, out int height, out int width);
// Contents inside the question box may not be larger than these
int maxInnerWidth = width - (boxPaddingSides * 2) - (boxMarginSides * 2);
int maxInnerHeight = height - boxPaddingTop - boxPaddingBottom - boxMarginTopBottom;
using var strReader = new StringReader (question);
string? inStr;
int innerWidth = 1;
int innerHeight = 1;
while ((inStr = strReader.ReadLine ()) is not null) {
if (inStr.Length > innerWidth) innerWidth = inStr.Length;
if (innerWidth > maxInnerWidth) {
innerWidth = maxInnerWidth;
innerHeight += (int) Math.Ceiling (inStr.Length / (double) maxInnerWidth);
} else {
innerHeight ++;
}
}
int boxWidth = innerWidth + (boxPaddingSides * 2);
int boxHeight = innerHeight + boxPaddingTop + boxPaddingBottom;
int boxAnchorX = (width / 2) - (boxWidth / 2);
int boxAnchorY = (height / 2) - (boxHeight / 2);
var boxWin = NCurses.SubWindow (screen, boxHeight, boxWidth, boxAnchorY, boxAnchorX);
NCurses.Box (boxWin, (char) 0, (char) 0);
NCurses.Refresh ();
NCurses.WindowRefresh (boxWin);
int questionTextWinAnchorX = boxAnchorX + boxPaddingSides;
int questionTextWinAnchorY = boxAnchorY + boxPaddingTop;
var questionTextWin = NCurses.SubWindow (boxWin, innerHeight, innerWidth, questionTextWinAnchorY, questionTextWinAnchorX);
NCurses.WindowAddString (questionTextWin, question.Trim ());
NCurses.WindowRefresh (questionTextWin);
int inputFieldWinX = questionTextWinAnchorX;
int inputFieldWinY = boxAnchorY + boxHeight - boxMarginTopBottom - 1;
var inputFieldWin = NCurses.SubWindow (boxWin, 1, innerWidth, inputFieldWinY, inputFieldWinX);
NCurses.WindowBackground (inputFieldWin, ColorSchemes.TextInputField ());
NCurses.WindowAttributeSet (inputFieldWin, ColorSchemes.TextInputField ());
NCurses.WindowRefresh (inputFieldWin);
NCurses.MoveWindow (inputFieldWin, inputFieldWinY, inputFieldWinX);
NCurses.SetCursor (1);
NCurses.Echo ();
var userInput = "";
InputHandler.KeypressEventHandler handlerFunction = (object sender, NCursesKeyPressEventArgs e) => {
if (e.KeyCode == '\n' || e.KeyCode == CursesKey.ENTER) {
callback (userInput);
}
if (e.KeyCode == '\n' || e.KeyCode == CursesKey.ENTER || e.KeyCode == CursesKey.ESC) {
NCurses.SetCursor (0);
NCurses.NoEcho ();
inputHandler.DisableRawEventHandler (screen);
NCurses.MoveWindow (screen, 0, 0);
NCurses.DeleteWindow (inputFieldWin);
NCurses.DeleteWindow (questionTextWin);
NCurses.DeleteWindow (boxWin);
NCurses.Refresh ();
} else if (e.KeyCode == CursesKey.BACKSPACE) {
userInput = userInput.Substring (0, userInput.Length - 2);
} else if (char.IsAscii ((char) e.KeyCode)) {
userInput += (char) e.KeyCode;
}
NCurses.MoveWindow (inputFieldWin, inputFieldWinY, inputFieldWinX);
};
inputHandler.EnableRawEventHandler (handlerFunction, inputFieldWin);
}
}