Files
Terminal.Gui/Terminal.Gui/View/View.ScrollBars.cs
2024-11-17 16:33:21 -07:00

197 lines
7.0 KiB
C#

#nullable enable
namespace Terminal.Gui;
public partial class View
{
private Lazy<ScrollBar> _horizontalScrollBar;
private Lazy<ScrollBar> _verticalScrollBar;
/// <summary>
/// Initializes the ScrollBars of the View. Called by the View constructor.
/// </summary>
private void SetupScrollBars ()
{
if (this is Adornment)
{
return;
}
_verticalScrollBar = new (() => CreateScrollBar (Orientation.Vertical));
_horizontalScrollBar = new (() => CreateScrollBar (Orientation.Horizontal));
}
private ScrollBar CreateScrollBar (Orientation orientation)
{
var scrollBar = new ScrollBar
{
Orientation = orientation,
Visible = false // Initially hidden until needed
};
if (orientation == Orientation.Vertical)
{
ConfigureVerticalScrollBar (scrollBar);
}
else
{
ConfigureHorizontalScrollBar (scrollBar);
}
scrollBar.Initialized += OnScrollBarInitialized;
// Add after setting Initialized event!
Padding?.Add (scrollBar);
return scrollBar;
}
private void ConfigureVerticalScrollBar (ScrollBar scrollBar)
{
scrollBar.X = Pos.AnchorEnd ();
scrollBar.Height = Dim.Fill (
Dim.Func (
() =>
{
if (_horizontalScrollBar.IsValueCreated)
{
return _horizontalScrollBar.Value.Visible ? 1 : 0;
}
return 0;
}));
scrollBar.ScrollableContentSize = GetContentSize ().Height;
ViewportChanged += (_, _) =>
{
scrollBar.Position = Viewport.Y;
};
ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Height; };
}
private void ConfigureHorizontalScrollBar (ScrollBar scrollBar)
{
scrollBar.Y = Pos.AnchorEnd ();
scrollBar.Width = Dim.Fill (
Dim.Func (
() =>
{
if (_verticalScrollBar.IsValueCreated)
{
return _verticalScrollBar.Value.Visible ? 1 : 0;
}
return 0;
}));
scrollBar.ScrollableContentSize = GetContentSize ().Width;
ViewportChanged += (_, _) =>
{
scrollBar.Position = Viewport.X;
};
ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Width; };
}
private void OnScrollBarInitialized (object? sender, EventArgs e)
{
var scrollBar = (ScrollBar)sender!;
if (scrollBar.Orientation == Orientation.Vertical)
{
ConfigureVerticalScrollBarEvents (scrollBar);
}
else
{
ConfigureHorizontalScrollBarEvents (scrollBar);
}
}
private void ConfigureVerticalScrollBarEvents (ScrollBar scrollBar)
{
Padding!.Thickness = Padding.Thickness with { Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : 0 };
scrollBar.PositionChanged += (_, args) =>
{
Viewport = Viewport with
{
Y = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
};
};
scrollBar.VisibleChanged += (_, _) =>
{
Padding.Thickness = Padding.Thickness with
{
Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : Padding.Thickness.Right - 1
};
};
}
private void ConfigureHorizontalScrollBarEvents (ScrollBar scrollBar)
{
Padding!.Thickness = Padding.Thickness with { Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : 0 };
scrollBar.PositionChanged += (_, args) =>
{
Viewport = Viewport with
{
X = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
};
};
scrollBar.VisibleChanged += (_, _) =>
{
Padding.Thickness = Padding.Thickness with
{
Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : Padding.Thickness.Bottom - 1
};
};
}
/// <summary>
/// Gets the horizontal <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
/// </summary>
/// <remarks>
/// <para>
/// See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
/// </para>
/// </remarks>
public ScrollBar HorizontalScrollBar => _horizontalScrollBar.Value;
/// <summary>
/// Gets the vertical <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
/// </summary>
/// <remarks>
/// <para>
/// See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
/// </para>
/// </remarks>
public ScrollBar VerticalScrollBar => _verticalScrollBar.Value;
/// <summary>
/// Clean up the ScrollBars of the View. Called by View.Dispose.
/// </summary>
private void DisposeScrollBars ()
{
if (this is Adornment)
{
return;
}
if (_horizontalScrollBar.IsValueCreated)
{
Padding?.Remove (_horizontalScrollBar.Value);
_horizontalScrollBar.Value.Dispose ();
}
if (_verticalScrollBar.IsValueCreated)
{
Padding?.Remove (_verticalScrollBar.Value);
_verticalScrollBar.Value.Dispose ();
}
}
}