mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-24 20:57:19 -08:00
optimize<DiffViewer>: use Models.TextChanges.Line directly for DiffViewer and HighlightableTextBlock
This commit is contained in:
parent
da1abaee16
commit
47cb708744
3 changed files with 82 additions and 100 deletions
|
@ -21,11 +21,29 @@ namespace SourceGit.Models {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Line {
|
public class Line {
|
||||||
public LineMode Mode = LineMode.Normal;
|
public LineMode Mode { get; set; } = LineMode.None;
|
||||||
public string Content = "";
|
public string Content { get; set; } = "";
|
||||||
public string OldLine = "";
|
public string OldLine { get; set; } = "";
|
||||||
public string NewLine = "";
|
public string NewLine { get; set; } = "";
|
||||||
public List<HighlightRange> Highlights = new List<HighlightRange>();
|
public List<HighlightRange> Highlights { get; set; } = new List<HighlightRange>();
|
||||||
|
|
||||||
|
public bool IsContent {
|
||||||
|
get {
|
||||||
|
return Mode == LineMode.Added
|
||||||
|
|| Mode == LineMode.Deleted
|
||||||
|
|| Mode == LineMode.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsDifference {
|
||||||
|
get {
|
||||||
|
return Mode == LineMode.Added
|
||||||
|
|| Mode == LineMode.Deleted
|
||||||
|
|| Mode == LineMode.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line() {}
|
||||||
|
|
||||||
public Line(LineMode mode, string content, string oldLine, string newLine) {
|
public Line(LineMode mode, string content, string oldLine, string newLine) {
|
||||||
Mode = mode;
|
Mode = mode;
|
||||||
|
|
|
@ -15,41 +15,15 @@ namespace SourceGit.Views.Controls {
|
||||||
private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(128, 0, 255, 0));
|
private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(128, 0, 255, 0));
|
||||||
private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
|
private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(128, 255, 0, 0));
|
||||||
|
|
||||||
public class Data {
|
public static readonly DependencyProperty DataProperty = DependencyProperty.Register(
|
||||||
public Models.TextChanges.LineMode Mode { get; set; } = Models.TextChanges.LineMode.None;
|
"Data",
|
||||||
public string Text { get; set; } = "";
|
typeof(Models.TextChanges.Line),
|
||||||
public List<Models.TextChanges.HighlightRange> Highlights { get; set; } = new List<Models.TextChanges.HighlightRange>();
|
|
||||||
|
|
||||||
public bool IsContent {
|
|
||||||
get {
|
|
||||||
return Mode == Models.TextChanges.LineMode.Added
|
|
||||||
|| Mode == Models.TextChanges.LineMode.Deleted
|
|
||||||
|| Mode == Models.TextChanges.LineMode.Normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsDifference {
|
|
||||||
get {
|
|
||||||
return Mode == Models.TextChanges.LineMode.Added
|
|
||||||
|| Mode == Models.TextChanges.LineMode.Deleted
|
|
||||||
|| Mode == Models.TextChanges.LineMode.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string FG {
|
|
||||||
get { return Mode == Models.TextChanges.LineMode.Indicator ? "Brush.FG2" : "Brush.FG1"; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
|
|
||||||
"Content",
|
|
||||||
typeof(Data),
|
|
||||||
typeof(HighlightableTextBlock),
|
typeof(HighlightableTextBlock),
|
||||||
new PropertyMetadata(null, OnContentChanged));
|
new PropertyMetadata(null, OnContentChanged));
|
||||||
|
|
||||||
public Data Content {
|
public Models.TextChanges.Line Data {
|
||||||
get { return (Data)GetValue(ContentProperty); }
|
get { return (Models.TextChanges.Line)GetValue(DataProperty); }
|
||||||
set { SetValue(ContentProperty, value); }
|
set { SetValue(DataProperty, value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
||||||
|
@ -61,10 +35,10 @@ namespace SourceGit.Views.Controls {
|
||||||
txt.Background = Brushes.Transparent;
|
txt.Background = Brushes.Transparent;
|
||||||
txt.FontStyle = FontStyles.Normal;
|
txt.FontStyle = FontStyles.Normal;
|
||||||
|
|
||||||
if (txt.Content == null) return;
|
if (txt.Data == null) return;
|
||||||
|
|
||||||
Brush highlightBrush = Brushes.Transparent;
|
Brush highlightBrush = Brushes.Transparent;
|
||||||
switch (txt.Content.Mode) {
|
switch (txt.Data.Mode) {
|
||||||
case Models.TextChanges.LineMode.None:
|
case Models.TextChanges.LineMode.None:
|
||||||
txt.Background = BG_EMPTY;
|
txt.Background = BG_EMPTY;
|
||||||
break;
|
break;
|
||||||
|
@ -83,30 +57,30 @@ namespace SourceGit.Views.Controls {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
txt.SetResourceReference(ForegroundProperty, txt.Content.FG);
|
txt.SetResourceReference(ForegroundProperty, txt.Data.Mode == Models.TextChanges.LineMode.Indicator ? "Brush.FG2" : "Brush.FG1");
|
||||||
|
|
||||||
if (txt.Content.Highlights == null || txt.Content.Highlights.Count == 0) {
|
if (txt.Data.Highlights == null || txt.Data.Highlights.Count == 0) {
|
||||||
txt.Text = txt.Content.Text;
|
txt.Text = txt.Data.Content;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var started = 0;
|
var started = 0;
|
||||||
foreach (var highlight in txt.Content.Highlights) {
|
foreach (var highlight in txt.Data.Highlights) {
|
||||||
if (started < highlight.Start) {
|
if (started < highlight.Start) {
|
||||||
txt.Inlines.Add(new Run(txt.Content.Text.Substring(started, highlight.Start - started)));
|
txt.Inlines.Add(new Run(txt.Data.Content.Substring(started, highlight.Start - started)));
|
||||||
}
|
}
|
||||||
|
|
||||||
txt.Inlines.Add(new TextBlock() {
|
txt.Inlines.Add(new TextBlock() {
|
||||||
Background = highlightBrush,
|
Background = highlightBrush,
|
||||||
LineHeight = txt.LineHeight,
|
LineHeight = txt.LineHeight,
|
||||||
Text = txt.Content.Text.Substring(highlight.Start, highlight.Count),
|
Text = txt.Data.Content.Substring(highlight.Start, highlight.Count),
|
||||||
});
|
});
|
||||||
|
|
||||||
started = highlight.Start + highlight.Count;
|
started = highlight.Start + highlight.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (started < txt.Content.Text.Length) {
|
if (started < txt.Data.Content.Length) {
|
||||||
txt.Inlines.Add(new Run(txt.Content.Text.Substring(started)));
|
txt.Inlines.Add(new Run(txt.Data.Content.Substring(started)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,12 +24,6 @@ namespace SourceGit.Views.Widgets {
|
||||||
public bool UseLFS = false;
|
public bool UseLFS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Block {
|
|
||||||
public string OldLine { get; set; } = "";
|
|
||||||
public string NewLine { get; set; } = "";
|
|
||||||
public Controls.HighlightableTextBlock.Data Data { get; set; } = new Controls.HighlightableTextBlock.Data();
|
|
||||||
}
|
|
||||||
|
|
||||||
private ulong seq = 0;
|
private ulong seq = 0;
|
||||||
private string repo = null;
|
private string repo = null;
|
||||||
private Option opt = null;
|
private Option opt = null;
|
||||||
|
@ -185,20 +179,22 @@ namespace SourceGit.Views.Widgets {
|
||||||
private void MakeCombinedViewer(ulong dummy) {
|
private void MakeCombinedViewer(ulong dummy) {
|
||||||
var lastOldLine = "";
|
var lastOldLine = "";
|
||||||
var lastNewLine = "";
|
var lastNewLine = "";
|
||||||
var blocks = new List<Block>();
|
var foundOld = false;
|
||||||
|
var foundNew = false;
|
||||||
|
|
||||||
foreach (var line in cachedTextChanges) {
|
for (int i = cachedTextChanges.Count - 1; i >= 0; i--) {
|
||||||
var block = new Block();
|
var line = cachedTextChanges[i];
|
||||||
block.OldLine = line.OldLine;
|
if (!foundOld && line.OldLine.Length > 0) {
|
||||||
block.NewLine = line.NewLine;
|
lastOldLine = line.OldLine;
|
||||||
block.Data.Mode = line.Mode;
|
if (foundNew) break;
|
||||||
block.Data.Text = line.Content;
|
foundOld = true;
|
||||||
block.Data.Highlights.AddRange(line.Highlights);
|
}
|
||||||
|
|
||||||
if (line.OldLine.Length > 0) lastOldLine = line.OldLine;
|
if (!foundNew && line.NewLine.Length > 0) {
|
||||||
if (line.NewLine.Length > 0) lastNewLine = line.NewLine;
|
lastNewLine = line.NewLine;
|
||||||
|
if (foundOld) break;
|
||||||
blocks.Add(block);
|
foundNew = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dispatcher.Invoke(() => {
|
Dispatcher.Invoke(() => {
|
||||||
|
@ -234,38 +230,32 @@ namespace SourceGit.Views.Widgets {
|
||||||
editor.Columns[0].Width = new DataGridLength(lineNumberWidth, DataGridLengthUnitType.Pixel);
|
editor.Columns[0].Width = new DataGridLength(lineNumberWidth, DataGridLengthUnitType.Pixel);
|
||||||
editor.Columns[1].Width = new DataGridLength(lineNumberWidth, DataGridLengthUnitType.Pixel);
|
editor.Columns[1].Width = new DataGridLength(lineNumberWidth, DataGridLengthUnitType.Pixel);
|
||||||
editor.Columns[2].MinWidth = minWidth;
|
editor.Columns[2].MinWidth = minWidth;
|
||||||
editor.SetBinding(DataGrid.ItemsSourceProperty, new Binding() { Source = blocks, IsAsync = true });
|
editor.SetBinding(DataGrid.ItemsSourceProperty, new Binding() { Source = cachedTextChanges, IsAsync = true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MakeSideBySideViewer(ulong dummy) {
|
private void MakeSideBySideViewer(ulong dummy) {
|
||||||
var lastOldLine = "";
|
var lastOldLine = "";
|
||||||
var lastNewLine = "";
|
var lastNewLine = "";
|
||||||
var oldSideBlocks = new List<Block>();
|
var oldSideBlocks = new List<Models.TextChanges.Line>();
|
||||||
var newSideBlocks = new List<Block>();
|
var newSideBlocks = new List<Models.TextChanges.Line>();
|
||||||
|
|
||||||
foreach (var line in cachedTextChanges) {
|
foreach (var line in cachedTextChanges) {
|
||||||
var block = new Block();
|
|
||||||
block.OldLine = line.OldLine;
|
|
||||||
block.NewLine = line.NewLine;
|
|
||||||
block.Data.Mode = line.Mode;
|
|
||||||
block.Data.Text = line.Content;
|
|
||||||
block.Data.Highlights.AddRange(line.Highlights);
|
|
||||||
|
|
||||||
if (line.OldLine.Length > 0) lastOldLine = line.OldLine;
|
|
||||||
if (line.NewLine.Length > 0) lastNewLine = line.NewLine;
|
|
||||||
|
|
||||||
switch (line.Mode) {
|
switch (line.Mode) {
|
||||||
case Models.TextChanges.LineMode.Added:
|
case Models.TextChanges.LineMode.Added:
|
||||||
newSideBlocks.Add(block);
|
newSideBlocks.Add(line);
|
||||||
|
lastNewLine = line.NewLine;
|
||||||
break;
|
break;
|
||||||
case Models.TextChanges.LineMode.Deleted:
|
case Models.TextChanges.LineMode.Deleted:
|
||||||
oldSideBlocks.Add(block);
|
oldSideBlocks.Add(line);
|
||||||
|
lastOldLine = line.OldLine;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
FillEmptyLines(oldSideBlocks, newSideBlocks);
|
FillEmptyLines(oldSideBlocks, newSideBlocks);
|
||||||
oldSideBlocks.Add(block);
|
oldSideBlocks.Add(line);
|
||||||
newSideBlocks.Add(block);
|
newSideBlocks.Add(line);
|
||||||
|
lastNewLine = line.NewLine;
|
||||||
|
lastOldLine = line.OldLine;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,13 +314,13 @@ namespace SourceGit.Views.Widgets {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FillEmptyLines(List<Block> old, List<Block> cur) {
|
private void FillEmptyLines(List<Models.TextChanges.Line> old, List<Models.TextChanges.Line> cur) {
|
||||||
if (old.Count < cur.Count) {
|
if (old.Count < cur.Count) {
|
||||||
int diff = cur.Count - old.Count;
|
int diff = cur.Count - old.Count;
|
||||||
for (int i = 0; i < diff; i++) old.Add(new Block());
|
for (int i = 0; i < diff; i++) old.Add(new Models.TextChanges.Line());
|
||||||
} else if (old.Count > cur.Count) {
|
} else if (old.Count > cur.Count) {
|
||||||
int diff = old.Count - cur.Count;
|
int diff = old.Count - cur.Count;
|
||||||
for (int i = 0; i < diff; i++) cur.Add(new Block());
|
for (int i = 0; i < diff; i++) cur.Add(new Models.TextChanges.Line());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,11 +351,11 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
foreach (var item in items) {
|
foreach (var item in items) {
|
||||||
var block = item as Block;
|
var block = item as Models.TextChanges.Line;
|
||||||
if (block == null) continue;
|
if (block == null) continue;
|
||||||
if (!block.Data.IsContent) continue;
|
if (!block.IsContent) continue;
|
||||||
|
|
||||||
builder.Append(block.Data.Text);
|
builder.Append(block.Content);
|
||||||
builder.AppendLine();
|
builder.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +371,7 @@ namespace SourceGit.Views.Widgets {
|
||||||
}
|
}
|
||||||
|
|
||||||
var line = new FrameworkElementFactory(typeof(Controls.HighlightableTextBlock));
|
var line = new FrameworkElementFactory(typeof(Controls.HighlightableTextBlock));
|
||||||
line.SetBinding(Controls.HighlightableTextBlock.ContentProperty, new Binding("Data"));
|
line.SetBinding(Controls.HighlightableTextBlock.DataProperty, new Binding("."));
|
||||||
line.SetValue(TextBlock.FontFamilyProperty, new FontFamily("Consolas,Microsoft YaHei UI"));
|
line.SetValue(TextBlock.FontFamilyProperty, new FontFamily("Consolas,Microsoft YaHei UI"));
|
||||||
line.SetValue(TextBlock.FontSizeProperty, 13.0);
|
line.SetValue(TextBlock.FontSizeProperty, 13.0);
|
||||||
line.SetValue(TextBlock.MarginProperty, new Thickness(0));
|
line.SetValue(TextBlock.MarginProperty, new Thickness(0));
|
||||||
|
@ -486,11 +476,11 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
var builder = new StringBuilder();
|
var builder = new StringBuilder();
|
||||||
foreach (var item in items) {
|
foreach (var item in items) {
|
||||||
var block = item as Block;
|
var block = item as Models.TextChanges.Line;
|
||||||
if (block == null) continue;
|
if (block == null) continue;
|
||||||
if (!block.Data.IsContent) continue;
|
if (!block.IsContent) continue;
|
||||||
|
|
||||||
builder.Append(block.Data.Text);
|
builder.Append(block.Content);
|
||||||
builder.AppendLine();
|
builder.AppendLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,11 +547,11 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
var firstVisible = (int)scroller.VerticalOffset;
|
var firstVisible = (int)scroller.VerticalOffset;
|
||||||
var firstModeEnded = false;
|
var firstModeEnded = false;
|
||||||
var first = grid.Items[firstVisible] as Block;
|
var first = grid.Items[firstVisible] as Models.TextChanges.Line;
|
||||||
for (int i = firstVisible - 1; i >= 0; i--) {
|
for (int i = firstVisible - 1; i >= 0; i--) {
|
||||||
var next = grid.Items[i] as Block;
|
var next = grid.Items[i] as Models.TextChanges.Line;
|
||||||
if (next.Data.IsDifference) {
|
if (next.IsDifference) {
|
||||||
if (firstModeEnded || next.Data.Mode != first.Data.Mode) {
|
if (firstModeEnded || next.Mode != first.Mode) {
|
||||||
scroller.ScrollToVerticalOffset(i);
|
scroller.ScrollToVerticalOffset(i);
|
||||||
grid.SelectedIndex = i;
|
grid.SelectedIndex = i;
|
||||||
break;
|
break;
|
||||||
|
@ -581,11 +571,11 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
var firstVisible = (int)scroller.VerticalOffset;
|
var firstVisible = (int)scroller.VerticalOffset;
|
||||||
var firstModeEnded = false;
|
var firstModeEnded = false;
|
||||||
var first = grid.Items[firstVisible] as Block;
|
var first = grid.Items[firstVisible] as Models.TextChanges.Line;
|
||||||
for (int i = firstVisible + 1; i < grid.Items.Count; i++) {
|
for (int i = firstVisible + 1; i < grid.Items.Count; i++) {
|
||||||
var next = grid.Items[i] as Block;
|
var next = grid.Items[i] as Models.TextChanges.Line;
|
||||||
if (next.Data.IsDifference) {
|
if (next.IsDifference) {
|
||||||
if (firstModeEnded || next.Data.Mode != first.Data.Mode) {
|
if (firstModeEnded || next.Mode != first.Mode) {
|
||||||
scroller.ScrollToVerticalOffset(i);
|
scroller.ScrollToVerticalOffset(i);
|
||||||
grid.SelectedIndex = i;
|
grid.SelectedIndex = i;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue