mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-23 20:47:25 -08:00
style<Welcome,PageTabBar>: re-design the style for Welcome page
This commit is contained in:
parent
c2517701cc
commit
b43044a7bf
19 changed files with 319 additions and 833 deletions
|
@ -49,7 +49,7 @@ namespace SourceGit {
|
||||||
var path = new Commands.GetRepositoryRootPath(e.Args[0]).Result();
|
var path = new Commands.GetRepositoryRootPath(e.Args[0]).Result();
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
var gitDir = new Commands.QueryGitDir(path).Result();
|
var gitDir = new Commands.QueryGitDir(path).Result();
|
||||||
repo = Models.Preference.Instance.AddRepository(path, gitDir, "");
|
repo = Models.Preference.Instance.AddRepository(path, gitDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
namespace SourceGit.Models {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仓库列表分组
|
|
||||||
/// </summary>
|
|
||||||
public class Group {
|
|
||||||
public string Id { get; set; } = "";
|
|
||||||
public string Name { get; set; } = "";
|
|
||||||
public string Parent { get; set; } = "";
|
|
||||||
public bool IsExpanded { get; set; } = false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -212,9 +212,7 @@ namespace SourceGit.Models {
|
||||||
public GitInfo Git { get; set; } = new GitInfo();
|
public GitInfo Git { get; set; } = new GitInfo();
|
||||||
public MergeToolInfo MergeTool { get; set; } = new MergeToolInfo();
|
public MergeToolInfo MergeTool { get; set; } = new MergeToolInfo();
|
||||||
public WindowInfo Window { get; set; } = new WindowInfo();
|
public WindowInfo Window { get; set; } = new WindowInfo();
|
||||||
public List<Group> Groups { get; set; } = new List<Group>();
|
|
||||||
public List<Repository> Repositories { get; set; } = new List<Repository>();
|
public List<Repository> Repositories { get; set; } = new List<Repository>();
|
||||||
public List<string> Recents { get; set; } = new List<string>();
|
|
||||||
public RestoreTabs Restore { get; set; } = new RestoreTabs();
|
public RestoreTabs Restore { get; set; } = new RestoreTabs();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
@ -251,71 +249,8 @@ namespace SourceGit.Models {
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region METHOD_ON_GROUPS
|
|
||||||
public Group AddGroup(string name, string parentId) {
|
|
||||||
var group = new Group() {
|
|
||||||
Name = name,
|
|
||||||
Id = Guid.NewGuid().ToString(),
|
|
||||||
Parent = parentId,
|
|
||||||
IsExpanded = false,
|
|
||||||
};
|
|
||||||
|
|
||||||
Groups.Add(group);
|
|
||||||
Groups.Sort((l, r) => l.Name.CompareTo(r.Name));
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Group FindGroup(string id) {
|
|
||||||
foreach (var group in Groups) {
|
|
||||||
if (group.Id == id) return group;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RenameGroup(string id, string newName) {
|
|
||||||
foreach (var group in Groups) {
|
|
||||||
if (group.Id == id) {
|
|
||||||
group.Name = newName;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Groups.Sort((l, r) => l.Name.CompareTo(r.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveGroup(string id) {
|
|
||||||
int removedIdx = -1;
|
|
||||||
|
|
||||||
for (int i = 0; i < Groups.Count; i++) {
|
|
||||||
if (Groups[i].Id == id) {
|
|
||||||
removedIdx = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (removedIdx >= 0) Groups.RemoveAt(removedIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSubGroup(string parent, string subId) {
|
|
||||||
if (string.IsNullOrEmpty(parent)) return false;
|
|
||||||
if (parent == subId) return true;
|
|
||||||
|
|
||||||
var g = FindGroup(subId);
|
|
||||||
if (g == null) return false;
|
|
||||||
|
|
||||||
g = FindGroup(g.Parent);
|
|
||||||
while (g != null) {
|
|
||||||
if (g.Id == parent) return true;
|
|
||||||
g = FindGroup(g.Parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region METHOD_ON_REPOSITORIES
|
#region METHOD_ON_REPOSITORIES
|
||||||
public Repository AddRepository(string path, string gitDir, string groupId) {
|
public Repository AddRepository(string path, string gitDir) {
|
||||||
var repo = FindRepository(path);
|
var repo = FindRepository(path);
|
||||||
if (repo != null) return repo;
|
if (repo != null) return repo;
|
||||||
|
|
||||||
|
@ -323,8 +258,7 @@ namespace SourceGit.Models {
|
||||||
repo = new Repository() {
|
repo = new Repository() {
|
||||||
Path = dir.FullName,
|
Path = dir.FullName,
|
||||||
GitDir = gitDir,
|
GitDir = gitDir,
|
||||||
Name = dir.Name,
|
Name = dir.Name
|
||||||
GroupId = groupId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Repositories.Add(repo);
|
Repositories.Add(repo);
|
||||||
|
@ -340,14 +274,6 @@ namespace SourceGit.Models {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RenameRepository(string path, string newName) {
|
|
||||||
var repo = FindRepository(path);
|
|
||||||
if (repo == null) return;
|
|
||||||
|
|
||||||
repo.Name = newName;
|
|
||||||
Repositories.Sort((l, r) => l.Name.CompareTo(r.Name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveRepository(string path) {
|
public void RemoveRepository(string path) {
|
||||||
var dir = new DirectoryInfo(path);
|
var dir = new DirectoryInfo(path);
|
||||||
var removedIdx = -1;
|
var removedIdx = -1;
|
||||||
|
@ -362,36 +288,5 @@ namespace SourceGit.Models {
|
||||||
if (removedIdx >= 0) Repositories.RemoveAt(removedIdx);
|
if (removedIdx >= 0) Repositories.RemoveAt(removedIdx);
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region RECENTS
|
|
||||||
public void AddRecent(string path) {
|
|
||||||
if (Recents.Count == 0) {
|
|
||||||
Recents.Add(path);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < Recents.Count; i++) {
|
|
||||||
if (Recents[i] == path) {
|
|
||||||
if (i != 0) {
|
|
||||||
Recents.RemoveAt(i);
|
|
||||||
Recents.Insert(0, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Recents.Insert(0, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveRecent(string path) {
|
|
||||||
for (int i = 0; i < Recents.Count; i++) {
|
|
||||||
if (Recents[i] == path) {
|
|
||||||
Recents.RemoveAt(i);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -27,7 +27,6 @@ namespace SourceGit.Models {
|
||||||
public string Name { get; set; } = "";
|
public string Name { get; set; } = "";
|
||||||
public string Path { get; set; } = "";
|
public string Path { get; set; } = "";
|
||||||
public string GitDir { get; set; } = "";
|
public string GitDir { get; set; } = "";
|
||||||
public string GroupId { get; set; } = "";
|
|
||||||
public int Bookmark { get; set; } = 0;
|
public int Bookmark { get; set; } = 0;
|
||||||
public List<SubTree> SubTrees { get; set; } = new List<SubTree>();
|
public List<SubTree> SubTrees { get; set; } = new List<SubTree>();
|
||||||
public List<string> Filters { get; set; } = new List<string>();
|
public List<string> Filters { get; set; } = new List<string>();
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
<Geometry x:Key="Icon.NewTab">M1024 427H597V0h-171v427H0v171h427V1024h171V597H1024z</Geometry>
|
<Geometry x:Key="Icon.NewTab">M1024 427H597V0h-171v427H0v171h427V1024h171V597H1024z</Geometry>
|
||||||
<Geometry x:Key="Icon.Copy">M682.7 42.7H85.3v682.7h85.3V128h512V42.7zM256 213.3l4.5 768H896V213.3H256zm554.7 682.7H341.3V298.7h469.3v597.3z</Geometry>
|
<Geometry x:Key="Icon.Copy">M682.7 42.7H85.3v682.7h85.3V128h512V42.7zM256 213.3l4.5 768H896V213.3H256zm554.7 682.7H341.3V298.7h469.3v597.3z</Geometry>
|
||||||
<Geometry x:Key="Icon.TreeAddNode">M204 291c45-11 77-49 77-96c0-53-43-98-98-98c-53 0-98 45-98 98c0 47 34 87 77 96v91c0 13 9 21 21 21h236c2 38 32 68 70 68h372c41 0 73-32 73-73v-38c0-41-32-73-73-73h-370c-38 0-70 30-70 68H204V291zm258 74h2c0-15 13-30 30-30h372c15 0 30 13 30 30v38c0 15-13 30-30 30h-375c-15 0-30-13-30-30v-38zM183 250c-30 0-55-26-55-55s26-55 55-55s55 26 55 55s-26 55-55 55zM679 495c-134 0-244 109-244 244s109 244 244 244c134 0 244-109 244-244s-109-244-244-244zm159 268h-134v134h-50V764H521v-50h134v-134h50v134h134V764zM244 766H185c-13 0-23-11-23-23s11-23 23-23h59c13 0 23 11 23 23s-11 23-23 23zM368 766h-42c-9 0-17-8-17-17v-13c0-9 8-17 17-17h42c9 0 17 8 17 17v13c0 9-8 17-17 17zM183 766c-12 0-21-9-21-21V320c0-12 9-21 21-21c12 0 21 9 21 21v425c0 12-10 21-21 21z</Geometry>
|
<Geometry x:Key="Icon.TreeAddNode">M204 291c45-11 77-49 77-96c0-53-43-98-98-98c-53 0-98 45-98 98c0 47 34 87 77 96v91c0 13 9 21 21 21h236c2 38 32 68 70 68h372c41 0 73-32 73-73v-38c0-41-32-73-73-73h-370c-38 0-70 30-70 68H204V291zm258 74h2c0-15 13-30 30-30h372c15 0 30 13 30 30v38c0 15-13 30-30 30h-375c-15 0-30-13-30-30v-38zM183 250c-30 0-55-26-55-55s26-55 55-55s55 26 55 55s-26 55-55 55zM679 495c-134 0-244 109-244 244s109 244 244 244c134 0 244-109 244-244s-109-244-244-244zm159 268h-134v134h-50V764H521v-50h134v-134h50v134h134V764zM244 766H185c-13 0-23-11-23-23s11-23 23-23h59c13 0 23 11 23 23s-11 23-23 23zM368 766h-42c-9 0-17-8-17-17v-13c0-9 8-17 17-17h42c9 0 17 8 17 17v13c0 9-8 17-17 17zM183 766c-12 0-21-9-21-21V320c0-12 9-21 21-21c12 0 21 9 21 21v425c0 12-10 21-21 21z</Geometry>
|
||||||
|
|
||||||
<Geometry x:Key="Icon.Minimize">M797 486H224c-14 0-25 11-25 25c0 14 11 25 25 25H797c14 0 25-11 25-25c0-14-11-25-25-25z</Geometry>
|
<Geometry x:Key="Icon.Minimize">M 0 0 L 1 0 V -0.861 M 153 154 h 768 v 60 h -767 z</Geometry>
|
||||||
<Geometry x:Key="Icon.Maximize">M153 154h768v768h-768v-768zm64 64v640h640v-640h-640z</Geometry>
|
<Geometry x:Key="Icon.Maximize">M153 154h768v768h-768v-768zm64 64v640h640v-640h-640z</Geometry>
|
||||||
<Geometry x:Key="Icon.Restore">M256 128l0 192L64 320l0 576 704 0 0-192 192 0L960 128 256 128zM704 832 128 832 128 384l576 0L704 832zM896 640l-128 0L768 320 320 320 320 192l576 0L896 640z</Geometry>
|
<Geometry x:Key="Icon.Restore">M256 128l0 192L64 320l0 576 704 0 0-192 192 0L960 128 256 128zM704 832 128 832 128 384l576 0L704 832zM896 640l-128 0L768 320 320 320 320 192l576 0L896 640z</Geometry>
|
||||||
<Geometry x:Key="Icon.Close">M519 459 222 162a37 37 0 10-52 52l297 297L169 809a37 37 0 1052 52l297-297 297 297a37 37 0 1052-52l-297-297 297-297a37 37 0 10-52-52L519 459z</Geometry>
|
<Geometry x:Key="Icon.Close">M519 459 222 162a37 37 0 10-52 52l297 297L169 809a37 37 0 1052 52l297-297 297 297a37 37 0 1052-52l-297-297 297-297a37 37 0 10-52-52L519 459z</Geometry>
|
||||||
|
|
|
@ -297,18 +297,13 @@
|
||||||
<sys:String x:Key="Text.Merge.Into">Into :</sys:String>
|
<sys:String x:Key="Text.Merge.Into">Into :</sys:String>
|
||||||
<sys:String x:Key="Text.Merge.Mode">Merge Option :</sys:String>
|
<sys:String x:Key="Text.Merge.Mode">Merge Option :</sys:String>
|
||||||
|
|
||||||
<sys:String x:Key="Text.Welcome.Title">Free & open source GUI for git users</sys:String>
|
<sys:String x:Key="Text.Welcome.Title">Free & open source GUI tool for git users</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.OpenOrInit">Open Repository</sys:String>
|
<sys:String x:Key="Text.Welcome.OpenOrInit">Open Repository</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.OpenTerminal">Open Terminal</sys:String>
|
<sys:String x:Key="Text.Welcome.OpenTerminal">Open Terminal</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.Clone">Clone Repository</sys:String>
|
<sys:String x:Key="Text.Welcome.Clone">Clone Repository</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.DragDrop">DROP FOLDER HERE</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Start">START</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Recent">RECENT OPENED</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Repositories">REPOSITORIES</sys:String>
|
<sys:String x:Key="Text.Welcome.Repositories">REPOSITORIES</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.NewFolder">Add Folder</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.NewSubFolder">Add Sub-Folder</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Rename">Rename</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Delete">Delete</sys:String>
|
<sys:String x:Key="Text.Welcome.Delete">Delete</sys:String>
|
||||||
|
<sys:String x:Key="Text.Welcome.Search">Search Repositories ...</sys:String>
|
||||||
|
|
||||||
<sys:String x:Key="Text.Pull">Pull</sys:String>
|
<sys:String x:Key="Text.Pull">Pull</sys:String>
|
||||||
<sys:String x:Key="Text.Pull.Title">Pull (Fetch & Merge)</sys:String>
|
<sys:String x:Key="Text.Pull.Title">Pull (Fetch & Merge)</sys:String>
|
||||||
|
|
|
@ -300,14 +300,9 @@
|
||||||
<sys:String x:Key="Text.Welcome.OpenOrInit">打开本地仓库</sys:String>
|
<sys:String x:Key="Text.Welcome.OpenOrInit">打开本地仓库</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.OpenTerminal">打开GIT终端</sys:String>
|
<sys:String x:Key="Text.Welcome.OpenTerminal">打开GIT终端</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.Clone">克隆远程仓库</sys:String>
|
<sys:String x:Key="Text.Welcome.Clone">克隆远程仓库</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.DragDrop">支持拖放操作</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Start">开始使用</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Recent">最近使用</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Repositories">收藏/书签</sys:String>
|
<sys:String x:Key="Text.Welcome.Repositories">收藏/书签</sys:String>
|
||||||
<sys:String x:Key="Text.Welcome.NewFolder">新建分组</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.NewSubFolder">新建子分组</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Rename">重命名</sys:String>
|
|
||||||
<sys:String x:Key="Text.Welcome.Delete">删除</sys:String>
|
<sys:String x:Key="Text.Welcome.Delete">删除</sys:String>
|
||||||
|
<sys:String x:Key="Text.Welcome.Search">快速查找仓库</sys:String>
|
||||||
|
|
||||||
<sys:String x:Key="Text.Pull">拉回</sys:String>
|
<sys:String x:Key="Text.Pull">拉回</sys:String>
|
||||||
<sys:String x:Key="Text.Pull.Title">拉回(拉取并合并)</sys:String>
|
<sys:String x:Key="Text.Pull.Title">拉回(拉取并合并)</sys:String>
|
||||||
|
|
|
@ -36,9 +36,9 @@
|
||||||
|
|
||||||
<!-- Window Commands -->
|
<!-- Window Commands -->
|
||||||
<StackPanel Grid.Column="3" Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
|
<StackPanel Grid.Column="3" Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
|
||||||
<controls:IconButton Click="Minimize" Width="28" Padding="9" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
<controls:IconButton Click="Minimize" Width="48" Padding="12" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
||||||
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="28" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="48" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
||||||
<controls:IconButton Click="Quit" Width="28" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
<controls:IconButton Click="Quit" Width="48" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace SourceGit.Views.Controls {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 标签页图标
|
|
||||||
/// </summary>
|
|
||||||
public class Bookmark : Border {
|
|
||||||
private Path icon = null;
|
|
||||||
|
|
||||||
public static readonly Brush[] COLORS = new Brush[] {
|
|
||||||
Brushes.Transparent,
|
|
||||||
Brushes.Red,
|
|
||||||
Brushes.Orange,
|
|
||||||
Brushes.Yellow,
|
|
||||||
Brushes.ForestGreen,
|
|
||||||
Brushes.Purple,
|
|
||||||
Brushes.DeepSkyBlue,
|
|
||||||
Brushes.Magenta,
|
|
||||||
};
|
|
||||||
|
|
||||||
public static readonly DependencyProperty ColorProperty =
|
|
||||||
DependencyProperty.Register("Color", typeof(int), typeof(Bookmark), new PropertyMetadata(0, UpdateBookmark));
|
|
||||||
|
|
||||||
public int Color {
|
|
||||||
get { return (int)GetValue(ColorProperty); }
|
|
||||||
set { SetValue(ColorProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static readonly DependencyProperty IsNewPageProperty =
|
|
||||||
DependencyProperty.Register("IsNewPage", typeof(bool), typeof(Bookmark), new PropertyMetadata(false, UpdateBookmark));
|
|
||||||
|
|
||||||
public bool IsNewPage {
|
|
||||||
get { return (bool)GetValue(IsNewPageProperty); }
|
|
||||||
set { SetValue(IsNewPageProperty, value); }
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bookmark() {
|
|
||||||
icon = new Path();
|
|
||||||
Child = icon;
|
|
||||||
UpdateBookmark(this, new DependencyPropertyChangedEventArgs());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void UpdateBookmark(DependencyObject d, DependencyPropertyChangedEventArgs e) {
|
|
||||||
var mark = d as Bookmark;
|
|
||||||
if (mark == null) return;
|
|
||||||
|
|
||||||
if (!mark.IsNewPage) {
|
|
||||||
mark.icon.Data = mark.FindResource("Icon.Git") as Geometry;
|
|
||||||
if (mark.Color == 0) {
|
|
||||||
mark.icon.SetResourceReference(Path.FillProperty, "Brush.FG1");
|
|
||||||
} else {
|
|
||||||
mark.icon.Fill = COLORS[mark.Color % COLORS.Length];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mark.icon.SetResourceReference(Path.FillProperty, "Brush.FG1");
|
|
||||||
mark.icon.Data = mark.FindResource("Icon.WelcomePage") as Geometry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
29
src/Views/Converters/IntToBookmarkBrush.cs
Normal file
29
src/Views/Converters/IntToBookmarkBrush.cs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Windows.Data;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace SourceGit.Views.Converters {
|
||||||
|
|
||||||
|
public class IntToBookmarkBrush : IValueConverter {
|
||||||
|
public static readonly Brush[] COLORS = new Brush[] {
|
||||||
|
Brushes.Transparent,
|
||||||
|
Brushes.Red,
|
||||||
|
Brushes.Orange,
|
||||||
|
Brushes.Yellow,
|
||||||
|
Brushes.ForestGreen,
|
||||||
|
Brushes.Purple,
|
||||||
|
Brushes.DeepSkyBlue,
|
||||||
|
Brushes.Magenta,
|
||||||
|
};
|
||||||
|
|
||||||
|
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||||
|
var index = (int)value;
|
||||||
|
return index == 0 ? (App.Current.FindResource("Brush.FG1") as Brush) : COLORS[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,9 +36,9 @@
|
||||||
|
|
||||||
<!-- Window Commands -->
|
<!-- Window Commands -->
|
||||||
<StackPanel Grid.Column="3" Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
|
<StackPanel Grid.Column="3" Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
|
||||||
<controls:IconButton Click="Minimize" Width="28" Padding="9" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
<controls:IconButton Click="Minimize" Width="48" Padding="12" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
||||||
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="28" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="48" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
||||||
<controls:IconButton Click="Quit" Width="28" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
<controls:IconButton Click="Quit" Width="48" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="32"/>
|
<ColumnDefinition Width="32"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="300"/>
|
<ColumnDefinition Width="360"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- Bottom border -->
|
<!-- Bottom border -->
|
||||||
|
@ -53,9 +53,9 @@
|
||||||
|
|
||||||
<!-- Right controls -->
|
<!-- Right controls -->
|
||||||
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Height="27" WindowChrome.IsHitTestVisibleInChrome="True">
|
<StackPanel Grid.Column="2" Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Height="27" WindowChrome.IsHitTestVisibleInChrome="True">
|
||||||
<controls:IconButton Click="Minimize" Width="28" Padding="9" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
<controls:IconButton Click="Minimize" Width="48" Padding="12" Icon="{StaticResource Icon.Minimize}" HoverBackground="#40000000" Opacity="1"/>
|
||||||
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="28" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
<ToggleButton Style="{StaticResource Style.ToggleButton.MaxOrRestore}" Width="48" IsChecked="{Binding ElementName=me, Path=IsMaximized}"/>
|
||||||
<controls:IconButton Click="Quit" Width="28" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
<controls:IconButton Click="Quit" Width="48" Padding="9" Icon="{StaticResource Icon.Close}" HoverBackground="Red" Opacity="1"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ namespace SourceGit.Views {
|
||||||
|
|
||||||
tabs.OnTabEdited += (t) => {
|
tabs.OnTabEdited += (t) => {
|
||||||
foreach (var tab in tabs.Tabs) {
|
foreach (var tab in tabs.Tabs) {
|
||||||
if (!tab.IsWelcomePage) continue;
|
if (tab.IsRepository) continue;
|
||||||
var page = container.Get(tab.Id) as Widgets.Welcome;
|
var page = container.Get(tab.Id) as Widgets.Welcome;
|
||||||
if (page != null) page.UpdateNodes(t.Id, t.Bookmark);
|
if (page != null) page.UpdateVisibles();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -37,7 +37,7 @@ namespace SourceGit.Views {
|
||||||
restore.Actived = null;
|
restore.Actived = null;
|
||||||
|
|
||||||
foreach (var tab in tabs.Tabs) {
|
foreach (var tab in tabs.Tabs) {
|
||||||
if (tab.IsWelcomePage) continue;
|
if (!tab.IsRepository) continue;
|
||||||
|
|
||||||
// 仅支持恢复加入管理的仓库页,Submodules等未加入管理的不支持
|
// 仅支持恢复加入管理的仓库页,Submodules等未加入管理的不支持
|
||||||
var repo = Models.Preference.Instance.FindRepository(tab.Id);
|
var repo = Models.Preference.Instance.FindRepository(tab.Id);
|
||||||
|
@ -138,7 +138,7 @@ namespace SourceGit.Views {
|
||||||
#region TAB_OPERATION
|
#region TAB_OPERATION
|
||||||
private void OnTabAdding(object sender, Widgets.PageTabBar.TabEventArgs e) {
|
private void OnTabAdding(object sender, Widgets.PageTabBar.TabEventArgs e) {
|
||||||
var page = new Widgets.Welcome();
|
var page = new Widgets.Welcome();
|
||||||
page.OnNodeEdited += node => tabs.Update(node.Id, node.Bookmark, node.Name);
|
page.OnBookmarkChanged += repo => tabs.Update(repo.Path, repo.Bookmark, repo.Name);
|
||||||
container.Add(e.TabId, page);
|
container.Add(e.TabId, page);
|
||||||
Controls.PopupWidget.RegisterContainer(e.TabId, page);
|
Controls.PopupWidget.RegisterContainer(e.TabId, page);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ namespace SourceGit.Views.Popups {
|
||||||
}
|
}
|
||||||
|
|
||||||
var gitDir = new Commands.QueryGitDir(path).Result();
|
var gitDir = new Commands.QueryGitDir(path).Result();
|
||||||
var repo = Models.Preference.Instance.AddRepository(path, gitDir, "");
|
var repo = Models.Preference.Instance.AddRepository(path, gitDir);
|
||||||
if (repo != null) Dispatcher.Invoke(() => Models.Watcher.Open(repo));
|
if (repo != null) Dispatcher.Invoke(() => Models.Watcher.Open(repo));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace SourceGit.Views.Popups {
|
||||||
if (!succ) return false;
|
if (!succ) return false;
|
||||||
|
|
||||||
var gitDir = Path.GetFullPath(Path.Combine(WorkDir, ".git"));
|
var gitDir = Path.GetFullPath(Path.Combine(WorkDir, ".git"));
|
||||||
var repo = Models.Preference.Instance.AddRepository(WorkDir, gitDir, "");
|
var repo = Models.Preference.Instance.AddRepository(WorkDir, gitDir);
|
||||||
Dispatcher.Invoke(() => Models.Watcher.Open(repo));
|
Dispatcher.Invoke(() => Models.Watcher.Open(repo));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
||||||
|
xmlns:converters="clr-namespace:SourceGit.Views.Converters"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="28" d:DesignWidth="800">
|
d:DesignHeight="28" d:DesignWidth="800">
|
||||||
<Grid Margin="0,4,0,0">
|
<Grid Margin="0,4,0,0">
|
||||||
|
@ -48,6 +49,11 @@
|
||||||
ItemsSource="{Binding ElementName=me, Path=Tabs}"
|
ItemsSource="{Binding ElementName=me, Path=Tabs}"
|
||||||
WindowChrome.IsHitTestVisibleInChrome="True"
|
WindowChrome.IsHitTestVisibleInChrome="True"
|
||||||
SelectionChanged="SelectionChanged">
|
SelectionChanged="SelectionChanged">
|
||||||
|
|
||||||
|
<ListBox.Resources>
|
||||||
|
<converters:IntToBookmarkBrush x:Key="IntToBookmarkBrush"/>
|
||||||
|
<converters:BoolToCollapsed x:Key="BoolToCollapsed"/>
|
||||||
|
</ListBox.Resources>
|
||||||
|
|
||||||
<ListBox.ItemsPanel>
|
<ListBox.ItemsPanel>
|
||||||
<ItemsPanelTemplate>
|
<ItemsPanelTemplate>
|
||||||
|
@ -64,32 +70,37 @@
|
||||||
<Setter.Value>
|
<Setter.Value>
|
||||||
<ControlTemplate TargetType="{x:Type ListBoxItem}">
|
<ControlTemplate TargetType="{x:Type ListBoxItem}">
|
||||||
<Border x:Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="1,1,1,0">
|
<Border x:Name="Border" Background="Transparent" BorderBrush="Transparent" BorderThickness="1,1,1,0">
|
||||||
<StackPanel x:Name="Contents" Orientation="Horizontal" VerticalAlignment="Center" Opacity=".5" ToolTip="{Binding Tooltip}">
|
<Grid x:Name="Contents" Width="160" VerticalAlignment="Center" Opacity=".5" ToolTip="{Binding Tooltip}">
|
||||||
<controls:Bookmark
|
<Path
|
||||||
Width="14" Height="14"
|
Width="8" Margin="8,0,0,0"
|
||||||
Margin="8,0,0,0"
|
HorizontalAlignment="Left"
|
||||||
IsNewPage="{Binding IsWelcomePage}"
|
Fill="{Binding Bookmark, Converter={StaticResource IntToBookmarkBrush}}"
|
||||||
Color="{Binding Bookmark}"/>
|
Visibility="{Binding IsRepository, Converter={StaticResource BoolToCollapsed}}">
|
||||||
|
<Path.Data>
|
||||||
|
<EllipseGeometry Center="0,0" RadiusX="14" RadiusY="14"/>
|
||||||
|
</Path.Data>
|
||||||
|
</Path>
|
||||||
|
|
||||||
|
<TextBlock Margin="32,0" HorizontalAlignment="Stretch" TextAlignment="Center" Text="{Binding Title}"/>
|
||||||
|
|
||||||
<TextBlock
|
|
||||||
Margin="4,0"
|
|
||||||
Width="80" MaxWidth="80" TextAlignment="Center"
|
|
||||||
Text="{Binding Title}"/>
|
|
||||||
|
|
||||||
<controls:IconButton
|
<controls:IconButton
|
||||||
Click="CloseTab"
|
Click="CloseTab"
|
||||||
|
x:Name="closer"
|
||||||
Width="16" Height="16"
|
Width="16" Height="16"
|
||||||
Margin="0,0,0,0" Padding="4"
|
Margin="0,1,8,0" Padding="4"
|
||||||
ToolTip="{DynamicResource Text.Close}"
|
ToolTip="{DynamicResource Text.Close}"
|
||||||
Icon="{StaticResource Icon.Close}"
|
Icon="{StaticResource Icon.Close}"
|
||||||
HoverBackground="{DynamicResource Brush.NewPageHover}"/>
|
HoverBackground="{DynamicResource Brush.NewPageHover}"
|
||||||
|
Visibility="Hidden"
|
||||||
|
HorizontalAlignment="Right"/>
|
||||||
|
|
||||||
<Rectangle
|
<Rectangle
|
||||||
x:Name="seperator"
|
x:Name="seperator"
|
||||||
Margin="4,2,0,0"
|
Margin="4,2,0,0"
|
||||||
Width="1"
|
Width="1"
|
||||||
Fill="Transparent"/>
|
Fill="Transparent"
|
||||||
</StackPanel>
|
HorizontalAlignment="Right"/>
|
||||||
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
<ControlTemplate.Triggers>
|
<ControlTemplate.Triggers>
|
||||||
|
@ -97,6 +108,7 @@
|
||||||
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
|
<Setter TargetName="Border" Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
|
||||||
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Brush.Window}"/>
|
<Setter TargetName="Border" Property="Background" Value="{DynamicResource Brush.Window}"/>
|
||||||
<Setter TargetName="Contents" Property="Opacity" Value="1"/>
|
<Setter TargetName="Contents" Property="Opacity" Value="1"/>
|
||||||
|
<Setter TargetName="closer" Property="Visibility" Value="Visible"/>
|
||||||
</Trigger>
|
</Trigger>
|
||||||
<DataTrigger Binding="{Binding IsSeperatorVisible}" Value="True">
|
<DataTrigger Binding="{Binding IsSeperatorVisible}" Value="True">
|
||||||
<Setter TargetName="seperator" Property="Fill" Value="{DynamicResource Brush.FG2}"/>
|
<Setter TargetName="seperator" Property="Fill" Value="{DynamicResource Brush.FG2}"/>
|
||||||
|
@ -107,6 +119,7 @@
|
||||||
<Condition Property="IsMouseOver" Value="True"/>
|
<Condition Property="IsMouseOver" Value="True"/>
|
||||||
</MultiTrigger.Conditions>
|
</MultiTrigger.Conditions>
|
||||||
<Setter TargetName="Contents" Property="Opacity" Value=".85"/>
|
<Setter TargetName="Contents" Property="Opacity" Value=".85"/>
|
||||||
|
<Setter TargetName="closer" Property="Visibility" Value="Visible"/>
|
||||||
</MultiTrigger>
|
</MultiTrigger>
|
||||||
</ControlTemplate.Triggers>
|
</ControlTemplate.Triggers>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
|
@ -118,14 +131,16 @@
|
||||||
</Style>
|
</Style>
|
||||||
</ListBox.ItemContainerStyle>
|
</ListBox.ItemContainerStyle>
|
||||||
</ListBox>
|
</ListBox>
|
||||||
|
|
||||||
<controls:IconButton
|
<Button
|
||||||
Width="16" Height="16" Margin="4,0,0,0" Padding="2"
|
Width="16" Height="16" Margin="8,0,0,0"
|
||||||
Icon="{StaticResource Icon.NewTab}"
|
Background="Transparent"
|
||||||
HoverBackground="{DynamicResource Brush.NewPageHover}"
|
BorderThickness="0"
|
||||||
ToolTip="{DynamicResource Text.PageTabBar.New}"
|
ToolTip="{DynamicResource Text.PageTabBar.New}"
|
||||||
Click="NewTab"
|
Click="NewTab"
|
||||||
WindowChrome.IsHitTestVisibleInChrome="True"/>
|
WindowChrome.IsHitTestVisibleInChrome="True">
|
||||||
|
<Path Width="12" Data="{StaticResource Icon.NewTab}" Fill="{DynamicResource Brush.FG1}"/>
|
||||||
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace SourceGit.Views.Widgets {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Tab : Controls.BindableBase {
|
public class Tab : Controls.BindableBase {
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public bool IsWelcomePage { get; set; }
|
public bool IsRepository { get; set; }
|
||||||
|
|
||||||
private string title;
|
private string title;
|
||||||
public string Title {
|
public string Title {
|
||||||
|
@ -108,7 +108,7 @@ namespace SourceGit.Views.Widgets {
|
||||||
public void Add(string title, string repo, int bookmark) {
|
public void Add(string title, string repo, int bookmark) {
|
||||||
var tab = new Tab() {
|
var tab = new Tab() {
|
||||||
Id = repo,
|
Id = repo,
|
||||||
IsWelcomePage = false,
|
IsRepository = true,
|
||||||
Title = title,
|
Title = title,
|
||||||
Tooltip = repo,
|
Tooltip = repo,
|
||||||
Bookmark = bookmark,
|
Bookmark = bookmark,
|
||||||
|
@ -137,7 +137,7 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
var replaced = new Tab() {
|
var replaced = new Tab() {
|
||||||
Id = repo,
|
Id = repo,
|
||||||
IsWelcomePage = false,
|
IsRepository = true,
|
||||||
Title = title,
|
Title = title,
|
||||||
Tooltip = repo,
|
Tooltip = repo,
|
||||||
Bookmark = bookmark,
|
Bookmark = bookmark,
|
||||||
|
@ -207,7 +207,7 @@ namespace SourceGit.Views.Widgets {
|
||||||
var id = Guid.NewGuid().ToString();
|
var id = Guid.NewGuid().ToString();
|
||||||
var tab = new Tab() {
|
var tab = new Tab() {
|
||||||
Id = id,
|
Id = id,
|
||||||
IsWelcomePage = true,
|
IsRepository = false,
|
||||||
Title = App.Text("PageTabBar.Welcome.Title"),
|
Title = App.Text("PageTabBar.Welcome.Title"),
|
||||||
Tooltip = App.Text("PageTabBar.Welcome.Tip"),
|
Tooltip = App.Text("PageTabBar.Welcome.Tip"),
|
||||||
Bookmark = 0,
|
Bookmark = 0,
|
||||||
|
@ -322,14 +322,14 @@ namespace SourceGit.Views.Widgets {
|
||||||
menu.Items.Add(closeOther);
|
menu.Items.Add(closeOther);
|
||||||
menu.Items.Add(closeRight);
|
menu.Items.Add(closeRight);
|
||||||
|
|
||||||
if (!tab.IsWelcomePage) {
|
if (tab.IsRepository) {
|
||||||
var iconBookmark = FindResource("Icon.Git") as Geometry;
|
var iconBookmark = FindResource("Icon.Git") as Geometry;
|
||||||
var bookmark = new MenuItem();
|
var bookmark = new MenuItem();
|
||||||
bookmark.Header = App.Text("PageTabBar.Tab.Bookmark");
|
bookmark.Header = App.Text("PageTabBar.Tab.Bookmark");
|
||||||
for (int i = 0; i < Controls.Bookmark.COLORS.Length; i++) {
|
for (int i = 0; i < Converters.IntToBookmarkBrush.COLORS.Length; i++) {
|
||||||
var icon = new System.Windows.Shapes.Path();
|
var icon = new System.Windows.Shapes.Path();
|
||||||
icon.Data = iconBookmark;
|
icon.Data = iconBookmark;
|
||||||
icon.Fill = i == 0 ? (FindResource("Brush.FG1") as Brush) : Controls.Bookmark.COLORS[i];
|
icon.Fill = i == 0 ? (FindResource("Brush.FG1") as Brush) : Converters.IntToBookmarkBrush.COLORS[i];
|
||||||
icon.Width = 12;
|
icon.Width = 12;
|
||||||
|
|
||||||
var mark = new MenuItem();
|
var mark = new MenuItem();
|
||||||
|
|
|
@ -6,11 +6,13 @@
|
||||||
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
|
||||||
xmlns:widgets="clr-namespace:SourceGit.Views.Widgets"
|
xmlns:widgets="clr-namespace:SourceGit.Views.Widgets"
|
||||||
xmlns:models="clr-namespace:SourceGit.Models"
|
xmlns:models="clr-namespace:SourceGit.Models"
|
||||||
|
xmlns:converters="clr-namespace:SourceGit.Views.Converters"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
d:DesignHeight="800" d:DesignWidth="800">
|
d:DesignHeight="800" d:DesignWidth="800">
|
||||||
<Grid Background="Transparent" AllowDrop="True" DragEnter="OnPageDragEnter" DragLeave="OnPageDragLeave" Drop="OnPageDrop">
|
<Grid Background="Transparent" AllowDrop="True" DragEnter="OnPageDragEnter" DragLeave="OnPageDragLeave" Drop="OnPageDrop">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="80"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
|
@ -18,14 +20,14 @@
|
||||||
|
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="800"/>
|
<ColumnDefinition Width="600"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- App Name -->
|
<!-- App Name -->
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="1"
|
Grid.Row="0" Grid.Column="1"
|
||||||
Grid.Column="1"
|
Margin="0,64,0,0"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Text="SourceGit"
|
Text="SourceGit"
|
||||||
FontSize="28pt"
|
FontSize="28pt"
|
||||||
|
@ -34,241 +36,163 @@
|
||||||
RenderOptions.ClearTypeHint="Enabled"/>
|
RenderOptions.ClearTypeHint="Enabled"/>
|
||||||
|
|
||||||
<!-- App Desc -->
|
<!-- App Desc -->
|
||||||
<TextBlock
|
<TextBlock
|
||||||
Grid.Row="2"
|
Grid.Row="1" Grid.Column="1"
|
||||||
Grid.Column="1"
|
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
Text="{DynamicResource Text.Welcome.Title}"
|
Text="{DynamicResource Text.Welcome.Title}"
|
||||||
Foreground="{DynamicResource Brush.FG2}"
|
Foreground="{DynamicResource Brush.FG2}"
|
||||||
FontSize="18pt"
|
FontSize="18pt"
|
||||||
Margin="0,8"/>
|
Margin="0,8"/>
|
||||||
|
|
||||||
<Grid x:Name="body" Grid.Row="3" Grid.Column="1" Margin="0,40,0,80" FocusManager.IsFocusScope="True">
|
<!-- Repositories Tool Bar -->
|
||||||
|
<Grid Grid.Row="2" Grid.Column="1" Margin="0,32,0,0">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
<ColumnDefinition Width="16"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<!-- Left Panel -->
|
<TextBlock
|
||||||
<Grid Grid.Column="0">
|
Grid.Column="0"
|
||||||
<Grid.RowDefinitions>
|
HorizontalAlignment="Left"
|
||||||
<RowDefinition Height="Auto"/>
|
Text="{DynamicResource Text.Welcome.Repositories}"
|
||||||
<RowDefinition Height="Auto"/>
|
FontSize="13pt"/>
|
||||||
<RowDefinition Height="Auto"/>
|
|
||||||
<RowDefinition Height="*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<!-- Options -->
|
<Button
|
||||||
<TextBlock
|
Grid.Column="2"
|
||||||
Grid.Row="0"
|
Width="32" Height="28"
|
||||||
Text="{DynamicResource Text.Welcome.Start}"
|
Style="{DynamicResource Style.Button.Link}"
|
||||||
FontSize="13pt"/>
|
ToolTip="{DynamicResource Text.Welcome.OpenOrInit}"
|
||||||
<StackPanel Grid.Row="1" Margin="4,12,0,0" Orientation="Vertical">
|
Click="OnOpenClicked">
|
||||||
<Button Click="OnOpenClicked" Height="28" Style="{DynamicResource Style.Button.Link}">
|
<Path Width="14" Height="14" Data="{StaticResource Icon.NewTab}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
</Button>
|
||||||
<Path Width="16" Height="15" Data="{StaticResource Icon.Folder.Open}" Fill="{DynamicResource Brush.Accent1}"/>
|
|
||||||
<TextBlock Margin="8,0,0,0" Text="{DynamicResource Text.Welcome.OpenOrInit}" Foreground="{DynamicResource Brush.Accent1}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Click="OnCloneClicked" Height="28" Style="{DynamicResource Style.Button.Link}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<Path Width="16" Height="16" Data="{StaticResource Icon.Pull}" Fill="{DynamicResource Brush.Accent1}"/>
|
|
||||||
<TextBlock Margin="8,0,0,0" Text="{DynamicResource Text.Welcome.Clone}" Foreground="{DynamicResource Brush.Accent1}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
<Button Click="OnOpenTerminalClicked" Height="28" Style="{DynamicResource Style.Button.Link}">
|
|
||||||
<StackPanel Orientation="Horizontal">
|
|
||||||
<Path Width="16" Height="14" Data="{StaticResource Icon.Terminal}" Fill="{DynamicResource Brush.Accent1}"/>
|
|
||||||
<TextBlock Margin="8,0,0,0" Text="{DynamicResource Text.Welcome.OpenTerminal}" Foreground="{DynamicResource Brush.Accent1}"/>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<!-- Recents -->
|
<Button
|
||||||
<TextBlock
|
Grid.Column="3"
|
||||||
Grid.Row="2" Margin="0,32,0,0"
|
Width="32" Height="28"
|
||||||
x:Name="lblRecent"
|
Style="{DynamicResource Style.Button.Link}"
|
||||||
Text="{DynamicResource Text.Welcome.Recent}"
|
ToolTip="{DynamicResource Text.Welcome.Clone}"
|
||||||
FontSize="13pt"
|
Click="OnCloneClicked">
|
||||||
Visibility="Hidden"/>
|
<Path Width="16" Height="15" Data="{StaticResource Icon.Pull}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
<DataGrid
|
</Button>
|
||||||
Grid.Row="3"
|
|
||||||
x:Name="list"
|
|
||||||
Margin="0,12,0,0"
|
|
||||||
SelectionUnit="FullRow"
|
|
||||||
SelectionMode="Single"
|
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
|
||||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
|
||||||
LostFocus="OnRecentLostFocus">
|
|
||||||
<DataGrid.RowStyle>
|
|
||||||
<Style BasedOn="{StaticResource Style.DataGridRow}" TargetType="{x:Type DataGridRow}">
|
|
||||||
<EventSetter Event="MouseDoubleClick" Handler="OnRecentDoubleClick"/>
|
|
||||||
<EventSetter Event="ContextMenuOpening" Handler="OnRecentContextMenuOpening"/>
|
|
||||||
</Style>
|
|
||||||
</DataGrid.RowStyle>
|
|
||||||
|
|
||||||
<DataGrid.Columns>
|
|
||||||
<DataGridTemplateColumn Width="*">
|
|
||||||
<DataGridTemplateColumn.CellTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<Grid Height="32" Margin="4,0,0,0" IsHitTestVisible="False">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto"/>
|
|
||||||
<ColumnDefinition Width="*"/>
|
|
||||||
<ColumnDefinition Width="22"/>
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<controls:Bookmark
|
<Button
|
||||||
Grid.Column="0"
|
Grid.Column="4"
|
||||||
Margin="2,0,0,0"
|
Width="32" Height="28"
|
||||||
x:Name="BookmarkIcon"
|
Style="{DynamicResource Style.Button.Link}"
|
||||||
Width="16" Height="16"
|
ToolTip="{DynamicResource Text.Welcome.OpenTerminal}"
|
||||||
Color="{Binding Bookmark}"
|
Click="OnOpenTerminalClicked">
|
||||||
IsNewPage="False"/>
|
<Path Width="16" Height="14" Data="{StaticResource Icon.Terminal}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Search Bar -->
|
||||||
|
<Grid Grid.Row="3" Grid.Column="1" Margin="2,8" Height="28" VerticalAlignment="Top">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="24"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<StackPanel Grid.Column="1" Orientation="Horizontal">
|
<Border
|
||||||
<TextBlock Margin="8,0" Text="{Binding Name}"/>
|
Grid.Column="0" Grid.ColumnSpan="2"
|
||||||
<TextBlock x:Name="Path" Text="{Binding Path}" Foreground="{DynamicResource Brush.FG2}"/>
|
BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
</StackPanel>
|
BorderThickness="1"/>
|
||||||
</Grid>
|
<Path
|
||||||
</DataTemplate>
|
Grid.Column="0"
|
||||||
</DataGridTemplateColumn.CellTemplate>
|
Width="14" Height="14"
|
||||||
</DataGridTemplateColumn>
|
Fill="{DynamicResource Brush.FG2}"
|
||||||
</DataGrid.Columns>
|
Data="{StaticResource Icon.Search}"
|
||||||
</DataGrid>
|
IsHitTestVisible="False"/>
|
||||||
</Grid>
|
<controls:TextEdit
|
||||||
|
x:Name="filter"
|
||||||
|
Grid.Column="1"
|
||||||
|
Height="24"
|
||||||
|
Margin="0"
|
||||||
|
Placeholder="{DynamicResource Text.Welcome.Search}"
|
||||||
|
BorderThickness="0"
|
||||||
|
TextChanged="OnSearchFilterChanged"/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<!-- Repositories List -->
|
||||||
|
<Grid Grid.Row="4" Grid.Column="1" Margin="0,0,0,8" AllowDrop="True" Drop="OnDropFolder">
|
||||||
|
<Grid.Resources>
|
||||||
|
<converters:IntToBookmarkBrush x:Key="IntToBookmarkBrush"/>
|
||||||
|
</Grid.Resources>
|
||||||
|
|
||||||
<!-- Right Panel -->
|
<!-- Wrap panel -->
|
||||||
<Grid Grid.Column="2">
|
<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
|
||||||
<Grid.RowDefinitions>
|
<ItemsControl x:Name="repoList">
|
||||||
<RowDefinition Height="Auto"/>
|
<ItemsControl.ItemsPanel>
|
||||||
<RowDefinition Height="*"/>
|
<ItemsPanelTemplate>
|
||||||
</Grid.RowDefinitions>
|
<VirtualizingStackPanel Orientation="Vertical"/>
|
||||||
|
</ItemsPanelTemplate>
|
||||||
|
</ItemsControl.ItemsPanel>
|
||||||
|
|
||||||
<!-- Repositories Label -->
|
<ItemsControl.ItemTemplate>
|
||||||
<TextBlock
|
<DataTemplate>
|
||||||
Grid.Row="0"
|
<Control MouseDoubleClick="OnDoubleClickRepository">
|
||||||
Text="{DynamicResource Text.Welcome.Repositories}"
|
<Control.Template>
|
||||||
FontSize="13pt"
|
<ControlTemplate>
|
||||||
HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
<Border
|
||||||
|
Height="36"
|
||||||
<!-- Repositories Tree DragDrop tip -->
|
Margin="2"
|
||||||
<StackPanel Grid.Row="1" x:Name="dropTip" Margin="4,16,0,0" HorizontalAlignment="Left" Orientation="Vertical">
|
BorderThickness="1" BorderBrush="{DynamicResource Brush.Border2}"
|
||||||
<Path
|
Background="{DynamicResource Brush.Contents}">
|
||||||
Data="{DynamicResource Icon.DragDrop}"
|
<Grid Margin="8,0">
|
||||||
Fill="{DynamicResource Brush.FG2}"
|
<Grid.ColumnDefinitions>
|
||||||
Width="48" Height="48"
|
<ColumnDefinition Width="Auto"/>
|
||||||
VerticalAlignment="Top"/>
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="*"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
<ColumnDefinition Width="Auto"/>
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock
|
<Button Grid.Column="0" Background="Transparent" Width="16" BorderThickness="0" ToolTip="{DynamicResource Text.RepoCM.Bookmark}" Click="OnChangeRepositoryBookmark">
|
||||||
Text="{DynamicResource Text.Welcome.DragDrop}"
|
<Path Width="8" Fill="{Binding Bookmark, Converter={StaticResource IntToBookmarkBrush}}">
|
||||||
FontSize="10pt"
|
<Path.Data>
|
||||||
Margin="0,8,0,0"
|
<EllipseGeometry Center="0,0" RadiusX="14" RadiusY="14"/>
|
||||||
HorizontalAlignment="Center" VerticalAlignment="Top"
|
</Path.Data>
|
||||||
Foreground="{DynamicResource Brush.FG2}"/>
|
</Path>
|
||||||
</StackPanel>
|
</Button>
|
||||||
|
|
||||||
<!-- Repositories Tree -->
|
<TextBlock Grid.Column="1" Margin="8,0" Text="{Binding Name}" FontSize="12pt" FontFamily="{Binding Source={x:Static models:Preference.Instance}, Path=General.FontFamilyContent, Mode=OneWay}"/>
|
||||||
<controls:Tree
|
<TextBlock Grid.Column="2" Text="{Binding Path}" FontSize="10pt" Foreground="{DynamicResource Brush.FG2}"/>
|
||||||
Grid.Row="1"
|
|
||||||
x:Name="tree"
|
|
||||||
Margin="0,8,0,0"
|
|
||||||
AllowDrop="True"
|
|
||||||
TextElement.FontSize="14"
|
|
||||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
|
||||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
|
||||||
ContextMenuOpening="OnTreeContextMenuOpening"
|
|
||||||
MouseMove="OnTreeMouseMove"
|
|
||||||
DragOver="OnTreeDragOver"
|
|
||||||
Drop="OnTreeDrop"
|
|
||||||
LostFocus="OnTreeLostFocus">
|
|
||||||
<controls:Tree.ItemContainerStyle>
|
|
||||||
<Style TargetType="{x:Type controls:TreeItem}" BasedOn="{StaticResource Style.TreeItem}">
|
|
||||||
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
|
|
||||||
|
|
||||||
<EventSetter Event="Expanded" Handler="OnTreeNodeStatusChange"/>
|
<Button Grid.Column="4" BorderThickness="0" Background="Transparent" ToolTip="{DynamicResource Text.RepoCM.Open}" Click="OnOpenRepository">
|
||||||
<EventSetter Event="Collapsed" Handler="OnTreeNodeStatusChange"/>
|
<Path Width="15" Data="{StaticResource Icon.Folder.Open}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
<EventSetter Event="MouseDoubleClick" Handler="OnTreeNodeDoubleClick"/>
|
</Button>
|
||||||
</Style>
|
<Button Grid.Column="5" Margin="8,0,0,0" BorderThickness="0" Background="Transparent" ToolTip="{DynamicResource Text.Welcome.OpenTerminal}" Click="OnOpenRepositoryTerminal">
|
||||||
</controls:Tree.ItemContainerStyle>
|
<Path Width="14" Data="{StaticResource Icon.Terminal}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
|
</Button>
|
||||||
<controls:Tree.ItemTemplate>
|
<Button Grid.Column="6" Margin="8,0,0,0" BorderThickness="0" Background="Transparent" ToolTip="{DynamicResource Text.Welcome.Delete}" Click="OnRemoveRepository">
|
||||||
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
|
<Path Width="10" Data="{StaticResource Icon.Close}" Fill="{DynamicResource Brush.Accent1}"/>
|
||||||
<Grid Height="32" IsHitTestVisible="False">
|
</Button>
|
||||||
<Grid.ColumnDefinitions>
|
</Grid>
|
||||||
<ColumnDefinition Width="Auto"/>
|
</Border>
|
||||||
<ColumnDefinition Width="*"/>
|
</ControlTemplate>
|
||||||
<ColumnDefinition Width="22"/>
|
</Control.Template>
|
||||||
</Grid.ColumnDefinitions>
|
</Control>
|
||||||
|
</DataTemplate>
|
||||||
<Path Grid.Column="0" Margin="2,0,0,0" x:Name="Icon" Width="16" Height="16" Data="{StaticResource Icon.Folder.Fill}"/>
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
<controls:Bookmark
|
</ScrollViewer>
|
||||||
Grid.Column="0"
|
|
||||||
Margin="2,0,0,0"
|
<!-- Drop Area -->
|
||||||
x:Name="BookmarkIcon"
|
<Rectangle
|
||||||
Width="16" Height="16"
|
x:Name="dropArea"
|
||||||
Color="{Binding Bookmark}"
|
Stroke="{DynamicResource Brush.Border1}"
|
||||||
IsNewPage="False"/>
|
StrokeThickness="2"
|
||||||
|
StrokeDashArray="4,4"
|
||||||
<StackPanel Grid.Column="1" x:Name="ContentsBookmark" Orientation="Horizontal">
|
SnapsToDevicePixels="True"
|
||||||
<TextBlock Margin="8,0" Text="{Binding Name}"/>
|
Visibility="Hidden"
|
||||||
<TextBlock x:Name="Path" Text="{Binding Id}" Foreground="{DynamicResource Brush.FG2}"/>
|
IsHitTestVisible="False"/>
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<controls:TextEdit
|
|
||||||
Grid.Column="1"
|
|
||||||
x:Name="EditorBookmarks"
|
|
||||||
Height="20"
|
|
||||||
Margin="4,0,0,0"
|
|
||||||
Text="{Binding Name}"
|
|
||||||
FontSize="9pt"
|
|
||||||
Loaded="RenameStart"
|
|
||||||
KeyDown="RenameKeyDown"
|
|
||||||
LostFocus="RenameEnd"
|
|
||||||
IsHitTestVisible="True"
|
|
||||||
Visibility="Collapsed"/>
|
|
||||||
</Grid>
|
|
||||||
|
|
||||||
<HierarchicalDataTemplate.Triggers>
|
|
||||||
<DataTrigger Binding="{Binding IsGroup}" Value="True">
|
|
||||||
<Setter TargetName="Path" Property="Visibility" Value="Collapsed"/>
|
|
||||||
<Setter TargetName="Icon" Property="Visibility" Value="Visible"/>
|
|
||||||
<Setter TargetName="BookmarkIcon" Property="Visibility" Value="Collapsed"/>
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding IsGroup}" Value="False">
|
|
||||||
<Setter TargetName="Path" Property="Visibility" Value="Visible"/>
|
|
||||||
<Setter TargetName="Icon" Property="Visibility" Value="Collapsed"/>
|
|
||||||
<Setter TargetName="BookmarkIcon" Property="Visibility" Value="Visible"/>
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:TreeItem}}, Path=IsExpanded}" Value="True">
|
|
||||||
<Setter TargetName="Icon" Property="Data" Value="{StaticResource Icon.Folder.Open}"/>
|
|
||||||
</DataTrigger>
|
|
||||||
<DataTrigger Binding="{Binding IsEditing}" Value="True">
|
|
||||||
<Setter TargetName="EditorBookmarks" Property="Visibility" Value="Visible"/>
|
|
||||||
<Setter TargetName="ContentsBookmark" Property="Visibility" Value="Collapsed"/>
|
|
||||||
</DataTrigger>
|
|
||||||
</HierarchicalDataTemplate.Triggers>
|
|
||||||
</HierarchicalDataTemplate>
|
|
||||||
</controls:Tree.ItemTemplate>
|
|
||||||
</controls:Tree>
|
|
||||||
|
|
||||||
<!-- Drop Area -->
|
|
||||||
<Rectangle
|
|
||||||
Grid.Row="1"
|
|
||||||
x:Name="dropArea"
|
|
||||||
Margin="0,4"
|
|
||||||
Stroke="{DynamicResource Brush.Border1}"
|
|
||||||
StrokeThickness="2"
|
|
||||||
StrokeDashArray="4,4"
|
|
||||||
SnapsToDevicePixels="True"
|
|
||||||
Visibility="Hidden"
|
|
||||||
IsHitTestVisible="False"/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<!-- Popup -->
|
<!-- Popup -->
|
||||||
<widgets:PopupPanel x:Name="popup" Grid.Row="0" Grid.RowSpan="4" Grid.Column="0" Grid.ColumnSpan="3"/>
|
<widgets:PopupPanel x:Name="popup" Grid.Row="0" Grid.RowSpan="5" Grid.Column="0" Grid.ColumnSpan="3"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|
|
@ -2,9 +2,9 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
@ -16,46 +16,13 @@ namespace SourceGit.Views.Widgets {
|
||||||
public partial class Welcome : UserControl, Controls.IPopupContainer {
|
public partial class Welcome : UserControl, Controls.IPopupContainer {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 树节点数据
|
/// 修改仓库标签颜色的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Node : Controls.BindableBase {
|
public event Action<Models.Repository> OnBookmarkChanged;
|
||||||
public string Id { get; set; }
|
|
||||||
public string ParentId { get; set; }
|
|
||||||
|
|
||||||
private string name;
|
|
||||||
public string Name {
|
|
||||||
get => name;
|
|
||||||
set => SetProperty(ref name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsGroup { get; set; }
|
|
||||||
|
|
||||||
private bool isEditing = false;
|
|
||||||
public bool IsEditing {
|
|
||||||
get => isEditing;
|
|
||||||
set => SetProperty(ref isEditing, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsExpanded { get; set; }
|
|
||||||
|
|
||||||
private int bookmark = 0;
|
|
||||||
public int Bookmark {
|
|
||||||
get => bookmark;
|
|
||||||
set => SetProperty(ref bookmark, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Node> Children { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 仓库节点编辑事件参数
|
|
||||||
/// </summary>
|
|
||||||
public event Action<Node> OnNodeEdited;
|
|
||||||
|
|
||||||
public Welcome() {
|
public Welcome() {
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
UpdateTree();
|
UpdateVisibles();
|
||||||
UpdateRecents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region POPUP_CONTAINER
|
#region POPUP_CONTAINER
|
||||||
|
@ -99,166 +66,84 @@ namespace SourceGit.Views.Widgets {
|
||||||
if (MakeSureReady()) new Popups.Clone().Show();
|
if (MakeSureReady()) new Popups.Clone().Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRecentContextMenuOpening(object sender, ContextMenuEventArgs e) {
|
private void OnRemoveRepository(object sender, RoutedEventArgs e) {
|
||||||
var repo = (sender as DataGridRow).DataContext as Models.Repository;
|
var repo = (sender as Button).DataContext as Models.Repository;
|
||||||
if (repo != null) {
|
Models.Preference.Instance.RemoveRepository(repo.Path);
|
||||||
var remove = new MenuItem();
|
UpdateVisibles();
|
||||||
remove.Header = App.Text("Welcome.Delete");
|
|
||||||
remove.Click += (o, ev) => {
|
|
||||||
Models.Preference.Instance.RemoveRecent(repo.Path);
|
|
||||||
UpdateRecents();
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
|
||||||
menu.Items.Add(remove);
|
|
||||||
menu.IsOpen = true;
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnRecentDoubleClick(object sender, MouseButtonEventArgs e) {
|
|
||||||
var repo = (sender as DataGridRow).DataContext as Models.Repository;
|
|
||||||
if (repo != null) CheckAndOpen(repo.Path);
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRecentLostFocus(object sender, RoutedEventArgs e) {
|
private void OnDoubleClickRepository(object sender, MouseButtonEventArgs e) {
|
||||||
list.UnselectAll();
|
OnOpenRepository(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOpenRepository(object sender, RoutedEventArgs e) {
|
||||||
|
var repo = (sender as Control).DataContext as Models.Repository;
|
||||||
|
CheckAndOpen(repo.Path);
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTreeLostFocus(object sender, RoutedEventArgs e) {
|
private void OnChangeRepositoryBookmark(object sender, RoutedEventArgs e) {
|
||||||
var child = FocusManager.GetFocusedElement(body);
|
var btn = (sender as Button);
|
||||||
if (child == null) return;
|
var repo = btn.DataContext as Models.Repository;
|
||||||
|
|
||||||
if (!tree.IsAncestorOf(child as UIElement)) tree.UnselectAll();
|
var menu = new ContextMenu();
|
||||||
e.Handled = true;
|
menu.Placement = PlacementMode.Bottom;
|
||||||
}
|
menu.PlacementTarget = btn;
|
||||||
|
menu.StaysOpen = false;
|
||||||
|
menu.Focusable = true;
|
||||||
|
|
||||||
private void OnTreeNodeStatusChange(object sender, RoutedEventArgs e) {
|
for (int i = 0; i < Converters.IntToBookmarkBrush.COLORS.Length; i++) {
|
||||||
var node = (sender as Controls.TreeItem).DataContext as Node;
|
var icon = new System.Windows.Shapes.Path();
|
||||||
if (node != null) {
|
icon.Data = new EllipseGeometry(new Point(0, 0), 8, 8);
|
||||||
var group = Models.Preference.Instance.FindGroup(node.Id);
|
icon.Fill = i == 0 ? (FindResource("Brush.FG1") as Brush) : Converters.IntToBookmarkBrush.COLORS[i];
|
||||||
group.IsExpanded = node.IsExpanded;
|
icon.Width = 12;
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTreeNodeDoubleClick(object sender, MouseButtonEventArgs e) {
|
var mark = new MenuItem();
|
||||||
var node = (sender as Controls.TreeItem).DataContext as Node;
|
mark.Icon = icon;
|
||||||
if (node != null && !node.IsGroup) {
|
mark.Header = $"{i}";
|
||||||
CheckAndOpen(node.Id);
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTreeContextMenuOpening(object sender, ContextMenuEventArgs e) {
|
var refIdx = i;
|
||||||
var item = tree.FindItem(e.OriginalSource as DependencyObject);
|
mark.Click += (o, ev) => {
|
||||||
if (item == null) {
|
if (repo != null) {
|
||||||
var addFolder = new MenuItem();
|
repo.Bookmark = refIdx;
|
||||||
addFolder.Header = App.Text("Welcome.NewFolder");
|
UpdateVisibles();
|
||||||
addFolder.Click += (o, ev) => {
|
OnBookmarkChanged?.Invoke(repo);
|
||||||
var group = Models.Preference.Instance.AddGroup("New Group", "");
|
|
||||||
UpdateTree(group.Id);
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
|
||||||
menu.Items.Add(addFolder);
|
|
||||||
menu.IsOpen = true;
|
|
||||||
e.Handled = true;
|
|
||||||
} else {
|
|
||||||
var node = item.DataContext as Node;
|
|
||||||
if (node == null) return;
|
|
||||||
|
|
||||||
var menu = new ContextMenu();
|
|
||||||
if (!node.IsGroup) {
|
|
||||||
var open = new MenuItem();
|
|
||||||
open.Header = App.Text("RepoCM.Open");
|
|
||||||
open.Click += (o, ev) => {
|
|
||||||
CheckAndOpen(node.Id);
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var explore = new MenuItem();
|
|
||||||
explore.Header = App.Text("RepoCM.Explore");
|
|
||||||
explore.Click += (o, ev) => {
|
|
||||||
Process.Start("explorer", node.Id);
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
var iconBookmark = FindResource("Icon.Git") as Geometry;
|
|
||||||
var bookmark = new MenuItem();
|
|
||||||
bookmark.Header = App.Text("RepoCM.Bookmark");
|
|
||||||
for (int i = 0; i < Controls.Bookmark.COLORS.Length; i++) {
|
|
||||||
var icon = new System.Windows.Shapes.Path();
|
|
||||||
icon.Data = iconBookmark;
|
|
||||||
icon.Fill = i == 0 ? (FindResource("Brush.FG1") as Brush) : Controls.Bookmark.COLORS[i];
|
|
||||||
icon.Width = 12;
|
|
||||||
|
|
||||||
var mark = new MenuItem();
|
|
||||||
mark.Icon = icon;
|
|
||||||
mark.Header = $"{i}";
|
|
||||||
|
|
||||||
var refIdx = i;
|
|
||||||
mark.Click += (o, ev) => {
|
|
||||||
var repo = Models.Preference.Instance.FindRepository(node.Id);
|
|
||||||
if (repo != null) {
|
|
||||||
repo.Bookmark = refIdx;
|
|
||||||
node.Bookmark = refIdx;
|
|
||||||
UpdateRecents();
|
|
||||||
OnNodeEdited?.Invoke(node);
|
|
||||||
}
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
bookmark.Items.Add(mark);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.Items.Add(open);
|
|
||||||
menu.Items.Add(explore);
|
|
||||||
menu.Items.Add(bookmark);
|
|
||||||
} else {
|
|
||||||
var addSubFolder = new MenuItem();
|
|
||||||
addSubFolder.Header = App.Text("Welcome.NewSubFolder");
|
|
||||||
addSubFolder.Click += (o, ev) => {
|
|
||||||
var parent = Models.Preference.Instance.FindGroup(node.Id);
|
|
||||||
if (parent != null) parent.IsExpanded = true;
|
|
||||||
|
|
||||||
var group = Models.Preference.Instance.AddGroup("New Group", node.Id);
|
|
||||||
UpdateTree(group.Id);
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
menu.Items.Add(addSubFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
var rename = new MenuItem();
|
|
||||||
rename.Header = App.Text("Welcome.Rename");
|
|
||||||
rename.Click += (o, ev) => {
|
|
||||||
UpdateTree(node.Id);
|
|
||||||
ev.Handled = true;
|
ev.Handled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
var delete = new MenuItem();
|
menu.Items.Add(mark);
|
||||||
delete.Header = App.Text("Welcome.Delete");
|
|
||||||
delete.Click += (o, ev) => {
|
|
||||||
DeleteNode(node);
|
|
||||||
ev.Handled = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
menu.Items.Add(rename);
|
|
||||||
menu.Items.Add(delete);
|
|
||||||
menu.IsOpen = true;
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
btn.ContextMenu = menu;
|
||||||
|
btn.ContextMenu.IsOpen = true;
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOpenRepositoryTerminal(object sender, RoutedEventArgs e) {
|
||||||
|
var repo = (sender as Button).DataContext as Models.Repository;
|
||||||
|
var bash = Path.Combine(Models.Preference.Instance.Git.Path, "..", "bash.exe");
|
||||||
|
if (!File.Exists(bash)) {
|
||||||
|
Models.Exception.Raise(App.Text("MissingBash"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Process.Start(new ProcessStartInfo {
|
||||||
|
WorkingDirectory = repo.Path,
|
||||||
|
FileName = bash,
|
||||||
|
UseShellExecute = true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSearchFilterChanged(object sender, TextChangedEventArgs e) {
|
||||||
|
UpdateVisibles();
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DRAP_DROP_EVENTS
|
#region DRAG_DROP
|
||||||
private void OnPageDragEnter(object sender, DragEventArgs e) {
|
private void OnPageDragEnter(object sender, DragEventArgs e) {
|
||||||
if (e.Data.GetDataPresent(DataFormats.FileDrop) || e.Data.GetDataPresent(typeof(Node))) {
|
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
||||||
dropArea.Visibility = Visibility.Visible;
|
dropArea.Visibility = Visibility.Visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,41 +156,10 @@ namespace SourceGit.Views.Widgets {
|
||||||
dropArea.Visibility = Visibility.Hidden;
|
dropArea.Visibility = Visibility.Hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTreeMouseMove(object sender, MouseEventArgs e) {
|
private void OnDropFolder(object sender, DragEventArgs e) {
|
||||||
if (e.LeftButton != MouseButtonState.Pressed) return;
|
|
||||||
|
|
||||||
var item = tree.FindItem(e.OriginalSource as DependencyObject);
|
|
||||||
if (item == null) return;
|
|
||||||
|
|
||||||
tree.UnselectAll();
|
|
||||||
|
|
||||||
var adorner = new Controls.DragDropAdorner(item);
|
|
||||||
DragDrop.DoDragDrop(item, item.DataContext, DragDropEffects.Move);
|
|
||||||
adorner.Remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTreeDragOver(object sender, DragEventArgs e) {
|
|
||||||
if (!e.Data.GetDataPresent(DataFormats.FileDrop) && !e.Data.GetDataPresent(typeof(Node))) return;
|
|
||||||
|
|
||||||
var item = tree.FindItem(e.OriginalSource as DependencyObject);
|
|
||||||
if (item == null) return;
|
|
||||||
|
|
||||||
var node = item.DataContext as Node;
|
|
||||||
if (node.IsGroup && !item.IsExpanded) item.IsExpanded = true;
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTreeDrop(object sender, DragEventArgs e) {
|
|
||||||
bool rebuild = false;
|
bool rebuild = false;
|
||||||
dropArea.Visibility = Visibility.Hidden;
|
dropArea.Visibility = Visibility.Hidden;
|
||||||
|
|
||||||
var parent = "";
|
|
||||||
var to = tree.FindItem(e.OriginalSource as DependencyObject);
|
|
||||||
if (to != null) {
|
|
||||||
var dst = to.DataContext as Node;
|
|
||||||
parent = dst.IsGroup ? dst.Id : dst.ParentId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
|
||||||
if (!MakeSureReady()) return;
|
if (!MakeSureReady()) return;
|
||||||
|
|
||||||
|
@ -314,118 +168,33 @@ namespace SourceGit.Views.Widgets {
|
||||||
var dir = new Commands.QueryGitDir(path).Result();
|
var dir = new Commands.QueryGitDir(path).Result();
|
||||||
if (dir != null) {
|
if (dir != null) {
|
||||||
var root = new Commands.GetRepositoryRootPath(path).Result();
|
var root = new Commands.GetRepositoryRootPath(path).Result();
|
||||||
Models.Preference.Instance.AddRepository(root, dir, parent);
|
Models.Preference.Instance.AddRepository(root, dir);
|
||||||
rebuild = true;
|
rebuild = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (e.Data.GetDataPresent(typeof(Node))) {
|
|
||||||
var src = e.Data.GetData(typeof(Node)) as Node;
|
|
||||||
if (src.IsGroup) {
|
|
||||||
if (!Models.Preference.Instance.IsSubGroup(src.Id, parent)) {
|
|
||||||
Models.Preference.Instance.FindGroup(src.Id).Parent = parent;
|
|
||||||
rebuild = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Models.Preference.Instance.FindRepository(src.Id).GroupId = parent;
|
|
||||||
rebuild = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rebuild) UpdateTree();
|
if (rebuild) UpdateVisibles();
|
||||||
e.Handled = true;
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region DATA
|
#region DATA
|
||||||
private void UpdateRecents() {
|
public void UpdateVisibles() {
|
||||||
var repos = new List<Models.Repository>();
|
var visibles = new List<Models.Repository>();
|
||||||
var dirty = new List<string>();
|
var curFilter = filter.Text.ToLower();
|
||||||
|
|
||||||
foreach (var path in Models.Preference.Instance.Recents) {
|
if (string.IsNullOrEmpty(curFilter)) {
|
||||||
var repo = Models.Preference.Instance.FindRepository(path);
|
visibles.AddRange(Models.Preference.Instance.Repositories);
|
||||||
if (repo != null) {
|
} else {
|
||||||
repos.Add(repo);
|
foreach (var repo in Models.Preference.Instance.Repositories) {
|
||||||
} else {
|
if (repo.Name.ToLower().Contains(curFilter, StringComparison.Ordinal) ||
|
||||||
dirty.Add(path);
|
repo.Path.ToLower().Contains(curFilter, StringComparison.Ordinal)) {
|
||||||
|
visibles.Add(repo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var path in dirty) Models.Preference.Instance.RemoveRecent(path);
|
repoList.ItemsSource = visibles;
|
||||||
list.ItemsSource = repos;
|
|
||||||
|
|
||||||
if (repos.Count == 0) {
|
|
||||||
lblRecent.Visibility = Visibility.Hidden;
|
|
||||||
} else {
|
|
||||||
lblRecent.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateTree(string editingNodeId = null) {
|
|
||||||
var groupNodes = new Dictionary<string, Node>();
|
|
||||||
var nodes = new List<Node>();
|
|
||||||
|
|
||||||
foreach (var group in Models.Preference.Instance.Groups) {
|
|
||||||
Node node = new Node() {
|
|
||||||
Id = group.Id,
|
|
||||||
ParentId = group.Parent,
|
|
||||||
Name = group.Name,
|
|
||||||
IsGroup = true,
|
|
||||||
IsEditing = group.Id == editingNodeId,
|
|
||||||
IsExpanded = group.IsExpanded,
|
|
||||||
Bookmark = 0,
|
|
||||||
Children = new List<Node>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
groupNodes.Add(node.Id, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
nodes.Clear();
|
|
||||||
|
|
||||||
foreach (var kv in groupNodes) {
|
|
||||||
if (groupNodes.ContainsKey(kv.Value.ParentId)) {
|
|
||||||
groupNodes[kv.Value.ParentId].Children.Add(kv.Value);
|
|
||||||
} else {
|
|
||||||
nodes.Add(kv.Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var repo in Models.Preference.Instance.Repositories) {
|
|
||||||
Node node = new Node() {
|
|
||||||
Id = repo.Path,
|
|
||||||
ParentId = repo.GroupId,
|
|
||||||
Name = repo.Name,
|
|
||||||
IsGroup = false,
|
|
||||||
IsEditing = repo.Path == editingNodeId,
|
|
||||||
IsExpanded = false,
|
|
||||||
Bookmark = repo.Bookmark,
|
|
||||||
Children = new List<Node>(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if (groupNodes.ContainsKey(repo.GroupId)) {
|
|
||||||
groupNodes[repo.GroupId].Children.Add(node);
|
|
||||||
} else {
|
|
||||||
nodes.Add(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tree.ItemsSource = nodes;
|
|
||||||
|
|
||||||
if (nodes.Count > 0) {
|
|
||||||
dropTip.Visibility = Visibility.Collapsed;
|
|
||||||
} else {
|
|
||||||
dropTip.Visibility = Visibility.Visible;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DeleteNode(Node node) {
|
|
||||||
if (node.IsGroup) {
|
|
||||||
Models.Preference.Instance.RemoveGroup(node.Id);
|
|
||||||
} else {
|
|
||||||
Models.Preference.Instance.RemoveRepository(node.Id);
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateTree();
|
|
||||||
UpdateRecents();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MakeSureReady() {
|
private bool MakeSureReady() {
|
||||||
|
@ -451,68 +220,9 @@ namespace SourceGit.Views.Widgets {
|
||||||
}
|
}
|
||||||
|
|
||||||
var gitDir = new Commands.QueryGitDir(root).Result();
|
var gitDir = new Commands.QueryGitDir(root).Result();
|
||||||
var repo = Models.Preference.Instance.AddRepository(root, gitDir, "");
|
var repo = Models.Preference.Instance.AddRepository(root, gitDir);
|
||||||
Models.Watcher.Open(repo);
|
Models.Watcher.Open(repo);
|
||||||
Models.Preference.Instance.AddRecent(repo.Path);
|
UpdateVisibles();
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateNodes(string id, int bookmark, IEnumerable<Node> nodes = null) {
|
|
||||||
if (nodes == null) nodes = tree.ItemsSource.OfType<Node>();
|
|
||||||
foreach (var node in nodes) {
|
|
||||||
if (!node.IsGroup) {
|
|
||||||
if (node.Id == id) {
|
|
||||||
node.Bookmark = bookmark;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (node.Children.Count > 0) {
|
|
||||||
UpdateNodes(id, bookmark, node.Children);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region RENAME_NODES
|
|
||||||
private void RenameStart(object sender, RoutedEventArgs e) {
|
|
||||||
var edit = sender as Controls.TextEdit;
|
|
||||||
if (edit == null || !edit.IsVisible) return;
|
|
||||||
|
|
||||||
edit.SelectAll();
|
|
||||||
edit.Focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RenameKeyDown(object sender, KeyEventArgs e) {
|
|
||||||
if (e.Key == Key.Escape) {
|
|
||||||
UpdateTree();
|
|
||||||
e.Handled = true;
|
|
||||||
} else if (e.Key == Key.Enter) {
|
|
||||||
RenameEnd(sender, e);
|
|
||||||
e.Handled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RenameEnd(object sender, RoutedEventArgs e) {
|
|
||||||
var edit = sender as Controls.TextEdit;
|
|
||||||
if (edit == null) return;
|
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(edit.Text)) {
|
|
||||||
UpdateTree();
|
|
||||||
e.Handled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var node = edit.DataContext as Node;
|
|
||||||
if (node != null) {
|
|
||||||
node.Name = edit.Text;
|
|
||||||
node.IsEditing = false;
|
|
||||||
if (node.IsGroup) {
|
|
||||||
Models.Preference.Instance.RenameGroup(node.Id, edit.Text);
|
|
||||||
} else {
|
|
||||||
Models.Preference.Instance.RenameRepository(node.Id, node.Name);
|
|
||||||
UpdateRecents();
|
|
||||||
OnNodeEdited?.Invoke(node);
|
|
||||||
}
|
|
||||||
e.Handled = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue