diff --git a/DiffPlex.App/DiffPlex.App.csproj b/DiffPlex.App/DiffPlex.App.csproj
index b1503d4..b900706 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 9942b10..5c2e96e 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 e3477b8..7cf2c9a 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 b3af136..e74e4ef 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 54976e9..2ee40ca 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 0000000..c40aff8
--- /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 83f8599..feab0a3 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 4772398..bb0a8a8 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 85b11c9..692dfab 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 0000000..b6ea35f
--- /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 4bf069c..d9961b3 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.
///