#nullable enable using System.ComponentModel; namespace Terminal.Gui; /// A proportional scroll bar that can be oriented either horizontally or vertically. /// /// /// indicates the current location between zero and . /// /// If the scrollbar is larger than three cells, arrow indicators are drawn. /// public class ScrollBar : View { /// public ScrollBar () { _scroll = new (); _decrease = new (); _increase = new () { NavigationDirection = NavigationDirection.Forward }; Add (_scroll, _decrease, _increase); CanFocus = false; Orientation = Orientation.Vertical; Width = Dim.Auto (DimAutoStyle.Content, 1); Height = Dim.Auto (DimAutoStyle.Content, 1); _scroll.PositionChanging += Scroll_PositionChanging; _scroll.PositionChanged += Scroll_PositionChanged; _scroll.SizeChanged += _scroll_SizeChanged; } private readonly Scroll _scroll; private readonly ScrollButton _decrease; private readonly ScrollButton _increase; private bool _autoHide = true; private bool _showScrollIndicator = true; /// /// Gets or sets whether will be set to if the dimension of the /// scroll bar is greater than or equal to . /// public bool AutoHide { get => _autoHide; set { if (_autoHide != value) { _autoHide = value; AdjustAll (); } } } /// Get or sets if the view-port is kept in all visible area of this . public bool KeepContentInAllViewport { get => _scroll.KeepContentInAllViewport; set => _scroll.KeepContentInAllViewport = value; } /// Gets or sets if a scrollbar is vertical or horizontal. public Orientation Orientation { get => _scroll.Orientation; set { Resize (value); _scroll.Orientation = value; } } /// Gets or sets the position, relative to , to set the scrollbar at. /// The position. public int Position { get => _scroll.Position; set { _scroll.Position = value; AdjustAll (); } } /// Raised when the has changed. public event EventHandler>? PositionChanged; /// /// Raised when the is changing. Set to /// to prevent the position from being changed. /// public event EventHandler>? PositionChanging; /// Gets or sets the visibility for the vertical or horizontal scroll indicator. /// true if show vertical or horizontal scroll indicator; otherwise, false. public bool ShowScrollIndicator { get => Visible; set { if (value == _showScrollIndicator) { return; } _showScrollIndicator = value; if (IsInitialized) { SetNeedsLayout (); if (value) { Visible = true; } else { Visible = false; Position = 0; } AdjustAll (); } } } /// /// Gets or sets the size of the Scroll. This is the total size of the content that can be scrolled through. /// public int Size { get => _scroll.Size; set { _scroll.Size = value; AdjustAll (); } } /// Raised when has changed. public event EventHandler>? SizeChanged; /// internal override void OnLayoutComplete (LayoutEventArgs args) { base.OnLayoutComplete (args); AdjustAll (); } private void _scroll_SizeChanged (object? sender, EventArgs e) { SizeChanged?.Invoke (this, e); } private void AdjustAll () { CheckVisibility (); _scroll.AdjustScroll (); _decrease.AdjustButton (); _increase.AdjustButton (); } private bool CheckVisibility () { if (!AutoHide) { if (Visible != _showScrollIndicator) { Visible = _showScrollIndicator; SetNeedsDisplay (); } return _showScrollIndicator; } int barSize = Orientation == Orientation.Vertical ? Viewport.Height : Viewport.Width; if (barSize == 0 || barSize >= Size) { if (Visible) { Visible = false; SetNeedsDisplay (); return false; } } else { if (!Visible) { Visible = true; SetNeedsDisplay (); } } return true; } private void Resize (Orientation orientation) { switch (orientation) { case Orientation.Horizontal: break; case Orientation.Vertical: break; default: throw new ArgumentOutOfRangeException (nameof (orientation), orientation, null); } } private void Scroll_PositionChanged (object? sender, EventArgs e) { PositionChanged?.Invoke (this, e); } private void Scroll_PositionChanging (object? sender, CancelEventArgs e) { PositionChanging?.Invoke (this, e); } }