From fff1a50634fc90ca2f6118091a540203eeb9082d Mon Sep 17 00:00:00 2001 From: zufuliu Date: Wed, 31 Jan 2024 18:23:57 +0800 Subject: [PATCH] Improve cache behavior, avoid output box get focused to prevent auto scroll. --- FindInFilesForm.cs | 19 ++++++++++++++++--- NET48/FindInFilesForm.cs | 19 ++++++++++++++++--- NET48/OutputLineParser.cs | 2 +- NET48/Util.cs | 5 +---- OutputLineParser.cs | 2 +- Util.cs | 5 +---- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/FindInFilesForm.cs b/FindInFilesForm.cs index 7a495f0..a737ee9 100644 --- a/FindInFilesForm.cs +++ b/FindInFilesForm.cs @@ -83,13 +83,12 @@ private async void buttonStart_Click(object sender, EventArgs e) { process.StartInfo.FileName = exePath; process.StartInfo.Arguments = argument; process.OutputDataReceived += Process_OutputDataReceived; - buttonFind.Enabled = false; process.Start(); process.BeginOutputReadLine(); var error = await process.StandardError.ReadToEndAsync(); await process.WaitForExitAsync(); - buttonFind.Enabled = true; lineParser.Flush(); + richTextBox.Invalidate(); if (!string.IsNullOrEmpty(error)) { AppendText($"{error}{Environment.NewLine}", Color.Red); } @@ -106,17 +105,28 @@ private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) private readonly OutputLineParser lineParser; private static readonly string MarkerPath = "\u200C"; // zero width non-joiner private static readonly string MarkerLine = "\u200D"; // zero width joiner + private int visibleDelta = 0; private void ClearMatchResult() { var page = (int)(richTextBox.Height / richTextBox.GetLineHeight()); - page += page / 4; page = Math.Max(page, 5); + visibleDelta = page * 2; richTextBox.Clear(); lineParser.MaxCachedLine = page; lineParser.Clear(); } private void RenderOutput(List lines) { + var visible = richTextBox.Focused; + if (!visible) { + var last = richTextBox.GetLineFromCharIndex(-1); + if (last < visibleDelta) { + visible = true; + } else { + var top = richTextBox.GetLineFromCharIndex(richTextBox.GetCharIndexFromPosition(new Point(1, 1))); + visible = last - top < visibleDelta; + } + } richTextBox.SetRedraw(false); foreach (var line in lines) { switch (line.LineType) { @@ -138,6 +148,9 @@ private void RenderOutput(List lines) { } } richTextBox.SetRedraw(true); + if (visible) { + richTextBox.Invalidate(); + } } private void AddContextLine(int number, string? line) { diff --git a/NET48/FindInFilesForm.cs b/NET48/FindInFilesForm.cs index 56afa2b..fe7ab13 100644 --- a/NET48/FindInFilesForm.cs +++ b/NET48/FindInFilesForm.cs @@ -88,13 +88,12 @@ private async void buttonStart_Click(object sender, EventArgs e) { process.StartInfo.FileName = exePath; process.StartInfo.Arguments = argument; process.OutputDataReceived += Process_OutputDataReceived; - buttonFind.Enabled = false; process.Start(); process.BeginOutputReadLine(); var error = await process.StandardError.ReadToEndAsync(); await Task.Run(() => process.WaitForExit()); - buttonFind.Enabled = true; lineParser.Flush(); + richTextBox.Invalidate(); if (!string.IsNullOrEmpty(error)) { AppendText($"{error}{Environment.NewLine}", Color.Red); } @@ -111,17 +110,28 @@ private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) private readonly OutputLineParser lineParser; private static readonly string MarkerPath = "\u200C"; // zero width non-joiner private static readonly string MarkerLine = "\u200D"; // zero width joiner + private int visibleDelta = 0; private void ClearMatchResult() { var page = (int)(richTextBox.Height / richTextBox.GetLineHeight()); - page += page / 4; page = Math.Max(page, 5); + visibleDelta = page * 2; richTextBox.Clear(); lineParser.MaxCachedLine = page; lineParser.Clear(); } private void RenderOutput(List lines) { + var visible = richTextBox.Focused; + if (!visible) { + var last = richTextBox.GetLineFromCharIndex(-1); + if (last < visibleDelta) { + visible = true; + } else { + var top = richTextBox.GetLineFromCharIndex(richTextBox.GetCharIndexFromPosition(new Point(1, 1))); + visible = last - top < visibleDelta; + } + } richTextBox.SetRedraw(false); foreach (var line in lines) { switch (line.LineType) { @@ -143,6 +153,9 @@ private void RenderOutput(List lines) { } } richTextBox.SetRedraw(true); + if (visible) { + richTextBox.Invalidate(); + } } private void AddContextLine(string number, string line) { diff --git a/NET48/OutputLineParser.cs b/NET48/OutputLineParser.cs index 2af64c8..e97335e 100644 --- a/NET48/OutputLineParser.cs +++ b/NET48/OutputLineParser.cs @@ -27,7 +27,7 @@ public void Clear() { public void Flush() { if (cachedLines.Count != 0) { - owner.Invoke(callback, cachedLines); + callback(cachedLines); cachedLines.Clear(); } } diff --git a/NET48/Util.cs b/NET48/Util.cs index 1cdc3e3..8f463bd 100644 --- a/NET48/Util.cs +++ b/NET48/Util.cs @@ -144,15 +144,12 @@ public static float GetLineHeight(this TextBoxBase textBox) { var lineSpacing = family.GetLineSpacing(style); var ascent = family.GetCellAscent(style); var descent = family.GetCellDescent(style); - var height = font.Size * (lineSpacing + ascent + descent) / emHeight; + var height = font.Size * (lineSpacing + (ascent + descent) / 2) / emHeight; return height; } public static void SetRedraw(this Control control, bool redraw) { SendMessage(control.Handle, WM_SETREDRAW, new IntPtr(redraw ? 1 : 0), IntPtr.Zero); - if (redraw) { - control.Invalidate(); - } } private const int WM_SETREDRAW = 0x000B; diff --git a/OutputLineParser.cs b/OutputLineParser.cs index 58f4615..c6861b5 100644 --- a/OutputLineParser.cs +++ b/OutputLineParser.cs @@ -24,7 +24,7 @@ public void Clear() { public void Flush() { if (cachedLines.Count != 0) { - owner.Invoke(callback, cachedLines); + callback(cachedLines); cachedLines.Clear(); } } diff --git a/Util.cs b/Util.cs index 1a57804..8bfa7f6 100644 --- a/Util.cs +++ b/Util.cs @@ -141,15 +141,12 @@ public static float GetLineHeight(this TextBoxBase textBox) { var lineSpacing = family.GetLineSpacing(style); var ascent = family.GetCellAscent(style); var descent = family.GetCellDescent(style); - var height = font.Size * (lineSpacing + ascent + descent) / emHeight; + var height = font.Size * (lineSpacing + (ascent + descent) / 2) / emHeight; return height; } public static void SetRedraw(this Control control, bool redraw) { SendMessage(control.Handle, WM_SETREDRAW, new IntPtr(redraw ? 1 : 0), IntPtr.Zero); - if (redraw) { - control.Invalidate(); - } } private const int WM_SETREDRAW = 0x000B;