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.

109 lines
2.8 KiB

4 weeks ago
using System.Drawing;
using Mindmagma.Curses;
namespace SCI.CursesWrapper;
public class ScrollWindow : Window {
private nint _innerPadId;
public nint InnerPadId { get { return _innerPadId; }}
private Point _scrollPosition;
public Point ScrollPosition { get { return _scrollPosition; }}
private Size _padSize;
public Size PadSize { get { return _padSize; }}
public ScrollWindow (Window parentWindow, InputHandler inputHandler, int innerHeight = -1) :
base (0, 0, 0, 0, inputHandler, parentWindow)
{
var padWidth = GetUsableWidth ();
var padHeight = innerHeight;
if (padHeight == -1) {
padHeight = parentWindow.GetUsableHeight ();
}
_innerPadId = NCurses.NewPad (padHeight, padWidth);
_padSize = new Size (padWidth, padHeight);
NCurses.WindowBackground (InnerPadId, ColorSchemes.TextInputField ());
ShowPad ();
OnKeyPress += ScrollKeyHandler;
}
/// <summary>
/// Scrolls the window up or down on up key or down key
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ScrollKeyHandler (object sender, NCursesKeyPressEventArgs e) {
if (e.SourceWindow is null || e.SourceWindow != this) return;
if (e.KeyCode == CursesKey.UP) {
ScrollTo (ScrollPosition.X, ScrollPosition.Y - 1);
} else if (e.KeyCode == CursesKey.DOWN) {
ScrollTo (ScrollPosition.X, ScrollPosition.Y + 1);
}
}
/// <summary>
/// Scrolls the pad to the specified coordinates
/// </summary>
/// <param name="scrollX"></param>
/// <param name="scrollY"></param>
public void ScrollTo (int scrollX, int scrollY) {
if (ParentWindow is null) return;
_scrollPosition = new Point (scrollX, scrollY);
ShowPad ();
}
/// <summary>
/// Shows the pad the current scroll location
/// </summary>
public void ShowPad () {
if (ParentWindow is null) return;
var scrollToX = ScrollPosition.X;
var scrollToY = ScrollPosition.Y;
var viewableWidth = GetUsableWidth ();
var viewableHeight = GetUsableHeight ();
// Check for unnecessary scrolling due to small Pad size
if (PadSize.Width <= viewableWidth) {
scrollToX = 0;
}
if (PadSize.Height <= viewableHeight) {
scrollToY = 0;
}
// Check values for upper bounds
if (scrollToX > PadSize.Width - viewableWidth) scrollToX = PadSize.Width - viewableWidth;
if (scrollToY > PadSize.Height - viewableHeight) scrollToY = PadSize.Height - viewableHeight;
// Check values for lower bounds
if (scrollToX < 0) scrollToX = 0;
if (scrollToY < 0) scrollToY = 0;
// Store potentially updated scroll coordinates
_scrollPosition = new Point (scrollToX, scrollToY);
var fromY = Position.Y;
var fromX = Position.X;
var toY = viewableHeight;
var toX = viewableWidth - 2; // TODO: Why the two? How is the geometry this wong?!
NCurses.PadRefresh (
_innerPadId,
scrollToY, scrollToX,
fromY,
fromX,
toY,
toX
);
}
}