mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-30 13:51:53 +08:00
refactor: rewrite text diff view
- Move some data-only code from `Views` to `ViewModels` - Remove unnecessary attributes - This commit also contains a feature request #1722 Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -48,17 +48,11 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public BlockNavigation(object context)
|
||||
public BlockNavigation(List<Models.TextDiffLine> lines)
|
||||
{
|
||||
Blocks.Clear();
|
||||
Current = -1;
|
||||
|
||||
var lines = new List<Models.TextDiffLine>();
|
||||
if (context is Models.TextDiff combined)
|
||||
lines = combined.Lines;
|
||||
else if (context is TwoSideTextDiff twoSide)
|
||||
lines = twoSide.Old;
|
||||
|
||||
if (lines.Count == 0)
|
||||
return;
|
||||
|
||||
@@ -96,7 +90,10 @@ namespace SourceGit.ViewModels
|
||||
|
||||
public Block GetCurrentBlock()
|
||||
{
|
||||
return (_current >= 0 && _current < Blocks.Count) ? Blocks[_current] : null;
|
||||
if (_current >= 0 && _current < Blocks.Count)
|
||||
return Blocks[_current];
|
||||
|
||||
return Blocks.Count > 0 ? Blocks[0] : null;
|
||||
}
|
||||
|
||||
public Block GotoFirst()
|
||||
@@ -105,6 +102,7 @@ namespace SourceGit.ViewModels
|
||||
return null;
|
||||
|
||||
Current = 0;
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
@@ -117,6 +115,8 @@ namespace SourceGit.ViewModels
|
||||
Current = 0;
|
||||
else if (_current > 0)
|
||||
Current = _current - 1;
|
||||
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
@@ -127,6 +127,8 @@ namespace SourceGit.ViewModels
|
||||
|
||||
if (_current < Blocks.Count - 1)
|
||||
Current = _current + 1;
|
||||
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
@@ -136,9 +138,35 @@ namespace SourceGit.ViewModels
|
||||
return null;
|
||||
|
||||
Current = Blocks.Count - 1;
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return Blocks[_current];
|
||||
}
|
||||
|
||||
public void AutoUpdate(int start, int end)
|
||||
{
|
||||
if (_current >= 0 && _current < Blocks.Count)
|
||||
{
|
||||
var block = Blocks[_current];
|
||||
if ((block.Start >= start && block.Start <= end) ||
|
||||
(block.End >= start && block.End <= end) ||
|
||||
(block.Start <= start && block.End >= end))
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < Blocks.Count; i++)
|
||||
{
|
||||
var block = Blocks[i];
|
||||
if ((block.Start >= start && block.Start <= end) ||
|
||||
(block.End >= start && block.End <= end) ||
|
||||
(block.Start <= start && block.End >= end))
|
||||
{
|
||||
Current = i;
|
||||
OnPropertyChanged(nameof(Indicator));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _current = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Threading;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
@@ -24,7 +22,58 @@ namespace SourceGit.ViewModels
|
||||
{
|
||||
Preferences.Instance.IgnoreWhitespaceChangesInDiff = value;
|
||||
OnPropertyChanged();
|
||||
LoadDiffContent();
|
||||
|
||||
if (_isTextDiff)
|
||||
LoadContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowEntireFile
|
||||
{
|
||||
get => Preferences.Instance.UseFullTextDiff;
|
||||
set
|
||||
{
|
||||
if (value != Preferences.Instance.UseFullTextDiff)
|
||||
{
|
||||
Preferences.Instance.UseFullTextDiff = value;
|
||||
OnPropertyChanged();
|
||||
|
||||
if (Content is TextDiffContext ctx)
|
||||
{
|
||||
ctx.Data.File = string.Empty; // Just to ignore both previous `ScrollOffset` and `BlockNavigation`
|
||||
LoadContent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseBlockNavigation
|
||||
{
|
||||
get => Preferences.Instance.UseBlockNavigationInDiffView;
|
||||
set
|
||||
{
|
||||
if (value != Preferences.Instance.UseBlockNavigationInDiffView)
|
||||
{
|
||||
Preferences.Instance.UseBlockNavigationInDiffView = value;
|
||||
OnPropertyChanged();
|
||||
(Content as TextDiffContext)?.ResetBlockNavigation(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool UseSideBySide
|
||||
{
|
||||
get => Preferences.Instance.UseSideBySideDiff;
|
||||
set
|
||||
{
|
||||
if (value != Preferences.Instance.UseSideBySideDiff)
|
||||
{
|
||||
Preferences.Instance.UseSideBySideDiff = value;
|
||||
OnPropertyChanged();
|
||||
|
||||
if (Content is TextDiffContext ctx && ctx.IsSideBySide() != value)
|
||||
Content = ctx.SwitchMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,25 +121,19 @@ namespace SourceGit.ViewModels
|
||||
else
|
||||
Title = $"{_option.OrgPath} → {_option.Path}";
|
||||
|
||||
LoadDiffContent();
|
||||
}
|
||||
|
||||
public void ToggleFullTextDiff()
|
||||
{
|
||||
Preferences.Instance.UseFullTextDiff = !Preferences.Instance.UseFullTextDiff;
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void IncrUnified()
|
||||
{
|
||||
UnifiedLines = _unifiedLines + 1;
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void DecrUnified()
|
||||
{
|
||||
UnifiedLines = Math.Max(4, _unifiedLines - 1);
|
||||
LoadDiffContent();
|
||||
LoadContent();
|
||||
}
|
||||
|
||||
public void OpenExternalMergeTool()
|
||||
@@ -98,7 +141,29 @@ namespace SourceGit.ViewModels
|
||||
new Commands.DiffTool(_repo, _option).Open();
|
||||
}
|
||||
|
||||
private void LoadDiffContent()
|
||||
public void CheckSettings()
|
||||
{
|
||||
if (Content is TextDiffContext ctx)
|
||||
{
|
||||
if ((ShowEntireFile && _info.UnifiedLines != _entireFileLine) ||
|
||||
(!ShowEntireFile && _info.UnifiedLines == _entireFileLine) ||
|
||||
(IgnoreWhitespace != _info.IgnoreWhitespace))
|
||||
{
|
||||
LoadContent();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx.IsSideBySide() != UseSideBySide)
|
||||
{
|
||||
ctx = ctx.SwitchMode();
|
||||
Content = ctx;
|
||||
}
|
||||
|
||||
ctx.ResetBlockNavigation(UseBlockNavigation);
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadContent()
|
||||
{
|
||||
if (_option.Path.EndsWith('/'))
|
||||
{
|
||||
@@ -109,7 +174,7 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Task.Run(async () =>
|
||||
{
|
||||
var numLines = Preferences.Instance.UseFullTextDiff ? 999999999 : _unifiedLines;
|
||||
var numLines = Preferences.Instance.UseFullTextDiff ? _entireFileLine : _unifiedLines;
|
||||
var ignoreWhitespace = Preferences.Instance.IgnoreWhitespaceChangesInDiff;
|
||||
|
||||
var latest = await new Commands.Diff(_repo, _option, numLines, ignoreWhitespace)
|
||||
@@ -228,12 +293,23 @@ namespace SourceGit.ViewModels
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
if (_content is Models.TextDiff old && rs is Models.TextDiff cur && old.File == cur.File)
|
||||
cur.ScrollOffset = old.ScrollOffset;
|
||||
|
||||
FileModeChange = latest.FileModeChange;
|
||||
Content = rs;
|
||||
IsTextDiff = rs is Models.TextDiff;
|
||||
|
||||
if (rs is Models.TextDiff cur)
|
||||
{
|
||||
IsTextDiff = true;
|
||||
|
||||
var hasBlockNavigation = Preferences.Instance.UseBlockNavigationInDiffView;
|
||||
if (Preferences.Instance.UseSideBySideDiff)
|
||||
Content = new TwoSideTextDiff(cur, hasBlockNavigation, _content as TwoSideTextDiff);
|
||||
else
|
||||
Content = new CombinedTextDiff(cur, hasBlockNavigation, _content as CombinedTextDiff);
|
||||
}
|
||||
else
|
||||
{
|
||||
IsTextDiff = false;
|
||||
Content = rs;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -279,6 +355,7 @@ namespace SourceGit.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private readonly int _entireFileLine = 999999999;
|
||||
private readonly string _repo;
|
||||
private readonly Models.DiffOption _option = null;
|
||||
private string _fileModeChange = string.Empty;
|
||||
|
||||
291
src/ViewModels/TextDiffContext.cs
Normal file
291
src/ViewModels/TextDiffContext.cs
Normal file
@@ -0,0 +1,291 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public record TextDiffSelectedChunk(double y, double h, int start, int end, bool combined, bool isOldSide)
|
||||
{
|
||||
public double Y { get; set; } = y;
|
||||
public double Height { get; set; } = h;
|
||||
public int StartIdx { get; set; } = start;
|
||||
public int EndIdx { get; set; } = end;
|
||||
public bool Combined { get; set; } = combined;
|
||||
public bool IsOldSide { get; set; } = isOldSide;
|
||||
|
||||
public static bool IsChanged(TextDiffSelectedChunk oldValue, TextDiffSelectedChunk newValue)
|
||||
{
|
||||
if (newValue == null)
|
||||
return oldValue != null;
|
||||
|
||||
if (oldValue == null)
|
||||
return true;
|
||||
|
||||
return Math.Abs(newValue.Y - oldValue.Y) > 0.001 ||
|
||||
Math.Abs(newValue.Height - oldValue.Height) > 0.001 ||
|
||||
newValue.StartIdx != oldValue.StartIdx ||
|
||||
newValue.EndIdx != oldValue.EndIdx ||
|
||||
newValue.Combined != oldValue.Combined ||
|
||||
newValue.IsOldSide != oldValue.IsOldSide;
|
||||
}
|
||||
}
|
||||
|
||||
public record TextDiffDisplayRange(int start, int end)
|
||||
{
|
||||
public int Start { get; set; } = start;
|
||||
public int End { get; set; } = end;
|
||||
}
|
||||
|
||||
public class TextDiffContext : ObservableObject
|
||||
{
|
||||
public Models.TextDiff Data => _data;
|
||||
public string File => _data.File;
|
||||
public bool IsUnstaged => _data.Option.IsUnstaged;
|
||||
public bool EnableChunkOption => _data.Option.WorkingCopyChange != null;
|
||||
|
||||
public Vector ScrollOffset
|
||||
{
|
||||
get => _scrollOffset;
|
||||
set => SetProperty(ref _scrollOffset, value);
|
||||
}
|
||||
|
||||
public BlockNavigation BlockNavigation
|
||||
{
|
||||
get => _blockNavigation;
|
||||
set => SetProperty(ref _blockNavigation, value);
|
||||
}
|
||||
|
||||
public TextDiffDisplayRange DisplayRange
|
||||
{
|
||||
get => _displayRange;
|
||||
set => SetProperty(ref _displayRange, value);
|
||||
}
|
||||
|
||||
public TextDiffSelectedChunk SelectedChunk
|
||||
{
|
||||
get => _selectedChunk;
|
||||
set => SetProperty(ref _selectedChunk, value);
|
||||
}
|
||||
|
||||
public void ResetBlockNavigation(bool enabled)
|
||||
{
|
||||
if (!enabled)
|
||||
BlockNavigation = null;
|
||||
else if (_blockNavigation == null)
|
||||
BlockNavigation = CreateBlockNavigation();
|
||||
}
|
||||
|
||||
public (int, int) FindRangeByIndex(List<Models.TextDiffLine> lines, int lineIdx)
|
||||
{
|
||||
var startIdx = -1;
|
||||
var endIdx = -1;
|
||||
|
||||
var normalLineCount = 0;
|
||||
var modifiedLineCount = 0;
|
||||
|
||||
for (int i = lineIdx; i >= 0; i--)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
startIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
normalLineCount = lines[lineIdx].Type == Models.TextDiffLineType.Normal ? 1 : 0;
|
||||
for (int i = lineIdx + 1; i < lines.Count; i++)
|
||||
{
|
||||
var line = lines[i];
|
||||
if (line.Type == Models.TextDiffLineType.Indicator)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.Type == Models.TextDiffLineType.Normal)
|
||||
{
|
||||
normalLineCount++;
|
||||
if (normalLineCount >= 2)
|
||||
{
|
||||
endIdx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
normalLineCount = 0;
|
||||
modifiedLineCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (endIdx == -1)
|
||||
endIdx = lines.Count - 1;
|
||||
|
||||
return modifiedLineCount > 0 ? (startIdx, endIdx) : (-1, -1);
|
||||
}
|
||||
|
||||
public virtual bool IsSideBySide()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public virtual TextDiffContext SwitchMode()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual BlockNavigation CreateBlockNavigation()
|
||||
{
|
||||
return new BlockNavigation(_data.Lines);
|
||||
}
|
||||
|
||||
protected Models.TextDiff _data = null;
|
||||
protected Vector _scrollOffset = Vector.Zero;
|
||||
protected BlockNavigation _blockNavigation = null;
|
||||
protected TextDiffDisplayRange _displayRange = null;
|
||||
protected TextDiffSelectedChunk _selectedChunk = null;
|
||||
}
|
||||
|
||||
public class CombinedTextDiff : TextDiffContext
|
||||
{
|
||||
public CombinedTextDiff(Models.TextDiff diff, bool hasBlockNavigation, CombinedTextDiff previous = null)
|
||||
{
|
||||
_data = diff;
|
||||
|
||||
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
|
||||
_scrollOffset = previous.ScrollOffset;
|
||||
|
||||
if (hasBlockNavigation)
|
||||
_blockNavigation = CreateBlockNavigation();
|
||||
}
|
||||
|
||||
public override TextDiffContext SwitchMode()
|
||||
{
|
||||
return new TwoSideTextDiff(_data, _blockNavigation != null);
|
||||
}
|
||||
}
|
||||
|
||||
public class TwoSideTextDiff : TextDiffContext
|
||||
{
|
||||
public List<Models.TextDiffLine> Old { get; } = new List<Models.TextDiffLine>();
|
||||
public List<Models.TextDiffLine> New { get; } = new List<Models.TextDiffLine>();
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff, bool hasBlockNavigation, TwoSideTextDiff previous = null)
|
||||
{
|
||||
_data = diff;
|
||||
|
||||
foreach (var line in diff.Lines)
|
||||
{
|
||||
switch (line.Type)
|
||||
{
|
||||
case Models.TextDiffLineType.Added:
|
||||
New.Add(line);
|
||||
break;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
Old.Add(line);
|
||||
break;
|
||||
default:
|
||||
FillEmptyLines();
|
||||
Old.Add(line);
|
||||
New.Add(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FillEmptyLines();
|
||||
|
||||
if (previous != null && previous.File.Equals(File, StringComparison.Ordinal))
|
||||
_scrollOffset = previous._scrollOffset;
|
||||
|
||||
if (hasBlockNavigation)
|
||||
_blockNavigation = CreateBlockNavigation();
|
||||
}
|
||||
|
||||
public override bool IsSideBySide()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override TextDiffContext SwitchMode()
|
||||
{
|
||||
return new CombinedTextDiff(_data, _blockNavigation != null);
|
||||
}
|
||||
|
||||
public override BlockNavigation CreateBlockNavigation()
|
||||
{
|
||||
return new BlockNavigation(Old);
|
||||
}
|
||||
|
||||
public void ConvertsToCombinedRange(ref int startLine, ref int endLine, bool isOldSide)
|
||||
{
|
||||
endLine = Math.Min(endLine, _data.Lines.Count - 1);
|
||||
|
||||
var oneSide = isOldSide ? Old : New;
|
||||
var firstContentLine = -1;
|
||||
for (int i = startLine; i <= endLine; i++)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
firstContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstContentLine < 0)
|
||||
return;
|
||||
|
||||
var endContentLine = -1;
|
||||
for (int i = Math.Min(endLine, oneSide.Count - 1); i >= startLine; i--)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
endContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endContentLine < 0)
|
||||
return;
|
||||
|
||||
var firstContent = oneSide[firstContentLine];
|
||||
var endContent = oneSide[endContentLine];
|
||||
startLine = _data.Lines.IndexOf(firstContent);
|
||||
endLine = _data.Lines.IndexOf(endContent);
|
||||
}
|
||||
|
||||
private void FillEmptyLines()
|
||||
{
|
||||
if (Old.Count < New.Count)
|
||||
{
|
||||
int diff = New.Count - Old.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
Old.Add(new Models.TextDiffLine());
|
||||
}
|
||||
else if (Old.Count > New.Count)
|
||||
{
|
||||
int diff = Old.Count - New.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
New.Add(new Models.TextDiffLine());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using Avalonia;
|
||||
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
{
|
||||
public class TwoSideTextDiff : ObservableObject
|
||||
{
|
||||
public string File { get; set; }
|
||||
public List<Models.TextDiffLine> Old { get; set; } = new List<Models.TextDiffLine>();
|
||||
public List<Models.TextDiffLine> New { get; set; } = new List<Models.TextDiffLine>();
|
||||
public int MaxLineNumber = 0;
|
||||
|
||||
public Vector SyncScrollOffset
|
||||
{
|
||||
get => _syncScrollOffset;
|
||||
set => SetProperty(ref _syncScrollOffset, value);
|
||||
}
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
|
||||
{
|
||||
File = diff.File;
|
||||
MaxLineNumber = diff.MaxLineNumber;
|
||||
|
||||
foreach (var line in diff.Lines)
|
||||
{
|
||||
switch (line.Type)
|
||||
{
|
||||
case Models.TextDiffLineType.Added:
|
||||
New.Add(line);
|
||||
break;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
Old.Add(line);
|
||||
break;
|
||||
default:
|
||||
FillEmptyLines();
|
||||
Old.Add(line);
|
||||
New.Add(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FillEmptyLines();
|
||||
|
||||
if (previous != null && previous.File == File)
|
||||
_syncScrollOffset = previous._syncScrollOffset;
|
||||
}
|
||||
|
||||
public void ConvertsToCombinedRange(Models.TextDiff combined, ref int startLine, ref int endLine, bool isOldSide)
|
||||
{
|
||||
endLine = Math.Min(endLine, combined.Lines.Count - 1);
|
||||
|
||||
var oneSide = isOldSide ? Old : New;
|
||||
var firstContentLine = -1;
|
||||
for (int i = startLine; i <= endLine; i++)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
firstContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstContentLine < 0)
|
||||
return;
|
||||
|
||||
var endContentLine = -1;
|
||||
for (int i = Math.Min(endLine, oneSide.Count - 1); i >= startLine; i--)
|
||||
{
|
||||
var line = oneSide[i];
|
||||
if (line.Type != Models.TextDiffLineType.None)
|
||||
{
|
||||
endContentLine = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endContentLine < 0)
|
||||
return;
|
||||
|
||||
var firstContent = oneSide[firstContentLine];
|
||||
var endContent = oneSide[endContentLine];
|
||||
startLine = combined.Lines.IndexOf(firstContent);
|
||||
endLine = combined.Lines.IndexOf(endContent);
|
||||
}
|
||||
|
||||
private void FillEmptyLines()
|
||||
{
|
||||
if (Old.Count < New.Count)
|
||||
{
|
||||
int diff = New.Count - Old.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
Old.Add(new Models.TextDiffLine());
|
||||
}
|
||||
else if (Old.Count > New.Count)
|
||||
{
|
||||
int diff = Old.Count - New.Count;
|
||||
for (int i = 0; i < diff; i++)
|
||||
New.Add(new Models.TextDiffLine());
|
||||
}
|
||||
}
|
||||
|
||||
private Vector _syncScrollOffset = Vector.Zero;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user