using System.Diagnostics.Contracts;
using System.IO.Pipes;
using Microsoft.VisualBasic;
using Mindmagma.Curses;
using Newtonsoft.Json.Linq;
namespace SCI.CursesWrapper;
public class Helper {
///
/// Create a centered NCurses window on the specified screen
///
/// Parent screen to attach window to
/// Width of columns of window
/// Height of rows of window
/// If true, shows default borders around window
/// nint - Pointer of new window
/// Throws exception if window is outside of screen bounds
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;
}
///
/// Prints text horizontally centered to window (on a specific line);
///
/// Parent window to print into
/// Text to display
/// Y posititon of the text
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
}
///
/// Shows a message box with specified text and returns the selected button from zero index
///
/// Parent screen to show message box on
/// Text to show
/// Type of buttons to show
/// Button pressed by user, zero indexed
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 GetStringsFromButtonEnum (MessageBoxButtons buttons) {
List buttonStrings;
switch (buttons) {
case MessageBoxButtons.OK:
buttonStrings = new List () { "OK" };
break;
case MessageBoxButtons.YesNo:
buttonStrings = new List () { "Yes", "No" };
break;
case MessageBoxButtons.RetryCancel:
buttonStrings = new List () { "Retry", "Cancel" };
break;
case MessageBoxButtons.RetryIgnoreCancel:
buttonStrings = new List () { "Retry", "Ignore", "Cancel" };
break;
default:
throw new Exception ("Unknown button layout for message box");
}
return buttonStrings;
}
///
/// Draws buttons specified by the buttons type
///
/// Window to draw buttons on
/// Buttons to display
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);
}
///
/// Handle the user selection of the buttons
///
/// Window to draw buttons on
/// Buttons to display
/// User choice of button, zero indexed
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;
}
}
public class ColorPairs {
public static int Ch_Topmenu_Label = 101;
public static int Ch_Topmenu_Label_Active = 102;
public static void InitColors () {
NCurses.InitPair (101, CursesColor.WHITE, CursesColor.BLUE);
NCurses.InitPair (102, CursesColor.BLACK, CursesColor.BLUE);
}
}
public class TopMenu {
private nint parentScreen;
private nint childWindow;
public List