mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-11-01 13:13:21 -07:00
Merge branch 'release/v8.17'
This commit is contained in:
commit
5a1827fdcb
73 changed files with 2069 additions and 1544 deletions
45
README.md
45
README.md
|
@ -9,6 +9,7 @@ Opensource Git GUI client.
|
||||||
* Fast
|
* Fast
|
||||||
* English/简体中文/繁體中文
|
* English/简体中文/繁體中文
|
||||||
* Built-in light/dark themes
|
* Built-in light/dark themes
|
||||||
|
* Customize theme
|
||||||
* Visual commit graph
|
* Visual commit graph
|
||||||
* Supports SSH access with each remote
|
* Supports SSH access with each remote
|
||||||
* GIT commands with GUI
|
* GIT commands with GUI
|
||||||
|
@ -24,6 +25,8 @@ Opensource Git GUI client.
|
||||||
* File histories
|
* File histories
|
||||||
* Blame
|
* Blame
|
||||||
* Revision Diffs
|
* Revision Diffs
|
||||||
|
* Branch Diff
|
||||||
|
* Image Diff
|
||||||
* GitFlow support
|
* GitFlow support
|
||||||
|
|
||||||
> **Linux** only tested on **Ubuntu 22.04** on **X11**.
|
> **Linux** only tested on **Ubuntu 22.04** on **X11**.
|
||||||
|
@ -87,6 +90,48 @@ This app supports open repository in external tools listed in the table below.
|
||||||
|
|
||||||
![Theme Light](./screenshots/theme_light.png)
|
![Theme Light](./screenshots/theme_light.png)
|
||||||
|
|
||||||
|
## How to Customize Theme
|
||||||
|
|
||||||
|
1. Create a new json file, and provide your favorite colors with follow keys:
|
||||||
|
|
||||||
|
| Key | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| Color.Window | Window background color |
|
||||||
|
| Color.WindowBorder | Window border color. Only used on Linux. |
|
||||||
|
| Color.TitleBar | Title bar background color |
|
||||||
|
| Color.ToolBar | Tool bar background color |
|
||||||
|
| Color.Popup | Popup panel background color |
|
||||||
|
| Color.Contents | Background color used in inputs, data grids, file content viewer, change lists, text diff viewer, etc. |
|
||||||
|
| Color.Badage | Badage background color |
|
||||||
|
| Color.Conflict | Conflict panel background color |
|
||||||
|
| Color.ConflictForeground | Conflict panel foreground color |
|
||||||
|
| Color.Border0 | Border color used in some controls, like Window, Tab, Toolbar, etc. |
|
||||||
|
| Color.Border1 | Border color used in inputs, like TextBox, ComboBox, etc. |
|
||||||
|
| Color.Border2 | Border color used in visual lines, like seperators, Rectange, etc. |
|
||||||
|
| Color.FlatButton.Background | Flat button background color, like `Cancel`, `Commit & Push` button |
|
||||||
|
| Color.FlatButton.BackgroundHovered | Flat button background color when hovered, like `Cancel` button |
|
||||||
|
| Color.FlatButton.PrimaryBackground | Primary flat button background color, like `Ok`, `Commit` button |
|
||||||
|
| Color.FlatButton.PrimaryBackgroundHovered | Primary flat button background color when hovered, like `Ok`, `Commit` button |
|
||||||
|
| Color.FG1 | Primary foreground color for all text elements |
|
||||||
|
| Color.FG2 | Secondary foreground color for all text elements |
|
||||||
|
| Color.Diff.EmptyBG | Background color used in empty lines in diff viewer |
|
||||||
|
| Color.Diff.AddedBG | Background color used in added lines in diff viewer |
|
||||||
|
| Color.Diff.DeletedBG | Background color used in deleted lines in diff viewer |
|
||||||
|
| Color.Diff.AddedHighlight | Background color used for changed words in added lines in diff viewer |
|
||||||
|
| Color.Diff.DeletedHighlight | Background color used for changed words in deleted lines in diff viewer |
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"Color.Window": "#FFFF6059"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Open `Preference` -> `Appearance`, choose the json file you just created in `Custom Color Schema`.
|
||||||
|
|
||||||
|
> **NOTE**: The `Custom Color Schema` will override the colors with same keys in current active theme.
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Thanks to all the people who contribute.
|
Thanks to all the people who contribute.
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
8.16
|
8.17
|
|
@ -6,6 +6,16 @@ if (Test-Path SourceGit) {
|
||||||
|
|
||||||
Remove-Item *.zip -Force
|
Remove-Item *.zip -Force
|
||||||
|
|
||||||
|
dotnet publish ..\src\SourceGit.csproj -c Release -r win-arm64 -o SourceGit -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
|
||||||
|
|
||||||
|
Remove-Item SourceGit\*.pdb -Force
|
||||||
|
|
||||||
|
Compress-Archive -Path SourceGit -DestinationPath "sourcegit_$version.win-arm64.zip"
|
||||||
|
|
||||||
|
if (Test-Path SourceGit) {
|
||||||
|
Remove-Item SourceGit -Recurse -Force
|
||||||
|
}
|
||||||
|
|
||||||
dotnet publish ..\src\SourceGit.csproj -c Release -r win-x64 -o SourceGit -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
|
dotnet publish ..\src\SourceGit.csproj -c Release -r win-x64 -o SourceGit -p:PublishAot=true -p:PublishTrimmed=true -p:TrimMode=link --self-contained
|
||||||
|
|
||||||
Remove-Item SourceGit\*.pdb -Force
|
Remove-Item SourceGit\*.pdb -Force
|
||||||
|
|
|
@ -1,90 +1,164 @@
|
||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
using Avalonia.Threading;
|
using Avalonia.Threading;
|
||||||
|
|
||||||
namespace SourceGit.Commands
|
namespace SourceGit.Commands
|
||||||
{
|
{
|
||||||
public class GitFlow : Command
|
public static class GitFlow
|
||||||
{
|
{
|
||||||
public GitFlow(string repo)
|
public class BranchDetectResult
|
||||||
{
|
{
|
||||||
WorkingDirectory = repo;
|
public bool IsGitFlowBranch { get; set; } = false;
|
||||||
Context = repo;
|
public string Type { get; set; } = string.Empty;
|
||||||
|
public string Prefix { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Init(List<Models.Branch> branches, string master, string develop, string feature, string release, string hotfix, string version)
|
public static bool IsEnabled(string repo, List<Models.Branch> branches)
|
||||||
|
{
|
||||||
|
var localBrancheNames = new HashSet<string>();
|
||||||
|
foreach (var branch in branches)
|
||||||
|
{
|
||||||
|
if (branch.IsLocal)
|
||||||
|
localBrancheNames.Add(branch.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = new Config(repo).ListAll();
|
||||||
|
if (!config.TryGetValue("gitflow.branch.master", out string master) || !localBrancheNames.Contains(master))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!config.TryGetValue("gitflow.branch.develop", out string develop) || !localBrancheNames.Contains(develop))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return config.ContainsKey("gitflow.prefix.feature") &&
|
||||||
|
config.ContainsKey("gitflow.prefix.release") &&
|
||||||
|
config.ContainsKey("gitflow.prefix.hotfix");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Init(string repo, List<Models.Branch> branches, string master, string develop, string feature, string release, string hotfix, string version)
|
||||||
{
|
{
|
||||||
var current = branches.Find(x => x.IsCurrent);
|
var current = branches.Find(x => x.IsCurrent);
|
||||||
|
|
||||||
var masterBranch = branches.Find(x => x.Name == master);
|
var masterBranch = branches.Find(x => x.Name == master);
|
||||||
if (masterBranch == null && current != null)
|
if (masterBranch == null && current != null)
|
||||||
Branch.Create(WorkingDirectory, master, current.Head);
|
Branch.Create(repo, master, current.Head);
|
||||||
|
|
||||||
var devBranch = branches.Find(x => x.Name == develop);
|
var devBranch = branches.Find(x => x.Name == develop);
|
||||||
if (devBranch == null && current != null)
|
if (devBranch == null && current != null)
|
||||||
Branch.Create(WorkingDirectory, develop, current.Head);
|
Branch.Create(repo, develop, current.Head);
|
||||||
|
|
||||||
var cmd = new Config(WorkingDirectory);
|
var config = new Config(repo);
|
||||||
cmd.Set("gitflow.branch.master", master);
|
config.Set("gitflow.branch.master", master);
|
||||||
cmd.Set("gitflow.branch.develop", develop);
|
config.Set("gitflow.branch.develop", develop);
|
||||||
cmd.Set("gitflow.prefix.feature", feature);
|
config.Set("gitflow.prefix.feature", feature);
|
||||||
cmd.Set("gitflow.prefix.bugfix", "bugfix/");
|
config.Set("gitflow.prefix.bugfix", "bugfix/");
|
||||||
cmd.Set("gitflow.prefix.release", release);
|
config.Set("gitflow.prefix.release", release);
|
||||||
cmd.Set("gitflow.prefix.hotfix", hotfix);
|
config.Set("gitflow.prefix.hotfix", hotfix);
|
||||||
cmd.Set("gitflow.prefix.support", "support/");
|
config.Set("gitflow.prefix.support", "support/");
|
||||||
cmd.Set("gitflow.prefix.versiontag", version, true);
|
config.Set("gitflow.prefix.versiontag", version, true);
|
||||||
|
|
||||||
Args = "flow init -d";
|
var init = new Command();
|
||||||
return Exec();
|
init.WorkingDirectory = repo;
|
||||||
|
init.Context = repo;
|
||||||
|
init.Args = "flow init -d";
|
||||||
|
return init.Exec();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Start(Models.GitFlowBranchType type, string name)
|
public static string Prefix(string repo, string type)
|
||||||
{
|
{
|
||||||
switch (type)
|
return new Config(repo).Get($"gitflow.prefix.{type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BranchDetectResult DetectType(string repo, List<Models.Branch> branches, string branch)
|
||||||
|
{
|
||||||
|
var rs = new BranchDetectResult();
|
||||||
|
var localBrancheNames = new HashSet<string>();
|
||||||
|
foreach (var b in branches)
|
||||||
{
|
{
|
||||||
case Models.GitFlowBranchType.Feature:
|
if (b.IsLocal)
|
||||||
Args = $"flow feature start {name}";
|
localBrancheNames.Add(b.Name);
|
||||||
break;
|
|
||||||
case Models.GitFlowBranchType.Release:
|
|
||||||
Args = $"flow release start {name}";
|
|
||||||
break;
|
|
||||||
case Models.GitFlowBranchType.Hotfix:
|
|
||||||
Args = $"flow hotfix start {name}";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
|
||||||
{
|
|
||||||
App.RaiseException(Context, "Bad branch type!!!");
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Exec();
|
var config = new Config(repo).ListAll();
|
||||||
|
if (!config.TryGetValue("gitflow.branch.master", out string master) || !localBrancheNames.Contains(master))
|
||||||
|
return rs;
|
||||||
|
|
||||||
|
if (!config.TryGetValue("gitflow.branch.develop", out string develop) || !localBrancheNames.Contains(develop))
|
||||||
|
return rs;
|
||||||
|
|
||||||
|
if (!config.TryGetValue("gitflow.prefix.feature", out var feature) ||
|
||||||
|
!config.TryGetValue("gitflow.prefix.release", out var release) ||
|
||||||
|
!config.TryGetValue("gitflow.prefix.hotfix", out var hotfix))
|
||||||
|
return rs;
|
||||||
|
|
||||||
|
if (branch.StartsWith(feature, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
rs.IsGitFlowBranch = true;
|
||||||
|
rs.Type = "feature";
|
||||||
|
rs.Prefix = feature;
|
||||||
|
}
|
||||||
|
else if (branch.StartsWith(release, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
rs.IsGitFlowBranch = true;
|
||||||
|
rs.Type = "release";
|
||||||
|
rs.Prefix = release;
|
||||||
|
}
|
||||||
|
else if (branch.StartsWith(hotfix, StringComparison.Ordinal))
|
||||||
|
{
|
||||||
|
rs.IsGitFlowBranch = true;
|
||||||
|
rs.Type = "hotfix";
|
||||||
|
rs.Prefix = hotfix;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Finish(Models.GitFlowBranchType type, string name, bool keepBranch)
|
public static bool Start(string repo, string type, string name)
|
||||||
{
|
{
|
||||||
|
if (!SUPPORTED_BRANCH_TYPES.Contains(type))
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
App.RaiseException(repo, "Bad branch type!!!");
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var start = new Command();
|
||||||
|
start.WorkingDirectory = repo;
|
||||||
|
start.Context = repo;
|
||||||
|
start.Args = $"flow {type} start {name}";
|
||||||
|
return start.Exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool Finish(string repo, string type, string name, bool keepBranch)
|
||||||
|
{
|
||||||
|
if (!SUPPORTED_BRANCH_TYPES.Contains(type))
|
||||||
|
{
|
||||||
|
Dispatcher.UIThread.Post(() =>
|
||||||
|
{
|
||||||
|
App.RaiseException(repo, "Bad branch type!!!");
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var option = keepBranch ? "-k" : string.Empty;
|
var option = keepBranch ? "-k" : string.Empty;
|
||||||
switch (type)
|
var finish = new Command();
|
||||||
{
|
finish.WorkingDirectory = repo;
|
||||||
case Models.GitFlowBranchType.Feature:
|
finish.Context = repo;
|
||||||
Args = $"flow feature finish {option} {name}";
|
finish.Args = $"flow {type} finish {option} {name}";
|
||||||
break;
|
return finish.Exec();
|
||||||
case Models.GitFlowBranchType.Release:
|
|
||||||
Args = $"flow release finish {option} {name} -m \"RELEASE_DONE\"";
|
|
||||||
break;
|
|
||||||
case Models.GitFlowBranchType.Hotfix:
|
|
||||||
Args = $"flow hotfix finish {option} {name} -m \"HOTFIX_DONE\"";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
|
||||||
{
|
|
||||||
App.RaiseException(Context, "Bad branch type!!!");
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static readonly List<string> SUPPORTED_BRANCH_TYPES = new List<string>()
|
||||||
|
{
|
||||||
|
"feature",
|
||||||
|
"release",
|
||||||
|
"bugfix",
|
||||||
|
"hotfix",
|
||||||
|
"support",
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
src/Commands/GitIgnore.cs
Normal file
16
src/Commands/GitIgnore.cs
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace SourceGit.Commands
|
||||||
|
{
|
||||||
|
public static class GitIgnore
|
||||||
|
{
|
||||||
|
public static void Add(string repo, string pattern)
|
||||||
|
{
|
||||||
|
var file = Path.Combine(repo, ".gitignore");
|
||||||
|
if (!File.Exists(file))
|
||||||
|
File.WriteAllLines(file, [ pattern ]);
|
||||||
|
else
|
||||||
|
File.AppendAllLines(file, [ pattern ]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,7 +12,8 @@ namespace SourceGit.Commands
|
||||||
public string Result()
|
public string Result()
|
||||||
{
|
{
|
||||||
var rs = ReadToEnd();
|
var rs = ReadToEnd();
|
||||||
if (rs.IsSuccess) return rs.StdOut.TrimEnd();
|
if (rs.IsSuccess)
|
||||||
|
return rs.StdOut.TrimEnd();
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,9 @@ namespace SourceGit.Commands
|
||||||
end = rs.StdOut.IndexOf('\n', start);
|
end = rs.StdOut.IndexOf('\n', start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (start < rs.StdOut.Length)
|
||||||
|
_current.Subject = rs.StdOut.Substring(start);
|
||||||
|
|
||||||
if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0)
|
if (_findFirstMerged && !_isHeadFounded && _commits.Count > 0)
|
||||||
MarkFirstMerged();
|
MarkFirstMerged();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace SourceGit.Commands
|
namespace SourceGit.Commands
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
using System;
|
|
||||||
|
|
||||||
using Avalonia;
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Data.Converters;
|
|
||||||
|
|
||||||
namespace SourceGit.Converters
|
|
||||||
{
|
|
||||||
public static class WindowStateConverters
|
|
||||||
{
|
|
||||||
public static readonly FuncValueConverter<WindowState, Thickness> ToContentMargin =
|
|
||||||
new FuncValueConverter<WindowState, Thickness>(state =>
|
|
||||||
{
|
|
||||||
if (OperatingSystem.IsWindows() && state == WindowState.Maximized)
|
|
||||||
return new Thickness(6);
|
|
||||||
else if (OperatingSystem.IsLinux() && state != WindowState.Maximized)
|
|
||||||
return new Thickness(6);
|
|
||||||
else
|
|
||||||
return new Thickness(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly FuncValueConverter<WindowState, GridLength> ToTitleBarHeight =
|
|
||||||
new FuncValueConverter<WindowState, GridLength>(state =>
|
|
||||||
{
|
|
||||||
if (state == WindowState.Maximized)
|
|
||||||
return new GridLength(OperatingSystem.IsMacOS() ? 34 : 30);
|
|
||||||
else
|
|
||||||
return new GridLength(38);
|
|
||||||
});
|
|
||||||
|
|
||||||
public static readonly FuncValueConverter<WindowState, bool> IsNormal =
|
|
||||||
new FuncValueConverter<WindowState, bool>(state => state == WindowState.Normal);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
namespace SourceGit.Models
|
|
||||||
{
|
|
||||||
public enum GitFlowBranchType
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Feature,
|
|
||||||
Release,
|
|
||||||
Hotfix,
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GitFlow
|
|
||||||
{
|
|
||||||
public string Feature { get; set; }
|
|
||||||
public string Release { get; set; }
|
|
||||||
public string Hotfix { get; set; }
|
|
||||||
|
|
||||||
public bool IsEnabled
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(Feature)
|
|
||||||
&& !string.IsNullOrEmpty(Release)
|
|
||||||
&& !string.IsNullOrEmpty(Hotfix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public GitFlowBranchType GetBranchType(string name)
|
|
||||||
{
|
|
||||||
if (!IsEnabled)
|
|
||||||
return GitFlowBranchType.None;
|
|
||||||
if (name.StartsWith(Feature))
|
|
||||||
return GitFlowBranchType.Feature;
|
|
||||||
if (name.StartsWith(Release))
|
|
||||||
return GitFlowBranchType.Release;
|
|
||||||
if (name.StartsWith(Hotfix))
|
|
||||||
return GitFlowBranchType.Hotfix;
|
|
||||||
return GitFlowBranchType.None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -98,4 +98,6 @@
|
||||||
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Lines.Decr">M408 232C408 210 426 192 448 192h416a40 40 0 110 80H448a40 40 0 01-40-40zM408 512c0-22 18-40 40-40h416a40 40 0 110 80H448A40 40 0 01408 512zM448 752A40 40 0 00448 832h416a40 40 0 100-80H448zM32 480l328 0 0 64-328 0Z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.Compare">M645 448l64 64 220-221L704 64l-64 64 115 115H128v90h628zM375 576l-64-64-220 224L314 960l64-64-116-115H896v-90H262z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.Compare">M645 448l64 64 220-221L704 64l-64 64 115 115H128v90h628zM375 576l-64-64-220 224L314 960l64-64-116-115H896v-90H262z</StreamGeometry>
|
||||||
<StreamGeometry x:Key="Icons.WordWrap">M248 221a77 77 0 00-30-21c-18-7-40-10-68-5a224 224 0 00-45 13c-5 2-10 5-15 8l-3 2v68l11-9c10-8 21-14 34-19 13-5 26-7 39-7 12 0 21 3 28 10 6 6 9 16 9 29l-62 9c-14 2-26 6-36 11a80 80 0 00-25 20c-7 8-12 17-15 27-6 21-6 44 1 65a70 70 0 0041 43c10 4 21 6 34 6a80 80 0 0063-28v22h64V298c0-16-2-31-6-44a91 91 0 00-18-33zm-41 121v15c0 8-1 15-4 22a48 48 0 01-24 29 44 44 0 01-33 2 29 29 0 01-10-6 25 25 0 01-6-9 30 30 0 01-2-12c0-5 1-9 2-14a21 21 0 015-9 28 28 0 0110-7 83 83 0 0120-5l42-6zm323-68a144 144 0 00-16-42 87 87 0 00-28-29 75 75 0 00-41-11 73 73 0 00-44 14c-6 5-12 11-17 17V64H326v398h59v-18c8 10 18 17 30 21 6 2 13 3 21 3 16 0 31-4 43-11 12-7 23-18 31-31a147 147 0 0019-46 248 248 0 006-57c0-17-2-33-5-49zm-55 49c0 15-1 28-4 39-2 11-6 20-10 27a41 41 0 01-15 15 37 37 0 01-36 1 44 44 0 01-13-12 59 59 0 01-9-18A76 76 0 01384 352v-33c0-10 1-20 4-29 2-8 6-15 10-22a43 43 0 0115-13 37 37 0 0119-5 35 35 0 0132 18c4 6 7 14 9 23 2 9 3 20 3 31zM154 634a58 58 0 0120-15c14-6 35-7 49-1 7 3 13 6 20 12l21 17V572l-6-4a124 124 0 00-58-14c-20 0-38 4-54 11-16 7-30 17-41 30-12 13-20 29-26 46-6 17-9 36-9 57 0 18 3 36 8 52 6 16 14 30 24 42 10 12 23 21 38 28 15 7 32 10 50 10 15 0 28-2 39-5 11-3 21-8 30-14l5-4v-57l-13 6a26 26 0 01-5 2c-3 1-6 2-8 3-2 1-15 6-15 6-4 2-9 3-14 4a63 63 0 01-38-4 53 53 0 01-20-14 70 70 0 01-13-24 111 111 0 01-5-34c0-13 2-26 5-36 3-10 8-19 14-26zM896 384h-256V320h288c21 1 32 12 32 32v384c0 18-12 32-32 32H504l132 133-45 45-185-185c-16-21-16-25 0-45l185-185L637 576l-128 128H896V384z</StreamGeometry>
|
<StreamGeometry x:Key="Icons.WordWrap">M248 221a77 77 0 00-30-21c-18-7-40-10-68-5a224 224 0 00-45 13c-5 2-10 5-15 8l-3 2v68l11-9c10-8 21-14 34-19 13-5 26-7 39-7 12 0 21 3 28 10 6 6 9 16 9 29l-62 9c-14 2-26 6-36 11a80 80 0 00-25 20c-7 8-12 17-15 27-6 21-6 44 1 65a70 70 0 0041 43c10 4 21 6 34 6a80 80 0 0063-28v22h64V298c0-16-2-31-6-44a91 91 0 00-18-33zm-41 121v15c0 8-1 15-4 22a48 48 0 01-24 29 44 44 0 01-33 2 29 29 0 01-10-6 25 25 0 01-6-9 30 30 0 01-2-12c0-5 1-9 2-14a21 21 0 015-9 28 28 0 0110-7 83 83 0 0120-5l42-6zm323-68a144 144 0 00-16-42 87 87 0 00-28-29 75 75 0 00-41-11 73 73 0 00-44 14c-6 5-12 11-17 17V64H326v398h59v-18c8 10 18 17 30 21 6 2 13 3 21 3 16 0 31-4 43-11 12-7 23-18 31-31a147 147 0 0019-46 248 248 0 006-57c0-17-2-33-5-49zm-55 49c0 15-1 28-4 39-2 11-6 20-10 27a41 41 0 01-15 15 37 37 0 01-36 1 44 44 0 01-13-12 59 59 0 01-9-18A76 76 0 01384 352v-33c0-10 1-20 4-29 2-8 6-15 10-22a43 43 0 0115-13 37 37 0 0119-5 35 35 0 0132 18c4 6 7 14 9 23 2 9 3 20 3 31zM154 634a58 58 0 0120-15c14-6 35-7 49-1 7 3 13 6 20 12l21 17V572l-6-4a124 124 0 00-58-14c-20 0-38 4-54 11-16 7-30 17-41 30-12 13-20 29-26 46-6 17-9 36-9 57 0 18 3 36 8 52 6 16 14 30 24 42 10 12 23 21 38 28 15 7 32 10 50 10 15 0 28-2 39-5 11-3 21-8 30-14l5-4v-57l-13 6a26 26 0 01-5 2c-3 1-6 2-8 3-2 1-15 6-15 6-4 2-9 3-14 4a63 63 0 01-38-4 53 53 0 01-20-14 70 70 0 01-13-24 111 111 0 01-5-34c0-13 2-26 5-36 3-10 8-19 14-26zM896 384h-256V320h288c21 1 32 12 32 32v384c0 18-12 32-32 32H504l132 133-45 45-185-185c-16-21-16-25 0-45l185-185L637 576l-128 128H896V384z</StreamGeometry>
|
||||||
|
<StreamGeometry x:Key="Icons.Detached">M128 183C128 154 154 128 183 128h521c30 0 55 26 55 55v38c0 17-17 34-34 34s-34-17-34-34v-26H196v495h26c17 0 34 17 34 34s-17 34-34 34h-38c-30 0-55-26-55-55V183zM380 896h-34c-26 0-47-21-47-47v-90h68V828h64V896H380c4 0 0 0 0 0zM759 828V896h90c26 0 47-21 47-47v-90h-68V828h-68zM828 435H896V346c0-26-21-47-47-47h-90v68H828v68zM435 299v68H367V439H299V346C299 320 320 299 346 299h90zM367 649H299v-107h68v107zM546 367V299h107v68h-107zM828 546H896v107h-68v-107zM649 828V896h-107v-68h107zM730 508v188c0 17-17 34-34 34h-188c-17 0-34-17-34-34s17-34 34-34h102l-124-124c-13-13-13-34 0-47 13-13 34-13 47 0l124 124V512c0-17 17-34 34-34 21-4 38 9 38 30z</StreamGeometry>
|
||||||
|
<StreamGeometry x:Key="Icons.GitIgnore">M590 74 859 342V876c0 38-31 68-68 68H233c-38 0-68-31-68-68V142c0-38 31-68 68-68h357zm-12 28H233a40 40 0 00-40 38L193 142v734a40 40 0 0038 40L233 916h558a40 40 0 0040-38L831 876V354L578 102zM855 371h-215c-46 0-83-36-84-82l0-2V74h28v213c0 30 24 54 54 55l2 0h215v28zM57 489m28 0 853 0q28 0 28 28l0 284q0 28-28 28l-853 0q-28 0-28-28l0-284q0-28 28-28ZM157 717c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C184 610 172 603 156 603c-29 0-54 21-54 57 0 37 24 56 54 56zM245 711v-108h-34v108h34zm69 0v-86H341V603H262v22h28V711h24zM393 711v-108h-34v108h34zm66 6c15 0 29-6 37-13v-51h-41v22h17v18c-2 2-6 3-10 3-21 0-30-13-30-34 0-21 12-34 28-34 9 0 15 4 20 9l14-17C485 610 474 603 458 603c-29 0-54 21-54 57 0 37 24 56 54 56zm88-6v-36c0-13-2-28-3-40h1l10 24 25 52H603v-108h-23v36c0 13 2 28 3 40h-1l-10-24L548 603H523v108h23zM677 717c30 0 51-22 51-57 0-36-21-56-51-56-30 0-51 20-51 56 0 36 21 57 51 57zm3-23c-16 0-26-12-26-32 0-19 10-31 26-31 16 0 26 11 26 31S696 694 680 694zm93 17v-38h13l21 38H836l-25-43c12-5 19-15 19-31 0-26-20-34-44-34H745v108h27zm16-51H774v-34h15c16 0 25 4 25 16s-9 18-25 18zM922 711v-22h-43v-23h35v-22h-35V625h41V603H853v108h68z</StreamGeometry>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">Blame</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">BLAME ON THIS FILE IS NOT SUPPORTED!!!</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">Checkout${0}$</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">Compare with Branch</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">Compare with HEAD</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">Compare with Worktree</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">Copy Branch Name</x:String>
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">Rename${0}$</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Tracking ...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">Tracking ...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String>
|
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">Unset Upstream</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">Branch Compare</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">Bytes</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">CANCEL</x:String>
|
||||||
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGE DISPLAY MODE</x:String>
|
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">CHANGE DISPLAY MODE</x:String>
|
||||||
|
@ -241,6 +243,8 @@
|
||||||
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Create new page</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">Create new page</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">Open preference dialog</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">Open preference dialog</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">REPOSITORY</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">Commit staged changes</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">Commit and push staged changes</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Force to reload this repository</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">Force to reload this repository</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Stage/Unstage selected changes</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">Stage/Unstage selected changes</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Open commit search</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">Open commit search</x:String>
|
||||||
|
@ -473,6 +477,11 @@
|
||||||
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories ...</x:String>
|
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories ...</x:String>
|
||||||
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String>
|
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
|
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">Add To .gitignore ...</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">Ignore all *{0} files</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">Ignore *{0} files in the same folder</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">Ignore files in the same folder</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">Ignore this file only</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
|
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">Amend</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
|
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">You can stage this file now.</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">COMMIT</x:String>
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">选中文件不支持该操作!!!</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout)${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">检出(checkout)${0}$</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">与其他分支对比</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">与当前HEAD比较</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">与本地工作树比较</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">复制分支名</x:String>
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重命名${0}$</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切换上游分支...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追踪</x:String>
|
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追踪</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比较</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">字节</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||||
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切换变更显示模式</x:String>
|
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切换变更显示模式</x:String>
|
||||||
|
@ -244,6 +246,8 @@
|
||||||
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">新建页面</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">新建页面</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">打开偏好设置面板</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">打开偏好设置面板</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">仓库页面快捷键</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">仓库页面快捷键</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暂存区更改</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暂存区更改并推送</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新加载仓库状态</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新加载仓库状态</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">将选中的变更暂存或从暂存列表中移除</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">将选中的变更暂存或从暂存列表中移除</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">打开历史搜索</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">打开历史搜索</x:String>
|
||||||
|
@ -476,6 +480,11 @@
|
||||||
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查找仓库...</x:String>
|
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查找仓库...</x:String>
|
||||||
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
|
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
|
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略列表 ...</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 文件</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同目录下所有 *{0} 文件</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同目录下所有文件</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本文件</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修补(--amend)</x:String>
|
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修补(--amend)</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String>
|
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">现在您已可将其加入暂存区中</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
|
<x:String x:Key="Text.Blame" xml:space="preserve">逐行追溯(blame)</x:String>
|
||||||
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">選中檔案不支援該操作!!!</x:String>
|
<x:String x:Key="Text.BlameTypeNotSupported" xml:space="preserve">選中檔案不支援該操作!!!</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">檢出(checkout)${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Checkout" xml:space="preserve">檢出(checkout)${0}$</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCM.CompareWithBranch" xml:space="preserve">與其他分支比較</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithHead" xml:space="preserve">與當前HEAD比較</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String>
|
<x:String x:Key="Text.BranchCM.CompareWithWorktree" xml:space="preserve">與本地工作樹比較</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名</x:String>
|
<x:String x:Key="Text.BranchCM.CopyName" xml:space="preserve">複製分支名</x:String>
|
||||||
|
@ -52,6 +53,7 @@
|
||||||
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名${0}$</x:String>
|
<x:String x:Key="Text.BranchCM.Rename" xml:space="preserve">重新命名${0}$</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
|
<x:String x:Key="Text.BranchCM.Tracking" xml:space="preserve">切換上游分支...</x:String>
|
||||||
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追蹤</x:String>
|
<x:String x:Key="Text.BranchCM.UnsetUpstream" xml:space="preserve">取消追蹤</x:String>
|
||||||
|
<x:String x:Key="Text.BranchCompare" xml:space="preserve">分支比較</x:String>
|
||||||
<x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String>
|
<x:String x:Key="Text.Bytes" xml:space="preserve">位元組</x:String>
|
||||||
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
<x:String x:Key="Text.Cancel" xml:space="preserve">取 消</x:String>
|
||||||
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切換變更顯示模式</x:String>
|
<x:String x:Key="Text.ChangeDisplayMode" xml:space="preserve">切換變更顯示模式</x:String>
|
||||||
|
@ -244,6 +246,8 @@
|
||||||
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">新建頁面</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.NewTab" xml:space="preserve">新建頁面</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">開啟偏好設定面板</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.OpenPreference" xml:space="preserve">開啟偏好設定面板</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">倉庫頁面快捷鍵</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo" xml:space="preserve">倉庫頁面快捷鍵</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.Commit" xml:space="preserve">提交暫存區變更</x:String>
|
||||||
|
<x:String x:Key="Text.Hotkeys.Repo.CommitAndPush" xml:space="preserve">提交暫存區變更併推送</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新載入倉庫狀態</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.Refresh" xml:space="preserve">重新載入倉庫狀態</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">將選中的變更暫存或從暫存列表中移除</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.StageOrUnstageSelected" xml:space="preserve">將選中的變更暫存或從暫存列表中移除</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">開啟歷史搜尋</x:String>
|
<x:String x:Key="Text.Hotkeys.Repo.OpenSearchCommits" xml:space="preserve">開啟歷史搜尋</x:String>
|
||||||
|
@ -476,6 +480,11 @@
|
||||||
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查詢倉庫...</x:String>
|
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">快速查詢倉庫...</x:String>
|
||||||
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
|
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">排序</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
|
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">本地更改</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore" xml:space="preserve">添加至 .gitignore 忽略清單 ...</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.Extension" xml:space="preserve">忽略所有 *{0} 檔案</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.ExtensionInSameFolder" xml:space="preserve">忽略同路徑下所有 *{0} 檔案</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.InSameFolder" xml:space="preserve">忽略同路徑下所有檔案</x:String>
|
||||||
|
<x:String x:Key="Text.WorkingCopy.AddToGitIgnore.SingleFile" xml:space="preserve">忽略本檔案</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修補(--amend)</x:String>
|
<x:String x:Key="Text.WorkingCopy.Amend" xml:space="preserve">修補(--amend)</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String>
|
<x:String x:Key="Text.WorkingCopy.CanStageTip" xml:space="preserve">現在您已可將其加入暫存區中</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
<x:String x:Key="Text.WorkingCopy.Commit" xml:space="preserve">提交</x:String>
|
||||||
|
|
|
@ -18,6 +18,143 @@
|
||||||
<Setter Property="HideDelay" Value="0:0:0.2"/>
|
<Setter Property="HideDelay" Value="0:0:0.2"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window">
|
||||||
|
<Setter Property="Background" Value="{DynamicResource Brush.Window}"/>
|
||||||
|
<Setter Property="BorderThickness" Value="1"/>
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
|
||||||
|
<Setter Property="ExtendClientAreaChromeHints" Value="NoChrome"/>
|
||||||
|
<Setter Property="ExtendClientAreaToDecorationsHint" Value="True"/>
|
||||||
|
<Setter Property="SystemDecorations" Value="Full"/>
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
|
||||||
|
<Style.Resources>
|
||||||
|
<SolidColorBrush x:Key="SystemControlErrorTextForegroundBrush" Color="Red"/>
|
||||||
|
<SolidColorBrush x:Key="SystemErrorTextColor" Color="Red"/>
|
||||||
|
</Style.Resources>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window[WindowState=Maximized]">
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window[WindowState=Maximized].fix_maximized_padding">
|
||||||
|
<Setter Property="Padding" Value="6"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window.custom_window_frame">
|
||||||
|
<Setter Property="Background" Value="Transparent"/>
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
<Setter Property="SystemDecorations" Value="None"/>
|
||||||
|
<Setter Property="Padding" Value="12"/>
|
||||||
|
|
||||||
|
<Setter Property="Template">
|
||||||
|
<ControlTemplate>
|
||||||
|
<Grid>
|
||||||
|
<Border x:Name="PART_BorderTopLeft"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Height="12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Left" VerticalAlignment="Top"
|
||||||
|
Cursor="TopLeftCorner"
|
||||||
|
Tag="{x:Static WindowEdge.NorthWest}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderTop"
|
||||||
|
Classes="resize_border"
|
||||||
|
Height="12" Margin="12,0"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Top"
|
||||||
|
Cursor="TopSide"
|
||||||
|
Tag="{x:Static WindowEdge.North}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderTopRight"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Height="12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Right" VerticalAlignment="Top"
|
||||||
|
Cursor="TopRightCorner"
|
||||||
|
Tag="{x:Static WindowEdge.NorthEast}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderLeft"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Margin="0,12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
||||||
|
Cursor="LeftSide"
|
||||||
|
Tag="{x:Static WindowEdge.West}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderRight"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Margin="0,12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Right" VerticalAlignment="Stretch"
|
||||||
|
Cursor="RightSide"
|
||||||
|
Tag="{x:Static WindowEdge.East}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderBottomLeft"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Height="12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Left" VerticalAlignment="Bottom"
|
||||||
|
Cursor="BottomLeftCorner"
|
||||||
|
Tag="{x:Static WindowEdge.SouthWest}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderBottom"
|
||||||
|
Classes="resize_border"
|
||||||
|
Height="12" Margin="12,0"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
|
||||||
|
Cursor="BottomSide"
|
||||||
|
Tag="{x:Static WindowEdge.South}"/>
|
||||||
|
|
||||||
|
<Border x:Name="PART_BorderBottomRight"
|
||||||
|
Classes="resize_border"
|
||||||
|
Width="12" Height="12"
|
||||||
|
Background="Transparent"
|
||||||
|
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
||||||
|
Cursor="BottomRightCorner"
|
||||||
|
Tag="{x:Static WindowEdge.SouthEast}"/>
|
||||||
|
|
||||||
|
<Grid Margin="{TemplateBinding Padding}" Effect="drop-shadow(0 0 12 #A0000000)">
|
||||||
|
<Border x:Name="PART_ContentRoot"
|
||||||
|
Background="{DynamicResource Brush.Window}"
|
||||||
|
BorderBrush="{DynamicResource Brush.WindowBorder}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8">
|
||||||
|
<VisualLayerManager>
|
||||||
|
<Border CornerRadius="8" ClipToBounds="True">
|
||||||
|
<ContentPresenter Name="PART_ContentPresenter"
|
||||||
|
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||||
|
Content="{TemplateBinding Content}"
|
||||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
|
||||||
|
</Border>
|
||||||
|
</VisualLayerManager>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window.custom_window_frame[WindowState=Maximized]">
|
||||||
|
<Setter Property="Padding" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window.custom_window_frame[WindowState=Maximized] /template/ Border#PART_ContentRoot">
|
||||||
|
<Setter Property="BorderThickness" Value="0"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window.custom_window_frame[WindowState=Maximized] /template/ Border.resize_border">
|
||||||
|
<Setter Property="IsVisible" Value="False"/>
|
||||||
|
<Setter Property="IsHitTestVisible" Value="False"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="Window.custom_window_frame[CanResize=False] /template/ Border.resize_border">
|
||||||
|
<Setter Property="IsVisible" Value="False"/>
|
||||||
|
<Setter Property="IsHitTestVisible" Value="False"/>
|
||||||
|
</Style>
|
||||||
|
|
||||||
<Style Selector="ContentPresenter">
|
<Style Selector="ContentPresenter">
|
||||||
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFont}"/>
|
<Setter Property="FontFamily" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFont}"/>
|
||||||
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>
|
<Setter Property="FontSize" Value="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize}"/>
|
||||||
|
@ -1163,4 +1300,22 @@
|
||||||
<Style Selector="TreeDataGridExpanderCell[IsExpanded=False] Path.folder_icon">
|
<Style Selector="TreeDataGridExpanderCell[IsExpanded=False] Path.folder_icon">
|
||||||
<Setter Property="Data" Value="{StaticResource Icons.Folder.Fill}"/>
|
<Setter Property="Data" Value="{StaticResource Icons.Folder.Fill}"/>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
<Style Selector="NumericUpDown">
|
||||||
|
<Style Selector="^ /template/ ButtonSpinner#PART_Spinner">
|
||||||
|
<Setter Property="MinHeight" Value="0"/>
|
||||||
|
<Setter Property="Height" Value="28"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^ /template/ TextBox#PART_TextBox">
|
||||||
|
<Setter Property="MinHeight" Value="0"/>
|
||||||
|
<Setter Property="Height" Value="28"/>
|
||||||
|
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^:focus-within /template/ ButtonSpinner#PART_Spinner">
|
||||||
|
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Accent}"/>
|
||||||
|
</Style>
|
||||||
|
<Style Selector="^ /template/ TextBox#PART_TextBox /template/ Border#PART_BorderElement">
|
||||||
|
<Setter Property="IsVisible" Value="False"/>
|
||||||
|
</Style>
|
||||||
|
</Style>
|
||||||
</Styles>
|
</Styles>
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
<Color x:Key="Color.MacOS.Minimize">#FFFFBE2F</Color>
|
<Color x:Key="Color.MacOS.Minimize">#FFFFBE2F</Color>
|
||||||
<Color x:Key="Color.MacOS.Maximize">#FF29c941</Color>
|
<Color x:Key="Color.MacOS.Maximize">#FF29c941</Color>
|
||||||
<Color x:Key="Color.Window">#FFF0F5F9</Color>
|
<Color x:Key="Color.Window">#FFF0F5F9</Color>
|
||||||
|
<Color x:Key="Color.WindowBorder">#FFAFAFAF</Color>
|
||||||
<Color x:Key="Color.TitleBar">#FFCFDEEA</Color>
|
<Color x:Key="Color.TitleBar">#FFCFDEEA</Color>
|
||||||
<Color x:Key="Color.ToolBar">#FFF0F5F9</Color>
|
<Color x:Key="Color.ToolBar">#FFF0F5F9</Color>
|
||||||
<Color x:Key="Color.Popup">#FFF8F8F8</Color>
|
<Color x:Key="Color.Popup">#FFF8F8F8</Color>
|
||||||
|
@ -14,22 +15,21 @@
|
||||||
<Color x:Key="Color.Decorator">#FF6F6F6F</Color>
|
<Color x:Key="Color.Decorator">#FF6F6F6F</Color>
|
||||||
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
||||||
<Color x:Key="Color.Conflict">#FF836C2E</Color>
|
<Color x:Key="Color.Conflict">#FF836C2E</Color>
|
||||||
|
<Color x:Key="Color.ConflictForeground">#FFFFFFFF</Color>
|
||||||
<Color x:Key="Color.Border0">#FFCFCFCF</Color>
|
<Color x:Key="Color.Border0">#FFCFCFCF</Color>
|
||||||
<Color x:Key="Color.Border1">#FF898989</Color>
|
<Color x:Key="Color.Border1">#FF898989</Color>
|
||||||
<Color x:Key="Color.Border2">#FFCFCFCF</Color>
|
<Color x:Key="Color.Border2">#FFCFCFCF</Color>
|
||||||
<Color x:Key="Color.Border3">#FFEFEFEF</Color>
|
|
||||||
<Color x:Key="Color.FlatButton.Background">#FFF8F8F8</Color>
|
<Color x:Key="Color.FlatButton.Background">#FFF8F8F8</Color>
|
||||||
<Color x:Key="Color.FlatButton.BackgroundHovered">White</Color>
|
<Color x:Key="Color.FlatButton.BackgroundHovered">White</Color>
|
||||||
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF4295FF</Color>
|
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF4295FF</Color>
|
||||||
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF529DFB</Color>
|
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF529DFB</Color>
|
||||||
<Color x:Key="Color.FG1">#FF1F1F1F</Color>
|
<Color x:Key="Color.FG1">#FF1F1F1F</Color>
|
||||||
<Color x:Key="Color.FG2">#FF6F6F6F</Color>
|
<Color x:Key="Color.FG2">#FF6F6F6F</Color>
|
||||||
<Color x:Key="Color.FG3">#FFFFFFFF</Color>
|
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.EMPTY">#3C000000</Color>
|
<Color x:Key="Color.Diff.AddedBG">#3C00FF00</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.ADD">#3C00FF00</Color>
|
<Color x:Key="Color.Diff.DeletedBG">#3CFF0000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.DELETED">#3CFF0000</Color>
|
<Color x:Key="Color.Diff.AddedHighlight">#5A00FF00</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG2.ADD">#5A00FF00</Color>
|
<Color x:Key="Color.Diff.DeletedHighlight">#50FF0000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG2.DELETED">#50FF0000</Color>
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
||||||
<ResourceDictionary x:Key="Dark">
|
<ResourceDictionary x:Key="Dark">
|
||||||
|
@ -37,6 +37,7 @@
|
||||||
<Color x:Key="Color.MacOS.Minimize">#FFFCBB2D</Color>
|
<Color x:Key="Color.MacOS.Minimize">#FFFCBB2D</Color>
|
||||||
<Color x:Key="Color.MacOS.Maximize">#FF25C53C</Color>
|
<Color x:Key="Color.MacOS.Maximize">#FF25C53C</Color>
|
||||||
<Color x:Key="Color.Window">#FF252525</Color>
|
<Color x:Key="Color.Window">#FF252525</Color>
|
||||||
|
<Color x:Key="Color.WindowBorder">#FF444444</Color>
|
||||||
<Color x:Key="Color.TitleBar">#FF1F1F1F</Color>
|
<Color x:Key="Color.TitleBar">#FF1F1F1F</Color>
|
||||||
<Color x:Key="Color.ToolBar">#FF2C2C2C</Color>
|
<Color x:Key="Color.ToolBar">#FF2C2C2C</Color>
|
||||||
<Color x:Key="Color.Popup">#FF2B2B2B</Color>
|
<Color x:Key="Color.Popup">#FF2B2B2B</Color>
|
||||||
|
@ -45,22 +46,21 @@
|
||||||
<Color x:Key="Color.Decorator">#FF505050</Color>
|
<Color x:Key="Color.Decorator">#FF505050</Color>
|
||||||
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
<Color x:Key="Color.DecoratorIcon">#FFF8F8F8</Color>
|
||||||
<Color x:Key="Color.Conflict">#FFFAFAD2</Color>
|
<Color x:Key="Color.Conflict">#FFFAFAD2</Color>
|
||||||
|
<Color x:Key="Color.ConflictForeground">#FF252525</Color>
|
||||||
<Color x:Key="Color.Border0">#FF181818</Color>
|
<Color x:Key="Color.Border0">#FF181818</Color>
|
||||||
<Color x:Key="Color.Border1">#FF7C7C7C</Color>
|
<Color x:Key="Color.Border1">#FF7C7C7C</Color>
|
||||||
<Color x:Key="Color.Border2">#FF404040</Color>
|
<Color x:Key="Color.Border2">#FF404040</Color>
|
||||||
<Color x:Key="Color.Border3">#FF252525</Color>
|
|
||||||
<Color x:Key="Color.FlatButton.Background">#FF303030</Color>
|
<Color x:Key="Color.FlatButton.Background">#FF303030</Color>
|
||||||
<Color x:Key="Color.FlatButton.BackgroundHovered">#FF333333</Color>
|
<Color x:Key="Color.FlatButton.BackgroundHovered">#FF333333</Color>
|
||||||
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF3A3A3A</Color>
|
<Color x:Key="Color.FlatButton.PrimaryBackground">#FF3A3A3A</Color>
|
||||||
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF404040</Color>
|
<Color x:Key="Color.FlatButton.PrimaryBackgroundHovered">#FF404040</Color>
|
||||||
<Color x:Key="Color.FG1">#FFDDDDDD</Color>
|
<Color x:Key="Color.FG1">#FFDDDDDD</Color>
|
||||||
<Color x:Key="Color.FG2">#40F1F1F1</Color>
|
<Color x:Key="Color.FG2">#40F1F1F1</Color>
|
||||||
<Color x:Key="Color.FG3">#FF252525</Color>
|
<Color x:Key="Color.Diff.EmptyBG">#3C000000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.EMPTY">#3C000000</Color>
|
<Color x:Key="Color.Diff.AddedBG">#3C00FF00</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.ADD">#3C00FF00</Color>
|
<Color x:Key="Color.Diff.DeletedBG">#3CFF0000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG1.DELETED">#3CFF0000</Color>
|
<Color x:Key="Color.Diff.AddedHighlight">#5A00FF00</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG2.ADD">#5A00FF00</Color>
|
<Color x:Key="Color.Diff.DeletedHighlight">#50FF0000</Color>
|
||||||
<Color x:Key="Color.TextDiffView.LineBG2.DELETED">#50FF0000</Color>
|
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
</ResourceDictionary.ThemeDictionaries>
|
</ResourceDictionary.ThemeDictionaries>
|
||||||
|
|
||||||
|
@ -68,6 +68,7 @@
|
||||||
<SolidColorBrush x:Key="Brush.MacOS.Minimize" Color="{DynamicResource Color.MacOS.Minimize}"/>
|
<SolidColorBrush x:Key="Brush.MacOS.Minimize" Color="{DynamicResource Color.MacOS.Minimize}"/>
|
||||||
<SolidColorBrush x:Key="Brush.MacOS.Maximize" Color="{DynamicResource Color.MacOS.Maximize}"/>
|
<SolidColorBrush x:Key="Brush.MacOS.Maximize" Color="{DynamicResource Color.MacOS.Maximize}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Window" Color="{DynamicResource Color.Window}"/>
|
<SolidColorBrush x:Key="Brush.Window" Color="{DynamicResource Color.Window}"/>
|
||||||
|
<SolidColorBrush x:Key="Brush.WindowBorder" Color="{DynamicResource Color.WindowBorder}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TitleBar" Color="{DynamicResource Color.TitleBar}"/>
|
<SolidColorBrush x:Key="Brush.TitleBar" Color="{DynamicResource Color.TitleBar}"/>
|
||||||
<SolidColorBrush x:Key="Brush.ToolBar" Color="{DynamicResource Color.ToolBar}"/>
|
<SolidColorBrush x:Key="Brush.ToolBar" Color="{DynamicResource Color.ToolBar}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Popup" Color="{DynamicResource Color.Popup}"/>
|
<SolidColorBrush x:Key="Brush.Popup" Color="{DynamicResource Color.Popup}"/>
|
||||||
|
@ -76,22 +77,21 @@
|
||||||
<SolidColorBrush x:Key="Brush.Decorator" Color="{DynamicResource Color.Decorator}"/>
|
<SolidColorBrush x:Key="Brush.Decorator" Color="{DynamicResource Color.Decorator}"/>
|
||||||
<SolidColorBrush x:Key="Brush.DecoratorIcon" Color="{DynamicResource Color.DecoratorIcon}"/>
|
<SolidColorBrush x:Key="Brush.DecoratorIcon" Color="{DynamicResource Color.DecoratorIcon}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
|
<SolidColorBrush x:Key="Brush.Conflict" Color="{DynamicResource Color.Conflict}"/>
|
||||||
|
<SolidColorBrush x:Key="Brush.ConflictForeground" Color="{DynamicResource Color.ConflictForeground}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/>
|
<SolidColorBrush x:Key="Brush.Border0" Color="{DynamicResource Color.Border0}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Border1" Color="{DynamicResource Color.Border1}"/>
|
<SolidColorBrush x:Key="Brush.Border1" Color="{DynamicResource Color.Border1}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/>
|
<SolidColorBrush x:Key="Brush.Border2" Color="{DynamicResource Color.Border2}"/>
|
||||||
<SolidColorBrush x:Key="Brush.Border3" Color="{DynamicResource Color.Border3}"/>
|
|
||||||
<SolidColorBrush x:Key="Brush.FlatButton.Background" Color="{DynamicResource Color.FlatButton.Background}"/>
|
<SolidColorBrush x:Key="Brush.FlatButton.Background" Color="{DynamicResource Color.FlatButton.Background}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FlatButton.BackgroundHovered" Color="{DynamicResource Color.FlatButton.BackgroundHovered}"/>
|
<SolidColorBrush x:Key="Brush.FlatButton.BackgroundHovered" Color="{DynamicResource Color.FlatButton.BackgroundHovered}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackground" Color="{DynamicResource Color.FlatButton.PrimaryBackground}"/>
|
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackground" Color="{DynamicResource Color.FlatButton.PrimaryBackground}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackgroundHovered" Color="{DynamicResource Color.FlatButton.PrimaryBackgroundHovered}"/>
|
<SolidColorBrush x:Key="Brush.FlatButton.PrimaryBackgroundHovered" Color="{DynamicResource Color.FlatButton.PrimaryBackgroundHovered}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FG1" Color="{DynamicResource Color.FG1}"/>
|
<SolidColorBrush x:Key="Brush.FG1" Color="{DynamicResource Color.FG1}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FG2" Color="{DynamicResource Color.FG2}"/>
|
<SolidColorBrush x:Key="Brush.FG2" Color="{DynamicResource Color.FG2}"/>
|
||||||
<SolidColorBrush x:Key="Brush.FG3" Color="{DynamicResource Color.FG3}"/>
|
|
||||||
<SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/>
|
<SolidColorBrush x:Key="Brush.Accent" Color="{DynamicResource SystemAccentColor}"/>
|
||||||
<SolidColorBrush x:Key="Brush.AccentHovered" Color="{DynamicResource SystemListLowColor}"/>
|
<SolidColorBrush x:Key="Brush.AccentHovered" Color="{DynamicResource SystemListLowColor}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.EMPTY" Color="{DynamicResource Color.TextDiffView.LineBG1.EMPTY}"/>
|
<SolidColorBrush x:Key="Brush.Diff.EmptyBG" Color="{DynamicResource Color.Diff.EmptyBG}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.ADD" Color="{DynamicResource Color.TextDiffView.LineBG1.ADD}"/>
|
<SolidColorBrush x:Key="Brush.Diff.AddedBG" Color="{DynamicResource Color.Diff.AddedBG}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG1.DELETED" Color="{DynamicResource Color.TextDiffView.LineBG1.DELETED}"/>
|
<SolidColorBrush x:Key="Brush.Diff.DeletedBG" Color="{DynamicResource Color.Diff.DeletedBG}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG2.ADD" Color="{DynamicResource Color.TextDiffView.LineBG2.ADD}"/>
|
<SolidColorBrush x:Key="Brush.Diff.AddedHighlight" Color="{DynamicResource Color.Diff.AddedHighlight}"/>
|
||||||
<SolidColorBrush x:Key="Brush.TextDiffView.LineBG2.DELETED" Color="{DynamicResource Color.TextDiffView.LineBG2.DELETED}"/>
|
<SolidColorBrush x:Key="Brush.Diff.DeletedHighlight" Color="{DynamicResource Color.Diff.DeletedHighlight}"/>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|
222
src/ViewModels/BranchCompare.cs
Normal file
222
src/ViewModels/BranchCompare.cs
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Threading;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class BranchCompare : ObservableObject
|
||||||
|
{
|
||||||
|
public Models.Branch Base
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.Branch To
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
private set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.Commit BaseHead
|
||||||
|
{
|
||||||
|
get => _baseHead;
|
||||||
|
private set => SetProperty(ref _baseHead, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Models.Commit ToHead
|
||||||
|
{
|
||||||
|
get => _toHead;
|
||||||
|
private set => SetProperty(ref _toHead, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Models.Change> VisibleChanges
|
||||||
|
{
|
||||||
|
get => _visibleChanges;
|
||||||
|
private set => SetProperty(ref _visibleChanges, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Models.Change> SelectedChanges
|
||||||
|
{
|
||||||
|
get => _selectedChanges;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _selectedChanges, value))
|
||||||
|
{
|
||||||
|
if (value != null && value.Count == 1)
|
||||||
|
DiffContext = new DiffContext(_repo, new Models.DiffOption(Base.Head, To.Head, value[0]), _diffContext);
|
||||||
|
else
|
||||||
|
DiffContext = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string SearchFilter
|
||||||
|
{
|
||||||
|
get => _searchFilter;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _searchFilter, value))
|
||||||
|
{
|
||||||
|
RefreshVisible();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DiffContext DiffContext
|
||||||
|
{
|
||||||
|
get => _diffContext;
|
||||||
|
private set => SetProperty(ref _diffContext, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BranchCompare(string repo, Models.Branch baseBranch, Models.Branch toBranch)
|
||||||
|
{
|
||||||
|
_repo = repo;
|
||||||
|
|
||||||
|
Base = baseBranch;
|
||||||
|
To = toBranch;
|
||||||
|
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
var baseHead = new Commands.QuerySingleCommit(_repo, Base.Head).Result();
|
||||||
|
var toHead = new Commands.QuerySingleCommit(_repo, To.Head).Result();
|
||||||
|
_changes = new Commands.CompareRevisions(_repo, Base.Head, To.Head).Result();
|
||||||
|
|
||||||
|
var visible = _changes;
|
||||||
|
if (!string.IsNullOrWhiteSpace(_searchFilter))
|
||||||
|
{
|
||||||
|
visible = new List<Models.Change>();
|
||||||
|
foreach (var c in _changes)
|
||||||
|
{
|
||||||
|
if (c.Path.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
|
||||||
|
visible.Add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
|
{
|
||||||
|
BaseHead = baseHead;
|
||||||
|
ToHead = toHead;
|
||||||
|
VisibleChanges = visible;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NavigateTo(string commitSHA)
|
||||||
|
{
|
||||||
|
var repo = Preference.FindRepository(_repo);
|
||||||
|
if (repo != null)
|
||||||
|
repo.NavigateToCommit(commitSHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ClearSearchFilter()
|
||||||
|
{
|
||||||
|
SearchFilter = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ContextMenu CreateChangeContextMenu()
|
||||||
|
{
|
||||||
|
if (_selectedChanges == null || _selectedChanges.Count != 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var change = _selectedChanges[0];
|
||||||
|
var menu = new ContextMenu();
|
||||||
|
|
||||||
|
var diffWithMerger = new MenuItem();
|
||||||
|
diffWithMerger.Header = App.Text("DiffWithMerger");
|
||||||
|
diffWithMerger.Icon = App.CreateMenuIcon("Icons.Diff");
|
||||||
|
diffWithMerger.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
var opt = new Models.DiffOption(Base.Head, To.Head, change);
|
||||||
|
var type = Preference.Instance.ExternalMergeToolType;
|
||||||
|
var exec = Preference.Instance.ExternalMergeToolPath;
|
||||||
|
|
||||||
|
var tool = Models.ExternalMerger.Supported.Find(x => x.Type == type);
|
||||||
|
if (tool == null || !File.Exists(exec))
|
||||||
|
{
|
||||||
|
App.RaiseException(_repo, "Invalid merge tool in preference setting!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var args = tool.Type != 0 ? tool.DiffCmd : Preference.Instance.ExternalMergeToolDiffCmd;
|
||||||
|
Task.Run(() => Commands.MergeTool.OpenForDiff(_repo, exec, args, opt));
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
menu.Items.Add(diffWithMerger);
|
||||||
|
|
||||||
|
if (change.Index != Models.ChangeState.Deleted)
|
||||||
|
{
|
||||||
|
var full = Path.GetFullPath(Path.Combine(_repo, change.Path));
|
||||||
|
var explore = new MenuItem();
|
||||||
|
explore.Header = App.Text("RevealFile");
|
||||||
|
explore.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
||||||
|
explore.IsEnabled = File.Exists(full);
|
||||||
|
explore.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
Native.OS.OpenInFileManager(full, true);
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
menu.Items.Add(explore);
|
||||||
|
}
|
||||||
|
|
||||||
|
var copyPath = new MenuItem();
|
||||||
|
copyPath.Header = App.Text("CopyPath");
|
||||||
|
copyPath.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||||
|
copyPath.Click += (_, ev) =>
|
||||||
|
{
|
||||||
|
App.CopyText(change.Path);
|
||||||
|
ev.Handled = true;
|
||||||
|
};
|
||||||
|
menu.Items.Add(copyPath);
|
||||||
|
|
||||||
|
var copyFileName = new MenuItem();
|
||||||
|
copyFileName.Header = App.Text("CopyFileName");
|
||||||
|
copyFileName.Icon = App.CreateMenuIcon("Icons.Copy");
|
||||||
|
copyFileName.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
App.CopyText(Path.GetFileName(change.Path));
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
menu.Items.Add(copyFileName);
|
||||||
|
|
||||||
|
return menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RefreshVisible()
|
||||||
|
{
|
||||||
|
if (_changes == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_searchFilter))
|
||||||
|
{
|
||||||
|
VisibleChanges = _changes;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var visible = new List<Models.Change>();
|
||||||
|
foreach (var c in _changes)
|
||||||
|
{
|
||||||
|
if (c.Path.Contains(_searchFilter, StringComparison.OrdinalIgnoreCase))
|
||||||
|
visible.Add(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
VisibleChanges = visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _repo = string.Empty;
|
||||||
|
private Models.Commit _baseHead = null;
|
||||||
|
private Models.Commit _toHead = null;
|
||||||
|
private List<Models.Change> _changes = null;
|
||||||
|
private List<Models.Change> _visibleChanges = null;
|
||||||
|
private List<Models.Change> _selectedChanges = null;
|
||||||
|
private string _searchFilter = string.Empty;
|
||||||
|
private DiffContext _diffContext = null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -385,6 +385,7 @@ namespace SourceGit.ViewModels
|
||||||
FullMessage = string.Empty;
|
FullMessage = string.Empty;
|
||||||
VisibleChanges = null;
|
VisibleChanges = null;
|
||||||
SelectedChanges = null;
|
SelectedChanges = null;
|
||||||
|
ViewRevisionFileContent = null;
|
||||||
|
|
||||||
if (_commit == null)
|
if (_commit == null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,10 +4,15 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
public class GitFlowFinish : Popup
|
public class GitFlowFinish : Popup
|
||||||
{
|
{
|
||||||
public Models.Branch Branch => _branch;
|
public Models.Branch Branch
|
||||||
public bool IsFeature => _type == Models.GitFlowBranchType.Feature;
|
{
|
||||||
public bool IsRelease => _type == Models.GitFlowBranchType.Release;
|
get;
|
||||||
public bool IsHotfix => _type == Models.GitFlowBranchType.Hotfix;
|
set;
|
||||||
|
} = null;
|
||||||
|
|
||||||
|
public bool IsFeature => _type == "feature";
|
||||||
|
public bool IsRelease => _type == "release";
|
||||||
|
public bool IsHotfix => _type == "hotfix";
|
||||||
|
|
||||||
public bool KeepBranch
|
public bool KeepBranch
|
||||||
{
|
{
|
||||||
|
@ -15,11 +20,13 @@ namespace SourceGit.ViewModels
|
||||||
set;
|
set;
|
||||||
} = false;
|
} = false;
|
||||||
|
|
||||||
public GitFlowFinish(Repository repo, Models.Branch branch, Models.GitFlowBranchType type)
|
public GitFlowFinish(Repository repo, Models.Branch branch, string type, string prefix)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_branch = branch;
|
|
||||||
_type = type;
|
_type = type;
|
||||||
|
_prefix = prefix;
|
||||||
|
|
||||||
|
Branch = branch;
|
||||||
View = new Views.GitFlowFinish() { DataContext = this };
|
View = new Views.GitFlowFinish() { DataContext = this };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,29 +35,16 @@ namespace SourceGit.ViewModels
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
var branch = _branch.Name;
|
var name = Branch.Name.StartsWith(_prefix) ? Branch.Name.Substring(_prefix.Length) : Branch.Name;
|
||||||
switch (_type)
|
SetProgressDescription($"Git Flow - finishing {_type} {name} ...");
|
||||||
{
|
var succ = Commands.GitFlow.Finish(_repo.FullPath, _type, name, KeepBranch);
|
||||||
case Models.GitFlowBranchType.Feature:
|
|
||||||
branch = branch.Substring(_repo.GitFlow.Feature.Length);
|
|
||||||
break;
|
|
||||||
case Models.GitFlowBranchType.Release:
|
|
||||||
branch = branch.Substring(_repo.GitFlow.Release.Length);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
branch = branch.Substring(_repo.GitFlow.Hotfix.Length);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetProgressDescription($"Git Flow - finishing {_branch.Name} ...");
|
|
||||||
var succ = new Commands.GitFlow(_repo.FullPath).Finish(_type, branch, KeepBranch);
|
|
||||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||||
return succ;
|
return succ;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Repository _repo = null;
|
private readonly Repository _repo = null;
|
||||||
private readonly Models.Branch _branch = null;
|
private readonly string _type = "feature";
|
||||||
private readonly Models.GitFlowBranchType _type = Models.GitFlowBranchType.None;
|
private readonly string _prefix = string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,15 @@ namespace SourceGit.ViewModels
|
||||||
get => _prefix;
|
get => _prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsFeature => _type == Models.GitFlowBranchType.Feature;
|
public bool IsFeature => _type == "feature";
|
||||||
public bool IsRelease => _type == Models.GitFlowBranchType.Release;
|
public bool IsRelease => _type == "release";
|
||||||
public bool IsHotfix => _type == Models.GitFlowBranchType.Hotfix;
|
public bool IsHotfix => _type == "hotfix";
|
||||||
|
|
||||||
public GitFlowStart(Repository repo, Models.GitFlowBranchType type)
|
public GitFlowStart(Repository repo, string type)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
_type = type;
|
_type = type;
|
||||||
|
_prefix = Commands.GitFlow.Prefix(repo.FullPath, type);
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case Models.GitFlowBranchType.Feature:
|
|
||||||
_prefix = repo.GitFlow.Feature;
|
|
||||||
break;
|
|
||||||
case Models.GitFlowBranchType.Release:
|
|
||||||
_prefix = repo.GitFlow.Release;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_prefix = repo.GitFlow.Hotfix;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
View = new Views.GitFlowStart() { DataContext = this };
|
View = new Views.GitFlowStart() { DataContext = this };
|
||||||
}
|
}
|
||||||
|
@ -65,15 +53,15 @@ namespace SourceGit.ViewModels
|
||||||
_repo.SetWatcherEnabled(false);
|
_repo.SetWatcherEnabled(false);
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
SetProgressDescription($"Git Flow - starting {_prefix}{_name} ...");
|
SetProgressDescription($"Git Flow - starting {_type} {_name} ...");
|
||||||
var succ = new Commands.GitFlow(_repo.FullPath).Start(_type, _name);
|
var succ = Commands.GitFlow.Start(_repo.FullPath, _type, _name);
|
||||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||||
return succ;
|
return succ;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private readonly Repository _repo = null;
|
private readonly Repository _repo = null;
|
||||||
private readonly Models.GitFlowBranchType _type = Models.GitFlowBranchType.Feature;
|
private readonly string _type = "feature";
|
||||||
private readonly string _prefix = string.Empty;
|
private readonly string _prefix = string.Empty;
|
||||||
private string _name = null;
|
private string _name = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -209,17 +209,6 @@ namespace SourceGit.ViewModels
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
menu.Items.Add(reset);
|
menu.Items.Add(reset);
|
||||||
|
|
||||||
var checkoutCommit = new MenuItem();
|
|
||||||
checkoutCommit.Header = App.Text("CommitCM.Checkout");
|
|
||||||
checkoutCommit.Icon = App.CreateMenuIcon("Icons.Check");
|
|
||||||
checkoutCommit.Click += (o, e) =>
|
|
||||||
{
|
|
||||||
if (PopupHost.CanCreatePopup())
|
|
||||||
PopupHost.ShowPopup(new CheckoutCommit(_repo, commit));
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
menu.Items.Add(checkoutCommit);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -290,6 +279,20 @@ namespace SourceGit.ViewModels
|
||||||
menu.Items.Add(revert);
|
menu.Items.Add(revert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (current.Head != commit.SHA)
|
||||||
|
{
|
||||||
|
var checkoutCommit = new MenuItem();
|
||||||
|
checkoutCommit.Header = App.Text("CommitCM.Checkout");
|
||||||
|
checkoutCommit.Icon = App.CreateMenuIcon("Icons.Detached");
|
||||||
|
checkoutCommit.Click += (o, e) =>
|
||||||
|
{
|
||||||
|
if (PopupHost.CanCreatePopup())
|
||||||
|
PopupHost.ShowPopup(new CheckoutCommit(_repo, commit));
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
menu.Items.Add(checkoutCommit);
|
||||||
|
}
|
||||||
|
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
if (current.Head != commit.SHA)
|
if (current.Head != commit.SHA)
|
||||||
|
@ -448,8 +451,8 @@ namespace SourceGit.ViewModels
|
||||||
submenu.Items.Add(push);
|
submenu.Items.Add(push);
|
||||||
submenu.Items.Add(new MenuItem() { Header = "-" });
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
var type = _repo.GitFlow.GetBranchType(current.Name);
|
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, current.Name);
|
||||||
if (type != Models.GitFlowBranchType.None)
|
if (detect.IsGitFlowBranch)
|
||||||
{
|
{
|
||||||
var finish = new MenuItem();
|
var finish = new MenuItem();
|
||||||
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name);
|
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", current.Name);
|
||||||
|
@ -457,7 +460,7 @@ namespace SourceGit.ViewModels
|
||||||
finish.Click += (o, e) =>
|
finish.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowFinish(_repo, current, type));
|
PopupHost.ShowPopup(new GitFlowFinish(_repo, current, detect.Type, detect.Prefix));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
submenu.Items.Add(finish);
|
submenu.Items.Add(finish);
|
||||||
|
@ -507,8 +510,8 @@ namespace SourceGit.ViewModels
|
||||||
submenu.Items.Add(merge);
|
submenu.Items.Add(merge);
|
||||||
submenu.Items.Add(new MenuItem() { Header = "-" });
|
submenu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
var type = _repo.GitFlow.GetBranchType(branch.Name);
|
var detect = Commands.GitFlow.DetectType(_repo.FullPath, _repo.Branches, branch.Name);
|
||||||
if (type != Models.GitFlowBranchType.None)
|
if (detect.IsGitFlowBranch)
|
||||||
{
|
{
|
||||||
var finish = new MenuItem();
|
var finish = new MenuItem();
|
||||||
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
|
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
|
||||||
|
@ -516,7 +519,7 @@ namespace SourceGit.ViewModels
|
||||||
finish.Click += (o, e) =>
|
finish.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowFinish(_repo, branch, type));
|
PopupHost.ShowPopup(new GitFlowFinish(_repo, branch, detect.Type, detect.Prefix));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
submenu.Items.Add(finish);
|
submenu.Items.Add(finish);
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -6,7 +7,6 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
public partial class InitGitFlow : Popup
|
public partial class InitGitFlow : Popup
|
||||||
{
|
{
|
||||||
|
|
||||||
[GeneratedRegex(@"^[\w\-/\.]+$")]
|
[GeneratedRegex(@"^[\w\-/\.]+$")]
|
||||||
private static partial Regex TAG_PREFIX();
|
private static partial Regex TAG_PREFIX();
|
||||||
|
|
||||||
|
@ -62,6 +62,23 @@ namespace SourceGit.ViewModels
|
||||||
public InitGitFlow(Repository repo)
|
public InitGitFlow(Repository repo)
|
||||||
{
|
{
|
||||||
_repo = repo;
|
_repo = repo;
|
||||||
|
|
||||||
|
var localBranches = new List<string>();
|
||||||
|
foreach (var branch in repo.Branches)
|
||||||
|
{
|
||||||
|
if (branch.IsLocal)
|
||||||
|
localBranches.Add(branch.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localBranches.Contains("master"))
|
||||||
|
_master = "master";
|
||||||
|
else if (localBranches.Contains("main"))
|
||||||
|
_master = "main";
|
||||||
|
else if (localBranches.Count > 0)
|
||||||
|
_master = localBranches[0];
|
||||||
|
else
|
||||||
|
_master = "master";
|
||||||
|
|
||||||
View = new Views.InitGitFlow() { DataContext = this };
|
View = new Views.InitGitFlow() { DataContext = this };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +96,7 @@ namespace SourceGit.ViewModels
|
||||||
public static ValidationResult ValidateTagPrefix(string tagPrefix, ValidationContext ctx)
|
public static ValidationResult ValidateTagPrefix(string tagPrefix, ValidationContext ctx)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrWhiteSpace(tagPrefix) && !TAG_PREFIX().IsMatch(tagPrefix))
|
if (!string.IsNullOrWhiteSpace(tagPrefix) && !TAG_PREFIX().IsMatch(tagPrefix))
|
||||||
{
|
|
||||||
return new ValidationResult("Bad tag prefix format!");
|
return new ValidationResult("Bad tag prefix format!");
|
||||||
}
|
|
||||||
|
|
||||||
return ValidationResult.Success;
|
return ValidationResult.Success;
|
||||||
}
|
}
|
||||||
|
@ -93,14 +108,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
return Task.Run(() =>
|
return Task.Run(() =>
|
||||||
{
|
{
|
||||||
var succ = new Commands.GitFlow(_repo.FullPath).Init(_repo.Branches, _master, _develop, _featurePrefix, _releasePrefix, _hotfixPrefix, _tagPrefix);
|
var succ = Commands.GitFlow.Init(_repo.FullPath, _repo.Branches, _master, _develop, _featurePrefix, _releasePrefix, _hotfixPrefix, _tagPrefix);
|
||||||
if (succ)
|
|
||||||
{
|
|
||||||
_repo.GitFlow.Feature = _featurePrefix;
|
|
||||||
_repo.GitFlow.Release = _releasePrefix;
|
|
||||||
_repo.GitFlow.Hotfix = _hotfixPrefix;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
CallUIThread(() => _repo.SetWatcherEnabled(true));
|
||||||
return succ;
|
return succ;
|
||||||
});
|
});
|
||||||
|
|
|
@ -136,6 +136,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() };
|
last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() };
|
||||||
last.Data = Welcome.Instance;
|
last.Data = Welcome.Instance;
|
||||||
|
last.Popup = null;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
@ -188,6 +189,7 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
Pages = new AvaloniaList<LauncherPage> { ActivePage };
|
Pages = new AvaloniaList<LauncherPage> { ActivePage };
|
||||||
|
OnPropertyChanged(nameof(Pages));
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
86
src/ViewModels/LayoutInfo.cs
Normal file
86
src/ViewModels/LayoutInfo.cs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
using Avalonia.Controls;
|
||||||
|
|
||||||
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
|
namespace SourceGit.ViewModels
|
||||||
|
{
|
||||||
|
public class LayoutInfo : ObservableObject
|
||||||
|
{
|
||||||
|
public double LauncherWidth
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = 1280;
|
||||||
|
|
||||||
|
public double LauncherHeight
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = 720;
|
||||||
|
|
||||||
|
public WindowState LauncherWindowState
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
} = WindowState.Normal;
|
||||||
|
|
||||||
|
[JsonConverter(typeof(GridLengthConverter))]
|
||||||
|
public GridLength RepositorySidebarWidth
|
||||||
|
{
|
||||||
|
get => _repositorySidebarWidth;
|
||||||
|
set => SetProperty(ref _repositorySidebarWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(GridLengthConverter))]
|
||||||
|
public GridLength WorkingCopyLeftWidth
|
||||||
|
{
|
||||||
|
get => _workingCopyLeftWidth;
|
||||||
|
set => SetProperty(ref _workingCopyLeftWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(GridLengthConverter))]
|
||||||
|
public GridLength StashesLeftWidth
|
||||||
|
{
|
||||||
|
get => _stashesLeftWidth;
|
||||||
|
set => SetProperty(ref _stashesLeftWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(GridLengthConverter))]
|
||||||
|
public GridLength CommitDetailChangesLeftWidth
|
||||||
|
{
|
||||||
|
get => _commitDetailChangesLeftWidth;
|
||||||
|
set => SetProperty(ref _commitDetailChangesLeftWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
[JsonConverter(typeof(GridLengthConverter))]
|
||||||
|
public GridLength CommitDetailFilesLeftWidth
|
||||||
|
{
|
||||||
|
get => _commitDetailFilesLeftWidth;
|
||||||
|
set => SetProperty(ref _commitDetailFilesLeftWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private GridLength _repositorySidebarWidth = new GridLength(250, GridUnitType.Pixel);
|
||||||
|
private GridLength _workingCopyLeftWidth = new GridLength(300, GridUnitType.Pixel);
|
||||||
|
private GridLength _stashesLeftWidth = new GridLength(300, GridUnitType.Pixel);
|
||||||
|
private GridLength _commitDetailChangesLeftWidth = new GridLength(256, GridUnitType.Pixel);
|
||||||
|
private GridLength _commitDetailFilesLeftWidth = new GridLength(256, GridUnitType.Pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GridLengthConverter : JsonConverter<GridLength>
|
||||||
|
{
|
||||||
|
public override GridLength Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
var size = reader.GetDouble();
|
||||||
|
return new GridLength(size, GridUnitType.Pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(Utf8JsonWriter writer, GridLength value, JsonSerializerOptions options)
|
||||||
|
{
|
||||||
|
writer.WriteNumberValue(value.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -109,6 +109,12 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _defaultFontSize, value);
|
set => SetProperty(ref _defaultFontSize, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LayoutInfo Layout
|
||||||
|
{
|
||||||
|
get => _layout;
|
||||||
|
set => SetProperty(ref _layout, value);
|
||||||
|
}
|
||||||
|
|
||||||
public string AvatarServer
|
public string AvatarServer
|
||||||
{
|
{
|
||||||
get => Models.AvatarManager.SelectedServer;
|
get => Models.AvatarManager.SelectedServer;
|
||||||
|
@ -531,6 +537,7 @@ namespace SourceGit.ViewModels
|
||||||
private FontFamily _defaultFont = null;
|
private FontFamily _defaultFont = null;
|
||||||
private FontFamily _monospaceFont = null;
|
private FontFamily _monospaceFont = null;
|
||||||
private double _defaultFontSize = 13;
|
private double _defaultFontSize = 13;
|
||||||
|
private LayoutInfo _layout = new LayoutInfo();
|
||||||
|
|
||||||
private int _maxHistoryCommits = 20000;
|
private int _maxHistoryCommits = 20000;
|
||||||
private bool _restoreTabs = false;
|
private bool _restoreTabs = false;
|
||||||
|
|
|
@ -51,13 +51,6 @@ namespace SourceGit.ViewModels
|
||||||
set;
|
set;
|
||||||
} = new AvaloniaList<string>();
|
} = new AvaloniaList<string>();
|
||||||
|
|
||||||
[JsonIgnore]
|
|
||||||
public Models.GitFlow GitFlow
|
|
||||||
{
|
|
||||||
get => _gitflow;
|
|
||||||
set => SetProperty(ref _gitflow, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public int SelectedViewIndex
|
public int SelectedViewIndex
|
||||||
{
|
{
|
||||||
|
@ -298,7 +291,6 @@ namespace SourceGit.ViewModels
|
||||||
Task.Run(RefreshSubmodules);
|
Task.Run(RefreshSubmodules);
|
||||||
Task.Run(RefreshWorkingCopyChanges);
|
Task.Run(RefreshWorkingCopyChanges);
|
||||||
Task.Run(RefreshStashes);
|
Task.Run(RefreshStashes);
|
||||||
Task.Run(RefreshGitFlow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OpenInFileManager()
|
public void OpenInFileManager()
|
||||||
|
@ -697,22 +689,6 @@ namespace SourceGit.ViewModels
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RefreshGitFlow()
|
|
||||||
{
|
|
||||||
var config = new Commands.Config(_fullpath).ListAll();
|
|
||||||
var gitFlow = new Models.GitFlow();
|
|
||||||
if (config.TryGetValue("gitflow.prefix.feature", out var feature))
|
|
||||||
gitFlow.Feature = feature;
|
|
||||||
if (config.TryGetValue("gitflow.prefix.release", out var release))
|
|
||||||
gitFlow.Release = release;
|
|
||||||
if (config.TryGetValue("gitflow.prefix.hotfix", out var hotfix))
|
|
||||||
gitFlow.Hotfix = hotfix;
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
|
||||||
{
|
|
||||||
GitFlow = gitFlow;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void CreateNewBranch()
|
public void CreateNewBranch()
|
||||||
{
|
{
|
||||||
var current = Branches.Find(x => x.IsCurrent);
|
var current = Branches.Find(x => x.IsCurrent);
|
||||||
|
@ -797,7 +773,8 @@ namespace SourceGit.ViewModels
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
||||||
|
|
||||||
if (GitFlow.IsEnabled)
|
var isGitFlowEnabled = Commands.GitFlow.IsEnabled(_fullpath, _branches);
|
||||||
|
if (isGitFlowEnabled)
|
||||||
{
|
{
|
||||||
var startFeature = new MenuItem();
|
var startFeature = new MenuItem();
|
||||||
startFeature.Header = App.Text("GitFlow.StartFeature");
|
startFeature.Header = App.Text("GitFlow.StartFeature");
|
||||||
|
@ -805,7 +782,7 @@ namespace SourceGit.ViewModels
|
||||||
startFeature.Click += (o, e) =>
|
startFeature.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Feature));
|
PopupHost.ShowPopup(new GitFlowStart(this, "feature"));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -815,7 +792,7 @@ namespace SourceGit.ViewModels
|
||||||
startRelease.Click += (o, e) =>
|
startRelease.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Release));
|
PopupHost.ShowPopup(new GitFlowStart(this, "release"));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -825,7 +802,7 @@ namespace SourceGit.ViewModels
|
||||||
startHotfix.Click += (o, e) =>
|
startHotfix.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Hotfix));
|
PopupHost.ShowPopup(new GitFlowStart(this, "hotfix"));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -909,6 +886,13 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.Items.Add(push);
|
menu.Items.Add(push);
|
||||||
|
|
||||||
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
||||||
|
if (compareWithBranch != null)
|
||||||
|
{
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
menu.Items.Add(compareWithBranch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -968,24 +952,6 @@ namespace SourceGit.ViewModels
|
||||||
menu.Items.Add(merge);
|
menu.Items.Add(merge);
|
||||||
menu.Items.Add(rebase);
|
menu.Items.Add(rebase);
|
||||||
|
|
||||||
var compare = new MenuItem();
|
|
||||||
compare.Header = App.Text("BranchCM.CompareWithHead");
|
|
||||||
compare.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
||||||
compare.Click += (o, e) =>
|
|
||||||
{
|
|
||||||
SearchResultSelectedCommit = null;
|
|
||||||
|
|
||||||
if (_histories != null)
|
|
||||||
{
|
|
||||||
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
|
||||||
var head = new Commands.QuerySingleCommit(FullPath, current.Head).Result();
|
|
||||||
_histories.AutoSelectedCommit = null;
|
|
||||||
_histories.DetailContext = new RevisionCompare(FullPath, target, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (WorkingCopyChangesCount > 0)
|
if (WorkingCopyChangesCount > 0)
|
||||||
{
|
{
|
||||||
var compareWithWorktree = new MenuItem();
|
var compareWithWorktree = new MenuItem();
|
||||||
|
@ -1002,15 +968,22 @@ namespace SourceGit.ViewModels
|
||||||
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
menu.Items.Add(compareWithWorktree);
|
menu.Items.Add(compareWithWorktree);
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
||||||
menu.Items.Add(compare);
|
if (compareWithBranch != null)
|
||||||
|
{
|
||||||
|
if (WorkingCopyChangesCount == 0)
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
|
menu.Items.Add(compareWithBranch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var type = GitFlow.GetBranchType(branch.Name);
|
var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name);
|
||||||
if (type != Models.GitFlowBranchType.None)
|
if (detect.IsGitFlowBranch)
|
||||||
{
|
{
|
||||||
var finish = new MenuItem();
|
var finish = new MenuItem();
|
||||||
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
|
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
|
||||||
|
@ -1018,7 +991,7 @@ namespace SourceGit.ViewModels
|
||||||
finish.Click += (o, e) =>
|
finish.Click += (o, e) =>
|
||||||
{
|
{
|
||||||
if (PopupHost.CanCreatePopup())
|
if (PopupHost.CanCreatePopup())
|
||||||
PopupHost.ShowPopup(new GitFlowFinish(this, branch, type));
|
PopupHost.ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix));
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
@ -1263,51 +1236,39 @@ namespace SourceGit.ViewModels
|
||||||
menu.Items.Add(merge);
|
menu.Items.Add(merge);
|
||||||
menu.Items.Add(rebase);
|
menu.Items.Add(rebase);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
if (current.Head != branch.Head)
|
|
||||||
{
|
|
||||||
var compare = new MenuItem();
|
|
||||||
compare.Header = App.Text("BranchCM.CompareWithHead");
|
|
||||||
compare.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
||||||
compare.Click += (o, e) =>
|
|
||||||
{
|
|
||||||
SearchResultSelectedCommit = null;
|
|
||||||
|
|
||||||
if (_histories != null)
|
|
||||||
{
|
|
||||||
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
|
||||||
var head = new Commands.QuerySingleCommit(FullPath, current.Head).Result();
|
|
||||||
_histories.AutoSelectedCommit = null;
|
|
||||||
_histories.DetailContext = new RevisionCompare(FullPath, target, head);
|
|
||||||
}
|
|
||||||
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
menu.Items.Add(compare);
|
|
||||||
|
|
||||||
if (WorkingCopyChangesCount > 0)
|
|
||||||
{
|
|
||||||
var compareWithWorktree = new MenuItem();
|
|
||||||
compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree");
|
|
||||||
compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
||||||
compareWithWorktree.Click += (o, e) =>
|
|
||||||
{
|
|
||||||
SearchResultSelectedCommit = null;
|
|
||||||
|
|
||||||
if (_histories != null)
|
|
||||||
{
|
|
||||||
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
|
||||||
_histories.AutoSelectedCommit = null;
|
|
||||||
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
menu.Items.Add(compareWithWorktree);
|
|
||||||
}
|
|
||||||
|
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasCompare = false;
|
||||||
|
if (WorkingCopyChangesCount > 0)
|
||||||
|
{
|
||||||
|
var compareWithWorktree = new MenuItem();
|
||||||
|
compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree");
|
||||||
|
compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare");
|
||||||
|
compareWithWorktree.Click += (o, e) =>
|
||||||
|
{
|
||||||
|
SearchResultSelectedCommit = null;
|
||||||
|
|
||||||
|
if (_histories != null)
|
||||||
|
{
|
||||||
|
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
||||||
|
_histories.AutoSelectedCommit = null;
|
||||||
|
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
menu.Items.Add(compareWithWorktree);
|
||||||
|
hasCompare = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
||||||
|
if (compareWithBranch != null)
|
||||||
|
{
|
||||||
|
menu.Items.Add(compareWithBranch);
|
||||||
|
hasCompare = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasCompare)
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
var delete = new MenuItem();
|
var delete = new MenuItem();
|
||||||
delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", $"{branch.Remote}/{branch.Name}");
|
delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", $"{branch.Remote}/{branch.Name}");
|
||||||
delete.Icon = App.CreateMenuIcon("Icons.Clear");
|
delete.Icon = App.CreateMenuIcon("Icons.Clear");
|
||||||
|
@ -1485,6 +1446,41 @@ namespace SourceGit.ViewModels
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private MenuItem CreateMenuItemToCompareBranches(Models.Branch branch)
|
||||||
|
{
|
||||||
|
if (Branches.Count == 1)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var compare = new MenuItem();
|
||||||
|
compare.Header = App.Text("BranchCM.CompareWithBranch");
|
||||||
|
compare.Icon = App.CreateMenuIcon("Icons.Compare");
|
||||||
|
|
||||||
|
foreach (var b in Branches)
|
||||||
|
{
|
||||||
|
if (b.FullName != branch.FullName)
|
||||||
|
{
|
||||||
|
var dup = b;
|
||||||
|
var target = new MenuItem();
|
||||||
|
target.Header = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
|
||||||
|
target.Icon = App.CreateMenuIcon(b.IsCurrent ? "Icons.Check" : "Icons.Branch");
|
||||||
|
target.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
var wnd = new Views.BranchCompare()
|
||||||
|
{
|
||||||
|
DataContext = new BranchCompare(FullPath, branch, dup)
|
||||||
|
};
|
||||||
|
|
||||||
|
wnd.Show(App.GetTopLevel() as Window);
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
compare.Items.Add(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return compare;
|
||||||
|
}
|
||||||
|
|
||||||
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
||||||
{
|
{
|
||||||
var builder = new BranchTreeNode.Builder();
|
var builder = new BranchTreeNode.Builder();
|
||||||
|
@ -1513,7 +1509,6 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
private string _fullpath = string.Empty;
|
private string _fullpath = string.Empty;
|
||||||
private string _gitDir = string.Empty;
|
private string _gitDir = string.Empty;
|
||||||
private Models.GitFlow _gitflow = new Models.GitFlow();
|
|
||||||
|
|
||||||
private Models.Watcher _watcher = null;
|
private Models.Watcher _watcher = null;
|
||||||
private Histories _histories = null;
|
private Histories _histories = null;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Avalonia;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
|
|
||||||
namespace SourceGit.ViewModels
|
namespace SourceGit.ViewModels
|
||||||
|
@ -11,7 +11,13 @@ namespace SourceGit.ViewModels
|
||||||
public List<Models.TextDiffLine> New { get; set; } = new List<Models.TextDiffLine>();
|
public List<Models.TextDiffLine> New { get; set; } = new List<Models.TextDiffLine>();
|
||||||
public int MaxLineNumber = 0;
|
public int MaxLineNumber = 0;
|
||||||
|
|
||||||
public TwoSideTextDiff(Models.TextDiff diff)
|
public Vector SyncScrollOffset
|
||||||
|
{
|
||||||
|
get => _syncScrollOffset;
|
||||||
|
set => SetProperty(ref _syncScrollOffset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TwoSideTextDiff(Models.TextDiff diff, TwoSideTextDiff previous = null)
|
||||||
{
|
{
|
||||||
File = diff.File;
|
File = diff.File;
|
||||||
MaxLineNumber = diff.MaxLineNumber;
|
MaxLineNumber = diff.MaxLineNumber;
|
||||||
|
@ -35,6 +41,9 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
FillEmptyLines();
|
FillEmptyLines();
|
||||||
|
|
||||||
|
if (previous != null && previous.File == File)
|
||||||
|
_syncScrollOffset = previous._syncScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FillEmptyLines()
|
private void FillEmptyLines()
|
||||||
|
@ -52,5 +61,7 @@ namespace SourceGit.ViewModels
|
||||||
New.Add(new Models.TextDiffLine());
|
New.Add(new Models.TextDiffLine());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Vector _syncScrollOffset = Vector.Zero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -379,24 +379,16 @@ namespace SourceGit.ViewModels
|
||||||
if (isUnstaged)
|
if (isUnstaged)
|
||||||
{
|
{
|
||||||
if (changes.Count == _unstaged.Count && _staged.Count == 0)
|
if (changes.Count == _unstaged.Count && _staged.Count == 0)
|
||||||
{
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo));
|
PopupHost.ShowPopup(new Discard(_repo));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo, changes, true));
|
PopupHost.ShowPopup(new Discard(_repo, changes, true));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (changes.Count == _staged.Count && _unstaged.Count == 0)
|
if (changes.Count == _staged.Count && _unstaged.Count == 0)
|
||||||
{
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo));
|
PopupHost.ShowPopup(new Discard(_repo));
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
PopupHost.ShowPopup(new Discard(_repo, changes, false));
|
PopupHost.ShowPopup(new Discard(_repo, changes, false));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,7 +405,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public ContextMenu CreateContextMenuForUnstagedChanges()
|
public ContextMenu CreateContextMenuForUnstagedChanges()
|
||||||
{
|
{
|
||||||
if (_selectedUnstaged.Count == 0)
|
if (_selectedUnstaged == null || _selectedUnstaged.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
@ -536,6 +528,16 @@ namespace SourceGit.ViewModels
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var assumeUnchanged = new MenuItem();
|
||||||
|
assumeUnchanged.Header = App.Text("FileCM.AssumeUnchanged");
|
||||||
|
assumeUnchanged.Icon = App.CreateMenuIcon("Icons.File.Ignore");
|
||||||
|
assumeUnchanged.IsVisible = change.WorkTree != Models.ChangeState.Untracked;
|
||||||
|
assumeUnchanged.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
new Commands.AssumeUnchanged(_repo.FullPath).Add(change.Path);
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
|
||||||
var history = new MenuItem();
|
var history = new MenuItem();
|
||||||
history.Header = App.Text("FileHistory");
|
history.Header = App.Text("FileHistory");
|
||||||
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
history.Icon = App.CreateMenuIcon("Icons.Histories");
|
||||||
|
@ -546,24 +548,67 @@ namespace SourceGit.ViewModels
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var assumeUnchanged = new MenuItem();
|
|
||||||
assumeUnchanged.Header = App.Text("FileCM.AssumeUnchanged");
|
|
||||||
assumeUnchanged.Icon = App.CreateMenuIcon("Icons.File.Ignore");
|
|
||||||
assumeUnchanged.IsEnabled = change.WorkTree != Models.ChangeState.Untracked;
|
|
||||||
assumeUnchanged.Click += (_, e) =>
|
|
||||||
{
|
|
||||||
new Commands.AssumeUnchanged(_repo.FullPath).Add(change.Path);
|
|
||||||
e.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
menu.Items.Add(stage);
|
menu.Items.Add(stage);
|
||||||
menu.Items.Add(discard);
|
menu.Items.Add(discard);
|
||||||
menu.Items.Add(stash);
|
menu.Items.Add(stash);
|
||||||
menu.Items.Add(patch);
|
menu.Items.Add(patch);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
||||||
menu.Items.Add(history);
|
|
||||||
menu.Items.Add(assumeUnchanged);
|
menu.Items.Add(assumeUnchanged);
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
menu.Items.Add(history);
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
|
||||||
|
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||||
|
{
|
||||||
|
var isRooted = change.Path.IndexOf('/', StringComparison.Ordinal) <= 0;
|
||||||
|
var addToIgnore = new MenuItem();
|
||||||
|
addToIgnore.Header = App.Text("WorkingCopy.AddToGitIgnore");
|
||||||
|
addToIgnore.Icon = App.CreateMenuIcon("Icons.GitIgnore");
|
||||||
|
|
||||||
|
var singleFile = new MenuItem();
|
||||||
|
singleFile.Header = App.Text("WorkingCopy.AddToGitIgnore.SingleFile");
|
||||||
|
singleFile.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
Commands.GitIgnore.Add(_repo.FullPath, change.Path);
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
addToIgnore.Items.Add(singleFile);
|
||||||
|
|
||||||
|
var byParentFolder = new MenuItem();
|
||||||
|
byParentFolder.Header = App.Text("WorkingCopy.AddToGitIgnore.InSameFolder");
|
||||||
|
byParentFolder.IsVisible = !isRooted;
|
||||||
|
byParentFolder.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
Commands.GitIgnore.Add(_repo.FullPath, Path.GetDirectoryName(change.Path) + "/");
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
addToIgnore.Items.Add(byParentFolder);
|
||||||
|
|
||||||
|
var extension = Path.GetExtension(change.Path);
|
||||||
|
if (!string.IsNullOrEmpty(extension))
|
||||||
|
{
|
||||||
|
var byExtension = new MenuItem();
|
||||||
|
byExtension.Header = App.Text("WorkingCopy.AddToGitIgnore.Extension", extension);
|
||||||
|
byExtension.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
Commands.GitIgnore.Add(_repo.FullPath, "*" + extension);
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
addToIgnore.Items.Add(byExtension);
|
||||||
|
|
||||||
|
var byExtensionInSameFolder = new MenuItem();
|
||||||
|
byExtensionInSameFolder.Header = App.Text("WorkingCopy.AddToGitIgnore.ExtensionInSameFolder", extension);
|
||||||
|
byExtensionInSameFolder.IsVisible = !isRooted;
|
||||||
|
byExtensionInSameFolder.Click += (_, e) =>
|
||||||
|
{
|
||||||
|
Commands.GitIgnore.Add(_repo.FullPath, Path.GetDirectoryName(change.Path) + "/*" + extension);
|
||||||
|
e.Handled = true;
|
||||||
|
};
|
||||||
|
addToIgnore.Items.Add(byExtensionInSameFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
menu.Items.Add(addToIgnore);
|
||||||
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var copy = new MenuItem();
|
var copy = new MenuItem();
|
||||||
|
@ -699,7 +744,7 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
public ContextMenu CreateContextMenuForStagedChanges()
|
public ContextMenu CreateContextMenuForStagedChanges()
|
||||||
{
|
{
|
||||||
if (_selectedStaged.Count == 0)
|
if (_selectedStaged == null || _selectedStaged.Count == 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
|
@ -921,24 +966,11 @@ namespace SourceGit.ViewModels
|
||||||
|
|
||||||
var isUnstaged = _selectedUnstaged != null && _selectedUnstaged.Count > 0;
|
var isUnstaged = _selectedUnstaged != null && _selectedUnstaged.Count > 0;
|
||||||
if (change == null)
|
if (change == null)
|
||||||
{
|
|
||||||
DetailContext = null;
|
DetailContext = null;
|
||||||
}
|
|
||||||
else if (change.IsConflit && isUnstaged)
|
else if (change.IsConflit && isUnstaged)
|
||||||
{
|
|
||||||
DetailContext = new ConflictContext(_repo.FullPath, change);
|
DetailContext = new ConflictContext(_repo.FullPath, change);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), _detailContext as DiffContext);
|
||||||
if (_detailContext is DiffContext previous)
|
|
||||||
{
|
|
||||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged), previous);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DetailContext = new DiffContext(_repo.FullPath, new Models.DiffOption(change, isUnstaged));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void UseTheirs(List<Models.Change> changes)
|
private async void UseTheirs(List<Models.Change> changes)
|
||||||
|
|
|
@ -1,28 +1,18 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.About"
|
x:Class="SourceGit.Views.About"
|
||||||
x:DataType="v:About"
|
x:DataType="v:About"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="{DynamicResource Text.About}"
|
Title="{DynamicResource Text.About}"
|
||||||
Background="Transparent"
|
SizeToContent="WidthAndHeight"
|
||||||
SizeToContent="WidthAndHeight"
|
CanResize="False"
|
||||||
CanResize="False"
|
WindowStartupLocation="CenterScreen">
|
||||||
WindowStartupLocation="CenterScreen"
|
<Grid RowDefinitions="Auto,*">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -59,7 +49,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid Grid.Row="1" ColumnDefinitions="Auto,*" Background="{DynamicResource Brush.Window}">
|
<Grid Grid.Row="1" ColumnDefinitions="Auto,*">
|
||||||
<Image Grid.Column="0"
|
<Image Grid.Column="0"
|
||||||
Width="200" Height="200"
|
Width="200" Height="200"
|
||||||
Margin="8,0"
|
Margin="8,0"
|
||||||
|
@ -100,4 +90,4 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class About : Window
|
public partial class About : ChromelessWindow
|
||||||
{
|
{
|
||||||
public string Version
|
public string Version
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,11 +28,11 @@
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Commit">
|
<DataTemplate DataType="m:Commit">
|
||||||
<StackPanel Orientation="Horizontal">
|
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Tag">
|
<DataTemplate DataType="m:Tag">
|
||||||
|
|
|
@ -1,29 +1,19 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.AssumeUnchangedManager"
|
x:Class="SourceGit.Views.AssumeUnchangedManager"
|
||||||
x:DataType="vm:AssumeUnchangedManager"
|
x:DataType="vm:AssumeUnchangedManager"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="{DynamicResource Text.AssumeUnchanged}"
|
Title="{DynamicResource Text.AssumeUnchanged}"
|
||||||
Background="Transparent"
|
Width="600" Height="400"
|
||||||
Width="600" Height="400"
|
CanResize="False"
|
||||||
CanResize="False"
|
WindowStartupLocation="CenterOwner">
|
||||||
WindowStartupLocation="CenterOwner"
|
<Grid RowDefinitions="Auto,*">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -61,7 +51,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Unchanged Files -->
|
<!-- Unchanged Files -->
|
||||||
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
|
<Grid Grid.Row="1">
|
||||||
<DataGrid Margin="8"
|
<DataGrid Margin="8"
|
||||||
Background="{DynamicResource Brush.Contents}"
|
Background="{DynamicResource Brush.Contents}"
|
||||||
ItemsSource="{Binding Files}"
|
ItemsSource="{Binding Files}"
|
||||||
|
@ -110,4 +100,4 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Avalonia.Interactivity;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class AssumeUnchangedManager : Window
|
public partial class AssumeUnchangedManager : ChromelessWindow
|
||||||
{
|
{
|
||||||
public AssumeUnchangedManager()
|
public AssumeUnchangedManager()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,36 +1,26 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.Blame"
|
x:Class="SourceGit.Views.Blame"
|
||||||
x:Name="me"
|
x:Name="me"
|
||||||
x:DataType="vm:Blame"
|
x:DataType="vm:Blame"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="{DynamicResource Text.Blame}"
|
Title="{DynamicResource Text.Blame}"
|
||||||
Background="Transparent"
|
WindowStartupLocation="CenterOwner"
|
||||||
WindowStartupLocation="CenterOwner"
|
MinWidth="1280" MinHeight="720">
|
||||||
MinWidth="1280" MinHeight="720"
|
<Grid>
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="30"/>
|
<RowDefinition Height="30"/>
|
||||||
<RowDefinition Height="24"/>
|
<RowDefinition Height="24"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
||||||
<!-- Bottom border -->
|
<!-- Bottom border -->
|
||||||
|
@ -38,7 +28,9 @@
|
||||||
Background="{DynamicResource Brush.TitleBar}"
|
Background="{DynamicResource Brush.TitleBar}"
|
||||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
|
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
DoubleTapped="MaximizeOrRestoreWindow"
|
DoubleTapped="MaximizeOrRestoreWindow"
|
||||||
PointerPressed="BeginMoveWindow"/>
|
PointerPressed="BeginMoveWindow"
|
||||||
|
PointerMoved="MoveWindow"
|
||||||
|
PointerReleased="EndMoveWindow"/>
|
||||||
|
|
||||||
<!-- Caption Buttons (macOS) -->
|
<!-- Caption Buttons (macOS) -->
|
||||||
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
|
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
|
||||||
|
@ -58,12 +50,12 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- File -->
|
<!-- File -->
|
||||||
<Border Grid.Row="1" Padding="8,0" Background="{DynamicResource Brush.Window}">
|
<Border Grid.Row="1" Padding="8,0">
|
||||||
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"/>
|
<TextBlock Text="{Binding Title}" VerticalAlignment="Center"/>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Grid Grid.Row="2" Background="{DynamicResource Brush.Window}">
|
<Grid Grid.Row="2">
|
||||||
<!-- Blame View -->
|
<!-- Blame View -->
|
||||||
<v:BlameTextEditor HorizontalScrollBarVisibility="Auto"
|
<v:BlameTextEditor HorizontalScrollBarVisibility="Auto"
|
||||||
VerticalScrollBarVisibility="Auto"
|
VerticalScrollBarVisibility="Auto"
|
||||||
|
@ -86,64 +78,5 @@
|
||||||
<!-- Loading -->
|
<!-- Loading -->
|
||||||
<v:LoadingIcon Width="48" Height="48" IsVisible="{Binding Data, Converter={x:Static ObjectConverters.IsNull}}"/>
|
<v:LoadingIcon Width="48" Height="48" IsVisible="{Binding Data, Converter={x:Static ObjectConverters.IsNull}}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Custom window sizer for Linux -->
|
|
||||||
<Grid Grid.Row="0" Grid.RowSpan="3" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
|
||||||
Cursor="TopLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Top"
|
|
||||||
Cursor="TopSide"
|
|
||||||
Tag="{x:Static WindowEdge.North}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
|
||||||
Cursor="TopRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
|
||||||
Cursor="LeftSide"
|
|
||||||
Tag="{x:Static WindowEdge.West}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Stretch"
|
|
||||||
Cursor="RightSide"
|
|
||||||
Tag="{x:Static WindowEdge.East}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomSide"
|
|
||||||
Tag="{x:Static WindowEdge.South}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -319,7 +319,7 @@ namespace SourceGit.Views
|
||||||
private TextMate.Installation _textMate = null;
|
private TextMate.Installation _textMate = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Blame : Window
|
public partial class Blame : ChromelessWindow
|
||||||
{
|
{
|
||||||
public Blame()
|
public Blame()
|
||||||
{
|
{
|
||||||
|
@ -333,31 +333,41 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
if (WindowState == WindowState.Maximized)
|
_pressedTitleBar = false;
|
||||||
{
|
|
||||||
WindowState = WindowState.Normal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WindowState = WindowState.Maximized;
|
|
||||||
}
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
if (WindowState == WindowState.Maximized)
|
||||||
{
|
WindowState = WindowState.Normal;
|
||||||
if (sender is Border border)
|
else
|
||||||
{
|
WindowState = WindowState.Maximized;
|
||||||
if (border.Tag is WindowEdge edge)
|
|
||||||
{
|
e.Handled = true;
|
||||||
BeginResizeDrag(edge, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
BeginMoveDrag(e);
|
if (e.ClickCount != 2)
|
||||||
|
_pressedTitleBar = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveWindow(object sender, PointerEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_pressedTitleBar)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visual = (Visual)e.Source;
|
||||||
|
BeginMoveDrag(new PointerPressedEventArgs(
|
||||||
|
e.Source,
|
||||||
|
e.Pointer,
|
||||||
|
visual,
|
||||||
|
e.GetPosition(visual),
|
||||||
|
e.Timestamp,
|
||||||
|
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||||
|
e.KeyModifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndMoveWindow(object sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
_pressedTitleBar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnClosed(EventArgs e)
|
protected override void OnClosed(EventArgs e)
|
||||||
|
@ -375,5 +385,7 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _pressedTitleBar = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
173
src/Views/BranchCompare.axaml
Normal file
173
src/Views/BranchCompare.axaml
Normal file
|
@ -0,0 +1,173 @@
|
||||||
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:m="using:SourceGit.Models"
|
||||||
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
|
xmlns:v="using:SourceGit.Views"
|
||||||
|
xmlns:c="using:SourceGit.Converters"
|
||||||
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
|
x:Class="SourceGit.Views.BranchCompare"
|
||||||
|
x:DataType="vm:BranchCompare"
|
||||||
|
x:Name="me"
|
||||||
|
Icon="/App.ico"
|
||||||
|
Title="{DynamicResource Text.BranchCompare}"
|
||||||
|
MinWidth="1280" MinHeight="720"
|
||||||
|
WindowStartupLocation="CenterOwner">
|
||||||
|
<Grid>
|
||||||
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="30"/>
|
||||||
|
<RowDefinition Height="64"/>
|
||||||
|
<RowDefinition Height="*"/>
|
||||||
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
|
<!-- TitleBar -->
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
||||||
|
<!-- Bottom border -->
|
||||||
|
<Border Grid.Column="0" Grid.ColumnSpan="4"
|
||||||
|
Background="{DynamicResource Brush.TitleBar}"
|
||||||
|
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
|
DoubleTapped="MaximizeOrRestoreWindow"
|
||||||
|
PointerPressed="BeginMoveWindow"
|
||||||
|
PointerMoved="MoveWindow"
|
||||||
|
PointerReleased="EndMoveWindow"/>
|
||||||
|
|
||||||
|
<!-- Caption Buttons (macOS) -->
|
||||||
|
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
|
||||||
|
<v:CaptionButtonsMacOS/>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Icon -->
|
||||||
|
<Path Grid.Column="1" Margin="8,0,0,0" Width="12" Height="12" Data="{StaticResource Icons.Compare}"/>
|
||||||
|
|
||||||
|
<!-- Title -->
|
||||||
|
<TextBlock Grid.Column="2" Margin="8,0,0,0" Text="{DynamicResource Text.BranchCompare}" FontWeight="Bold" IsHitTestVisible="False" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<!-- Caption Buttons (Windows/Linux) -->
|
||||||
|
<Border Grid.Column="3" IsVisible="{OnPlatform True, macOS=False}">
|
||||||
|
<v:CaptionButtons/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Compare Targets -->
|
||||||
|
<Border Grid.Row="1">
|
||||||
|
<Grid Margin="48,8,48,8" ColumnDefinitions="*,48,*">
|
||||||
|
<Border Grid.Column="0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
|
||||||
|
<Grid RowDefinitions="Auto,*">
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
|
||||||
|
<v:Avatar Width="16" Height="16"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
User="{Binding BaseHead.Author}"/>
|
||||||
|
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding BaseHead.Author.Name}" Margin="8,0,0,0"/>
|
||||||
|
<Border Grid.Column="2" Background="{DynamicResource Brush.Accent}" CornerRadius="4">
|
||||||
|
<TextBlock Text="{Binding Base, Converter={x:Static c:BranchConverters.ToName}}" Classes="monospace" Margin="4,0" Foreground="#FFDDDDDD"/>
|
||||||
|
</Border>
|
||||||
|
<TextBlock Grid.Column="3" Classes="monospace" Text="{Binding BaseHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" PointerPressed="OnPressedSHA"/>
|
||||||
|
<TextBlock Grid.Column="4" Classes="monospace" Text="{Binding BaseHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Classes="monospace" Text="{Binding BaseHead.Subject}" VerticalAlignment="Bottom"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Path Grid.Column="1" Width="16" Height="16" Fill="{DynamicResource Brush.FG2}" Data="{DynamicResource Icons.Down}" RenderTransformOrigin="50%,50%" RenderTransform="rotate(270deg)"/>
|
||||||
|
|
||||||
|
<Border Grid.Column="2" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}" CornerRadius="4" Padding="4">
|
||||||
|
<Grid RowDefinitions="Auto,*">
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto,Auto,Auto">
|
||||||
|
<v:Avatar Width="16" Height="16"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
IsHitTestVisible="False"
|
||||||
|
User="{Binding ToHead.Author}"/>
|
||||||
|
<TextBlock Grid.Column="1" Classes="monospace" Text="{Binding ToHead.Author.Name}" Margin="8,0,0,0"/>
|
||||||
|
<Border Grid.Column="2" Background="{DynamicResource Brush.Accent}" CornerRadius="4">
|
||||||
|
<TextBlock Text="{Binding To, Converter={x:Static c:BranchConverters.ToName}}" Classes="monospace" Margin="4,0" Foreground="#FFDDDDDD"/>
|
||||||
|
</Border>
|
||||||
|
<TextBlock Grid.Column="3" Classes="monospace" Text="{Binding ToHead.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0" TextDecorations="Underline" PointerPressed="OnPressedSHA"/>
|
||||||
|
<TextBlock Grid.Column="4" Classes="monospace" Text="{Binding ToHead.CommitterTimeStr}" Foreground="{DynamicResource Brush.FG2}" Margin="8,0,0,0"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Classes="monospace" Text="{Binding ToHead.Subject}" VerticalAlignment="Bottom"/>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<!-- Changes -->
|
||||||
|
<Border Grid.Row="2">
|
||||||
|
<Grid Margin="8,0,8,8">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="256" MinWidth="200" MaxWidth="480"/>
|
||||||
|
<ColumnDefinition Width="4"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Grid Grid.Column="0" RowDefinitions="26,*">
|
||||||
|
<!-- Search & Display Mode -->
|
||||||
|
<Grid Grid.Row="0" ColumnDefinitions="*,18">
|
||||||
|
<TextBox Grid.Column="0"
|
||||||
|
Height="26"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
|
Background="Transparent"
|
||||||
|
CornerRadius="4"
|
||||||
|
Watermark="{DynamicResource Text.CommitDetail.Changes.Search}"
|
||||||
|
Text="{Binding SearchFilter, Mode=TwoWay}">
|
||||||
|
<TextBox.InnerLeftContent>
|
||||||
|
<Path Width="14" Height="14" Margin="4,0,0,0" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Search}"/>
|
||||||
|
</TextBox.InnerLeftContent>
|
||||||
|
|
||||||
|
<TextBox.InnerRightContent>
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
IsVisible="{Binding SearchFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
|
Command="{Binding ClearSearchFilter}">
|
||||||
|
<Path Width="14" Height="14" Fill="{DynamicResource Brush.FG2}" Data="{StaticResource Icons.Clear}"/>
|
||||||
|
</Button>
|
||||||
|
</TextBox.InnerRightContent>
|
||||||
|
</TextBox>
|
||||||
|
|
||||||
|
<v:ChangeViewModeSwitcher Grid.Column="1"
|
||||||
|
Width="14" Height="14"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=CommitChangeViewMode, Mode=TwoWay}"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Changes -->
|
||||||
|
<Border Grid.Row="1" Margin="0,4,0,0" BorderBrush="{DynamicResource Brush.Border2}" BorderThickness="1" Background="{DynamicResource Brush.Contents}">
|
||||||
|
<v:ChangeCollectionView IsWorkingCopyChange="False"
|
||||||
|
ViewMode="{Binding Source={x:Static vm:Preference.Instance}, Path=CommitChangeViewMode}"
|
||||||
|
Changes="{Binding VisibleChanges}"
|
||||||
|
SelectedChanges="{Binding SelectedChanges, Mode=TwoWay}"
|
||||||
|
ContextRequested="OnChangeContextRequested"/>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<GridSplitter Grid.Column="1"
|
||||||
|
MinWidth="1"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
|
||||||
|
Background="Transparent"/>
|
||||||
|
|
||||||
|
<Grid Grid.Column="2">
|
||||||
|
<Border BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}">
|
||||||
|
<StackPanel Orientation="Vertical" VerticalAlignment="Center">
|
||||||
|
<Path Width="64" Height="64" Data="{StaticResource Icons.Diff}" Fill="{DynamicResource Brush.FG2}"/>
|
||||||
|
<TextBlock Margin="0,16,0,0"
|
||||||
|
Text="{DynamicResource Text.Diff.Welcome}"
|
||||||
|
FontSize="18" FontWeight="Bold"
|
||||||
|
Foreground="{DynamicResource Brush.FG2}"
|
||||||
|
HorizontalAlignment="Center"/>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding DiffContext}">
|
||||||
|
<ContentControl.DataTemplates>
|
||||||
|
<DataTemplate DataType="vm:DiffContext">
|
||||||
|
<v:DiffView/>
|
||||||
|
</DataTemplate>
|
||||||
|
</ContentControl.DataTemplates>
|
||||||
|
</ContentControl>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
|
</Grid>
|
||||||
|
</v:ChromelessWindow>
|
74
src/Views/BranchCompare.axaml.cs
Normal file
74
src/Views/BranchCompare.axaml.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Input;
|
||||||
|
|
||||||
|
namespace SourceGit.Views
|
||||||
|
{
|
||||||
|
public partial class BranchCompare : ChromelessWindow
|
||||||
|
{
|
||||||
|
public BranchCompare()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||||
|
{
|
||||||
|
_pressedTitleBar = false;
|
||||||
|
|
||||||
|
if (WindowState == WindowState.Maximized)
|
||||||
|
WindowState = WindowState.Normal;
|
||||||
|
else
|
||||||
|
WindowState = WindowState.Maximized;
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ClickCount != 2)
|
||||||
|
_pressedTitleBar = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MoveWindow(object sender, PointerEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_pressedTitleBar)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visual = (Visual)e.Source;
|
||||||
|
BeginMoveDrag(new PointerPressedEventArgs(
|
||||||
|
e.Source,
|
||||||
|
e.Pointer,
|
||||||
|
visual,
|
||||||
|
e.GetPosition(visual),
|
||||||
|
e.Timestamp,
|
||||||
|
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||||
|
e.KeyModifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndMoveWindow(object sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
_pressedTitleBar = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChangeContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is ViewModels.BranchCompare vm && sender is ChangeCollectionView view)
|
||||||
|
{
|
||||||
|
var menu = vm.CreateChangeContextMenu();
|
||||||
|
view.OpenContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnPressedSHA(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (DataContext is ViewModels.BranchCompare vm && sender is TextBlock block)
|
||||||
|
vm.NavigateTo(block.Text);
|
||||||
|
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _pressedTitleBar = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,22 +12,24 @@
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.Checkout.Commit}" />
|
Text="{DynamicResource Text.Checkout.Commit}" />
|
||||||
|
|
||||||
<TextBlock Margin="0,8,0,16"
|
<StackPanel Orientation="Horizontal" Margin="0,12,0,16">
|
||||||
Text="{DynamicResource Text.Checkout.Commit.Warning}"
|
<Path Width="14" Height="14" Data="{StaticResource Icons.Error}" Fill="DarkOrange"/>
|
||||||
TextWrapping="Wrap"
|
<TextBlock Margin="4,0,0,0"
|
||||||
Foreground="{DynamicResource Brush.FG2}"
|
Text="{DynamicResource Text.Checkout.Commit.Warning}"
|
||||||
FontStyle="Italic"/>
|
TextWrapping="Wrap"
|
||||||
|
FontStyle="Italic"/>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
<Grid RowDefinitions="32,Auto" ColumnDefinitions="Auto,*" ClipToBounds="True">
|
<Grid RowDefinitions="32,Auto" ColumnDefinitions="Auto,*" ClipToBounds="True" HorizontalAlignment="Center">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Checkout.Commit.Target}" />
|
Text="{DynamicResource Text.Checkout.Commit.Target}" />
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal">
|
<Grid Grid.Row="0" Grid.Column="1" ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}" />
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}" />
|
||||||
<TextBlock Classes="monospace" Foreground="DarkOrange" VerticalAlignment="Center" Margin="8,0" Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" />
|
<TextBlock Grid.Column="1" Classes="monospace" Foreground="DarkOrange" VerticalAlignment="Center" Margin="8,0" Text="{Binding Commit.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" />
|
||||||
<TextBlock Text="{Binding Commit.Subject}"/>
|
<TextBlock Grid.Column="2" Text="{Binding Commit.Subject}" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
|
|
|
@ -12,17 +12,17 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.CherryPick}"/>
|
Text="{DynamicResource Text.CherryPick}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="120,*">
|
||||||
<TextBlock Grid.Column="0"
|
<TextBlock Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.CherryPick.Commit}"/>
|
Text="{DynamicResource Text.CherryPick.Commit}"/>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
<Grid Grid.Column="1" ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding Target.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding Target.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Target.Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Target.Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||||
Content="{DynamicResource Text.CherryPick.CommitChanges}"
|
Content="{DynamicResource Text.CherryPick.CommitChanges}"
|
||||||
|
|
56
src/Views/ChromelessWindow.cs
Normal file
56
src/Views/ChromelessWindow.cs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Input;
|
||||||
|
|
||||||
|
namespace SourceGit.Views
|
||||||
|
{
|
||||||
|
public class ChromelessWindow : Window
|
||||||
|
{
|
||||||
|
protected override Type StyleKeyOverride => typeof(Window);
|
||||||
|
|
||||||
|
public ChromelessWindow()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsLinux())
|
||||||
|
Classes.Add("custom_window_frame");
|
||||||
|
else if (OperatingSystem.IsWindows())
|
||||||
|
Classes.Add("fix_maximized_padding");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
|
||||||
|
if (Classes.Contains("custom_window_frame") && CanResize)
|
||||||
|
{
|
||||||
|
string[] borderNames = [
|
||||||
|
"PART_BorderTopLeft",
|
||||||
|
"PART_BorderTop",
|
||||||
|
"PART_BorderTopRight",
|
||||||
|
"PART_BorderLeft",
|
||||||
|
"PART_BorderRight",
|
||||||
|
"PART_BorderBottomLeft",
|
||||||
|
"PART_BorderBottom",
|
||||||
|
"PART_BorderBottomRight",
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach (var name in borderNames)
|
||||||
|
{
|
||||||
|
var border = e.NameScope.Find<Border>(name);
|
||||||
|
if (border != null)
|
||||||
|
{
|
||||||
|
border.PointerPressed -= OnWindowBorderPointerPressed;
|
||||||
|
border.PointerPressed += OnWindowBorderPointerPressed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWindowBorderPointerPressed(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (sender is Border border && border.Tag is WindowEdge edge && CanResize)
|
||||||
|
BeginResizeDrag(edge, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,46 +10,71 @@
|
||||||
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
|
<StackPanel Orientation="Vertical" Margin="8,0,0,0">
|
||||||
<TextBlock Classes="bold" FontSize="18" Text="{DynamicResource Text.Clone}"/>
|
<TextBlock Classes="bold" FontSize="18" Text="{DynamicResource Text.Clone}"/>
|
||||||
|
|
||||||
<Grid Margin="8,16,0,0" Height="28" ColumnDefinitions="140,*">
|
<Grid Margin="8,16,0,0" RowDefinitions="32,Auto,32,32,32" ColumnDefinitions="Auto,*">
|
||||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.Clone.RemoteURL}"/>
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
<TextBox Grid.Column="1" CornerRadius="3" Text="{Binding Remote, Mode=TwoWay}" v:AutoFocusBehaviour.IsEnabled="True"/>
|
HorizontalAlignment="Right"
|
||||||
</Grid>
|
Margin="0,0,8,0"
|
||||||
<Grid Margin="8,4,0,0" Height="28" ColumnDefinitions="140,*" IsVisible="{Binding UseSSH}">
|
Text="{DynamicResource Text.Clone.RemoteURL}"/>
|
||||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.SSHKey}"/>
|
<TextBox Grid.Row="0" Grid.Column="1"
|
||||||
<TextBox Grid.Column="1"
|
Height="28"
|
||||||
|
CornerRadius="3"
|
||||||
|
Text="{Binding Remote, Mode=TwoWay}"
|
||||||
|
v:AutoFocusBehaviour.IsEnabled="True"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
Text="{DynamicResource Text.SSHKey}"
|
||||||
|
IsVisible="{Binding UseSSH}"/>
|
||||||
|
<TextBox Grid.Row="1" Grid.Column="1"
|
||||||
x:Name="TxtSshKey"
|
x:Name="TxtSshKey"
|
||||||
Height="28"
|
Height="28"
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Watermark="{DynamicResource Text.SSHKey.Placeholder}"
|
Watermark="{DynamicResource Text.SSHKey.Placeholder}"
|
||||||
Text="{Binding SSHKey, Mode=TwoWay}">
|
Text="{Binding SSHKey, Mode=TwoWay}"
|
||||||
|
IsVisible="{Binding UseSSH}">
|
||||||
<TextBox.InnerRightContent>
|
<TextBox.InnerRightContent>
|
||||||
<Button Classes="icon_button" Width="30" Height="30" Click="SelectSSHKey">
|
<Button Classes="icon_button" Width="28" Height="28" Click="SelectSSHKey">
|
||||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||||
</Button>
|
</Button>
|
||||||
</TextBox.InnerRightContent>
|
</TextBox.InnerRightContent>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
</Grid>
|
|
||||||
<Grid Margin="8,4,0,0" Height="28" ColumnDefinitions="140,*">
|
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.Clone.ParentFolder}"/>
|
HorizontalAlignment="Right"
|
||||||
<TextBox Grid.Column="1"
|
Margin="0,0,8,0"
|
||||||
|
Text="{DynamicResource Text.Clone.ParentFolder}"/>
|
||||||
|
<TextBox Grid.Row="2" Grid.Column="1"
|
||||||
x:Name="TxtParentFolder"
|
x:Name="TxtParentFolder"
|
||||||
Height="28"
|
Height="28"
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Text="{Binding ParentFolder, Mode=TwoWay}">
|
Text="{Binding ParentFolder, Mode=TwoWay}">
|
||||||
<TextBox.InnerRightContent>
|
<TextBox.InnerRightContent>
|
||||||
<Button Classes="icon_button" Width="30" Height="30" Margin="4,0,0,0" Click="SelectParentFolder">
|
<Button Classes="icon_button" Width="28" Height="28" Margin="4,0,0,0" Click="SelectParentFolder">
|
||||||
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
<Path Data="{StaticResource Icons.Folder.Open}" Fill="{DynamicResource Brush.FG1}"/>
|
||||||
</Button>
|
</Button>
|
||||||
</TextBox.InnerRightContent>
|
</TextBox.InnerRightContent>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
</Grid>
|
|
||||||
<Grid Margin="8,4,0,0" Height="28" ColumnDefinitions="140,*">
|
<TextBlock Grid.Row="3" Grid.Column="0"
|
||||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.Clone.LocalName}"/>
|
HorizontalAlignment="Right"
|
||||||
<TextBox Grid.Column="1" CornerRadius="3" Watermark="{DynamicResource Text.Clone.LocalName.Placeholder}" Text="{Binding Local, Mode=TwoWay}"/>
|
Margin="0,0,8,0"
|
||||||
</Grid>
|
Text="{DynamicResource Text.Clone.LocalName}"/>
|
||||||
<Grid Margin="8,4,0,0" Height="28" ColumnDefinitions="140,*">
|
<TextBox Grid.Row="3" Grid.Column="1"
|
||||||
<TextBlock Grid.Column="0" HorizontalAlignment="Right" Margin="0,0,8,0" Text="{DynamicResource Text.Clone.AdditionalParam}"/>
|
Height="28"
|
||||||
<TextBox Grid.Column="1" CornerRadius="3" Watermark="{DynamicResource Text.Clone.AdditionalParam.Placeholder}" Text="{Binding ExtraArgs, Mode=TwoWay}"/>
|
CornerRadius="3"
|
||||||
|
Watermark="{DynamicResource Text.Clone.LocalName.Placeholder}"
|
||||||
|
Text="{Binding Local, Mode=TwoWay}"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,8,0"
|
||||||
|
Text="{DynamicResource Text.Clone.AdditionalParam}"/>
|
||||||
|
<TextBox Grid.Row="4" Grid.Column="1"
|
||||||
|
Height="28"
|
||||||
|
CornerRadius="3"
|
||||||
|
Watermark="{DynamicResource Text.Clone.AdditionalParam.Placeholder}"
|
||||||
|
Text="{Binding ExtraArgs, Mode=TwoWay}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
x:DataType="vm:CommitDetail">
|
x:DataType="vm:CommitDetail">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="256" MinWidth="200" MaxWidth="480"/>
|
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailChangesLeftWidth, Mode=TwoWay}" MinWidth="200" MaxWidth="480"/>
|
||||||
<ColumnDefinition Width="4"/>
|
<ColumnDefinition Width="4"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
|
@ -29,11 +29,11 @@
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Commit">
|
<DataTemplate DataType="m:Commit">
|
||||||
<StackPanel Orientation="Horizontal">
|
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Tag">
|
<DataTemplate DataType="m:Tag">
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.CreateTag}"/>
|
Text="{DynamicResource Text.CreateTag}"/>
|
||||||
<Grid Margin="0,16,8,0" RowDefinitions="32,32,32,Auto,Auto,32" ColumnDefinitions="150,*">
|
<Grid Margin="0,16,8,0" RowDefinitions="32,32,32,Auto,Auto,32" ColumnDefinitions="120,*">
|
||||||
<TextBlock Grid.Column="0"
|
<TextBlock Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
|
@ -28,11 +28,11 @@
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Commit">
|
<DataTemplate DataType="m:Commit">
|
||||||
<StackPanel Orientation="Horizontal">
|
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
|
|
|
@ -234,9 +234,7 @@
|
||||||
|
|
||||||
<!-- Text Diff -->
|
<!-- Text Diff -->
|
||||||
<DataTemplate DataType="m:TextDiff">
|
<DataTemplate DataType="m:TextDiff">
|
||||||
<v:TextDiffView TextDiff="{Binding}"
|
<v:TextDiffView UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
|
||||||
SyncScrollOffset="{Binding SyncScrollOffset, Mode=TwoWay}"
|
|
||||||
UseSideBySideDiff="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSideBySideDiff, Mode=OneWay}"/>
|
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<!-- Empty or only EOL changes -->
|
<!-- Empty or only EOL changes -->
|
||||||
|
|
|
@ -1,34 +1,24 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.FileHistories"
|
x:Class="SourceGit.Views.FileHistories"
|
||||||
x:DataType="vm:FileHistories"
|
x:DataType="vm:FileHistories"
|
||||||
x:Name="me"
|
x:Name="me"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="{DynamicResource Text.FileHistory}"
|
Title="{DynamicResource Text.FileHistory}"
|
||||||
Background="Transparent"
|
MinWidth="1280" MinHeight="720">
|
||||||
MinWidth="1280" MinHeight="720"
|
<Grid>
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="30"/>
|
<RowDefinition Height="30"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*,Auto">
|
||||||
<!-- Bottom border -->
|
<!-- Bottom border -->
|
||||||
|
@ -36,7 +26,9 @@
|
||||||
Background="{DynamicResource Brush.TitleBar}"
|
Background="{DynamicResource Brush.TitleBar}"
|
||||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||||
DoubleTapped="MaximizeOrRestoreWindow"
|
DoubleTapped="MaximizeOrRestoreWindow"
|
||||||
PointerPressed="BeginMoveWindow"/>
|
PointerPressed="BeginMoveWindow"
|
||||||
|
PointerMoved="MoveWindow"
|
||||||
|
PointerReleased="EndMoveWindow"/>
|
||||||
|
|
||||||
<!-- Caption Buttons (macOS) -->
|
<!-- Caption Buttons (macOS) -->
|
||||||
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
|
<Border Grid.Column="0" IsVisible="{OnPlatform False, macOS=True}">
|
||||||
|
@ -56,7 +48,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="300" MinWidth="300" MaxWidth="600"/>
|
<ColumnDefinition Width="300" MinWidth="300" MaxWidth="600"/>
|
||||||
<ColumnDefinition Width="4"/>
|
<ColumnDefinition Width="4"/>
|
||||||
|
@ -143,64 +135,5 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Custom window sizer for Linux -->
|
|
||||||
<Grid Grid.Row="0" Grid.RowSpan="2" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
|
||||||
Cursor="TopLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Top"
|
|
||||||
Cursor="TopSide"
|
|
||||||
Tag="{x:Static WindowEdge.North}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
|
||||||
Cursor="TopRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
|
||||||
Cursor="LeftSide"
|
|
||||||
Tag="{x:Static WindowEdge.West}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Stretch"
|
|
||||||
Cursor="RightSide"
|
|
||||||
Tag="{x:Static WindowEdge.East}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomSide"
|
|
||||||
Tag="{x:Static WindowEdge.South}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class FileHistories : Window
|
public partial class FileHistories : ChromelessWindow
|
||||||
{
|
{
|
||||||
public FileHistories()
|
public FileHistories()
|
||||||
{
|
{
|
||||||
|
@ -12,31 +13,43 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
if (WindowState == WindowState.Maximized)
|
_pressedTitleBar = false;
|
||||||
{
|
|
||||||
WindowState = WindowState.Normal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WindowState = WindowState.Maximized;
|
|
||||||
}
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
if (WindowState == WindowState.Maximized)
|
||||||
{
|
WindowState = WindowState.Normal;
|
||||||
if (sender is Border border)
|
else
|
||||||
{
|
WindowState = WindowState.Maximized;
|
||||||
if (border.Tag is WindowEdge edge)
|
|
||||||
{
|
e.Handled = true;
|
||||||
BeginResizeDrag(edge, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
BeginMoveDrag(e);
|
if (e.ClickCount != 2)
|
||||||
|
_pressedTitleBar = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MoveWindow(object sender, PointerEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_pressedTitleBar)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visual = (Visual)e.Source;
|
||||||
|
BeginMoveDrag(new PointerPressedEventArgs(
|
||||||
|
e.Source,
|
||||||
|
e.Pointer,
|
||||||
|
visual,
|
||||||
|
e.GetPosition(visual),
|
||||||
|
e.Timestamp,
|
||||||
|
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||||
|
e.KeyModifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndMoveWindow(object sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
_pressedTitleBar = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool _pressedTitleBar = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,18 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
xmlns:v="using:SourceGit.Views"
|
||||||
x:Class="SourceGit.Views.Hotkeys"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
Icon="/App.ico"
|
x:Class="SourceGit.Views.Hotkeys"
|
||||||
Title="{DynamicResource Text.Hotkeys}"
|
Icon="/App.ico"
|
||||||
Background="Transparent"
|
Title="{DynamicResource Text.Hotkeys}"
|
||||||
SizeToContent="WidthAndHeight"
|
SizeToContent="WidthAndHeight"
|
||||||
CanResize="False"
|
CanResize="False"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
<Grid RowDefinitions="Auto,*">
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -59,7 +50,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Border Grid.Row="1" Background="{DynamicResource Brush.Window}">
|
<Border Grid.Row="1">
|
||||||
<StackPanel Orientation="Vertical" Margin="16,8,16,16">
|
<StackPanel Orientation="Vertical" Margin="16,8,16,16">
|
||||||
<TextBlock Text="{DynamicResource Text.Hotkeys.Global}"
|
<TextBlock Text="{DynamicResource Text.Hotkeys.Global}"
|
||||||
Foreground="{DynamicResource Brush.FG2}"
|
Foreground="{DynamicResource Brush.FG2}"
|
||||||
|
@ -93,7 +84,7 @@
|
||||||
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Increase}}"
|
FontSize="{Binding Source={x:Static vm:Preference.Instance}, Path=DefaultFontSize, Converter={x:Static c:FontSizeModifyConverters.Increase}}"
|
||||||
Margin="0,8"/>
|
Margin="0,8"/>
|
||||||
|
|
||||||
<Grid RowDefinitions="20,20,20,20,20,20" ColumnDefinitions="150,*">
|
<Grid RowDefinitions="20,20,20,20,20,20,20,20" ColumnDefinitions="150,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+F, macOS=⌘+F}"/>
|
<TextBlock Grid.Row="0" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+F, macOS=⌘+F}"/>
|
||||||
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.OpenSearchCommits}" />
|
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.OpenSearchCommits}" />
|
||||||
|
|
||||||
|
@ -109,8 +100,14 @@
|
||||||
<TextBlock Grid.Row="4" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Space, macOS=␣}"/>
|
<TextBlock Grid.Row="4" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Space, macOS=␣}"/>
|
||||||
<TextBlock Grid.Row="4" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.StageOrUnstageSelected}" />
|
<TextBlock Grid.Row="4" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.StageOrUnstageSelected}" />
|
||||||
|
|
||||||
<TextBlock Grid.Row="5" Grid.Column="0" Classes="monospace bold" Text="F5"/>
|
<TextBlock Grid.Row="5" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"/>
|
||||||
<TextBlock Grid.Row="5" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
|
<TextBlock Grid.Row="5" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Commit}" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="6" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+⇧+Enter}"/>
|
||||||
|
<TextBlock Grid.Row="6" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.CommitAndPush}" />
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="7" Grid.Column="0" Classes="monospace bold" Text="F5"/>
|
||||||
|
<TextBlock Grid.Row="7" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Repo.Refresh}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}"
|
<TextBlock Text="{DynamicResource Text.Hotkeys.TextEditor}"
|
||||||
|
@ -135,4 +132,4 @@
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class Hotkeys : Window
|
public partial class Hotkeys : ChromelessWindow
|
||||||
{
|
{
|
||||||
public Hotkeys()
|
public Hotkeys()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,48 +1,39 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:s="using:SourceGit"
|
xmlns:s="using:SourceGit"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.Launcher"
|
x:Class="SourceGit.Views.Launcher"
|
||||||
x:DataType="vm:Launcher"
|
x:DataType="vm:Launcher"
|
||||||
x:Name="me"
|
x:Name="me"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="SourceGit"
|
Title="SourceGit"
|
||||||
Background="Transparent"
|
MinWidth="1280" MinHeight="720"
|
||||||
MinWidth="1280" MinHeight="720"
|
Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherWidth, Mode=TwoWay}"
|
||||||
WindowStartupLocation="CenterScreen"
|
Height="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherHeight, Mode=TwoWay}"
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
WindowState="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.LauncherWindowState, Mode=TwoWay}"
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
WindowStartupLocation="CenterScreen">
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
<Grid>
|
||||||
<Window.Resources>
|
|
||||||
<SolidColorBrush x:Key="SystemControlErrorTextForegroundBrush" Color="Red"/>
|
|
||||||
</Window.Resources>
|
|
||||||
|
|
||||||
<Grid Margin="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToContentMargin}}">
|
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.ToTitleBarHeight}}"/>
|
<RowDefinition Height="{Binding #me.TitleBarHeight}"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- Custom TitleBar -->
|
<!-- Custom TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto">
|
||||||
<!-- Bottom border -->
|
<!-- Bottom border -->
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
Background="{DynamicResource Brush.TitleBar}"
|
Background="{DynamicResource Brush.TitleBar}"
|
||||||
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
BorderThickness="0,0,0,1" BorderBrush="{DynamicResource Brush.Border0}"
|
||||||
DoubleTapped="MaximizeOrRestoreWindow"
|
DoubleTapped="OnTitleBarDoubleTapped"
|
||||||
PointerPressed="BeginMoveWindow"/>
|
PointerPressed="BeginMoveWindow"
|
||||||
|
PointerMoved="MoveWindow"
|
||||||
|
PointerReleased="EndMoveWindow"/>
|
||||||
|
|
||||||
<!-- Caption Buttons (macOS) -->
|
<!-- Caption Buttons (macOS) -->
|
||||||
<Border Grid.Column="0" VerticalAlignment="Stretch" Margin="2,0,8,3" IsVisible="{OnPlatform False, macOS=True}">
|
<Border Grid.Column="0" VerticalAlignment="Stretch" Margin="2,0,8,3" IsVisible="{OnPlatform False, macOS=True}">
|
||||||
|
@ -92,10 +83,9 @@
|
||||||
|
|
||||||
<ScrollViewer Grid.Column="1"
|
<ScrollViewer Grid.Column="1"
|
||||||
x:Name="launcherTabsScroller"
|
x:Name="launcherTabsScroller"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
HorizontalScrollBarVisibility="Hidden"
|
HorizontalScrollBarVisibility="Hidden"
|
||||||
VerticalScrollBarVisibility="Disabled"
|
VerticalScrollBarVisibility="Disabled"
|
||||||
DoubleTapped="MaximizeOrRestoreWindow"
|
|
||||||
PointerPressed="BeginMoveWindow"
|
|
||||||
PointerWheelChanged="ScrollTabs"
|
PointerWheelChanged="ScrollTabs"
|
||||||
ScrollChanged="OnTabsScrollChanged">
|
ScrollChanged="OnTabsScrollChanged">
|
||||||
<StackPanel x:Name="launcherTabsBar" Orientation="Horizontal" SizeChanged="UpdateScrollIndicator">
|
<StackPanel x:Name="launcherTabsBar" Orientation="Horizontal" SizeChanged="UpdateScrollIndicator">
|
||||||
|
@ -260,62 +250,46 @@
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
|
|
||||||
<!-- Popup container -->
|
<!-- Popup container -->
|
||||||
<Grid Grid.Row="1" Margin="0,36,0,0" IsVisible="{Binding ActivePage.Popup, Converter={x:Static ObjectConverters.IsNotNull}}">
|
<Grid Grid.Row="1" Margin="0,36,0,0" IsVisible="{Binding ActivePage.Popup, Converter={x:Static ObjectConverters.IsNotNull}}" ClipToBounds="True">
|
||||||
<Border Background="Transparent" PointerPressed="OnPopupCancelByClickMask"/>
|
<Border Background="Transparent" PointerPressed="OnPopupCancelByClickMask"/>
|
||||||
|
|
||||||
<Grid Width="500" HorizontalAlignment="Center" VerticalAlignment="Top">
|
<Border Width="500" HorizontalAlignment="Center" VerticalAlignment="Top" Effect="drop-shadow(0 0 8 #8F000000)" CornerRadius="0,0,4,4" ClipToBounds="True">
|
||||||
<ContentControl Content="{Binding ActivePage.Popup}" ClipToBounds="True">
|
<ContentControl Content="{Binding ActivePage.Popup}" Background="{DynamicResource Brush.Popup}">
|
||||||
<ContentControl.DataTemplates>
|
<ContentControl.DataTemplates>
|
||||||
<DataTemplate DataType="vm:Popup">
|
<DataTemplate DataType="vm:Popup">
|
||||||
<Border Margin="8,0,8,8"
|
<StackPanel Orientation="Vertical" Background="{DynamicResource Brush.Popup}">
|
||||||
Background="{DynamicResource Brush.Popup}"
|
<!-- Popup Widget -->
|
||||||
BorderBrush="{DynamicResource Brush.Border0}">
|
<ContentPresenter Margin="8,16,8,8"
|
||||||
<Border.CornerRadius>
|
Content="{Binding View}"
|
||||||
<OnPlatform Default="0,0,4,4" Linux="0"/>
|
IsHitTestVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}"/>
|
||||||
</Border.CornerRadius>
|
|
||||||
|
|
||||||
<Border.BorderThickness>
|
<!-- Options -->
|
||||||
<OnPlatform Default="0" Linux="1,0,1,1"/>
|
<StackPanel Margin="8,4,8,8"
|
||||||
</Border.BorderThickness>
|
Height="32"
|
||||||
|
Orientation="Horizontal"
|
||||||
<Border.Effect>
|
HorizontalAlignment="Right"
|
||||||
<OnPlatform Default="drop-shadow(0 0 8 #8F000000)" Linux="{x:Null}"/>
|
IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}">
|
||||||
</Border.Effect>
|
<Button Classes="flat primary"
|
||||||
|
Width="80"
|
||||||
<StackPanel Margin="8" Orientation="Vertical">
|
Content="{DynamicResource Text.Sure}"
|
||||||
<!-- Popup Widget -->
|
Click="OnPopupSure"
|
||||||
<ContentPresenter Margin="0,8"
|
HotKey="Enter"/>
|
||||||
Content="{Binding View}"
|
<Button Classes="flat"
|
||||||
IsHitTestVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}"/>
|
Width="80"
|
||||||
|
Margin="8,0,0,0"
|
||||||
<!-- Options -->
|
Content="{DynamicResource Text.Cancel}"
|
||||||
<StackPanel Margin="0,8,0,0"
|
Click="OnPopupCancel"/>
|
||||||
Height="32"
|
|
||||||
Orientation="Horizontal"
|
|
||||||
HorizontalAlignment="Right"
|
|
||||||
IsVisible="{Binding InProgress, Converter={x:Static BoolConverters.Not}}">
|
|
||||||
<Button Classes="flat primary"
|
|
||||||
Width="80"
|
|
||||||
Content="{DynamicResource Text.Sure}"
|
|
||||||
Click="OnPopupSure"
|
|
||||||
HotKey="Enter"/>
|
|
||||||
<Button Classes="flat"
|
|
||||||
Width="80"
|
|
||||||
Margin="8,0,0,0"
|
|
||||||
Content="{DynamicResource Text.Cancel}"
|
|
||||||
Click="OnPopupCancel"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Running -->
|
|
||||||
<v:PopupRunningStatus Margin="8"
|
|
||||||
Description="{Binding ProgressDescription}"
|
|
||||||
IsVisible="{Binding InProgress}"/>
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Border>
|
|
||||||
|
<!-- Running -->
|
||||||
|
<v:PopupRunningStatus Margin="12,8"
|
||||||
|
Description="{Binding ProgressDescription}"
|
||||||
|
IsVisible="{Binding InProgress}"/>
|
||||||
|
</StackPanel>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
</Grid>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Notification container -->
|
<!-- Notification container -->
|
||||||
|
@ -363,64 +337,5 @@
|
||||||
</ItemsControl>
|
</ItemsControl>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Custom window sizer for Linux -->
|
|
||||||
<Grid Grid.Row="0" Grid.RowSpan="2" IsVisible="{OnPlatform False, Linux=True}" IsHitTestVisible="{Binding #me.WindowState, Converter={x:Static c:WindowStateConverters.IsNormal}}">
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Top"
|
|
||||||
Cursor="TopLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Top"
|
|
||||||
Cursor="TopSide"
|
|
||||||
Tag="{x:Static WindowEdge.North}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Top"
|
|
||||||
Cursor="TopRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.NorthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Stretch"
|
|
||||||
Cursor="LeftSide"
|
|
||||||
Tag="{x:Static WindowEdge.West}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Margin="0,4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Stretch"
|
|
||||||
Cursor="RightSide"
|
|
||||||
Tag="{x:Static WindowEdge.East}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomLeftCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthWest}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Height="4" Margin="4,0"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Stretch" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomSide"
|
|
||||||
Tag="{x:Static WindowEdge.South}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
|
|
||||||
<Border Width="4" Height="4"
|
|
||||||
Background="Transparent"
|
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Bottom"
|
|
||||||
Cursor="BottomRightCorner"
|
|
||||||
Tag="{x:Static WindowEdge.SouthEast}"
|
|
||||||
PointerPressed="CustomResizeWindow"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -7,8 +7,17 @@ using Avalonia.Interactivity;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class Launcher : Window, Models.INotificationReceiver
|
public partial class Launcher : ChromelessWindow, Models.INotificationReceiver
|
||||||
{
|
{
|
||||||
|
public static readonly StyledProperty<GridLength> TitleBarHeightProperty =
|
||||||
|
AvaloniaProperty.Register<Launcher, GridLength>(nameof(TitleBarHeight), new GridLength(38, GridUnitType.Pixel));
|
||||||
|
|
||||||
|
public GridLength TitleBarHeight
|
||||||
|
{
|
||||||
|
get => GetValue(TitleBarHeightProperty);
|
||||||
|
set => SetValue(TitleBarHeightProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
public Launcher()
|
public Launcher()
|
||||||
{
|
{
|
||||||
DataContext = new ViewModels.Launcher();
|
DataContext = new ViewModels.Launcher();
|
||||||
|
@ -34,6 +43,20 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
|
{
|
||||||
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
|
if (change.Property == WindowStateProperty)
|
||||||
|
{
|
||||||
|
var state = (WindowState)change.NewValue;
|
||||||
|
if (state == WindowState.Maximized)
|
||||||
|
SetCurrentValue(TitleBarHeightProperty, new GridLength(OperatingSystem.IsMacOS() ? 34 : 30));
|
||||||
|
else
|
||||||
|
SetCurrentValue(TitleBarHeightProperty, new GridLength(38, GridUnitType.Pixel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnKeyDown(KeyEventArgs e)
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
{
|
{
|
||||||
var vm = DataContext as ViewModels.Launcher;
|
var vm = DataContext as ViewModels.Launcher;
|
||||||
|
@ -136,36 +159,43 @@ namespace SourceGit.Views
|
||||||
base.OnClosing(e);
|
base.OnClosing(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MaximizeOrRestoreWindow(object sender, TappedEventArgs e)
|
private void OnTitleBarDoubleTapped(object sender, TappedEventArgs e)
|
||||||
{
|
{
|
||||||
if (WindowState == WindowState.Maximized)
|
_pressedTitleBar = false;
|
||||||
{
|
|
||||||
WindowState = WindowState.Normal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
WindowState = WindowState.Maximized;
|
|
||||||
}
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CustomResizeWindow(object sender, PointerPressedEventArgs e)
|
if (WindowState == WindowState.Maximized)
|
||||||
{
|
WindowState = WindowState.Normal;
|
||||||
if (sender is Border border)
|
else
|
||||||
{
|
WindowState = WindowState.Maximized;
|
||||||
if (border.Tag is WindowEdge edge)
|
|
||||||
{
|
e.Handled = true;
|
||||||
BeginResizeDrag(edge, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.ClickCount != 2)
|
if (e.ClickCount != 2)
|
||||||
{
|
_pressedTitleBar = true;
|
||||||
BeginMoveDrag(e);
|
}
|
||||||
}
|
|
||||||
|
private void MoveWindow(object sender, PointerEventArgs e)
|
||||||
|
{
|
||||||
|
if (!_pressedTitleBar)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var visual = (Visual)e.Source;
|
||||||
|
BeginMoveDrag(new PointerPressedEventArgs(
|
||||||
|
e.Source,
|
||||||
|
e.Pointer,
|
||||||
|
visual,
|
||||||
|
e.GetPosition(visual),
|
||||||
|
e.Timestamp,
|
||||||
|
new PointerPointProperties(RawInputModifiers.None, PointerUpdateKind.LeftButtonPressed),
|
||||||
|
e.KeyModifiers));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndMoveWindow(object sender, PointerReleasedEventArgs e)
|
||||||
|
{
|
||||||
|
_pressedTitleBar = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ScrollTabs(object sender, PointerWheelEventArgs e)
|
private void ScrollTabs(object sender, PointerWheelEventArgs e)
|
||||||
|
@ -229,26 +259,26 @@ namespace SourceGit.Views
|
||||||
private void OnPointerPressedTab(object sender, PointerPressedEventArgs e)
|
private void OnPointerPressedTab(object sender, PointerPressedEventArgs e)
|
||||||
{
|
{
|
||||||
_pressedTab = true;
|
_pressedTab = true;
|
||||||
_startDrag = false;
|
_startDragTab = false;
|
||||||
_pressedTabPosition = e.GetPosition(sender as Border);
|
_pressedTabPosition = e.GetPosition(sender as Border);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPointerReleasedTab(object sender, PointerReleasedEventArgs e)
|
private void OnPointerReleasedTab(object sender, PointerReleasedEventArgs e)
|
||||||
{
|
{
|
||||||
_pressedTab = false;
|
_pressedTab = false;
|
||||||
_startDrag = false;
|
_startDragTab = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPointerMovedOverTab(object sender, PointerEventArgs e)
|
private void OnPointerMovedOverTab(object sender, PointerEventArgs e)
|
||||||
{
|
{
|
||||||
if (_pressedTab && !_startDrag && sender is Border border)
|
if (_pressedTab && !_startDragTab && sender is Border border)
|
||||||
{
|
{
|
||||||
var delta = e.GetPosition(border) - _pressedTabPosition;
|
var delta = e.GetPosition(border) - _pressedTabPosition;
|
||||||
var sizeSquired = delta.X * delta.X + delta.Y * delta.Y;
|
var sizeSquired = delta.X * delta.X + delta.Y * delta.Y;
|
||||||
if (sizeSquired < 64)
|
if (sizeSquired < 64)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_startDrag = true;
|
_startDragTab = true;
|
||||||
|
|
||||||
var data = new DataObject();
|
var data = new DataObject();
|
||||||
data.Set("MovedTab", border.DataContext);
|
data.Set("MovedTab", border.DataContext);
|
||||||
|
@ -270,7 +300,7 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
|
|
||||||
_pressedTab = false;
|
_pressedTab = false;
|
||||||
_startDrag = false;
|
_startDragTab = false;
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,8 +327,9 @@ namespace SourceGit.Views
|
||||||
OnPopupCancel(sender, e);
|
OnPopupCancel(sender, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _pressedTitleBar = false;
|
||||||
private bool _pressedTab = false;
|
private bool _pressedTab = false;
|
||||||
private Point _pressedTabPosition = new Point();
|
private Point _pressedTabPosition = new Point();
|
||||||
private bool _startDrag = false;
|
private bool _startDragTab = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
x:Class="SourceGit.Views.PopupRunningStatus"
|
x:Class="SourceGit.Views.PopupRunningStatus"
|
||||||
x:Name="me">
|
x:Name="me">
|
||||||
<StackPanel Orientation="Vertical">
|
<StackPanel Orientation="Vertical">
|
||||||
<Rectangle Height="1" Margin="-8,0" HorizontalAlignment="Stretch" Fill="{DynamicResource Brush.Border1}" />
|
<Rectangle Height="1" HorizontalAlignment="Stretch" Fill="{DynamicResource Brush.Border1}" />
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,8">
|
<StackPanel Orientation="Horizontal" Margin="0,8">
|
||||||
<ContentPresenter x:Name="icon" Width="12" Height="12"/>
|
<ContentPresenter x:Name="icon" Width="12" Height="12"/>
|
||||||
|
|
|
@ -1,33 +1,23 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:c="using:SourceGit.Converters"
|
xmlns:c="using:SourceGit.Converters"
|
||||||
xmlns:ac="using:Avalonia.Controls.Converters"
|
xmlns:ac="using:Avalonia.Controls.Converters"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.Preference"
|
x:Class="SourceGit.Views.Preference"
|
||||||
x:DataType="vm:Preference"
|
x:DataType="vm:Preference"
|
||||||
x:Name="me"
|
x:Name="me"
|
||||||
Icon="/App.ico"
|
Icon="/App.ico"
|
||||||
Title="{DynamicResource Text.Preference}"
|
Title="{DynamicResource Text.Preference}"
|
||||||
Background="Transparent"
|
Width="600" SizeToContent="Height"
|
||||||
Width="600" SizeToContent="Height"
|
CanResize="False"
|
||||||
CanResize="False"
|
WindowStartupLocation="CenterScreen">
|
||||||
WindowStartupLocation="CenterScreen"
|
<Grid RowDefinitions="Auto,Auto">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,Auto" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -62,7 +52,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Border Grid.Row="1" Background="{DynamicResource Brush.Window}">
|
<Border Grid.Row="1">
|
||||||
<TabControl>
|
<TabControl>
|
||||||
<TabItem>
|
<TabItem>
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
|
@ -210,20 +200,7 @@
|
||||||
Padding="4"
|
Padding="4"
|
||||||
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border1}"
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Value="{Binding DefaultFontSize, Mode=TwoWay}">
|
Value="{Binding DefaultFontSize, Mode=TwoWay}"/>
|
||||||
<NumericUpDown.Styles>
|
|
||||||
<Style Selector="NumericUpDown /template/ ButtonSpinner#PART_Spinner">
|
|
||||||
<Setter Property="MinHeight" Value="0"/>
|
|
||||||
<Setter Property="Height" Value="28"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="NumericUpDown /template/ TextBox#PART_TextBox">
|
|
||||||
<Setter Property="MinHeight" Value="0"/>
|
|
||||||
<Setter Property="Height" Value="28"/>
|
|
||||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
|
||||||
<Setter Property="CornerRadius" Value="3,0,0,3"/>
|
|
||||||
</Style>
|
|
||||||
</NumericUpDown.Styles>
|
|
||||||
</NumericUpDown>
|
|
||||||
|
|
||||||
<TextBlock Grid.Row="4" Grid.Column="0"
|
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||||
Text="{DynamicResource Text.Preference.Appearance.ColorOverrides}"
|
Text="{DynamicResource Text.Preference.Appearance.ColorOverrides}"
|
||||||
|
@ -392,20 +369,7 @@
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
ParsingNumberStyle="Integer"
|
ParsingNumberStyle="Integer"
|
||||||
FormatString="0"
|
FormatString="0"
|
||||||
Value="{Binding GitAutoFetchInterval, Mode=TwoWay, FallbackValue=10}">
|
Value="{Binding GitAutoFetchInterval, Mode=TwoWay, FallbackValue=10}"/>
|
||||||
<NumericUpDown.Styles>
|
|
||||||
<Style Selector="NumericUpDown /template/ ButtonSpinner#PART_Spinner">
|
|
||||||
<Setter Property="MinHeight" Value="0"/>
|
|
||||||
<Setter Property="Height" Value="28"/>
|
|
||||||
</Style>
|
|
||||||
<Style Selector="NumericUpDown /template/ TextBox#PART_TextBox">
|
|
||||||
<Setter Property="MinHeight" Value="0"/>
|
|
||||||
<Setter Property="Height" Value="28"/>
|
|
||||||
<Setter Property="VerticalContentAlignment" Value="Center"/>
|
|
||||||
<Setter Property="CornerRadius" Value="3,0,0,3"/>
|
|
||||||
</Style>
|
|
||||||
</NumericUpDown.Styles>
|
|
||||||
</NumericUpDown>
|
|
||||||
|
|
||||||
<TextBlock Grid.Column="1"
|
<TextBlock Grid.Column="1"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
|
@ -553,4 +517,4 @@
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -5,7 +5,6 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
using Avalonia.Controls;
|
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
@ -14,7 +13,7 @@ using Avalonia.Threading;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class Preference : Window
|
public partial class Preference : ChromelessWindow
|
||||||
{
|
{
|
||||||
public AvaloniaList<FontFamily> InstalledFonts
|
public AvaloniaList<FontFamily> InstalledFonts
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.Rebase}"/>
|
Text="{DynamicResource Text.Rebase}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32" ColumnDefinitions="150,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32" ColumnDefinitions="130,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
|
@ -36,11 +36,11 @@
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="m:Commit">
|
<DataTemplate DataType="m:Commit">
|
||||||
<StackPanel Orientation="Horizontal">
|
<Grid ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
|
|
|
@ -103,7 +103,7 @@
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Grid Grid.Row="1">
|
<Grid Grid.Row="1">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="250" MinWidth="200" MaxWidth="400"/>
|
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.RepositorySidebarWidth, Mode=TwoWay}" MinWidth="200" MaxWidth="400"/>
|
||||||
<ColumnDefinition Width="3"/>
|
<ColumnDefinition Width="3"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
@ -615,19 +615,19 @@
|
||||||
<ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}">
|
<ContentControl Grid.Column="0" Margin="8,0" Content="{Binding InProgressContext}">
|
||||||
<ContentControl.DataTemplates>
|
<ContentControl.DataTemplates>
|
||||||
<DataTemplate DataType="vm:CherryPickInProgress">
|
<DataTemplate DataType="vm:CherryPickInProgress">
|
||||||
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.FG3}" Text="{DynamicResource Text.InProgress.CherryPick}"/>
|
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.CherryPick}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="vm:RebaseInProgress">
|
<DataTemplate DataType="vm:RebaseInProgress">
|
||||||
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.FG3}" Text="{DynamicResource Text.InProgress.Rebase}"/>
|
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Rebase}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="vm:RevertInProgress">
|
<DataTemplate DataType="vm:RevertInProgress">
|
||||||
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.FG3}" Text="{DynamicResource Text.InProgress.Revert}"/>
|
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Revert}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
<DataTemplate DataType="vm:MergeInProgress">
|
<DataTemplate DataType="vm:MergeInProgress">
|
||||||
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.FG3}" Text="{DynamicResource Text.InProgress.Merge}"/>
|
<TextBlock FontWeight="Bold" Foreground="{DynamicResource Brush.ConflictForeground}" Text="{DynamicResource Text.InProgress.Merge}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</ContentControl.DataTemplates>
|
</ContentControl.DataTemplates>
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
|
|
|
@ -25,11 +25,11 @@
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Reset.MoveTo}"/>
|
Text="{DynamicResource Text.Reset.MoveTo}"/>
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
<Grid Grid.Row="1" Grid.Column="1" ColumnDefinitions="Auto,Auto,*" Height="20" VerticalAlignment="Center">
|
||||||
<Path Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Text="{Binding To.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
<TextBlock Grid.Column="1" Text="{Binding To.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||||
<TextBlock Text="{Binding To.Subject}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="2" Text="{Binding To.Subject}" Margin="8,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
|
|
|
@ -12,17 +12,17 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.Revert}"/>
|
Text="{DynamicResource Text.Revert}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="150,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32" ColumnDefinitions="130,*">
|
||||||
<TextBlock Grid.Column="0"
|
<TextBlock Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Revert.Commit}"/>
|
Text="{DynamicResource Text.Revert.Commit}"/>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
<Grid Grid.Column="1" ColumnDefinitions="Auto,Auto,*">
|
||||||
<Path Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Width="14" Height="14" Margin="0,8,0,0" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Classes="monospace" VerticalAlignment="Center" Text="{Binding Target.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="1" Classes="monospace" VerticalAlignment="Center" Text="{Binding Target.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange" Margin="8,0,0,0"/>
|
||||||
<TextBlock VerticalAlignment="Center" Text="{Binding Target.Subject}" Margin="4,0,0,0"/>
|
<TextBlock Grid.Column="2" VerticalAlignment="Center" Text="{Binding Target.Subject}" Margin="4,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<CheckBox Grid.Row="1" Grid.Column="1"
|
<CheckBox Grid.Row="1" Grid.Column="1"
|
||||||
Content="{DynamicResource Text.Revert.CommitChanges}"
|
Content="{DynamicResource Text.Revert.CommitChanges}"
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
x:DataType="vm:CommitDetail">
|
x:DataType="vm:CommitDetail">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="256" MinWidth="200" MaxWidth="480"/>
|
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.CommitDetailFilesLeftWidth, Mode=TwoWay}" MinWidth="200" MaxWidth="480"/>
|
||||||
<ColumnDefinition Width="4"/>
|
<ColumnDefinition Width="4"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
|
@ -12,22 +12,23 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.Reword}"/>
|
Text="{DynamicResource Text.Reword}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32" ColumnDefinitions="100,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="100,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Reword.On}"/>
|
Text="{DynamicResource Text.Reword.On}"/>
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
<Grid Grid.Row="0" Grid.Column="1" ColumnDefinitions="Auto,Auto,*" Height="20" VerticalAlignment="Center">
|
||||||
<Path Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
<TextBlock Grid.Column="1" Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||||
<TextBlock Text="{Binding Head.Subject}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="2" Text="{Binding Head.Subject}" Margin="8,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Reword.Message}"/>
|
Text="{DynamicResource Text.Reword.Message}"/>
|
||||||
<TextBox Grid.Row="1" Grid.RowSpan="2" Grid.Column="1"
|
<TextBox Grid.Row="1" Grid.RowSpan="3" Grid.Column="1"
|
||||||
|
Margin="0,4,0,0"
|
||||||
CornerRadius="2"
|
CornerRadius="2"
|
||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
VerticalContentAlignment="Top"
|
VerticalContentAlignment="Top"
|
||||||
|
|
|
@ -1,29 +1,20 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
xmlns:sys="clr-namespace:System;assembly=mscorlib"
|
||||||
x:Class="SourceGit.Views.SelfUpdate"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:DataType="vm:SelfUpdate"
|
x:Class="SourceGit.Views.SelfUpdate"
|
||||||
Title="{DynamicResource Text.SelfUpdate.Title}"
|
x:DataType="vm:SelfUpdate"
|
||||||
Icon="/App.ico"
|
Title="{DynamicResource Text.SelfUpdate.Title}"
|
||||||
Background="Transparent"
|
Icon="/App.ico"
|
||||||
SizeToContent="WidthAndHeight"
|
SizeToContent="WidthAndHeight"
|
||||||
CanResize="False"
|
CanResize="False"
|
||||||
WindowStartupLocation="CenterOwner"
|
WindowStartupLocation="CenterOwner">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
<Grid RowDefinitions="Auto,*">
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,*" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- TitleBar -->
|
<!-- TitleBar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -61,7 +52,7 @@
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
<Grid Grid.Row="1" Background="{DynamicResource Brush.Window}">
|
<Grid Grid.Row="1">
|
||||||
<ContentControl Content="{Binding Data}">
|
<ContentControl Content="{Binding Data}">
|
||||||
<ContentControl.DataTemplates>
|
<ContentControl.DataTemplates>
|
||||||
<DataTemplate DataType="m:Version">
|
<DataTemplate DataType="m:Version">
|
||||||
|
@ -150,4 +141,4 @@
|
||||||
</ContentControl>
|
</ContentControl>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Avalonia.Interactivity;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public partial class SelfUpdate : Window
|
public partial class SelfUpdate : ChromelessWindow
|
||||||
{
|
{
|
||||||
public SelfUpdate()
|
public SelfUpdate()
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,32 +12,33 @@
|
||||||
<TextBlock FontSize="18"
|
<TextBlock FontSize="18"
|
||||||
Classes="bold"
|
Classes="bold"
|
||||||
Text="{DynamicResource Text.Squash}"/>
|
Text="{DynamicResource Text.Squash}"/>
|
||||||
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32" ColumnDefinitions="100,*">
|
<Grid Margin="0,16,0,0" RowDefinitions="32,32,32,32,32" ColumnDefinitions="100,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Squash.Head}"/>
|
Text="{DynamicResource Text.Squash.Head}"/>
|
||||||
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
<Grid Grid.Row="0" Grid.Column="1" ColumnDefinitions="Auto,Auto,*" Height="20" VerticalAlignment="Center">
|
||||||
<Path Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
<TextBlock Grid.Column="1" Text="{Binding Head.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||||
<TextBlock Text="{Binding Head.Subject}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="2" Text="{Binding Head.Subject}" Margin="8,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0"
|
<TextBlock Grid.Row="1" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Squash.To}"/>
|
Text="{DynamicResource Text.Squash.To}"/>
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal" Height="20" VerticalAlignment="Center">
|
<Grid Grid.Row="1" Grid.Column="1" ColumnDefinitions="Auto,Auto,*" Height="20" VerticalAlignment="Center">
|
||||||
<Path Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
<Path Grid.Column="0" Margin="0,6,8,0" Width="14" Height="14" Fill="{DynamicResource Brush.FG1}" Data="{StaticResource Icons.Commit}"/>
|
||||||
<TextBlock Text="{Binding Parent.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
<TextBlock Grid.Column="1" Text="{Binding Parent.SHA, Converter={x:Static c:StringConverters.ToShortSHA}}" Foreground="DarkOrange"/>
|
||||||
<TextBlock Text="{Binding Parent.Subject}" Margin="8,0,0,0"/>
|
<TextBlock Grid.Column="2" Text="{Binding Parent.Subject}" Margin="8,0,0,0" TextTrimming="CharacterEllipsis"/>
|
||||||
</StackPanel>
|
</Grid>
|
||||||
|
|
||||||
<TextBlock Grid.Row="2" Grid.Column="0"
|
<TextBlock Grid.Row="2" Grid.Column="0"
|
||||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||||
Margin="0,0,8,0"
|
Margin="0,0,8,0"
|
||||||
Text="{DynamicResource Text.Squash.Message}"/>
|
Text="{DynamicResource Text.Squash.Message}"/>
|
||||||
<TextBox Grid.Row="2" Grid.RowSpan="2" Grid.Column="1"
|
<TextBox Grid.Row="2" Grid.RowSpan="3" Grid.Column="1"
|
||||||
|
Margin="0,4,0,0"
|
||||||
CornerRadius="2"
|
CornerRadius="2"
|
||||||
AcceptsReturn="True"
|
AcceptsReturn="True"
|
||||||
VerticalContentAlignment="Top"
|
VerticalContentAlignment="Top"
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
x:DataType="vm:StashesPage">
|
x:DataType="vm:StashesPage">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="300" MinWidth="300"/>
|
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.StashesLeftWidth, Mode=TwoWay}" MinWidth="300"/>
|
||||||
<ColumnDefinition Width="4"/>
|
<ColumnDefinition Width="4"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
|
@ -1,33 +1,18 @@
|
||||||
<Window xmlns="https://github.com/avaloniaui"
|
<v:ChromelessWindow xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:m="using:SourceGit.Models"
|
xmlns:m="using:SourceGit.Models"
|
||||||
xmlns:vm="using:SourceGit.ViewModels"
|
xmlns:vm="using:SourceGit.ViewModels"
|
||||||
xmlns:v="using:SourceGit.Views"
|
xmlns:v="using:SourceGit.Views"
|
||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="SourceGit.Views.Statistics"
|
x:Class="SourceGit.Views.Statistics"
|
||||||
x:DataType="vm:Statistics"
|
x:DataType="vm:Statistics"
|
||||||
Title="{DynamicResource Text.Statistics}"
|
Title="{DynamicResource Text.Statistics}"
|
||||||
Background="Transparent"
|
Width="800" Height="450"
|
||||||
Width="800" Height="450"
|
WindowStartupLocation="CenterOwner"
|
||||||
WindowStartupLocation="CenterOwner"
|
CanResize="False">
|
||||||
CanResize="False"
|
<Grid RowDefinitions="Auto,Auto,*">
|
||||||
ExtendClientAreaToDecorationsHint="True"
|
|
||||||
ExtendClientAreaChromeHints="NoChrome"
|
|
||||||
SystemDecorations="{OnPlatform Full, Linux=None}">
|
|
||||||
<Grid RowDefinitions="Auto,Auto,*" Margin="{OnPlatform 0, Linux=6}">
|
|
||||||
<!-- Custom window shadow for Linux -->
|
|
||||||
<Border Grid.Row="0" Grid.RowSpan="3"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
Effect="drop-shadow(0 0 6 #A0000000)"
|
|
||||||
IsVisible="{OnPlatform False, Linux=True}"/>
|
|
||||||
|
|
||||||
<!-- Window BG -->
|
|
||||||
<Border Grid.Row="1" Grid.RowSpan="2"
|
|
||||||
Background="{DynamicResource Brush.Window}"
|
|
||||||
IsVisible="{OnPlatform True, Linux=False}"/>
|
|
||||||
|
|
||||||
<!-- Title bar -->
|
<!-- Title bar -->
|
||||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
<Grid Grid.Row="0" ColumnDefinitions="Auto,*,Auto" Height="30">
|
||||||
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
<Border Grid.Column="0" Grid.ColumnSpan="3"
|
||||||
|
@ -185,4 +170,4 @@
|
||||||
HorizontalAlignment="Center" VerticalAlignment="Center"
|
HorizontalAlignment="Center" VerticalAlignment="Center"
|
||||||
IsVisible="{Binding IsLoading}"/>
|
IsVisible="{Binding IsLoading}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</v:ChromelessWindow>
|
||||||
|
|
|
@ -226,7 +226,7 @@ namespace SourceGit.Views
|
||||||
private int _lastHitIdx = -1;
|
private int _lastHitIdx = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class Statistics : Window
|
public partial class Statistics : ChromelessWindow
|
||||||
{
|
{
|
||||||
public Statistics()
|
public Statistics()
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,18 +11,16 @@
|
||||||
Background="{DynamicResource Brush.Contents}">
|
Background="{DynamicResource Brush.Contents}">
|
||||||
<UserControl.DataTemplates>
|
<UserControl.DataTemplates>
|
||||||
<DataTemplate DataType="m:TextDiff">
|
<DataTemplate DataType="m:TextDiff">
|
||||||
<v:CombinedTextDiffPresenter BorderBrush="{DynamicResource Brush.Border2}"
|
<v:CombinedTextDiffPresenter FileName="{Binding File}"
|
||||||
BorderThickness="0"
|
|
||||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
|
||||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
|
||||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
|
||||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
|
||||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
|
||||||
Foreground="{DynamicResource Brush.FG1}"
|
Foreground="{DynamicResource Brush.FG1}"
|
||||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
LineBrush="{DynamicResource Brush.Border2}"
|
||||||
|
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||||
|
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||||
|
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||||
|
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||||
|
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||||
|
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||||
DiffData="{Binding}"
|
|
||||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
|
||||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
@ -30,40 +28,36 @@
|
||||||
<DataTemplate DataType="vm:TwoSideTextDiff">
|
<DataTemplate DataType="vm:TwoSideTextDiff">
|
||||||
<Grid ColumnDefinitions="*,1,*">
|
<Grid ColumnDefinitions="*,1,*">
|
||||||
<v:SingleSideTextDiffPresenter Grid.Column="0"
|
<v:SingleSideTextDiffPresenter Grid.Column="0"
|
||||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
|
||||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
|
||||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
|
|
||||||
IsOld="True"
|
IsOld="True"
|
||||||
BorderBrush="{DynamicResource Brush.Border2}"
|
FileName="{Binding File}"
|
||||||
BorderThickness="0"
|
|
||||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
|
||||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
|
||||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
|
||||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
|
||||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
|
||||||
Foreground="{DynamicResource Brush.FG1}"
|
Foreground="{DynamicResource Brush.FG1}"
|
||||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
LineBrush="{DynamicResource Brush.Border2}"
|
||||||
|
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||||
|
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||||
|
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||||
|
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||||
|
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||||
|
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||||
DiffData="{Binding}"/>
|
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||||
|
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||||
|
|
||||||
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
<Rectangle Grid.Column="1" Fill="{DynamicResource Brush.Border2}" Width="1" HorizontalAlignment="Center" VerticalAlignment="Stretch"/>
|
||||||
|
|
||||||
<v:SingleSideTextDiffPresenter Grid.Column="2"
|
<v:SingleSideTextDiffPresenter Grid.Column="2"
|
||||||
SyncScrollOffset="{Binding #ThisControl.SyncScrollOffset, Mode=TwoWay}"
|
|
||||||
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
|
||||||
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"
|
|
||||||
IsOld="False"
|
IsOld="False"
|
||||||
BorderBrush="{DynamicResource Brush.Border2}"
|
FileName="{Binding File}"
|
||||||
BorderThickness="0"
|
|
||||||
LineBGEmpty = "{DynamicResource Brush.TextDiffView.LineBG1.EMPTY}"
|
|
||||||
LineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG1.ADD}"
|
|
||||||
LineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG1.DELETED}"
|
|
||||||
SecondaryLineBGAdd = "{DynamicResource Brush.TextDiffView.LineBG2.ADD}"
|
|
||||||
SecondaryLineBGDeleted = "{DynamicResource Brush.TextDiffView.LineBG2.DELETED}"
|
|
||||||
Foreground="{DynamicResource Brush.FG1}"
|
Foreground="{DynamicResource Brush.FG1}"
|
||||||
SecondaryFG="{DynamicResource Brush.FG2}"
|
LineBrush="{DynamicResource Brush.Border2}"
|
||||||
|
EmptyContentBackground="{DynamicResource Brush.Diff.EmptyBG}"
|
||||||
|
AddedContentBackground="{DynamicResource Brush.Diff.AddedBG}"
|
||||||
|
DeletedContentBackground="{DynamicResource Brush.Diff.DeletedBG}"
|
||||||
|
AddedHighlightBrush="{DynamicResource Brush.Diff.AddedHighlight}"
|
||||||
|
DeletedHighlightBrush="{DynamicResource Brush.Diff.DeletedHighlight}"
|
||||||
|
IndicatorForeground="{DynamicResource Brush.FG2}"
|
||||||
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
FontFamily="{Binding Source={x:Static vm:Preference.Instance}, Path=MonospaceFont}"
|
||||||
DiffData="{Binding}"/>
|
UseSyntaxHighlighting="{Binding Source={x:Static vm:Preference.Instance}, Path=UseSyntaxHighlighting}"
|
||||||
|
WordWrap="{Binding Source={x:Static vm:Preference.Instance}, Path=EnableDiffViewWordWrap}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
</UserControl.DataTemplates>
|
</UserControl.DataTemplates>
|
||||||
|
|
|
@ -7,6 +7,7 @@ using System.Text;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Data;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Interactivity;
|
using Avalonia.Interactivity;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
|
@ -21,7 +22,161 @@ using AvaloniaEdit.Utils;
|
||||||
|
|
||||||
namespace SourceGit.Views
|
namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
public class CombinedTextDiffPresenter : TextEditor
|
public class IThemedTextDiffPresenter : TextEditor
|
||||||
|
{
|
||||||
|
public static readonly StyledProperty<string> FileNameProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, string>(nameof(FileName), string.Empty);
|
||||||
|
|
||||||
|
public string FileName
|
||||||
|
{
|
||||||
|
get => GetValue(FileNameProperty);
|
||||||
|
set => SetValue(FileNameProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> LineBrushProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(LineBrush), new SolidColorBrush(Colors.DarkGray));
|
||||||
|
|
||||||
|
public IBrush LineBrush
|
||||||
|
{
|
||||||
|
get => GetValue(LineBrushProperty);
|
||||||
|
set => SetValue(LineBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> EmptyContentBackgroundProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(EmptyContentBackground), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
||||||
|
|
||||||
|
public IBrush EmptyContentBackground
|
||||||
|
{
|
||||||
|
get => GetValue(EmptyContentBackgroundProperty);
|
||||||
|
set => SetValue(EmptyContentBackgroundProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> AddedContentBackgroundProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(AddedContentBackground), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
||||||
|
|
||||||
|
public IBrush AddedContentBackground
|
||||||
|
{
|
||||||
|
get => GetValue(AddedContentBackgroundProperty);
|
||||||
|
set => SetValue(AddedContentBackgroundProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> DeletedContentBackgroundProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(DeletedContentBackground), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
||||||
|
|
||||||
|
public IBrush DeletedContentBackground
|
||||||
|
{
|
||||||
|
get => GetValue(DeletedContentBackgroundProperty);
|
||||||
|
set => SetValue(DeletedContentBackgroundProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> AddedHighlightBrushProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(AddedHighlightBrush), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
||||||
|
|
||||||
|
public IBrush AddedHighlightBrush
|
||||||
|
{
|
||||||
|
get => GetValue(AddedHighlightBrushProperty);
|
||||||
|
set => SetValue(AddedHighlightBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> DeletedHighlightBrushProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(DeletedHighlightBrush), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
||||||
|
|
||||||
|
public IBrush DeletedHighlightBrush
|
||||||
|
{
|
||||||
|
get => GetValue(DeletedHighlightBrushProperty);
|
||||||
|
set => SetValue(DeletedHighlightBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<IBrush> IndicatorForegroundProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, IBrush>(nameof(IndicatorForeground), Brushes.Gray);
|
||||||
|
|
||||||
|
public IBrush IndicatorForeground
|
||||||
|
{
|
||||||
|
get => GetValue(IndicatorForegroundProperty);
|
||||||
|
set => SetValue(IndicatorForegroundProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
||||||
|
AvaloniaProperty.Register<IThemedTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
||||||
|
|
||||||
|
public bool UseSyntaxHighlighting
|
||||||
|
{
|
||||||
|
get => GetValue(UseSyntaxHighlightingProperty);
|
||||||
|
set => SetValue(UseSyntaxHighlightingProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Type StyleKeyOverride => typeof(TextEditor);
|
||||||
|
|
||||||
|
public IThemedTextDiffPresenter(TextArea area, TextDocument doc) : base(area, doc)
|
||||||
|
{
|
||||||
|
IsReadOnly = true;
|
||||||
|
ShowLineNumbers = false;
|
||||||
|
BorderThickness = new Thickness(0);
|
||||||
|
|
||||||
|
TextArea.TextView.Margin = new Thickness(4, 0);
|
||||||
|
TextArea.TextView.Options.EnableHyperlinks = false;
|
||||||
|
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnLoaded(RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnLoaded(e);
|
||||||
|
UpdateTextMate();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnUnloaded(RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnUnloaded(e);
|
||||||
|
|
||||||
|
if (_textMate != null)
|
||||||
|
{
|
||||||
|
_textMate.Dispose();
|
||||||
|
_textMate = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
|
{
|
||||||
|
base.OnPropertyChanged(change);
|
||||||
|
|
||||||
|
if (change.Property == UseSyntaxHighlightingProperty)
|
||||||
|
UpdateTextMate();
|
||||||
|
else if (change.Property == FileNameProperty)
|
||||||
|
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
|
||||||
|
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
||||||
|
Models.TextMateHelper.SetThemeByApp(_textMate);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void UpdateTextMate()
|
||||||
|
{
|
||||||
|
if (UseSyntaxHighlighting)
|
||||||
|
{
|
||||||
|
if (_textMate == null)
|
||||||
|
{
|
||||||
|
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
||||||
|
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
||||||
|
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||||
|
Models.TextMateHelper.SetGrammarByFileName(_textMate, FileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_textMate != null)
|
||||||
|
{
|
||||||
|
_textMate.Dispose();
|
||||||
|
_textMate = null;
|
||||||
|
GC.Collect();
|
||||||
|
|
||||||
|
TextArea.TextView.Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private TextMate.Installation _textMate = null;
|
||||||
|
protected IVisualLineTransformer _lineStyleTransformer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CombinedTextDiffPresenter : IThemedTextDiffPresenter
|
||||||
{
|
{
|
||||||
public class LineNumberMargin : AbstractMargin
|
public class LineNumberMargin : AbstractMargin
|
||||||
{
|
{
|
||||||
|
@ -104,7 +259,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
var pen = new Pen(_editor.BorderBrush, 1);
|
var pen = new Pen(_editor.LineBrush, 1);
|
||||||
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,11 +310,11 @@ namespace SourceGit.Views
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Models.TextDiffLineType.None:
|
case Models.TextDiffLineType.None:
|
||||||
return _editor.LineBGEmpty;
|
return _editor.EmptyContentBackground;
|
||||||
case Models.TextDiffLineType.Added:
|
case Models.TextDiffLineType.Added:
|
||||||
return _editor.LineBGAdd;
|
return _editor.AddedContentBackground;
|
||||||
case Models.TextDiffLineType.Deleted:
|
case Models.TextDiffLineType.Deleted:
|
||||||
return _editor.LineBGDeleted;
|
return _editor.DeletedContentBackground;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +341,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
||||||
{
|
{
|
||||||
v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
|
v.TextRunProperties.SetForegroundBrush(_editor.IndicatorForeground);
|
||||||
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -195,7 +350,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (info.Highlights.Count > 0)
|
if (info.Highlights.Count > 0)
|
||||||
{
|
{
|
||||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.SecondaryLineBGAdd : _editor.SecondaryLineBGDeleted;
|
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.AddedHighlightBrush : _editor.DeletedHighlightBrush;
|
||||||
foreach (var highlight in info.Highlights)
|
foreach (var highlight in info.Highlights)
|
||||||
{
|
{
|
||||||
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
||||||
|
@ -209,129 +364,57 @@ namespace SourceGit.Views
|
||||||
private readonly CombinedTextDiffPresenter _editor;
|
private readonly CombinedTextDiffPresenter _editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Models.TextDiff> DiffDataProperty =
|
public Models.TextDiff DiffData => DataContext as Models.TextDiff;
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, Models.TextDiff>(nameof(DiffData));
|
|
||||||
|
|
||||||
public Models.TextDiff DiffData
|
|
||||||
{
|
|
||||||
get => GetValue(DiffDataProperty);
|
|
||||||
set => SetValue(DiffDataProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGEmptyProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGEmpty), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGEmpty
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGEmptyProperty);
|
|
||||||
set => SetValue(LineBGEmptyProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGAddProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGAdd), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGAdd
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGAddProperty);
|
|
||||||
set => SetValue(LineBGAddProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGDeletedProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(LineBGDeleted), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGDeleted
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGDeletedProperty);
|
|
||||||
set => SetValue(LineBGDeletedProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryLineBGAddProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryLineBGAdd), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
|
||||||
|
|
||||||
public IBrush SecondaryLineBGAdd
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryLineBGAddProperty);
|
|
||||||
set => SetValue(SecondaryLineBGAddProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryLineBGDeletedProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryLineBGDeleted), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush SecondaryLineBGDeleted
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryLineBGDeletedProperty);
|
|
||||||
set => SetValue(SecondaryLineBGDeletedProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryFGProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, IBrush>(nameof(SecondaryFG), Brushes.Gray);
|
|
||||||
|
|
||||||
public IBrush SecondaryFG
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryFGProperty);
|
|
||||||
set => SetValue(SecondaryFGProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, Vector>(nameof(SyncScrollOffset));
|
|
||||||
|
|
||||||
public Vector SyncScrollOffset
|
|
||||||
{
|
|
||||||
get => GetValue(SyncScrollOffsetProperty);
|
|
||||||
set => SetValue(SyncScrollOffsetProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
|
||||||
AvaloniaProperty.Register<CombinedTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
|
||||||
|
|
||||||
public bool UseSyntaxHighlighting
|
|
||||||
{
|
|
||||||
get => GetValue(UseSyntaxHighlightingProperty);
|
|
||||||
set => SetValue(UseSyntaxHighlightingProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
|
||||||
|
|
||||||
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
public CombinedTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||||
{
|
{
|
||||||
_lineStyleTransformer = new LineStyleTransformer(this);
|
_lineStyleTransformer = new LineStyleTransformer(this);
|
||||||
|
|
||||||
IsReadOnly = true;
|
|
||||||
ShowLineNumbers = false;
|
|
||||||
|
|
||||||
TextArea.LeftMargins.Add(new LineNumberMargin(this, true) { Margin = new Thickness(8, 0) });
|
TextArea.LeftMargins.Add(new LineNumberMargin(this, true) { Margin = new Thickness(8, 0) });
|
||||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||||
TextArea.LeftMargins.Add(new LineNumberMargin(this, false) { Margin = new Thickness(8, 0) });
|
TextArea.LeftMargins.Add(new LineNumberMargin(this, false) { Margin = new Thickness(8, 0) });
|
||||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||||
|
|
||||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
|
||||||
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
||||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
}
|
||||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
|
||||||
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnApplyTemplate(e);
|
||||||
|
|
||||||
|
var scroller = (ScrollViewer)e.NameScope.Find("PART_ScrollViewer");
|
||||||
|
scroller.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.TwoWay));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoaded(RoutedEventArgs e)
|
protected override void OnLoaded(RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnLoaded(e);
|
base.OnLoaded(e);
|
||||||
|
|
||||||
UpdateTextMate();
|
|
||||||
|
|
||||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||||
TextArea.TextView.ScrollOffsetChanged += OnTextViewScrollOffsetChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnUnloaded(RoutedEventArgs e)
|
protected override void OnUnloaded(RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnUnloaded(e);
|
base.OnUnloaded(e);
|
||||||
|
|
||||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||||
TextArea.TextView.ScrollOffsetChanged -= OnTextViewScrollOffsetChanged;
|
}
|
||||||
|
|
||||||
if (_textMate != null)
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDataContextChanged(e);
|
||||||
|
|
||||||
|
var textDiff = DataContext as Models.TextDiff;
|
||||||
|
if (textDiff != null)
|
||||||
{
|
{
|
||||||
_textMate.Dispose();
|
var builder = new StringBuilder();
|
||||||
_textMate = null;
|
foreach (var line in textDiff.Lines)
|
||||||
|
builder.AppendLine(line.Content);
|
||||||
|
|
||||||
|
Text = builder.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Text = string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
|
@ -346,9 +429,7 @@ namespace SourceGit.Views
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
var parentView = this.FindAncestorOfType<TextDiffView>();
|
var parentView = this.FindAncestorOfType<TextDiffView>();
|
||||||
if (parentView != null)
|
if (parentView != null)
|
||||||
{
|
|
||||||
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, false);
|
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, false);
|
||||||
}
|
|
||||||
|
|
||||||
var copy = new MenuItem();
|
var copy = new MenuItem();
|
||||||
copy.Header = App.Text("Copy");
|
copy.Header = App.Text("Copy");
|
||||||
|
@ -364,84 +445,9 @@ namespace SourceGit.Views
|
||||||
TextArea.TextView.OpenContextMenu(menu);
|
TextArea.TextView.OpenContextMenu(menu);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTextViewScrollOffsetChanged(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
SetCurrentValue(SyncScrollOffsetProperty, TextArea.TextView.ScrollOffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
||||||
{
|
|
||||||
base.OnPropertyChanged(change);
|
|
||||||
|
|
||||||
if (change.Property == DiffDataProperty)
|
|
||||||
{
|
|
||||||
if (DiffData != null)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
foreach (var line in DiffData.Lines)
|
|
||||||
{
|
|
||||||
builder.AppendLine(line.Content);
|
|
||||||
}
|
|
||||||
|
|
||||||
Text = builder.ToString();
|
|
||||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Text = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (change.Property == SyncScrollOffsetProperty)
|
|
||||||
{
|
|
||||||
if (TextArea.TextView.ScrollOffset != SyncScrollOffset)
|
|
||||||
{
|
|
||||||
IScrollable scrollable = TextArea.TextView;
|
|
||||||
scrollable.Offset = SyncScrollOffset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (change.Property == UseSyntaxHighlightingProperty)
|
|
||||||
{
|
|
||||||
UpdateTextMate();
|
|
||||||
}
|
|
||||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
|
||||||
{
|
|
||||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTextMate()
|
|
||||||
{
|
|
||||||
if (UseSyntaxHighlighting)
|
|
||||||
{
|
|
||||||
if (_textMate == null)
|
|
||||||
{
|
|
||||||
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
|
||||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
|
||||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
|
||||||
|
|
||||||
if (DiffData != null)
|
|
||||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_textMate != null)
|
|
||||||
{
|
|
||||||
_textMate.Dispose();
|
|
||||||
_textMate = null;
|
|
||||||
GC.Collect();
|
|
||||||
|
|
||||||
TextArea.TextView.Redraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextMate.Installation _textMate;
|
|
||||||
private readonly LineStyleTransformer _lineStyleTransformer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SingleSideTextDiffPresenter : TextEditor
|
public class SingleSideTextDiffPresenter : IThemedTextDiffPresenter
|
||||||
{
|
{
|
||||||
public class LineNumberMargin : AbstractMargin
|
public class LineNumberMargin : AbstractMargin
|
||||||
{
|
{
|
||||||
|
@ -523,7 +529,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
var pen = new Pen(_editor.BorderBrush, 1);
|
var pen = new Pen(_editor.LineBrush, 1);
|
||||||
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
context.DrawLine(pen, new Point(0, 0), new Point(0, Bounds.Height));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,11 +581,11 @@ namespace SourceGit.Views
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case Models.TextDiffLineType.None:
|
case Models.TextDiffLineType.None:
|
||||||
return _editor.LineBGEmpty;
|
return _editor.EmptyContentBackground;
|
||||||
case Models.TextDiffLineType.Added:
|
case Models.TextDiffLineType.Added:
|
||||||
return _editor.LineBGAdd;
|
return _editor.AddedContentBackground;
|
||||||
case Models.TextDiffLineType.Deleted:
|
case Models.TextDiffLineType.Deleted:
|
||||||
return _editor.LineBGDeleted;
|
return _editor.DeletedContentBackground;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -607,7 +613,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
ChangeLinePart(line.Offset, line.EndOffset, v =>
|
||||||
{
|
{
|
||||||
v.TextRunProperties.SetForegroundBrush(_editor.SecondaryFG);
|
v.TextRunProperties.SetForegroundBrush(_editor.IndicatorForeground);
|
||||||
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
v.TextRunProperties.SetTypeface(new Typeface(_editor.FontFamily, FontStyle.Italic));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -616,7 +622,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (info.Highlights.Count > 0)
|
if (info.Highlights.Count > 0)
|
||||||
{
|
{
|
||||||
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.LineBGAdd : _editor.LineBGDeleted;
|
var bg = info.Type == Models.TextDiffLineType.Added ? _editor.AddedHighlightBrush : _editor.DeletedHighlightBrush;
|
||||||
foreach (var highlight in info.Highlights)
|
foreach (var highlight in info.Highlights)
|
||||||
{
|
{
|
||||||
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
ChangeLinePart(line.Offset + highlight.Start, line.Offset + highlight.Start + highlight.Count, v =>
|
||||||
|
@ -639,103 +645,16 @@ namespace SourceGit.Views
|
||||||
set => SetValue(IsOldProperty, value);
|
set => SetValue(IsOldProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<ViewModels.TwoSideTextDiff> DiffDataProperty =
|
public ViewModels.TwoSideTextDiff DiffData => DataContext as ViewModels.TwoSideTextDiff;
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, ViewModels.TwoSideTextDiff>(nameof(DiffData));
|
|
||||||
|
|
||||||
public ViewModels.TwoSideTextDiff DiffData
|
|
||||||
{
|
|
||||||
get => GetValue(DiffDataProperty);
|
|
||||||
set => SetValue(DiffDataProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGEmptyProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGEmpty), new SolidColorBrush(Color.FromArgb(60, 0, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGEmpty
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGEmptyProperty);
|
|
||||||
set => SetValue(LineBGEmptyProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGAddProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGAdd), new SolidColorBrush(Color.FromArgb(60, 0, 255, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGAdd
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGAddProperty);
|
|
||||||
set => SetValue(LineBGAddProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> LineBGDeletedProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(LineBGDeleted), new SolidColorBrush(Color.FromArgb(60, 255, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush LineBGDeleted
|
|
||||||
{
|
|
||||||
get => GetValue(LineBGDeletedProperty);
|
|
||||||
set => SetValue(LineBGDeletedProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryLineBGAddProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryLineBGAdd), new SolidColorBrush(Color.FromArgb(90, 0, 255, 0)));
|
|
||||||
|
|
||||||
public IBrush SecondaryLineBGAdd
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryLineBGAddProperty);
|
|
||||||
set => SetValue(SecondaryLineBGAddProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryLineBGDeletedProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryLineBGDeleted), new SolidColorBrush(Color.FromArgb(80, 255, 0, 0)));
|
|
||||||
|
|
||||||
public IBrush SecondaryLineBGDeleted
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryLineBGDeletedProperty);
|
|
||||||
set => SetValue(SecondaryLineBGDeletedProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<IBrush> SecondaryFGProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, IBrush>(nameof(SecondaryFG), Brushes.Gray);
|
|
||||||
|
|
||||||
public IBrush SecondaryFG
|
|
||||||
{
|
|
||||||
get => GetValue(SecondaryFGProperty);
|
|
||||||
set => SetValue(SecondaryFGProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, Vector>(nameof(SyncScrollOffset), Vector.Zero);
|
|
||||||
|
|
||||||
public Vector SyncScrollOffset
|
|
||||||
{
|
|
||||||
get => GetValue(SyncScrollOffsetProperty);
|
|
||||||
set => SetValue(SyncScrollOffsetProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> UseSyntaxHighlightingProperty =
|
|
||||||
AvaloniaProperty.Register<SingleSideTextDiffPresenter, bool>(nameof(UseSyntaxHighlighting), false);
|
|
||||||
|
|
||||||
public bool UseSyntaxHighlighting
|
|
||||||
{
|
|
||||||
get => GetValue(UseSyntaxHighlightingProperty);
|
|
||||||
set => SetValue(UseSyntaxHighlightingProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override Type StyleKeyOverride => typeof(TextEditor);
|
|
||||||
|
|
||||||
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
public SingleSideTextDiffPresenter() : base(new TextArea(), new TextDocument())
|
||||||
{
|
{
|
||||||
_lineStyleTransformer = new LineStyleTransformer(this);
|
_lineStyleTransformer = new LineStyleTransformer(this);
|
||||||
|
|
||||||
IsReadOnly = true;
|
|
||||||
ShowLineNumbers = false;
|
|
||||||
|
|
||||||
TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) });
|
TextArea.LeftMargins.Add(new LineNumberMargin(this) { Margin = new Thickness(8, 0) });
|
||||||
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
TextArea.LeftMargins.Add(new VerticalSeperatorMargin(this));
|
||||||
TextArea.TextView.Margin = new Thickness(4, 0);
|
|
||||||
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
TextArea.TextView.BackgroundRenderers.Add(new LineBackgroundRenderer(this));
|
||||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
||||||
TextArea.TextView.Options.EnableHyperlinks = false;
|
|
||||||
TextArea.TextView.Options.EnableEmailHyperlinks = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnLoaded(RoutedEventArgs e)
|
protected override void OnLoaded(RoutedEventArgs e)
|
||||||
|
@ -745,12 +664,10 @@ namespace SourceGit.Views
|
||||||
_scrollViewer = this.FindDescendantOfType<ScrollViewer>();
|
_scrollViewer = this.FindDescendantOfType<ScrollViewer>();
|
||||||
if (_scrollViewer != null)
|
if (_scrollViewer != null)
|
||||||
{
|
{
|
||||||
_scrollViewer.Offset = SyncScrollOffset;
|
|
||||||
_scrollViewer.ScrollChanged += OnTextViewScrollChanged;
|
_scrollViewer.ScrollChanged += OnTextViewScrollChanged;
|
||||||
|
_scrollViewer.Bind(ScrollViewer.OffsetProperty, new Binding("SyncScrollOffset", BindingMode.OneWay));
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTextMate();
|
|
||||||
|
|
||||||
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
|
TextArea.PointerWheelChanged += OnTextAreaPointerWheelChanged;
|
||||||
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
TextArea.TextView.ContextRequested += OnTextViewContextRequested;
|
||||||
}
|
}
|
||||||
|
@ -765,18 +682,31 @@ namespace SourceGit.Views
|
||||||
_scrollViewer = null;
|
_scrollViewer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_textMate != null)
|
|
||||||
{
|
|
||||||
_textMate.Dispose();
|
|
||||||
_textMate = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
|
TextArea.PointerWheelChanged -= OnTextAreaPointerWheelChanged;
|
||||||
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
TextArea.TextView.ContextRequested -= OnTextViewContextRequested;
|
||||||
|
|
||||||
GC.Collect();
|
GC.Collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDataContextChanged(e);
|
||||||
|
|
||||||
|
if (DataContext is ViewModels.TwoSideTextDiff diff)
|
||||||
|
{
|
||||||
|
var builder = new StringBuilder();
|
||||||
|
var lines = IsOld ? diff.Old : diff.New;
|
||||||
|
foreach (var line in lines)
|
||||||
|
builder.AppendLine(line.Content);
|
||||||
|
|
||||||
|
Text = builder.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Text = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e)
|
private void OnTextAreaPointerWheelChanged(object sender, PointerWheelEventArgs e)
|
||||||
{
|
{
|
||||||
if (!TextArea.IsFocused)
|
if (!TextArea.IsFocused)
|
||||||
|
@ -785,8 +715,8 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
|
private void OnTextViewScrollChanged(object sender, ScrollChangedEventArgs e)
|
||||||
{
|
{
|
||||||
if (TextArea.IsFocused)
|
if (TextArea.IsFocused && DataContext is ViewModels.TwoSideTextDiff diff)
|
||||||
SetCurrentValue(SyncScrollOffsetProperty, _scrollViewer.Offset);
|
diff.SyncScrollOffset = _scrollViewer.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
private void OnTextViewContextRequested(object sender, ContextRequestedEventArgs e)
|
||||||
|
@ -798,9 +728,7 @@ namespace SourceGit.Views
|
||||||
var menu = new ContextMenu();
|
var menu = new ContextMenu();
|
||||||
var parentView = this.FindAncestorOfType<TextDiffView>();
|
var parentView = this.FindAncestorOfType<TextDiffView>();
|
||||||
if (parentView != null)
|
if (parentView != null)
|
||||||
{
|
|
||||||
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, IsOld);
|
parentView.FillContextMenuForWorkingCopyChange(menu, selection.StartPosition.Line, selection.EndPosition.Line, IsOld);
|
||||||
}
|
|
||||||
|
|
||||||
var copy = new MenuItem();
|
var copy = new MenuItem();
|
||||||
copy.Header = App.Text("Copy");
|
copy.Header = App.Text("Copy");
|
||||||
|
@ -817,96 +745,11 @@ namespace SourceGit.Views
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
|
||||||
{
|
|
||||||
base.OnPropertyChanged(change);
|
|
||||||
|
|
||||||
if (change.Property == DiffDataProperty)
|
|
||||||
{
|
|
||||||
if (DiffData != null)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
if (IsOld)
|
|
||||||
{
|
|
||||||
foreach (var line in DiffData.Old)
|
|
||||||
{
|
|
||||||
builder.AppendLine(line.Content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (var line in DiffData.New)
|
|
||||||
{
|
|
||||||
builder.AppendLine(line.Content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Text = builder.ToString();
|
|
||||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Text = string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (change.Property == SyncScrollOffsetProperty)
|
|
||||||
{
|
|
||||||
if (!TextArea.IsFocused && _scrollViewer != null)
|
|
||||||
_scrollViewer.Offset = SyncScrollOffset;
|
|
||||||
}
|
|
||||||
else if (change.Property == UseSyntaxHighlightingProperty)
|
|
||||||
{
|
|
||||||
UpdateTextMate();
|
|
||||||
}
|
|
||||||
else if (change.Property.Name == "ActualThemeVariant" && change.NewValue != null)
|
|
||||||
{
|
|
||||||
Models.TextMateHelper.SetThemeByApp(_textMate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTextMate()
|
|
||||||
{
|
|
||||||
if (UseSyntaxHighlighting)
|
|
||||||
{
|
|
||||||
if (_textMate == null)
|
|
||||||
{
|
|
||||||
TextArea.TextView.LineTransformers.Remove(_lineStyleTransformer);
|
|
||||||
_textMate = Models.TextMateHelper.CreateForEditor(this);
|
|
||||||
TextArea.TextView.LineTransformers.Add(_lineStyleTransformer);
|
|
||||||
|
|
||||||
if (DiffData != null)
|
|
||||||
Models.TextMateHelper.SetGrammarByFileName(_textMate, DiffData.File);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (_textMate != null)
|
|
||||||
{
|
|
||||||
_textMate.Dispose();
|
|
||||||
_textMate = null;
|
|
||||||
GC.Collect();
|
|
||||||
|
|
||||||
TextArea.TextView.Redraw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private TextMate.Installation _textMate;
|
|
||||||
private readonly LineStyleTransformer _lineStyleTransformer = null;
|
|
||||||
private ScrollViewer _scrollViewer = null;
|
private ScrollViewer _scrollViewer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public partial class TextDiffView : UserControl
|
public partial class TextDiffView : UserControl
|
||||||
{
|
{
|
||||||
public static readonly StyledProperty<Models.TextDiff> TextDiffProperty =
|
|
||||||
AvaloniaProperty.Register<TextDiffView, Models.TextDiff>(nameof(TextDiff), null);
|
|
||||||
|
|
||||||
public Models.TextDiff TextDiff
|
|
||||||
{
|
|
||||||
get => GetValue(TextDiffProperty);
|
|
||||||
set => SetValue(TextDiffProperty, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly StyledProperty<bool> UseSideBySideDiffProperty =
|
public static readonly StyledProperty<bool> UseSideBySideDiffProperty =
|
||||||
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseSideBySideDiff), false);
|
AvaloniaProperty.Register<TextDiffView, bool>(nameof(UseSideBySideDiff), false);
|
||||||
|
|
||||||
|
@ -916,13 +759,20 @@ namespace SourceGit.Views
|
||||||
set => SetValue(UseSideBySideDiffProperty, value);
|
set => SetValue(UseSideBySideDiffProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<Vector> SyncScrollOffsetProperty =
|
static TextDiffView()
|
||||||
AvaloniaProperty.Register<TextDiffView, Vector>(nameof(SyncScrollOffset));
|
|
||||||
|
|
||||||
public Vector SyncScrollOffset
|
|
||||||
{
|
{
|
||||||
get => GetValue(SyncScrollOffsetProperty);
|
UseSideBySideDiffProperty.Changed.AddClassHandler<TextDiffView>((v, e) =>
|
||||||
set => SetValue(SyncScrollOffsetProperty, value);
|
{
|
||||||
|
if (v.DataContext is Models.TextDiff diff)
|
||||||
|
{
|
||||||
|
diff.SyncScrollOffset = Vector.Zero;
|
||||||
|
|
||||||
|
if (v.UseSideBySideDiff)
|
||||||
|
v.Content = new ViewModels.TwoSideTextDiff(diff);
|
||||||
|
else
|
||||||
|
v.Content = diff;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextDiffView()
|
public TextDiffView()
|
||||||
|
@ -932,6 +782,10 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
public void FillContextMenuForWorkingCopyChange(ContextMenu menu, int startLine, int endLine, bool isOldSide)
|
public void FillContextMenuForWorkingCopyChange(ContextMenu menu, int startLine, int endLine, bool isOldSide)
|
||||||
{
|
{
|
||||||
|
var diff = DataContext as Models.TextDiff;
|
||||||
|
if (diff == null)
|
||||||
|
return;
|
||||||
|
|
||||||
var parentView = this.FindAncestorOfType<DiffView>();
|
var parentView = this.FindAncestorOfType<DiffView>();
|
||||||
if (parentView == null)
|
if (parentView == null)
|
||||||
return;
|
return;
|
||||||
|
@ -951,7 +805,7 @@ namespace SourceGit.Views
|
||||||
endLine = tmp;
|
endLine = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
var selection = GetUnifiedSelection(startLine, endLine, isOldSide);
|
var selection = GetUnifiedSelection(diff, startLine, endLine, isOldSide);
|
||||||
if (!selection.HasChanges)
|
if (!selection.HasChanges)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1033,17 +887,17 @@ namespace SourceGit.Views
|
||||||
var tmpFile = Path.GetTempFileName();
|
var tmpFile = Path.GetTempFileName();
|
||||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||||
{
|
{
|
||||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile);
|
diff.GenerateNewPatchFromSelection(change, null, selection, false, tmpFile);
|
||||||
}
|
}
|
||||||
else if (!UseSideBySideDiff)
|
else if (!UseSideBySideDiff)
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
|
diff.GeneratePatchFromSelection(change, treeGuid, selection, false, tmpFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, isOldSide, tmpFile);
|
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, false, isOldSide, tmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index").Exec();
|
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index").Exec();
|
||||||
|
@ -1065,17 +919,17 @@ namespace SourceGit.Views
|
||||||
var tmpFile = Path.GetTempFileName();
|
var tmpFile = Path.GetTempFileName();
|
||||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||||
{
|
{
|
||||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else if (!UseSideBySideDiff)
|
else if (!UseSideBySideDiff)
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--reverse").Exec();
|
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--reverse").Exec();
|
||||||
|
@ -1103,15 +957,15 @@ namespace SourceGit.Views
|
||||||
var tmpFile = Path.GetTempFileName();
|
var tmpFile = Path.GetTempFileName();
|
||||||
if (change.Index == Models.ChangeState.Added)
|
if (change.Index == Models.ChangeState.Added)
|
||||||
{
|
{
|
||||||
TextDiff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
diff.GenerateNewPatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else if (!UseSideBySideDiff)
|
else if (!UseSideBySideDiff)
|
||||||
{
|
{
|
||||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index --reverse").Exec();
|
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--cache --index --reverse").Exec();
|
||||||
|
@ -1133,17 +987,17 @@ namespace SourceGit.Views
|
||||||
var tmpFile = Path.GetTempFileName();
|
var tmpFile = Path.GetTempFileName();
|
||||||
if (change.WorkTree == Models.ChangeState.Untracked)
|
if (change.WorkTree == Models.ChangeState.Untracked)
|
||||||
{
|
{
|
||||||
TextDiff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
diff.GenerateNewPatchFromSelection(change, null, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else if (!UseSideBySideDiff)
|
else if (!UseSideBySideDiff)
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
diff.GeneratePatchFromSelection(change, treeGuid, selection, true, tmpFile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
var treeGuid = new Commands.QueryStagedFileBlobGuid(ctx.RepositoryPath, change.Path).Result();
|
||||||
TextDiff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
diff.GeneratePatchFromSelectionSingleSide(change, treeGuid, selection, true, isOldSide, tmpFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--index --reverse").Exec();
|
new Commands.Apply(ctx.RepositoryPath, tmpFile, true, "nowarn", "--index --reverse").Exec();
|
||||||
|
@ -1162,44 +1016,29 @@ namespace SourceGit.Views
|
||||||
menu.Items.Add(new MenuItem() { Header = "-" });
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(change);
|
base.OnDataContextChanged(e);
|
||||||
|
|
||||||
var data = TextDiff;
|
var diff = DataContext as Models.TextDiff;
|
||||||
if (data == null)
|
if (diff == null)
|
||||||
{
|
{
|
||||||
Content = null;
|
Content = null;
|
||||||
SyncScrollOffset = Vector.Zero;
|
GC.Collect();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.Property == TextDiffProperty)
|
if (UseSideBySideDiff)
|
||||||
{
|
Content = new ViewModels.TwoSideTextDiff(diff, Content as ViewModels.TwoSideTextDiff);
|
||||||
if (UseSideBySideDiff)
|
else
|
||||||
Content = new ViewModels.TwoSideTextDiff(TextDiff);
|
Content = diff;
|
||||||
else
|
|
||||||
Content = TextDiff;
|
|
||||||
|
|
||||||
SetCurrentValue(SyncScrollOffsetProperty, TextDiff.SyncScrollOffset);
|
|
||||||
}
|
|
||||||
else if (change.Property == UseSideBySideDiffProperty)
|
|
||||||
{
|
|
||||||
if (UseSideBySideDiff)
|
|
||||||
Content = new ViewModels.TwoSideTextDiff(TextDiff);
|
|
||||||
else
|
|
||||||
Content = TextDiff;
|
|
||||||
|
|
||||||
SetCurrentValue(SyncScrollOffsetProperty, Vector.Zero);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Models.TextDiffSelection GetUnifiedSelection(int startLine, int endLine, bool isOldSide)
|
private Models.TextDiffSelection GetUnifiedSelection(Models.TextDiff diff, int startLine, int endLine, bool isOldSide)
|
||||||
{
|
{
|
||||||
var rs = new Models.TextDiffSelection();
|
var rs = new Models.TextDiffSelection();
|
||||||
var diff = TextDiff;
|
|
||||||
|
|
||||||
endLine = Math.Min(endLine, TextDiff.Lines.Count);
|
endLine = Math.Min(endLine, diff.Lines.Count);
|
||||||
if (Content is ViewModels.TwoSideTextDiff twoSides)
|
if (Content is ViewModels.TwoSideTextDiff twoSides)
|
||||||
{
|
{
|
||||||
var target = isOldSide ? twoSides.Old : twoSides.New;
|
var target = isOldSide ? twoSides.Old : twoSides.New;
|
||||||
|
@ -1233,8 +1072,8 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
var firstContent = target[firstContentLine];
|
var firstContent = target[firstContentLine];
|
||||||
var endContent = target[endContentLine];
|
var endContent = target[endContentLine];
|
||||||
startLine = TextDiff.Lines.IndexOf(firstContent) + 1;
|
startLine = diff.Lines.IndexOf(firstContent) + 1;
|
||||||
endLine = TextDiff.Lines.IndexOf(endContent) + 1;
|
endLine = diff.Lines.IndexOf(endContent) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rs.StartLine = startLine;
|
rs.StartLine = startLine;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
x:DataType="vm:WorkingCopy">
|
x:DataType="vm:WorkingCopy">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="300" MinWidth="300"/>
|
<ColumnDefinition Width="{Binding Source={x:Static vm:Preference.Instance}, Path=Layout.WorkingCopyLeftWidth, Mode=TwoWay}" MinWidth="300"/>
|
||||||
<ColumnDefinition Width="5"/>
|
<ColumnDefinition Width="5"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
@ -198,7 +198,9 @@
|
||||||
Height="28"
|
Height="28"
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Padding="8,0"
|
Padding="8,0"
|
||||||
Command="{Binding Commit}"/>
|
Command="{Binding Commit}"
|
||||||
|
HotKey="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"
|
||||||
|
ToolTip.Tip="{OnPlatform Ctrl+Enter, macOS=⌘+Enter}"/>
|
||||||
|
|
||||||
<Button Grid.Column="5"
|
<Button Grid.Column="5"
|
||||||
Classes="flat"
|
Classes="flat"
|
||||||
|
@ -207,6 +209,8 @@
|
||||||
Margin="8,0,0,0"
|
Margin="8,0,0,0"
|
||||||
Padding="8,0"
|
Padding="8,0"
|
||||||
Command="{Binding CommitWithPush}"
|
Command="{Binding CommitWithPush}"
|
||||||
|
HotKey="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
|
||||||
|
ToolTip.Tip="{OnPlatform Ctrl+Shift+Enter, macOS=⌘+Shift+Enter}"
|
||||||
IsVisible="{Binding IsCommitWithPushVisible}"/>
|
IsVisible="{Binding IsCommitWithPushVisible}"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
Loading…
Reference in a new issue