From 216f6fb2b5c0db3fabf37149ae53cc3f0db45f4b Mon Sep 17 00:00:00 2001 From: p0_INT32 <834936537@qq.com> Date: Sun, 21 Apr 2024 10:13:17 +0800 Subject: [PATCH 1/2] Fixed bug for clas Studio and class TextBox --- src/Myra/Events/TextDeletedEventArgs.cs | 23 +++++++++ src/Myra/Graphics2D/UI/Simple/TextBox.cs | 32 +++++++----- src/MyraPad/StringExtensions.cs | 54 ++++++++++++++++++++ src/MyraPad/Studio.cs | 64 +++++++++++++++++++----- 4 files changed, 149 insertions(+), 24 deletions(-) create mode 100644 src/Myra/Events/TextDeletedEventArgs.cs create mode 100644 src/MyraPad/StringExtensions.cs diff --git a/src/Myra/Events/TextDeletedEventArgs.cs b/src/Myra/Events/TextDeletedEventArgs.cs new file mode 100644 index 00000000..b8337c7b --- /dev/null +++ b/src/Myra/Events/TextDeletedEventArgs.cs @@ -0,0 +1,23 @@ +using System; + +namespace Myra.Events +{ + public class TextDeletedEventArgs : EventArgs + { + public int StartPosition + { + get; + } + + public string Value + { + get; + } + + public TextDeletedEventArgs(int startPosition, string value) + { + StartPosition = startPosition; + Value = value; + } + } +} \ No newline at end of file diff --git a/src/Myra/Graphics2D/UI/Simple/TextBox.cs b/src/Myra/Graphics2D/UI/Simple/TextBox.cs index b1210313..912db235 100644 --- a/src/Myra/Graphics2D/UI/Simple/TextBox.cs +++ b/src/Myra/Graphics2D/UI/Simple/TextBox.cs @@ -314,7 +314,12 @@ internal set /// Fires every time when the text had been changed by user(doesnt fire if it had been assigned through code) /// public event EventHandler> TextChangedByUser; - + + /// + /// Fires every time when the text had been deleted + /// + public event EventHandler TextDeleted; + public event EventHandler CursorPositionChanged; public TextBox(string styleName = Stylesheet.DefaultStyleName) @@ -332,7 +337,7 @@ public TextBox(string styleName = Stylesheet.DefaultStyleName) MouseCursor = MouseCursorType.IBeam; } - + private void DeleteChars(int pos, int l) { if (l == 0) @@ -434,8 +439,10 @@ private int Delete(int where, int len) } UndoStack.MakeDelete(Text, where, len); + var stringToDelete = Text.Substring(where, len); DeleteChars(where, len); + TextDeleted?.Invoke(this, new TextDeletedEventArgs(where, stringToDelete)); return len; } @@ -915,19 +922,11 @@ private bool SetText(string value, bool byUser) InvalidateMeasure(); - var ev = TextChanged; - if (ev != null) - { - ev(this, new ValueChangedEventArgs(oldValue, value)); - } + TextChanged?.Invoke(this, new ValueChangedEventArgs(oldValue, value)); if (byUser) { - ev = TextChangedByUser; - if (ev != null) - { - ev(this, new ValueChangedEventArgs(oldValue, value)); - } + TextChangedByUser?.Invoke(this, new ValueChangedEventArgs(oldValue, value)); } return true; @@ -1106,6 +1105,8 @@ private void UpdateScrolling() private void OnCursorIndexChanged() { + _lastCursorUpdate = DateTime.Now; + UpdateScrolling(); CursorPositionChanged.Invoke(this); @@ -1439,6 +1440,13 @@ public override void InternalRender(RenderContext context) } var now = DateTime.Now; + + if (_lastCursorUpdate > _lastBlinkStamp) + { + _lastBlinkStamp = _lastCursorUpdate; + _cursorOn = true; + } + if ((now - _lastBlinkStamp).TotalMilliseconds >= BlinkIntervalInMs) { _cursorOn = !_cursorOn; diff --git a/src/MyraPad/StringExtensions.cs b/src/MyraPad/StringExtensions.cs new file mode 100644 index 00000000..075a4c00 --- /dev/null +++ b/src/MyraPad/StringExtensions.cs @@ -0,0 +1,54 @@ +namespace MyraPad +{ + internal static class StringExtensions + { + /// + /// Returns the character at the index of string, or returns null when out of range and does not throw exception. + /// + /// + /// + /// + internal static char? GetCharSafely(this string @this, int index) + { + if (index < @this.Length && index >= 0) + { + return @this[index]; + } + + return null; + } + + /// + /// Returns a substring of this string, or returns null when out of range and does not throw exception. + /// + /// + /// + /// + /// + internal static string SubstringSafely(this string @this, int index, int count) + { + if (count <= 0) + { + return string.Empty; + } + + if (index < 0) + { + return null; + } + + if (index >= @this.Length) + { + return null; + } + + if (index + count >= @this.Length) + { + return null; + } + + return @this.Substring(index, count); + + } + } +} \ No newline at end of file diff --git a/src/MyraPad/Studio.cs b/src/MyraPad/Studio.cs index cd64b316..6943f42e 100644 --- a/src/MyraPad/Studio.cs +++ b/src/MyraPad/Studio.cs @@ -483,7 +483,7 @@ private void BuildUI() _ui._textSource.TextChanged += _textSource_TextChanged; _ui._textSource.KeyDown += _textSource_KeyDown; _ui._textSource.Char += _textSource_Char; - + _ui._textSource.TextDeleted += _textSource_TextDeleted; _ui._textStatus.Text = string.Empty; _ui._textLocation.Text = "Line: 0, Column: 0, Indent: 0"; @@ -502,6 +502,39 @@ private void BuildUI() UpdateMenuFile(); } + private void _textSource_TextDeleted(object sender, TextDeletedEventArgs e) + { + if (e.Value.Contains('\n')) + { + return; + } + + var endIndexOfLine = _ui._textSource.Text.IndexOf('\n', e.StartPosition); + var startIndexOfLine = _ui._textSource.Text.LastIndexOf('\n', e.StartPosition - 1); + + if (endIndexOfLine < 0) + { + endIndexOfLine = _ui._textSource.Text.Length; + } + + if (startIndexOfLine < 0) + { + startIndexOfLine = 0; + } + + var currentLineString = _ui._textSource.Text[startIndexOfLine..endIndexOfLine]; + if (currentLineString is null) + { + return; + } + + if (string.IsNullOrWhiteSpace(currentLineString)) + { + _ui._textSource.Text = _ui._textSource.Text.Remove(startIndexOfLine, currentLineString.Length); + _ui._textSource.CursorPosition = startIndexOfLine + 1; + } + } + private void _textBoxFilter_TextChanged(object sender, ValueChangedEventArgs e) { PropertyGrid.Filter = _ui._textBoxFilter.Text; @@ -742,20 +775,24 @@ private void ApplyAutoIndent() return; } - var il = _indentLevel; - if (pos < text.Length - 2 && text[pos] == '<' && text[pos + 1] == '/') - { - --il; - } + var indentLevel = _indentLevel; + bool wrapAfterIndent = text.SubstringSafely(pos + 1, 2) == ""; - _ui._textSource.Insert(pos, close); + var closeTag = ""; + _ui._textSource.Insert(pos + 1, closeTag); + + _ui._textSource.CursorPosition = pos; + //Method Insert(int, string) has moved the cursor position + //this will restore the cursor to the position after '' and before '' } private void _textSource_TextChanged(object sender, ValueChangedEventArgs e) From da7d4f4a7dcd3504848373349ccc8f484701f938 Mon Sep 17 00:00:00 2001 From: p0_INT32 <834936537@qq.com> Date: Sun, 21 Apr 2024 10:56:34 +0800 Subject: [PATCH 2/2] Fixed bug with deleting --- src/MyraPad/StringExtensions.cs | 20 ++++++++++++++++++++ src/MyraPad/Studio.cs | 7 +++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/MyraPad/StringExtensions.cs b/src/MyraPad/StringExtensions.cs index 075a4c00..573fcc2f 100644 --- a/src/MyraPad/StringExtensions.cs +++ b/src/MyraPad/StringExtensions.cs @@ -50,5 +50,25 @@ internal static string SubstringSafely(this string @this, int index, int count) return @this.Substring(index, count); } + + public static int LastIndexOfSafely(this string @this, char character, int index) + { + if (index < 0 || index >= @this.Length) + { + return -1; + } + + return @this.LastIndexOf(character, index); + } + + public static int IndexOfSafely(this string @this, char character, int index) + { + if (index < 0 || index >= @this.Length) + { + return -1; + } + + return @this.IndexOf(character, index); + } } } \ No newline at end of file diff --git a/src/MyraPad/Studio.cs b/src/MyraPad/Studio.cs index 6943f42e..fedc06d7 100644 --- a/src/MyraPad/Studio.cs +++ b/src/MyraPad/Studio.cs @@ -502,16 +502,15 @@ private void BuildUI() UpdateMenuFile(); } - private void _textSource_TextDeleted(object sender, TextDeletedEventArgs e) + private void _textSource_TextDeleted(object _, TextDeletedEventArgs e) { if (e.Value.Contains('\n')) { return; } - var endIndexOfLine = _ui._textSource.Text.IndexOf('\n', e.StartPosition); - var startIndexOfLine = _ui._textSource.Text.LastIndexOf('\n', e.StartPosition - 1); - + int startIndexOfLine = _ui._textSource.Text.LastIndexOfSafely('\n', _ui._textSource.CursorPosition - 2); + var endIndexOfLine = _ui._textSource.Text.IndexOfSafely('\n', _ui._textSource.CursorPosition - 2); if (endIndexOfLine < 0) { endIndexOfLine = _ui._textSource.Text.Length;