parent
fa4fd92cdf
commit
04677ab97a
@ -1,6 +1,6 @@
|
||||
using Mindmagma.Curses;
|
||||
|
||||
namespace ANSI_Fahrplan;
|
||||
namespace SCI.CursesWrapper;
|
||||
|
||||
public class ColorSchemes {
|
||||
public static void InitAll () {
|
@ -0,0 +1,41 @@
|
||||
using Mindmagma.Curses;
|
||||
|
||||
namespace SCI.CursesWrapper;
|
||||
|
||||
public class CursesWrapper {
|
||||
/// <summary>
|
||||
/// Initializes NCurses and creates a screen
|
||||
/// </summary>
|
||||
public static nint InitNCurses () {
|
||||
var screen = NCurses.InitScreen ();
|
||||
NCurses.SetCursor (0);
|
||||
NCurses.NoEcho ();
|
||||
|
||||
if (NCurses.HasColors ()) {
|
||||
NCurses.StartColor ();
|
||||
ColorSchemes.InitAll ();
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the total width of a window
|
||||
/// </summary>
|
||||
/// <param name="window">Window to query</param>
|
||||
/// <returns>Width of window in columns</returns>
|
||||
public static int GetWidth (nint window) {
|
||||
NCurses.GetMaxYX (window, out int _, out int width);
|
||||
return width;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the total height of a window
|
||||
/// </summary>
|
||||
/// <param name="window">Window to query</param>
|
||||
/// <returns>Height of window in rows</returns>
|
||||
public static int GetHeight (nint window) {
|
||||
NCurses.GetMaxYX (window, out int height, out int _);
|
||||
return height;
|
||||
}
|
||||
}
|
@ -0,0 +1,265 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using Mindmagma.Curses;
|
||||
|
||||
namespace SCI.CursesWrapper;
|
||||
|
||||
public class Window {
|
||||
/// <summary>
|
||||
/// Gets or sets the window position on the screen
|
||||
/// </summary>
|
||||
private Point _position;
|
||||
public Point Position {
|
||||
get {
|
||||
return _position;
|
||||
}
|
||||
set {
|
||||
if (ParentWindow is not null) {
|
||||
NCurses.WindowMove (
|
||||
WindowId,
|
||||
ParentWindow.Position.Y + value.Y,
|
||||
ParentWindow.Position.X + value.X
|
||||
);
|
||||
} else {
|
||||
NCurses.WindowMove (
|
||||
WindowId,
|
||||
value.Y,
|
||||
value.X
|
||||
);
|
||||
}
|
||||
_position = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the width and height of the window
|
||||
/// </summary>
|
||||
private Size _windowSize;
|
||||
public Size WindowSize {
|
||||
get {
|
||||
return _windowSize;
|
||||
}
|
||||
set {
|
||||
_windowSize = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the window background color pair
|
||||
/// </summary>
|
||||
private uint _backgroundColorId;
|
||||
public uint BackgroundColorId {
|
||||
get {
|
||||
return _backgroundColorId;
|
||||
}
|
||||
set {
|
||||
NCurses.WindowBackground (WindowId, value);
|
||||
Redraw ();
|
||||
_backgroundColorId = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the parent window
|
||||
/// </summary>
|
||||
private Window? _parentWindow;
|
||||
public Window? ParentWindow { get { return _parentWindow; }}
|
||||
|
||||
/// <summary>
|
||||
/// Holds a list of children windows this window posesses
|
||||
/// </summary>
|
||||
private List<Window> _childWindows = new List<Window> ();
|
||||
public ReadOnlyCollection<Window> ChildWindows { get { return _childWindows.AsReadOnly (); }}
|
||||
|
||||
/// <summary>
|
||||
/// Holds the pointer for this window
|
||||
/// </summary>
|
||||
private nint _windowId;
|
||||
public nint WindowId { get { return _windowId; }}
|
||||
|
||||
/// <summary>
|
||||
/// Input handler assigned to this window
|
||||
/// </summary>
|
||||
private InputHandler? inputHandler;
|
||||
|
||||
/// <summary>
|
||||
/// Event handler called when this window is active and a key is pressed
|
||||
/// </summary>
|
||||
public event InputHandler.KeypressEventHandler? OnKeyPress;
|
||||
|
||||
/// <summary>
|
||||
/// Create new window by specifying X/Y and Width/Height geometry
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="parentWindow"></param>
|
||||
public Window (int x, int y, int width, int height, Window? parentWindow = null) {
|
||||
if (parentWindow is not null) {
|
||||
_windowId = NCurses.DeriveWindow (
|
||||
parentWindow.WindowId,
|
||||
height, width,
|
||||
y, x
|
||||
);
|
||||
} else {
|
||||
_windowId = NCurses.NewWindow (
|
||||
height, width,
|
||||
y, x
|
||||
);
|
||||
}
|
||||
|
||||
Redraw ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create new window by specifying geometry through Point and Size objects
|
||||
/// </summary>
|
||||
/// <param name="position"></param>
|
||||
/// <param name="windowSize"></param>
|
||||
/// <param name="parentWindow"></param>
|
||||
public Window (Point position, Size windowSize, Window? parentWindow = null) {
|
||||
if (parentWindow is not null) {
|
||||
_windowId = NCurses.SubWindow (
|
||||
parentWindow.WindowId,
|
||||
windowSize.Height, windowSize.Width,
|
||||
position.Y, position.X
|
||||
);
|
||||
} else {
|
||||
_windowId = NCurses.NewWindow (
|
||||
windowSize.Height, windowSize.Width,
|
||||
position.Y, position.X
|
||||
);
|
||||
}
|
||||
|
||||
Redraw ();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a child window to this window
|
||||
/// </summary>
|
||||
/// <param name="child"></param>
|
||||
public void AddChildWindow (Window child) {
|
||||
if (_childWindows.Contains (child)) return;
|
||||
_childWindows.Add (child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a child window from this window
|
||||
/// </summary>
|
||||
/// <param name="child"></param>
|
||||
public void RemoveChildWindow (Window child) {
|
||||
if (!_childWindows.Contains (child)) return;
|
||||
_childWindows.Remove (child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Discards all optimization options about drawn parts of this window.
|
||||
/// Call before drawing a sub window
|
||||
/// </summary>
|
||||
public void TouchWin () {
|
||||
NCurses.TouchWindow (WindowId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Redraws this window
|
||||
/// </summary>
|
||||
public void Redraw () {
|
||||
NCurses.Refresh (); // TODO: Necessary?
|
||||
|
||||
if (ChildWindows.Count > 0) {
|
||||
foreach (var window in ChildWindows) {
|
||||
window.Redraw ();
|
||||
}
|
||||
}
|
||||
|
||||
if (ParentWindow is not null) ParentWindow.TouchWin ();
|
||||
NCurses.WindowRefresh (WindowId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys this window and all children windows
|
||||
/// </summary>
|
||||
public void Destroy () {
|
||||
if (ChildWindows.Count > 0) {
|
||||
foreach (var window in _childWindows) {
|
||||
window.Destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
if (inputHandler is not null) inputHandler.ActiveWindow = null;
|
||||
if (ParentWindow is not null) ParentWindow.RemoveChildWindow (this);
|
||||
|
||||
UnregisterInputHandler ();
|
||||
|
||||
SetBorder (false);
|
||||
|
||||
NCurses.ClearWindow (WindowId);
|
||||
Console.Title = "About to destroy";
|
||||
NCurses.DeleteWindow (WindowId);
|
||||
Console.Title = "Destroyed";
|
||||
|
||||
//TODO: Program hangs on DeleteWindow
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Register an input handler for this window to attach to OnKeyPress events
|
||||
/// </summary>
|
||||
/// <param name="inputHandler">InputHandler to register</param>
|
||||
public void RegisterInputHandler (InputHandler targetInputHandler) {
|
||||
if (inputHandler is not null) throw new Exception (
|
||||
"Another input handler is already registered"
|
||||
);
|
||||
|
||||
inputHandler = targetInputHandler;
|
||||
inputHandler.OnKeyPress += KeyPressHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Detach from all OnKeyPress events and unset input handler
|
||||
/// </summary>
|
||||
public void UnregisterInputHandler () {
|
||||
if (inputHandler is null) return;
|
||||
|
||||
inputHandler.OnKeyPress -= KeyPressHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle key press events from the input handler
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void KeyPressHandler (object sender, NCursesKeyPressEventArgs e) {
|
||||
if (e.SourceWindow != this) return;
|
||||
|
||||
if (OnKeyPress is not null) {
|
||||
OnKeyPress (sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tells the input handler this window is active
|
||||
/// </summary>
|
||||
public void SetWindowActive () {
|
||||
if (inputHandler is null) return;
|
||||
|
||||
inputHandler.ActiveWindow = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables or disables a border around this window
|
||||
/// </summary>
|
||||
/// <param name="enabled">Sets the status of the border</param>
|
||||
/// <param name="horizontalChar">If specified, uses this character as the top and bottom border</param>
|
||||
/// <param name="verticalChar">If specified, uses this character as the left and right border</param>
|
||||
public void SetBorder (bool enabled, char? horizontalChar = null, char? verticalChar = null) {
|
||||
if (horizontalChar is null) horizontalChar = (char) 0;
|
||||
if (verticalChar is null) verticalChar = (char) 0;
|
||||
|
||||
if (enabled) {
|
||||
NCurses.Box (WindowId, (char) horizontalChar, (char) verticalChar);
|
||||
} else {
|
||||
NCurses.Box (WindowId, ' ', ' ');
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,28 @@
|
||||
using Mindmagma.Curses;
|
||||
using SCI.CursesWrapper;
|
||||
|
||||
namespace ANSI_Fahrplan.Screens;
|
||||
|
||||
public class IntroScreen : Screen {
|
||||
public class IntroScreen : Window {
|
||||
private nint infoTextBox;
|
||||
|
||||
/// <summary>
|
||||
/// Pass class constructor through to inherited constructor
|
||||
/// </summary>
|
||||
/// <param name="rootWindow">Root window to use for this screen</param>
|
||||
public IntroScreen (nint rootWindow) : base (rootWindow) { }
|
||||
|
||||
public override void Show () {
|
||||
string asciiArtPlusText =
|
||||
"Press F1 for a quick start guide or simply press Enter\n" +
|
||||
"to see upcoming events\n" +
|
||||
AsciiArt.logo38c3_80x24 +
|
||||
"\n38C3 Fahrplan in your terminal!";
|
||||
|
||||
AsciiArt.ShowCentered (RootWindow, asciiArtPlusText);
|
||||
|
||||
//infoTextBox = NCurses.SubWindow (infoTextBox, );
|
||||
|
||||
NCurses.Refresh ();
|
||||
NCurses.WindowRefresh (RootWindow);
|
||||
}
|
||||
|
||||
public override void Hide () {
|
||||
|
||||
/// <param name="parentWindow">Parent window of this window object</param>
|
||||
public IntroScreen (nint screen) :
|
||||
base (
|
||||
1, 1,
|
||||
CursesWrapper.GetWidth (screen) - 2,
|
||||
CursesWrapper.GetHeight (screen) - 2
|
||||
)
|
||||
{
|
||||
string asciiArtPlusText =
|
||||
"Press F1 for a quick start guide or simply press Enter\n" +
|
||||
"to see upcoming events\n" +
|
||||
AsciiArt.logo38c3_80x24 +
|
||||
"\n38C3 Fahrplan in your terminal!";
|
||||
|
||||
AsciiArt.ShowCentered (WindowId, asciiArtPlusText);
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace ANSI_Fahrplan.Screens;
|
||||
|
||||
public abstract class ScrollableScreen : Screen {
|
||||
|
||||
public ScrollableScreen (nint rootWindow) : base (rootWindow) {}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in new issue