mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-24 20:57:19 -08:00
Merge branch 'release/v8.13'
This commit is contained in:
commit
12d7fa6670
22 changed files with 216 additions and 138 deletions
|
@ -39,8 +39,8 @@ This software creates a folder `$"{System.Environment.SpecialFolder.ApplicationD
|
||||||
| OS | PATH |
|
| OS | PATH |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` |
|
| Windows | `C:\Users\USER_NAME\AppData\Roaming\SourceGit` |
|
||||||
| Linux | `/home/USER_NAME/.config/SourceGit` |
|
| Linux | `${HOME}/.config/SourceGit` |
|
||||||
| macOS | `/Users/USER_NAME/.config/SourceGit` |
|
| macOS | `${HOME}/Library/Application Support/SourceGit` |
|
||||||
|
|
||||||
For **Windows** users:
|
For **Windows** users:
|
||||||
|
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
||||||
8.12
|
8.13
|
0
build/build.osx.command
Normal file → Executable file
0
build/build.osx.command
Normal file → Executable file
|
@ -24,7 +24,7 @@ chmod 755 -R $RPM_BUILD_ROOT
|
||||||
|
|
||||||
%files
|
%files
|
||||||
/opt
|
/opt
|
||||||
/usr/bin
|
%attr(555,root,root)/usr/bin
|
||||||
/usr/share
|
/usr/share
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 519 KiB After Width: | Height: | Size: 559 KiB |
Binary file not shown.
Before Width: | Height: | Size: 527 KiB After Width: | Height: | Size: 569 KiB |
|
@ -26,12 +26,12 @@
|
||||||
<NativeMenu.Menu>
|
<NativeMenu.Menu>
|
||||||
<NativeMenu>
|
<NativeMenu>
|
||||||
<NativeMenuItem Header="{DynamicResource Text.About.Menu}" Command="{x:Static s:App.OpenAboutCommand}"/>
|
<NativeMenuItem Header="{DynamicResource Text.About.Menu}" Command="{x:Static s:App.OpenAboutCommand}"/>
|
||||||
<NativeMenuItem Header="{DynamicResource Text.Hotkeys.Menu}" Command="{x:Static s:App.OpenHotkeysCommand}"/>
|
<NativeMenuItem Header="{DynamicResource Text.Hotkeys}" Command="{x:Static s:App.OpenHotkeysCommand}"/>
|
||||||
<NativeMenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}"/>
|
<NativeMenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}"/>
|
||||||
<NativeMenuItemSeparator/>
|
<NativeMenuItemSeparator/>
|
||||||
<NativeMenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" Gesture="⌘+,"/>
|
<NativeMenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" Gesture="⌘+,"/>
|
||||||
<NativeMenuItemSeparator/>
|
<NativeMenuItemSeparator/>
|
||||||
<NativeMenuItem Header="{DynamicResource Text.Quit}" Command="{x:Static s:App.QuitCommand}"/>
|
<NativeMenuItem Header="{DynamicResource Text.Quit}" Command="{x:Static s:App.QuitCommand}" Gesture="⌘+Q"/>
|
||||||
</NativeMenu>
|
</NativeMenu>
|
||||||
</NativeMenu.Menu>
|
</NativeMenu.Menu>
|
||||||
</Application>
|
</Application>
|
||||||
|
|
|
@ -266,6 +266,7 @@ namespace SourceGit
|
||||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
||||||
{
|
{
|
||||||
BindingPlugins.DataValidators.RemoveAt(0);
|
BindingPlugins.DataValidators.RemoveAt(0);
|
||||||
|
Native.OS.SetupEnternalTools();
|
||||||
|
|
||||||
var launcher = new Views.Launcher();
|
var launcher = new Views.Launcher();
|
||||||
_notificationReceiver = launcher;
|
_notificationReceiver = launcher;
|
||||||
|
|
|
@ -12,34 +12,23 @@ namespace SourceGit.Models
|
||||||
{
|
{
|
||||||
public class ExternalTool
|
public class ExternalTool
|
||||||
{
|
{
|
||||||
public string Name { get; set; } = string.Empty;
|
public string Name { get; private set; } = string.Empty;
|
||||||
public string Icon { get; set; } = string.Empty;
|
public string Executable { get; private set; } = string.Empty;
|
||||||
public string Executable { get; set; } = string.Empty;
|
public string OpenCmdArgs { get; private set; } = string.Empty;
|
||||||
public string OpenCmdArgs { get; set; } = string.Empty;
|
public Bitmap IconImage { get; private set; } = null;
|
||||||
|
|
||||||
public Bitmap IconImage
|
public ExternalTool(string name, string icon, string executable, string openCmdArgs)
|
||||||
{
|
{
|
||||||
get
|
Name = name;
|
||||||
{
|
Executable = executable;
|
||||||
if (_isFirstTimeGetIcon)
|
OpenCmdArgs = openCmdArgs;
|
||||||
{
|
|
||||||
_isFirstTimeGetIcon = false;
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(Icon))
|
|
||||||
{
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{Icon}.png", UriKind.RelativeOrAbsolute));
|
var asset = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/ExternalToolIcons/{icon}.png", UriKind.RelativeOrAbsolute));
|
||||||
_iconImage = new Bitmap(icon);
|
IconImage = new Bitmap(asset);
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return _iconImage;
|
|
||||||
}
|
}
|
||||||
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Open(string repo)
|
public void Open(string repo)
|
||||||
|
@ -52,9 +41,6 @@ namespace SourceGit.Models
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _isFirstTimeGetIcon = true;
|
|
||||||
private Bitmap _iconImage = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class JetBrainsState
|
public class JetBrainsState
|
||||||
|
@ -107,13 +93,7 @@ namespace SourceGit.Models
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Founded.Add(new ExternalTool
|
Founded.Add(new ExternalTool(name, icon, path, args));
|
||||||
{
|
|
||||||
Name = name,
|
|
||||||
Icon = icon,
|
|
||||||
OpenCmdArgs = args,
|
|
||||||
Executable = path
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void VSCode(Func<string> platformFinder)
|
public void VSCode(Func<string> platformFinder)
|
||||||
|
@ -154,13 +134,11 @@ namespace SourceGit.Models
|
||||||
if (exclude.Contains(tool.ToolId.ToLowerInvariant()))
|
if (exclude.Contains(tool.ToolId.ToLowerInvariant()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Founded.Add(new ExternalTool
|
Founded.Add(new ExternalTool(
|
||||||
{
|
$"{tool.DisplayName} {tool.DisplayVersion}",
|
||||||
Name = $"{tool.DisplayName} {tool.DisplayVersion}",
|
supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : "JetBrains/JB",
|
||||||
Icon = supported_icons.Contains(tool.ProductCode) ? $"JetBrains/{tool.ProductCode}" : $"JetBrains/JB",
|
Path.Combine(tool.InstallLocation, tool.LaunchCommand),
|
||||||
OpenCmdArgs = "\"{0}\"",
|
"\"{0}\""));
|
||||||
Executable = Path.Combine(tool.InstallLocation, tool.LaunchCommand),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,20 +25,14 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public static User FindOrAdd(string data)
|
public static User FindOrAdd(string data)
|
||||||
{
|
{
|
||||||
if (_caches.TryGetValue(data, out var value))
|
return _caches.GetOrAdd(data, key =>
|
||||||
{
|
{
|
||||||
return value;
|
var nameEndIdx = key.IndexOf('<', System.StringComparison.Ordinal);
|
||||||
}
|
var name = nameEndIdx >= 2 ? key.Substring(0, nameEndIdx - 1) : string.Empty;
|
||||||
else
|
var email = key.Substring(nameEndIdx + 1);
|
||||||
{
|
|
||||||
var nameEndIdx = data.IndexOf('<', System.StringComparison.Ordinal);
|
|
||||||
var name = nameEndIdx >= 2 ? data.Substring(0, nameEndIdx - 1) : string.Empty;
|
|
||||||
var email = data.Substring(nameEndIdx + 1);
|
|
||||||
|
|
||||||
User user = new User() { Name = name, Email = email };
|
return new User() { Name = name, Email = email };
|
||||||
_caches.TryAdd(data, user);
|
});
|
||||||
return user;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ConcurrentDictionary<string, User> _caches = new ConcurrentDictionary<string, User>();
|
private static ConcurrentDictionary<string, User> _caches = new ConcurrentDictionary<string, User>();
|
||||||
|
|
|
@ -43,6 +43,11 @@ namespace SourceGit.Native
|
||||||
DefaultFamilyName = "fonts:SourceGit#JetBrains Mono",
|
DefaultFamilyName = "fonts:SourceGit#JetBrains Mono",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.With(new X11PlatformOptions()
|
||||||
|
{
|
||||||
|
EnableIme = true,
|
||||||
|
});
|
||||||
|
|
||||||
// Free-desktop file picker has an extra black background panel.
|
// Free-desktop file picker has an extra black background panel.
|
||||||
builder.UseManagedSystemDialogs();
|
builder.UseManagedSystemDialogs();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,8 +41,6 @@ namespace SourceGit.Native
|
||||||
{
|
{
|
||||||
throw new Exception("Platform unsupported!!!");
|
throw new Exception("Platform unsupported!!!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ExternalTools = _backend.FindExternalTools();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Models.Shell GetShell()
|
public static Models.Shell GetShell()
|
||||||
|
@ -77,6 +75,11 @@ namespace SourceGit.Native
|
||||||
_backend.SetupApp(builder);
|
_backend.SetupApp(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetupEnternalTools()
|
||||||
|
{
|
||||||
|
ExternalTools = _backend.FindExternalTools();
|
||||||
|
}
|
||||||
|
|
||||||
public static string FindGitExecutable()
|
public static string FindGitExecutable()
|
||||||
{
|
{
|
||||||
return _backend.FindGitExecutable();
|
return _backend.FindGitExecutable();
|
||||||
|
|
|
@ -210,8 +210,7 @@
|
||||||
<x:String x:Key="Text.Histories.Search" xml:space="preserve">SEARCH SHA/SUBJECT/AUTHOR. PRESS ENTER TO SEARCH, ESC TO QUIT</x:String>
|
<x:String x:Key="Text.Histories.Search" xml:space="preserve">SEARCH SHA/SUBJECT/AUTHOR. PRESS ENTER TO SEARCH, ESC TO QUIT</x:String>
|
||||||
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">CLEAR</x:String>
|
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">CLEAR</x:String>
|
||||||
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String>
|
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys" xml:space="preserve">HotKeys</x:String>
|
<x:String x:Key="Text.Hotkeys" xml:space="preserve">Keyboard Shortcuts Reference</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Menu" xml:space="preserve">About HotKeys</x:String>
|
|
||||||
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String>
|
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">GLOBAL</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Cancel current popup</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">Cancel current popup</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">Close current page</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">Close current page</x:String>
|
||||||
|
@ -343,6 +342,7 @@
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">Configure this repository</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">CONTINUE</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">Open In File Browser</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">Filter Branches</x:String>
|
||||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
|
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">LOCAL BRANCHES</x:String>
|
||||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
|
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">Navigate To HEAD</x:String>
|
||||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
|
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">Create Branch</x:String>
|
||||||
|
|
|
@ -210,8 +210,7 @@
|
||||||
<x:String x:Key="Text.Histories.Search" xml:space="preserve">查询提交指纹、信息、作者。回车键开始,ESC键取消</x:String>
|
<x:String x:Key="Text.Histories.Search" xml:space="preserve">查询提交指纹、信息、作者。回车键开始,ESC键取消</x:String>
|
||||||
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String>
|
<x:String x:Key="Text.Histories.SearchClear" xml:space="preserve">清空</x:String>
|
||||||
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">已选中 {0} 项提交</x:String>
|
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">已选中 {0} 项提交</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷键</x:String>
|
<x:String x:Key="Text.Hotkeys" xml:space="preserve">快捷键参考</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Menu" xml:space="preserve">显示快捷键</x:String>
|
|
||||||
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全局快捷键</x:String>
|
<x:String x:Key="Text.Hotkeys.Global" xml:space="preserve">全局快捷键</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消弹出面板</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.CancelPopup" xml:space="preserve">取消弹出面板</x:String>
|
||||||
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">关闭当前页面</x:String>
|
<x:String x:Key="Text.Hotkeys.Global.CloseTab" xml:space="preserve">关闭当前页面</x:String>
|
||||||
|
@ -343,6 +342,7 @@
|
||||||
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
|
<x:String x:Key="Text.Repository.Configure" xml:space="preserve">配置本仓库</x:String>
|
||||||
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
<x:String x:Key="Text.Repository.Continue" xml:space="preserve">下一步</x:String>
|
||||||
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
|
<x:String x:Key="Text.Repository.Explore" xml:space="preserve">在文件浏览器中打开</x:String>
|
||||||
|
<x:String x:Key="Text.Repository.FilterBranchTip" xml:space="preserve">过滤显示分支</x:String>
|
||||||
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String>
|
<x:String x:Key="Text.Repository.LocalBranches" xml:space="preserve">本地分支</x:String>
|
||||||
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String>
|
<x:String x:Key="Text.Repository.NavigateToCurrentHead" xml:space="preserve">定位HEAD</x:String>
|
||||||
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
|
<x:String x:Key="Text.Repository.NewBranch" xml:space="preserve">新建分支</x:String>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
|
|
||||||
namespace SourceGit.Models
|
namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
public enum BranchTreeNodeType
|
public enum BranchTreeNodeType
|
||||||
{
|
{
|
||||||
|
@ -23,12 +23,12 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public bool IsUpstreamTrackStatusVisible
|
public bool IsUpstreamTrackStatusVisible
|
||||||
{
|
{
|
||||||
get => IsBranch && !string.IsNullOrEmpty((Backend as Branch).UpstreamTrackStatus);
|
get => IsBranch && !string.IsNullOrEmpty((Backend as Models.Branch).UpstreamTrackStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string UpstreamTrackStatus
|
public string UpstreamTrackStatus
|
||||||
{
|
{
|
||||||
get => Type == BranchTreeNodeType.Branch ? (Backend as Branch).UpstreamTrackStatus : "";
|
get => Type == BranchTreeNodeType.Branch ? (Backend as Models.Branch).UpstreamTrackStatus : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsRemote
|
public bool IsRemote
|
||||||
|
@ -48,7 +48,7 @@ namespace SourceGit.Models
|
||||||
|
|
||||||
public bool IsCurrent
|
public bool IsCurrent
|
||||||
{
|
{
|
||||||
get => IsBranch && (Backend as Branch).IsCurrent;
|
get => IsBranch && (Backend as Models.Branch).IsCurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Builder
|
public class Builder
|
||||||
|
@ -56,8 +56,10 @@ namespace SourceGit.Models
|
||||||
public List<BranchTreeNode> Locals => _locals;
|
public List<BranchTreeNode> Locals => _locals;
|
||||||
public List<BranchTreeNode> Remotes => _remotes;
|
public List<BranchTreeNode> Remotes => _remotes;
|
||||||
|
|
||||||
public void Run(List<Branch> branches, List<Remote> remotes)
|
public void Run(List<Models.Branch> branches, List<Models.Remote> remotes, bool bForceExpanded)
|
||||||
{
|
{
|
||||||
|
var folders = new Dictionary<string, BranchTreeNode>();
|
||||||
|
|
||||||
foreach (var remote in remotes)
|
foreach (var remote in remotes)
|
||||||
{
|
{
|
||||||
var path = $"remote/{remote.Name}";
|
var path = $"remote/{remote.Name}";
|
||||||
|
@ -66,10 +68,10 @@ namespace SourceGit.Models
|
||||||
Name = remote.Name,
|
Name = remote.Name,
|
||||||
Type = BranchTreeNodeType.Remote,
|
Type = BranchTreeNodeType.Remote,
|
||||||
Backend = remote,
|
Backend = remote,
|
||||||
IsExpanded = _expanded.Contains(path),
|
IsExpanded = bForceExpanded || _expanded.Contains(path),
|
||||||
};
|
};
|
||||||
|
|
||||||
_maps.Add(path, node);
|
folders.Add(path, node);
|
||||||
_remotes.Add(node);
|
_remotes.Add(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,16 +80,17 @@ namespace SourceGit.Models
|
||||||
var isFiltered = _filters.Contains(branch.FullName);
|
var isFiltered = _filters.Contains(branch.FullName);
|
||||||
if (branch.IsLocal)
|
if (branch.IsLocal)
|
||||||
{
|
{
|
||||||
MakeBranchNode(branch, _locals, "local", isFiltered);
|
MakeBranchNode(branch, _locals, folders, "local", isFiltered, bForceExpanded);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var remote = _remotes.Find(x => x.Name == branch.Remote);
|
var remote = _remotes.Find(x => x.Name == branch.Remote);
|
||||||
if (remote != null)
|
if (remote != null)
|
||||||
MakeBranchNode(branch, remote.Children, $"remote/{remote.Name}", isFiltered);
|
MakeBranchNode(branch, remote.Children, folders, $"remote/{remote.Name}", isFiltered, bForceExpanded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
folders.Clear();
|
||||||
SortNodes(_locals);
|
SortNodes(_locals);
|
||||||
SortNodes(_remotes);
|
SortNodes(_remotes);
|
||||||
}
|
}
|
||||||
|
@ -113,67 +116,69 @@ namespace SourceGit.Models
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MakeBranchNode(Branch branch, List<BranchTreeNode> roots, string prefix, bool isFiltered)
|
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool isFiltered, bool bForceExpanded)
|
||||||
{
|
{
|
||||||
var subs = branch.Name.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
var sepIdx = branch.Name.IndexOf('/', StringComparison.Ordinal);
|
||||||
|
if (sepIdx == -1)
|
||||||
if (subs.Length == 1)
|
|
||||||
{
|
{
|
||||||
var node = new BranchTreeNode()
|
roots.Add(new BranchTreeNode()
|
||||||
{
|
{
|
||||||
Name = subs[0],
|
Name = branch.Name,
|
||||||
Type = BranchTreeNodeType.Branch,
|
Type = BranchTreeNodeType.Branch,
|
||||||
Backend = branch,
|
Backend = branch,
|
||||||
IsExpanded = false,
|
IsExpanded = false,
|
||||||
IsFiltered = isFiltered,
|
IsFiltered = isFiltered,
|
||||||
};
|
});
|
||||||
roots.Add(node);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BranchTreeNode lastFolder = null;
|
var lastFolder = null as BranchTreeNode;
|
||||||
string path = prefix;
|
var start = 0;
|
||||||
for (int i = 0; i < subs.Length - 1; i++)
|
|
||||||
|
while (sepIdx != -1)
|
||||||
{
|
{
|
||||||
path = string.Concat(path, "/", subs[i]);
|
var folder = string.Concat(prefix, "/", branch.Name.Substring(0, sepIdx));
|
||||||
if (_maps.TryGetValue(path, out var value))
|
var name = branch.Name.Substring(start, sepIdx - start);
|
||||||
|
if (folders.TryGetValue(folder, out var val))
|
||||||
{
|
{
|
||||||
lastFolder = value;
|
lastFolder = val;
|
||||||
}
|
}
|
||||||
else if (lastFolder == null)
|
else if (lastFolder == null)
|
||||||
{
|
{
|
||||||
lastFolder = new BranchTreeNode()
|
lastFolder = new BranchTreeNode()
|
||||||
{
|
{
|
||||||
Name = subs[i],
|
Name = name,
|
||||||
Type = BranchTreeNodeType.Folder,
|
Type = BranchTreeNodeType.Folder,
|
||||||
IsExpanded = branch.IsCurrent || _expanded.Contains(path),
|
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
|
||||||
};
|
};
|
||||||
roots.Add(lastFolder);
|
roots.Add(lastFolder);
|
||||||
_maps.Add(path, lastFolder);
|
folders.Add(folder, lastFolder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var folder = new BranchTreeNode()
|
var cur = new BranchTreeNode()
|
||||||
{
|
{
|
||||||
Name = subs[i],
|
Name = name,
|
||||||
Type = BranchTreeNodeType.Folder,
|
Type = BranchTreeNodeType.Folder,
|
||||||
IsExpanded = branch.IsCurrent || _expanded.Contains(path),
|
IsExpanded = bForceExpanded || branch.IsCurrent || _expanded.Contains(folder),
|
||||||
};
|
};
|
||||||
_maps.Add(path, folder);
|
lastFolder.Children.Add(cur);
|
||||||
lastFolder.Children.Add(folder);
|
folders.Add(folder, cur);
|
||||||
lastFolder = folder;
|
lastFolder = cur;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var last = new BranchTreeNode()
|
start = sepIdx + 1;
|
||||||
|
sepIdx = branch.Name.IndexOf('/', start);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastFolder.Children.Add(new BranchTreeNode()
|
||||||
{
|
{
|
||||||
Name = subs[subs.Length - 1],
|
Name = Path.GetFileName(branch.Name),
|
||||||
Type = BranchTreeNodeType.Branch,
|
Type = BranchTreeNodeType.Branch,
|
||||||
Backend = branch,
|
Backend = branch,
|
||||||
IsExpanded = false,
|
IsExpanded = false,
|
||||||
IsFiltered = isFiltered,
|
IsFiltered = isFiltered,
|
||||||
};
|
});
|
||||||
lastFolder.Children.Add(last);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SortNodes(List<BranchTreeNode> nodes)
|
private void SortNodes(List<BranchTreeNode> nodes)
|
||||||
|
@ -186,7 +191,7 @@ namespace SourceGit.Models
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (int)(l.Type) - (int)(r.Type);
|
return (int)l.Type - (int)r.Type;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -198,7 +203,6 @@ namespace SourceGit.Models
|
||||||
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
|
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
|
||||||
private readonly HashSet<string> _expanded = new HashSet<string>();
|
private readonly HashSet<string> _expanded = new HashSet<string>();
|
||||||
private readonly List<string> _filters = new List<string>();
|
private readonly List<string> _filters = new List<string>();
|
||||||
private readonly Dictionary<string, BranchTreeNode> _maps = new Dictionary<string, BranchTreeNode>();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -89,6 +89,21 @@ namespace SourceGit.ViewModels
|
||||||
set => SetProperty(ref _selectedView, value);
|
set => SetProperty(ref _selectedView, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public string SearchBranchFilter
|
||||||
|
{
|
||||||
|
get => _searchBranchFilter;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (SetProperty(ref _searchBranchFilter, value))
|
||||||
|
{
|
||||||
|
var builder = BuildBranchTree(_branches, _remotes);
|
||||||
|
LocalBranchTrees = builder.Locals;
|
||||||
|
RemoteBranchTrees = builder.Remotes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<Models.Remote> Remotes
|
public List<Models.Remote> Remotes
|
||||||
{
|
{
|
||||||
|
@ -104,14 +119,14 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<Models.BranchTreeNode> LocalBranchTrees
|
public List<BranchTreeNode> LocalBranchTrees
|
||||||
{
|
{
|
||||||
get => _localBranchTrees;
|
get => _localBranchTrees;
|
||||||
private set => SetProperty(ref _localBranchTrees, value);
|
private set => SetProperty(ref _localBranchTrees, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public List<Models.BranchTreeNode> RemoteBranchTrees
|
public List<BranchTreeNode> RemoteBranchTrees
|
||||||
{
|
{
|
||||||
get => _remoteBranchTrees;
|
get => _remoteBranchTrees;
|
||||||
private set => SetProperty(ref _remoteBranchTrees, value);
|
private set => SetProperty(ref _remoteBranchTrees, value);
|
||||||
|
@ -221,6 +236,7 @@ namespace SourceGit.ViewModels
|
||||||
private set => SetProperty(ref _hasUnsolvedConflicts, value);
|
private set => SetProperty(ref _hasUnsolvedConflicts, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
public Models.Commit SearchResultSelectedCommit
|
public Models.Commit SearchResultSelectedCommit
|
||||||
{
|
{
|
||||||
get => _searchResultSelectedCommit;
|
get => _searchResultSelectedCommit;
|
||||||
|
@ -422,6 +438,11 @@ namespace SourceGit.ViewModels
|
||||||
SearchedCommits = visible;
|
SearchedCommits = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ClearSearchBranchFilter()
|
||||||
|
{
|
||||||
|
SearchBranchFilter = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetWatcherEnabled(bool enabled)
|
public void SetWatcherEnabled(bool enabled)
|
||||||
{
|
{
|
||||||
if (_watcher != null)
|
if (_watcher != null)
|
||||||
|
@ -533,12 +554,7 @@ namespace SourceGit.ViewModels
|
||||||
{
|
{
|
||||||
var branches = new Commands.QueryBranches(FullPath).Result();
|
var branches = new Commands.QueryBranches(FullPath).Result();
|
||||||
var remotes = new Commands.QueryRemotes(FullPath).Result();
|
var remotes = new Commands.QueryRemotes(FullPath).Result();
|
||||||
|
var builder = BuildBranchTree(branches, remotes);
|
||||||
var builder = new Models.BranchTreeNode.Builder();
|
|
||||||
builder.SetFilters(Filters);
|
|
||||||
builder.CollectExpandedNodes(_localBranchTrees, true);
|
|
||||||
builder.CollectExpandedNodes(_remoteBranchTrees, false);
|
|
||||||
builder.Run(branches, remotes);
|
|
||||||
|
|
||||||
Dispatcher.UIThread.Invoke(() =>
|
Dispatcher.UIThread.Invoke(() =>
|
||||||
{
|
{
|
||||||
|
@ -1354,6 +1370,32 @@ namespace SourceGit.ViewModels
|
||||||
return menu;
|
return menu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
||||||
|
{
|
||||||
|
var builder = new BranchTreeNode.Builder();
|
||||||
|
builder.SetFilters(Filters);
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(_searchBranchFilter))
|
||||||
|
{
|
||||||
|
builder.CollectExpandedNodes(_localBranchTrees, true);
|
||||||
|
builder.CollectExpandedNodes(_remoteBranchTrees, false);
|
||||||
|
builder.Run(branches, remotes, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var visibles = new List<Models.Branch>();
|
||||||
|
foreach (var b in branches)
|
||||||
|
{
|
||||||
|
if (b.FullName.Contains(_searchBranchFilter, StringComparison.OrdinalIgnoreCase))
|
||||||
|
visibles.Add(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Run(visibles, remotes, visibles.Count <= 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
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.GitFlow _gitflow = new Models.GitFlow();
|
||||||
|
@ -1372,10 +1414,12 @@ namespace SourceGit.ViewModels
|
||||||
private bool _isTagGroupExpanded = false;
|
private bool _isTagGroupExpanded = false;
|
||||||
private bool _isSubmoduleGroupExpanded = false;
|
private bool _isSubmoduleGroupExpanded = false;
|
||||||
|
|
||||||
|
private string _searchBranchFilter = string.Empty;
|
||||||
|
|
||||||
private List<Models.Remote> _remotes = new List<Models.Remote>();
|
private List<Models.Remote> _remotes = new List<Models.Remote>();
|
||||||
private List<Models.Branch> _branches = new List<Models.Branch>();
|
private List<Models.Branch> _branches = new List<Models.Branch>();
|
||||||
private List<Models.BranchTreeNode> _localBranchTrees = new List<Models.BranchTreeNode>();
|
private List<BranchTreeNode> _localBranchTrees = new List<BranchTreeNode>();
|
||||||
private List<Models.BranchTreeNode> _remoteBranchTrees = new List<Models.BranchTreeNode>();
|
private List<BranchTreeNode> _remoteBranchTrees = new List<BranchTreeNode>();
|
||||||
private List<Models.Tag> _tags = new List<Models.Tag>();
|
private List<Models.Tag> _tags = new List<Models.Tag>();
|
||||||
private List<string> _submodules = new List<string>();
|
private List<string> _submodules = new List<string>();
|
||||||
private bool _canCommitWithPush = false;
|
private bool _canCommitWithPush = false;
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
Margin="0,0,0,8"/>
|
Margin="0,0,0,8"/>
|
||||||
|
|
||||||
<Grid RowDefinitions="20,20,20,20,20,20" ColumnDefinitions="150,*">
|
<Grid RowDefinitions="20,20,20,20,20,20" ColumnDefinitions="150,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+Shift+T, macOS=⌘+,}"/>
|
<TextBlock Grid.Row="0" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+Shift+P, macOS=⌘+\,}"/>
|
||||||
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.OpenPreference}"/>
|
<TextBlock Grid.Row="0" Grid.Column="1" Margin="16,0,0,0" Text="{DynamicResource Text.Hotkeys.Global.OpenPreference}"/>
|
||||||
|
|
||||||
<TextBlock Grid.Row="1" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+T, macOS=⌘+T}"/>
|
<TextBlock Grid.Row="1" Grid.Column="0" Classes="monospace bold" Text="{OnPlatform Ctrl+T, macOS=⌘+T}"/>
|
||||||
|
|
|
@ -222,9 +222,12 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
private void BeginMoveWindow(object sender, PointerPressedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.ClickCount != 2)
|
||||||
{
|
{
|
||||||
BeginMoveDrag(e);
|
BeginMoveDrag(e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void ScrollTabs(object sender, PointerWheelEventArgs e)
|
private void ScrollTabs(object sender, PointerWheelEventArgs e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- Left Normal Mode -->
|
<!-- Left Normal Mode -->
|
||||||
<Grid Grid.Column="0" RowDefinitions="28,Auto,28,Auto,28,*,28,Auto,28,Auto" Margin="0,0,0,4" IsVisible="{Binding !IsSearching}">
|
<Grid Grid.Column="0" RowDefinitions="28,Auto,5,28,28,Auto,28,*,28,Auto,28,Auto" Margin="0,0,0,4" IsVisible="{Binding !IsSearching}">
|
||||||
<!-- WorkingCopy -->
|
<!-- WorkingCopy -->
|
||||||
<TextBlock Grid.Row="0" Classes="group_header_label" Text="{DynamicResource Text.Repository.Workspace}"/>
|
<TextBlock Grid.Row="0" Classes="group_header_label" Text="{DynamicResource Text.Repository.Workspace}"/>
|
||||||
<ListBox Grid.Row="1" Classes="page_switcher" Background="Transparent" SelectedIndex="{Binding SelectedViewIndex, Mode=TwoWay}">
|
<ListBox Grid.Row="1" Classes="page_switcher" Background="Transparent" SelectedIndex="{Binding SelectedViewIndex, Mode=TwoWay}">
|
||||||
|
@ -159,9 +159,43 @@
|
||||||
</ListBoxItem>
|
</ListBoxItem>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
|
|
||||||
|
<!-- Filter Branches -->
|
||||||
|
<Rectangle Grid.Row="2" Height=".65" HorizontalAlignment="Stretch" VerticalAlignment="Center" Fill="{DynamicResource Brush.Border2}"/>
|
||||||
|
<TextBox Grid.Row="3"
|
||||||
|
Margin="4,2,1,0"
|
||||||
|
Height="24"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="3"
|
||||||
|
BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
|
Background="{DynamicResource Brush.Contents}"
|
||||||
|
Watermark="{DynamicResource Text.Repository.FilterBranchTip}"
|
||||||
|
Text="{Binding SearchBranchFilter, Mode=TwoWay}"
|
||||||
|
VerticalContentAlignment="Center">
|
||||||
|
<TextBox.InnerLeftContent>
|
||||||
|
<Path Width="14" Height="14"
|
||||||
|
Margin="6,0,0,0"
|
||||||
|
Fill="{DynamicResource Brush.FG2}"
|
||||||
|
Data="{StaticResource Icons.Search}"/>
|
||||||
|
</TextBox.InnerLeftContent>
|
||||||
|
|
||||||
|
<TextBox.InnerRightContent>
|
||||||
|
<Button Classes="icon_button"
|
||||||
|
Width="16"
|
||||||
|
Margin="0,0,6,0"
|
||||||
|
Command="{Binding ClearSearchBranchFilter}"
|
||||||
|
IsVisible="{Binding SearchBranchFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"
|
||||||
|
HorizontalAlignment="Right">
|
||||||
|
<Path Width="14" Height="14"
|
||||||
|
Margin="0,1,0,0"
|
||||||
|
Fill="{DynamicResource Brush.FG1}"
|
||||||
|
Data="{StaticResource Icons.Clear}"/>
|
||||||
|
</Button>
|
||||||
|
</TextBox.InnerRightContent>
|
||||||
|
</TextBox>
|
||||||
|
|
||||||
<!-- Local Branches -->
|
<!-- Local Branches -->
|
||||||
<TextBlock Grid.Row="2" Classes="group_header_label" Text="{DynamicResource Text.Repository.LocalBranches}"/>
|
<TextBlock Grid.Row="4" Classes="group_header_label" Text="{DynamicResource Text.Repository.LocalBranches}"/>
|
||||||
<TreeView Grid.Row="3"
|
<TreeView Grid.Row="5"
|
||||||
x:Name="localBranchTree"
|
x:Name="localBranchTree"
|
||||||
MaxHeight="400"
|
MaxHeight="400"
|
||||||
ItemsSource="{Binding LocalBranchTrees}"
|
ItemsSource="{Binding LocalBranchTrees}"
|
||||||
|
@ -170,12 +204,12 @@
|
||||||
LostFocus="OnLocalBranchTreeLostFocus"
|
LostFocus="OnLocalBranchTreeLostFocus"
|
||||||
SelectionChanged="OnLocalBranchTreeSelectionChanged">
|
SelectionChanged="OnLocalBranchTreeSelectionChanged">
|
||||||
<TreeView.Styles>
|
<TreeView.Styles>
|
||||||
<Style Selector="TreeViewItem" x:DataType="m:BranchTreeNode">
|
<Style Selector="TreeViewItem" x:DataType="vm:BranchTreeNode">
|
||||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
||||||
</Style>
|
</Style>
|
||||||
</TreeView.Styles>
|
</TreeView.Styles>
|
||||||
<TreeView.ItemTemplate>
|
<TreeView.ItemTemplate>
|
||||||
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type m:BranchTreeNode}">
|
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type vm:BranchTreeNode}">
|
||||||
<Grid Height="24" ColumnDefinitions="20,*,Auto,Auto" Background="Transparent" ContextRequested="OnLocalBranchContextMenuRequested" DoubleTapped="OnDoubleTappedLocalBranchNode">
|
<Grid Height="24" ColumnDefinitions="20,*,Auto,Auto" Background="Transparent" ContextRequested="OnLocalBranchContextMenuRequested" DoubleTapped="OnDoubleTappedLocalBranchNode">
|
||||||
<Path Grid.Column="0" Classes="folder_icon" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,1,0,0" IsVisible="{Binding IsFolder}"/>
|
<Path Grid.Column="0" Classes="folder_icon" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,1,0,0" IsVisible="{Binding IsFolder}"/>
|
||||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Check}" IsVisible="{Binding IsCurrent}" VerticalAlignment="Center"/>
|
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Check}" IsVisible="{Binding IsCurrent}" VerticalAlignment="Center"/>
|
||||||
|
@ -208,13 +242,13 @@
|
||||||
</TreeView>
|
</TreeView>
|
||||||
|
|
||||||
<!-- Remotes -->
|
<!-- Remotes -->
|
||||||
<Grid Grid.Row="4" ColumnDefinitions="*,Auto">
|
<Grid Grid.Row="6" ColumnDefinitions="*,Auto">
|
||||||
<TextBlock Grid.Column="0" Classes="group_header_label" Text="{DynamicResource Text.Repository.Remotes}"/>
|
<TextBlock Grid.Column="0" Classes="group_header_label" Text="{DynamicResource Text.Repository.Remotes}"/>
|
||||||
<Button Grid.Column="1" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
|
<Button Grid.Column="1" Classes="icon_button" Width="14" Margin="8,0" Command="{Binding AddRemote}" ToolTip.Tip="{DynamicResource Text.Repository.Remotes.Add}">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
|
<Path Width="12" Height="12" Data="{StaticResource Icons.Remote.Add}"/>
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<TreeView Grid.Row="5"
|
<TreeView Grid.Row="7"
|
||||||
x:Name="remoteBranchTree"
|
x:Name="remoteBranchTree"
|
||||||
ItemsSource="{Binding RemoteBranchTrees}"
|
ItemsSource="{Binding RemoteBranchTrees}"
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||||
|
@ -222,13 +256,13 @@
|
||||||
LostFocus="OnRemoteBranchTreeLostFocus"
|
LostFocus="OnRemoteBranchTreeLostFocus"
|
||||||
SelectionChanged="OnRemoteBranchTreeSelectionChanged">
|
SelectionChanged="OnRemoteBranchTreeSelectionChanged">
|
||||||
<TreeView.Styles>
|
<TreeView.Styles>
|
||||||
<Style Selector="TreeViewItem" x:DataType="m:BranchTreeNode">
|
<Style Selector="TreeViewItem" x:DataType="vm:BranchTreeNode">
|
||||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
||||||
</Style>
|
</Style>
|
||||||
</TreeView.Styles>
|
</TreeView.Styles>
|
||||||
|
|
||||||
<TreeView.ItemTemplate>
|
<TreeView.ItemTemplate>
|
||||||
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type m:BranchTreeNode}">
|
<TreeDataTemplate ItemsSource="{Binding Children}" x:DataType="{x:Type vm:BranchTreeNode}">
|
||||||
<Grid Height="24" ColumnDefinitions="20,*,Auto" Background="Transparent" ContextRequested="OnRemoteBranchContextMenuRequested">
|
<Grid Height="24" ColumnDefinitions="20,*,Auto" Background="Transparent" ContextRequested="OnRemoteBranchContextMenuRequested">
|
||||||
<Path Grid.Column="0" Classes="folder_icon" Width="10" Height="10" HorizontalAlignment="Left" Margin="0,2,0,0" IsVisible="{Binding IsFolder}" VerticalAlignment="Center"/>
|
<Path Grid.Column="0" Classes="folder_icon" Width="10" Height="10" HorizontalAlignment="Left" Margin="0,2,0,0" IsVisible="{Binding IsFolder}" VerticalAlignment="Center"/>
|
||||||
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Remote}" IsVisible="{Binding IsRemote}" VerticalAlignment="Center"/>
|
<Path Grid.Column="0" Width="12" Height="12" HorizontalAlignment="Left" Margin="0,2,0,0" Data="{StaticResource Icons.Remote}" IsVisible="{Binding IsRemote}" VerticalAlignment="Center"/>
|
||||||
|
@ -250,7 +284,7 @@
|
||||||
</TreeView>
|
</TreeView>
|
||||||
|
|
||||||
<!-- Tags -->
|
<!-- Tags -->
|
||||||
<ToggleButton Grid.Row="6" Classes="group_expander" IsChecked="{Binding IsTagGroupExpanded, Mode=TwoWay}">
|
<ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsTagGroupExpanded, Mode=TwoWay}">
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||||
<TextBlock Grid.Column="0" Classes="group_header_label" Margin="4,0,0,0" Text="{DynamicResource Text.Repository.Tags}"/>
|
<TextBlock Grid.Column="0" Classes="group_header_label" Margin="4,0,0,0" Text="{DynamicResource Text.Repository.Tags}"/>
|
||||||
<TextBlock Grid.Column="1" Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
|
<TextBlock Grid.Column="1" Text="{Binding Tags, Converter={x:Static c:ListConverters.ToCount}}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
|
||||||
|
@ -259,7 +293,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<DataGrid Grid.Row="7"
|
<DataGrid Grid.Row="9"
|
||||||
MaxHeight="200"
|
MaxHeight="200"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
ItemsSource="{Binding Tags}"
|
ItemsSource="{Binding Tags}"
|
||||||
|
@ -310,7 +344,7 @@
|
||||||
</DataGrid>
|
</DataGrid>
|
||||||
|
|
||||||
<!-- Submodules -->
|
<!-- Submodules -->
|
||||||
<ToggleButton Grid.Row="8" Classes="group_expander" IsChecked="{Binding IsSubmoduleGroupExpanded, Mode=TwoWay}">
|
<ToggleButton Grid.Row="10" Classes="group_expander" IsChecked="{Binding IsSubmoduleGroupExpanded, Mode=TwoWay}">
|
||||||
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
|
<Grid ColumnDefinitions="Auto,*,Auto,Auto">
|
||||||
<TextBlock Grid.Column="0" Classes="group_header_label" Margin="4,0,0,0" Text="{DynamicResource Text.Repository.Submodules}"/>
|
<TextBlock Grid.Column="0" Classes="group_header_label" Margin="4,0,0,0" Text="{DynamicResource Text.Repository.Submodules}"/>
|
||||||
<TextBlock Grid.Column="1" Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
|
<TextBlock Grid.Column="1" Text="{Binding Submodules, Converter={x:Static c:ListConverters.ToCount}}" Foreground="{DynamicResource Brush.FG2}" FontWeight="Bold"/>
|
||||||
|
@ -328,7 +362,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
<DataGrid Grid.Row="9"
|
<DataGrid Grid.Row="11"
|
||||||
MaxHeight="200"
|
MaxHeight="200"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
ItemsSource="{Binding Submodules}"
|
ItemsSource="{Binding Submodules}"
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
remoteBranchTree.UnselectAll();
|
remoteBranchTree.UnselectAll();
|
||||||
|
|
||||||
var node = tree.SelectedItem as Models.BranchTreeNode;
|
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||||
|
@ -112,7 +112,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
localBranchTree.UnselectAll();
|
localBranchTree.UnselectAll();
|
||||||
|
|
||||||
var node = tree.SelectedItem as Models.BranchTreeNode;
|
var node = tree.SelectedItem as ViewModels.BranchTreeNode;
|
||||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
repo.NavigateToCommit((node.Backend as Models.Branch).Head);
|
||||||
|
@ -171,7 +171,7 @@ namespace SourceGit.Views
|
||||||
if (sender is ToggleButton toggle)
|
if (sender is ToggleButton toggle)
|
||||||
{
|
{
|
||||||
var filter = string.Empty;
|
var filter = string.Empty;
|
||||||
if (toggle.DataContext is Models.BranchTreeNode node)
|
if (toggle.DataContext is ViewModels.BranchTreeNode node)
|
||||||
{
|
{
|
||||||
if (node.IsBranch)
|
if (node.IsBranch)
|
||||||
{
|
{
|
||||||
|
@ -196,7 +196,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
remoteBranchTree.UnselectAll();
|
remoteBranchTree.UnselectAll();
|
||||||
|
|
||||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node)
|
if (sender is Grid grid && grid.DataContext is ViewModels.BranchTreeNode node)
|
||||||
{
|
{
|
||||||
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
if (node.IsBranch && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
|
@ -213,7 +213,7 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
localBranchTree.UnselectAll();
|
localBranchTree.UnselectAll();
|
||||||
|
|
||||||
if (sender is Grid grid && grid.DataContext is Models.BranchTreeNode node && DataContext is ViewModels.Repository repo)
|
if (sender is Grid grid && grid.DataContext is ViewModels.BranchTreeNode node && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
if (node.IsRemote)
|
if (node.IsRemote)
|
||||||
{
|
{
|
||||||
|
@ -291,7 +291,7 @@ namespace SourceGit.Views
|
||||||
|
|
||||||
if (sender is Grid grid && DataContext is ViewModels.Repository repo)
|
if (sender is Grid grid && DataContext is ViewModels.Repository repo)
|
||||||
{
|
{
|
||||||
var node = grid.DataContext as Models.BranchTreeNode;
|
var node = grid.DataContext as ViewModels.BranchTreeNode;
|
||||||
if (node != null && node.IsBranch)
|
if (node != null && node.IsBranch)
|
||||||
{
|
{
|
||||||
var branch = node.Backend as Models.Branch;
|
var branch = node.Backend as Models.Branch;
|
||||||
|
|
|
@ -45,13 +45,13 @@ namespace SourceGit.Views
|
||||||
{
|
{
|
||||||
c._hitBoxes.Clear();
|
c._hitBoxes.Clear();
|
||||||
c._lastHitIdx = -1;
|
c._lastHitIdx = -1;
|
||||||
c.InvalidateVisual();
|
c.InvalidateMeasure();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Render(DrawingContext context)
|
public override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
if (Samples == null)
|
if (Samples == null || Bounds.Width == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var samples = Samples;
|
var samples = Samples;
|
||||||
|
@ -97,7 +97,7 @@ namespace SourceGit.Views
|
||||||
var height = Bounds.Height;
|
var height = Bounds.Height;
|
||||||
|
|
||||||
// Transparent background to block mouse move events.
|
// Transparent background to block mouse move events.
|
||||||
context.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, Bounds.Width, Bounds.Height));
|
context.DrawRectangle(Brushes.Transparent, null, new Rect(0, 0, width, height));
|
||||||
|
|
||||||
// Draw coordinate
|
// Draw coordinate
|
||||||
var maxLabel = new FormattedText($"{maxV}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12.0, LineBrush);
|
var maxLabel = new FormattedText($"{maxV}", CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeface, 12.0, LineBrush);
|
||||||
|
|
|
@ -85,6 +85,12 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDataContextChanged(e);
|
||||||
|
InvalidateMeasure();
|
||||||
|
}
|
||||||
|
|
||||||
private readonly CombinedTextDiffPresenter _editor;
|
private readonly CombinedTextDiffPresenter _editor;
|
||||||
private readonly bool _isOldLine;
|
private readonly bool _isOldLine;
|
||||||
}
|
}
|
||||||
|
@ -458,6 +464,12 @@ namespace SourceGit.Views
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnDataContextChanged(EventArgs e)
|
||||||
|
{
|
||||||
|
base.OnDataContextChanged(e);
|
||||||
|
InvalidateMeasure();
|
||||||
|
}
|
||||||
|
|
||||||
private readonly SingleSideTextDiffPresenter _editor;
|
private readonly SingleSideTextDiffPresenter _editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue