Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixes #2196. TextView: Setting Text places cursor at beginning, unlike TextField #2572

Merged
merged 5 commits into from
Apr 29, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 64 additions & 25 deletions Terminal.Gui/Views/TextView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,11 @@ private void Model_LinesLoaded (object sender, EventArgs e)
// If this call happens, HistoryText_ChangeText will get called multiple times
// when Text is set, which is wrong.
//historyText.Clear (Text);

if (!multiline && !IsInitialized) {
BDisp marked this conversation as resolved.
Show resolved Hide resolved
currentColumn = Text.RuneCount;
leftColumn = currentColumn > Frame.Width + 1 ? currentColumn - Frame.Width + 1 : 0;
}
}

private void HistoryText_ChangeText (object sender, HistoryText.HistoryTextItem obj)
Expand Down Expand Up @@ -1970,6 +1975,9 @@ public bool Multiline {
}
Height = 1;
LayoutStyle = lyout;
if (!IsInitialized) {
BDisp marked this conversation as resolved.
Show resolved Hide resolved
model.LoadString (Text);
}
SetNeedsDisplay ();
} else if (multiline && savedHeight != null) {
var lyout = LayoutStyle;
Expand Down Expand Up @@ -2094,10 +2102,11 @@ public override void PositionCursor ()
}

if (selecting) {
var minRow = Math.Min (Math.Max (Math.Min (selectionStartRow, currentRow) - topRow, 0), Frame.Height);
var maxRow = Math.Min (Math.Max (Math.Max (selectionStartRow, currentRow) - topRow, 0), Frame.Height);

SetNeedsDisplay (new Rect (0, minRow, Frame.Width, maxRow));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//var minRow = Math.Min (Math.Max (Math.Min (selectionStartRow, currentRow) - topRow, 0), Frame.Height);
//var maxRow = Math.Min (Math.Max (Math.Max (selectionStartRow, currentRow) - topRow, 0), Frame.Height);
//SetNeedsDisplay (new Rect (0, minRow, Frame.Width, maxRow));
SetNeedsDisplay ();
}
var line = model.GetLine (currentRow);
var col = 0;
Expand Down Expand Up @@ -2340,7 +2349,9 @@ void ClearRegion ()
if (wordWrap) {
SetNeedsDisplay ();
} else {
SetNeedsDisplay (new Rect (0, startRow - topRow, Frame.Width, startRow - topRow + 1));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, startRow - topRow, Frame.Width, startRow - topRow + 1));
SetNeedsDisplay ();
}

historyText.Add (new List<List<Rune>> (removedLines), CursorPosition, HistoryText.LineStatus.Removed);
Expand Down Expand Up @@ -2746,9 +2757,10 @@ void Insert (Rune rune)
}
var prow = currentRow - topRow;
if (!wrapNeeded) {
SetNeedsDisplay (new Rect (0, prow, Math.Max (Frame.Width, 0), Math.Max (prow + 1, 0)));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, prow, Math.Max (Frame.Width, 0), Math.Max (prow + 1, 0)));
SetNeedsDisplay ();
}

}

ustring StringFromRunes (List<Rune> runes)
Expand Down Expand Up @@ -2807,7 +2819,9 @@ void InsertText (ustring text)
if (wordWrap) {
SetNeedsDisplay ();
} else {
SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Math.Max (currentRow - topRow + 1, 0)));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Math.Max (currentRow - topRow + 1, 0)));
SetNeedsDisplay ();
}

UpdateWrapModel ();
Expand Down Expand Up @@ -3411,10 +3425,13 @@ bool ProcessReturn ()
leftColumn = 0;
}

if (fullNeedsDisplay)
if (fullNeedsDisplay) {
SetNeedsDisplay ();
} else {
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, 2, Frame.Height));
SetNeedsDisplay ();
else
SetNeedsDisplay (new Rect (0, currentRow - topRow, 2, Frame.Height));
}

UpdateWrapModel ();

Expand Down Expand Up @@ -3470,7 +3487,9 @@ void KillWordBackward ()
if (wrapNeeded) {
SetNeedsDisplay ();
} else {
SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
SetNeedsDisplay ();
}
DoNeededAction ();
}
Expand Down Expand Up @@ -3517,7 +3536,9 @@ void KillWordForward ()
if (wrapNeeded) {
SetNeedsDisplay ();
} else {
SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
SetNeedsDisplay ();
}
DoNeededAction ();
}
Expand Down Expand Up @@ -3613,10 +3634,14 @@ void KillToStartOfLine ()

UpdateWrapModel ();

if (wrapNeeded)
if (wrapNeeded) {
SetNeedsDisplay ();
else
SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
} else {
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
SetNeedsDisplay ();
}

lastWasKill = setLastWasKill;
DoNeededAction ();
}
Expand Down Expand Up @@ -3684,10 +3709,14 @@ void KillToEndOfLine ()

UpdateWrapModel ();

if (wrapNeeded)
if (wrapNeeded) {
BDisp marked this conversation as resolved.
Show resolved Hide resolved
SetNeedsDisplay ();
else
SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
} else {
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, Frame.Width, Frame.Height));
SetNeedsDisplay ();
}

lastWasKill = setLastWasKill;
DoNeededAction ();
}
Expand All @@ -3702,6 +3731,9 @@ void MoveEndOfLine ()

void MoveStartOfLine ()
{
if (leftColumn > 0) {
SetNeedsDisplay ();
}
currentColumn = 0;
leftColumn = 0;
Adjust ();
Expand Down Expand Up @@ -4002,8 +4034,10 @@ bool DeleteTextForwards ()
if (wrapNeeded) {
SetNeedsDisplay ();
} else {
var sr = currentRow - topRow;
SetNeedsDisplay (new Rect (0, sr, Frame.Width, sr + 1));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//var sr = currentRow - topRow;
//SetNeedsDisplay (new Rect (0, sr, Frame.Width, sr + 1));
SetNeedsDisplay ();
}
} else {
historyText.Add (new List<List<Rune>> () { new List<Rune> (currentLine) }, CursorPosition);
Expand All @@ -4020,8 +4054,10 @@ bool DeleteTextForwards ()
if (wrapNeeded) {
SetNeedsDisplay ();
} else {
var r = currentRow - topRow;
SetNeedsDisplay (new Rect (currentColumn - leftColumn, r, Frame.Width, r + 1));
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//var r = currentRow - topRow;
//SetNeedsDisplay (new Rect (currentColumn - leftColumn, r, Frame.Width, r + 1));
SetNeedsDisplay ();
}
}

Expand Down Expand Up @@ -4052,8 +4088,11 @@ bool DeleteTextBackwards ()
if (currentColumn < leftColumn) {
leftColumn--;
SetNeedsDisplay ();
} else
SetNeedsDisplay (new Rect (0, currentRow - topRow, 1, Frame.Width));
} else {
// BUGBUG: customized rect aren't supported now because the Redraw isn't using the Intersect method.
//SetNeedsDisplay (new Rect (0, currentRow - topRow, 1, Frame.Width));
SetNeedsDisplay ();
}
} else {
// Merges the current line with the previous one.
if (currentRow == 0)
Expand Down
24 changes: 17 additions & 7 deletions UICatalog/Scenarios/Text.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ void TextView_DrawContent (object sender, DrawEventArgs e)
var chxMultiline = new CheckBox ("Multiline") {
X = Pos.Left (textView),
Y = Pos.Bottom (textView),
Checked = true
Checked = textView.Multiline
};
chxMultiline.Toggled += (s,e) => textView.Multiline = (bool)e.OldValue;
Win.Add (chxMultiline);

var chxWordWrap = new CheckBox ("Word Wrap") {
X = Pos.Right (chxMultiline) + 2,
Y = Pos.Top (chxMultiline)
Y = Pos.Top (chxMultiline),
Checked = textView.WordWrap
};
chxWordWrap.Toggled += (s,e) => textView.WordWrap = (bool)e.OldValue;
chxWordWrap.Toggled += (s,e) => textView.WordWrap = (bool)e.NewValue;
Win.Add (chxWordWrap);

// TextView captures Tabs (so users can enter /t into text) by default;
Expand All @@ -106,20 +106,30 @@ void TextView_DrawContent (object sender, DrawEventArgs e)
var chxCaptureTabs = new CheckBox ("Capture Tabs") {
X = Pos.Right (chxWordWrap) + 2,
Y = Pos.Top (chxWordWrap),
Checked = true
Checked = textView.AllowsTab
};

chxMultiline.Toggled += (s, e) => {
textView.Multiline = (bool)e.NewValue;
if (!textView.Multiline && (bool)chxWordWrap.Checked) {
chxWordWrap.Checked = false;
}
if (!textView.Multiline && (bool)chxCaptureTabs.Checked) {
chxCaptureTabs.Checked = false;
}
};

Key keyTab = textView.GetKeyFromCommand (Command.Tab);
Key keyBackTab = textView.GetKeyFromCommand (Command.BackTab);
chxCaptureTabs.Toggled += (s,e) => {
if (e.OldValue == true) {
if (e.NewValue == true) {
textView.AddKeyBinding (keyTab, Command.Tab);
textView.AddKeyBinding (keyBackTab, Command.BackTab);
} else {
textView.ClearKeybinding (keyTab);
textView.ClearKeybinding (keyBackTab);
}
textView.WordWrap = (bool)e.OldValue;
textView.AllowsTab = (bool)e.NewValue;
};
Win.Add (chxCaptureTabs);

Expand Down
10 changes: 10 additions & 0 deletions UnitTests/Views/TextFieldTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1588,5 +1588,15 @@ public void WordBackward_WordForward_Mixed ()
tf.ProcessKey (new KeyEvent (Key.CtrlMask | Key.CursorRight, new KeyModifiers () { Ctrl = true }));
Assert.Equal (22, tf.CursorPosition);
}

[Fact, TextFieldTestsAutoInitShutdown]
public void Cursor_Position_Initialization ()
{
Assert.False (_textField.IsInitialized);
Assert.Equal (32, _textField.CursorPosition);
Assert.Equal (0, _textField.SelectedLength);
Assert.Null (_textField.SelectedText);
Assert.Equal ("TAB to jump between text fields.", _textField.Text);
}
}
}
14 changes: 14 additions & 0 deletions UnitTests/Views/TextViewTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6934,5 +6934,19 @@ public void WordBackward_WordForward_Limits_Return_Null ()
newPos = model.WordForward (4, 0);
Assert.Null (newPos);
}

[Fact, TextViewTestsAutoInitShutdown]
public void Cursor_Position_Multiline_False_Initialization ()
{
Assert.False (_textView.IsInitialized);
Assert.True (_textView.Multiline);
_textView.Multiline = false;
Assert.Equal (32, _textView.CursorPosition.X);
Assert.Equal (0, _textView.CursorPosition.Y);
Assert.Equal (0, _textView.SelectedLength);
Assert.Equal ("", _textView.SelectedText);
Assert.Equal ("TAB to jump between text fields.", _textView.Text);
}

}
}