View.ScrollBars.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #nullable enable
  2. namespace Terminal.Gui;
  3. public partial class View
  4. {
  5. private Lazy<ScrollBar> _horizontalScrollBar = null!;
  6. private Lazy<ScrollBar> _verticalScrollBar = null!;
  7. /// <summary>
  8. /// Initializes the ScrollBars of the View. Called by the View constructor.
  9. /// </summary>
  10. private void SetupScrollBars ()
  11. {
  12. if (this is Adornment)
  13. {
  14. return;
  15. }
  16. _verticalScrollBar = new (() => CreateScrollBar (Orientation.Vertical));
  17. _horizontalScrollBar = new (() => CreateScrollBar (Orientation.Horizontal));
  18. }
  19. private ScrollBar CreateScrollBar (Orientation orientation)
  20. {
  21. var scrollBar = new ScrollBar
  22. {
  23. Orientation = orientation,
  24. Visible = false // Initially hidden until needed
  25. };
  26. if (orientation == Orientation.Vertical)
  27. {
  28. ConfigureVerticalScrollBar (scrollBar);
  29. }
  30. else
  31. {
  32. ConfigureHorizontalScrollBar (scrollBar);
  33. }
  34. scrollBar.Initialized += OnScrollBarInitialized;
  35. // Add after setting Initialized event!
  36. Padding?.Add (scrollBar);
  37. return scrollBar;
  38. }
  39. private void ConfigureVerticalScrollBar (ScrollBar scrollBar)
  40. {
  41. scrollBar.X = Pos.AnchorEnd ();
  42. scrollBar.Height = Dim.Fill (
  43. Dim.Func (
  44. () =>
  45. {
  46. if (_horizontalScrollBar.IsValueCreated)
  47. {
  48. return _horizontalScrollBar.Value.Visible ? 1 : 0;
  49. }
  50. return 0;
  51. }));
  52. scrollBar.ScrollableContentSize = GetContentSize ().Height;
  53. ViewportChanged += (_, _) =>
  54. {
  55. scrollBar.Position = Viewport.Y;
  56. };
  57. ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Height; };
  58. }
  59. private void ConfigureHorizontalScrollBar (ScrollBar scrollBar)
  60. {
  61. scrollBar.Y = Pos.AnchorEnd ();
  62. scrollBar.Width = Dim.Fill (
  63. Dim.Func (
  64. () =>
  65. {
  66. if (_verticalScrollBar.IsValueCreated)
  67. {
  68. return _verticalScrollBar.Value.Visible ? 1 : 0;
  69. }
  70. return 0;
  71. }));
  72. scrollBar.ScrollableContentSize = GetContentSize ().Width;
  73. ViewportChanged += (_, _) =>
  74. {
  75. scrollBar.Position = Viewport.X;
  76. };
  77. ContentSizeChanged += (_, _) => { scrollBar.ScrollableContentSize = GetContentSize ().Width; };
  78. }
  79. private void OnScrollBarInitialized (object? sender, EventArgs e)
  80. {
  81. var scrollBar = (ScrollBar)sender!;
  82. if (scrollBar.Orientation == Orientation.Vertical)
  83. {
  84. ConfigureVerticalScrollBarEvents (scrollBar);
  85. }
  86. else
  87. {
  88. ConfigureHorizontalScrollBarEvents (scrollBar);
  89. }
  90. }
  91. private void ConfigureVerticalScrollBarEvents (ScrollBar scrollBar)
  92. {
  93. Padding!.Thickness = Padding.Thickness with { Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : 0 };
  94. scrollBar.PositionChanged += (_, args) =>
  95. {
  96. Viewport = Viewport with
  97. {
  98. Y = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
  99. };
  100. };
  101. scrollBar.VisibleChanged += (_, _) =>
  102. {
  103. Padding.Thickness = Padding.Thickness with
  104. {
  105. Right = scrollBar.Visible ? Padding.Thickness.Right + 1 : Padding.Thickness.Right - 1
  106. };
  107. };
  108. }
  109. private void ConfigureHorizontalScrollBarEvents (ScrollBar scrollBar)
  110. {
  111. Padding!.Thickness = Padding.Thickness with { Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : 0 };
  112. scrollBar.PositionChanged += (_, args) =>
  113. {
  114. Viewport = Viewport with
  115. {
  116. X = Math.Min (args.CurrentValue, scrollBar.ScrollableContentSize - scrollBar.VisibleContentSize)
  117. };
  118. };
  119. scrollBar.VisibleChanged += (_, _) =>
  120. {
  121. Padding.Thickness = Padding.Thickness with
  122. {
  123. Bottom = scrollBar.Visible ? Padding.Thickness.Bottom + 1 : Padding.Thickness.Bottom - 1
  124. };
  125. };
  126. }
  127. /// <summary>
  128. /// Gets the horizontal <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
  129. /// </summary>
  130. /// <remarks>
  131. /// <para>
  132. /// See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
  133. /// </para>
  134. /// </remarks>
  135. public ScrollBar HorizontalScrollBar => _horizontalScrollBar.Value;
  136. /// <summary>
  137. /// Gets the vertical <see cref="ScrollBar"/>. This property is lazy-loaded and will not be created until it is accessed.
  138. /// </summary>
  139. /// <remarks>
  140. /// <para>
  141. /// See <see cref="ScrollBar"/> for more information on how to use the ScrollBar.
  142. /// </para>
  143. /// </remarks>
  144. public ScrollBar VerticalScrollBar => _verticalScrollBar.Value;
  145. /// <summary>
  146. /// Clean up the ScrollBars of the View. Called by View.Dispose.
  147. /// </summary>
  148. private void DisposeScrollBars ()
  149. {
  150. if (this is Adornment)
  151. {
  152. return;
  153. }
  154. if (_horizontalScrollBar.IsValueCreated)
  155. {
  156. Padding?.Remove (_horizontalScrollBar.Value);
  157. _horizontalScrollBar.Value.Dispose ();
  158. }
  159. if (_verticalScrollBar.IsValueCreated)
  160. {
  161. Padding?.Remove (_verticalScrollBar.Value);
  162. _verticalScrollBar.Value.Dispose ();
  163. }
  164. }
  165. }