mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-22 20:37:19 -08:00
feature<CommitViewer>: show line numbers in file preview and remove limitation for line counts
This commit is contained in:
parent
0517142330
commit
06d98a374d
5 changed files with 136 additions and 30 deletions
|
@ -30,6 +30,14 @@ namespace SourceGit.Git {
|
|||
public string SHA { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Line of text in file.
|
||||
/// </summary>
|
||||
public class Line {
|
||||
public int No { get; set; }
|
||||
public string Content { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SHA
|
||||
/// </summary>
|
||||
|
@ -224,10 +232,10 @@ namespace SourceGit.Git {
|
|||
/// <param name="repo"></param>
|
||||
/// <param name="file"></param>
|
||||
/// <returns></returns>
|
||||
public string GetTextFileContent(Repository repo, string file, out bool isBinary) {
|
||||
var data = new List<string>();
|
||||
var count = 0;
|
||||
public List<Line> GetTextFileContent(Repository repo, string file, out bool isBinary) {
|
||||
var data = new List<Line>();
|
||||
var binary = false;
|
||||
var count = 0;
|
||||
|
||||
repo.RunCommand($"diff 4b825dc642cb6eb9a060e54bf8d69288fbee4904 {SHA} --numstat -- \"{file}\"", line => {
|
||||
if (REG_TESTBINARY.IsMatch(line)) binary = true;
|
||||
|
@ -237,29 +245,21 @@ namespace SourceGit.Git {
|
|||
var errs = repo.RunCommand($"show {SHA}:\"{file}\"", line => {
|
||||
if (binary) return;
|
||||
|
||||
count++;
|
||||
if (data.Count >= 1000) return;
|
||||
|
||||
if (line.IndexOf('\0') >= 0) {
|
||||
binary = true;
|
||||
data.Clear();
|
||||
data.Add("BINARY FILE PREVIEW NOT SUPPORTED!");
|
||||
return;
|
||||
}
|
||||
|
||||
data.Add(line);
|
||||
count++;
|
||||
data.Add(new Line() { No = count, Content = line });
|
||||
});
|
||||
|
||||
if (errs != null) App.RaiseError(errs);
|
||||
}
|
||||
|
||||
if (!binary && count > 1000) {
|
||||
data.Add("...");
|
||||
data.Add($"Total {count} lines. Hide {count-1000} lines.");
|
||||
}
|
||||
|
||||
isBinary = binary;
|
||||
return string.Join("\n", data);
|
||||
isBinary = binary;
|
||||
return data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -11,6 +11,26 @@
|
|||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
Unloaded="Cleanup">
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="Style.DataGridRow.NoBringIntoView" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource Style.DataGridRow}">
|
||||
<EventSetter Event="RequestBringIntoView" Handler="OnPreviewRequestBringIntoView"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="Style.DataGridText.LineNumber" TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Right"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="8,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
|
||||
<Style x:Key="Style.DataGridText.Content" TargetType="{x:Type TextBlock}">
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
<Setter Property="VerticalAlignment" Value="Center"/>
|
||||
<Setter Property="Padding" Value="4,0,0,0"/>
|
||||
<Setter Property="FontSize" Value="12"/>
|
||||
</Style>
|
||||
</UserControl.Resources>
|
||||
|
||||
<TabControl>
|
||||
<TabItem Header="INFORMATION">
|
||||
<Grid>
|
||||
|
@ -427,16 +447,7 @@
|
|||
|
||||
<Border Grid.Column="2" BorderThickness="1" Margin="2,0" BorderBrush="{StaticResource Brush.Border2}">
|
||||
<Grid>
|
||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock
|
||||
FontSize="10pt"
|
||||
FontFamily="Consolas"
|
||||
Padding="8"
|
||||
Opacity="0.8"
|
||||
Background="{StaticResource Brush.BG2}"
|
||||
Foreground="{StaticResource Brush.FG}"
|
||||
x:Name="filePreview"/>
|
||||
</ScrollViewer>
|
||||
<Grid x:Name="previewEditor" SizeChanged="OnPreviewSizeChanged" TextElement.FontFamily="Consolas" TextElement.Foreground="{StaticResource Brush.FG}"/>
|
||||
|
||||
<StackPanel x:Name="maskRevision" Orientation="Vertical" VerticalAlignment="Center" HorizontalAlignment="Center" Visibility="Collapsed">
|
||||
<Path x:Name="iconPreviewRevision" Width="64" Height="64" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Submodule}" Fill="{StaticResource Brush.FG2}"/>
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
|
@ -423,12 +425,105 @@ namespace SourceGit.UI {
|
|||
|
||||
Dispatcher.Invoke(() => {
|
||||
fileTree.ItemsSource = fileTreeSource;
|
||||
filePreview.Text = "";
|
||||
previewEditor.Children.Clear();
|
||||
});
|
||||
}
|
||||
|
||||
private void LayoutPreview(List<Git.Commit.Line> data) {
|
||||
var maxLineNumber = $"{data.Count + 1}";
|
||||
var formatted = new FormattedText(
|
||||
maxLineNumber,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
new Typeface(new FontFamily("Consolas"), FontStyles.Normal, FontWeights.Normal, FontStretches.Normal),
|
||||
12.0,
|
||||
Brushes.Black,
|
||||
VisualTreeHelper.GetDpi(this).PixelsPerDip);
|
||||
|
||||
var grid = new DataGrid();
|
||||
grid.SetValue(Grid.RowProperty, 1);
|
||||
grid.RowHeight = 16.0;
|
||||
grid.FrozenColumnCount = 1;
|
||||
grid.ContextMenuOpening += OnPreviewContextMenuOpening;
|
||||
grid.RowStyle = FindResource("Style.DataGridRow.NoBringIntoView") as Style;
|
||||
|
||||
var colLineNumber = new DataGridTextColumn();
|
||||
colLineNumber.IsReadOnly = true;
|
||||
colLineNumber.Binding = new Binding("No");
|
||||
colLineNumber.ElementStyle = FindResource("Style.DataGridText.LineNumber") as Style;
|
||||
colLineNumber.Width = new DataGridLength(formatted.Width + 16, DataGridLengthUnitType.Pixel);
|
||||
grid.Columns.Add(colLineNumber);
|
||||
|
||||
var offset = formatted.Width + 16;
|
||||
if (data.Count * 16 > previewEditor.ActualHeight) offset += 8;
|
||||
|
||||
var colContent = new DataGridTextColumn();
|
||||
colContent.IsReadOnly = true;
|
||||
colContent.Binding = new Binding("Content");
|
||||
colContent.ElementStyle = FindResource("Style.DataGridText.Content") as Style;
|
||||
colContent.MinWidth = previewEditor.ActualWidth - offset;
|
||||
colContent.Width = DataGridLength.SizeToCells;
|
||||
grid.Columns.Add(colContent);
|
||||
|
||||
var splitter = new System.Windows.Shapes.Rectangle();
|
||||
splitter.Width = 1;
|
||||
splitter.Fill = FindResource("Brush.Border2") as Brush;
|
||||
splitter.HorizontalAlignment = HorizontalAlignment.Left;
|
||||
splitter.Margin = new Thickness(formatted.Width + 15, 0, 0, 0);
|
||||
|
||||
grid.ItemsSource = data;
|
||||
previewEditor.Children.Add(grid);
|
||||
previewEditor.Children.Add(splitter);
|
||||
}
|
||||
|
||||
private void OnPreviewContextMenuOpening(object sender, ContextMenuEventArgs e) {
|
||||
var grid = sender as DataGrid;
|
||||
if (grid == null) return;
|
||||
|
||||
var menu = new ContextMenu();
|
||||
var copy = new MenuItem();
|
||||
copy.Header = "Copy";
|
||||
copy.Click += (o, ev) => {
|
||||
var items = grid.SelectedItems;
|
||||
if (items.Count == 0) return;
|
||||
|
||||
var builder = new StringBuilder();
|
||||
foreach (var item in items) {
|
||||
var line = item as Git.Commit.Line;
|
||||
if (line == null) continue;
|
||||
|
||||
builder.Append(line.Content);
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
Clipboard.SetText(builder.ToString());
|
||||
};
|
||||
menu.Items.Add(copy);
|
||||
menu.IsOpen = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPreviewRequestBringIntoView(object sender, RequestBringIntoViewEventArgs e) {
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPreviewSizeChanged(object sender, SizeChangedEventArgs e) {
|
||||
if (previewEditor.Children.Count == 0) return;
|
||||
|
||||
var totalWidth = previewEditor.ActualWidth;
|
||||
var totalHeight = previewEditor.ActualHeight;
|
||||
var editor = previewEditor.Children[0] as DataGrid;
|
||||
var minWidth = totalWidth - editor.NonFrozenColumnsViewportHorizontalOffset;
|
||||
var desireHeight = editor.Items.Count * editor.RowHeight;
|
||||
if (desireHeight > totalHeight) minWidth -= 8;
|
||||
|
||||
editor.Columns[1].MinWidth = minWidth;
|
||||
editor.Columns[1].Width = DataGridLength.SizeToCells;
|
||||
editor.UpdateLayout();
|
||||
}
|
||||
|
||||
private async void FileTreeItemSelected(object sender, RoutedPropertyChangedEventArgs<object> e) {
|
||||
filePreview.Text = "";
|
||||
previewEditor.Children.Clear();
|
||||
maskPreviewNotSupported.Visibility = Visibility.Collapsed;
|
||||
maskRevision.Visibility = Visibility.Collapsed;
|
||||
|
||||
|
@ -450,7 +545,7 @@ namespace SourceGit.UI {
|
|||
if (isBinary) {
|
||||
Dispatcher.Invoke(() => maskPreviewNotSupported.Visibility = Visibility.Visible);
|
||||
} else {
|
||||
Dispatcher.Invoke(() => filePreview.Text = data);
|
||||
Dispatcher.Invoke(() => LayoutPreview(data));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
mc:Ignorable="d"
|
||||
FontFamily="Consolas">
|
||||
<UserControl.Resources>
|
||||
<Style x:Key="Style.DataGridRow.TextChange" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource Style.DataGridRow}">
|
||||
<Style x:Key="Style.DataGridRow.NoBringIntoView" TargetType="{x:Type DataGridRow}" BasedOn="{StaticResource Style.DataGridRow}">
|
||||
<EventSetter Event="RequestBringIntoView" Handler="OnLineRequestBringIntoView"/>
|
||||
</Style>
|
||||
|
||||
|
|
|
@ -421,7 +421,7 @@ namespace SourceGit.UI {
|
|||
grid.RowHeight = 16.0;
|
||||
grid.FrozenColumnCount = lineNumbers.Length;
|
||||
grid.ContextMenuOpening += OnTextChangeContextMenuOpening;
|
||||
grid.RowStyle = FindResource("Style.DataGridRow.TextChange") as Style;
|
||||
grid.RowStyle = FindResource("Style.DataGridRow.NoBringIntoView") as Style;
|
||||
|
||||
foreach (var number in lineNumbers) {
|
||||
var colLineNumber = new DataGridTextColumn();
|
||||
|
|
Loading…
Reference in a new issue