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
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);
|
|
}
|
|
} |