mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-23 20:47:25 -08:00
refactor: rewrite TextDiffView
This commit is contained in:
parent
eab680ae55
commit
68061f82b1
6 changed files with 318 additions and 497 deletions
|
@ -25,11 +25,11 @@
|
|||
<Color x:Key="Color.FG1">#FF1F1F1F</Color>
|
||||
<Color x:Key="Color.FG2">#FF6F6F6F</Color>
|
||||
<Color x:Key="Color.FG3">#FFFFFFFF</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.EMPTY">#3C000000</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.ADD">#3C00FF00</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.DELETED">#3CFF0000</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG2.ADD">#5A00FF00</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG2.DELETED">#50FF0000</Color>
|
||||
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
|
||||
<Color x:Key="Color.Diff.AddedBG">#3C00FF00</Color>
|
||||
<Color x:Key="Color.Diff.DeletedBG">#3CFF0000</Color>
|
||||
<Color x:Key="Color.Diff.AddedHighlight">#5A00FF00</Color>
|
||||
<Color x:Key="Color.Diff.DeletedHighlight">#50FF0000</Color>
|
||||
</ResourceDictionary>
|
||||
|
||||
<ResourceDictionary x:Key="Dark">
|
||||
|
@ -56,11 +56,11 @@
|
|||
<Color x:Key="Color.FG1">#FFDDDDDD</Color>
|
||||
<Color x:Key="Color.FG2">#40F1F1F1</Color>
|
||||
<Color x:Key="Color.FG3">#FF252525</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.EMPTY">#3C000000</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.ADD">#3C00FF00</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG1.DELETED">#3CFF0000</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG2.ADD">#5A00FF00</Color>
|
||||
<Color x:Key="Color.TextDiffView.LineBG2.DELETED">#50FF0000</Color>
|
||||
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
|
||||
<Color x:Key="Color.Diff.AddedBG">#3C00FF00</Color>
|
||||
<Color x:Key="Color.Diff.DeletedBG">#3CFF0000</Color>
|
||||
<Color x:Key="Color.Diff.AddedHighlight">#5A00FF00</Color>
|
||||
<Color x:Key="Color.Diff.DeletedHighlight">#50FF0000</Color>
|
||||
</ResourceDictionary>
|
||||
</ResourceDictionary.ThemeDictionaries>
|
||||
|
||||
|
@ -89,9 +89,9 @@
|
|||
<SolidColorBrush x:Key="Brush.FG3" Color="{DynamicResource Color.FG3}"/>
|
||||
<SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/>
|
||||
<SolidColorBrush x:Key="Brush.AccentHovered" Color="{DynamicResource SystemListLowColor}"/>
|
||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.EMPTY" Color="{DynamicResource Color.TextDiffView.LineBG1.EMPTY}"/>
|
||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.ADD" Color="{DynamicResource Color.TextDiffView.LineBG1.ADD}"/>
|
||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.DELETED" Color="{DynamicResource Color.TextDiffView.LineBG1.DELETED}"/>
|
||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG2.ADD" Color="{DynamicResource Color.TextDiffView.LineBG2.ADD}"/>
|
||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG2.DELETED" Color="{DynamicResource Color.TextDiffView.LineBG2.DELETED}"/>
|
||||
<SolidColorBrush x:Key="Brush.Diff.EmptyBG" Color="{DynamicResource Color.Diff.EmptyBG}"/>
|
||||
<SolidColorBrush x:Key="Brush.Diff.AddedBG" Color="{DynamicResource Color.Diff.AddedBG}"/>
|
||||
<SolidColorBrush x:Key="Brush.Diff.DeletedBG" Color="{DynamicResource Color.Diff.DeletedBG}"/>
|
||||
<SolidColorBrush x:Key="Brush.Diff.AddedHighlight" Color="{DynamicResource Color.Diff.AddedHighlight}"/>
|
||||
<SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/>
|
||||
</ResourceDictionary>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Avalonia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
namespace SourceGit.ViewModels
|
||||
|
@ -11,7 +11,13 @@ namespace SourceGit.ViewModels
|
|||
public List<Models.TextDiffLine> New { get; set; } = new List<Models.TextDiffLine>();
|
||||
public int MaxLineNumber = 0;
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff)
|
||||
public Vector SyncScrollOffset
|
||||
{
|
||||
get => _syncScrollOffset;
|
||||
set => SetProperty(ref _syncScrollOffset, value);
|
||||
}
|
||||
|
||||
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
|
||||
{
|
||||
File = diff.File;
|
||||
MaxLineNumber = diff.MaxLineNumber;
|
||||
|
@ -35,6 +41,9 @@ namespace SourceGit.ViewModels
|
|||
}
|
||||
|
||||
FillEmptyLines();
|
||||
|
||||
if (previous != null && previous.File == File)
|
||||
_syncScrollOffset = previous._syncScrollOffset;
|
||||
}
|
||||
|
||||
private void FillEmptyLines()
|
||||
|
@ -52,5 +61,7 @@ namespace SourceGit.ViewModels
|
|||
New.Add(new Models.TextDiffLine());
|
||||
}
|
||||
}
|
||||
|
||||
private Vector _syncScrollOffset = Vector.Zero;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,24 +379,16 @@ namespace SourceGit.ViewModels
|
|||
if (isUnstaged)
|
||||
{
|
||||
if (changes.Count == _unstaged.Count && _staged.Count == 0)
|
||||
{
|
||||
PopupHost.ShowPopup(new Discard(_repo));
|
||||
}
|
||||
else
|
||||
{
|
||||
PopupHost.ShowPopup(new Discard(_repo, changes, true));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (changes.Count == _staged.Count && _unstaged.Count == 0)
|
||||
{
|
||||
PopupHost.ShowPopup(new Discard(_repo));
|
||||
}
|
||||
else
|
||||
{
|
||||
PopupHost.ShowPopup(new Discard(_repo, changes, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -921,24 +913,11 @@ namespace SourceGit.ViewModels
|
|||
|
||||
var isUnstaged = _selectedUnstaged != null && _selectedUnstaged.Count > 0;
|
||||
if (change == null)
|
||||
{
|
||||
DetailContext = null;
|
||||
}
|
||||
else if (change.IsConflit && isUnstaged)
|
||||
{
|
||||
DetailContext = new ConflictContext(_repo.FullPath, change);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_detailContext is DiffContext previous)
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), previous);
|
||||
}
|
||||
else
|
||||
{
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged));
|
||||
}
|
||||
}
|
||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
|
||||
}
|
||||
|
||||
private async void UseTheirs(List<Models.Change> changes)
|
||||
|
|
|
@ -234,9 +234,7 @@
|
|||
|
||||
<!-- Text Diff -->
|
||||
<DataTemplate DataType="m:TextDiff">
|
||||
<v:TextDiffView TextDiff="{Binding}"
|
||||
SyncScrollOffset="{Binding SyncScrollOffset, Mode=TwoWay}"
|
||||
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
|
||||
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Empty or only EOL changes -->
|
||||
|
|
|
@ -11,18 +11,16 @@
|
|||
Background="{DynamicResource Brush.Contents}">
|
||||
<UserControl.DataTemplates>
|
||||
<DataTemplate DataType="m:TextDiff">
|
||||
<v:CombinedTextDiffPresenter BorderBrush="{DynamicResource Brush.Border2}"
|
||||
BorderThickness="0"
|
||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
||||
<v:CombinedTextDiffPresenter FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
||||
LineBrush="{DynamicResource Brush.Border2}"
|
||||
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||
DiffData="{Binding}"
|
||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||
</DataTemplate>
|
||||
|
@ -30,40 +28,36 @@
|
|||
<DataTemplate DataType="vm:TwoSideTextDiff">
|
||||
<Grid ColumnDefinitions="*,1,*">
|
||||
<v:SingleSideTextDiffPresenter Grid.Column="0"
|
||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
|
||||
IsOld="True"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
BorderThickness="0"
|
||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
||||
FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
||||
LineBrush="{DynamicResource Brush.Border2}"
|
||||
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||
DiffData="{Binding}"/>
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||
|
||||
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
||||
|
||||
<v:SingleSideTextDiffPresenter Grid.Column="2"
|
||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
|
||||
IsOld="False"
|
||||
BorderBrush="{DynamicResource Brush.Border2}"
|
||||
BorderThickness="0"
|
||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
||||
FileName="{Binding File}"
|
||||
Foreground="{DynamicResource Brush.FG1}"
|
||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
||||
LineBrush="{DynamicResource Brush.Border2}"
|
||||
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||
DiffData="{Binding}"/>
|
||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</UserControl.DataTemplates>
|
||||
|
|
|
@ -7,6 +7,7 @@ using System.Text;
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
@ -21,7 +22,161 @@ using AvaloniaEdit.Utils;
|
|||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class CombinedTextDiffPresenter : TextEditor
|
||||
public class IThemedTextDiffPresenter : TextEditor
|
||||
{
|
||||
public static readonly StyledProperty<string> FileNameProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, string>(nameof(FileName), string.Empty);
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get => GetValue(FileNameProperty);
|
||||
set => SetValue(FileNameProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBrushProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(LineBrush), new SolidColorBrush(Colors.DarkGray));
|
||||
|
||||
public IBrush LineBrush
|
||||
{
|
||||
get => GetValue(LineBrushProperty);
|
||||
set => SetValue(LineBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> EmptyContentBackgroundProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(EmptyContentBackground), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
||||
|
||||
public IBrush EmptyContentBackground
|
||||
{
|
||||
get => GetValue(EmptyContentBackgroundProperty);
|
||||
set => SetValue(EmptyContentBackgroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> AddedContentBackgroundProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(AddedContentBackground), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
||||
|
||||
public IBrush AddedContentBackground
|
||||
{
|
||||
get => GetValue(AddedContentBackgroundProperty);
|
||||
set => SetValue(AddedContentBackgroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> DeletedContentBackgroundProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(DeletedContentBackground), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
||||
|
||||
public IBrush DeletedContentBackground
|
||||
{
|
||||
get => GetValue(DeletedContentBackgroundProperty);
|
||||
set => SetValue(DeletedContentBackgroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> AddedHighlightBrushProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(AddedHighlightBrush), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
||||
|
||||
public IBrush AddedHighlightBrush
|
||||
{
|
||||
get => GetValue(AddedHighlightBrushProperty);
|
||||
set => SetValue(AddedHighlightBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> DeletedHighlightBrushProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(DeletedHighlightBrush), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
||||
|
||||
public IBrush DeletedHighlightBrush
|
||||
{
|
||||
get => GetValue(DeletedHighlightBrushProperty);
|
||||
set => SetValue(DeletedHighlightBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> IndicatorForegroundProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(IndicatorForeground), Brushes.Gray);
|
||||
|
||||
public IBrush IndicatorForeground
|
||||
{
|
||||
get => GetValue(IndicatorForegroundProperty);
|
||||
set => SetValue(IndicatorForegroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
||||
AvaloniaProperty.Register<IThemedTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
||||
|
||||
public bool UseSyntaxHighlighting
|
||||
{
|
||||
get => GetValue(UseSyntaxHighlightingProperty);
|
||||
set => SetValue(UseSyntaxHighlightingProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
|
||||
public IThemedTextDiffPresenter(TextArea area, TextDocument doc): base(area, doc)
|
||||
{
|
||||
IsReadOnly = true;
|
||||
ShowLineNumbers = false;
|
||||
BorderThickness = new Thickness(0);
|
||||
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
UpdateTextMate();
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
|
||||
if (_textMate != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == UseSyntaxHighlightingProperty)
|
||||
UpdateTextMate();
|
||||
else if (change.Property == FileNameProperty)
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
|
||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
||||
}
|
||||
|
||||
protected void UpdateTextMate()
|
||||
{
|
||||
if (UseSyntaxHighlighting)
|
||||
{
|
||||
if (_textMate == null)
|
||||
{
|
||||
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_textMate != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
GC.Collect();
|
||||
|
||||
TextArea.TextView.Redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextMate.Installation _textMate = null;
|
||||
protected IVisualLineTransformer _lineStyleTransformer = null;
|
||||
}
|
||||
|
||||
public class CombinedTextDiffPresenter : IThemedTextDiffPresenter
|
||||
{
|
||||
public class LineNumberMargin : AbstractMargin
|
||||
{
|
||||
|
@ -104,7 +259,7 @@ namespace SourceGit.Views
|
|||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
var pen = new Pen(_editor.BorderBrush, 1);
|
||||
var pen = new Pen(_editor.LineBrush, 1);
|
||||
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
||||
}
|
||||
|
||||
|
@ -155,11 +310,11 @@ namespace SourceGit.Views
|
|||
switch (type)
|
||||
{
|
||||
case Models.TextDiffLineType.None:
|
||||
return _editor.LineBGEmpty;
|
||||
return _editor.EmptyContentBackground;
|
||||
case Models.TextDiffLineType.Added:
|
||||
return _editor.LineBGAdd;
|
||||
return _editor.AddedContentBackground;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
return _editor.LineBGDeleted;
|
||||
return _editor.DeletedContentBackground;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -186,7 +341,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
||||
{
|
||||
v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
|
||||
v.TextRunProperties.SetForegroundBrush(_editor.IndicatorForeground);
|
||||
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
||||
});
|
||||
|
||||
|
@ -195,7 +350,7 @@ namespace SourceGit.Views
|
|||
|
||||
if (info.Highlights.Count > 0)
|
||||
{
|
||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.SecondaryLineBGAdd : _editor.SecondaryLineBGDeleted;
|
||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.AddedHighlightBrush : _editor.DeletedHighlightBrush;
|
||||
foreach (var highlight in info.Highlights)
|
||||
{
|
||||
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
||||
|
@ -209,129 +364,57 @@ namespace SourceGit.Views
|
|||
private readonly CombinedTextDiffPresenter _editor;
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Models.TextDiff> DiffDataProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, Models.TextDiff>(nameof(DiffData));
|
||||
|
||||
public Models.TextDiff DiffData
|
||||
{
|
||||
get => GetValue(DiffDataProperty);
|
||||
set => SetValue(DiffDataProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGEmptyProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGEmpty), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
||||
|
||||
public IBrush LineBGEmpty
|
||||
{
|
||||
get => GetValue(LineBGEmptyProperty);
|
||||
set => SetValue(LineBGEmptyProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGAddProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGAdd), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
||||
|
||||
public IBrush LineBGAdd
|
||||
{
|
||||
get => GetValue(LineBGAddProperty);
|
||||
set => SetValue(LineBGAddProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGDeletedProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGDeleted), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
||||
|
||||
public IBrush LineBGDeleted
|
||||
{
|
||||
get => GetValue(LineBGDeletedProperty);
|
||||
set => SetValue(LineBGDeletedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryLineBGAddProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryLineBGAdd), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
||||
|
||||
public IBrush SecondaryLineBGAdd
|
||||
{
|
||||
get => GetValue(SecondaryLineBGAddProperty);
|
||||
set => SetValue(SecondaryLineBGAddProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryLineBGDeletedProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryLineBGDeleted), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
||||
|
||||
public IBrush SecondaryLineBGDeleted
|
||||
{
|
||||
get => GetValue(SecondaryLineBGDeletedProperty);
|
||||
set => SetValue(SecondaryLineBGDeletedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryFGProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryFG), Brushes.Gray);
|
||||
|
||||
public IBrush SecondaryFG
|
||||
{
|
||||
get => GetValue(SecondaryFGProperty);
|
||||
set => SetValue(SecondaryFGProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, Vector>(nameof(SyncScrollOffset));
|
||||
|
||||
public Vector SyncScrollOffset
|
||||
{
|
||||
get => GetValue(SyncScrollOffsetProperty);
|
||||
set => SetValue(SyncScrollOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
||||
|
||||
public bool UseSyntaxHighlighting
|
||||
{
|
||||
get => GetValue(UseSyntaxHighlightingProperty);
|
||||
set => SetValue(UseSyntaxHighlightingProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
public Models.TextDiff DiffData => DataContext as Models.TextDiff;
|
||||
|
||||
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
_lineStyleTransformer = new LineStyleTransformer(this);
|
||||
|
||||
IsReadOnly = true;
|
||||
ShowLineNumbers = false;
|
||||
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(this, true) { Margin = new Thickness(8, 0) });
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(this, false) { Margin = new Thickness(8, 0) });
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
var scroller = (ScrollViewer)e.NameScope.Find("PART_ScrollViewer");
|
||||
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
UpdateTextMate();
|
||||
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged;
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
|
||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||
TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged;
|
||||
}
|
||||
|
||||
if (_textMate != null)
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
var textDiff = DataContext as Models.TextDiff;
|
||||
if (textDiff != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
var builder = new StringBuilder();
|
||||
foreach (var line in textDiff.Lines)
|
||||
builder.AppendLine(line.Content);
|
||||
|
||||
Text = builder.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = string.Empty;
|
||||
}
|
||||
|
||||
GC.Collect();
|
||||
|
@ -346,9 +429,7 @@ namespace SourceGit.Views
|
|||
var menu = new ContextMenu();
|
||||
var parentView = this.FindAncestorOfType<TextDiffView>();
|
||||
if (parentView != null)
|
||||
{
|
||||
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, false);
|
||||
}
|
||||
|
||||
var copy = new MenuItem();
|
||||
copy.Header = App.Text("Copy");
|
||||
|
@ -364,84 +445,9 @@ namespace SourceGit.Views
|
|||
TextArea.TextView.OpenContextMenu(menu);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTextViewScrollOffsetChanged(object sender, EventArgs e)
|
||||
{
|
||||
SetCurrentValue(SyncScrollOffsetProperty, TextArea.TextView.ScrollOffset);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == DiffDataProperty)
|
||||
{
|
||||
if (DiffData != null)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
foreach (var line in DiffData.Lines)
|
||||
{
|
||||
builder.AppendLine(line.Content);
|
||||
}
|
||||
|
||||
Text = builder.ToString();
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = string.Empty;
|
||||
}
|
||||
}
|
||||
else if (change.Property == SyncScrollOffsetProperty)
|
||||
{
|
||||
if (TextArea.TextView.ScrollOffset != SyncScrollOffset)
|
||||
{
|
||||
IScrollable scrollable = TextArea.TextView;
|
||||
scrollable.Offset = SyncScrollOffset;
|
||||
}
|
||||
}
|
||||
else if (change.Property == UseSyntaxHighlightingProperty)
|
||||
{
|
||||
UpdateTextMate();
|
||||
}
|
||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
||||
{
|
||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTextMate()
|
||||
{
|
||||
if (UseSyntaxHighlighting)
|
||||
{
|
||||
if (_textMate == null)
|
||||
{
|
||||
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
|
||||
if (DiffData != null)
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_textMate != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
GC.Collect();
|
||||
|
||||
TextArea.TextView.Redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextMate.Installation _textMate;
|
||||
private readonly LineStyleTransformer _lineStyleTransformer = null;
|
||||
}
|
||||
|
||||
public class SingleSideTextDiffPresenter : TextEditor
|
||||
public class SingleSideTextDiffPresenter : IThemedTextDiffPresenter
|
||||
{
|
||||
public class LineNumberMargin : AbstractMargin
|
||||
{
|
||||
|
@ -523,7 +529,7 @@ namespace SourceGit.Views
|
|||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
var pen = new Pen(_editor.BorderBrush, 1);
|
||||
var pen = new Pen(_editor.LineBrush, 1);
|
||||
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
||||
}
|
||||
|
||||
|
@ -575,11 +581,11 @@ namespace SourceGit.Views
|
|||
switch (type)
|
||||
{
|
||||
case Models.TextDiffLineType.None:
|
||||
return _editor.LineBGEmpty;
|
||||
return _editor.EmptyContentBackground;
|
||||
case Models.TextDiffLineType.Added:
|
||||
return _editor.LineBGAdd;
|
||||
return _editor.AddedContentBackground;
|
||||
case Models.TextDiffLineType.Deleted:
|
||||
return _editor.LineBGDeleted;
|
||||
return _editor.DeletedContentBackground;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
@ -607,7 +613,7 @@ namespace SourceGit.Views
|
|||
{
|
||||
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
||||
{
|
||||
v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
|
||||
v.TextRunProperties.SetForegroundBrush(_editor.IndicatorForeground);
|
||||
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
||||
});
|
||||
|
||||
|
@ -616,7 +622,7 @@ namespace SourceGit.Views
|
|||
|
||||
if (info.Highlights.Count > 0)
|
||||
{
|
||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.LineBGAdd : _editor.LineBGDeleted;
|
||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.AddedHighlightBrush : _editor.DeletedHighlightBrush;
|
||||
foreach (var highlight in info.Highlights)
|
||||
{
|
||||
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
||||
|
@ -639,103 +645,16 @@ namespace SourceGit.Views
|
|||
set => SetValue(IsOldProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<ViewModels.TwoSideTextDiff> DiffDataProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, ViewModels.TwoSideTextDiff>(nameof(DiffData));
|
||||
|
||||
public ViewModels.TwoSideTextDiff DiffData
|
||||
{
|
||||
get => GetValue(DiffDataProperty);
|
||||
set => SetValue(DiffDataProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGEmptyProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGEmpty), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
||||
|
||||
public IBrush LineBGEmpty
|
||||
{
|
||||
get => GetValue(LineBGEmptyProperty);
|
||||
set => SetValue(LineBGEmptyProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGAddProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGAdd), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
||||
|
||||
public IBrush LineBGAdd
|
||||
{
|
||||
get => GetValue(LineBGAddProperty);
|
||||
set => SetValue(LineBGAddProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> LineBGDeletedProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGDeleted), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
||||
|
||||
public IBrush LineBGDeleted
|
||||
{
|
||||
get => GetValue(LineBGDeletedProperty);
|
||||
set => SetValue(LineBGDeletedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryLineBGAddProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryLineBGAdd), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
||||
|
||||
public IBrush SecondaryLineBGAdd
|
||||
{
|
||||
get => GetValue(SecondaryLineBGAddProperty);
|
||||
set => SetValue(SecondaryLineBGAddProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryLineBGDeletedProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryLineBGDeleted), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
||||
|
||||
public IBrush SecondaryLineBGDeleted
|
||||
{
|
||||
get => GetValue(SecondaryLineBGDeletedProperty);
|
||||
set => SetValue(SecondaryLineBGDeletedProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SecondaryFGProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryFG), Brushes.Gray);
|
||||
|
||||
public IBrush SecondaryFG
|
||||
{
|
||||
get => GetValue(SecondaryFGProperty);
|
||||
set => SetValue(SecondaryFGProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, Vector>(nameof(SyncScrollOffset), Vector.Zero);
|
||||
|
||||
public Vector SyncScrollOffset
|
||||
{
|
||||
get => GetValue(SyncScrollOffsetProperty);
|
||||
set => SetValue(SyncScrollOffsetProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
||||
|
||||
public bool UseSyntaxHighlighting
|
||||
{
|
||||
get => GetValue(UseSyntaxHighlightingProperty);
|
||||
set => SetValue(UseSyntaxHighlightingProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
public ViewModels.TwoSideTextDiff DiffData => DataContext as ViewModels.TwoSideTextDiff;
|
||||
|
||||
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
_lineStyleTransformer = new LineStyleTransformer(this);
|
||||
|
||||
IsReadOnly = true;
|
||||
ShowLineNumbers = false;
|
||||
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) });
|
||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
|
@ -745,12 +664,10 @@ namespace SourceGit.Views
|
|||
_scrollViewer = this.FindDescendantOfType<ScrollViewer>();
|
||||
if (_scrollViewer != null)
|
||||
{
|
||||
_scrollViewer.Offset = SyncScrollOffset;
|
||||
_scrollViewer.ScrollChanged += OnTextViewScrollChanged;
|
||||
_scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay));
|
||||
}
|
||||
|
||||
UpdateTextMate();
|
||||
|
||||
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
}
|
||||
|
@ -765,18 +682,31 @@ namespace SourceGit.Views
|
|||
_scrollViewer = null;
|
||||
}
|
||||
|
||||
if (_textMate != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
}
|
||||
|
||||
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
|
||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
var lines = IsOld ? diff.Old : diff.New;
|
||||
foreach (var line in lines)
|
||||
builder.AppendLine(line.Content);
|
||||
|
||||
Text = builder.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e)
|
||||
{
|
||||
if (!TextArea.IsFocused)
|
||||
|
@ -785,8 +715,8 @@ namespace SourceGit.Views
|
|||
|
||||
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||
{
|
||||
if (TextArea.IsFocused)
|
||||
SetCurrentValue(SyncScrollOffsetProperty, _scrollViewer.Offset);
|
||||
if (TextArea.IsFocused && DataContext is ViewModels.TwoSideTextDiff diff)
|
||||
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||
}
|
||||
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
|
@ -798,9 +728,7 @@ namespace SourceGit.Views
|
|||
var menu = new ContextMenu();
|
||||
var parentView = this.FindAncestorOfType<TextDiffView>();
|
||||
if (parentView != null)
|
||||
{
|
||||
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, IsOld);
|
||||
}
|
||||
|
||||
var copy = new MenuItem();
|
||||
copy.Header = App.Text("Copy");
|
||||
|
@ -817,96 +745,11 @@ namespace SourceGit.Views
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == DiffDataProperty)
|
||||
{
|
||||
if (DiffData != null)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
if (IsOld)
|
||||
{
|
||||
foreach (var line in DiffData.Old)
|
||||
{
|
||||
builder.AppendLine(line.Content);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var line in DiffData.New)
|
||||
{
|
||||
builder.AppendLine(line.Content);
|
||||
}
|
||||
}
|
||||
|
||||
Text = builder.ToString();
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = string.Empty;
|
||||
}
|
||||
}
|
||||
else if (change.Property == SyncScrollOffsetProperty)
|
||||
{
|
||||
if (!TextArea.IsFocused && _scrollViewer != null)
|
||||
_scrollViewer.Offset = SyncScrollOffset;
|
||||
}
|
||||
else if (change.Property == UseSyntaxHighlightingProperty)
|
||||
{
|
||||
UpdateTextMate();
|
||||
}
|
||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
||||
{
|
||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateTextMate()
|
||||
{
|
||||
if (UseSyntaxHighlighting)
|
||||
{
|
||||
if (_textMate == null)
|
||||
{
|
||||
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||
|
||||
if (DiffData != null)
|
||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_textMate != null)
|
||||
{
|
||||
_textMate.Dispose();
|
||||
_textMate = null;
|
||||
GC.Collect();
|
||||
|
||||
TextArea.TextView.Redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextMate.Installation _textMate;
|
||||
private readonly LineStyleTransformer _lineStyleTransformer = null;
|
||||
private ScrollViewer _scrollViewer = null;
|
||||
}
|
||||
|
||||
public partial class TextDiffView : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<Models.TextDiff> TextDiffProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, Models.TextDiff>(nameof(TextDiff), null);
|
||||
|
||||
public Models.TextDiff TextDiff
|
||||
{
|
||||
get => GetValue(TextDiffProperty);
|
||||
set => SetValue(TextDiffProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<bool> UseSideBySideDiffProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseSideBySideDiff), false);
|
||||
|
||||
|
@ -916,13 +759,20 @@ namespace SourceGit.Views
|
|||
set => SetValue(UseSideBySideDiffProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
||||
AvaloniaProperty.Register<TextDiffView, Vector>(nameof(SyncScrollOffset));
|
||||
|
||||
public Vector SyncScrollOffset
|
||||
static TextDiffView()
|
||||
{
|
||||
get => GetValue(SyncScrollOffsetProperty);
|
||||
set => SetValue(SyncScrollOffsetProperty, value);
|
||||
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, e) =>
|
||||
{
|
||||
if (v.DataContext is Models.TextDiff diff)
|
||||
{
|
||||
diff.SyncScrollOffset = Vector.Zero;
|
||||
|
||||
if (v.UseSideBySideDiff)
|
||||
v.Content = new ViewModels.TwoSideTextDiff(diff);
|
||||
else
|
||||
v.Content = diff;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public TextDiffView()
|
||||
|
@ -932,6 +782,10 @@ namespace SourceGit.Views
|
|||
|
||||
public void FillContextMenuForWorkingCopyChange(ContextMenu menu, int startLine, int endLine, bool isOldSide)
|
||||
{
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
if (diff == null)
|
||||
return;
|
||||
|
||||
var parentView = this.FindAncestorOfType<DiffView>();
|
||||
if (parentView == null)
|
||||
return;
|
||||
|
@ -951,7 +805,7 @@ namespace SourceGit.Views
|
|||
endLine = tmp;
|
||||
}
|
||||
|
||||
var selection = GetUnifiedSelection(startLine, endLine, isOldSide);
|
||||
var selection = GetUnifiedSelection(diff, startLine, endLine, isOldSide);
|
||||
if (!selection.HasChanges)
|
||||
return;
|
||||
|
||||
|
@ -1033,17 +887,17 @@ namespace SourceGit.Views
|
|||
var tmpFile = Path.GetTempFileName();
|
||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||
{
|
||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile);
|
||||
diff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile);
|
||||
}
|
||||
else if (!UseSideBySideDiff)
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, isOldSide, tmpFile);
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, isOldSide, tmpFile);
|
||||
}
|
||||
|
||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index").Exec();
|
||||
|
@ -1065,17 +919,17 @@ namespace SourceGit.Views
|
|||
var tmpFile = Path.GetTempFileName();
|
||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||
{
|
||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||
diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||
}
|
||||
else if (!UseSideBySideDiff)
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
}
|
||||
|
||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--reverse").Exec();
|
||||
|
@ -1103,15 +957,15 @@ namespace SourceGit.Views
|
|||
var tmpFile = Path.GetTempFileName();
|
||||
if (change.Index == Models.ChangeState.Added)
|
||||
{
|
||||
TextDiff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
diff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
}
|
||||
else if (!UseSideBySideDiff)
|
||||
{
|
||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
}
|
||||
|
||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index --reverse").Exec();
|
||||
|
@ -1133,17 +987,17 @@ namespace SourceGit.Views
|
|||
var tmpFile = Path.GetTempFileName();
|
||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||
{
|
||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||
diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||
}
|
||||
else if (!UseSideBySideDiff)
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||
}
|
||||
else
|
||||
{
|
||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||
}
|
||||
|
||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--index --reverse").Exec();
|
||||
|
@ -1162,44 +1016,29 @@ namespace SourceGit.Views
|
|||
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
var data = TextDiff;
|
||||
if (data == null)
|
||||
var diff = DataContext as Models.TextDiff;
|
||||
if (diff == null)
|
||||
{
|
||||
Content = null;
|
||||
SyncScrollOffset = Vector.Zero;
|
||||
GC.Collect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (change.Property == TextDiffProperty)
|
||||
{
|
||||
if (UseSideBySideDiff)
|
||||
Content = new ViewModels.TwoSideTextDiff(TextDiff);
|
||||
else
|
||||
Content = TextDiff;
|
||||
|
||||
SetCurrentValue(SyncScrollOffsetProperty, TextDiff.SyncScrollOffset);
|
||||
}
|
||||
else if (change.Property == UseSideBySideDiffProperty)
|
||||
{
|
||||
if (UseSideBySideDiff)
|
||||
Content = new ViewModels.TwoSideTextDiff(TextDiff);
|
||||
else
|
||||
Content = TextDiff;
|
||||
|
||||
SetCurrentValue(SyncScrollOffsetProperty, Vector.Zero);
|
||||
}
|
||||
if (UseSideBySideDiff)
|
||||
Content = new ViewModels.TwoSideTextDiff(diff, Content as ViewModels.TwoSideTextDiff);
|
||||
else
|
||||
Content = diff;
|
||||
}
|
||||
|
||||
private Models.TextDiffSelection GetUnifiedSelection(int startLine, int endLine, bool isOldSide)
|
||||
private Models.TextDiffSelection GetUnifiedSelection(Models.TextDiff diff, int startLine, int endLine, bool isOldSide)
|
||||
{
|
||||
var rs = new Models.TextDiffSelection();
|
||||
var diff = TextDiff;
|
||||
|
||||
endLine = Math.Min(endLine, TextDiff.Lines.Count);
|
||||
endLine = Math.Min(endLine, diff.Lines.Count);
|
||||
if (Content is ViewModels.TwoSideTextDiff twoSides)
|
||||
{
|
||||
var target = isOldSide ? twoSides.Old : twoSides.New;
|
||||
|
@ -1233,8 +1072,8 @@ namespace SourceGit.Views
|
|||
|
||||
var firstContent = target[firstContentLine];
|
||||
var endContent = target[endContentLine];
|
||||
startLine = TextDiff.Lines.IndexOf(firstContent) + 1;
|
||||
endLine = TextDiff.Lines.IndexOf(endContent) + 1;
|
||||
startLine = diff.Lines.IndexOf(firstContent) + 1;
|
||||
endLine = diff.Lines.IndexOf(endContent) + 1;
|
||||
}
|
||||
|
||||
rs.StartLine = startLine;
|
||||
|
|
Loading…
Reference in a new issue