From 4aa953ba4402899ebcd720d2dc306e14094d73a8 Mon Sep 17 00:00:00 2001 From: Kingcean Date: Fri, 10 Jan 2025 22:56:26 +0800 Subject: [PATCH] Optimize WPF components to get lines in viewport and by query finding --- DiffPlex.App/DiffPlex.App.csproj | 2 +- DiffPlex.Windows/Converters.cs | 82 ++++- DiffPlex.Windows/DiffPlex.Windows.csproj | 2 +- DiffPlex.Windows/DiffTextView.xaml.cs | 63 +++- DiffPlex.Windows/{Internals.cs => Helper.cs} | 136 ------- DiffPlex.Windows/Models.cs | 334 ++++++++++++++++++ DiffPlex.Wpf/Controls/DiffViewer.xaml.cs | 11 + DiffPlex.Wpf/Controls/Helper.cs | 60 ++-- .../Controls/InlineDiffViewer.xaml.cs | 10 + .../Controls/LineViewportStateInfo.cs | 53 +++ .../Controls/SideBySideDiffViewer.xaml.cs | 20 ++ 11 files changed, 590 insertions(+), 183 deletions(-) rename DiffPlex.Windows/{Internals.cs => Helper.cs} (54%) create mode 100644 DiffPlex.Windows/Models.cs create mode 100644 DiffPlex.Wpf/Controls/LineViewportStateInfo.cs diff --git a/DiffPlex.App/DiffPlex.App.csproj b/DiffPlex.App/DiffPlex.App.csproj index b1503d4e..b900706f 100644 --- a/DiffPlex.App/DiffPlex.App.csproj +++ b/DiffPlex.App/DiffPlex.App.csproj @@ -27,7 +27,7 @@ - + diff --git a/DiffPlex.Windows/Converters.cs b/DiffPlex.Windows/Converters.cs index 9942b10d..5c2e96ee 100644 --- a/DiffPlex.Windows/Converters.cs +++ b/DiffPlex.Windows/Converters.cs @@ -16,21 +16,13 @@ namespace DiffPlex.UI; /// /// The base converter for change type. /// -public class DiffChangeTypeConverter : IValueConverter +/// The default chagne type. +public class DiffChangeTypeConverter(ChangeType defaultChangeType) : IValueConverter { - /// - /// Initializes a new instance of the DiffChangeTypeConverter class. - /// - /// The default chagne type. - public DiffChangeTypeConverter(ChangeType defaultChangeType) - { - ModifyChangeType = defaultChangeType; - } - /// /// Gets or sets the default change type for modify. /// - public ChangeType ModifyChangeType { get; set; } + public ChangeType ModifyChangeType { get; set; } = defaultChangeType; /// /// Gets or sets the default change type for modify. @@ -129,3 +121,71 @@ public NewDiffChangeTypeConverter() { } } + +/// +/// The base converter for change type. +/// +/// The default chagne type. +public class DiffTextHighlighterConverter(ChangeType defaultChangeType) : IValueConverter +{ + /// + /// Gets or sets the default change type for modify. + /// + public ChangeType ModifyChangeType { get; set; } = defaultChangeType; + + /// + /// Gets or sets the foreground. + /// + public Brush Foreground { get; set; } + + /// + /// Converts a source to target. + /// + public object Convert(object value, Type targetType, object parameter, string language) + { + if (value is FrameworkElement element) value = element.DataContext; + if (value is not List sub) + { + if (value is DiffPiece p) sub = p.SubPieces; + else return null; + } + + return InternalUtilities.GetTextHighlighter(sub, ModifyChangeType, Foreground ?? (parameter as Brush)); + } + + /// + /// Converts the source back. + /// + public object ConvertBack(object value, Type targetType, object parameter, string language) + { + return null; + } +} + +/// +/// The diff change type converter for old text. +/// +public class DeletedDiffTextHighlighterConverter : DiffTextHighlighterConverter +{ + /// + /// Initializes a new instance of the DeletedDiffTextHighlighterConverter class. + /// + public DeletedDiffTextHighlighterConverter() + : base(ChangeType.Deleted) + { + } +} + +/// +/// The diff change type converter for new text. +/// +public class InsertedDiffTextHighlighterConverter : DiffTextHighlighterConverter +{ + /// + /// Initializes a new instance of the InsertedDiffTextHighlighterConverter class. + /// + public InsertedDiffTextHighlighterConverter() + : base(ChangeType.Inserted) + { + } +} diff --git a/DiffPlex.Windows/DiffPlex.Windows.csproj b/DiffPlex.Windows/DiffPlex.Windows.csproj index e3477b89..7cf2c9a2 100644 --- a/DiffPlex.Windows/DiffPlex.Windows.csproj +++ b/DiffPlex.Windows/DiffPlex.Windows.csproj @@ -37,7 +37,7 @@ - + diff --git a/DiffPlex.Windows/DiffTextView.xaml.cs b/DiffPlex.Windows/DiffTextView.xaml.cs index b3af1361..e74e4ef7 100644 --- a/DiffPlex.Windows/DiffTextView.xaml.cs +++ b/DiffPlex.Windows/DiffTextView.xaml.cs @@ -545,13 +545,13 @@ public void ScrollNextDiffIntoView() /// /// The string to seek. /// All line numbers with the given string. - public IEnumerable Find(string q) + public IEnumerable Find(string q) { var list = GetActiveListView(); foreach (var item in list.Items) { - if (!GetItemFromList(list, item, out var container, out var model)) continue; - if (model.Contains(q)) yield return model.LineNumber; + if (item is not BaseDiffTextViewModel m) continue; + if (m.Contains(q)) yield return m.ToInfo(); } } @@ -577,6 +577,28 @@ public bool Focus(int lineNumber, FocusState focusState) } } + /// + /// Attempts to set focus to a specific line. + /// + /// The line. + /// How this element obtains focus. + /// true if keyboard focus and logical focus were set to the specific line; otherwise, false, if only logical focus was set to the specific line, or if the call to this method did not force the focus to change. + public bool Focus(DiffTextViewInfo info, FocusState focusState) + { + if (!info.Position.HasValue) return false; + switch (info.ViewType) + { + case DiffTextViewType.Inline: + return FocusInUnifiedView(info.Position.Value, focusState); + case DiffTextViewType.Left: + return FocusInSplitView(info.Position.Value, true, focusState); + case DiffTextViewType.Right: + return FocusInSplitView(info.Position.Value, false, focusState); + } + + return false; + } + /// /// Attempts to set focus to a specific line. /// @@ -636,6 +658,41 @@ public void ScrollIntoView(int lineNumber, ScrollIntoViewAlignment alignment = S } } + /// + /// Scrolls the list to bring the specified line number into view with the specified alignment. + /// + /// The line info. + /// An enumeration value that specifies whether the item uses default or leading alignment. + public void ScrollIntoView(DiffTextViewInfo info, ScrollIntoViewAlignment alignment = ScrollIntoViewAlignment.Default) + { + if (info.Position == null) return; + var lineNumber = info.Position.Value; + switch (info.ViewType) + { + case DiffTextViewType.Inline: + { + var line = inlines.FirstOrDefault(ele => ele?.Position == lineNumber); + if (line is null) return; + UnifiedElement.ScrollIntoView(line, alignment); + break; + } + case DiffTextViewType.Left: + { + var line = sideBySide.FirstOrDefault(ele => ele?.Left?.Position == lineNumber); + if (line is null) return; + SplitElement.ScrollIntoView(line, alignment); + break; + } + case DiffTextViewType.Right: + { + var line = sideBySide.FirstOrDefault(ele => ele?.Right?.Position == lineNumber); + if (line is null) return; + SplitElement.ScrollIntoView(line, alignment); + break; + } + } + } + /// /// Collapses unchanged sections. /// diff --git a/DiffPlex.Windows/Internals.cs b/DiffPlex.Windows/Helper.cs similarity index 54% rename from DiffPlex.Windows/Internals.cs rename to DiffPlex.Windows/Helper.cs index 54976e9d..2ee40ca0 100644 --- a/DiffPlex.Windows/Internals.cs +++ b/DiffPlex.Windows/Helper.cs @@ -166,139 +166,3 @@ public static async Task TryGetFileTextAsync(Window window, Action -/// The base view model for diff text. -/// -internal abstract class BaseDiffTextViewModel -{ - /// - /// Get or set the line number. - /// - public int LineNumber { get; set; } - - /// - /// Gets a value indicating whether the line is unchanged. - /// - public abstract bool IsUnchanged { get; } - - /// - /// Gets a value indicating whether the current line is null. - /// - public abstract bool IsNullLine { get; } - - /// - /// Returns a value indicating whether a specified substring occurs within the text in this view model. - /// - /// The string to seek. - /// true if the value parameter occurs within the text in this view model; otherwise, false. - public abstract bool Contains(string q); -} - -/// -/// The diff text view model of split mode. -/// -internal class DiffTextViewModel : BaseDiffTextViewModel -{ - public DiffTextViewModel() - { - } - - public DiffTextViewModel(int number, DiffPiece left, DiffPiece right) - : this(number, left, right, null) - { - } - - public DiffTextViewModel(int number, DiffPiece left, DiffPiece right, DiffTextViewReference reference) - { - LineNumber = number; - Left = left; - Right = right; - Reference = reference; - } - - public DiffPiece Left { get; private set; } - - public DiffPiece Right { get; private set; } - - public DiffTextViewReference Reference { get; private set; } - - public string LeftText => Left?.Text; - - public string RightText => Right?.Text; - - /// - public override bool IsUnchanged => Right?.Type == ChangeType.Unchanged; - - /// - public override bool IsNullLine => Right is null; - - public IEnumerable GetLeftHighlighter() - => InternalUtilities.GetTextHighlighter(Left?.SubPieces, ChangeType.Deleted, Reference?.Element?.Foreground); - - public IEnumerable GetRightHighlighter() - => InternalUtilities.GetTextHighlighter(Right?.SubPieces, ChangeType.Inserted, Reference?.Element?.Foreground); - - /// - public override bool Contains(string q) - { - if (string.IsNullOrEmpty(q)) return false; - var v = Right?.Text; - if (v != null && v.Contains(q)) return true; - v = Left?.Text; - if (v != null && v.Contains(q)) return true; - return false; - } -} - -/// -/// The diff text view model of unified mode. -/// -internal class InlineDiffTextViewModel : BaseDiffTextViewModel -{ - public InlineDiffTextViewModel() - { - } - - public InlineDiffTextViewModel(int number, DiffPiece line) - : this(number, line, null) - { - } - - public InlineDiffTextViewModel(int number, DiffPiece line, DiffTextViewReference reference) - { - LineNumber = number; - Line = line; - Reference = reference; - } - - public DiffPiece Line { get; private set; } - - public string Text => Line?.Text; - - public int? Position => Line?.Position; - - public DiffTextViewReference Reference { get; private set; } - - /// - public override bool IsUnchanged => Line?.Type == ChangeType.Unchanged; - - /// - public override bool IsNullLine => Line is null; - - public IEnumerable GetTextHighlighter() - => InternalUtilities.GetTextHighlighter(Line?.SubPieces, ChangeType.Deleted, Reference?.Element?.Foreground); - - /// - public override bool Contains(string q) - { - if (string.IsNullOrEmpty(q)) return false; - var v = Line?.Text; - return v != null && v.Contains(q); - } -} - -internal class DiffTextViewReference(DiffTextView element) -{ - public DiffTextView Element { get; set; } = element; -} diff --git a/DiffPlex.Windows/Models.cs b/DiffPlex.Windows/Models.cs new file mode 100644 index 00000000..c40aff85 --- /dev/null +++ b/DiffPlex.Windows/Models.cs @@ -0,0 +1,334 @@ +using DiffPlex.DiffBuilder.Model; +using Microsoft.UI.Xaml.Documents; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DiffPlex.UI; + +/// +/// The view types of the diff text. +/// +public enum DiffTextViewType : byte +{ + /// + /// Unknown. + /// + Unknown = 0, + + /// + /// Inline item in unified view. + /// + Inline = 1, + + /// + /// Left (old) item in split view. + /// + Left = 2, + + /// + /// Right (new) item in split view. + /// + Right = 3, +} + +public struct DiffTextViewInfo +{ + private readonly object token; + + /// + /// Initializes a new instance of the DiffTextViewInfo class. + /// + /// The token. + /// The view type. + /// The diff piece instance. + internal DiffTextViewInfo(object token, DiffTextViewType viewType, DiffPiece model) + { + this.token = token ?? new(); + ViewType = viewType; + model ??= new(); + ChangeType = model.Type; + Position = model.Position; + Text = model.Text; + } + + /// + /// Gets the view type. + /// + public DiffTextViewType ViewType { get; } + + /// + /// Gets the change type. + /// + public ChangeType ChangeType { get; } + + /// + /// Gets the line position. + /// + public int? Position { get; } + + /// + /// Gets the content text. + /// + public string Text { get; } + + /// + public override string ToString() + { + var sb = new StringBuilder(); + if (Position.HasValue) + { + sb.Append(Position.Value); + sb.Append(' '); + } + + switch (ChangeType) + { + case ChangeType.Inserted: + sb.Append("+ "); + break; + case ChangeType.Deleted: + sb.Append("- "); + break; + } + + sb.Append('\t'); + sb.Append(Text); + return sb.ToString(); + } + + /// + /// Tests if the token is the current one. + /// + /// The token to test. + /// true if the same; otherwise, false. + internal bool IsToken(object token) + => token == this.token; +} + +/// +/// The base view model for diff text. +/// +internal abstract class BaseDiffTextViewModel : IEquatable +{ + private readonly object token = new(); + + /// + /// Get or set the line index. + /// + public int Index { get; set; } + + /// + /// Gets a value indicating whether the line is unchanged. + /// + public abstract bool IsUnchanged { get; } + + /// + /// Gets a value indicating whether the text is null. + /// + public bool IsNullLine => SourceText is null; + + /// + /// Gets the text. + /// + public abstract string SourceText { get; } + + /// + /// Gets the position. + /// + public abstract int? Position { get; } + + /// + /// Returns a value indicating whether a specified substring occurs within the text in this view model. + /// + /// The string to seek. + /// true if the value parameter occurs within the text in this view model; otherwise, false. + public abstract bool Contains(string q); + + /// + /// Converts to the view info of diff piece. + /// + public abstract DiffTextViewInfo ToInfo(); + + /// + /// Converts to the view info of diff piece. + /// + protected DiffTextViewInfo ToInfo(DiffTextViewType viewType, DiffPiece diffPiece) + { + return new(token, viewType, diffPiece); + } + + public bool Equals(DiffTextViewInfo other) + { + return other.IsToken(token); + } +} + +/// +/// The diff text view model of split mode. +/// +internal class DiffTextViewModel : BaseDiffTextViewModel +{ + private object token = new(); + + /// + /// Initializes a new instance of the class. + /// + public DiffTextViewModel() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The line index. + /// The left diff piece instance. + /// The right diff piece instance. + public DiffTextViewModel(int index, DiffPiece left, DiffPiece right) + : this(index, left, right, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The line index. + /// The left diff piece instance. + /// The right diff piece instance. + /// The view reference. + public DiffTextViewModel(int index, DiffPiece left, DiffPiece right, DiffTextViewReference reference) + { + Index = index; + Left = left; + Right = right; + Reference = reference; + } + + public DiffPiece Left { get; private set; } + + public DiffPiece Right { get; private set; } + + /// + /// Gets the view reference. + /// + public DiffTextViewReference Reference { get; private set; } + + /// + /// Gets the left text. + /// + public string LeftText => Left?.Text; + + /// + /// Gets the right text. + /// + public string RightText => Right?.Text; + + /// + public override bool IsUnchanged => Right?.Type == ChangeType.Unchanged; + + /// + public override string SourceText => Right?.Text; + + /// + public override int? Position => Right?.Position; + + public IEnumerable GetLeftHighlighter() + => InternalUtilities.GetTextHighlighter(Left?.SubPieces, ChangeType.Deleted, Reference?.Element?.Foreground); + + public IEnumerable GetRightHighlighter() + => InternalUtilities.GetTextHighlighter(Right?.SubPieces, ChangeType.Inserted, Reference?.Element?.Foreground); + + /// + public override bool Contains(string q) + { + if (string.IsNullOrEmpty(q)) return false; + var v = Right?.Text; + if (v != null && v.Contains(q)) return true; + v = Left?.Text; + if (v != null && v.Contains(q)) return true; + return false; + } + + /// + public override DiffTextViewInfo ToInfo() + => ToInfo(DiffTextViewType.Right, Right); +} + +/// +/// The diff text view model of unified mode. +/// +internal class InlineDiffTextViewModel : BaseDiffTextViewModel +{ + /// + /// Initializes a new instance of the class. + /// + public InlineDiffTextViewModel() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The line index. + /// The inline diff piece instance. + public InlineDiffTextViewModel(int index, DiffPiece line) + : this(index, line, null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The line index. + /// The inline diff piece instance. + /// The view reference. + public InlineDiffTextViewModel(int index, DiffPiece line, DiffTextViewReference reference) + { + Index = index; + Line = line; + Reference = reference; + } + + public DiffPiece Line { get; private set; } + + /// + /// Gets the text. + /// + public string Text => Line?.Text; + + /// + public override int? Position => Line?.Position; + + /// + /// Gets the view reference. + /// + public DiffTextViewReference Reference { get; private set; } + + /// + public override bool IsUnchanged => Line?.Type == ChangeType.Unchanged; + + /// + public override string SourceText => Line?.Text; + + public IEnumerable GetTextHighlighter() + => InternalUtilities.GetTextHighlighter(Line?.SubPieces, ChangeType.Deleted, Reference?.Element?.Foreground); + + /// + public override bool Contains(string q) + { + if (string.IsNullOrEmpty(q)) return false; + var v = Line?.Text; + return v != null && v.Contains(q); + } + + /// + public override DiffTextViewInfo ToInfo() + => ToInfo(DiffTextViewType.Inline, Line); +} + +internal class DiffTextViewReference(DiffTextView element) +{ + public DiffTextView Element { get; set; } = element; +} diff --git a/DiffPlex.Wpf/Controls/DiffViewer.xaml.cs b/DiffPlex.Wpf/Controls/DiffViewer.xaml.cs index 83f8599e..feab0a3c 100644 --- a/DiffPlex.Wpf/Controls/DiffViewer.xaml.cs +++ b/DiffPlex.Wpf/Controls/DiffViewer.xaml.cs @@ -1064,6 +1064,17 @@ public IEnumerable GetLinesAfterViewport(VisibilityLevels level) else return Helper.GetLinesAfterViewport(InlineContentPanel, level); } + /// + /// Finds all line numbers that the text contains the given string. + /// + /// The string to seek. + /// All lines with the given string. + public IEnumerable Find(string q) + { + if (IsSideBySide) return Helper.Find(RightContentPanel, q); + else return Helper.Find(InlineContentPanel, q); + } + /// /// Opens the context menu for view mode selection. /// diff --git a/DiffPlex.Wpf/Controls/Helper.cs b/DiffPlex.Wpf/Controls/Helper.cs index 47723981..bb0a8a8c 100644 --- a/DiffPlex.Wpf/Controls/Helper.cs +++ b/DiffPlex.Wpf/Controls/Helper.cs @@ -9,27 +9,6 @@ namespace DiffPlex.Wpf.Controls; -/// -/// Visibility levels. -/// -public enum VisibilityLevels -{ - /// - /// Any part of visual in viewport. - /// - Any = 0, - - /// - /// Half at least in viewport. - /// - Half = 1, - - /// - /// All visual in viewport. - /// - All = 2 -} - internal static class Helper { private const int MaxCount = 3000; @@ -296,14 +275,15 @@ internal static IEnumerable GetLinesInViewport(InternalLinesViewer pa var needBreak = false; foreach (var item in states) { - if (!item.Item2) + if (item.IsCollapsed) continue; + if (!item.IsInViewport) { if (needBreak) yield break; continue; } needBreak = true; - yield return item.Item1; + yield return item.Model; } } @@ -318,8 +298,9 @@ internal static IEnumerable GetLinesBeforeViewport(InternalLinesViewe var states = GetLineViewportStates(panel, level); foreach (var item in states) { - if (item.Item2) yield break; - yield return item.Item1; + if (item.IsCollapsed) continue; + if (item.IsInViewport) yield break; + yield return item.Model; } } @@ -335,13 +316,14 @@ internal static IEnumerable GetLinesAfterViewport(InternalLinesViewer var needReturn = false; foreach (var item in states) { - if (item.Item2) + if (item.IsCollapsed) continue; + if (item.IsInViewport) { needReturn = true; continue; } - if (needReturn) yield return item.Item1; + if (needReturn) yield return item.Model; } } @@ -398,13 +380,29 @@ internal static ContextMenu CreateLineContextMenu(FrameworkElement parentElement return menu; } + /// + /// Finds all line numbers that the text contains the given string. + /// + /// The content panel. + /// The string to seek. + /// All lines with the given string. + internal static IEnumerable Find(InternalLinesViewer panel, string q) + { + if (string.IsNullOrEmpty(q)) yield break; + foreach (var item in panel.ValuePanel.Children) + { + if (item is not FrameworkElement ele || ele.Tag is not DiffPiece line || line.Text == null) continue; + if (line.Text.Contains(q)) yield return line; + } + } + /// /// Gets all line information in viewport. /// /// The content panel. /// The optional visibility level. /// All lines. - private static IEnumerable> GetLineViewportStates(InternalLinesViewer panel, VisibilityLevels level) + private static IEnumerable GetLineViewportStates(InternalLinesViewer panel, VisibilityLevels level) { var scrollView = panel.ValueScrollViewer; var point = new Point(0, 0); @@ -416,7 +414,7 @@ private static IEnumerable> GetLineViewportStates(Interna if (item is not FrameworkElement ele || ele.Tag is not DiffPiece line) continue; var pos = ele.TranslatePoint(point, panel.ValueScrollViewer); var isIn = ele.ActualHeight > 0 && pos.Y >= 0 && pos.Y <= scrollView.ActualHeight - ele.ActualHeight; - yield return new Tuple(line, isIn); + yield return new(line, isIn, ele.Visibility != Visibility.Visible); } break; @@ -427,7 +425,7 @@ private static IEnumerable> GetLineViewportStates(Interna var pos = ele.TranslatePoint(point, panel.ValueScrollViewer); var halfHeight = ele.ActualHeight / 2; var isIn = halfHeight > 0 && pos.Y >= -halfHeight && pos.Y <= scrollView.ActualHeight - halfHeight; - yield return new Tuple(line, isIn); + yield return new(line, isIn, ele.Visibility != Visibility.Visible); } break; @@ -437,7 +435,7 @@ private static IEnumerable> GetLineViewportStates(Interna if (item is not FrameworkElement ele || ele.Tag is not DiffPiece line) continue; var pos = ele.TranslatePoint(point, panel.ValueScrollViewer); var isIn = ele.ActualHeight > 0 && pos.Y > -ele.ActualHeight && pos.Y < scrollView.ActualHeight; - yield return new Tuple(line, isIn); + yield return new(line, isIn, ele.Visibility != Visibility.Visible); } break; diff --git a/DiffPlex.Wpf/Controls/InlineDiffViewer.xaml.cs b/DiffPlex.Wpf/Controls/InlineDiffViewer.xaml.cs index 85b11c98..692dfab1 100644 --- a/DiffPlex.Wpf/Controls/InlineDiffViewer.xaml.cs +++ b/DiffPlex.Wpf/Controls/InlineDiffViewer.xaml.cs @@ -497,6 +497,16 @@ public IEnumerable GetLinesAfterViewport(VisibilityLevels level) return Helper.GetLinesAfterViewport(ContentPanel, level); } + /// + /// Finds all line numbers that the text contains the given string. + /// + /// The string to seek. + /// All line numbers with the given string. + public IEnumerable Find(string q) + { + return Helper.Find(ContentPanel, q); + } + /// /// Collapses unchanged sections. /// diff --git a/DiffPlex.Wpf/Controls/LineViewportStateInfo.cs b/DiffPlex.Wpf/Controls/LineViewportStateInfo.cs new file mode 100644 index 00000000..b6ea35fe --- /dev/null +++ b/DiffPlex.Wpf/Controls/LineViewportStateInfo.cs @@ -0,0 +1,53 @@ +using DiffPlex.DiffBuilder.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DiffPlex.Wpf.Controls; + +/// +/// Visibility levels. +/// +public enum VisibilityLevels : byte +{ + /// + /// Any part of visual in viewport. + /// + Any = 0, + + /// + /// Half at least in viewport. + /// + Half = 1, + + /// + /// All visual in viewport. + /// + All = 2 +} + +/// +/// The state information of the line viewport. +/// +/// The diff piece instance. +/// true if the element is in viewport; otherwise, false. +/// true if the visibility of the element is to collapse; otherwise, false. +internal struct LineViewportStateInfo(DiffPiece model, bool isInViewport, bool isCollapsed) +{ + /// + /// Gets the diff piece instance. + /// + public DiffPiece Model { get; } = model; + + /// + /// Gets a value indicating whether the element is in viewport. + /// + public bool IsInViewport { get; } = isInViewport; + + /// + /// Gets a value indicating whether the visibility of the element is to collapse. + /// + public bool IsCollapsed { get; } = isCollapsed; +} diff --git a/DiffPlex.Wpf/Controls/SideBySideDiffViewer.xaml.cs b/DiffPlex.Wpf/Controls/SideBySideDiffViewer.xaml.cs index 4bf069c4..d9961b3a 100644 --- a/DiffPlex.Wpf/Controls/SideBySideDiffViewer.xaml.cs +++ b/DiffPlex.Wpf/Controls/SideBySideDiffViewer.xaml.cs @@ -586,6 +586,26 @@ public IEnumerable GetLinesAfterViewport(VisibilityLevels level) return Helper.GetLinesAfterViewport(RightContentPanel, level); } + /// + /// Finds all line numbers that the text contains the given string. + /// + /// The string to seek. + /// All lines with the given string. + public IEnumerable Find(string q) + { + return Helper.Find(RightContentPanel, q); + } + + /// + /// Finds all line numbers that the text contains the given string. + /// + /// The string to seek. + /// All line numbers with the given string. + public IEnumerable FindInOld(string q) + { + return Helper.Find(LeftContentPanel, q); + } + /// /// Collapses unchanged sections. ///