enhance: leave the current state until we got the new diff result to reduce flickering

This commit is contained in:
leo 2024-03-20 18:27:48 +08:00
parent 2782ef4cc1
commit 340fe9e3ba
10 changed files with 158 additions and 227 deletions

View file

@ -0,0 +1,59 @@
using System.IO;
using Avalonia.Styling;
using AvaloniaEdit;
using AvaloniaEdit.TextMate;
using TextMateSharp.Grammars;
namespace SourceGit.Models
{
public static class TextMateHelper
{
public static TextMate.Installation CreateForEditor(TextEditor editor)
{
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
return editor.InstallTextMate(new RegistryOptions(ThemeName.DarkPlus));
}
else
{
return editor.InstallTextMate(new RegistryOptions(ThemeName.LightPlus));
}
}
public static void SetThemeByApp(TextMate.Installation installation)
{
if (installation == null) return;
var reg = installation.RegistryOptions as RegistryOptions;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
installation.SetTheme(reg.LoadTheme(ThemeName.DarkPlus));
}
else
{
installation.SetTheme(reg.LoadTheme(ThemeName.LightPlus));
}
}
public static void SetGrammarByFileName(TextMate.Installation installation, string filePath)
{
if (installation == null) return;
var ext = Path.GetExtension(filePath);
if (ext == ".h")
{
ext = ".cpp";
}
else if (ext == ".resx")
{
ext = ".xml";
}
var reg = installation.RegistryOptions as RegistryOptions;
installation.SetGrammar(reg.GetScopeByExtension(ext));
}
}
}

View file

@ -67,7 +67,7 @@ namespace SourceGit.ViewModels
else else
{ {
SelectedChangeNode = FileTreeNode.SelectByPath(_changeTree, value.Path); SelectedChangeNode = FileTreeNode.SelectByPath(_changeTree, value.Path);
DiffContext = new DiffContext(_repo, new Models.DiffOption(_commit, value)); DiffContext = new DiffContext(_repo, new Models.DiffOption(_commit, value), _diffContext);
} }
} }
} }

View file

@ -70,10 +70,11 @@ namespace SourceGit.ViewModels
set => SetProperty(ref _syncScrollOffset, value); set => SetProperty(ref _syncScrollOffset, value);
} }
public DiffContext(string repo, Models.DiffOption option) public DiffContext(string repo, Models.DiffOption option, DiffContext previous = null)
{ {
_repo = repo; _repo = repo;
_option = option; _option = option;
_content = previous != null ? previous._content : null;
OnPropertyChanged(nameof(FilePath)); OnPropertyChanged(nameof(FilePath));
OnPropertyChanged(nameof(IsOrgFilePathVisible)); OnPropertyChanged(nameof(IsOrgFilePathVisible));
@ -101,7 +102,7 @@ namespace SourceGit.ViewModels
} }
} }
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.Post(() =>
{ {
if (latest.IsBinary) if (latest.IsBinary)
{ {

View file

@ -39,7 +39,7 @@ namespace SourceGit.ViewModels
} }
else else
{ {
DiffContext = new DiffContext(_repo, new Models.DiffOption(value, _file)); DiffContext = new DiffContext(_repo, new Models.DiffOption(value, _file), _diffContext);
} }
} }
} }

View file

@ -51,7 +51,7 @@ namespace SourceGit.ViewModels
else else
{ {
SelectedNode = FileTreeNode.SelectByPath(_changeTree, value.Path); SelectedNode = FileTreeNode.SelectByPath(_changeTree, value.Path);
DiffContext = new DiffContext(_repo, new Models.DiffOption(StartPoint.SHA, EndPoint.SHA, value)); DiffContext = new DiffContext(_repo, new Models.DiffOption(StartPoint.SHA, EndPoint.SHA, value), _diffContext);
} }
} }
} }

View file

@ -77,7 +77,7 @@ namespace SourceGit.ViewModels
} }
else else
{ {
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption($"{_selectedStash.SHA}^", _selectedStash.SHA, value)); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption($"{_selectedStash.SHA}^", _selectedStash.SHA, value), _diffContext);
} }
} }
} }

View file

@ -286,10 +286,17 @@ namespace SourceGit.ViewModels
DetailContext = new ConflictContext() { Change = change }; DetailContext = new ConflictContext() { Change = change };
} }
else 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));
} }
} }
}
public async void StageChanges(List<Models.Change> changes) public async void StageChanges(List<Models.Change> changes)
{ {

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.IO;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
@ -9,7 +8,6 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Styling;
using AvaloniaEdit; using AvaloniaEdit;
using AvaloniaEdit.Document; using AvaloniaEdit.Document;
@ -18,8 +16,6 @@ using AvaloniaEdit.Rendering;
using AvaloniaEdit.TextMate; using AvaloniaEdit.TextMate;
using AvaloniaEdit.Utils; using AvaloniaEdit.Utils;
using TextMateSharp.Grammars;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class BlameTextEditor : TextEditor public class BlameTextEditor : TextEditor
@ -214,6 +210,16 @@ namespace SourceGit.Views
IsReadOnly = true; IsReadOnly = true;
ShowLineNumbers = false; ShowLineNumbers = false;
WordWrap = false; WordWrap = false;
_textMate = Models.TextMateHelper.CreateForEditor(this);
TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged;
TextArea.TextView.Margin = new Thickness(4, 0);
} }
public void OnCommitSHAClicked(string sha) public void OnCommitSHAClicked(string sha)
@ -224,31 +230,6 @@ namespace SourceGit.Views
} }
} }
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
TextArea.LeftMargins.Add(new CommitInfoMargin(this) { Margin = new Thickness(8, 0) });
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged;
TextArea.TextView.Margin = new Thickness(4, 0);
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
}
else
{
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
}
_textMate = this.InstallTextMate(_registryOptions);
UpdateGrammar();
}
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
base.OnUnloaded(e); base.OnUnloaded(e);
@ -257,10 +238,12 @@ namespace SourceGit.Views
TextArea.TextView.ContextRequested -= OnTextViewContextRequested; TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
TextArea.TextView.VisualLinesChanged -= OnTextViewVisualLinesChanged; TextArea.TextView.VisualLinesChanged -= OnTextViewVisualLinesChanged;
_registryOptions = null; if (_textMate != null)
{
_textMate.Dispose(); _textMate.Dispose();
_textMate = null; _textMate = null;
} }
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{ {
@ -270,24 +253,17 @@ namespace SourceGit.Views
{ {
if (BlameData != null) if (BlameData != null)
{ {
Models.TextMateHelper.SetGrammarByFileName(_textMate, BlameData.File);
Text = BlameData.Content; Text = BlameData.Content;
UpdateGrammar();
} }
else else
{ {
Text = string.Empty; Text = string.Empty;
} }
} }
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
{ {
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) Models.TextMateHelper.SetThemeByApp(_textMate);
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
}
else
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
}
} }
} }
@ -329,22 +305,6 @@ namespace SourceGit.Views
} }
} }
private void UpdateGrammar()
{
if (_textMate == null || BlameData == null) return;
var ext = Path.GetExtension(BlameData.File);
if (ext == ".h")
{
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
}
else
{
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
}
}
private RegistryOptions _registryOptions = null;
private TextMate.Installation _textMate = null; private TextMate.Installation _textMate = null;
} }

View file

@ -1,23 +1,18 @@
using System; using System;
using System.IO;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Styling;
using AvaloniaEdit; using AvaloniaEdit;
using AvaloniaEdit.Document; using AvaloniaEdit.Document;
using AvaloniaEdit.Editing; using AvaloniaEdit.Editing;
using AvaloniaEdit.TextMate; using AvaloniaEdit.TextMate;
using TextMateSharp.Grammars;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class RevisionTextFileView : TextEditor public class RevisionTextFileView : TextEditor
{ {
protected override Type StyleKeyOverride => typeof(TextEditor); protected override Type StyleKeyOverride => typeof(TextEditor);
@ -39,17 +34,12 @@ namespace SourceGit.Views
base.OnLoaded(e); base.OnLoaded(e);
TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.ContextRequested += OnTextViewContextRequested;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
}
else
{
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
}
_textMate = this.InstallTextMate(_registryOptions); _textMate = Models.TextMateHelper.CreateForEditor(this);
UpdateGrammar(); if (DataContext is Models.RevisionTextFile source)
{
Models.TextMateHelper.SetGrammarByFileName(_textMate, source.FileName);
}
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
@ -57,9 +47,13 @@ namespace SourceGit.Views
base.OnUnloaded(e); base.OnUnloaded(e);
TextArea.TextView.ContextRequested -= OnTextViewContextRequested; TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
_registryOptions = null;
if (_textMate != null)
{
_textMate.Dispose(); _textMate.Dispose();
_textMate = null; _textMate = null;
}
GC.Collect(); GC.Collect();
} }
@ -70,7 +64,7 @@ namespace SourceGit.Views
var source = DataContext as Models.RevisionTextFile; var source = DataContext as Models.RevisionTextFile;
if (source != null) if (source != null)
{ {
UpdateGrammar(); Models.TextMateHelper.SetGrammarByFileName(_textMate, source.FileName);
Text = source.Content; Text = source.Content;
} }
} }
@ -79,16 +73,9 @@ namespace SourceGit.Views
{ {
base.OnPropertyChanged(change); base.OnPropertyChanged(change);
if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
{ {
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) Models.TextMateHelper.SetThemeByApp(_textMate);
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
}
else
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
}
} }
} }
@ -118,25 +105,6 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private void UpdateGrammar()
{
if (_textMate == null) return;
var src = DataContext as Models.RevisionTextFile;
if (src == null) return;
var ext = Path.GetExtension(src.FileName);
if (ext == ".h")
{
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
}
else
{
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
}
}
private RegistryOptions _registryOptions = null;
private TextMate.Installation _textMate = null; private TextMate.Installation _textMate = null;
} }

View file

@ -9,7 +9,6 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using AvaloniaEdit; using AvaloniaEdit;
@ -19,8 +18,6 @@ using AvaloniaEdit.Rendering;
using AvaloniaEdit.TextMate; using AvaloniaEdit.TextMate;
using AvaloniaEdit.Utils; using AvaloniaEdit.Utils;
using TextMateSharp.Grammars;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class CombinedTextDiffPresenter : TextEditor public class CombinedTextDiffPresenter : TextEditor
@ -160,10 +157,9 @@ namespace SourceGit.Views
private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)); private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(90, 0, 255, 0));
private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)); private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(80, 255, 0, 0));
public LineStyleTransformer(CombinedTextDiffPresenter editor, IBrush indicatorFG) public LineStyleTransformer(CombinedTextDiffPresenter editor)
{ {
_editor = editor; _editor = editor;
_indicatorFG = indicatorFG;
_indicatorTypeface = new Typeface("fonts:SourceGit#JetBrains Mono", FontStyle.Italic); _indicatorTypeface = new Typeface("fonts:SourceGit#JetBrains Mono", FontStyle.Italic);
} }
@ -177,7 +173,7 @@ namespace SourceGit.Views
{ {
ChangeLinePart(line.Offset, line.EndOffset, v => ChangeLinePart(line.Offset, line.EndOffset, v =>
{ {
v.TextRunProperties.SetForegroundBrush(_indicatorFG); v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
v.TextRunProperties.SetTypeface(_indicatorTypeface); v.TextRunProperties.SetTypeface(_indicatorTypeface);
}); });
@ -198,7 +194,6 @@ namespace SourceGit.Views
} }
private readonly CombinedTextDiffPresenter _editor; private readonly CombinedTextDiffPresenter _editor;
private readonly IBrush _indicatorFG = Brushes.DarkGray;
private readonly Typeface _indicatorTypeface = Typeface.Default; private readonly Typeface _indicatorTypeface = Typeface.Default;
} }
@ -233,14 +228,11 @@ namespace SourceGit.Views
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument()) public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
{ {
_lineStyleTransformer = new LineStyleTransformer(this);
IsReadOnly = true; IsReadOnly = true;
ShowLineNumbers = false; ShowLineNumbers = false;
WordWrap = false; WordWrap = false;
}
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
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));
@ -249,37 +241,34 @@ namespace SourceGit.Views
TextArea.TextView.Margin = new Thickness(4, 0); TextArea.TextView.Margin = new Thickness(4, 0);
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this)); TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
}
protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);
_textMate = Models.TextMateHelper.CreateForEditor(this);
if (DiffData != null) Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.ContextRequested += OnTextViewContextRequested;
TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged; TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
}
else
{
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
}
_textMate = this.InstallTextMate(_registryOptions);
UpdateGrammar();
// This line must after InstallTextMate.
TextArea.TextView.LineTransformers.Add(new LineStyleTransformer(this, SecondaryFG));
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
{ {
base.OnUnloaded(e); base.OnUnloaded(e);
TextArea.LeftMargins.Clear(); TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
TextArea.TextView.BackgroundRenderers.Clear();
TextArea.TextView.LineTransformers.Clear();
TextArea.TextView.ContextRequested -= OnTextViewContextRequested; TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged; TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged;
_registryOptions = null;
if (_textMate != null)
{
_textMate.Dispose(); _textMate.Dispose();
_textMate = null; _textMate = null;
}
GC.Collect(); GC.Collect();
} }
@ -328,7 +317,7 @@ namespace SourceGit.Views
builder.AppendLine(line.Content); builder.AppendLine(line.Content);
} }
UpdateGrammar(); Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
Text = builder.ToString(); Text = builder.ToString();
} }
else else
@ -344,36 +333,14 @@ namespace SourceGit.Views
scrollable.Offset = SyncScrollOffset; scrollable.Offset = SyncScrollOffset;
} }
} }
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
{ {
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) Models.TextMateHelper.SetThemeByApp(_textMate);
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
}
else
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
}
} }
} }
private void UpdateGrammar()
{
if (_textMate == null || DiffData == null) return;
var ext = Path.GetExtension(DiffData.File);
if (ext == ".h")
{
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
}
else
{
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
}
}
private RegistryOptions _registryOptions;
private TextMate.Installation _textMate; private TextMate.Installation _textMate;
private LineStyleTransformer _lineStyleTransformer = null;
} }
public class SingleSideTextDiffPresenter : TextEditor public class SingleSideTextDiffPresenter : TextEditor
@ -513,10 +480,9 @@ namespace SourceGit.Views
private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)); private static readonly Brush HL_ADDED = new SolidColorBrush(Color.FromArgb(90, 0, 255, 0));
private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)); private static readonly Brush HL_DELETED = new SolidColorBrush(Color.FromArgb(80, 255, 0, 0));
public LineStyleTransformer(SingleSideTextDiffPresenter editor, IBrush indicatorFG) public LineStyleTransformer(SingleSideTextDiffPresenter editor)
{ {
_editor = editor; _editor = editor;
_indicatorFG = indicatorFG;
_indicatorTypeface = new Typeface("fonts:SourceGit#JetBrains Mono", FontStyle.Italic); _indicatorTypeface = new Typeface("fonts:SourceGit#JetBrains Mono", FontStyle.Italic);
} }
@ -531,7 +497,7 @@ namespace SourceGit.Views
{ {
ChangeLinePart(line.Offset, line.EndOffset, v => ChangeLinePart(line.Offset, line.EndOffset, v =>
{ {
v.TextRunProperties.SetForegroundBrush(_indicatorFG); v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
v.TextRunProperties.SetTypeface(_indicatorTypeface); v.TextRunProperties.SetTypeface(_indicatorTypeface);
}); });
@ -552,7 +518,6 @@ namespace SourceGit.Views
} }
private readonly SingleSideTextDiffPresenter _editor; private readonly SingleSideTextDiffPresenter _editor;
private readonly IBrush _indicatorFG = Brushes.DarkGray;
private readonly Typeface _indicatorTypeface = Typeface.Default; private readonly Typeface _indicatorTypeface = Typeface.Default;
} }
@ -596,9 +561,16 @@ namespace SourceGit.Views
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument()) public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
{ {
_lineStyleTransformer = new LineStyleTransformer(this);
IsReadOnly = true; IsReadOnly = true;
ShowLineNumbers = false; ShowLineNumbers = false;
WordWrap = false; WordWrap = 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));
} }
protected override void OnLoaded(RoutedEventArgs e) protected override void OnLoaded(RoutedEventArgs e)
@ -612,26 +584,11 @@ namespace SourceGit.Views
_scrollViewer.ScrollChanged += OnTextViewScrollChanged; _scrollViewer.ScrollChanged += OnTextViewScrollChanged;
} }
TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) }); _textMate = Models.TextMateHelper.CreateForEditor(this);
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this)); if (DiffData != null) Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
TextArea.TextView.Margin = new Thickness(4, 0);
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this)); TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
TextArea.TextView.ContextRequested += OnTextViewContextRequested; TextArea.TextView.ContextRequested += OnTextViewContextRequested;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
{
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
}
else
{
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
}
_textMate = this.InstallTextMate(_registryOptions);
UpdateGrammar();
// This line must after InstallTextMate
TextArea.TextView.LineTransformers.Add(new LineStyleTransformer(this, SecondaryFG));
} }
protected override void OnUnloaded(RoutedEventArgs e) protected override void OnUnloaded(RoutedEventArgs e)
@ -644,13 +601,15 @@ namespace SourceGit.Views
_scrollViewer = null; _scrollViewer = null;
} }
TextArea.LeftMargins.Clear(); if (_textMate != null)
TextArea.TextView.BackgroundRenderers.Clear(); {
TextArea.TextView.LineTransformers.Clear();
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
_registryOptions = null;
_textMate.Dispose(); _textMate.Dispose();
_textMate = null; _textMate = null;
}
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
GC.Collect(); GC.Collect();
} }
@ -716,7 +675,7 @@ namespace SourceGit.Views
} }
} }
UpdateGrammar(); Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
Text = builder.ToString(); Text = builder.ToString();
} }
else else
@ -744,37 +703,14 @@ namespace SourceGit.Views
} }
} }
} }
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
{ {
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) Models.TextMateHelper.SetThemeByApp(_textMate);
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
}
else
{
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
}
} }
} }
private void UpdateGrammar()
{
if (_textMate == null || DiffData == null) return;
var ext = Path.GetExtension(DiffData.File);
if (ext == ".h")
{
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
}
else
{
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
}
}
private RegistryOptions _registryOptions;
private TextMate.Installation _textMate; private TextMate.Installation _textMate;
private LineStyleTransformer _lineStyleTransformer = null;
private ScrollViewer _scrollViewer = null; private ScrollViewer _scrollViewer = null;
private bool _syncScrollingByOthers = false; private bool _syncScrollingByOthers = false;
} }