diff --git a/src/Resources/Icons.xaml b/src/Resources/Icons.xaml
index 2774df12..2389a263 100644
--- a/src/Resources/Icons.xaml
+++ b/src/Resources/Icons.xaml
@@ -53,15 +53,14 @@
M1024 896v128H0V704h128v192h768V704h128v192zM576 555 811 320 896 405l-384 384-384-384L213 320 448 555V0h128v555z
M432 0h160c27 0 48 21 48 48v336h175c36 0 53 43 28 68L539 757c-15 15-40 15-55 0L180 452c-25-25-7-68 28-68H384V48c0-27 21-48 48-48zm592 752v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h293l98 98c40 40 105 40 145 0l98-98H976c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z
M592 768h-160c-27 0-48-21-48-48V384h-175c-36 0-53-43-28-68L485 11c15-15 40-15 55 0l304 304c25 25 7 68-28 68H640v336c0 27-21 48-48 48zm432-16v224c0 27-21 48-48 48H48c-27 0-48-21-48-48V752c0-27 21-48 48-48h272v16c0 62 50 112 112 112h160c62 0 112-50 112-112v-16h272c27 0 48 21 48 48zm-248 176c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40zm128 0c0-22-18-40-40-40s-40 18-40 40s18 40 40 40s40-18 40-40z
- M961 320 512 577 63 320 512 62l449 258zM512 628 185 442 63 512 512 770 961 512l-123-70L512 628zM512 821 185 634 63 704 512 962l449-258L839 634 512 821z
- M154 256h410v51H154zM154 563h154v51H154zM154 410h307v51H154zM154 973H51V51h819v102l51 51V0H0v1024h154v-51zM870 666v307H563l-51 51h410V614l-51 51zM819 205 205 819v205h205l614-614zM256 973v-102l102 102zm563-461-102-102 51-51 102 102z
+ M961 320 512 577 63 320 512 62l449 258zM512 628 185 442 63 512 512 770 961 512l-123-70L512 628zM512 821 185 634 63 704 512 962l449-258L839 634 512 821z
M144 112h736c18 0 32 14 32 32v736c0 18-14 32-32 32H144c-18 0-32-14-32-32V144c0-18 14-32 32-32zm112 211v72a9 9 0 003 7L386 509 259 615a9 9 0 00-3 7v72a9 9 0 0015 7L493 516a9 9 0 000-14l-222-186a9 9 0 00-15 7zM522 624a10 10 0 00-10 10v60a10 10 0 0010 10h237a10 10 0 0010-10v-60a10 10 0 00-10-10H522z
M509 556l93 149h124l-80-79 49-50 165 164-165 163-49-50 79-79h-163l-96-153 41-65zm187-395 165 164-165 163-49-50L726 360H530l-136 224H140v-70h215l136-224h236l-80-79 49-50z
M796 471A292 292 0 00512 256a293 293 0 00-284 215H0v144h228A293 293 0 00512 832a291 291 0 00284-217H1024V471h-228M512 688A146 146 0 01366 544A145 145 0 01512 400c80 0 146 63 146 144A146 146 0 01512 688
M0 586l404 119 498-410-386 441-2 251 155-205 279 83L1170 37z
M24 512A488 488 0 01512 24A488 488 0 011000 512A488 488 0 01512 1000A488 488 0 0124 512zm447-325v327L243 619l51 111 300-138V187H471z
- M715 254h-405l-58 57h520zm-492 86v201h578V340zm405 143h-29v-29H425v29h-29v-57h231v57zm-405 295h578V559H223zm174-133h231v57h-29v-29H425v29h-29v-57z
+ M715 254h-405l-58 57h520zm-492 86v201h578V340zm405 143h-29v-29H425v29h-29v-57h231v57zm-405 295h578V559H223zm174-133h231v57h-29v-29H425v29h-29v-57z
M869 145a145 145 0 10-289 0c0 56 33 107 83 131c-5 96-77 128-201 175c-52 20-110 42-160 74V276A144 144 0 00242 0a145 145 0 00-145 145c0 58 35 108 84 131v461a144 144 0 00-84 131a145 145 0 10289 0a144 144 0 00-84-131c5-95 77-128 201-175c122-46 274-103 280-287a145 145 0 0085-132zM242 61a83 83 0 110 167a83 83 0 010-167zm0 891a84 84 0 110-167a84 84 0 010 167zM724 228a84 84 0 110-167a84 84 0 010 167z
M896 128h-64V64c0-35-29-64-64-64s-64 29-64 64v64h-64c-35 0-64 29-64 64s29 64 64 64h64v64c0 35 29 64 64 64s64-29 64-64V256h64c35 0 64-29 64-64s-29-64-64-64zm-204 307C673 481 628 512 576 512H448c-47 0-90 13-128 35V372C394 346 448 275 448 192c0-106-86-192-192-192S64 86 64 192c0 83 54 154 128 180v280c-74 26-128 97-128 180c0 106 86 192 192 192s192-86 192-192c0-67-34-125-84-159c22-20 52-33 84-33h128c122 0 223-85 249-199c-19 4-37 7-57 7c-26 0-51-5-76-13zM256 128c35 0 64 29 64 64s-29 64-64 64s-64-29-64-64s29-64 64-64zm0 768c-35 0-64-29-64-64s29-64 64-64s64 29 64 64s-29 64-64 64z
M902 479v-1c0-133-112-242-250-242c-106 0-196 64-232 154c-28-20-62-32-100-32c-76 0-140 49-160 116c-52 37-86 97-86 165c0 112 90 202 202 202h503c112 0 202-90 202-202c0-65-31-123-79-160z
diff --git a/src/Views/Widgets/Dashboard.xaml b/src/Views/Widgets/Dashboard.xaml
index 9a8a8c5d..f514df04 100644
--- a/src/Views/Widgets/Dashboard.xaml
+++ b/src/Views/Widgets/Dashboard.xaml
@@ -1,576 +1,576 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Views/Widgets/Dashboard.xaml.cs b/src/Views/Widgets/Dashboard.xaml.cs
index a791b2cf..648e30e2 100644
--- a/src/Views/Widgets/Dashboard.xaml.cs
+++ b/src/Views/Widgets/Dashboard.xaml.cs
@@ -671,14 +671,22 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var createBranchIcon = new System.Windows.Shapes.Path();
+ createBranchIcon.Data = FindResource("Icon.Branch.Add") as Geometry;
+ createBranchIcon.Width = 10;
var createBranch = new MenuItem();
+ createBranch.Icon = createBranchIcon;
createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, e) => {
new Popups.CreateBranch(repo, branch).Show();
e.Handled = true;
};
+ var createTagIcon = new System.Windows.Shapes.Path();
+ createTagIcon.Data = FindResource("Icon.Tag.Add") as Geometry;
+ createTagIcon.Width = 10;
var createTag = new MenuItem();
+ createTag.Icon = createTagIcon;
createTag.Header = App.Text("CreateTag");
createTag.Click += (o, e) => {
new Popups.CreateTag(repo, branch).Show();
@@ -735,7 +743,11 @@ namespace SourceGit.Views.Widgets {
menu.Items.Add(tracking);
}
+ var archiveIcon = new System.Windows.Shapes.Path();
+ archiveIcon.Data = FindResource("Icon.Archive") as Geometry;
+ archiveIcon.Width = 10;
var archive = new MenuItem();
+ archive.Icon = archiveIcon;
archive.Header = App.Text("Archive");
archive.Click += (o, e) => {
new Popups.Archive(repo.Path, branch).Show();
@@ -858,21 +870,33 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var createBranchIcon = new System.Windows.Shapes.Path();
+ createBranchIcon.Data = FindResource("Icon.Branch.Add") as Geometry;
+ createBranchIcon.Width = 10;
var createBranch = new MenuItem();
+ createBranch.Icon = createBranchIcon;
createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, e) => {
new Popups.CreateBranch(repo, branch).Show();
e.Handled = true;
};
+ var createTagIcon = new System.Windows.Shapes.Path();
+ createTagIcon.Data = FindResource("Icon.Tag.Add") as Geometry;
+ createTagIcon.Width = 10;
var createTag = new MenuItem();
+ createTag.Icon = createTagIcon;
createTag.Header = App.Text("CreateTag");
createTag.Click += (o, e) => {
new Popups.CreateTag(repo, branch).Show();
e.Handled = true;
};
+ var archiveIcon = new System.Windows.Shapes.Path();
+ archiveIcon.Data = FindResource("Icon.Archive") as Geometry;
+ archiveIcon.Width = 10;
var archive = new MenuItem();
+ archive.Icon = archiveIcon;
archive.Header = App.Text("Archive");
archive.Click += (o, e) => {
new Popups.Archive(repo.Path, branch).Show();
@@ -916,7 +940,11 @@ namespace SourceGit.Views.Widgets {
var tag = tagList.SelectedItem as Models.Tag;
if (tag == null) return;
+ var createBranchIcon = new System.Windows.Shapes.Path();
+ createBranchIcon.Data = FindResource("Icon.Branch.Add") as Geometry;
+ createBranchIcon.Width = 10;
var createBranch = new MenuItem();
+ createBranch.Icon = createBranchIcon;
createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, ev) => {
new Popups.CreateBranch(repo, tag).Show();
@@ -938,7 +966,11 @@ namespace SourceGit.Views.Widgets {
ev.Handled = true;
};
+ var archiveIcon = new System.Windows.Shapes.Path();
+ archiveIcon.Data = FindResource("Icon.Archive") as Geometry;
+ archiveIcon.Width = 10;
var archive = new MenuItem();
+ archive.Icon = archiveIcon;
archive.Header = App.Text("Archive");
archive.Click += (o, ev) => {
new Popups.Archive(repo.Path, tag).Show();
diff --git a/src/Views/Widgets/Histories.xaml.cs b/src/Views/Widgets/Histories.xaml.cs
index d1b51a1c..ac923ae7 100644
--- a/src/Views/Widgets/Histories.xaml.cs
+++ b/src/Views/Widgets/Histories.xaml.cs
@@ -1,626 +1,642 @@
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Animation;
-using System.Windows.Shapes;
-
-namespace SourceGit.Views.Widgets {
- ///
- /// 历史记录
- ///
- public partial class Histories : UserControl {
- private Models.Repository repo = null;
- private List cachedCommits = new List();
- private bool searching = false;
-
- public Histories(Models.Repository repo) {
- this.repo = repo;
-
- InitializeComponent();
- ChangeOrientation();
-
- Unloaded += (o, e) => {
- cachedCommits.Clear();
- commitList.ItemsSource = cachedCommits;
- graph.SetData(cachedCommits, false);
- };
- }
-
- #region DATA
- public void NavigateTo(string commit) {
- if (string.IsNullOrEmpty(commit) || commitList == null || commitList.ItemsSource == null) return;
-
- foreach (var item in commitList.ItemsSource) {
- var c = item as Models.Commit;
- if (c != null && c.SHA.StartsWith(commit, StringComparison.Ordinal)) {
- commitList.SelectedItem = c;
- commitList.ScrollIntoView(c);
- break;
- }
- }
- }
-
- public void UpdateCommits() {
- Dispatcher.Invoke(() => {
- loading.Visibility = Visibility.Visible;
- loading.IsAnimating = true;
- });
-
- Task.Run(() => {
- var limits = "-20000 ";
- if (repo.Filters.Count > 0) {
- limits += string.Join(" ", repo.Filters);
- } else {
- limits += "--branches --remotes --tags";
- }
-
- cachedCommits = new Commands.Commits(repo.Path, limits).Result();
- UpdateVisibleCommits();
- });
- }
-
- private void UpdateVisibleCommits(string filter = null) {
- var visible = new List();
- searching = false;
-
- if (string.IsNullOrEmpty(filter)) {
- visible = cachedCommits;
- } else {
- searching = true;
- foreach (var c in cachedCommits) {
-#if NET48
- if (c.SHA.Contains(filter)
- || c.Subject.Contains(filter)
- || c.Message.Contains(filter)
- || c.Author.Name.Contains(filter)
- || c.Committer.Name.Contains(filter)) {
- visible.Add(c);
- }
-#else
- if (c.SHA.Contains(filter, StringComparison.Ordinal)
- || c.Subject.Contains(filter, StringComparison.Ordinal)
- || c.Message.Contains(filter, StringComparison.Ordinal)
- || c.Author.Name.Contains(filter, StringComparison.Ordinal)
- || c.Committer.Name.Contains(filter, StringComparison.Ordinal)) {
- visible.Add(c);
- }
-#endif
- }
- }
-
- graph.SetData(visible, searching);
-
- Dispatcher.Invoke(() => {
- loading.IsAnimating = false;
- loading.Visibility = Visibility.Collapsed;
- commitList.ItemsSource = visible;
- });
- }
- #endregion
-
- #region LAYOUT
- public void ChangeOrientation() {
- if (layout == null || commitListPanel == null || inspector == null || splitter == null) return;
-
- layout.RowDefinitions.Clear();
- layout.ColumnDefinitions.Clear();
-
- if (Models.Preference.Instance.Window.MoveCommitInfoRight) {
- layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });
- layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1) });
- layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });
-
- splitter.HorizontalAlignment = HorizontalAlignment.Center;
- splitter.VerticalAlignment = VerticalAlignment.Stretch;
- splitter.Width = 1;
- splitter.Height = double.NaN;
-
- Grid.SetRow(commitListPanel, 0);
- Grid.SetRow(splitter, 0);
- Grid.SetRow(inspector, 0);
- Grid.SetColumn(commitListPanel, 0);
- Grid.SetColumn(splitter, 1);
- Grid.SetColumn(inspector, 2);
- } else {
- layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), MinHeight = 100 });
- layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1) });
- layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), MinHeight = 100 });
-
- splitter.HorizontalAlignment = HorizontalAlignment.Stretch;
- splitter.VerticalAlignment = VerticalAlignment.Center;
- splitter.Width = double.NaN;
- splitter.Height = 1;
-
- Grid.SetRow(commitListPanel, 0);
- Grid.SetRow(splitter, 1);
- Grid.SetRow(inspector, 2);
- Grid.SetColumn(commitListPanel, 0);
- Grid.SetColumn(splitter, 0);
- Grid.SetColumn(inspector, 0);
- }
-
- layout.InvalidateArrange();
- }
- #endregion
-
- #region SEARCH_BAR
- public void ToggleSearch() {
- if (searchBar.Margin.Top == 0) {
- if (searchBar.Margin.Top != 0) return;
-
- if (searching) {
- loading.Visibility = Visibility.Visible;
- loading.IsAnimating = true;
- txtSearch.Text = "";
- Task.Run(() => UpdateVisibleCommits());
- }
-
- ThicknessAnimation anim = new ThicknessAnimation();
- anim.From = new Thickness(0);
- anim.To = new Thickness(0, -32, 0, 0);
- anim.Duration = TimeSpan.FromSeconds(.1);
- searchBar.BeginAnimation(MarginProperty, anim);
- } else {
- ThicknessAnimation anim = new ThicknessAnimation();
- anim.From = new Thickness(0, -32, 0, 0);
- anim.To = new Thickness(0);
- anim.Duration = TimeSpan.FromSeconds(.1);
- searchBar.BeginAnimation(MarginProperty, anim);
-
- txtSearch.Focus();
- }
- }
-
- private void ClearSearch(object sender, RoutedEventArgs e) {
- txtSearch.Text = "";
- }
-
- private void HideSearch(object sender, RoutedEventArgs e) {
- if (searching) {
- loading.Visibility = Visibility.Visible;
- loading.IsAnimating = true;
- txtSearch.Text = "";
- Task.Run(() => UpdateVisibleCommits());
- }
-
- ThicknessAnimation anim = new ThicknessAnimation();
- anim.From = new Thickness(0);
- anim.To = new Thickness(0, -32, 0, 0);
- anim.Duration = TimeSpan.FromSeconds(.1);
- searchBar.BeginAnimation(MarginProperty, anim);
- }
-
- private void OnSearchPreviewKeyDown(object sender, KeyEventArgs e) {
- if (e.Key == Key.Enter) {
- loading.Visibility = Visibility.Visible;
- loading.IsAnimating = true;
-
- var filter = txtSearch.Text;
- Task.Run(() => UpdateVisibleCommits(filter));
- } else if (e.Key == Key.Escape) {
- ToggleSearch();
- }
- }
- #endregion
-
- #region COMMIT_LIST
- private void OnCommitListScrolled(object sender, ScrollChangedEventArgs e) {
- graph.SetOffset(e.VerticalOffset * commitList.RowHeight);
- }
-
- private void OnCommitListKeyUp(object sender, KeyEventArgs e) {
- if (e.Key == Key.Up || e.Key == Key.Down) {
- OnCommitSelectionChanged(sender, null);
- e.Handled = true;
- }
- }
-
- private void OnCommitSelectionChanged(object sender, SelectionChangedEventArgs e) {
- if (Keyboard.IsKeyDown(Key.Up) || Keyboard.IsKeyDown(Key.Down)) return;
-
- mask.Visibility = Visibility.Collapsed;
- commitDetail.Visibility = Visibility.Collapsed;
- revisionCompare.Visibility = Visibility.Collapsed;
-
- var selected = commitList.SelectedItems;
- if (selected.Count == 1) {
- commitDetail.SetData(repo.Path, selected[0] as Models.Commit);
- commitDetail.Visibility = Visibility.Visible;
- } else if (selected.Count == 2) {
- revisionCompare.SetData(repo.Path, selected[0] as Models.Commit, selected[1] as Models.Commit);
- revisionCompare.Visibility = Visibility.Visible;
- } else if (selected.Count > 2) {
- mask.Visibility = Visibility.Visible;
- txtCounter.Text = App.Text("Histories.Selected", selected.Count);
- } else {
- mask.Visibility = Visibility.Visible;
- txtCounter.Text = App.Text("Histories.Guide");
- }
- }
-
- private void OnCommitContextMenuOpening(object sender, ContextMenuEventArgs ev) {
- var row = sender as DataGridRow;
- if (row == null) return;
-
- var commit = row.DataContext as Models.Commit;
- if (commit == null) return;
-
- commitList.SelectedItem = commit;
-
- var current = repo.Branches.Find(x => x.IsCurrent);
- if (current == null) return;
-
- var merged = commit.IsMerged;
- var menu = new ContextMenu();
- var tags = new List();
-
- // Decorators
- if (commit.HasDecorators) {
- foreach (var d in commit.Decorators) {
- if (d.Type == Models.DecoratorType.CurrentBranchHead) {
- FillCurrentBranchMenu(menu, current);
- } else if (d.Type == Models.DecoratorType.LocalBranchHead) {
- FillOtherLocalBranchMenu(menu, repo.Branches.Find(x => x.IsLocal && x.Name == d.Name), current, merged);
- } else if (d.Type == Models.DecoratorType.RemoteBranchHead) {
- FillRemoteBranchMenu(menu, repo.Branches.Find(x => !x.IsLocal && d.Name == $"{x.Remote}/{x.Name}"), current, merged);
- } else if (d.Type == Models.DecoratorType.Tag) {
- tags.Add(d.Name);
- }
- }
-
- if (menu.Items.Count > 0) menu.Items.Add(new Separator());
- }
-
- // Tags
- if (tags.Count > 0) {
- foreach (var tag in tags) FillTagMenu(menu, tag);
- menu.Items.Add(new Separator());
- }
-
- if (current.Head != commit.SHA) {
- var reset = new MenuItem();
- reset.Header = App.Text("CommitCM.Reset", current.Name);
- reset.Click += (o, e) => {
- new Popups.Reset(repo.Path, current.Name, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(reset);
- } else {
- var reword = new MenuItem();
- reword.Header = App.Text("CommitCM.Reword");
- reword.Click += (o, e) => {
- new Popups.Reword(repo.Path, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(reword);
-
- var squash = new MenuItem();
- squash.Header = App.Text("CommitCM.Squash");
- squash.IsEnabled = commit.Parents.Count == 1;
- squash.Click += (o, e) => {
- foreach (var c in cachedCommits) {
- if (c.SHA == commit.Parents[0]) {
- new Popups.Squash(repo.Path, commit, c).Show();
- e.Handled = true;
- return;
- }
- }
-
- Models.Exception.Raise("Can NOT found parent of HEAD!");
- e.Handled = true;
- };
- menu.Items.Add(squash);
- }
-
- if (!merged) {
- var rebase = new MenuItem();
- rebase.Header = App.Text("CommitCM.Rebase", current.Name);
- rebase.Click += (o, e) => {
- new Popups.Rebase(repo.Path, current.Name, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(rebase);
-
- var cherryPick = new MenuItem();
- cherryPick.Header = App.Text("CommitCM.CherryPick");
- cherryPick.Click += (o, e) => {
- new Popups.CherryPick(repo.Path, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(cherryPick);
- } else {
- var revert = new MenuItem();
- revert.Header = App.Text("CommitCM.Revert");
- revert.Click += (o, e) => {
- new Popups.Revert(repo.Path, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(revert);
- }
-
- menu.Items.Add(new Separator());
-
- var createBranch = new MenuItem();
- createBranch.Header = App.Text("CreateBranch");
- createBranch.Click += (o, e) => {
- new Popups.CreateBranch(repo, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(createBranch);
-
- var createTag = new MenuItem();
- createTag.Header = App.Text("CreateTag");
- createTag.Click += (o, e) => {
- new Popups.CreateTag(repo, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(createTag);
- menu.Items.Add(new Separator());
-
- var saveToPatch = new MenuItem();
- saveToPatch.Header = App.Text("CommitCM.SaveAsPatch");
- saveToPatch.Click += (o, e) => {
- var dialog = new Controls.FolderDialog();
- if (dialog.ShowDialog() == true) {
- new Commands.FormatPatch(repo.Path, commit.SHA, dialog.SelectedPath).Exec();
- }
- };
- menu.Items.Add(saveToPatch);
-
- var archive = new MenuItem();
- archive.Header = App.Text("Archive");
- archive.Click += (o, e) => {
- new Popups.Archive(repo.Path, commit).Show();
- e.Handled = true;
- };
- menu.Items.Add(archive);
- menu.Items.Add(new Separator());
-
- var copySHA = new MenuItem();
- copySHA.Header = App.Text("CommitCM.CopySHA");
- copySHA.Click += (o, e) => {
- Clipboard.SetDataObject(commit.SHA, true);
- e.Handled = true;
- };
- menu.Items.Add(copySHA);
-
- var copyInfo = new MenuItem();
- copyInfo.Header = App.Text("CommitCM.CopyInfo");
- copyInfo.Click += (o, e) => {
- Clipboard.SetDataObject(string.Format(
- "SHA: {0}\nTITLE: {1}\nAUTHOR: {2} <{3}>\nTIME: {4}",
- commit.SHA, commit.Subject, commit.Committer.Name, commit.Committer.Email, commit.Committer.Time), true);
- };
- menu.Items.Add(copyInfo);
-
- menu.IsOpen = true;
- ev.Handled = true;
- }
-
- private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current) {
- var icon = new Path();
- icon.Data = FindResource("Icon.Branch") as Geometry;
- icon.VerticalAlignment = VerticalAlignment.Bottom;
- icon.Width = 10;
- icon.Height = 10;
-
- var dirty = !string.IsNullOrEmpty(current.UpstreamTrackStatus);
- var submenu = new MenuItem();
- submenu.Header = current.Name;
- submenu.Icon = icon;
-
- if (!string.IsNullOrEmpty(current.Upstream)) {
- var upstream = current.Upstream.Substring(13);
-
- var fastForward = new MenuItem();
- fastForward.Header = App.Text("BranchCM.FastForward", upstream);
- fastForward.IsEnabled = dirty;
- fastForward.Click += (o, e) => {
- new Popups.Merge(repo.Path, upstream, current.Name).ShowAndStart();
- e.Handled = true;
- };
- submenu.Items.Add(fastForward);
-
- var pull = new MenuItem();
- pull.Header = App.Text("BranchCM.Pull", upstream);
- pull.IsEnabled = dirty;
- pull.Click += (o, e) => {
- new Popups.Pull(repo, null).Show();
- e.Handled = true;
- };
- submenu.Items.Add(pull);
- }
-
- var push = new MenuItem();
- push.Header = App.Text("BranchCM.Push", current.Name);
- push.IsEnabled = repo.Remotes.Count > 0 && dirty;
- push.Click += (o, e) => {
- new Popups.Push(repo, current).Show();
- e.Handled = true;
- };
- submenu.Items.Add(push);
- submenu.Items.Add(new Separator());
-
- var type = repo.GitFlow.GetBranchType(current.Name);
- if (type != Models.GitFlowBranchType.None) {
- var flowIcon = new Path();
- flowIcon.Data = FindResource("Icon.Flow") as Geometry;
- flowIcon.Width = 10;
- flowIcon.Height = 10;
-
- var finish = new MenuItem();
- finish.Header = App.Text("BranchCM.Finish", current.Name);
- finish.Icon = flowIcon;
- finish.Click += (o, e) => {
- new Popups.GitFlowFinish(repo, current.Name, type).Show();
- e.Handled = true;
- };
- submenu.Items.Add(finish);
- submenu.Items.Add(new Separator());
- }
-
- var rename = new MenuItem();
- rename.Header = App.Text("BranchCM.Rename", current.Name);
- rename.Click += (o, e) => {
- new Popups.RenameBranch(repo, current.Name).Show();
- e.Handled = true;
- };
- submenu.Items.Add(rename);
-
- menu.Items.Add(submenu);
- }
-
- private void FillOtherLocalBranchMenu(ContextMenu menu, Models.Branch branch, Models.Branch current, bool merged) {
- var icon = new Path();
- icon.Data = FindResource("Icon.Branch") as Geometry;
- icon.VerticalAlignment = VerticalAlignment.Bottom;
- icon.Width = 10;
- icon.Height = 10;
-
- var submenu = new MenuItem();
- submenu.Header = branch.Name;
- submenu.Icon = icon;
-
- var checkout = new MenuItem();
- checkout.Header = App.Text("BranchCM.Checkout", branch.Name);
- checkout.Click += (o, e) => {
- new Popups.Checkout(repo.Path, branch.Name).ShowAndStart();
- e.Handled = true;
- };
- submenu.Items.Add(checkout);
-
- var merge = new MenuItem();
- merge.Header = App.Text("BranchCM.Merge", branch.Name, current.Name);
- merge.IsEnabled = !merged;
- merge.Click += (o, e) => {
- new Popups.Merge(repo.Path, branch.Name, current.Name).Show();
- e.Handled = true;
- };
-
- submenu.Items.Add(merge);
- submenu.Items.Add(new Separator());
-
- var type = repo.GitFlow.GetBranchType(branch.Name);
- if (type != Models.GitFlowBranchType.None) {
- var flowIcon = new Path();
- flowIcon.Data = FindResource("Icon.Flow") as Geometry;
- flowIcon.Width = 10;
- flowIcon.Height = 10;
-
- var finish = new MenuItem();
- finish.Header = App.Text("BranchCM.Finish", branch.Name);
- finish.Icon = flowIcon;
- finish.Click += (o, e) => {
- new Popups.GitFlowFinish(repo, branch.Name, type).Show();
- e.Handled = true;
- };
- submenu.Items.Add(finish);
- submenu.Items.Add(new Separator());
- }
-
- var rename = new MenuItem();
- rename.Header = App.Text("BranchCM.Rename", branch.Name);
- rename.Click += (o, e) => {
- new Popups.RenameBranch(repo, branch.Name).Show();
- e.Handled = true;
- };
- submenu.Items.Add(rename);
-
- var delete = new MenuItem();
- delete.Header = App.Text("BranchCM.Delete", branch.Name);
- delete.Click += (o, e) => {
- new Popups.DeleteBranch(repo.Path, branch.Name).Show();
- e.Handled = true;
- };
- submenu.Items.Add(delete);
-
- menu.Items.Add(submenu);
- }
-
- private void FillRemoteBranchMenu(ContextMenu menu, Models.Branch branch, Models.Branch current, bool merged) {
- var name = $"{branch.Remote}/{branch.Name}";
-
- var icon = new Path();
- icon.Data = FindResource("Icon.Branch") as Geometry;
- icon.VerticalAlignment = VerticalAlignment.Bottom;
- icon.Width = 10;
- icon.Height = 10;
-
- var submenu = new MenuItem();
- submenu.Header = name;
- submenu.Icon = icon;
-
- var checkout = new MenuItem();
- checkout.Header = App.Text("BranchCM.Checkout", name);
- checkout.Click += (o, e) => {
- foreach (var b in repo.Branches) {
- if (b.IsLocal && b.Upstream == branch.FullName) {
- if (b.IsCurrent) return;
- new Popups.Checkout(repo.Path, b.Name).ShowAndStart();
- return;
- }
- }
-
- new Popups.CreateBranch(repo, branch).Show();
- e.Handled = true;
- };
- submenu.Items.Add(checkout);
-
- var merge = new MenuItem();
- merge.Header = App.Text("BranchCM.Merge", name, current.Name);
- merge.IsEnabled = !merged;
- merge.Click += (o, e) => {
- new Popups.Merge(repo.Path, name, current.Name).Show();
- e.Handled = true;
- };
-
- submenu.Items.Add(merge);
- submenu.Items.Add(new Separator());
-
- var delete = new MenuItem();
- delete.Header = App.Text("BranchCM.Delete", name);
- delete.Click += (o, e) => {
- new Popups.DeleteBranch(repo.Path, branch.Name, branch.Remote).Show();
- e.Handled = true;
- };
- submenu.Items.Add(delete);
-
- menu.Items.Add(submenu);
- }
-
- private void FillTagMenu(ContextMenu menu, string tag) {
- var icon = new Path();
- icon.Data = FindResource("Icon.Tag") as Geometry;
- icon.Width = 10;
- icon.Height = 10;
-
- var submenu = new MenuItem();
- submenu.Header = tag;
- submenu.Icon = icon;
- submenu.MinWidth = 200;
-
- var push = new MenuItem();
- push.Header = App.Text("TagCM.Push", tag);
- push.IsEnabled = repo.Remotes.Count > 0;
- push.Click += (o, e) => {
- new Popups.PushTag(repo, tag).Show();
- e.Handled = true;
- };
- submenu.Items.Add(push);
-
- var delete = new MenuItem();
- delete.Header = App.Text("TagCM.Delete", tag);
- delete.Click += (o, e) => {
- new Popups.DeleteTag(repo.Path, tag).Show();
- e.Handled = true;
- };
- submenu.Items.Add(delete);
- menu.Items.Add(submenu);
- }
- #endregion
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Shapes;
+
+namespace SourceGit.Views.Widgets {
+ ///
+ /// 历史记录
+ ///
+ public partial class Histories : UserControl {
+ private Models.Repository repo = null;
+ private List cachedCommits = new List();
+ private bool searching = false;
+
+ public Histories(Models.Repository repo) {
+ this.repo = repo;
+
+ InitializeComponent();
+ ChangeOrientation();
+
+ Unloaded += (o, e) => {
+ cachedCommits.Clear();
+ commitList.ItemsSource = cachedCommits;
+ graph.SetData(cachedCommits, false);
+ };
+ }
+
+ #region DATA
+ public void NavigateTo(string commit) {
+ if (string.IsNullOrEmpty(commit) || commitList == null || commitList.ItemsSource == null) return;
+
+ foreach (var item in commitList.ItemsSource) {
+ var c = item as Models.Commit;
+ if (c != null && c.SHA.StartsWith(commit, StringComparison.Ordinal)) {
+ commitList.SelectedItem = c;
+ commitList.ScrollIntoView(c);
+ break;
+ }
+ }
+ }
+
+ public void UpdateCommits() {
+ Dispatcher.Invoke(() => {
+ loading.Visibility = Visibility.Visible;
+ loading.IsAnimating = true;
+ });
+
+ Task.Run(() => {
+ var limits = "-20000 ";
+ if (repo.Filters.Count > 0) {
+ limits += string.Join(" ", repo.Filters);
+ } else {
+ limits += "--branches --remotes --tags";
+ }
+
+ cachedCommits = new Commands.Commits(repo.Path, limits).Result();
+ UpdateVisibleCommits();
+ });
+ }
+
+ private void UpdateVisibleCommits(string filter = null) {
+ var visible = new List();
+ searching = false;
+
+ if (string.IsNullOrEmpty(filter)) {
+ visible = cachedCommits;
+ } else {
+ searching = true;
+ foreach (var c in cachedCommits) {
+#if NET48
+ if (c.SHA.Contains(filter)
+ || c.Subject.Contains(filter)
+ || c.Message.Contains(filter)
+ || c.Author.Name.Contains(filter)
+ || c.Committer.Name.Contains(filter)) {
+ visible.Add(c);
+ }
+#else
+ if (c.SHA.Contains(filter, StringComparison.Ordinal)
+ || c.Subject.Contains(filter, StringComparison.Ordinal)
+ || c.Message.Contains(filter, StringComparison.Ordinal)
+ || c.Author.Name.Contains(filter, StringComparison.Ordinal)
+ || c.Committer.Name.Contains(filter, StringComparison.Ordinal)) {
+ visible.Add(c);
+ }
+#endif
+ }
+ }
+
+ graph.SetData(visible, searching);
+
+ Dispatcher.Invoke(() => {
+ loading.IsAnimating = false;
+ loading.Visibility = Visibility.Collapsed;
+ commitList.ItemsSource = visible;
+ });
+ }
+ #endregion
+
+ #region LAYOUT
+ public void ChangeOrientation() {
+ if (layout == null || commitListPanel == null || inspector == null || splitter == null) return;
+
+ layout.RowDefinitions.Clear();
+ layout.ColumnDefinitions.Clear();
+
+ if (Models.Preference.Instance.Window.MoveCommitInfoRight) {
+ layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });
+ layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1) });
+ layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });
+
+ splitter.HorizontalAlignment = HorizontalAlignment.Center;
+ splitter.VerticalAlignment = VerticalAlignment.Stretch;
+ splitter.Width = 1;
+ splitter.Height = double.NaN;
+
+ Grid.SetRow(commitListPanel, 0);
+ Grid.SetRow(splitter, 0);
+ Grid.SetRow(inspector, 0);
+ Grid.SetColumn(commitListPanel, 0);
+ Grid.SetColumn(splitter, 1);
+ Grid.SetColumn(inspector, 2);
+ } else {
+ layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), MinHeight = 100 });
+ layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1) });
+ layout.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star), MinHeight = 100 });
+
+ splitter.HorizontalAlignment = HorizontalAlignment.Stretch;
+ splitter.VerticalAlignment = VerticalAlignment.Center;
+ splitter.Width = double.NaN;
+ splitter.Height = 1;
+
+ Grid.SetRow(commitListPanel, 0);
+ Grid.SetRow(splitter, 1);
+ Grid.SetRow(inspector, 2);
+ Grid.SetColumn(commitListPanel, 0);
+ Grid.SetColumn(splitter, 0);
+ Grid.SetColumn(inspector, 0);
+ }
+
+ layout.InvalidateArrange();
+ }
+ #endregion
+
+ #region SEARCH_BAR
+ public void ToggleSearch() {
+ if (searchBar.Margin.Top == 0) {
+ if (searchBar.Margin.Top != 0) return;
+
+ if (searching) {
+ loading.Visibility = Visibility.Visible;
+ loading.IsAnimating = true;
+ txtSearch.Text = "";
+ Task.Run(() => UpdateVisibleCommits());
+ }
+
+ ThicknessAnimation anim = new ThicknessAnimation();
+ anim.From = new Thickness(0);
+ anim.To = new Thickness(0, -32, 0, 0);
+ anim.Duration = TimeSpan.FromSeconds(.1);
+ searchBar.BeginAnimation(MarginProperty, anim);
+ } else {
+ ThicknessAnimation anim = new ThicknessAnimation();
+ anim.From = new Thickness(0, -32, 0, 0);
+ anim.To = new Thickness(0);
+ anim.Duration = TimeSpan.FromSeconds(.1);
+ searchBar.BeginAnimation(MarginProperty, anim);
+
+ txtSearch.Focus();
+ }
+ }
+
+ private void ClearSearch(object sender, RoutedEventArgs e) {
+ txtSearch.Text = "";
+ }
+
+ private void HideSearch(object sender, RoutedEventArgs e) {
+ if (searching) {
+ loading.Visibility = Visibility.Visible;
+ loading.IsAnimating = true;
+ txtSearch.Text = "";
+ Task.Run(() => UpdateVisibleCommits());
+ }
+
+ ThicknessAnimation anim = new ThicknessAnimation();
+ anim.From = new Thickness(0);
+ anim.To = new Thickness(0, -32, 0, 0);
+ anim.Duration = TimeSpan.FromSeconds(.1);
+ searchBar.BeginAnimation(MarginProperty, anim);
+ }
+
+ private void OnSearchPreviewKeyDown(object sender, KeyEventArgs e) {
+ if (e.Key == Key.Enter) {
+ loading.Visibility = Visibility.Visible;
+ loading.IsAnimating = true;
+
+ var filter = txtSearch.Text;
+ Task.Run(() => UpdateVisibleCommits(filter));
+ } else if (e.Key == Key.Escape) {
+ ToggleSearch();
+ }
+ }
+ #endregion
+
+ #region COMMIT_LIST
+ private void OnCommitListScrolled(object sender, ScrollChangedEventArgs e) {
+ graph.SetOffset(e.VerticalOffset * commitList.RowHeight);
+ }
+
+ private void OnCommitListKeyUp(object sender, KeyEventArgs e) {
+ if (e.Key == Key.Up || e.Key == Key.Down) {
+ OnCommitSelectionChanged(sender, null);
+ e.Handled = true;
+ }
+ }
+
+ private void OnCommitSelectionChanged(object sender, SelectionChangedEventArgs e) {
+ if (Keyboard.IsKeyDown(Key.Up) || Keyboard.IsKeyDown(Key.Down)) return;
+
+ mask.Visibility = Visibility.Collapsed;
+ commitDetail.Visibility = Visibility.Collapsed;
+ revisionCompare.Visibility = Visibility.Collapsed;
+
+ var selected = commitList.SelectedItems;
+ if (selected.Count == 1) {
+ commitDetail.SetData(repo.Path, selected[0] as Models.Commit);
+ commitDetail.Visibility = Visibility.Visible;
+ } else if (selected.Count == 2) {
+ revisionCompare.SetData(repo.Path, selected[0] as Models.Commit, selected[1] as Models.Commit);
+ revisionCompare.Visibility = Visibility.Visible;
+ } else if (selected.Count > 2) {
+ mask.Visibility = Visibility.Visible;
+ txtCounter.Text = App.Text("Histories.Selected", selected.Count);
+ } else {
+ mask.Visibility = Visibility.Visible;
+ txtCounter.Text = App.Text("Histories.Guide");
+ }
+ }
+
+ private void OnCommitContextMenuOpening(object sender, ContextMenuEventArgs ev) {
+ var row = sender as DataGridRow;
+ if (row == null) return;
+
+ var commit = row.DataContext as Models.Commit;
+ if (commit == null) return;
+
+ commitList.SelectedItem = commit;
+
+ var current = repo.Branches.Find(x => x.IsCurrent);
+ if (current == null) return;
+
+ var merged = commit.IsMerged;
+ var menu = new ContextMenu();
+ var tags = new List();
+
+ // Decorators
+ if (commit.HasDecorators) {
+ foreach (var d in commit.Decorators) {
+ if (d.Type == Models.DecoratorType.CurrentBranchHead) {
+ FillCurrentBranchMenu(menu, current);
+ } else if (d.Type == Models.DecoratorType.LocalBranchHead) {
+ FillOtherLocalBranchMenu(menu, repo.Branches.Find(x => x.IsLocal && x.Name == d.Name), current, merged);
+ } else if (d.Type == Models.DecoratorType.RemoteBranchHead) {
+ FillRemoteBranchMenu(menu, repo.Branches.Find(x => !x.IsLocal && d.Name == $"{x.Remote}/{x.Name}"), current, merged);
+ } else if (d.Type == Models.DecoratorType.Tag) {
+ tags.Add(d.Name);
+ }
+ }
+
+ if (menu.Items.Count > 0) menu.Items.Add(new Separator());
+ }
+
+ // Tags
+ if (tags.Count > 0) {
+ foreach (var tag in tags) FillTagMenu(menu, tag);
+ menu.Items.Add(new Separator());
+ }
+
+ if (current.Head != commit.SHA) {
+ var reset = new MenuItem();
+ reset.Header = App.Text("CommitCM.Reset", current.Name);
+ reset.Click += (o, e) => {
+ new Popups.Reset(repo.Path, current.Name, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(reset);
+ } else {
+ var reword = new MenuItem();
+ reword.Header = App.Text("CommitCM.Reword");
+ reword.Click += (o, e) => {
+ new Popups.Reword(repo.Path, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(reword);
+
+ var squash = new MenuItem();
+ squash.Header = App.Text("CommitCM.Squash");
+ squash.IsEnabled = commit.Parents.Count == 1;
+ squash.Click += (o, e) => {
+ foreach (var c in cachedCommits) {
+ if (c.SHA == commit.Parents[0]) {
+ new Popups.Squash(repo.Path, commit, c).Show();
+ e.Handled = true;
+ return;
+ }
+ }
+
+ Models.Exception.Raise("Can NOT found parent of HEAD!");
+ e.Handled = true;
+ };
+ menu.Items.Add(squash);
+ }
+
+ if (!merged) {
+ var rebase = new MenuItem();
+ rebase.Header = App.Text("CommitCM.Rebase", current.Name);
+ rebase.Click += (o, e) => {
+ new Popups.Rebase(repo.Path, current.Name, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(rebase);
+
+ var cherryPick = new MenuItem();
+ cherryPick.Header = App.Text("CommitCM.CherryPick");
+ cherryPick.Click += (o, e) => {
+ new Popups.CherryPick(repo.Path, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(cherryPick);
+ } else {
+ var revert = new MenuItem();
+ revert.Header = App.Text("CommitCM.Revert");
+ revert.Click += (o, e) => {
+ new Popups.Revert(repo.Path, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(revert);
+ }
+
+ menu.Items.Add(new Separator());
+
+ var createBranchIcon = new Path();
+ createBranchIcon.Data = FindResource("Icon.Branch.Add") as Geometry;
+ createBranchIcon.Width = 10;
+ var createBranch = new MenuItem();
+ createBranch.Icon = createBranchIcon;
+ createBranch.Header = App.Text("CreateBranch");
+ createBranch.Click += (o, e) => {
+ new Popups.CreateBranch(repo, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(createBranch);
+
+ var createTagIcon = new Path();
+ createTagIcon.Data = FindResource("Icon.Tag.Add") as Geometry;
+ createTagIcon.Width = 10;
+ var createTag = new MenuItem();
+ createTag.Icon = createTagIcon;
+ createTag.Header = App.Text("CreateTag");
+ createTag.Click += (o, e) => {
+ new Popups.CreateTag(repo, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(createTag);
+ menu.Items.Add(new Separator());
+
+ var saveToPatchIcon = new Path();
+ saveToPatchIcon.Data = FindResource("Icon.Diff") as Geometry;
+ saveToPatchIcon.Width = 10;
+ var saveToPatch = new MenuItem();
+ saveToPatch.Icon = saveToPatchIcon;
+ saveToPatch.Header = App.Text("CommitCM.SaveAsPatch");
+ saveToPatch.Click += (o, e) => {
+ var dialog = new Controls.FolderDialog();
+ if (dialog.ShowDialog() == true) {
+ new Commands.FormatPatch(repo.Path, commit.SHA, dialog.SelectedPath).Exec();
+ }
+ };
+ menu.Items.Add(saveToPatch);
+
+ var archiveIcon = new Path();
+ archiveIcon.Data = FindResource("Icon.Archive") as Geometry;
+ archiveIcon.Width = 10;
+ var archive = new MenuItem();
+ archive.Icon = archiveIcon;
+ archive.Header = App.Text("Archive");
+ archive.Click += (o, e) => {
+ new Popups.Archive(repo.Path, commit).Show();
+ e.Handled = true;
+ };
+ menu.Items.Add(archive);
+ menu.Items.Add(new Separator());
+
+ var copySHA = new MenuItem();
+ copySHA.Header = App.Text("CommitCM.CopySHA");
+ copySHA.Click += (o, e) => {
+ Clipboard.SetDataObject(commit.SHA, true);
+ e.Handled = true;
+ };
+ menu.Items.Add(copySHA);
+
+ var copyInfo = new MenuItem();
+ copyInfo.Header = App.Text("CommitCM.CopyInfo");
+ copyInfo.Click += (o, e) => {
+ Clipboard.SetDataObject(string.Format(
+ "SHA: {0}\nTITLE: {1}\nAUTHOR: {2} <{3}>\nTIME: {4}",
+ commit.SHA, commit.Subject, commit.Committer.Name, commit.Committer.Email, commit.Committer.Time), true);
+ };
+ menu.Items.Add(copyInfo);
+
+ menu.IsOpen = true;
+ ev.Handled = true;
+ }
+
+ private void FillCurrentBranchMenu(ContextMenu menu, Models.Branch current) {
+ var icon = new Path();
+ icon.Data = FindResource("Icon.Branch") as Geometry;
+ icon.VerticalAlignment = VerticalAlignment.Bottom;
+ icon.Width = 10;
+ icon.Height = 10;
+
+ var dirty = !string.IsNullOrEmpty(current.UpstreamTrackStatus);
+ var submenu = new MenuItem();
+ submenu.Header = current.Name;
+ submenu.Icon = icon;
+
+ if (!string.IsNullOrEmpty(current.Upstream)) {
+ var upstream = current.Upstream.Substring(13);
+
+ var fastForward = new MenuItem();
+ fastForward.Header = App.Text("BranchCM.FastForward", upstream);
+ fastForward.IsEnabled = dirty;
+ fastForward.Click += (o, e) => {
+ new Popups.Merge(repo.Path, upstream, current.Name).ShowAndStart();
+ e.Handled = true;
+ };
+ submenu.Items.Add(fastForward);
+
+ var pull = new MenuItem();
+ pull.Header = App.Text("BranchCM.Pull", upstream);
+ pull.IsEnabled = dirty;
+ pull.Click += (o, e) => {
+ new Popups.Pull(repo, null).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(pull);
+ }
+
+ var push = new MenuItem();
+ push.Header = App.Text("BranchCM.Push", current.Name);
+ push.IsEnabled = repo.Remotes.Count > 0 && dirty;
+ push.Click += (o, e) => {
+ new Popups.Push(repo, current).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(push);
+ submenu.Items.Add(new Separator());
+
+ var type = repo.GitFlow.GetBranchType(current.Name);
+ if (type != Models.GitFlowBranchType.None) {
+ var flowIcon = new Path();
+ flowIcon.Data = FindResource("Icon.Flow") as Geometry;
+ flowIcon.Width = 10;
+ flowIcon.Height = 10;
+
+ var finish = new MenuItem();
+ finish.Header = App.Text("BranchCM.Finish", current.Name);
+ finish.Icon = flowIcon;
+ finish.Click += (o, e) => {
+ new Popups.GitFlowFinish(repo, current.Name, type).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(finish);
+ submenu.Items.Add(new Separator());
+ }
+
+ var rename = new MenuItem();
+ rename.Header = App.Text("BranchCM.Rename", current.Name);
+ rename.Click += (o, e) => {
+ new Popups.RenameBranch(repo, current.Name).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(rename);
+
+ menu.Items.Add(submenu);
+ }
+
+ private void FillOtherLocalBranchMenu(ContextMenu menu, Models.Branch branch, Models.Branch current, bool merged) {
+ var icon = new Path();
+ icon.Data = FindResource("Icon.Branch") as Geometry;
+ icon.VerticalAlignment = VerticalAlignment.Bottom;
+ icon.Width = 10;
+ icon.Height = 10;
+
+ var submenu = new MenuItem();
+ submenu.Header = branch.Name;
+ submenu.Icon = icon;
+
+ var checkout = new MenuItem();
+ checkout.Header = App.Text("BranchCM.Checkout", branch.Name);
+ checkout.Click += (o, e) => {
+ new Popups.Checkout(repo.Path, branch.Name).ShowAndStart();
+ e.Handled = true;
+ };
+ submenu.Items.Add(checkout);
+
+ var merge = new MenuItem();
+ merge.Header = App.Text("BranchCM.Merge", branch.Name, current.Name);
+ merge.IsEnabled = !merged;
+ merge.Click += (o, e) => {
+ new Popups.Merge(repo.Path, branch.Name, current.Name).Show();
+ e.Handled = true;
+ };
+
+ submenu.Items.Add(merge);
+ submenu.Items.Add(new Separator());
+
+ var type = repo.GitFlow.GetBranchType(branch.Name);
+ if (type != Models.GitFlowBranchType.None) {
+ var flowIcon = new Path();
+ flowIcon.Data = FindResource("Icon.Flow") as Geometry;
+ flowIcon.Width = 10;
+ flowIcon.Height = 10;
+
+ var finish = new MenuItem();
+ finish.Header = App.Text("BranchCM.Finish", branch.Name);
+ finish.Icon = flowIcon;
+ finish.Click += (o, e) => {
+ new Popups.GitFlowFinish(repo, branch.Name, type).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(finish);
+ submenu.Items.Add(new Separator());
+ }
+
+ var rename = new MenuItem();
+ rename.Header = App.Text("BranchCM.Rename", branch.Name);
+ rename.Click += (o, e) => {
+ new Popups.RenameBranch(repo, branch.Name).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(rename);
+
+ var delete = new MenuItem();
+ delete.Header = App.Text("BranchCM.Delete", branch.Name);
+ delete.Click += (o, e) => {
+ new Popups.DeleteBranch(repo.Path, branch.Name).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(delete);
+
+ menu.Items.Add(submenu);
+ }
+
+ private void FillRemoteBranchMenu(ContextMenu menu, Models.Branch branch, Models.Branch current, bool merged) {
+ var name = $"{branch.Remote}/{branch.Name}";
+
+ var icon = new Path();
+ icon.Data = FindResource("Icon.Branch") as Geometry;
+ icon.VerticalAlignment = VerticalAlignment.Bottom;
+ icon.Width = 10;
+ icon.Height = 10;
+
+ var submenu = new MenuItem();
+ submenu.Header = name;
+ submenu.Icon = icon;
+
+ var checkout = new MenuItem();
+ checkout.Header = App.Text("BranchCM.Checkout", name);
+ checkout.Click += (o, e) => {
+ foreach (var b in repo.Branches) {
+ if (b.IsLocal && b.Upstream == branch.FullName) {
+ if (b.IsCurrent) return;
+ new Popups.Checkout(repo.Path, b.Name).ShowAndStart();
+ return;
+ }
+ }
+
+ new Popups.CreateBranch(repo, branch).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(checkout);
+
+ var merge = new MenuItem();
+ merge.Header = App.Text("BranchCM.Merge", name, current.Name);
+ merge.IsEnabled = !merged;
+ merge.Click += (o, e) => {
+ new Popups.Merge(repo.Path, name, current.Name).Show();
+ e.Handled = true;
+ };
+
+ submenu.Items.Add(merge);
+ submenu.Items.Add(new Separator());
+
+ var delete = new MenuItem();
+ delete.Header = App.Text("BranchCM.Delete", name);
+ delete.Click += (o, e) => {
+ new Popups.DeleteBranch(repo.Path, branch.Name, branch.Remote).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(delete);
+
+ menu.Items.Add(submenu);
+ }
+
+ private void FillTagMenu(ContextMenu menu, string tag) {
+ var icon = new Path();
+ icon.Data = FindResource("Icon.Tag") as Geometry;
+ icon.Width = 10;
+ icon.Height = 10;
+
+ var submenu = new MenuItem();
+ submenu.Header = tag;
+ submenu.Icon = icon;
+ submenu.MinWidth = 200;
+
+ var push = new MenuItem();
+ push.Header = App.Text("TagCM.Push", tag);
+ push.IsEnabled = repo.Remotes.Count > 0;
+ push.Click += (o, e) => {
+ new Popups.PushTag(repo, tag).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(push);
+
+ var delete = new MenuItem();
+ delete.Header = App.Text("TagCM.Delete", tag);
+ delete.Click += (o, e) => {
+ new Popups.DeleteTag(repo.Path, tag).Show();
+ e.Handled = true;
+ };
+ submenu.Items.Add(delete);
+ menu.Items.Add(submenu);
+ }
+ #endregion
+ }
+}
diff --git a/src/Views/Widgets/WorkingCopyChanges.xaml.cs b/src/Views/Widgets/WorkingCopyChanges.xaml.cs
index f1c04623..94796161 100644
--- a/src/Views/Widgets/WorkingCopyChanges.xaml.cs
+++ b/src/Views/Widgets/WorkingCopyChanges.xaml.cs
@@ -369,14 +369,22 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var stashIcon = new System.Windows.Shapes.Path();
+ stashIcon.Data = FindResource("Icon.Stashes") as System.Windows.Media.Geometry;
+ stashIcon.Width = 10;
var stash = new MenuItem();
+ stash.Icon = stashIcon;
stash.Header = App.Text("FileCM.Stash");
stash.Click += (o, e) => {
new Popups.Stash(repo, changes).Show();
e.Handled = true;
};
+ var patchIcon = new System.Windows.Shapes.Path();
+ patchIcon.Data = FindResource("Icon.Diff") as System.Windows.Media.Geometry;
+ patchIcon.Width = 10;
var patch = new MenuItem();
+ patch.Icon = patchIcon;
patch.Header = App.Text("FileCM.SaveAsPatch");
patch.Click += (o, e) => {
var dialog = new SaveFileDialog();
@@ -432,14 +440,22 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var stashIcon = new System.Windows.Shapes.Path();
+ stashIcon.Data = FindResource("Icon.Stashes") as System.Windows.Media.Geometry;
+ stashIcon.Width = 10;
var stash = new MenuItem();
+ stash.Icon = stashIcon;
stash.Header = App.Text("FileCM.StashMulti", changes.Count);
stash.Click += (o, e) => {
new Popups.Stash(repo, changes).Show();
e.Handled = true;
};
+ var patchIcon = new System.Windows.Shapes.Path();
+ patchIcon.Data = FindResource("Icon.Diff") as System.Windows.Media.Geometry;
+ patchIcon.Width = 10;
var patch = new MenuItem();
+ patch.Icon = patchIcon;
patch.Header = App.Text("FileCM.SaveAsPatch");
patch.Click += (o, e) => {
var dialog = new SaveFileDialog();
@@ -491,14 +507,22 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var stashIcon = new System.Windows.Shapes.Path();
+ stashIcon.Data = FindResource("Icon.Stashes") as System.Windows.Media.Geometry;
+ stashIcon.Width = 10;
var stash = new MenuItem();
+ stash.Icon = stashIcon;
stash.Header = App.Text("FileCM.Stash");
stash.Click += (o, e) => {
new Popups.Stash(repo, changes).Show();
e.Handled = true;
};
+ var patchIcon = new System.Windows.Shapes.Path();
+ patchIcon.Data = FindResource("Icon.Diff") as System.Windows.Media.Geometry;
+ patchIcon.Width = 10;
var patch = new MenuItem();
+ patch.Icon = patchIcon;
patch.Header = App.Text("FileCM.SaveAsPatch");
patch.Click += (o, e) => {
var dialog = new SaveFileDialog();
@@ -553,14 +577,22 @@ namespace SourceGit.Views.Widgets {
e.Handled = true;
};
+ var stashIcon = new System.Windows.Shapes.Path();
+ stashIcon.Data = FindResource("Icon.Stashes") as System.Windows.Media.Geometry;
+ stashIcon.Width = 10;
var stash = new MenuItem();
+ stash.Icon = stashIcon;
stash.Header = App.Text("FileCM.StashMulti", changes.Count);
stash.Click += (o, e) => {
new Popups.Stash(repo, changes).Show();
e.Handled = true;
};
+ var patchIcon = new System.Windows.Shapes.Path();
+ patchIcon.Data = FindResource("Icon.Diff") as System.Windows.Media.Geometry;
+ patchIcon.Width = 10;
var patch = new MenuItem();
+ patch.Icon = patchIcon;
patch.Header = App.Text("FileCM.SaveAsPatch");
patch.Click += (o, e) => {
var dialog = new SaveFileDialog();