using System.Collections.ObjectModel;
using System.Drawing;
using Mindmagma.Curses;
namespace SCI.CursesWrapper;
public class Window {
///
/// Gets or sets the window position on the screen
///
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;
}
}
///
/// Gets or sets the width and height of the window
///
private Size _windowSize;
public Size WindowSize {
get {
return _windowSize;
}
set {
_windowSize = value;
}
}
///
/// Gets or sets the window background color pair
///
private uint _backgroundColorId;
public uint BackgroundColorId {
get {
return _backgroundColorId;
}
set {
NCurses.WindowBackground (WindowId, value);
Redraw ();
_backgroundColorId = value;
}
}
///
/// Sets the parent window
///
private Window? _parentWindow;
public Window? ParentWindow { get { return _parentWindow; }}
///
/// Holds a list of children windows this window posesses
///
private List _childWindows = new List ();
public ReadOnlyCollection ChildWindows { get { return _childWindows.AsReadOnly (); }}
///
/// Holds the pointer for this window
///
private nint _windowId;
public nint WindowId { get { return _windowId; }}
///
/// Input handler assigned to this window
///
private InputHandler? inputHandler;
///
/// Event handler called when this window is active and a key is pressed
///
public event InputHandler.KeypressEventHandler? OnKeyPress;
///
/// Create new window by specifying X/Y and Width/Height geometry
///
///
///
///
///
///
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 ();
}
///
/// Create new window by specifying geometry through Point and Size objects
///
///
///
///
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 ();
}
///
/// Adds a child window to this window
///
///
public void AddChildWindow (Window child) {
if (_childWindows.Contains (child)) return;
_childWindows.Add (child);
}
///
/// Removes a child window from this window
///
///
public void RemoveChildWindow (Window child) {
if (!_childWindows.Contains (child)) return;
_childWindows.Remove (child);
}
///
/// Discards all optimization options about drawn parts of this window.
/// Call before drawing a sub window
///
public void TouchWin () {
NCurses.TouchWindow (WindowId);
}
///
/// Redraws this window
///
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);
}
///
/// Destroys this window and all children windows
///
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
}
///
/// Register an input handler for this window to attach to OnKeyPress events
///
/// InputHandler to register
public void RegisterInputHandler (InputHandler targetInputHandler) {
if (inputHandler is not null) throw new Exception (
"Another input handler is already registered"
);
inputHandler = targetInputHandler;
inputHandler.OnKeyPress += KeyPressHandler;
}
///
/// Detach from all OnKeyPress events and unset input handler
///
public void UnregisterInputHandler () {
if (inputHandler is null) return;
inputHandler.OnKeyPress -= KeyPressHandler;
}
///
/// Handle key press events from the input handler
///
///
///
private void KeyPressHandler (object sender, NCursesKeyPressEventArgs e) {
if (e.SourceWindow != this) return;
if (OnKeyPress is not null) {
OnKeyPress (sender, e);
}
}
///
/// Tells the input handler this window is active
///
public void SetWindowActive () {
if (inputHandler is null) return;
inputHandler.ActiveWindow = this;
}
///
/// Enables or disables a border around this window
///
/// Sets the status of the border
/// If specified, uses this character as the top and bottom border
/// If specified, uses this character as the left and right border
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, ' ', ' ');
}
}
}