|
|
|
using System.Diagnostics.Contracts;
|
|
|
|
using System.IO.Pipes;
|
|
|
|
using Microsoft.VisualBasic;
|
|
|
|
using Mindmagma.Curses;
|
|
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
|
|
|
|
namespace SCI.CursesWrapper;
|
|
|
|
|
|
|
|
public class Helper {
|
|
|
|
/// <summary>
|
|
|
|
/// Create a centered NCurses window on the specified screen
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="screen">Parent screen to attach window to</param>
|
|
|
|
/// <param name="width">Width of columns of window</param>
|
|
|
|
/// <param name="height">Height of rows of window</param>
|
|
|
|
/// <param name="borders">If true, shows default borders around window</param>
|
|
|
|
/// <returns>nint - Pointer of new window</returns>
|
|
|
|
/// <exception cref="ArgumentOutOfRangeException">Throws exception if window is outside of screen bounds</exception>
|
|
|
|
public static nint CreateCenteredWindow (nint screen, int width, int height, bool borders = true) {
|
|
|
|
NCurses.GetMaxYX (screen, out int screenHeight, out int screenWidth);
|
|
|
|
|
|
|
|
int originY = (screenHeight / 2) - (height / 2);
|
|
|
|
int originX = (screenWidth / 2) - (width / 2);
|
|
|
|
|
|
|
|
if (originX + width > screenWidth) throw new ArgumentOutOfRangeException ("width");
|
|
|
|
if (originY + height > screenHeight) throw new ArgumentOutOfRangeException ("height");
|
|
|
|
|
|
|
|
if (originX < 0) throw new ArgumentOutOfRangeException ("originX");
|
|
|
|
if (originY < 0) throw new ArgumentOutOfRangeException ("originY");
|
|
|
|
|
|
|
|
nint window = NCurses.NewWindow (height, width, originY, originX);
|
|
|
|
if (borders) NCurses.Box (window, (char) 0, (char) 0);
|
|
|
|
|
|
|
|
return window;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Prints text horizontally centered to window (on a specific line);
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window">Parent window to print into</param>
|
|
|
|
/// <param name="text">Text to display</param>
|
|
|
|
/// <param name="y">Y posititon of the text</param>
|
|
|
|
public static void PrintHCenteredText (nint window, string text, int y = 0) {
|
|
|
|
NCurses.GetMaxYX (window, out int _, out int windowWidth);
|
|
|
|
|
|
|
|
var x = windowWidth / 2 - text.Length / 2;
|
|
|
|
NCurses.MoveWindowAddString (window, y, x, text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public class MessageBox {
|
|
|
|
public enum MessageBoxButtons {
|
|
|
|
OK,
|
|
|
|
YesNo,
|
|
|
|
RetryCancel,
|
|
|
|
RetryIgnoreCancel
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Shows a message box with specified text and returns the selected button from zero index
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="screen">Parent screen to show message box on</param>
|
|
|
|
/// <param name="text">Text to show</param>
|
|
|
|
/// <param name="buttons">Type of buttons to show</param>
|
|
|
|
/// <returns>Button pressed by user, zero indexed</returns>
|
|
|
|
public static int Show (nint screen, string text, MessageBoxButtons buttons = MessageBoxButtons.OK) {
|
|
|
|
NCurses.GetMaxYX (screen, out int screenHeight, out int screenWidth);
|
|
|
|
|
|
|
|
// Set static box width, if width is larger than screen, reduce to screen size,
|
|
|
|
// then calculate the message box and inner pad origin X coords
|
|
|
|
var boxWidth = 50;
|
|
|
|
if (boxWidth + 3 >= screenWidth) boxWidth = screenWidth - 3;
|
|
|
|
int originX = (screenWidth / 2) - (boxWidth / 2);
|
|
|
|
var padOriginX = originX + 2; // Add one for the border and for a single character padding
|
|
|
|
|
|
|
|
// Calculate sizes for the inner pad element
|
|
|
|
var padWidth = boxWidth - 4; // Add four to the total box width due to the two character padding on both sides
|
|
|
|
var totalTextLines = (int) Math.Ceiling ((double) text.Length / padWidth); // Get total amount of lines required to hold all text limited by box width
|
|
|
|
var padHeight = totalTextLines;
|
|
|
|
if (padHeight + 8 > screenHeight) { // If height required to show all text lines plus padding is larger than screen, reduce size of message box
|
|
|
|
padHeight = screenHeight - 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Now calculate the height and Y origin of the text box and inner pad
|
|
|
|
var boxHeight = padHeight + 6; // Add five to the pad height due to the title bar and two character padding top and bottom
|
|
|
|
if (boxHeight + 2 > screenHeight) boxHeight = screenHeight - 2;
|
|
|
|
int originY = (screenHeight / 2) - (boxHeight / 2);
|
|
|
|
var padOriginY = originY + 3; // Add one for the border, one for the title and one for a single character padding
|
|
|
|
|
|
|
|
//if (text.Length > (totalTextRows * textCols)) text = text.Substring (0, (totalTextRows * textCols) - 1) + "$";
|
|
|
|
|
|
|
|
// Create message box and inner Pad
|
|
|
|
var msgBoxWindow = Helper.CreateCenteredWindow (screen, boxWidth, boxHeight, true);
|
|
|
|
var msgTextPad = NCurses.NewPad (padHeight, padWidth);
|
|
|
|
|
|
|
|
NCurses.Refresh ();
|
|
|
|
|
|
|
|
// Title, currently not in use
|
|
|
|
Helper.PrintHCenteredText (msgBoxWindow, "Info", 1);
|
|
|
|
NCurses.WindowRefresh (msgBoxWindow);
|
|
|
|
|
|
|
|
NCurses.WindowAddString (msgTextPad, text);
|
|
|
|
|
|
|
|
NCurses.PadRefresh (msgTextPad, 0, 0, padOriginY, padOriginX, padOriginY + padHeight, padOriginX + padWidth);
|
|
|
|
|
|
|
|
return InputHandler (msgBoxWindow, buttons);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static List<string> GetStringsFromButtonEnum (MessageBoxButtons buttons) {
|
|
|
|
List<string> buttonStrings;
|
|
|
|
|
|
|
|
switch (buttons) {
|
|
|
|
case MessageBoxButtons.OK:
|
|
|
|
buttonStrings = new List<string> () { "OK" };
|
|
|
|
break;
|
|
|
|
case MessageBoxButtons.YesNo:
|
|
|
|
buttonStrings = new List<string> () { "Yes", "No" };
|
|
|
|
break;
|
|
|
|
case MessageBoxButtons.RetryCancel:
|
|
|
|
buttonStrings = new List<string> () { "Retry", "Cancel" };
|
|
|
|
break;
|
|
|
|
case MessageBoxButtons.RetryIgnoreCancel:
|
|
|
|
buttonStrings = new List<string> () { "Retry", "Ignore", "Cancel" };
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Exception ("Unknown button layout for message box");
|
|
|
|
}
|
|
|
|
|
|
|
|
return buttonStrings;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Draws buttons specified by the buttons type
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window">Window to draw buttons on</param>
|
|
|
|
/// <param name="buttons">Buttons to display</param>
|
|
|
|
private static void DrawButtons (nint window, MessageBoxButtons buttons, int active = 0) {
|
|
|
|
NCurses.GetMaxYX (window, out int windowHeight, out int windowWidth);
|
|
|
|
|
|
|
|
var buttonStrings = GetStringsFromButtonEnum (buttons);
|
|
|
|
var totalStringLength = buttonStrings.Count - 1;
|
|
|
|
foreach (var str in buttonStrings) totalStringLength += str.Length + 2;
|
|
|
|
|
|
|
|
NCurses.WindowMove (window, windowHeight - 2, (windowWidth / 2) - (totalStringLength / 2));
|
|
|
|
|
|
|
|
var index = 0;
|
|
|
|
foreach (var str in buttonStrings) {
|
|
|
|
if (index == active) {
|
|
|
|
NCurses.WindowAddString (window, $"[{str}]");
|
|
|
|
} else {
|
|
|
|
NCurses.WindowAddString (window, $" {str} ");
|
|
|
|
}
|
|
|
|
|
|
|
|
NCurses.WindowAddChar (window, ' ');
|
|
|
|
|
|
|
|
index ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
NCurses.WindowRefresh (window);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Handle the user selection of the buttons
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="window">Window to draw buttons on</param>
|
|
|
|
/// <param name="buttons">Buttons to display</param>
|
|
|
|
/// <returns>User choice of button, zero indexed</returns>
|
|
|
|
private static int InputHandler (nint window, MessageBoxButtons buttons) {
|
|
|
|
DrawButtons (window, buttons);
|
|
|
|
|
|
|
|
int index = 0;
|
|
|
|
int maxIndex = GetStringsFromButtonEnum (buttons).Count - 1;
|
|
|
|
|
|
|
|
int chr = 0;
|
|
|
|
while ((chr = NCurses.GetChar ()) != 10) {
|
|
|
|
if (chr == 260) { // Left
|
|
|
|
index ++;
|
|
|
|
if (index > maxIndex) index = 0;
|
|
|
|
DrawButtons (window, buttons, index);
|
|
|
|
} else if (chr == 261) { // Right
|
|
|
|
index --;
|
|
|
|
if (index < 0) index = maxIndex;
|
|
|
|
DrawButtons (window, buttons, index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
}
|