namespace Terminal.Gui.Views;
/// Navigation functionality - cursor movement and scrolling
public partial class TextView
{
#region Public Navigation Methods
/// Will scroll the to the last line and position the cursor there.
public void MoveEnd ()
{
CurrentRow = _model.Count - 1;
List line = GetCurrentLine ();
CurrentColumn = line.Count;
TrackColumn ();
DoNeededAction ();
}
/// Will scroll the to the first line and position the cursor there.
public void MoveHome ()
{
CurrentRow = 0;
_topRow = 0;
CurrentColumn = 0;
_leftColumn = 0;
TrackColumn ();
DoNeededAction ();
}
///
/// Will scroll the to display the specified row at the top if is
/// true or will scroll the to display the specified column at the left if
/// is false.
///
///
/// Row that should be displayed at the top or Column that should be displayed at the left, if the value
/// is negative it will be reset to zero
///
/// If true (default) the is a row, column otherwise.
public void ScrollTo (int idx, bool isRow = true)
{
if (idx < 0)
{
idx = 0;
}
if (isRow)
{
_topRow = Math.Max (idx > _model.Count - 1 ? _model.Count - 1 : idx, 0);
if (IsInitialized && Viewport.Y != _topRow)
{
Viewport = Viewport with { Y = _topRow };
}
}
else if (!_wordWrap)
{
int maxlength = _model.GetMaxVisibleLine (_topRow, _topRow + Viewport.Height, TabWidth);
_leftColumn = Math.Max (!_wordWrap && idx > maxlength - 1 ? maxlength - 1 : idx, 0);
if (IsInitialized && Viewport.X != _leftColumn)
{
Viewport = Viewport with { X = _leftColumn };
}
}
SetNeedsDraw ();
}
#endregion
#region Private Navigation Methods
private void MoveBottomEnd ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveEnd ();
}
private void MoveBottomEndExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveEnd ();
}
private bool MoveDown ()
{
if (CurrentRow + 1 < _model.Count)
{
if (_columnTrack == -1)
{
_columnTrack = CurrentColumn;
}
CurrentRow++;
if (CurrentRow >= _topRow + Viewport.Height)
{
_topRow++;
SetNeedsDraw ();
}
TrackColumn ();
PositionCursor ();
}
else if (CurrentRow > Viewport.Height)
{
Adjust ();
}
else
{
return false;
}
DoNeededAction ();
return true;
}
private void MoveEndOfLine ()
{
List currentLine = GetCurrentLine ();
CurrentColumn = currentLine.Count;
DoNeededAction ();
}
private bool MoveLeft ()
{
if (CurrentColumn > 0)
{
CurrentColumn--;
}
else
{
if (CurrentRow > 0)
{
CurrentRow--;
if (CurrentRow < _topRow)
{
_topRow--;
SetNeedsDraw ();
}
List currentLine = GetCurrentLine ();
CurrentColumn = Math.Max (currentLine.Count - (ReadOnly ? 1 : 0), 0);
}
else
{
return false;
}
}
DoNeededAction ();
return true;
}
private void MovePageDown ()
{
int nPageDnShift = Viewport.Height - 1;
if (CurrentRow >= 0 && CurrentRow < _model.Count)
{
if (_columnTrack == -1)
{
_columnTrack = CurrentColumn;
}
CurrentRow = CurrentRow + nPageDnShift > _model.Count
? _model.Count > 0 ? _model.Count - 1 : 0
: CurrentRow + nPageDnShift;
if (_topRow < CurrentRow - nPageDnShift)
{
_topRow = CurrentRow >= _model.Count
? CurrentRow - nPageDnShift
: _topRow + nPageDnShift;
SetNeedsDraw ();
}
TrackColumn ();
PositionCursor ();
}
DoNeededAction ();
}
private void MovePageUp ()
{
int nPageUpShift = Viewport.Height - 1;
if (CurrentRow > 0)
{
if (_columnTrack == -1)
{
_columnTrack = CurrentColumn;
}
CurrentRow = CurrentRow - nPageUpShift < 0 ? 0 : CurrentRow - nPageUpShift;
if (CurrentRow < _topRow)
{
_topRow = _topRow - nPageUpShift < 0 ? 0 : _topRow - nPageUpShift;
SetNeedsDraw ();
}
TrackColumn ();
PositionCursor ();
}
DoNeededAction ();
}
private bool MoveRight ()
{
List currentLine = GetCurrentLine ();
if ((ReadOnly ? CurrentColumn + 1 : CurrentColumn) < currentLine.Count)
{
CurrentColumn++;
}
else
{
if (CurrentRow + 1 < _model.Count)
{
CurrentRow++;
CurrentColumn = 0;
if (CurrentRow >= _topRow + Viewport.Height)
{
_topRow++;
SetNeedsDraw ();
}
}
else
{
return false;
}
}
DoNeededAction ();
return true;
}
private void MoveLeftStart ()
{
if (_leftColumn > 0)
{
SetNeedsDraw ();
}
CurrentColumn = 0;
_leftColumn = 0;
DoNeededAction ();
}
private void MoveTopHome ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveHome ();
}
private void MoveTopHomeExtend ()
{
ResetColumnTrack ();
StartSelecting ();
MoveHome ();
}
private bool MoveUp ()
{
if (CurrentRow > 0)
{
if (_columnTrack == -1)
{
_columnTrack = CurrentColumn;
}
CurrentRow--;
if (CurrentRow < _topRow)
{
_topRow--;
SetNeedsDraw ();
}
TrackColumn ();
PositionCursor ();
}
else
{
return false;
}
DoNeededAction ();
return true;
}
private void MoveWordBackward ()
{
(int col, int row)? newPos = _model.WordBackward (CurrentColumn, CurrentRow, UseSameRuneTypeForWords);
if (newPos.HasValue)
{
CurrentColumn = newPos.Value.col;
CurrentRow = newPos.Value.row;
}
DoNeededAction ();
}
private void MoveWordForward ()
{
(int col, int row)? newPos = _model.WordForward (CurrentColumn, CurrentRow, UseSameRuneTypeForWords);
if (newPos.HasValue)
{
CurrentColumn = newPos.Value.col;
CurrentRow = newPos.Value.row;
}
DoNeededAction ();
}
#endregion
#region Process Navigation Methods
private bool ProcessMoveDown ()
{
ResetContinuousFindTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
return MoveDown ();
}
private void ProcessMoveDownExtend ()
{
ResetColumnTrack ();
StartSelecting ();
MoveDown ();
}
private void ProcessMoveEndOfLine ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveEndOfLine ();
}
private void ProcessMoveRightEndExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveEndOfLine ();
}
private bool ProcessMoveLeft ()
{
// if the user presses Left (without any control keys) and they are at the start of the text
if (CurrentColumn == 0 && CurrentRow == 0)
{
if (IsSelecting)
{
StopSelecting ();
return true;
}
// do not respond (this lets the key press fall through to navigation system - which usually changes focus backward)
return false;
}
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveLeft ();
return true;
}
private void ProcessMoveLeftExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveLeft ();
}
private bool ProcessMoveRight ()
{
// if the user presses Right (without any control keys)
// determine where the last cursor position in the text is
int lastRow = _model.Count - 1;
int lastCol = _model.GetLine (lastRow).Count;
// if they are at the very end of all the text do not respond (this lets the key press fall through to navigation system - which usually changes focus forward)
if (CurrentColumn == lastCol && CurrentRow == lastRow)
{
// Unless they have text selected
if (IsSelecting)
{
// In which case clear
StopSelecting ();
return true;
}
return false;
}
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveRight ();
return true;
}
private void ProcessMoveRightExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveRight ();
}
private void ProcessMoveLeftStart ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveLeftStart ();
}
private void ProcessMoveLeftStartExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveLeftStart ();
}
private bool ProcessMoveUp ()
{
ResetContinuousFindTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
return MoveUp ();
}
private void ProcessMoveUpExtend ()
{
ResetColumnTrack ();
StartSelecting ();
MoveUp ();
}
private void ProcessMoveWordBackward ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveWordBackward ();
}
private void ProcessMoveWordBackwardExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveWordBackward ();
}
private void ProcessMoveWordForward ()
{
ResetAllTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MoveWordForward ();
}
private void ProcessMoveWordForwardExtend ()
{
ResetAllTrack ();
StartSelecting ();
MoveWordForward ();
}
private void ProcessPageDown ()
{
ResetColumnTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MovePageDown ();
}
private void ProcessPageDownExtend ()
{
ResetColumnTrack ();
StartSelecting ();
MovePageDown ();
}
private void ProcessPageUp ()
{
ResetColumnTrack ();
if (_shiftSelecting && IsSelecting)
{
StopSelecting ();
}
MovePageUp ();
}
private void ProcessPageUpExtend ()
{
ResetColumnTrack ();
StartSelecting ();
MovePageUp ();
}
#endregion
#region Column Tracking
// Tries to snap the cursor to the tracking column
private void TrackColumn ()
{
// Now track the column
List| line = GetCurrentLine ();
if (line.Count < _columnTrack)
{
CurrentColumn = line.Count;
}
else if (_columnTrack != -1)
{
CurrentColumn = _columnTrack;
}
else if (CurrentColumn > line.Count)
{
CurrentColumn = line.Count;
}
Adjust ();
}
#endregion
}
| | | | |