From b43044a7bf12cf9d331af074c812b168997d5a17 Mon Sep 17 00:00:00 2001 From: leo Date: Fri, 14 Oct 2022 20:38:53 +0800 Subject: [PATCH] style: re-design the style for Welcome page --- src/App.xaml.cs | 2 +- src/Models/Group.cs | 12 - src/Models/Preference.cs | 109 +---- src/Models/Repository.cs | 1 - src/Resources/Icons.xaml | 4 +- src/Resources/Locales/en_US.xaml | 9 +- src/Resources/Locales/zh_CN.xaml | 7 +- src/Views/Blame.xaml | 6 +- src/Views/Controls/Bookmark.cs | 64 --- src/Views/Converters/IntToBookmarkBrush.cs | 29 ++ src/Views/FileHistories.xaml | 6 +- src/Views/Launcher.xaml | 8 +- src/Views/Launcher.xaml.cs | 8 +- src/Views/Popups/Clone.xaml.cs | 2 +- src/Views/Popups/Init.xaml.cs | 2 +- src/Views/Widgets/PageTabBar.xaml | 57 ++- src/Views/Widgets/PageTabBar.xaml.cs | 14 +- src/Views/Widgets/Welcome.xaml | 362 +++++++---------- src/Views/Widgets/Welcome.xaml.cs | 450 ++++----------------- 19 files changed, 319 insertions(+), 833 deletions(-) delete mode 100644 src/Models/Group.cs delete mode 100644 src/Views/Controls/Bookmark.cs create mode 100644 src/Views/Converters/IntToBookmarkBrush.cs diff --git a/src/App.xaml.cs b/src/App.xaml.cs index 808bd4e3..267d5e98 100644 --- a/src/App.xaml.cs +++ b/src/App.xaml.cs @@ -49,7 +49,7 @@ namespace SourceGit { var path = new Commands.GetRepositoryRootPath(e.Args[0]).Result(); if (path != null) { var gitDir = new Commands.QueryGitDir(path).Result(); - repo = Models.Preference.Instance.AddRepository(path, gitDir, ""); + repo = Models.Preference.Instance.AddRepository(path, gitDir); } } diff --git a/src/Models/Group.cs b/src/Models/Group.cs deleted file mode 100644 index 22fdf024..00000000 --- a/src/Models/Group.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace SourceGit.Models { - - /// - /// 仓库列表分组 - /// - public class Group { - public string Id { get; set; } = ""; - public string Name { get; set; } = ""; - public string Parent { get; set; } = ""; - public bool IsExpanded { get; set; } = false; - } -} diff --git a/src/Models/Preference.cs b/src/Models/Preference.cs index 8e327f9e..bb16df69 100644 --- a/src/Models/Preference.cs +++ b/src/Models/Preference.cs @@ -212,9 +212,7 @@ namespace SourceGit.Models { public GitInfo Git { get; set; } = new GitInfo(); public MergeToolInfo MergeTool { get; set; } = new MergeToolInfo(); public WindowInfo Window { get; set; } = new WindowInfo(); - public List Groups { get; set; } = new List(); public List Repositories { get; set; } = new List(); - public List Recents { get; set; } = new List(); public RestoreTabs Restore { get; set; } = new RestoreTabs(); #endregion @@ -251,71 +249,8 @@ namespace SourceGit.Models { } #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 - public Repository AddRepository(string path, string gitDir, string groupId) { + public Repository AddRepository(string path, string gitDir) { var repo = FindRepository(path); if (repo != null) return repo; @@ -323,8 +258,7 @@ namespace SourceGit.Models { repo = new Repository() { Path = dir.FullName, GitDir = gitDir, - Name = dir.Name, - GroupId = groupId, + Name = dir.Name }; Repositories.Add(repo); @@ -340,14 +274,6 @@ namespace SourceGit.Models { 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) { var dir = new DirectoryInfo(path); var removedIdx = -1; @@ -362,36 +288,5 @@ namespace SourceGit.Models { if (removedIdx >= 0) Repositories.RemoveAt(removedIdx); } #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 } } \ No newline at end of file diff --git a/src/Models/Repository.cs b/src/Models/Repository.cs index e7accc47..792e5b49 100644 --- a/src/Models/Repository.cs +++ b/src/Models/Repository.cs @@ -27,7 +27,6 @@ namespace SourceGit.Models { public string Name { get; set; } = ""; public string Path { get; set; } = ""; public string GitDir { get; set; } = ""; - public string GroupId { get; set; } = ""; public int Bookmark { get; set; } = 0; public List SubTrees { get; set; } = new List(); public List Filters { get; set; } = new List(); diff --git a/src/Resources/Icons.xaml b/src/Resources/Icons.xaml index f6e198ac..d81bc0ac 100644 --- a/src/Resources/Icons.xaml +++ b/src/Resources/Icons.xaml @@ -9,8 +9,8 @@ M1024 427H597V0h-171v427H0v171h427V1024h171V597H1024z M682.7 42.7H85.3v682.7h85.3V128h512V42.7zM256 213.3l4.5 768H896V213.3H256zm554.7 682.7H341.3V298.7h469.3v597.3z 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 - - M797 486H224c-14 0-25 11-25 25c0 14 11 25 25 25H797c14 0 25-11 25-25c0-14-11-25-25-25z + + M 0 0 L 1 0 V -0.861 M 153 154 h 768 v 60 h -767 z M153 154h768v768h-768v-768zm64 64v640h640v-640h-640z 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 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 diff --git a/src/Resources/Locales/en_US.xaml b/src/Resources/Locales/en_US.xaml index 48117316..a1a1fd90 100644 --- a/src/Resources/Locales/en_US.xaml +++ b/src/Resources/Locales/en_US.xaml @@ -297,18 +297,13 @@ Into : Merge Option : - Free & open source GUI for git users + Free & open source GUI tool for git users Open Repository Open Terminal Clone Repository - DROP FOLDER HERE - START - RECENT OPENED REPOSITORIES - Add Folder - Add Sub-Folder - Rename Delete + Search Repositories ... Pull Pull (Fetch & Merge) diff --git a/src/Resources/Locales/zh_CN.xaml b/src/Resources/Locales/zh_CN.xaml index d8393834..f8ae2882 100644 --- a/src/Resources/Locales/zh_CN.xaml +++ b/src/Resources/Locales/zh_CN.xaml @@ -300,14 +300,9 @@ 打开本地仓库 打开GIT终端 克隆远程仓库 - 支持拖放操作 - 开始使用 - 最近使用 收藏/书签 - 新建分组 - 新建子分组 - 重命名 删除 + 快速查找仓库 拉回 拉回(拉取并合并) diff --git a/src/Views/Blame.xaml b/src/Views/Blame.xaml index 5cc7fc87..35d4a2ee 100644 --- a/src/Views/Blame.xaml +++ b/src/Views/Blame.xaml @@ -36,9 +36,9 @@ - - - + + + diff --git a/src/Views/Controls/Bookmark.cs b/src/Views/Controls/Bookmark.cs deleted file mode 100644 index 20d80fca..00000000 --- a/src/Views/Controls/Bookmark.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Shapes; - -namespace SourceGit.Views.Controls { - - /// - /// 标签页图标 - /// - 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; - } - } - } -} diff --git a/src/Views/Converters/IntToBookmarkBrush.cs b/src/Views/Converters/IntToBookmarkBrush.cs new file mode 100644 index 00000000..aa6c6063 --- /dev/null +++ b/src/Views/Converters/IntToBookmarkBrush.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/src/Views/FileHistories.xaml b/src/Views/FileHistories.xaml index 84f68297..325d1fea 100644 --- a/src/Views/FileHistories.xaml +++ b/src/Views/FileHistories.xaml @@ -36,9 +36,9 @@ - - - + + + diff --git a/src/Views/Launcher.xaml b/src/Views/Launcher.xaml index 84c0b563..ec5cc273 100644 --- a/src/Views/Launcher.xaml +++ b/src/Views/Launcher.xaml @@ -27,7 +27,7 @@ - + @@ -53,9 +53,9 @@ - - - + + + diff --git a/src/Views/Launcher.xaml.cs b/src/Views/Launcher.xaml.cs index c44acd47..4aa6a1e7 100644 --- a/src/Views/Launcher.xaml.cs +++ b/src/Views/Launcher.xaml.cs @@ -22,9 +22,9 @@ namespace SourceGit.Views { tabs.OnTabEdited += (t) => { foreach (var tab in tabs.Tabs) { - if (!tab.IsWelcomePage) continue; + if (tab.IsRepository) continue; 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; foreach (var tab in tabs.Tabs) { - if (tab.IsWelcomePage) continue; + if (!tab.IsRepository) continue; // 仅支持恢复加入管理的仓库页,Submodules等未加入管理的不支持 var repo = Models.Preference.Instance.FindRepository(tab.Id); @@ -138,7 +138,7 @@ namespace SourceGit.Views { #region TAB_OPERATION private void OnTabAdding(object sender, Widgets.PageTabBar.TabEventArgs e) { 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); Controls.PopupWidget.RegisterContainer(e.TabId, page); } diff --git a/src/Views/Popups/Clone.xaml.cs b/src/Views/Popups/Clone.xaml.cs index 04b9d879..b88e58c8 100644 --- a/src/Views/Popups/Clone.xaml.cs +++ b/src/Views/Popups/Clone.xaml.cs @@ -66,7 +66,7 @@ namespace SourceGit.Views.Popups { } 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)); return true; }); diff --git a/src/Views/Popups/Init.xaml.cs b/src/Views/Popups/Init.xaml.cs index d89e5d4d..9f50aee6 100644 --- a/src/Views/Popups/Init.xaml.cs +++ b/src/Views/Popups/Init.xaml.cs @@ -24,7 +24,7 @@ namespace SourceGit.Views.Popups { if (!succ) return false; 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)); return true; }); diff --git a/src/Views/Widgets/PageTabBar.xaml b/src/Views/Widgets/PageTabBar.xaml index b6c2a173..31cbd511 100644 --- a/src/Views/Widgets/PageTabBar.xaml +++ b/src/Views/Widgets/PageTabBar.xaml @@ -5,6 +5,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="clr-namespace:SourceGit.Views.Controls" + xmlns:converters="clr-namespace:SourceGit.Views.Converters" mc:Ignorable="d" d:DesignHeight="28" d:DesignWidth="800"> @@ -48,6 +49,11 @@ ItemsSource="{Binding ElementName=me, Path=Tabs}" WindowChrome.IsHitTestVisibleInChrome="True" SelectionChanged="SelectionChanged"> + + + + + @@ -64,32 +70,37 @@ - - + + + + + + + + - - + HoverBackground="{DynamicResource Brush.NewPageHover}" + Visibility="Hidden" + HorizontalAlignment="Right"/> - + Fill="Transparent" + HorizontalAlignment="Right"/> + @@ -97,6 +108,7 @@ + @@ -107,6 +119,7 @@ + @@ -118,14 +131,16 @@ - - + WindowChrome.IsHitTestVisibleInChrome="True"> + + diff --git a/src/Views/Widgets/PageTabBar.xaml.cs b/src/Views/Widgets/PageTabBar.xaml.cs index a5f7004c..1b57e301 100644 --- a/src/Views/Widgets/PageTabBar.xaml.cs +++ b/src/Views/Widgets/PageTabBar.xaml.cs @@ -18,7 +18,7 @@ namespace SourceGit.Views.Widgets { /// public class Tab : Controls.BindableBase { public string Id { get; set; } - public bool IsWelcomePage { get; set; } + public bool IsRepository { get; set; } private string title; public string Title { @@ -108,7 +108,7 @@ namespace SourceGit.Views.Widgets { public void Add(string title, string repo, int bookmark) { var tab = new Tab() { Id = repo, - IsWelcomePage = false, + IsRepository = true, Title = title, Tooltip = repo, Bookmark = bookmark, @@ -137,7 +137,7 @@ namespace SourceGit.Views.Widgets { var replaced = new Tab() { Id = repo, - IsWelcomePage = false, + IsRepository = true, Title = title, Tooltip = repo, Bookmark = bookmark, @@ -207,7 +207,7 @@ namespace SourceGit.Views.Widgets { var id = Guid.NewGuid().ToString(); var tab = new Tab() { Id = id, - IsWelcomePage = true, + IsRepository = false, Title = App.Text("PageTabBar.Welcome.Title"), Tooltip = App.Text("PageTabBar.Welcome.Tip"), Bookmark = 0, @@ -322,14 +322,14 @@ namespace SourceGit.Views.Widgets { menu.Items.Add(closeOther); menu.Items.Add(closeRight); - if (!tab.IsWelcomePage) { + if (tab.IsRepository) { var iconBookmark = FindResource("Icon.Git") as Geometry; var bookmark = new MenuItem(); 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(); 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; var mark = new MenuItem(); diff --git a/src/Views/Widgets/Welcome.xaml b/src/Views/Widgets/Welcome.xaml index 906395e7..a951aca4 100644 --- a/src/Views/Widgets/Welcome.xaml +++ b/src/Views/Widgets/Welcome.xaml @@ -6,11 +6,13 @@ xmlns:controls="clr-namespace:SourceGit.Views.Controls" xmlns:widgets="clr-namespace:SourceGit.Views.Widgets" xmlns:models="clr-namespace:SourceGit.Models" + xmlns:converters="clr-namespace:SourceGit.Views.Converters" mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="800"> - + + @@ -18,14 +20,14 @@ - + - - - + + + + - - + + + - - - - - - - - + - - - - - - - + - - - - - - - - - - - - - - - - - + - + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + diff --git a/src/Views/Widgets/Welcome.xaml.cs b/src/Views/Widgets/Welcome.xaml.cs index dfddc654..6ee3a0b0 100644 --- a/src/Views/Widgets/Welcome.xaml.cs +++ b/src/Views/Widgets/Welcome.xaml.cs @@ -2,9 +2,9 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Input; using System.Windows.Media; @@ -16,46 +16,13 @@ namespace SourceGit.Views.Widgets { public partial class Welcome : UserControl, Controls.IPopupContainer { /// - /// 树节点数据 + /// 修改仓库标签颜色的回调 /// - public class Node : Controls.BindableBase { - 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 Children { get; set; } - } - - /// - /// 仓库节点编辑事件参数 - /// - public event Action OnNodeEdited; + public event Action OnBookmarkChanged; public Welcome() { InitializeComponent(); - UpdateTree(); - UpdateRecents(); + UpdateVisibles(); } #region POPUP_CONTAINER @@ -99,166 +66,84 @@ namespace SourceGit.Views.Widgets { if (MakeSureReady()) new Popups.Clone().Show(); } - private void OnRecentContextMenuOpening(object sender, ContextMenuEventArgs e) { - var repo = (sender as DataGridRow).DataContext as Models.Repository; - if (repo != null) { - var remove = new MenuItem(); - 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); + private void OnRemoveRepository(object sender, RoutedEventArgs e) { + var repo = (sender as Button).DataContext as Models.Repository; + Models.Preference.Instance.RemoveRepository(repo.Path); + UpdateVisibles(); e.Handled = true; } - private void OnRecentLostFocus(object sender, RoutedEventArgs e) { - list.UnselectAll(); + private void OnDoubleClickRepository(object sender, MouseButtonEventArgs e) { + 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; } - private void OnTreeLostFocus(object sender, RoutedEventArgs e) { - var child = FocusManager.GetFocusedElement(body); - if (child == null) return; + private void OnChangeRepositoryBookmark(object sender, RoutedEventArgs e) { + var btn = (sender as Button); + var repo = btn.DataContext as Models.Repository; - if (!tree.IsAncestorOf(child as UIElement)) tree.UnselectAll(); - e.Handled = true; - } + var menu = new ContextMenu(); + menu.Placement = PlacementMode.Bottom; + menu.PlacementTarget = btn; + menu.StaysOpen = false; + menu.Focusable = true; - private void OnTreeNodeStatusChange(object sender, RoutedEventArgs e) { - var node = (sender as Controls.TreeItem).DataContext as Node; - if (node != null) { - var group = Models.Preference.Instance.FindGroup(node.Id); - group.IsExpanded = node.IsExpanded; - e.Handled = true; - } - } + for (int i = 0; i < Converters.IntToBookmarkBrush.COLORS.Length; i++) { + var icon = new System.Windows.Shapes.Path(); + icon.Data = new EllipseGeometry(new Point(0, 0), 8, 8); + icon.Fill = i == 0 ? (FindResource("Brush.FG1") as Brush) : Converters.IntToBookmarkBrush.COLORS[i]; + icon.Width = 12; - private void OnTreeNodeDoubleClick(object sender, MouseButtonEventArgs e) { - var node = (sender as Controls.TreeItem).DataContext as Node; - if (node != null && !node.IsGroup) { - CheckAndOpen(node.Id); - e.Handled = true; - } - } + var mark = new MenuItem(); + mark.Icon = icon; + mark.Header = $"{i}"; - private void OnTreeContextMenuOpening(object sender, ContextMenuEventArgs e) { - var item = tree.FindItem(e.OriginalSource as DependencyObject); - if (item == null) { - var addFolder = new MenuItem(); - addFolder.Header = App.Text("Welcome.NewFolder"); - addFolder.Click += (o, ev) => { - 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); + var refIdx = i; + mark.Click += (o, ev) => { + if (repo != null) { + repo.Bookmark = refIdx; + UpdateVisibles(); + OnBookmarkChanged?.Invoke(repo); } - - 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; }; - var delete = new MenuItem(); - 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; + menu.Items.Add(mark); } + + 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 - #region DRAP_DROP_EVENTS + #region DRAG_DROP 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; } } @@ -271,41 +156,10 @@ namespace SourceGit.Views.Widgets { dropArea.Visibility = Visibility.Hidden; } - private void OnTreeMouseMove(object sender, MouseEventArgs 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) { + private void OnDropFolder(object sender, DragEventArgs e) { bool rebuild = false; 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 (!MakeSureReady()) return; @@ -314,118 +168,33 @@ namespace SourceGit.Views.Widgets { var dir = new Commands.QueryGitDir(path).Result(); if (dir != null) { var root = new Commands.GetRepositoryRootPath(path).Result(); - Models.Preference.Instance.AddRepository(root, dir, parent); + Models.Preference.Instance.AddRepository(root, dir); 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(); - e.Handled = true; + if (rebuild) UpdateVisibles(); } #endregion #region DATA - private void UpdateRecents() { - var repos = new List(); - var dirty = new List(); + public void UpdateVisibles() { + var visibles = new List(); + var curFilter = filter.Text.ToLower(); - foreach (var path in Models.Preference.Instance.Recents) { - var repo = Models.Preference.Instance.FindRepository(path); - if (repo != null) { - repos.Add(repo); - } else { - dirty.Add(path); + if (string.IsNullOrEmpty(curFilter)) { + visibles.AddRange(Models.Preference.Instance.Repositories); + } else { + foreach (var repo in Models.Preference.Instance.Repositories) { + if (repo.Name.ToLower().Contains(curFilter, StringComparison.Ordinal) || + repo.Path.ToLower().Contains(curFilter, StringComparison.Ordinal)) { + visibles.Add(repo); + } } } - foreach (var path in dirty) Models.Preference.Instance.RemoveRecent(path); - 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(); - var nodes = new List(); - - 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(), - }; - - 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(), - }; - - 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(); + repoList.ItemsSource = visibles; } private bool MakeSureReady() { @@ -451,68 +220,9 @@ namespace SourceGit.Views.Widgets { } 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.Preference.Instance.AddRecent(repo.Path); - } - - public void UpdateNodes(string id, int bookmark, IEnumerable nodes = null) { - if (nodes == null) nodes = tree.ItemsSource.OfType(); - 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; - } + UpdateVisibles(); } #endregion }