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