Improve cursor movements

This commit is contained in:
Alexander Luzgarev 2020-07-10 22:44:27 +02:00
parent b8914311b4
commit a7207aaab1

View File

@ -10,16 +10,18 @@ namespace MApplication
int height, int height,
int startingColumn = 0, int startingColumn = 0,
int startingLine = 0, int startingLine = 0,
int cursorRelativeColumn = 0, int cursorAbsoluteColumn = 0,
int cursorRelativeLine = 0) int cursorAbsoluteLine = 0,
int virtualCursorAbsoluteColumn = 0)
{ {
Text = text; Text = text;
Width = width; Width = width;
Height = height; Height = height;
StartingColumn = startingColumn; StartingColumn = startingColumn;
StartingLine = startingLine; StartingLine = startingLine;
CursorRelativeColumn = cursorRelativeColumn; CursorAbsoluteColumn = cursorAbsoluteColumn;
CursorRelativeLine = cursorRelativeLine; CursorAbsoluteLine = cursorAbsoluteLine;
VirtualCursorAbsoluteColumn = virtualCursorAbsoluteColumn;
} }
public DisplayText Text { get; } public DisplayText Text { get; }
@ -32,61 +34,80 @@ namespace MApplication
public int StartingLine { get; } public int StartingLine { get; }
public int CursorRelativeColumn { get; } public int CursorRelativeColumn => CursorAbsoluteColumn - StartingColumn;
public int CursorRelativeLine { get; } public int CursorRelativeLine => CursorAbsoluteLine - StartingLine;
public int CursorAbsoluteColumn => CursorRelativeColumn + StartingColumn; public int CursorAbsoluteColumn { get; }
public int CursorAbsoluteLine => CursorRelativeLine + StartingLine; public int CursorAbsoluteLine { get; }
public int VirtualCursorAbsoluteColumn { get; }
public int CurrentLineWidth => Text.Lines[CursorAbsoluteLine].Width; public int CurrentLineWidth => Text.Lines[CursorAbsoluteLine].Width;
public DisplayTextViewPort CursorLeft(out bool needsRedraw) public DisplayTextViewPort CursorLeft(out bool needsRedraw)
{ {
var newCursorAbsoluteColumn = Math.Max(CursorAbsoluteColumn - 1, 0);
if (CursorRelativeColumn == 0) if (CursorRelativeColumn == 0)
{ {
return ShiftLeft(out needsRedraw); return With(
out needsRedraw,
cursorAbsoluteColumn: newCursorAbsoluteColumn,
virtualCursorAbsoluteColumn: newCursorAbsoluteColumn,
startingColumn: Math.Max(StartingColumn - 1, 0));
} }
else else
{ {
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn - 1); return With(
out needsRedraw,
cursorAbsoluteColumn: newCursorAbsoluteColumn,
virtualCursorAbsoluteColumn: newCursorAbsoluteColumn);
} }
} }
public DisplayTextViewPort CursorRight(out bool needsRedraw) public DisplayTextViewPort CursorRight(out bool needsRedraw)
{ {
var newCursorAbsoluteColumn = Math.Min(CursorAbsoluteColumn + 1, CurrentLineWidth);
if (CursorRelativeColumn == Width - 1) if (CursorRelativeColumn == Width - 1)
{ {
return ShiftRight(out needsRedraw); return With(
out needsRedraw,
cursorAbsoluteColumn: newCursorAbsoluteColumn,
virtualCursorAbsoluteColumn: newCursorAbsoluteColumn,
startingColumn: StartingColumn + 1);
} }
else else
{ {
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn + 1); return With(
out needsRedraw,
cursorAbsoluteColumn: newCursorAbsoluteColumn,
virtualCursorAbsoluteColumn: newCursorAbsoluteColumn);
} }
} }
private DisplayTextViewPort SnapToLine(out bool needsRedraw) private DisplayTextViewPort SnapToLine(out bool needsRedraw)
{ {
if (CursorAbsoluteColumn > CurrentLineWidth) var cursorAbsoluteColumn = Math.Min(VirtualCursorAbsoluteColumn, CurrentLineWidth);
if (cursorAbsoluteColumn < StartingColumn)
{ {
needsRedraw = true;
var toSubtract = CursorAbsoluteColumn - CurrentLineWidth;
if (toSubtract < CursorRelativeColumn)
{
return With(out var _, cursorRelativeColumn: CursorRelativeColumn - toSubtract);
}
return With( return With(
out var _, out needsRedraw,
startingColumn: StartingColumn - (toSubtract - CursorRelativeColumn), startingColumn: cursorAbsoluteColumn,
cursorRelativeColumn: 0); cursorAbsoluteColumn: cursorAbsoluteColumn);
} }
else
if (cursorAbsoluteColumn > StartingColumn + Width - 1)
{ {
needsRedraw = false; return With(
return this; out needsRedraw,
startingColumn: cursorAbsoluteColumn - Width + 1,
cursorAbsoluteColumn: cursorAbsoluteColumn);
} }
return With(
out needsRedraw,
cursorAbsoluteColumn: cursorAbsoluteColumn);
} }
public DisplayTextViewPort CursorUp(out bool needsRedraw) public DisplayTextViewPort CursorUp(out bool needsRedraw)
@ -94,8 +115,11 @@ namespace MApplication
bool changed1; bool changed1;
var result1 = CursorRelativeLine switch var result1 = CursorRelativeLine switch
{ {
0 => ShiftUp(out changed1), 0 => With(
_ => With(out changed1, cursorRelativeLine: CursorRelativeLine - 1), out changed1,
startingLine: Math.Max(StartingLine - 1, 0),
cursorAbsoluteLine: Math.Max(StartingLine - 1, 0)),
_ => With(out changed1, cursorAbsoluteLine: CursorAbsoluteLine - 1),
}; };
var result = result1.SnapToLine(out var changed2); var result = result1.SnapToLine(out var changed2);
needsRedraw = changed1 || changed2; needsRedraw = changed1 || changed2;
@ -107,8 +131,14 @@ namespace MApplication
bool changed1; bool changed1;
var result1 = CursorRelativeLine switch var result1 = CursorRelativeLine switch
{ {
_ when CursorRelativeLine == Height - 1 => ShiftDown(out changed1), _ when CursorRelativeLine == Height - 1 =>
_ => With(out changed1, cursorRelativeLine: CursorRelativeLine + 1), With(
out changed1,
startingLine: Math.Min(CursorAbsoluteLine + 1, Text.Lines.Count) - Height + 1,
cursorAbsoluteLine: Math.Min(CursorAbsoluteLine + 1, Text.Lines.Count)),
_ => With(
out changed1,
cursorAbsoluteLine: CursorAbsoluteLine + 1),
}; };
var result = result1.SnapToLine(out var changed2); var result = result1.SnapToLine(out var changed2);
needsRedraw = changed1 || changed2; needsRedraw = changed1 || changed2;
@ -117,7 +147,11 @@ namespace MApplication
public DisplayTextViewPort CursorHome(out bool needsRedraw) public DisplayTextViewPort CursorHome(out bool needsRedraw)
{ {
return With(out needsRedraw, startingColumn: 0, cursorRelativeColumn: 0); return With(
out needsRedraw,
startingColumn: 0,
cursorAbsoluteColumn: 0,
virtualCursorAbsoluteColumn: 0);
} }
public DisplayTextViewPort CursorEnd(out bool needsRedraw) public DisplayTextViewPort CursorEnd(out bool needsRedraw)
@ -132,33 +166,17 @@ namespace MApplication
if (CursorRelativeColumn + toAdd < Width) if (CursorRelativeColumn + toAdd < Width)
{ {
return With(out needsRedraw, cursorRelativeColumn: CursorRelativeColumn + toAdd); return With(
out needsRedraw,
cursorAbsoluteColumn: CursorAbsoluteColumn + toAdd,
virtualCursorAbsoluteColumn: CursorAbsoluteColumn + toAdd);
} }
return With( return With(
out needsRedraw, out needsRedraw,
startingColumn: StartingColumn + CursorRelativeColumn + toAdd - Width + 1, startingColumn: lineWidth - Width + 1,
cursorRelativeColumn: Width - 1); cursorAbsoluteColumn: lineWidth,
} virtualCursorAbsoluteColumn: lineWidth);
public DisplayTextViewPort ShiftLeft(out bool needsRedraw)
{
return With(out needsRedraw, startingColumn: Math.Max(StartingColumn - 1, 0));
}
public DisplayTextViewPort ShiftRight(out bool needsRedraw)
{
return With(out needsRedraw, startingColumn: StartingColumn + 1);
}
public DisplayTextViewPort ShiftUp(out bool needsRedraw)
{
return With(out needsRedraw, startingLine: Math.Max(StartingLine - 1, 0));
}
public DisplayTextViewPort ShiftDown(out bool needsRedraw)
{
return With(out needsRedraw, startingLine: StartingLine + 1);
} }
public void RenderTo(IOutputView view) public void RenderTo(IOutputView view)
@ -172,6 +190,7 @@ namespace MApplication
view.WriteText(new string(' ', Width)); view.WriteText(new string(' ', Width));
continue; continue;
} }
var line = Text.Lines[lineNumber]; var line = Text.Lines[lineNumber];
var startsIn = StartingColumn; var startsIn = StartingColumn;
foreach (var chunk in line.Chunks) foreach (var chunk in line.Chunks)
@ -207,21 +226,24 @@ namespace MApplication
int? height = null, int? height = null,
int? startingColumn = null, int? startingColumn = null,
int? startingLine = null, int? startingLine = null,
int? cursorRelativeColumn = null, int? cursorAbsoluteColumn = null,
int? cursorRelativeLine = null) int? cursorAbsoluteLine = null,
int? virtualCursorAbsoluteColumn = null)
{ {
var widthValue = width ?? Width; var widthValue = width ?? Width;
var heightValue = height ?? Height; var heightValue = height ?? Height;
var startingColumnValue = startingColumn ?? StartingColumn; var startingColumnValue = startingColumn ?? StartingColumn;
var startingLineValue = startingLine ?? StartingLine; var startingLineValue = startingLine ?? StartingLine;
var cursorRelativeColumnValue = cursorRelativeColumn ?? CursorRelativeColumn; var cursorAbsoluteColumnValue = cursorAbsoluteColumn ?? CursorAbsoluteColumn;
var cursorRelativeLineValue = cursorRelativeLine ?? CursorRelativeLine; var cursorAbsoluteLineValue = cursorAbsoluteLine ?? CursorAbsoluteLine;
var virtualCursorAbsoluteColumnValue = virtualCursorAbsoluteColumn ?? VirtualCursorAbsoluteColumn;
if (widthValue == Width && if (widthValue == Width &&
heightValue == Height && heightValue == Height &&
startingColumnValue == StartingColumn && startingColumnValue == StartingColumn &&
startingLineValue == StartingLine && startingLineValue == StartingLine &&
cursorRelativeColumnValue == CursorRelativeColumn && cursorAbsoluteColumnValue == CursorAbsoluteColumn &&
cursorRelativeLineValue == CursorRelativeLine) cursorAbsoluteLineValue == CursorAbsoluteLine &&
virtualCursorAbsoluteColumnValue == VirtualCursorAbsoluteColumn)
{ {
changed = false; changed = false;
return this; return this;
@ -234,8 +256,9 @@ namespace MApplication
height: heightValue, height: heightValue,
startingColumn: startingColumnValue, startingColumn: startingColumnValue,
startingLine: startingLineValue, startingLine: startingLineValue,
cursorRelativeColumn: cursorRelativeColumnValue, cursorAbsoluteColumn: cursorAbsoluteColumnValue,
cursorRelativeLine: cursorRelativeLineValue); cursorAbsoluteLine: cursorAbsoluteLineValue,
virtualCursorAbsoluteColumn: virtualCursorAbsoluteColumnValue);
} }
} }
} }