TextView.Utilities.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. namespace Terminal.Gui.Views;
  2. /// <summary>Utility and helper methods for TextView</summary>
  3. public partial class TextView
  4. {
  5. private void Adjust ()
  6. {
  7. (int width, int height) offB = OffSetBackground ();
  8. List<Cell> line = GetCurrentLine ();
  9. bool need = NeedsDraw || _wrapNeeded || !Used;
  10. (int size, int length) tSize = TextModel.DisplaySize (line, -1, -1, false, TabWidth);
  11. (int size, int length) dSize = TextModel.DisplaySize (line, _leftColumn, CurrentColumn, true, TabWidth);
  12. if (!_wordWrap && CurrentColumn < _leftColumn)
  13. {
  14. _leftColumn = CurrentColumn;
  15. need = true;
  16. }
  17. else if (!_wordWrap
  18. && (CurrentColumn - _leftColumn + 1 > Viewport.Width + offB.width || dSize.size + 1 >= Viewport.Width + offB.width))
  19. {
  20. _leftColumn = TextModel.CalculateLeftColumn (
  21. line,
  22. _leftColumn,
  23. CurrentColumn,
  24. Viewport.Width + offB.width,
  25. TabWidth
  26. );
  27. need = true;
  28. }
  29. else if ((_wordWrap && _leftColumn > 0) || (dSize.size < Viewport.Width + offB.width && tSize.size < Viewport.Width + offB.width))
  30. {
  31. if (_leftColumn > 0)
  32. {
  33. _leftColumn = 0;
  34. need = true;
  35. }
  36. }
  37. if (CurrentRow < _topRow)
  38. {
  39. _topRow = CurrentRow;
  40. need = true;
  41. }
  42. else if (CurrentRow - _topRow >= Viewport.Height + offB.height)
  43. {
  44. _topRow = Math.Min (Math.Max (CurrentRow - Viewport.Height + 1, 0), CurrentRow);
  45. need = true;
  46. }
  47. else if (_topRow > 0 && CurrentRow < _topRow)
  48. {
  49. _topRow = Math.Max (_topRow - 1, 0);
  50. need = true;
  51. }
  52. // Sync Viewport with the internal scroll position
  53. if (IsInitialized && (_leftColumn != Viewport.X || _topRow != Viewport.Y))
  54. {
  55. Viewport = new Rectangle (_leftColumn, _topRow, Viewport.Width, Viewport.Height);
  56. }
  57. if (need)
  58. {
  59. if (_wrapNeeded)
  60. {
  61. WrapTextModel ();
  62. _wrapNeeded = false;
  63. }
  64. SetNeedsDraw ();
  65. }
  66. else
  67. {
  68. if (IsInitialized)
  69. {
  70. PositionCursor ();
  71. }
  72. }
  73. OnUnwrappedCursorPosition ();
  74. }
  75. private void DoNeededAction ()
  76. {
  77. if (!NeedsDraw && (IsSelecting || _wrapNeeded || !Used))
  78. {
  79. SetNeedsDraw ();
  80. }
  81. if (NeedsDraw)
  82. {
  83. Adjust ();
  84. }
  85. else
  86. {
  87. PositionCursor ();
  88. OnUnwrappedCursorPosition ();
  89. }
  90. }
  91. private (int width, int height) OffSetBackground ()
  92. {
  93. var w = 0;
  94. var h = 0;
  95. if (SuperView?.Viewport.Right - Viewport.Right < 0)
  96. {
  97. w = SuperView!.Viewport.Right - Viewport.Right - 1;
  98. }
  99. if (SuperView?.Viewport.Bottom - Viewport.Bottom < 0)
  100. {
  101. h = SuperView!.Viewport.Bottom - Viewport.Bottom - 1;
  102. }
  103. return (w, h);
  104. }
  105. /// <summary>
  106. /// Updates the content size based on the text model dimensions.
  107. /// </summary>
  108. private void UpdateContentSize ()
  109. {
  110. int contentHeight = Math.Max (_model.Count, 1);
  111. // For horizontal size: if word wrap is enabled, content width equals viewport width
  112. // Otherwise, calculate the maximum line width (but only if we have a reasonable viewport)
  113. int contentWidth;
  114. if (_wordWrap)
  115. {
  116. // Word wrap: content width follows viewport width
  117. contentWidth = Math.Max (Viewport.Width, 1);
  118. }
  119. else
  120. {
  121. // No word wrap: calculate max line width
  122. // Cache the current value to avoid recalculating on every call
  123. contentWidth = Math.Max (_model.GetMaxVisibleLine (0, _model.Count, TabWidth), 1);
  124. }
  125. SetContentSize (new Size (contentWidth, contentHeight));
  126. }
  127. private void ResetPosition ()
  128. {
  129. _topRow = _leftColumn = CurrentRow = CurrentColumn = 0;
  130. StopSelecting ();
  131. }
  132. private void ResetAllTrack ()
  133. {
  134. // Handle some state here - whether the last command was a kill
  135. // operation and the column tracking (up/down)
  136. _lastWasKill = false;
  137. _columnTrack = -1;
  138. _continuousFind = false;
  139. }
  140. private void ResetColumnTrack ()
  141. {
  142. // Handle some state here - whether the last command was a kill
  143. // operation and the column tracking (up/down)
  144. _lastWasKill = false;
  145. _columnTrack = -1;
  146. }
  147. private void ToggleSelecting ()
  148. {
  149. ResetColumnTrack ();
  150. IsSelecting = !IsSelecting;
  151. _selectionStartColumn = CurrentColumn;
  152. _selectionStartRow = CurrentRow;
  153. }
  154. }