mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-25 14:15:00 +00:00
style: add .editorconfig for code formatting. see issu #25
This commit is contained in:
parent
a8eeea4f78
commit
18aaa0a143
225 changed files with 7781 additions and 3911 deletions
|
@ -1,43 +1,53 @@
|
|||
using System.Reflection;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using System.Reflection;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class About : Window {
|
||||
public string Version {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class About : Window
|
||||
{
|
||||
public string Version
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public About() {
|
||||
public About()
|
||||
{
|
||||
var ver = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
Version = $"{ver.Major}.{ver.Minor}";
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void OnVisitAvaloniaUI(object sender, PointerPressedEventArgs e) {
|
||||
private void OnVisitAvaloniaUI(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
Native.OS.OpenBrowser("https://www.avaloniaui.net/");
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnVisitAvaloniaEdit(object sender, PointerPressedEventArgs e) {
|
||||
private void OnVisitAvaloniaEdit(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
Native.OS.OpenBrowser("https://github.com/AvaloniaUI/AvaloniaEdit");
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnVisitJetBrainsMonoFont(object sender, PointerPressedEventArgs e) {
|
||||
private void OnVisitJetBrainsMonoFont(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
Native.OS.OpenBrowser("https://www.jetbrains.com/lp/mono/");
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,21 +2,26 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class AddRemote : UserControl {
|
||||
public AddRemote() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class AddRemote : UserControl
|
||||
{
|
||||
public AddRemote()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e) {
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FilePickerOpenOptions() { AllowMultiple = false, FileTypeFilter = [new FilePickerFileType("SSHKey") { Patterns = ["*.*"] }] };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
var selected = await toplevel.StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
txtSSHKey.Text = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class AddSubmodule : UserControl {
|
||||
public AddSubmodule() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class AddSubmodule : UserControl
|
||||
{
|
||||
public AddSubmodule()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,23 +2,28 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Apply : UserControl {
|
||||
public Apply() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Apply : UserControl
|
||||
{
|
||||
public Apply()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectPatchFile(object sender, RoutedEventArgs e) {
|
||||
private async void SelectPatchFile(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
if (topLevel == null) return;
|
||||
|
||||
var options = new FilePickerOpenOptions() { AllowMultiple = false, FileTypeFilter = [ new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }] };
|
||||
var options = new FilePickerOpenOptions() { AllowMultiple = false, FileTypeFilter = [new FilePickerFileType("Patch File") { Patterns = ["*.patch"] }] };
|
||||
var selected = await topLevel.StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
txtPatchFile.Text = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,21 +2,26 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Archive : UserControl {
|
||||
public Archive() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Archive : UserControl
|
||||
{
|
||||
public Archive()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectOutputFile(object sender, RoutedEventArgs e) {
|
||||
var options = new FilePickerSaveOptions() { DefaultExtension = ".zip", FileTypeChoices = [ new FilePickerFileType("ZIP") { Patterns = [ "*.zip" ]}] };
|
||||
private async void SelectOutputFile(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FilePickerSaveOptions() { DefaultExtension = ".zip", FileTypeChoices = [new FilePickerFileType("ZIP") { Patterns = ["*.zip"] }] };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
var selected = await toplevel.StorageProvider.SaveFilePickerAsync(options);
|
||||
if (selected != null) {
|
||||
if (selected != null)
|
||||
{
|
||||
txtSaveFile.Text = selected.Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,18 +2,23 @@ using Avalonia.Controls;
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class AssumeUnchangedManager : Window {
|
||||
public AssumeUnchangedManager() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class AssumeUnchangedManager : Window
|
||||
{
|
||||
public AssumeUnchangedManager()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class Avatar : Control, Models.IAvatarHost {
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class Avatar : Control, Models.IAvatarHost
|
||||
{
|
||||
private static readonly GradientStops[] FALLBACK_GRADIENTS = [
|
||||
new GradientStops() { new GradientStop(Colors.Orange, 0), new GradientStop(Color.FromRgb(255, 213, 134), 1) },
|
||||
new GradientStops() { new GradientStop(Colors.DodgerBlue, 0), new GradientStop(Colors.LightSkyBlue, 1) },
|
||||
|
@ -20,19 +23,24 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<Models.User> UserProperty =
|
||||
AvaloniaProperty.Register<Avatar, Models.User>(nameof(User));
|
||||
|
||||
public Models.User User {
|
||||
public Models.User User
|
||||
{
|
||||
get => GetValue(UserProperty);
|
||||
set => SetValue(UserProperty, value);
|
||||
}
|
||||
|
||||
static Avatar() {
|
||||
static Avatar()
|
||||
{
|
||||
UserProperty.Changed.AddClassHandler<Avatar>(OnUserPropertyChanged);
|
||||
}
|
||||
|
||||
public Avatar() {
|
||||
public Avatar()
|
||||
{
|
||||
var refetch = new MenuItem() { Header = App.Text("RefetchAvatar") };
|
||||
refetch.Click += (o, e) => {
|
||||
if (User != null) {
|
||||
refetch.Click += (o, e) =>
|
||||
{
|
||||
if (User != null)
|
||||
{
|
||||
Models.AvatarManager.Request(_emailMD5, true);
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
@ -42,40 +50,50 @@ namespace SourceGit.Views {
|
|||
ContextMenu.Items.Add(refetch);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (User == null) return;
|
||||
|
||||
var corner = (float)Math.Max(2, Bounds.Width / 16);
|
||||
var img = Models.AvatarManager.Request(_emailMD5, false);
|
||||
if (img != null) {
|
||||
if (img != null)
|
||||
{
|
||||
var rect = new Rect(0, 0, Bounds.Width, Bounds.Height);
|
||||
context.PushClip(new RoundedRect(rect, corner));
|
||||
context.DrawImage(img, rect);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Point textOrigin = new Point((Bounds.Width - _fallbackLabel.Width) * 0.5, (Bounds.Height - _fallbackLabel.Height) * 0.5);
|
||||
context.DrawRectangle(_fallbackBrush, null, new Rect(0, 0, Bounds.Width, Bounds.Height), corner, corner);
|
||||
context.DrawText(_fallbackLabel, textOrigin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnAvatarResourceChanged(string md5) {
|
||||
if (_emailMD5 == md5) {
|
||||
public void OnAvatarResourceChanged(string md5)
|
||||
{
|
||||
if (_emailMD5 == md5)
|
||||
{
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e) {
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
Models.AvatarManager.Subscribe(this);
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e) {
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
Models.AvatarManager.Unsubscribe(this);
|
||||
}
|
||||
|
||||
private static void OnUserPropertyChanged(Avatar avatar, AvaloniaPropertyChangedEventArgs e) {
|
||||
if (avatar.User == null) {
|
||||
private static void OnUserPropertyChanged(Avatar avatar, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (avatar.User == null)
|
||||
{
|
||||
avatar._emailMD5 = null;
|
||||
return;
|
||||
}
|
||||
|
@ -91,7 +109,8 @@ namespace SourceGit.Views {
|
|||
var md5 = builder.ToString();
|
||||
if (avatar._emailMD5 != md5) avatar._emailMD5 = md5;
|
||||
|
||||
avatar._fallbackBrush = new LinearGradientBrush {
|
||||
avatar._fallbackBrush = new LinearGradientBrush
|
||||
{
|
||||
GradientStops = FALLBACK_GRADIENTS[sum % FALLBACK_GRADIENTS.Length],
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
|
@ -100,8 +119,8 @@ namespace SourceGit.Views {
|
|||
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
|
||||
|
||||
avatar._fallbackLabel = new FormattedText(
|
||||
placeholder,
|
||||
CultureInfo.CurrentCulture,
|
||||
placeholder,
|
||||
CultureInfo.CurrentCulture,
|
||||
FlowDirection.LeftToRight,
|
||||
typeface,
|
||||
avatar.Width * 0.65,
|
||||
|
@ -114,4 +133,4 @@ namespace SourceGit.Views {
|
|||
private LinearGradientBrush _fallbackBrush = null;
|
||||
private string _emailMD5 = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,39 +1,49 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Styling;
|
||||
|
||||
using AvaloniaEdit;
|
||||
using AvaloniaEdit.Document;
|
||||
using AvaloniaEdit.Editing;
|
||||
using AvaloniaEdit.Rendering;
|
||||
using AvaloniaEdit.TextMate;
|
||||
using AvaloniaEdit.Utils;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using TextMateSharp.Grammars;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class BlameTextEditor : TextEditor {
|
||||
public class CommitInfoMargin : AbstractMargin {
|
||||
public CommitInfoMargin(BlameTextEditor editor) {
|
||||
using TextMateSharp.Grammars;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class BlameTextEditor : TextEditor
|
||||
{
|
||||
public class CommitInfoMargin : AbstractMargin
|
||||
{
|
||||
public CommitInfoMargin(BlameTextEditor editor)
|
||||
{
|
||||
_editor = editor;
|
||||
ClipToBounds = true;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (_editor.BlameData == null) return;
|
||||
|
||||
var view = TextView;
|
||||
if (view != null && view.VisualLinesValid) {
|
||||
if (view != null && view.VisualLinesValid)
|
||||
{
|
||||
var typeface = view.CreateTypeface();
|
||||
var underlinePen = new Pen(Brushes.DarkOrange, 1);
|
||||
|
||||
foreach (var line in view.VisualLines) {
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber > _editor.BlameData.LineInfos.Count) break;
|
||||
|
||||
|
@ -75,13 +85,16 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize) {
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var view = TextView;
|
||||
var maxWidth = 0.0;
|
||||
if (view != null && view.VisualLinesValid && _editor.BlameData != null) {
|
||||
if (view != null && view.VisualLinesValid && _editor.BlameData != null)
|
||||
{
|
||||
var typeface = view.CreateTypeface();
|
||||
var calculated = new HashSet<string>();
|
||||
foreach (var line in view.VisualLines) {
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber > _editor.BlameData.LineInfos.Count) break;
|
||||
|
||||
|
@ -125,15 +138,18 @@ namespace SourceGit.Views {
|
|||
return new Size(maxWidth, 0);
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e) {
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
base.OnPointerPressed(e);
|
||||
|
||||
var view = TextView;
|
||||
if (!e.Handled && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && view != null && view.VisualLinesValid) {
|
||||
if (!e.Handled && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed && view != null && view.VisualLinesValid)
|
||||
{
|
||||
var pos = e.GetPosition(this);
|
||||
var typeface = view.CreateTypeface();
|
||||
|
||||
foreach (var line in view.VisualLines) {
|
||||
foreach (var line in view.VisualLines)
|
||||
{
|
||||
var lineNumber = line.FirstDocumentLine.LineNumber;
|
||||
if (lineNumber >= _editor.BlameData.LineInfos.Count) break;
|
||||
|
||||
|
@ -148,7 +164,8 @@ namespace SourceGit.Views {
|
|||
Brushes.DarkOrange);
|
||||
|
||||
var rect = new Rect(0, y, shaLink.Width, shaLink.Height);
|
||||
if (rect.Contains(pos)) {
|
||||
if (rect.Contains(pos))
|
||||
{
|
||||
_editor.OnCommitSHAClicked(info.CommitSHA);
|
||||
e.Handled = true;
|
||||
break;
|
||||
|
@ -157,49 +174,58 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
private BlameTextEditor _editor = null;
|
||||
private readonly BlameTextEditor _editor = null;
|
||||
}
|
||||
|
||||
public class VerticalSeperatorMargin : AbstractMargin {
|
||||
public VerticalSeperatorMargin(BlameTextEditor editor) {
|
||||
public class VerticalSeperatorMargin : AbstractMargin
|
||||
{
|
||||
public VerticalSeperatorMargin(BlameTextEditor editor)
|
||||
{
|
||||
_editor = editor;
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
var pen = new Pen(_editor.BorderBrush, 1);
|
||||
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize) {
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
return new Size(1, 0);
|
||||
}
|
||||
|
||||
private BlameTextEditor _editor = null;
|
||||
private readonly BlameTextEditor _editor = null;
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<Models.BlameData> BlameDataProperty =
|
||||
AvaloniaProperty.Register<BlameTextEditor, Models.BlameData>(nameof(BlameData));
|
||||
|
||||
public Models.BlameData BlameData {
|
||||
public Models.BlameData BlameData
|
||||
{
|
||||
get => GetValue(BlameDataProperty);
|
||||
set => SetValue(BlameDataProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
|
||||
public BlameTextEditor() : base(new TextArea(), new TextDocument()) {
|
||||
public BlameTextEditor() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
IsReadOnly = true;
|
||||
ShowLineNumbers = false;
|
||||
WordWrap = false;
|
||||
}
|
||||
|
||||
public void OnCommitSHAClicked(string sha) {
|
||||
if (DataContext is ViewModels.Blame blame) {
|
||||
public void OnCommitSHAClicked(string sha)
|
||||
{
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
blame.NavigateToCommit(sha);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e) {
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
TextArea.LeftMargins.Add(new LineNumberMargin() { Margin = new Thickness(8, 0) });
|
||||
|
@ -210,9 +236,12 @@ namespace SourceGit.Views {
|
|||
TextArea.TextView.VisualLinesChanged += OnTextViewVisualLinesChanged;
|
||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
|
||||
{
|
||||
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
|
||||
}
|
||||
|
||||
|
@ -220,7 +249,8 @@ namespace SourceGit.Views {
|
|||
UpdateGrammar();
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e) {
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
|
||||
TextArea.LeftMargins.Clear();
|
||||
|
@ -232,26 +262,37 @@ namespace SourceGit.Views {
|
|||
_textMate = null;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) {
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == BlameDataProperty) {
|
||||
if (BlameData != null) {
|
||||
if (change.Property == BlameDataProperty)
|
||||
{
|
||||
if (BlameData != null)
|
||||
{
|
||||
Text = BlameData.Content;
|
||||
UpdateGrammar();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
Text = string.Empty;
|
||||
}
|
||||
} else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) {
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
|
||||
}
|
||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null)
|
||||
{
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
|
||||
{
|
||||
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var selected = SelectedText;
|
||||
if (string.IsNullOrEmpty(selected)) return;
|
||||
|
||||
|
@ -264,7 +305,8 @@ namespace SourceGit.Views {
|
|||
var copy = new MenuItem();
|
||||
copy.Header = App.Text("Copy");
|
||||
copy.Icon = icon;
|
||||
copy.Click += (o, ev) => {
|
||||
copy.Click += (o, ev) =>
|
||||
{
|
||||
App.CopyText(selected);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
@ -275,22 +317,29 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTextViewVisualLinesChanged(object sender, EventArgs e) {
|
||||
foreach (var margin in TextArea.LeftMargins) {
|
||||
if (margin is CommitInfoMargin commitInfo) {
|
||||
private void OnTextViewVisualLinesChanged(object sender, EventArgs e)
|
||||
{
|
||||
foreach (var margin in TextArea.LeftMargins)
|
||||
{
|
||||
if (margin is CommitInfoMargin commitInfo)
|
||||
{
|
||||
commitInfo.InvalidateMeasure();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGrammar() {
|
||||
private void UpdateGrammar()
|
||||
{
|
||||
if (_textMate == null || BlameData == null) return;
|
||||
|
||||
var ext = Path.GetExtension(BlameData.File);
|
||||
if (ext == ".h") {
|
||||
if (ext == ".h")
|
||||
{
|
||||
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
|
||||
}
|
||||
}
|
||||
|
@ -299,47 +348,61 @@ namespace SourceGit.Views {
|
|||
private TextMate.Installation _textMate = null;
|
||||
}
|
||||
|
||||
public partial class Blame : Window {
|
||||
public Blame() {
|
||||
if (App.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
|
||||
public partial class Blame : Window
|
||||
{
|
||||
public Blame()
|
||||
{
|
||||
if (App.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
Owner = desktop.MainWindow;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e) {
|
||||
if (WindowState == WindowState.Maximized) {
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (WindowState == WindowState.Maximized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e) {
|
||||
if (sender is Border border) {
|
||||
if (border.Tag is WindowEdge edge) {
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is Border border)
|
||||
{
|
||||
if (border.Tag is WindowEdge edge)
|
||||
{
|
||||
BeginResizeDrag(edge, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
protected override void OnClosed(EventArgs e) {
|
||||
protected override void OnClosed(EventArgs e)
|
||||
{
|
||||
base.OnClosed(e);
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
private void OnCommitSHAPointerPressed(object sender, PointerPressedEventArgs e) {
|
||||
if (DataContext is ViewModels.Blame blame) {
|
||||
private void OnCommitSHAPointerPressed(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Blame blame)
|
||||
{
|
||||
var txt = sender as TextBlock;
|
||||
blame.NavigateToCommit(txt.Text);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,32 +2,40 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CaptionButtons : UserControl {
|
||||
public CaptionButtons() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CaptionButtons : UserControl
|
||||
{
|
||||
public CaptionButtons()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MinimizeWindow(object sender, RoutedEventArgs e) {
|
||||
private void MinimizeWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = WindowState.Minimized;
|
||||
}
|
||||
}
|
||||
|
||||
private void MaximizeOrRestoreWindow(object sender, RoutedEventArgs e) {
|
||||
private void MaximizeOrRestoreWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -2,32 +2,40 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CaptionButtonsMacOS : UserControl {
|
||||
public CaptionButtonsMacOS() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CaptionButtonsMacOS : UserControl
|
||||
{
|
||||
public CaptionButtonsMacOS()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MinimizeWindow(object sender, RoutedEventArgs e) {
|
||||
private void MinimizeWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = WindowState.Minimized;
|
||||
}
|
||||
}
|
||||
|
||||
private void MaximizeOrRestoreWindow(object sender, RoutedEventArgs e) {
|
||||
private void MaximizeOrRestoreWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var window = this.FindAncestorOfType<Window>();
|
||||
if (window != null) {
|
||||
if (window != null)
|
||||
{
|
||||
window.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +1,54 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class ChangeStatusIcon : Control {
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class ChangeStatusIcon : Control
|
||||
{
|
||||
private static readonly IBrush[] BACKGROUNDS = [
|
||||
Brushes.Transparent,
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(238, 160, 14), 0), new GradientStop(Color.FromRgb(228, 172, 67), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(47, 185, 47), 0), new GradientStop(Color.FromRgb(75, 189, 75), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Colors.Tomato, 0), new GradientStop(Color.FromRgb(252, 165, 150), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Colors.Orchid, 0), new GradientStop(Color.FromRgb(248, 161, 245), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(238, 160, 14), 0), new GradientStop(Color.FromRgb(228, 172, 67), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(238, 160, 14), 0), new GradientStop(Color.FromRgb(228, 172, 67), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
},
|
||||
new LinearGradientBrush {
|
||||
new LinearGradientBrush
|
||||
{
|
||||
GradientStops = new GradientStops() { new GradientStop(Color.FromRgb(47, 185, 47), 0), new GradientStop(Color.FromRgb(75, 189, 75), 1) },
|
||||
StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(0, 1, RelativeUnit.Relative),
|
||||
|
@ -50,7 +60,8 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<bool> IsWorkingCopyChangeProperty =
|
||||
AvaloniaProperty.Register<Avatar, bool>(nameof(IsWorkingCopyChange));
|
||||
|
||||
public bool IsWorkingCopyChange {
|
||||
public bool IsWorkingCopyChange
|
||||
{
|
||||
get => GetValue(IsWorkingCopyChangeProperty);
|
||||
set => SetValue(IsWorkingCopyChangeProperty, value);
|
||||
}
|
||||
|
@ -58,31 +69,40 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<Models.Change> ChangeProperty =
|
||||
AvaloniaProperty.Register<Avatar, Models.Change>(nameof(Change));
|
||||
|
||||
public Models.Change Change {
|
||||
public Models.Change Change
|
||||
{
|
||||
get => GetValue(ChangeProperty);
|
||||
set => SetValue(ChangeProperty, value);
|
||||
}
|
||||
|
||||
static ChangeStatusIcon() {
|
||||
static ChangeStatusIcon()
|
||||
{
|
||||
AffectsRender<ChangeStatusIcon>(IsWorkingCopyChangeProperty, ChangeProperty);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (Change == null || Bounds.Width <= 0) return;
|
||||
|
||||
var typeface = new Typeface("fonts:SourceGit#JetBrains Mono");
|
||||
|
||||
IBrush background = null;
|
||||
string indicator;
|
||||
if (IsWorkingCopyChange) {
|
||||
if (Change.IsConflit) {
|
||||
if (IsWorkingCopyChange)
|
||||
{
|
||||
if (Change.IsConflit)
|
||||
{
|
||||
background = Brushes.OrangeRed;
|
||||
indicator = "!";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
background = BACKGROUNDS[(int)Change.WorkTree];
|
||||
indicator = INDICATOR[(int)Change.WorkTree];
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
background = BACKGROUNDS[(int)Change.Index];
|
||||
indicator = INDICATOR[(int)Change.Index];
|
||||
}
|
||||
|
@ -101,4 +121,4 @@ namespace SourceGit.Views {
|
|||
context.DrawText(txt, textOrigin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +1,28 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class ChangeViewModeSwitcher : UserControl {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class ChangeViewModeSwitcher : UserControl
|
||||
{
|
||||
public static readonly StyledProperty<Models.ChangeViewMode> ViewModeProperty =
|
||||
AvaloniaProperty.Register<ChangeViewModeSwitcher, Models.ChangeViewMode>(nameof(ViewMode));
|
||||
|
||||
public Models.ChangeViewMode ViewMode {
|
||||
public Models.ChangeViewMode ViewMode
|
||||
{
|
||||
get => GetValue(ViewModeProperty);
|
||||
set => SetValue(ViewModeProperty, value);
|
||||
}
|
||||
|
||||
public ChangeViewModeSwitcher() {
|
||||
public ChangeViewModeSwitcher()
|
||||
{
|
||||
DataContext = this;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void SwitchMode(object param) {
|
||||
public void SwitchMode(object param)
|
||||
{
|
||||
ViewMode = (Models.ChangeViewMode)param;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Checkout : UserControl {
|
||||
public Checkout() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Checkout : UserControl
|
||||
{
|
||||
public Checkout()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CherryPick : UserControl {
|
||||
public CherryPick() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CherryPick : UserControl
|
||||
{
|
||||
public CherryPick()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Cleanup : UserControl {
|
||||
public Cleanup() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Cleanup : UserControl
|
||||
{
|
||||
public Cleanup()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class ClearStashes : UserControl {
|
||||
public ClearStashes() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class ClearStashes : UserControl
|
||||
{
|
||||
public ClearStashes()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,32 +2,39 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Clone : UserControl {
|
||||
public Clone() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Clone : UserControl
|
||||
{
|
||||
public Clone()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectParentFolder(object sender, RoutedEventArgs e) {
|
||||
private async void SelectParentFolder(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
var selected = await toplevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
txtParentFolder.Text = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e) {
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FilePickerOpenOptions() { AllowMultiple = false, FileTypeFilter = [new FilePickerFileType("SSHKey") { Patterns = ["*.*"] }] };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
var selected = await toplevel.StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
txtSSHKey.Text = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +1,22 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CommitBaseInfo : UserControl {
|
||||
public CommitBaseInfo() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CommitBaseInfo : UserControl
|
||||
{
|
||||
public CommitBaseInfo()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnParentSHAPressed(object sender, PointerPressedEventArgs e) {
|
||||
if (DataContext is ViewModels.CommitDetail detail) {
|
||||
private void OnParentSHAPressed(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail detail)
|
||||
{
|
||||
detail.NavigateTo((sender as Control).DataContext as string);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +1,27 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CommitChanges : UserControl {
|
||||
public CommitChanges() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CommitChanges : UserControl
|
||||
{
|
||||
public CommitChanges()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.IsVisible && datagrid.SelectedItem != null) {
|
||||
private void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.IsVisible && datagrid.SelectedItem != null)
|
||||
{
|
||||
datagrid.ScrollIntoView(datagrid.SelectedItem, null);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDataGridContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null) {
|
||||
private void OnDataGridContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null)
|
||||
{
|
||||
var detail = DataContext as ViewModels.CommitDetail;
|
||||
var menu = detail.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change);
|
||||
menu.Open(datagrid);
|
||||
|
@ -23,11 +30,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is TreeView view && view.SelectedItem != null) {
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView view && view.SelectedItem != null)
|
||||
{
|
||||
var detail = DataContext as ViewModels.CommitDetail;
|
||||
var node = view.SelectedItem as ViewModels.FileTreeNode;
|
||||
if (node != null && !node.IsFolder) {
|
||||
if (node != null && !node.IsFolder)
|
||||
{
|
||||
var menu = detail.CreateChangeContextMenu(node.Backend as Models.Change);
|
||||
menu.Open(view);
|
||||
}
|
||||
|
@ -36,4 +46,4 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CommitDetail : UserControl {
|
||||
public CommitDetail() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CommitDetail : UserControl
|
||||
{
|
||||
public CommitDetail()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnChangeListDoubleTapped(object sender, TappedEventArgs e) {
|
||||
if (DataContext is ViewModels.CommitDetail detail) {
|
||||
private void OnChangeListDoubleTapped(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail detail)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
detail.ActivePageIndex = 1;
|
||||
detail.SelectedChange = datagrid.SelectedItem as Models.Change;
|
||||
|
@ -16,10 +21,13 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnChangeListContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (DataContext is ViewModels.CommitDetail detail) {
|
||||
private void OnChangeListContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.CommitDetail detail)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
if (datagrid.SelectedItem == null) {
|
||||
if (datagrid.SelectedItem == null)
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
@ -30,4 +38,4 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CreateBranch : UserControl {
|
||||
public CreateBranch() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CreateBranch : UserControl
|
||||
{
|
||||
public CreateBranch()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CreateGroup : UserControl {
|
||||
public CreateGroup() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CreateGroup : UserControl
|
||||
{
|
||||
public CreateGroup()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class CreateTag : UserControl {
|
||||
public CreateTag() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class CreateTag : UserControl
|
||||
{
|
||||
public CreateTag()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DeleteBranch : UserControl {
|
||||
public DeleteBranch() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteBranch : UserControl
|
||||
{
|
||||
public DeleteBranch()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DeleteRemote : UserControl {
|
||||
public DeleteRemote() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteRemote : UserControl
|
||||
{
|
||||
public DeleteRemote()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DeleteRepositoryNode : UserControl {
|
||||
public DeleteRepositoryNode() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteRepositoryNode : UserControl
|
||||
{
|
||||
public DeleteRepositoryNode()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DeleteSubmodule : UserControl {
|
||||
public DeleteSubmodule() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteSubmodule : UserControl
|
||||
{
|
||||
public DeleteSubmodule()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DeleteTag : UserControl {
|
||||
public DeleteTag() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DeleteTag : UserControl
|
||||
{
|
||||
public DeleteTag()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DiffView : UserControl {
|
||||
public DiffView() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DiffView : UserControl
|
||||
{
|
||||
public DiffView()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Discard : UserControl {
|
||||
public Discard() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Discard : UserControl
|
||||
{
|
||||
public Discard()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class DropStash : UserControl {
|
||||
public DropStash() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class DropStash : UserControl
|
||||
{
|
||||
public DropStash()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,21 +2,26 @@ using Avalonia.Controls;
|
|||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class EditRemote : UserControl {
|
||||
public EditRemote() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class EditRemote : UserControl
|
||||
{
|
||||
public EditRemote()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e) {
|
||||
private async void SelectSSHKey(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FilePickerOpenOptions() { AllowMultiple = false, FileTypeFilter = [new FilePickerFileType("SSHKey") { Patterns = ["*.*"] }] };
|
||||
var toplevel = TopLevel.GetTopLevel(this);
|
||||
var selected = await toplevel.StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
txtSSHKey.Text = selected[0].Path.LocalPath;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class EditRepositoryNode : UserControl {
|
||||
public EditRepositoryNode() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class EditRepositoryNode : UserControl
|
||||
{
|
||||
public EditRepositoryNode()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class FastForwardWithoutCheckout : UserControl {
|
||||
public FastForwardWithoutCheckout() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class FastForwardWithoutCheckout : UserControl
|
||||
{
|
||||
public FastForwardWithoutCheckout()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Fetch : UserControl {
|
||||
public Fetch() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Fetch : UserControl
|
||||
{
|
||||
public Fetch()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +1,48 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class FileHistories : Window {
|
||||
public FileHistories() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class FileHistories : Window
|
||||
{
|
||||
public FileHistories()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e) {
|
||||
if (WindowState == WindowState.Maximized) {
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (WindowState == WindowState.Maximized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e) {
|
||||
if (sender is Border border) {
|
||||
if (border.Tag is WindowEdge edge) {
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is Border border)
|
||||
{
|
||||
if (border.Tag is WindowEdge edge)
|
||||
{
|
||||
BeginResizeDrag(edge, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void OnPressedSHA(object sender, PointerPressedEventArgs e) {
|
||||
if (sender is TextBlock block) {
|
||||
private void OnPressedSHA(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is TextBlock block)
|
||||
{
|
||||
var histories = DataContext as ViewModels.FileHistories;
|
||||
histories.NavigateToCommit(block.Text);
|
||||
}
|
||||
|
@ -37,4 +50,4 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class GitFlowFinish : UserControl {
|
||||
public GitFlowFinish() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class GitFlowFinish : UserControl
|
||||
{
|
||||
public GitFlowFinish()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class GitFlowStart : UserControl {
|
||||
public GitFlowStart() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class GitFlowStart : UserControl
|
||||
{
|
||||
public GitFlowStart()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,44 +1,56 @@
|
|||
using System;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.VisualTree;
|
||||
using System;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class LayoutableGrid : Grid {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class LayoutableGrid : Grid
|
||||
{
|
||||
public static readonly StyledProperty<bool> UseHorizontalProperty =
|
||||
AvaloniaProperty.Register<LayoutableGrid, bool>(nameof(UseHorizontal), false);
|
||||
|
||||
public bool UseHorizontal {
|
||||
public bool UseHorizontal
|
||||
{
|
||||
get => GetValue(UseHorizontalProperty);
|
||||
set => SetValue(UseHorizontalProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Grid);
|
||||
|
||||
static LayoutableGrid() {
|
||||
static LayoutableGrid()
|
||||
{
|
||||
UseHorizontalProperty.Changed.AddClassHandler<LayoutableGrid>((o, _) => o.RefreshLayout());
|
||||
}
|
||||
|
||||
public override void ApplyTemplate() {
|
||||
public override void ApplyTemplate()
|
||||
{
|
||||
base.ApplyTemplate();
|
||||
RefreshLayout();
|
||||
}
|
||||
|
||||
private void RefreshLayout() {
|
||||
if (UseHorizontal) {
|
||||
private void RefreshLayout()
|
||||
{
|
||||
if (UseHorizontal)
|
||||
{
|
||||
var rowSpan = RowDefinitions.Count;
|
||||
for (int i = 0; i < Children.Count; i++) {
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
var child = Children[i];
|
||||
child.SetValue(RowProperty, 0);
|
||||
child.SetValue(RowSpanProperty, rowSpan);
|
||||
child.SetValue(ColumnProperty, i);
|
||||
child.SetValue(ColumnSpanProperty, 1);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
var colSpan = ColumnDefinitions.Count;
|
||||
for (int i = 0; i < Children.Count; i++) {
|
||||
for (int i = 0; i < Children.Count; i++)
|
||||
{
|
||||
var child = Children[i];
|
||||
child.SetValue(RowProperty, i);
|
||||
child.SetValue(RowSpanProperty, 1);
|
||||
|
@ -49,7 +61,8 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
public class CommitGraph : Control {
|
||||
public class CommitGraph : Control
|
||||
{
|
||||
public static readonly Pen[] Pens = [
|
||||
new Pen(Brushes.Orange, 2),
|
||||
new Pen(Brushes.ForestGreen, 2),
|
||||
|
@ -64,7 +77,8 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<Models.CommitGraph> GraphProperty =
|
||||
AvaloniaProperty.Register<CommitGraph, Models.CommitGraph>(nameof(Graph));
|
||||
|
||||
public Models.CommitGraph Graph {
|
||||
public Models.CommitGraph Graph
|
||||
{
|
||||
get => GetValue(GraphProperty);
|
||||
set => SetValue(GraphProperty, value);
|
||||
}
|
||||
|
@ -72,24 +86,29 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<DataGrid> BindingDataGridProperty =
|
||||
AvaloniaProperty.Register<CommitGraph, DataGrid>(nameof(BindingDataGrid));
|
||||
|
||||
public DataGrid BindingDataGrid {
|
||||
public DataGrid BindingDataGrid
|
||||
{
|
||||
get => GetValue(BindingDataGridProperty);
|
||||
set => SetValue(BindingDataGridProperty, value);
|
||||
}
|
||||
|
||||
static CommitGraph() {
|
||||
static CommitGraph()
|
||||
{
|
||||
AffectsRender<CommitGraph>(BindingDataGridProperty, GraphProperty);
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) {
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property.Name == "ActualThemeVariant") {
|
||||
if (change.Property.Name == "ActualThemeVariant")
|
||||
{
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
|
||||
var graph = Graph;
|
||||
|
@ -102,9 +121,11 @@ namespace SourceGit.Views {
|
|||
// Find the content display offset Y of binding DataGrid.
|
||||
double rowHeight = grid.RowHeight;
|
||||
double startY = 0;
|
||||
foreach (var child in rowsPresenter.Children) {
|
||||
foreach (var child in rowsPresenter.Children)
|
||||
{
|
||||
var row = child as DataGridRow;
|
||||
if (row.IsVisible && row.Bounds.Top <= 0 && row.Bounds.Top > -rowHeight) {
|
||||
if (row.IsVisible && row.Bounds.Top <= 0 && row.Bounds.Top > -rowHeight)
|
||||
{
|
||||
var test = rowHeight * row.GetIndex() - row.Bounds.Top;
|
||||
if (startY < test) startY = test;
|
||||
}
|
||||
|
@ -123,10 +144,12 @@ namespace SourceGit.Views {
|
|||
|
||||
// Draw connect dots
|
||||
Brush dotFill = null;
|
||||
if (App.Current.TryGetResource("Brush.Contents", App.Current.ActualThemeVariant, out object res) && res is SolidColorBrush) {
|
||||
if (App.Current.TryGetResource("Brush.Contents", App.Current.ActualThemeVariant, out object res) && res is SolidColorBrush)
|
||||
{
|
||||
dotFill = res as SolidColorBrush;
|
||||
}
|
||||
foreach (var dot in graph.Dots) {
|
||||
foreach (var dot in graph.Dots)
|
||||
{
|
||||
if (dot.Center.Y < top) continue;
|
||||
if (dot.Center.Y > bottom) break;
|
||||
|
||||
|
@ -134,8 +157,10 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawCurves(DrawingContext context, double top, double bottom) {
|
||||
foreach (var line in Graph.Paths) {
|
||||
private void DrawCurves(DrawingContext context, double top, double bottom)
|
||||
{
|
||||
foreach (var line in Graph.Paths)
|
||||
{
|
||||
var last = line.Points[0];
|
||||
var size = line.Points.Count;
|
||||
|
||||
|
@ -144,38 +169,51 @@ namespace SourceGit.Views {
|
|||
|
||||
var geo = new StreamGeometry();
|
||||
var pen = Pens[line.Color];
|
||||
using (var ctx = geo.Open()) {
|
||||
using (var ctx = geo.Open())
|
||||
{
|
||||
var started = false;
|
||||
var ended = false;
|
||||
for (int i = 1; i < size; i++) {
|
||||
for (int i = 1; i < size; i++)
|
||||
{
|
||||
var cur = line.Points[i];
|
||||
if (cur.Y < top) {
|
||||
if (cur.Y < top)
|
||||
{
|
||||
last = cur;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
if (!started)
|
||||
{
|
||||
ctx.BeginFigure(last, false);
|
||||
started = true;
|
||||
}
|
||||
|
||||
if (cur.Y > bottom) {
|
||||
if (cur.Y > bottom)
|
||||
{
|
||||
cur = new Point(cur.X, bottom);
|
||||
ended = true;
|
||||
}
|
||||
|
||||
if (cur.X > last.X) {
|
||||
if (cur.X > last.X)
|
||||
{
|
||||
ctx.QuadraticBezierTo(new Point(cur.X, last.Y), cur);
|
||||
} else if (cur.X < last.X) {
|
||||
if (i < size - 1) {
|
||||
}
|
||||
else if (cur.X < last.X)
|
||||
{
|
||||
if (i < size - 1)
|
||||
{
|
||||
var midY = (last.Y + cur.Y) / 2;
|
||||
var midX = (last.X + cur.X) / 2;
|
||||
ctx.QuadraticBezierTo(new Point(last.X, midY), new Point(midX, midY));
|
||||
ctx.QuadraticBezierTo(new Point(cur.X, midY), cur);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.QuadraticBezierTo(new Point(last.X, cur.Y), cur);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.LineTo(cur);
|
||||
}
|
||||
|
||||
|
@ -187,12 +225,14 @@ namespace SourceGit.Views {
|
|||
context.DrawGeometry(null, pen, geo);
|
||||
}
|
||||
|
||||
foreach (var link in Graph.Links) {
|
||||
foreach (var link in Graph.Links)
|
||||
{
|
||||
if (link.End.Y < top) continue;
|
||||
if (link.Start.Y > bottom) break;
|
||||
|
||||
var geo = new StreamGeometry();
|
||||
using (var ctx = geo.Open()) {
|
||||
using (var ctx = geo.Open())
|
||||
{
|
||||
ctx.BeginFigure(link.Start, false);
|
||||
ctx.QuadraticBezierTo(link.Control, link.End);
|
||||
}
|
||||
|
@ -202,32 +242,40 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
public partial class Histories : UserControl {
|
||||
public Histories() {
|
||||
public partial class Histories : UserControl
|
||||
{
|
||||
public Histories()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnCommitDataGridLayoutUpdated(object sender, EventArgs e) {
|
||||
private void OnCommitDataGridLayoutUpdated(object sender, EventArgs e)
|
||||
{
|
||||
commitGraph.InvalidateVisual();
|
||||
}
|
||||
|
||||
private void OnCommitDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (DataContext is ViewModels.Histories histories) {
|
||||
private void OnCommitDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Histories histories)
|
||||
{
|
||||
histories.Select(commitDataGrid.SelectedItems);
|
||||
|
||||
if (histories.DetailContext is ViewModels.CommitDetail detail) {
|
||||
if (histories.DetailContext is ViewModels.CommitDetail detail)
|
||||
{
|
||||
commitDataGrid.ScrollIntoView(detail.Commit, null);
|
||||
}
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnCommitDataGridContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (DataContext is ViewModels.Histories histories) {
|
||||
private void OnCommitDataGridContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Histories histories)
|
||||
{
|
||||
var menu = histories.MakeContextMenu();
|
||||
menu?.Open(sender as Control);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,18 +2,23 @@ using Avalonia.Controls;
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Hotkeys : Window {
|
||||
public Hotkeys() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Hotkeys : Window
|
||||
{
|
||||
public Hotkeys()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Init : UserControl {
|
||||
public Init() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Init : UserControl
|
||||
{
|
||||
public Init()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class InitGitFlow : UserControl {
|
||||
public InitGitFlow() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class InitGitFlow : UserControl
|
||||
{
|
||||
public InitGitFlow()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +1,90 @@
|
|||
using System;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using System;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class LauncherTab : Grid {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class LauncherTab : Grid
|
||||
{
|
||||
public static readonly StyledProperty<bool> UseFixedTabWidthProperty =
|
||||
AvaloniaProperty.Register<LauncherTab, bool>(nameof(UseFixedTabWidth), false);
|
||||
|
||||
public bool UseFixedTabWidth {
|
||||
public bool UseFixedTabWidth
|
||||
{
|
||||
get => GetValue(UseFixedTabWidthProperty);
|
||||
set => SetValue(UseFixedTabWidthProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Grid);
|
||||
|
||||
static LauncherTab() {
|
||||
UseFixedTabWidthProperty.Changed.AddClassHandler<LauncherTab>((tab, ev) => {
|
||||
static LauncherTab()
|
||||
{
|
||||
UseFixedTabWidthProperty.Changed.AddClassHandler<LauncherTab>((tab, ev) =>
|
||||
{
|
||||
tab.Width = tab.UseFixedTabWidth ? 200.0 : double.NaN;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public class LauncherBody : Border {
|
||||
public class LauncherBody : Border
|
||||
{
|
||||
public static readonly StyledProperty<object> DataProperty =
|
||||
AvaloniaProperty.Register<LauncherBody, object>(nameof(Data), false);
|
||||
|
||||
public object Data {
|
||||
public object Data
|
||||
{
|
||||
get => GetValue(DataProperty);
|
||||
set => SetValue(DataProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Border);
|
||||
|
||||
static LauncherBody() {
|
||||
DataProperty.Changed.AddClassHandler<LauncherBody>((body, ev) => {
|
||||
static LauncherBody()
|
||||
{
|
||||
DataProperty.Changed.AddClassHandler<LauncherBody>((body, ev) =>
|
||||
{
|
||||
var data = body.Data;
|
||||
|
||||
if (data == null) {
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
body.Child = null;
|
||||
} else if (data is ViewModels.Welcome) {
|
||||
}
|
||||
else if (data is ViewModels.Welcome)
|
||||
{
|
||||
body.Child = new Welcome { DataContext = data };
|
||||
} else if (data is ViewModels.Repository) {
|
||||
}
|
||||
else if (data is ViewModels.Repository)
|
||||
{
|
||||
body.Child = new Repository { DataContext = data };
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
body.Child = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public partial class Launcher : Window, Models.INotificationReceiver {
|
||||
public Launcher() {
|
||||
public partial class Launcher : Window, Models.INotificationReceiver
|
||||
{
|
||||
public Launcher()
|
||||
{
|
||||
DataContext = new ViewModels.Launcher();
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public void OnReceiveNotification(string ctx, Models.Notification notice) {
|
||||
if (DataContext is ViewModels.Launcher vm) {
|
||||
foreach (var page in vm.Pages) {
|
||||
public void OnReceiveNotification(string ctx, Models.Notification notice)
|
||||
{
|
||||
if (DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
foreach (var page in vm.Pages)
|
||||
{
|
||||
var pageId = page.Node.Id.Replace("\\", "/");
|
||||
if (pageId == ctx) {
|
||||
if (pageId == ctx)
|
||||
{
|
||||
page.Notifications.Add(notice);
|
||||
return;
|
||||
}
|
||||
|
@ -71,37 +94,53 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
protected override void OnKeyDown(KeyEventArgs e) {
|
||||
protected override void OnKeyDown(KeyEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.Launcher;
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Control)) {
|
||||
if (e.Key == Key.W) {
|
||||
if (e.KeyModifiers.HasFlag(KeyModifiers.Control))
|
||||
{
|
||||
if (e.Key == Key.W)
|
||||
{
|
||||
vm.CloseTab(null);
|
||||
e.Handled = true;
|
||||
return;
|
||||
} else if (e.Key == Key.Tab) {
|
||||
}
|
||||
else if (e.Key == Key.Tab)
|
||||
{
|
||||
vm.GotoNextTab();
|
||||
e.Handled = true;
|
||||
return;
|
||||
} else if (vm.ActivePage.Data is ViewModels.Repository repo) {
|
||||
if (e.Key == Key.D1 || e.Key == Key.NumPad1) {
|
||||
}
|
||||
else if (vm.ActivePage.Data is ViewModels.Repository repo)
|
||||
{
|
||||
if (e.Key == Key.D1 || e.Key == Key.NumPad1)
|
||||
{
|
||||
repo.SelectedViewIndex = 0;
|
||||
e.Handled = true;
|
||||
return;
|
||||
} else if (e.Key == Key.D2 || e.Key == Key.NumPad2) {
|
||||
}
|
||||
else if (e.Key == Key.D2 || e.Key == Key.NumPad2)
|
||||
{
|
||||
repo.SelectedViewIndex = 1;
|
||||
e.Handled = true;
|
||||
return;
|
||||
} else if (e.Key == Key.D3 || e.Key == Key.NumPad3) {
|
||||
}
|
||||
else if (e.Key == Key.D3 || e.Key == Key.NumPad3)
|
||||
{
|
||||
repo.SelectedViewIndex = 2;
|
||||
e.Handled = true;
|
||||
return;
|
||||
} else if (e.Key == Key.F) {
|
||||
}
|
||||
else if (e.Key == Key.F)
|
||||
{
|
||||
repo.IsSearching = !repo.IsSearching;
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (e.Key == Key.Escape) {
|
||||
}
|
||||
}
|
||||
else if (e.Key == Key.Escape)
|
||||
{
|
||||
vm.ActivePage.CancelPopup();
|
||||
e.Handled = true;
|
||||
return;
|
||||
|
@ -110,84 +149,107 @@ namespace SourceGit.Views {
|
|||
base.OnKeyDown(e);
|
||||
}
|
||||
|
||||
protected override void OnClosing(WindowClosingEventArgs e) {
|
||||
protected override void OnClosing(WindowClosingEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.Launcher;
|
||||
vm.Quit();
|
||||
|
||||
base.OnClosing(e);
|
||||
}
|
||||
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e) {
|
||||
if (WindowState == WindowState.Maximized) {
|
||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (WindowState == WindowState.Maximized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e) {
|
||||
if (sender is Border border) {
|
||||
if (border.Tag is WindowEdge edge) {
|
||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is Border border)
|
||||
{
|
||||
if (border.Tag is WindowEdge edge)
|
||||
{
|
||||
BeginResizeDrag(edge, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void ScrollTabs(object sender, PointerWheelEventArgs e) {
|
||||
if (!e.KeyModifiers.HasFlag(KeyModifiers.Shift)) {
|
||||
private void ScrollTabs(object sender, PointerWheelEventArgs e)
|
||||
{
|
||||
if (!e.KeyModifiers.HasFlag(KeyModifiers.Shift))
|
||||
{
|
||||
if (e.Delta.Y < 0) launcherTabsScroller.LineRight();
|
||||
else launcherTabsScroller.LineLeft();
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void ScrollTabsLeft(object sender, RoutedEventArgs e) {
|
||||
private void ScrollTabsLeft(object sender, RoutedEventArgs e)
|
||||
{
|
||||
launcherTabsScroller.LineLeft();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void ScrollTabsRight(object sender, RoutedEventArgs e) {
|
||||
private void ScrollTabsRight(object sender, RoutedEventArgs e)
|
||||
{
|
||||
launcherTabsScroller.LineRight();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateScrollIndicator(object sender, SizeChangedEventArgs e) {
|
||||
if (launcherTabsBar.Bounds.Width > launcherTabsContainer.Bounds.Width) {
|
||||
private void UpdateScrollIndicator(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (launcherTabsBar.Bounds.Width > launcherTabsContainer.Bounds.Width)
|
||||
{
|
||||
leftScrollIndicator.IsVisible = true;
|
||||
rightScrollIndicator.IsVisible = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
leftScrollIndicator.IsVisible = false;
|
||||
rightScrollIndicator.IsVisible = false;
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void SetupDragAndDrop(object sender, RoutedEventArgs e) {
|
||||
if (sender is Border border) {
|
||||
private void SetupDragAndDrop(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Border border)
|
||||
{
|
||||
DragDrop.SetAllowDrop(border, true);
|
||||
border.AddHandler(DragDrop.DropEvent, DropTab);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPointerPressedTab(object sender, PointerPressedEventArgs e) {
|
||||
private void OnPointerPressedTab(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
_pressedTab = true;
|
||||
_startDrag = false;
|
||||
_pressedTabPosition = e.GetPosition(sender as Border);
|
||||
}
|
||||
|
||||
private void OnPointerReleasedTab(object sender, PointerReleasedEventArgs e) {
|
||||
private void OnPointerReleasedTab(object sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
_pressedTab = false;
|
||||
_startDrag = false;
|
||||
}
|
||||
|
||||
private void OnPointerMovedOverTab(object sender, PointerEventArgs e) {
|
||||
if (_pressedTab && !_startDrag && sender is Border border) {
|
||||
private void OnPointerMovedOverTab(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (_pressedTab && !_startDrag && sender is Border border)
|
||||
{
|
||||
var delta = e.GetPosition(border) - _pressedTabPosition;
|
||||
var sizeSquired = delta.X * delta.X + delta.Y * delta.Y;
|
||||
if (sizeSquired < 64) return;
|
||||
|
@ -201,11 +263,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void DropTab(object sender, DragEventArgs e) {
|
||||
if (e.Data.Contains("MovedTab") && sender is Border border) {
|
||||
private void DropTab(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.Contains("MovedTab") && sender is Border border)
|
||||
{
|
||||
var to = border.DataContext as ViewModels.LauncherPage;
|
||||
var moved = e.Data.Get("MovedTab") as ViewModels.LauncherPage;
|
||||
if (to != null && moved != null && to != moved && DataContext is ViewModels.Launcher vm) {
|
||||
if (to != null && moved != null && to != moved && DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
vm.MoveTab(moved, to);
|
||||
}
|
||||
}
|
||||
|
@ -215,37 +280,45 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPopupSure(object sender, RoutedEventArgs e) {
|
||||
if (DataContext is ViewModels.Launcher vm) {
|
||||
private void OnPopupSure(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
vm.ActivePage.ProcessPopup();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPopupCancel(object sender, RoutedEventArgs e) {
|
||||
if (DataContext is ViewModels.Launcher vm) {
|
||||
private void OnPopupCancel(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Launcher vm)
|
||||
{
|
||||
vm.ActivePage.CancelPopup();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPopupCancelByClickMask(object sender, PointerPressedEventArgs e) {
|
||||
private void OnPopupCancelByClickMask(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
OnPopupCancel(sender, e);
|
||||
}
|
||||
|
||||
private async void OpenPreference(object sender, RoutedEventArgs e) {
|
||||
private async void OpenPreference(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new Preference();
|
||||
await dialog.ShowDialog(this);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OpenHotkeys(object sender, RoutedEventArgs e) {
|
||||
private async void OpenHotkeys(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new Hotkeys();
|
||||
await dialog.ShowDialog(this);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OpenAboutDialog(object sender, RoutedEventArgs e) {
|
||||
private async void OpenAboutDialog(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var dialog = new About();
|
||||
await dialog.ShowDialog(this);
|
||||
e.Handled = true;
|
||||
|
@ -253,6 +326,6 @@ namespace SourceGit.Views {
|
|||
|
||||
private bool _pressedTab = false;
|
||||
private Point _pressedTabPosition = new Point();
|
||||
private bool _startDrag = false;
|
||||
private bool _startDrag = false;
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Merge : UserControl {
|
||||
public Merge() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Merge : UserControl
|
||||
{
|
||||
public Merge()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,16 +1,20 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class NameHighlightedTextBlock : Control {
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class NameHighlightedTextBlock : Control
|
||||
{
|
||||
|
||||
public static readonly StyledProperty<string> TextProperty =
|
||||
AvaloniaProperty.Register<NameHighlightedTextBlock, string>(nameof(Text));
|
||||
|
||||
public string Text {
|
||||
public string Text
|
||||
{
|
||||
get => GetValue(TextProperty);
|
||||
set => SetValue(TextProperty, value);
|
||||
}
|
||||
|
@ -18,7 +22,8 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<FontFamily> FontFamilyProperty =
|
||||
TextBlock.FontFamilyProperty.AddOwner<NameHighlightedTextBlock>();
|
||||
|
||||
public FontFamily FontFamily {
|
||||
public FontFamily FontFamily
|
||||
{
|
||||
get => GetValue(FontFamilyProperty);
|
||||
set => SetValue(FontFamilyProperty, value);
|
||||
}
|
||||
|
@ -26,7 +31,8 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<double> FontSizeProperty =
|
||||
TextBlock.FontSizeProperty.AddOwner<NameHighlightedTextBlock>();
|
||||
|
||||
public double FontSize {
|
||||
public double FontSize
|
||||
{
|
||||
get => GetValue(FontSizeProperty);
|
||||
set => SetValue(FontSizeProperty, value);
|
||||
}
|
||||
|
@ -34,21 +40,25 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<IBrush> ForegroundProperty =
|
||||
TextBlock.ForegroundProperty.AddOwner<NameHighlightedTextBlock>();
|
||||
|
||||
public IBrush Foreground {
|
||||
public IBrush Foreground
|
||||
{
|
||||
get => GetValue(ForegroundProperty);
|
||||
set => SetValue(ForegroundProperty, value);
|
||||
}
|
||||
|
||||
static NameHighlightedTextBlock() {
|
||||
static NameHighlightedTextBlock()
|
||||
{
|
||||
AffectsMeasure<NameHighlightedTextBlock>(TextProperty);
|
||||
}
|
||||
|
||||
public NameHighlightedTextBlock(string nameKey, params object[] args) {
|
||||
public NameHighlightedTextBlock(string nameKey, params object[] args)
|
||||
{
|
||||
Text = App.Text(nameKey, args);
|
||||
VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center;
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize) {
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var text = Text;
|
||||
if (string.IsNullOrEmpty(text)) return base.MeasureOverride(availableSize);
|
||||
|
||||
|
@ -64,7 +74,8 @@ namespace SourceGit.Views {
|
|||
return new Size(formatted.Width - 16, formatted.Height);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
var text = Text;
|
||||
if (string.IsNullOrEmpty(text)) return;
|
||||
|
||||
|
@ -75,8 +86,10 @@ namespace SourceGit.Views {
|
|||
|
||||
var parts = text.Split('$', StringSplitOptions.None);
|
||||
var isName = false;
|
||||
foreach (var part in parts) {
|
||||
if (string.IsNullOrEmpty(part)) {
|
||||
foreach (var part in parts)
|
||||
{
|
||||
if (string.IsNullOrEmpty(part))
|
||||
{
|
||||
isName = !isName;
|
||||
continue;
|
||||
}
|
||||
|
@ -90,13 +103,16 @@ namespace SourceGit.Views {
|
|||
FontSize,
|
||||
Foreground);
|
||||
|
||||
if (isName) {
|
||||
if (isName)
|
||||
{
|
||||
var lineY = formatted.Baseline + 2;
|
||||
offsetX += 4;
|
||||
context.DrawText(formatted, new Point(offsetX, 0));
|
||||
context.DrawLine(underlinePen, new Point(offsetX, lineY), new Point(offsetX + formatted.Width, lineY));
|
||||
offsetX += formatted.Width + 4;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DrawText(formatted, new Point(offsetX, 0));
|
||||
offsetX += formatted.Width;
|
||||
}
|
||||
|
@ -105,4 +121,4 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +1,59 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Preference : Window {
|
||||
public string DefaultUser {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Preference : Window
|
||||
{
|
||||
public string DefaultUser
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string DefaultEmail {
|
||||
public string DefaultEmail
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Models.CRLFMode CRLFMode {
|
||||
public Models.CRLFMode CRLFMode
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public bool EnableGPGSigning {
|
||||
public bool EnableGPGSigning
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string GPGExecutableFile {
|
||||
public string GPGExecutableFile
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public string GPGUserKey {
|
||||
public string GPGUserKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Preference() {
|
||||
public Preference()
|
||||
{
|
||||
var pref = ViewModels.Preference.Instance;
|
||||
DataContext = pref;
|
||||
|
||||
var ver = string.Empty;
|
||||
if (pref.IsGitConfigured) {
|
||||
if (pref.IsGitConfigured)
|
||||
{
|
||||
var config = new Commands.Config(null).ListAll();
|
||||
|
||||
if (config.ContainsKey("user.name")) DefaultUser = config["user.name"];
|
||||
|
@ -59,11 +70,13 @@ namespace SourceGit.Views {
|
|||
txtVersion.Text = ver;
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var cmd = new Commands.Config(null);
|
||||
|
||||
var config = cmd.ListAll();
|
||||
|
@ -78,21 +91,24 @@ namespace SourceGit.Views {
|
|||
if (DefaultEmail != oldEmail) cmd.Set("user.email", DefaultEmail);
|
||||
if (GPGUserKey != oldGPGSignKey) cmd.Set("user.signingkey", GPGUserKey);
|
||||
if (CRLFMode != null && CRLFMode.Value != oldCRLF) cmd.Set("core.autocrlf", CRLFMode.Value);
|
||||
if (EnableGPGSigning != (oldGPGSignEnable == "true")) cmd.Set("commit.gpgsign", EnableGPGSigning ? "true" : "false");
|
||||
if (EnableGPGSigning != (oldGPGSignEnable == "true")) cmd.Set("commit.gpgsign", EnableGPGSigning ? "true" : "false");
|
||||
if (GPGExecutableFile != oldGPGExec) cmd.Set("gpg.program", GPGExecutableFile);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
private async void SelectGitExecutable(object sender, RoutedEventArgs e) {
|
||||
private async void SelectGitExecutable(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var pattern = OperatingSystem.IsWindows() ? "git.exe" : "git";
|
||||
var options = new FilePickerOpenOptions() {
|
||||
FileTypeFilter = [new FilePickerFileType("Git Executable") { Patterns = [ pattern ] }],
|
||||
var options = new FilePickerOpenOptions()
|
||||
{
|
||||
FileTypeFilter = [new FilePickerFileType("Git Executable") { Patterns = [pattern] }],
|
||||
AllowMultiple = false,
|
||||
};
|
||||
|
||||
var selected = await StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
ViewModels.Preference.Instance.GitInstallPath = selected[0].Path.LocalPath;
|
||||
txtVersion.Text = new Commands.Version().Query();
|
||||
}
|
||||
|
@ -100,45 +116,54 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void SelectDefaultCloneDir(object sender, RoutedEventArgs e) {
|
||||
private async void SelectDefaultCloneDir(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
var selected = await StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
ViewModels.Preference.Instance.GitDefaultCloneDir = selected[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
|
||||
private async void SelectGPGExecutable(object sender, RoutedEventArgs e) {
|
||||
private async void SelectGPGExecutable(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var pattern = OperatingSystem.IsWindows() ? "gpg.exe" : "gpg";
|
||||
var options = new FilePickerOpenOptions() {
|
||||
FileTypeFilter = [new FilePickerFileType("GPG Executable") { Patterns = [ pattern ] }],
|
||||
var options = new FilePickerOpenOptions()
|
||||
{
|
||||
FileTypeFilter = [new FilePickerFileType("GPG Executable") { Patterns = [pattern] }],
|
||||
AllowMultiple = false,
|
||||
};
|
||||
|
||||
var selected = await StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
GPGExecutableFile = selected[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
|
||||
private async void SelectExternalMergeTool(object sender, RoutedEventArgs e) {
|
||||
private async void SelectExternalMergeTool(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var type = ViewModels.Preference.Instance.ExternalMergeToolType;
|
||||
if (type < 0 || type >= Models.ExternalMergeTools.Supported.Count) {
|
||||
if (type < 0 || type >= Models.ExternalMergeTools.Supported.Count)
|
||||
{
|
||||
ViewModels.Preference.Instance.ExternalMergeToolType = 0;
|
||||
type = 0;
|
||||
}
|
||||
|
||||
var tool = Models.ExternalMergeTools.Supported[type];
|
||||
var pattern = Path.GetFileName(tool.Exec);
|
||||
var options = new FilePickerOpenOptions() {
|
||||
var options = new FilePickerOpenOptions()
|
||||
{
|
||||
FileTypeFilter = [new FilePickerFileType(tool.Name) { Patterns = [pattern] }],
|
||||
AllowMultiple = false,
|
||||
};
|
||||
|
||||
var selected = await StorageProvider.OpenFilePickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
ViewModels.Preference.Instance.ExternalMergeToolPath = selected[0].Path.LocalPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class PruneRemote : UserControl {
|
||||
public PruneRemote() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class PruneRemote : UserControl
|
||||
{
|
||||
public PruneRemote()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Pull : UserControl {
|
||||
public Pull() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Pull : UserControl
|
||||
{
|
||||
public Pull()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Push : UserControl {
|
||||
public Push() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Push : UserControl
|
||||
{
|
||||
public Push()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class PushTag : UserControl {
|
||||
public PushTag() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class PushTag : UserControl
|
||||
{
|
||||
public PushTag()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Rebase : UserControl {
|
||||
public Rebase() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Rebase : UserControl
|
||||
{
|
||||
public Rebase()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class RenameBranch : UserControl {
|
||||
public RenameBranch() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class RenameBranch : UserControl
|
||||
{
|
||||
public RenameBranch()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +1,53 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using SourceGit.ViewModels;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class RepositorySubView : Border {
|
||||
using SourceGit.ViewModels;
|
||||
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class RepositorySubView : Border
|
||||
{
|
||||
public static readonly StyledProperty<object> DataProperty =
|
||||
AvaloniaProperty.Register<RepositorySubView, object>(nameof(Data), false);
|
||||
|
||||
public object Data {
|
||||
public object Data
|
||||
{
|
||||
get => GetValue(DataProperty);
|
||||
set => SetValue(DataProperty, value);
|
||||
}
|
||||
|
||||
protected override Type StyleKeyOverride => typeof(Border);
|
||||
|
||||
static RepositorySubView() {
|
||||
DataProperty.Changed.AddClassHandler<RepositorySubView>((view, ev) => {
|
||||
static RepositorySubView()
|
||||
{
|
||||
DataProperty.Changed.AddClassHandler<RepositorySubView>((view, ev) =>
|
||||
{
|
||||
var data = view.Data;
|
||||
|
||||
if (data == null) {
|
||||
if (data == null)
|
||||
{
|
||||
view.Child = null;
|
||||
} else if (data is ViewModels.Histories) {
|
||||
}
|
||||
else if (data is ViewModels.Histories)
|
||||
{
|
||||
view.Child = new Histories { DataContext = data };
|
||||
} else if (data is ViewModels.WorkingCopy) {
|
||||
}
|
||||
else if (data is ViewModels.WorkingCopy)
|
||||
{
|
||||
view.Child = new WorkingCopy { DataContext = data };
|
||||
} else if (data is ViewModels.StashesPage) {
|
||||
}
|
||||
else if (data is ViewModels.StashesPage)
|
||||
{
|
||||
view.Child = new StashesPage { DataContext = data };
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
view.Child = null;
|
||||
}
|
||||
|
||||
|
@ -40,73 +56,95 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
public partial class Repository : UserControl {
|
||||
public Repository() {
|
||||
public partial class Repository : UserControl
|
||||
{
|
||||
public Repository()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnLocalBranchTreeLostFocus(object sender, RoutedEventArgs e) {
|
||||
private void OnLocalBranchTreeLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree) tree.UnselectAll();
|
||||
}
|
||||
|
||||
private void OnRemoteBranchTreeLostFocus(object sender, RoutedEventArgs e) {
|
||||
private void OnRemoteBranchTreeLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree) tree.UnselectAll();
|
||||
}
|
||||
|
||||
private void OnTagDataGridLostFocus(object sender, RoutedEventArgs e) {
|
||||
private void OnTagDataGridLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid) datagrid.SelectedItem = null;
|
||||
}
|
||||
|
||||
private void OnLocalBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is TreeView tree && tree.SelectedItem != null) {
|
||||
private void OnLocalBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree && tree.SelectedItem != null)
|
||||
{
|
||||
remoteBranchTree.UnselectAll();
|
||||
|
||||
var node = tree.SelectedItem as Models.BranchTreeNode;
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo) {
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRemoteBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is TreeView tree && tree.SelectedItem != null) {
|
||||
private void OnRemoteBranchTreeSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView tree && tree.SelectedItem != null)
|
||||
{
|
||||
localBranchTree.UnselectAll();
|
||||
|
||||
var node = tree.SelectedItem as Models.BranchTreeNode;
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo) {
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTagDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null) {
|
||||
private void OnTagDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null)
|
||||
{
|
||||
var tag = datagrid.SelectedItem as Models.Tag;
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.NavigateToCommit(tag.SHA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchCommitPanelPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) {
|
||||
private void OnSearchCommitPanelPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
var grid = sender as Grid;
|
||||
if (e.Property == IsVisibleProperty && grid.IsVisible) {
|
||||
if (e.Property == IsVisibleProperty && grid.IsVisible)
|
||||
{
|
||||
txtSearchCommitsBox.Focus();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchKeyDown(object sender, KeyEventArgs e) {
|
||||
if (e.Key == Key.Enter) {
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
private void OnSearchKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.StartSearchCommits();
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSearchResultDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null) {
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
private void OnSearchResultDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var commit = datagrid.SelectedItem as Models.Commit;
|
||||
repo.NavigateToCommit(commit.SHA);
|
||||
}
|
||||
|
@ -114,18 +152,25 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnToggleFilter(object sender, RoutedEventArgs e) {
|
||||
if (sender is ToggleButton toggle) {
|
||||
private void OnToggleFilter(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is ToggleButton toggle)
|
||||
{
|
||||
var filter = string.Empty;
|
||||
if (toggle.DataContext is Models.BranchTreeNode node) {
|
||||
if (node.IsBranch) {
|
||||
if (toggle.DataContext is Models.BranchTreeNode node)
|
||||
{
|
||||
if (node.IsBranch)
|
||||
{
|
||||
filter = (node.Backend as Models.Branch).FullName;
|
||||
}
|
||||
} else if (toggle.DataContext is Models.Tag tag) {
|
||||
}
|
||||
else if (toggle.DataContext is Models.Tag tag)
|
||||
{
|
||||
filter = tag.Name;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filter) && DataContext is ViewModels.Repository repo) {
|
||||
if (!string.IsNullOrEmpty(filter) && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.UpdateFilter(filter, toggle.IsChecked == true);
|
||||
}
|
||||
}
|
||||
|
@ -133,11 +178,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnLocalBranchContextMenuRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnLocalBranchContextMenuRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
remoteBranchTree.UnselectAll();
|
||||
|
||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node) {
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo) {
|
||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node)
|
||||
{
|
||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForLocalBranch(node.Backend as Models.Branch);
|
||||
if (menu != null) menu.Open(grid);
|
||||
}
|
||||
|
@ -146,14 +194,19 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnRemoteBranchContextMenuRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnRemoteBranchContextMenuRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
localBranchTree.UnselectAll();
|
||||
|
||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node && DataContext is ViewModels.Repository repo) {
|
||||
if (node.IsRemote) {
|
||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
if (node.IsRemote)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForRemote(node.Backend as Models.Remote);
|
||||
if (menu != null) menu.Open(grid);
|
||||
} else if (node.IsBranch) {
|
||||
}
|
||||
else if (node.IsBranch)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForRemoteBranch(node.Backend as Models.Branch);
|
||||
if (menu != null) menu.Open(grid);
|
||||
}
|
||||
|
@ -162,8 +215,10 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTagContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo) {
|
||||
private void OnTagContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var tag = datagrid.SelectedItem as Models.Tag;
|
||||
var menu = repo.CreateContextMenuForTag(tag);
|
||||
if (menu != null) menu.Open(datagrid);
|
||||
|
@ -172,8 +227,10 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSubmoduleContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo) {
|
||||
private void OnSubmoduleContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var submodule = datagrid.SelectedItem as string;
|
||||
var menu = repo.CreateContextMenuForSubmodule(submodule);
|
||||
if (menu != null) menu.Open(datagrid);
|
||||
|
@ -182,8 +239,10 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OpenGitFlowMenu(object sender, RoutedEventArgs e) {
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
private void OpenGitFlowMenu(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var menu = repo.CreateContextMenuForGitFlow();
|
||||
if (menu != null) menu.Open(sender as Button);
|
||||
}
|
||||
|
@ -191,8 +250,10 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void UpdateSubmodules(object sender, RoutedEventArgs e) {
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
private async void UpdateSubmodules(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
repo.SetWatcherEnabled(false);
|
||||
iconSubmoduleUpdate.Classes.Add("rotating");
|
||||
await Task.Run(() => new Commands.Submodule(repo.FullPath).Update());
|
||||
|
@ -203,12 +264,15 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDoubleTappedLocalBranchNode(object sender, TappedEventArgs e) {
|
||||
private void OnDoubleTappedLocalBranchNode(object sender, TappedEventArgs e)
|
||||
{
|
||||
if (!PopupHost.CanCreatePopup()) return;
|
||||
|
||||
if (sender is Grid grid && DataContext is ViewModels.Repository repo) {
|
||||
if (sender is Grid grid && DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var node = grid.DataContext as Models.BranchTreeNode;
|
||||
if (node != null && node.IsBranch) {
|
||||
if (node != null && node.IsBranch)
|
||||
{
|
||||
var branch = node.Backend as Models.Branch;
|
||||
if (branch.IsCurrent) return;
|
||||
|
||||
|
@ -218,13 +282,14 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
private async void OpenStatistics(object sender, RoutedEventArgs e) {
|
||||
if (DataContext is ViewModels.Repository repo) {
|
||||
private async void OpenStatistics(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.Repository repo)
|
||||
{
|
||||
var dialog = new Statistics() { DataContext = new ViewModels.Statistics(repo.FullPath) };
|
||||
await dialog.ShowDialog(TopLevel.GetTopLevel(this) as Window);
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class RepositoryConfigure : UserControl {
|
||||
public RepositoryConfigure() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class RepositoryConfigure : UserControl
|
||||
{
|
||||
public RepositoryConfigure()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Reset : UserControl {
|
||||
public Reset() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Reset : UserControl
|
||||
{
|
||||
public Reset()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Revert : UserControl {
|
||||
public Revert() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Revert : UserControl
|
||||
{
|
||||
public Revert()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,21 +1,28 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class RevisionCompare : UserControl {
|
||||
public RevisionCompare() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class RevisionCompare : UserControl
|
||||
{
|
||||
public RevisionCompare()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.IsVisible) {
|
||||
private void OnDataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.IsVisible)
|
||||
{
|
||||
datagrid.ScrollIntoView(datagrid.SelectedItem, null);
|
||||
}
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnDataGridContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null) {
|
||||
private void OnDataGridContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is DataGrid datagrid && datagrid.SelectedItem != null)
|
||||
{
|
||||
var compare = DataContext as ViewModels.RevisionCompare;
|
||||
var menu = compare.CreateChangeContextMenu(datagrid.SelectedItem as Models.Change);
|
||||
menu.Open(datagrid);
|
||||
|
@ -24,11 +31,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
if (sender is TreeView view && view.SelectedItem != null) {
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView view && view.SelectedItem != null)
|
||||
{
|
||||
var compare = DataContext as ViewModels.RevisionCompare;
|
||||
var node = view.SelectedItem as ViewModels.FileTreeNode;
|
||||
if (node != null && !node.IsFolder) {
|
||||
if (node != null && !node.IsFolder)
|
||||
{
|
||||
var menu = compare.CreateChangeContextMenu(node.Backend as Models.Change);
|
||||
menu.Open(view);
|
||||
}
|
||||
|
@ -37,8 +47,10 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnPressedSHA(object sender, PointerPressedEventArgs e) {
|
||||
if (sender is TextBlock block) {
|
||||
private void OnPressedSHA(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is TextBlock block)
|
||||
{
|
||||
var compare = DataContext as ViewModels.RevisionCompare;
|
||||
compare.NavigateTo(block.Text);
|
||||
}
|
||||
|
@ -46,4 +58,4 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,23 +1,29 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
|
||||
using AvaloniaEdit;
|
||||
using AvaloniaEdit.Document;
|
||||
using AvaloniaEdit.Editing;
|
||||
using AvaloniaEdit.TextMate;
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
using TextMateSharp.Grammars;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
|
||||
public class RevisionTextFileView : TextEditor {
|
||||
public class RevisionTextFileView : TextEditor
|
||||
{
|
||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||
|
||||
public RevisionTextFileView() : base(new TextArea(), new TextDocument()) {
|
||||
public RevisionTextFileView() : base(new TextArea(), new TextDocument())
|
||||
{
|
||||
IsReadOnly = true;
|
||||
ShowLineNumbers = true;
|
||||
WordWrap = false;
|
||||
|
@ -28,13 +34,17 @@ namespace SourceGit.Views {
|
|||
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||
}
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e) {
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
|
||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
|
||||
{
|
||||
_registryOptions = new RegistryOptions(ThemeName.DarkPlus);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_registryOptions = new RegistryOptions(ThemeName.LightPlus);
|
||||
}
|
||||
|
||||
|
@ -42,7 +52,8 @@ namespace SourceGit.Views {
|
|||
UpdateGrammar();
|
||||
}
|
||||
|
||||
protected override void OnUnloaded(RoutedEventArgs e) {
|
||||
protected override void OnUnloaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnUnloaded(e);
|
||||
|
||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||
|
@ -52,29 +63,37 @@ namespace SourceGit.Views {
|
|||
GC.Collect();
|
||||
}
|
||||
|
||||
protected override void OnDataContextChanged(EventArgs e) {
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
base.OnDataContextChanged(e);
|
||||
|
||||
var source = DataContext as Models.RevisionTextFile;
|
||||
if (source != null) {
|
||||
if (source != null)
|
||||
{
|
||||
UpdateGrammar();
|
||||
Text = source.Content;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) {
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null) {
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) {
|
||||
if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null && _textMate != null)
|
||||
{
|
||||
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
|
||||
{
|
||||
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.DarkPlus));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_textMate.SetTheme(_registryOptions.LoadTheme(ThemeName.LightPlus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var selected = SelectedText;
|
||||
if (string.IsNullOrEmpty(selected)) return;
|
||||
|
||||
|
@ -87,7 +106,8 @@ namespace SourceGit.Views {
|
|||
var copy = new MenuItem();
|
||||
copy.Header = App.Text("Copy");
|
||||
copy.Icon = icon;
|
||||
copy.Click += (o, ev) => {
|
||||
copy.Click += (o, ev) =>
|
||||
{
|
||||
App.CopyText(selected);
|
||||
ev.Handled = true;
|
||||
};
|
||||
|
@ -98,16 +118,20 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateGrammar() {
|
||||
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") {
|
||||
if (ext == ".h")
|
||||
{
|
||||
_textMate.SetGrammar(_registryOptions.GetScopeByLanguageId("cpp"));
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_textMate.SetGrammar(_registryOptions.GetScopeByExtension(ext));
|
||||
}
|
||||
}
|
||||
|
@ -116,15 +140,19 @@ namespace SourceGit.Views {
|
|||
private TextMate.Installation _textMate = null;
|
||||
}
|
||||
|
||||
public partial class RevisionFiles : UserControl {
|
||||
public RevisionFiles() {
|
||||
public partial class RevisionFiles : UserControl
|
||||
{
|
||||
public RevisionFiles()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnTreeViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var detail = DataContext as ViewModels.CommitDetail;
|
||||
var node = detail.SelectedRevisionFileNode;
|
||||
if (!node.IsFolder) {
|
||||
if (!node.IsFolder)
|
||||
{
|
||||
var menu = detail.CreateRevisionFileContextMenu(node.Backend as Models.Object);
|
||||
menu.Open(sender as Control);
|
||||
}
|
||||
|
@ -132,4 +160,4 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Reword : UserControl {
|
||||
public Reword() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Reword : UserControl
|
||||
{
|
||||
public Reword()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Squash : UserControl {
|
||||
public Squash() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Squash : UserControl
|
||||
{
|
||||
public Squash()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class StashChanges : UserControl {
|
||||
public StashChanges() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class StashChanges : UserControl
|
||||
{
|
||||
public StashChanges()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
using Avalonia.Controls;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class StashesPage : UserControl {
|
||||
public StashesPage() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class StashesPage : UserControl
|
||||
{
|
||||
public StashesPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,18 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Media;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public class Chart : Control {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public class Chart : Control
|
||||
{
|
||||
public static readonly StyledProperty<IBrush> LineBrushProperty =
|
||||
AvaloniaProperty.Register<Chart, IBrush>(nameof(LineBrush), Brushes.Gray);
|
||||
|
||||
public IBrush LineBrush {
|
||||
public IBrush LineBrush
|
||||
{
|
||||
get => GetValue(LineBrushProperty);
|
||||
set => SetValue(LineBrushProperty, value);
|
||||
}
|
||||
|
@ -20,7 +24,8 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<IBrush> ShapeBrushProperty =
|
||||
AvaloniaProperty.Register<Chart, IBrush>(nameof(ShapeBrush), Brushes.Gray);
|
||||
|
||||
public IBrush ShapeBrush {
|
||||
public IBrush ShapeBrush
|
||||
{
|
||||
get => GetValue(ShapeBrushProperty);
|
||||
set => SetValue(ShapeBrushProperty, value);
|
||||
}
|
||||
|
@ -28,41 +33,59 @@ namespace SourceGit.Views {
|
|||
public static readonly StyledProperty<List<Models.StatisticsSample>> SamplesProperty =
|
||||
AvaloniaProperty.Register<Chart, List<Models.StatisticsSample>>(nameof(Samples), null);
|
||||
|
||||
public List<Models.StatisticsSample> Samples {
|
||||
public List<Models.StatisticsSample> Samples
|
||||
{
|
||||
get => GetValue(SamplesProperty);
|
||||
set => SetValue(SamplesProperty, value);
|
||||
}
|
||||
|
||||
static Chart() {
|
||||
SamplesProperty.Changed.AddClassHandler<Chart>((c, e) => {
|
||||
static Chart()
|
||||
{
|
||||
SamplesProperty.Changed.AddClassHandler<Chart>((c, e) =>
|
||||
{
|
||||
c._hitBoxes.Clear();
|
||||
c._lastHitIdx = -1;
|
||||
c.InvalidateVisual();
|
||||
});
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context) {
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (Samples == null) return;
|
||||
|
||||
var samples = Samples;
|
||||
int maxV = 0;
|
||||
foreach (var s in samples) {
|
||||
foreach (var s in samples)
|
||||
{
|
||||
if (maxV < s.Count) maxV = s.Count;
|
||||
}
|
||||
|
||||
if (maxV < 5) {
|
||||
if (maxV < 5)
|
||||
{
|
||||
maxV = 5;
|
||||
} else if (maxV < 10) {
|
||||
}
|
||||
else if (maxV < 10)
|
||||
{
|
||||
maxV = 10;
|
||||
} else if (maxV < 50) {
|
||||
}
|
||||
else if (maxV < 50)
|
||||
{
|
||||
maxV = 50;
|
||||
} else if (maxV < 100) {
|
||||
}
|
||||
else if (maxV < 100)
|
||||
{
|
||||
maxV = 100;
|
||||
} else if (maxV < 200) {
|
||||
}
|
||||
else if (maxV < 200)
|
||||
{
|
||||
maxV = 200;
|
||||
} else if (maxV < 500) {
|
||||
}
|
||||
else if (maxV < 500)
|
||||
{
|
||||
maxV = 500;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
maxV = (int)Math.Ceiling(maxV / 500.0) * 500;
|
||||
}
|
||||
|
||||
|
@ -89,7 +112,8 @@ namespace SourceGit.Views {
|
|||
var stepV = (height - labelHeight) / 5;
|
||||
var labelStepV = maxV / 5;
|
||||
var gridPen = new Pen(LineBrush, 1, new DashStyle());
|
||||
for (int i = 1; i < 5; i++) {
|
||||
for (int i = 1; i < 5; i++)
|
||||
{
|
||||
var vLabel = new FormattedText(
|
||||
$"{maxV - i * labelStepV}",
|
||||
CultureInfo.CurrentCulture,
|
||||
|
@ -100,16 +124,19 @@ namespace SourceGit.Views {
|
|||
|
||||
var dashHeight = i * stepV;
|
||||
var vy = Math.Max(0, dashHeight - vLabel.Height * 0.5);
|
||||
using (context.PushOpacity(.1)) {
|
||||
using (context.PushOpacity(.1))
|
||||
{
|
||||
context.DrawLine(gridPen, new Point(horizonStart + 1, dashHeight), new Point(width, dashHeight));
|
||||
}
|
||||
context.DrawText(vLabel, new Point(horizonStart - vLabel.Width - 8, vy));
|
||||
}
|
||||
|
||||
// Calculate hit boxes
|
||||
if (_hitBoxes.Count == 0) {
|
||||
if (_hitBoxes.Count == 0)
|
||||
{
|
||||
var shapeWidth = Math.Min(32, stepX - 4);
|
||||
for (int i = 0; i < samples.Count; i++) {
|
||||
for (int i = 0; i < samples.Count; i++)
|
||||
{
|
||||
var h = samples[i].Count * (height - labelHeight) / maxV;
|
||||
var x = horizonStart + 1 + stepX * i + (stepX - shapeWidth) * 0.5;
|
||||
var y = height - labelHeight - h;
|
||||
|
@ -118,7 +145,8 @@ namespace SourceGit.Views {
|
|||
}
|
||||
|
||||
// Draw shapes
|
||||
for (int i = 0; i < samples.Count; i++) {
|
||||
for (int i = 0; i < samples.Count; i++)
|
||||
{
|
||||
var hLabel = new FormattedText(
|
||||
samples[i].Name,
|
||||
CultureInfo.CurrentCulture,
|
||||
|
@ -132,20 +160,25 @@ namespace SourceGit.Views {
|
|||
|
||||
context.DrawRectangle(ShapeBrush, null, rect);
|
||||
|
||||
if (stepX < 32) {
|
||||
if (stepX < 32)
|
||||
{
|
||||
var matrix = Matrix.CreateTranslation(hLabel.Width * 0.5, -hLabel.Height * 0.5) // Center of label
|
||||
* Matrix.CreateRotation(Math.PI * 0.25) // Rotate
|
||||
* Matrix.CreateTranslation(xLabel, yLabel); // Move
|
||||
using (context.PushTransform(matrix)) {
|
||||
using (context.PushTransform(matrix))
|
||||
{
|
||||
context.DrawText(hLabel, new Point(0, 0));
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
context.DrawText(hLabel, new Point(xLabel, yLabel));
|
||||
}
|
||||
}
|
||||
|
||||
// Draw labels on hover
|
||||
if (_lastHitIdx >= 0 && _lastHitIdx < samples.Count) {
|
||||
if (_lastHitIdx >= 0 && _lastHitIdx < samples.Count)
|
||||
{
|
||||
var rect = _hitBoxes[_lastHitIdx];
|
||||
var tooltip = new FormattedText(
|
||||
$"{samples[_lastHitIdx].Count}",
|
||||
|
@ -161,42 +194,51 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e) {
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
base.OnPointerMoved(e);
|
||||
|
||||
var p = e.GetPosition(this);
|
||||
for (int i = 0; i < _hitBoxes.Count; i++) {
|
||||
if (_hitBoxes[i].Contains(p)) {
|
||||
if (_lastHitIdx != i) {
|
||||
for (int i = 0; i < _hitBoxes.Count; i++)
|
||||
{
|
||||
if (_hitBoxes[i].Contains(p))
|
||||
{
|
||||
if (_lastHitIdx != i)
|
||||
{
|
||||
_lastHitIdx = i;
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (_lastHitIdx != -1) {
|
||||
if (_lastHitIdx != -1)
|
||||
{
|
||||
_lastHitIdx = -1;
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<Rect> _hitBoxes = new List<Rect>();
|
||||
private readonly List<Rect> _hitBoxes = new List<Rect>();
|
||||
private int _lastHitIdx = -1;
|
||||
}
|
||||
|
||||
public partial class Statistics : Window {
|
||||
public Statistics() {
|
||||
public partial class Statistics : Window
|
||||
{
|
||||
public Statistics()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e) {
|
||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
BeginMoveDrag(e);
|
||||
}
|
||||
|
||||
private void CloseWindow(object sender, RoutedEventArgs e) {
|
||||
private void CloseWindow(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -1,52 +1,67 @@
|
|||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class Welcome : UserControl {
|
||||
public Welcome() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class Welcome : UserControl
|
||||
{
|
||||
public Welcome()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void SetupTreeViewDragAndDrop(object sender, RoutedEventArgs e) {
|
||||
if (sender is TreeView view) {
|
||||
private void SetupTreeViewDragAndDrop(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is TreeView view)
|
||||
{
|
||||
DragDrop.SetAllowDrop(view, true);
|
||||
view.AddHandler(DragDrop.DragOverEvent, DragOverTreeView);
|
||||
view.AddHandler(DragDrop.DropEvent, DropOnTreeView);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupTreeNodeDragAndDrop(object sender, RoutedEventArgs e) {
|
||||
if (sender is Grid grid) {
|
||||
private void SetupTreeNodeDragAndDrop(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Grid grid)
|
||||
{
|
||||
DragDrop.SetAllowDrop(grid, true);
|
||||
grid.AddHandler(DragDrop.DragOverEvent, DragOverTreeNode);
|
||||
grid.AddHandler(DragDrop.DropEvent, DropOnTreeNode);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerPressedTreeNode(object sender, PointerPressedEventArgs e) {
|
||||
if (e.GetCurrentPoint(sender as Visual).Properties.IsLeftButtonPressed) {
|
||||
private void OnPointerPressedTreeNode(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (e.GetCurrentPoint(sender as Visual).Properties.IsLeftButtonPressed)
|
||||
{
|
||||
_pressedTreeNode = true;
|
||||
_startDragTreeNode = false;
|
||||
_pressedTreeNodePosition = e.GetPosition(sender as Grid);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
_pressedTreeNode = false;
|
||||
_startDragTreeNode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerReleasedOnTreeNode(object sender, PointerReleasedEventArgs e) {
|
||||
private void OnPointerReleasedOnTreeNode(object sender, PointerReleasedEventArgs e)
|
||||
{
|
||||
_pressedTreeNode = false;
|
||||
_startDragTreeNode = false;
|
||||
}
|
||||
|
||||
private void OnPointerMovedOverTreeNode(object sender, PointerEventArgs e) {
|
||||
if (_pressedTreeNode && !_startDragTreeNode && sender is Grid grid) {
|
||||
private void OnPointerMovedOverTreeNode(object sender, PointerEventArgs e)
|
||||
{
|
||||
if (_pressedTreeNode && !_startDragTreeNode && sender is Grid grid)
|
||||
{
|
||||
var delta = e.GetPosition(grid) - _pressedTreeNodePosition;
|
||||
var sizeSquired = delta.X * delta.X + delta.Y * delta.Y;
|
||||
if (sizeSquired < 64) return;
|
||||
|
@ -59,34 +74,45 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
|
||||
private void OnTreeViewLostFocus(object sender, RoutedEventArgs e) {
|
||||
private void OnTreeViewLostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_pressedTreeNode = false;
|
||||
_startDragTreeNode = false;
|
||||
}
|
||||
|
||||
private void DragOverTreeView(object sender, DragEventArgs e) {
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode") || e.Data.Contains(DataFormats.Files)) {
|
||||
private void DragOverTreeView(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode") || e.Data.Contains(DataFormats.Files))
|
||||
{
|
||||
e.DragEffects = DragDropEffects.Move;
|
||||
e.Handled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
e.DragEffects = DragDropEffects.None;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async void DropOnTreeView(object sender, DragEventArgs e) {
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode")) {
|
||||
private async void DropOnTreeView(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode"))
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
var moved = e.Data.Get("MovedRepositoryTreeNode") as ViewModels.RepositoryNode;
|
||||
if (moved != null && DataContext is ViewModels.Welcome vm) {
|
||||
if (moved != null && DataContext is ViewModels.Welcome vm)
|
||||
{
|
||||
vm.MoveNode(moved, null);
|
||||
}
|
||||
} else if (e.Data.Contains(DataFormats.Files)) {
|
||||
}
|
||||
else if (e.Data.Contains(DataFormats.Files))
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
var items = e.Data.GetFiles();
|
||||
foreach (var item in items) {
|
||||
foreach (var item in items)
|
||||
{
|
||||
await OpenOrInitRepository(item.Path.LocalPath);
|
||||
break;
|
||||
}
|
||||
|
@ -96,46 +122,58 @@ namespace SourceGit.Views {
|
|||
_startDragTreeNode = false;
|
||||
}
|
||||
|
||||
private void DragOverTreeNode(object sender, DragEventArgs e) {
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode") || e.Data.Contains(DataFormats.Files)) {
|
||||
private void DragOverTreeNode(object sender, DragEventArgs e)
|
||||
{
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode") || e.Data.Contains(DataFormats.Files))
|
||||
{
|
||||
var grid = sender as Grid;
|
||||
if (grid == null) return;
|
||||
|
||||
var to = grid.DataContext as ViewModels.RepositoryNode;
|
||||
if (to == null) return;
|
||||
|
||||
if (to.IsRepository) {
|
||||
if (to.IsRepository)
|
||||
{
|
||||
e.DragEffects = DragDropEffects.None;
|
||||
e.Handled = true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
e.DragEffects = DragDropEffects.Move;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async void DropOnTreeNode(object sender, DragEventArgs e) {
|
||||
private async void DropOnTreeNode(object sender, DragEventArgs e)
|
||||
{
|
||||
var grid = sender as Grid;
|
||||
if (grid == null) return;
|
||||
|
||||
var to = grid.DataContext as ViewModels.RepositoryNode;
|
||||
if (to == null || to.IsRepository) {
|
||||
if (to == null || to.IsRepository)
|
||||
{
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode")) {
|
||||
if (e.Data.Contains("MovedRepositoryTreeNode"))
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
var moved = e.Data.Get("MovedRepositoryTreeNode") as ViewModels.RepositoryNode;
|
||||
if (to != null && moved != null && to != moved && DataContext is ViewModels.Welcome vm) {
|
||||
if (to != null && moved != null && to != moved && DataContext is ViewModels.Welcome vm)
|
||||
{
|
||||
vm.MoveNode(moved, to);
|
||||
}
|
||||
} else if (e.Data.Contains(DataFormats.Files)) {
|
||||
}
|
||||
else if (e.Data.Contains(DataFormats.Files))
|
||||
{
|
||||
e.Handled = true;
|
||||
|
||||
var items = e.Data.GetFiles();
|
||||
foreach (var item in items) {
|
||||
foreach (var item in items)
|
||||
{
|
||||
await OpenOrInitRepository(item.Path.LocalPath, to);
|
||||
break;
|
||||
}
|
||||
|
@ -145,12 +183,14 @@ namespace SourceGit.Views {
|
|||
_startDragTreeNode = false;
|
||||
}
|
||||
|
||||
private void OnDoubleTappedTreeNode(object sender, TappedEventArgs e) {
|
||||
private void OnDoubleTappedTreeNode(object sender, TappedEventArgs e)
|
||||
{
|
||||
var grid = sender as Grid;
|
||||
if (grid == null) return;
|
||||
|
||||
var to = grid.DataContext as ViewModels.RepositoryNode;
|
||||
if (to == null || !to.IsRepository) {
|
||||
if (to == null || !to.IsRepository)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -159,39 +199,48 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OpenLocalRepository(object sender, RoutedEventArgs e) {
|
||||
private async void OpenLocalRepository(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!ViewModels.PopupHost.CanCreatePopup()) return;
|
||||
|
||||
var topLevel = TopLevel.GetTopLevel(this);
|
||||
var options = new FolderPickerOpenOptions() { AllowMultiple = false };
|
||||
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
|
||||
if (selected.Count == 1) {
|
||||
if (selected.Count == 1)
|
||||
{
|
||||
await OpenOrInitRepository(selected[0].Path.LocalPath);
|
||||
}
|
||||
}
|
||||
|
||||
private Task OpenOrInitRepository(string path, ViewModels.RepositoryNode parent = null) {
|
||||
private Task OpenOrInitRepository(string path, ViewModels.RepositoryNode parent = null)
|
||||
{
|
||||
var launcher = TopLevel.GetTopLevel(this).DataContext as ViewModels.Launcher;
|
||||
var page = launcher.ActivePage;
|
||||
|
||||
if (!Directory.Exists(path)) {
|
||||
if (!Directory.Exists(path))
|
||||
{
|
||||
if (File.Exists(path)) path = Path.GetDirectoryName(path);
|
||||
else return null;
|
||||
}
|
||||
|
||||
return Task.Run(() => {
|
||||
return Task.Run(() =>
|
||||
{
|
||||
var root = new Commands.QueryRepositoryRootPath(path).Result();
|
||||
if (string.IsNullOrEmpty(root)) {
|
||||
Dispatcher.UIThread.Invoke(() => {
|
||||
if (string.IsNullOrEmpty(root))
|
||||
{
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
(DataContext as ViewModels.Welcome).InitRepository(path);
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var gitDir = new Commands.QueryGitDir(root).Result();
|
||||
Dispatcher.UIThread.Invoke(() => {
|
||||
Dispatcher.UIThread.Invoke(() =>
|
||||
{
|
||||
var repo = ViewModels.Preference.AddRepository(root, gitDir);
|
||||
var node = new ViewModels.RepositoryNode() {
|
||||
var node = new ViewModels.RepositoryNode()
|
||||
{
|
||||
Id = repo.FullPath,
|
||||
Name = Path.GetFileName(repo.FullPath),
|
||||
Bookmark = 0,
|
||||
|
@ -199,7 +248,7 @@ namespace SourceGit.Views {
|
|||
};
|
||||
ViewModels.Preference.AddNode(node, parent);
|
||||
launcher.OpenRepositoryInTab(node, page);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,24 @@
|
|||
using System.Collections.Generic;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.VisualTree;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SourceGit.Views {
|
||||
public partial class WorkingCopy : UserControl {
|
||||
public WorkingCopy() {
|
||||
namespace SourceGit.Views
|
||||
{
|
||||
public partial class WorkingCopy : UserControl
|
||||
{
|
||||
public WorkingCopy()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ViewAssumeUnchanged(object sender, RoutedEventArgs e) {
|
||||
private void ViewAssumeUnchanged(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var repoPage = this.FindAncestorOfType<Repository>();
|
||||
if (repoPage != null) {
|
||||
if (repoPage != null)
|
||||
{
|
||||
var repo = (repoPage.DataContext as ViewModels.Repository).FullPath;
|
||||
var window = new AssumeUnchangedManager();
|
||||
window.DataContext = new ViewModels.AssumeUnchangedManager(repo);
|
||||
|
@ -22,34 +28,40 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void StageSelected(object sender, RoutedEventArgs e) {
|
||||
private void StageSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
if (vm == null) return;
|
||||
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
switch (ViewModels.Preference.Instance.UnstagedChangeViewMode) {
|
||||
case Models.ChangeViewMode.List:
|
||||
foreach (var item in unstagedList.SelectedItems) {
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
case Models.ChangeViewMode.Grid:
|
||||
foreach (var item in unstagedGrid.SelectedItems) {
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
foreach (var item in unstagedTree.SelectedItems) {
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
break;
|
||||
switch (ViewModels.Preference.Instance.UnstagedChangeViewMode)
|
||||
{
|
||||
case Models.ChangeViewMode.List:
|
||||
foreach (var item in unstagedList.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
case Models.ChangeViewMode.Grid:
|
||||
foreach (var item in unstagedGrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
foreach (var item in unstagedTree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vm.StageChanges(selected);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void StageAll(object sender, RoutedEventArgs e) {
|
||||
private void StageAll(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
if (vm == null) return;
|
||||
|
||||
|
@ -57,34 +69,40 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UnstageSelected(object sender, RoutedEventArgs e) {
|
||||
private void UnstageSelected(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
if (vm == null) return;
|
||||
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
switch (ViewModels.Preference.Instance.StagedChangeViewMode) {
|
||||
case Models.ChangeViewMode.List:
|
||||
foreach (var item in stagedList.SelectedItems) {
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
case Models.ChangeViewMode.Grid:
|
||||
foreach (var item in stagedGrid.SelectedItems) {
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
foreach (var item in stagedTree.SelectedItems) {
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
break;
|
||||
switch (ViewModels.Preference.Instance.StagedChangeViewMode)
|
||||
{
|
||||
case Models.ChangeViewMode.List:
|
||||
foreach (var item in stagedList.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
case Models.ChangeViewMode.Grid:
|
||||
foreach (var item in stagedGrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
foreach (var item in stagedTree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
vm.UnstageChanges(selected);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void UnstageAll(object sender, RoutedEventArgs e) {
|
||||
private void UnstageAll(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
if (vm == null) return;
|
||||
|
||||
|
@ -92,11 +110,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnUnstagedListKeyDown(object sender, KeyEventArgs e) {
|
||||
private void OnUnstagedListKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
if (datagrid.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (datagrid.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in datagrid.SelectedItems) {
|
||||
foreach (var item in datagrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
|
||||
|
@ -106,11 +127,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnUnstagedTreeViewKeyDown(object sender, KeyEventArgs e) {
|
||||
private void OnUnstagedTreeViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (tree.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in tree.SelectedItems) {
|
||||
foreach (var item in tree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
|
||||
|
@ -120,11 +144,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStagedListKeyDown(object sender, KeyEventArgs e) {
|
||||
private void OnStagedListKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
if (datagrid.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (datagrid.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in datagrid.SelectedItems) {
|
||||
foreach (var item in datagrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
|
||||
|
@ -134,11 +161,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStagedTreeViewKeyDown(object sender, KeyEventArgs e) {
|
||||
private void OnStagedTreeViewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (tree.SelectedItems.Count > 0 && e.Key == Key.Space && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in tree.SelectedItems) {
|
||||
foreach (var item in tree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
|
||||
|
@ -148,11 +178,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnUnstagedListContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnUnstagedListContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
if (datagrid.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (datagrid.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in datagrid.SelectedItems) {
|
||||
foreach (var item in datagrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
|
||||
|
@ -163,11 +196,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnUnstagedTreeViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnUnstagedTreeViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (tree.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in tree.SelectedItems) {
|
||||
foreach (var item in tree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
|
||||
|
@ -178,11 +214,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStagedListContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnStagedListContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var datagrid = sender as DataGrid;
|
||||
if (datagrid.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (datagrid.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in datagrid.SelectedItems) {
|
||||
foreach (var item in datagrid.SelectedItems)
|
||||
{
|
||||
if (item is Models.Change change) selected.Add(change);
|
||||
}
|
||||
|
||||
|
@ -193,11 +232,14 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void OnStagedTreeViewContextRequested(object sender, ContextRequestedEventArgs e) {
|
||||
private void OnStagedTreeViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||
{
|
||||
var tree = sender as TreeView;
|
||||
if (tree.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm) {
|
||||
if (tree.SelectedItems.Count > 0 && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
List<Models.Change> selected = new List<Models.Change>();
|
||||
foreach (var item in tree.SelectedItems) {
|
||||
foreach (var item in tree.SelectedItems)
|
||||
{
|
||||
if (item is ViewModels.FileTreeNode node) CollectChangesFromNode(selected, node);
|
||||
}
|
||||
|
||||
|
@ -208,12 +250,15 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void StartAmend(object sender, RoutedEventArgs e) {
|
||||
private void StartAmend(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var repoPage = this.FindAncestorOfType<Repository>();
|
||||
if (repoPage != null) {
|
||||
if (repoPage != null)
|
||||
{
|
||||
var repo = (repoPage.DataContext as ViewModels.Repository).FullPath;
|
||||
var commits = new Commands.QueryCommits(repo, "-n 1", false).Result();
|
||||
if (commits.Count == 0) {
|
||||
if (commits.Count == 0)
|
||||
{
|
||||
App.RaiseException(repo, "No commits to amend!!!");
|
||||
|
||||
var chkBox = sender as CheckBox;
|
||||
|
@ -229,29 +274,37 @@ namespace SourceGit.Views {
|
|||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void Commit(object sender, RoutedEventArgs e) {
|
||||
private void Commit(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
vm.DoCommit(false);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CommitWithPush(object sender, RoutedEventArgs e) {
|
||||
private void CommitWithPush(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var vm = DataContext as ViewModels.WorkingCopy;
|
||||
vm.DoCommit(true);
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CollectChangesFromNode(List<Models.Change> outs, ViewModels.FileTreeNode node) {
|
||||
if (node.IsFolder) {
|
||||
private void CollectChangesFromNode(List<Models.Change> outs, ViewModels.FileTreeNode node)
|
||||
{
|
||||
if (node.IsFolder)
|
||||
{
|
||||
foreach (var child in node.Children) CollectChangesFromNode(outs, child);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
var change = node.Backend as Models.Change;
|
||||
if (change != null && !outs.Contains(change)) outs.Add(change);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnOpenCommitMessagePicker(object sender, RoutedEventArgs e) {
|
||||
if (sender is Button button && DataContext is ViewModels.WorkingCopy vm) {
|
||||
private void OnOpenCommitMessagePicker(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (sender is Button button && DataContext is ViewModels.WorkingCopy vm)
|
||||
{
|
||||
var menu = vm.CreateContextMenuForCommitMessages();
|
||||
menu.Placement = PlacementMode.TopEdgeAlignedLeft;
|
||||
menu.Open(button);
|
||||
|
@ -259,4 +312,4 @@ namespace SourceGit.Views {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue