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
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
|
||
|
);
|
||
|
}
|
||
|
}
|