refactor<*>: move SourceGit.Git.Preference to SourceGit.Preference

This commit is contained in:
leo 2020-12-17 11:55:06 +08:00
parent d248394e42
commit 3e6c837916
27 changed files with 236 additions and 260 deletions

View file

@ -1,15 +1,83 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Text.Json;
namespace SourceGit.Git { namespace SourceGit {
/// <summary> /// <summary>
/// User's preference settings. Serialized to /// User's preference settings. Serialized to
/// </summary> /// </summary>
public class Preference { public class Preference {
/// <summary>
/// Tools setting.
/// </summary>
public class ToolSetting {
/// <summary>
/// Git executable file path.
/// </summary>
public string GitExecutable { get; set; }
/// <summary>
/// Default clone directory.
/// </summary>
public string GitDefaultCloneDir { get; set; }
/// <summary>
/// Selected merge tool.
/// </summary>
public int MergeTool { get; set; } = 0;
/// <summary>
/// Executable file path for merge tool.
/// </summary>
public string MergeExecutable { get; set; } = "--";
}
/// <summary>
/// File's display mode.
/// </summary>
public enum FilesDisplayMode {
Tree,
List,
Grid,
}
/// <summary>
/// Settings for UI.
/// </summary>
public class UISetting {
/// <summary>
/// Use light theme?
/// </summary>
public bool UseLightTheme { get; set; }
/// <summary>
/// Main window width
/// </summary>
public double WindowWidth { get; set; }
/// <summary>
/// Main window height
/// </summary>
public double WindowHeight { get; set; }
/// <summary>
/// Move commit viewer from bottom to right
/// </summary>
public bool MoveCommitViewerRight { get; set; }
/// <summary>
/// File's display mode in unstaged view.
/// </summary>
public FilesDisplayMode UnstageFileDisplayMode { get; set; }
/// <summary>
/// File's display mode in staged view.
/// </summary>
public FilesDisplayMode StagedFileDisplayMode { get; set; }
/// <summary>
/// Use DataGrid instead of TreeView in changes view.
/// </summary>
public bool UseListInChanges { get; set; }
/// <summary>
/// Use combined instead of side-by-side mode in diff viewer.
/// </summary>
public bool UseCombinedDiff { get; set; }
}
/// <summary> /// <summary>
/// Group(Virtual folder) for watched repositories. /// Group(Virtual folder) for watched repositories.
/// </summary> /// </summary>
@ -32,104 +100,19 @@ namespace SourceGit.Git {
public bool IsExpended { get; set; } public bool IsExpended { get; set; }
} }
/// <summary> #region SAVED_DATAS
/// File's display mode.
/// </summary>
public enum FilesDisplayMode {
Tree,
List,
Grid,
}
#region STATICS
/// <summary>
/// Storage path for Preference.
/// </summary>
private static readonly string SAVE_PATH = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"SourceGit",
"preference.json");
/// <summary>
/// Runtime singleton instance.
/// </summary>
private static Preference instance = null;
public static Preference Instance {
get {
if (instance == null) Load();
return instance;
}
set {
instance = value;
}
}
#endregion
#region SETTING_GENERAL
/// <summary>
/// Use light color theme.
/// </summary>
public bool UseLightTheme { get; set; }
/// <summary> /// <summary>
/// Check for updates. /// Check for updates.
/// </summary> /// </summary>
public bool CheckUpdate { get; set; } public bool CheckUpdate { get; set; } = true;
#endregion
#region SETTING_GIT
/// <summary> /// <summary>
/// Git executable file path. /// Settings for executables.
/// </summary> /// </summary>
public string GitExecutable { get; set; } public ToolSetting Tools { get; set; } = new ToolSetting();
/// <summary> /// <summary>
/// Default clone directory. /// Use light color theme.
/// </summary> /// </summary>
public string GitDefaultCloneDir { get; set; } public UISetting UI { get; set; } = new UISetting();
#endregion
#region SETTING_MERGE_TOOL
/// <summary>
/// Selected merge tool.
/// </summary>
public int MergeTool { get; set; } = 0;
/// <summary>
/// Executable file path for merge tool.
/// </summary>
public string MergeExecutable { get; set; } = "--";
#endregion
#region SETTING_UI
/// <summary>
/// Main window's width
/// </summary>
public double UIMainWindowWidth { get; set; }
/// <summary>
/// Main window's height
/// </summary>
public double UIMainWindowHeight { get; set; }
/// <summary>
/// Show/Hide tags' list view.
/// </summary>
public bool UIShowTags { get; set; } = true;
/// <summary>
/// Use horizontal layout for histories.
/// </summary>
public bool UIUseHorizontalLayout { get; set; }
/// <summary>
/// Files' display mode in unstage view.
/// </summary>
public FilesDisplayMode UIUnstageDisplayMode { get; set; } = FilesDisplayMode.Grid;
/// <summary>
/// Files' display mode in staged view.
/// </summary>
public FilesDisplayMode UIStagedDisplayMode { get; set; } = FilesDisplayMode.Grid;
/// <summary>
/// Using datagrid instead of tree in changes.
/// </summary>
public bool UIUseListInChanges { get; set; }
/// <summary>
/// Use one side diff instead of two sides.
/// </summary>
public bool UIUseOneSideDiff { get; set; }
#endregion #endregion
#region SETTING_REPOS #region SETTING_REPOS
@ -140,34 +123,7 @@ namespace SourceGit.Git {
/// <summary> /// <summary>
/// Watched repositories. /// Watched repositories.
/// </summary> /// </summary>
public List<Repository> Repositories { get; set; } = new List<Git.Repository>(); public List<Git.Repository> Repositories { get; set; } = new List<Git.Repository>();
#endregion
#region METHODS_LOAD_SAVE
/// <summary>
/// Load preference from disk.
/// </summary>
/// <returns>Loaded preference instance.</returns>
public static void Load() {
if (!File.Exists(SAVE_PATH)) {
instance = new Preference();
} else {
instance = JsonSerializer.Deserialize<Preference>(File.ReadAllText(SAVE_PATH));
}
}
/// <summary>
/// Save current preference into disk.
/// </summary>
public static void Save() {
if (instance == null) return;
var dir = Path.GetDirectoryName(SAVE_PATH);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
var data = JsonSerializer.Serialize(instance, new JsonSerializerOptions() { WriteIndented = true });
File.WriteAllText(SAVE_PATH, data);
}
#endregion #endregion
#region METHODS_ON_GROUP #region METHODS_ON_GROUP
@ -244,12 +200,12 @@ namespace SourceGit.Git {
/// <param name="path">Local storage path.</param> /// <param name="path">Local storage path.</param>
/// <param name="groupId">Group's ID</param> /// <param name="groupId">Group's ID</param>
/// <returns>Added repository instance.</returns> /// <returns>Added repository instance.</returns>
public Repository AddRepository(string path, string groupId) { public Git.Repository AddRepository(string path, string groupId) {
var repo = FindRepository(path); var repo = FindRepository(path);
if (repo != null) return repo; if (repo != null) return repo;
var dir = new DirectoryInfo(path); var dir = new DirectoryInfo(path);
repo = new Repository() { repo = new Git.Repository() {
Path = dir.FullName, Path = dir.FullName,
Name = dir.Name, Name = dir.Name,
GroupId = groupId, GroupId = groupId,
@ -266,7 +222,7 @@ namespace SourceGit.Git {
/// </summary> /// </summary>
/// <param name="path">Local storage path.</param> /// <param name="path">Local storage path.</param>
/// <returns>Founded repository instance.</returns> /// <returns>Founded repository instance.</returns>
public Repository FindRepository(string path) { public Git.Repository FindRepository(string path) {
var dir = new DirectoryInfo(path); var dir = new DirectoryInfo(path);
foreach (var repo in Repositories) { foreach (var repo in Repositories) {
if (repo.Path == dir.FullName) return repo; if (repo.Path == dir.FullName) return repo;

View file

@ -1,6 +1,7 @@
using Microsoft.Win32; using Microsoft.Win32;
using System; using System;
using System.IO; using System.IO;
using System.Text.Json;
using System.Windows; using System.Windows;
namespace SourceGit { namespace SourceGit {
@ -9,22 +10,18 @@ namespace SourceGit {
/// Application. /// Application.
/// </summary> /// </summary>
public partial class App : Application { public partial class App : Application {
/// <summary> /// <summary>
/// Getter/Setter for Git preference. /// Getter/Setter for application user setting.
/// </summary> /// </summary>
public static Git.Preference Preference { public static Preference Setting { get; set; }
get { return Git.Preference.Instance; }
set { Git.Preference.Instance = value; }
}
/// <summary> /// <summary>
/// Check if GIT has been configured. /// Check if GIT has been configured.
/// </summary> /// </summary>
public static bool IsGitConfigured { public static bool IsGitConfigured {
get { get {
return !string.IsNullOrEmpty(Preference.GitExecutable) return !string.IsNullOrEmpty(Setting.Tools.GitExecutable)
&& File.Exists(Preference.GitExecutable); && File.Exists(Setting.Tools.GitExecutable);
} }
} }
@ -60,6 +57,17 @@ namespace SourceGit {
return; return;
} }
// Load settings.
var settingFile = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"SourceGit",
"preference.json");
if (!File.Exists(settingFile)) {
Setting = new Preference();
} else {
Setting = JsonSerializer.Deserialize<Preference>(File.ReadAllText(settingFile));
}
// Try auto configure git via registry. // Try auto configure git via registry.
if (!IsGitConfigured) { if (!IsGitConfigured) {
var root = RegistryKey.OpenBaseKey( var root = RegistryKey.OpenBaseKey(
@ -68,7 +76,7 @@ namespace SourceGit {
var git = root.OpenSubKey("SOFTWARE\\GitForWindows"); var git = root.OpenSubKey("SOFTWARE\\GitForWindows");
if (git != null) { if (git != null) {
Preference.GitExecutable = Path.Combine( Setting.Tools.GitExecutable = Path.Combine(
git.GetValue("InstallPath") as string, git.GetValue("InstallPath") as string,
"bin", "bin",
"git.exe"); "git.exe");
@ -76,7 +84,7 @@ namespace SourceGit {
} }
// Apply themes // Apply themes
if (Preference.UseLightTheme) { if (Setting.UI.UseLightTheme) {
foreach (var rs in Current.Resources.MergedDictionaries) { foreach (var rs in Current.Resources.MergedDictionaries) {
if (rs.Source != null && rs.Source.OriginalString.StartsWith("pack://application:,,,/Resources/Themes/")) { if (rs.Source != null && rs.Source.OriginalString.StartsWith("pack://application:,,,/Resources/Themes/")) {
rs.Source = new Uri("pack://application:,,,/Resources/Themes/Light.xaml", UriKind.Absolute); rs.Source = new Uri("pack://application:,,,/Resources/Themes/Light.xaml", UriKind.Absolute);
@ -98,14 +106,30 @@ namespace SourceGit {
(Current.MainWindow as UI.Launcher).Open(repo); (Current.MainWindow as UI.Launcher).Open(repo);
} }
/// <summary>
/// Save settings.
/// </summary>
public static void SaveSetting() {
var settingFile = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"SourceGit",
"preference.json");
var dir = Path.GetDirectoryName(settingFile);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir);
var data = JsonSerializer.Serialize(Setting, new JsonSerializerOptions() { WriteIndented = true });
File.WriteAllText(settingFile, data);
}
/// <summary> /// <summary>
/// Deactivated event. /// Deactivated event.
/// </summary> /// </summary>
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void OnAppDeactivated(object sender, EventArgs e) { private void OnAppDeactivated(object sender, EventArgs e) {
Git.Preference.Save();
GC.Collect(); GC.Collect();
SaveSetting();
} }
} }
} }

View file

@ -27,7 +27,7 @@ namespace SourceGit.Converters {
status = change.Index; status = change.Index;
} }
if (App.Preference.UseLightTheme) { if (App.Setting.UI.UseLightTheme) {
switch (status) { switch (status) {
case Git.Change.Status.Modified: return Brushes.Goldenrod; case Git.Change.Status.Modified: return Brushes.Goldenrod;
case Git.Change.Status.Added: return Brushes.Green; case Git.Change.Status.Added: return Brushes.Green;

View file

@ -8,11 +8,11 @@ namespace SourceGit.Converters {
public class FilesDisplayModeToIcon : IValueConverter { public class FilesDisplayModeToIcon : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var mode = (Git.Preference.FilesDisplayMode)value; var mode = (Preference.FilesDisplayMode)value;
switch (mode) { switch (mode) {
case Git.Preference.FilesDisplayMode.Grid: case Preference.FilesDisplayMode.Grid:
return App.Current.FindResource("Icon.Grid") as Geometry; return App.Current.FindResource("Icon.Grid") as Geometry;
case Git.Preference.FilesDisplayMode.List: case Preference.FilesDisplayMode.List:
return App.Current.FindResource("Icon.List") as Geometry; return App.Current.FindResource("Icon.List") as Geometry;
default: default:
return App.Current.FindResource("Icon.Tree") as Geometry; return App.Current.FindResource("Icon.Tree") as Geometry;

View file

@ -10,9 +10,9 @@ namespace SourceGit.Converters {
public bool TreatGridAsList { get; set; } = true; public bool TreatGridAsList { get; set; } = true;
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var mode = (Git.Preference.FilesDisplayMode)value; var mode = (Preference.FilesDisplayMode)value;
if (mode == Git.Preference.FilesDisplayMode.Tree) return Visibility.Collapsed; if (mode == Preference.FilesDisplayMode.Tree) return Visibility.Collapsed;
if (mode == Git.Preference.FilesDisplayMode.List) return Visibility.Visible; if (mode == Preference.FilesDisplayMode.List) return Visibility.Visible;
if (TreatGridAsList) return Visibility.Visible; if (TreatGridAsList) return Visibility.Visible;
return Visibility.Collapsed; return Visibility.Collapsed;
} }
@ -25,7 +25,7 @@ namespace SourceGit.Converters {
public class FilesDisplayModeToGrid : IValueConverter { public class FilesDisplayModeToGrid : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return (Git.Preference.FilesDisplayMode)value == Git.Preference.FilesDisplayMode.Grid ? Visibility.Visible : Visibility.Collapsed; return (Preference.FilesDisplayMode)value == Preference.FilesDisplayMode.Grid ? Visibility.Visible : Visibility.Collapsed;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
@ -36,7 +36,7 @@ namespace SourceGit.Converters {
public class FilesDisplayModeToTree : IValueConverter { public class FilesDisplayModeToTree : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
return (Git.Preference.FilesDisplayMode)value == Git.Preference.FilesDisplayMode.Tree ? Visibility.Visible : Visibility.Collapsed; return (Preference.FilesDisplayMode)value == Preference.FilesDisplayMode.Tree ? Visibility.Visible : Visibility.Collapsed;
} }
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {

View file

@ -153,24 +153,6 @@ namespace SourceGit.Git {
commits.Add(current); commits.Add(current);
} }
if (!findHead && commits.Count > 0) {
var startInfo = new ProcessStartInfo();
startInfo.FileName = Preference.Instance.GitExecutable;
startInfo.Arguments = $"merge-base --is-ancestor {commits[0].SHA} HEAD";
startInfo.WorkingDirectory = repo.Path;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
startInfo.RedirectStandardOutput = false;
startInfo.RedirectStandardError = false;
var proc = new Process() { StartInfo = startInfo };
proc.Start();
proc.WaitForExit();
commits[0].IsMerged = proc.ExitCode == 0;
proc.Close();
}
return commits; return commits;
} }

View file

@ -47,6 +47,10 @@ namespace SourceGit.Git {
/// </summary> /// </summary>
public long LastOpenTime { get; set; } public long LastOpenTime { get; set; }
/// <summary> /// <summary>
/// Expand tags.
/// </summary>
public bool ExpandTags { get; set; }
/// <summary>
/// Filters for logs. /// Filters for logs.
/// </summary> /// </summary>
public List<string> LogFilters { get; set; } = new List<string>(); public List<string> LogFilters { get; set; } = new List<string>();
@ -89,7 +93,7 @@ namespace SourceGit.Git {
/// <returns></returns> /// <returns></returns>
public string GetConfig(string key) { public string GetConfig(string key) {
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = Preference.Instance.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = $"config {key}"; startInfo.Arguments = $"config {key}";
startInfo.WorkingDirectory = Path; startInfo.WorkingDirectory = Path;
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
@ -113,7 +117,7 @@ namespace SourceGit.Git {
/// <param name="value"></param> /// <param name="value"></param>
public void SetConfig(string key, string value) { public void SetConfig(string key, string value) {
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = Preference.Instance.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = $"config {key} \"{value}\""; startInfo.Arguments = $"config {key} \"{value}\"";
startInfo.WorkingDirectory = Path; startInfo.WorkingDirectory = Path;
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
@ -135,7 +139,7 @@ namespace SourceGit.Git {
/// <returns>Errors if exists.</returns> /// <returns>Errors if exists.</returns>
public static string RunCommand(string cwd, string args, Action<string> outputHandler, bool includeError = false) { public static string RunCommand(string cwd, string args, Action<string> outputHandler, bool includeError = false) {
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = Preference.Instance.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = "--no-pager -c core.quotepath=off " + args; startInfo.Arguments = "--no-pager -c core.quotepath=off " + args;
startInfo.WorkingDirectory = cwd; startInfo.WorkingDirectory = cwd;
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
@ -213,7 +217,7 @@ namespace SourceGit.Git {
/// <returns></returns> /// <returns></returns>
public static bool IsValid(string path) { public static bool IsValid(string path) {
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = Preference.Instance.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = "rev-parse --git-dir"; startInfo.Arguments = "rev-parse --git-dir";
startInfo.WorkingDirectory = path; startInfo.WorkingDirectory = path;
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
@ -416,7 +420,7 @@ namespace SourceGit.Git {
/// <param name="name">Local name</param> /// <param name="name">Local name</param>
/// <param name="onProgress"></param> /// <param name="onProgress"></param>
/// <returns></returns> /// <returns></returns>
public static Repository Clone(string url, string folder, string rName, string lName, Action<string> onProgress) { public static bool Clone(string url, string folder, string rName, string lName, Action<string> onProgress) {
string RemoteName; string RemoteName;
if (rName != null) { if (rName != null) {
RemoteName = $" --origin {rName}"; RemoteName = $" --origin {rName}";
@ -430,12 +434,10 @@ namespace SourceGit.Git {
if (errs != null) { if (errs != null) {
App.RaiseError(errs); App.RaiseError(errs);
return null; return false;
} }
var path = new DirectoryInfo(folder + "/" + lName).FullName; return true;
var repo = Preference.Instance.AddRepository(path, "");
return repo;
} }
/// <summary> /// <summary>

View file

@ -1,3 +1,4 @@
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
@ -34,7 +35,7 @@ namespace SourceGit.UI {
/// Constructor. /// Constructor.
/// </summary> /// </summary>
public Clone(PopupManager mgr) { public Clone(PopupManager mgr) {
ParentFolder = App.Preference.GitDefaultCloneDir; ParentFolder = App.Setting.Tools.GitDefaultCloneDir;
popup = mgr; popup = mgr;
InitializeComponent(); InitializeComponent();
} }
@ -82,15 +83,16 @@ namespace SourceGit.UI {
popup.Lock(); popup.Lock();
var repo = await Task.Run(() => { var succ = await Task.Run(() => {
return Git.Repository.Clone(RemoteUri, ParentFolder, rName, repoName, popup.UpdateStatus); return Git.Repository.Clone(RemoteUri, ParentFolder, rName, repoName, popup.UpdateStatus);
}); });
if (repo == null) { if (succ) {
popup.Unlock(); var path = new DirectoryInfo(ParentFolder + "/" + repoName).FullName;
} else { var repo = App.Setting.AddRepository(path, "");
popup.Close(true);
repo.Open(); repo.Open();
} else {
popup.Unlock();
} }
} }

View file

@ -305,7 +305,7 @@
Margin="4,0,0,0" Margin="4,0,0,0"
ToolTip="SWITCH TO LIST/TREE VIEW" ToolTip="SWITCH TO LIST/TREE VIEW"
Style="{StaticResource Style.ToggleButton.ListOrTree}" Style="{StaticResource Style.ToggleButton.ListOrTree}"
IsChecked="{Binding Source={x:Static source:App.Preference}, Path=UIUseListInChanges, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static source:App.Setting}, Path=UI.UseListInChanges, Mode=TwoWay}"/>
</Grid> </Grid>
<TreeView <TreeView

View file

@ -56,7 +56,7 @@ namespace SourceGit.UI {
if (CommitTemplate != repo.CommitTemplate) { if (CommitTemplate != repo.CommitTemplate) {
repo.CommitTemplate = CommitTemplate; repo.CommitTemplate = CommitTemplate;
Git.Preference.Save(); App.SaveSetting();
} }
Close(sender, e); Close(sender, e);

View file

@ -1,4 +1,5 @@
<UserControl x:Class="SourceGit.UI.Dashboard" <UserControl x:Class="SourceGit.UI.Dashboard"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@ -359,7 +360,7 @@
x:Name="tagListToggle" x:Name="tagListToggle"
Grid.Row="6" Grid.Row="6"
Style="{StaticResource Style.ToggleButton.Expender}" Style="{StaticResource Style.ToggleButton.Expender}"
IsChecked="{Binding Source={x:Static source:App.Preference}, Path=UIShowTags, Mode=TwoWay}"> IsChecked="{Binding Path=ExpandTags, ElementName=me, Mode=TwoWay}">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>

View file

@ -46,6 +46,14 @@ namespace SourceGit.UI {
private List<RemoteNode> cachedRemotes = new List<RemoteNode>(); private List<RemoteNode> cachedRemotes = new List<RemoteNode>();
private string abortCommand = null; private string abortCommand = null;
/// <summary>
/// Expand/Collapsed tags
/// </summary>
public bool ExpandTags {
get { return repo.ExpandTags; }
set { repo.ExpandTags = value; }
}
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
@ -65,9 +73,10 @@ namespace SourceGit.UI {
}); });
}; };
repo = opened;
InitializeComponent(); InitializeComponent();
repo = opened;
histories.Repo = opened; histories.Repo = opened;
commits.Repo = opened; commits.Repo = opened;
@ -347,7 +356,7 @@ namespace SourceGit.UI {
} }
private void OpenTerminal(object sender, RoutedEventArgs e) { private void OpenTerminal(object sender, RoutedEventArgs e) {
var bash = Path.Combine(App.Preference.GitExecutable, "..", "bash.exe"); var bash = Path.Combine(App.Setting.Tools.GitExecutable, "..", "bash.exe");
if (!File.Exists(bash)) { if (!File.Exists(bash)) {
App.RaiseError("Can NOT locate bash.exe. Make sure bash.exe exists under the same folder with git.exe"); App.RaiseError("Can NOT locate bash.exe. Make sure bash.exe exists under the same folder with git.exe");
return; return;

View file

@ -61,7 +61,7 @@
Margin="8,0,0,0" Margin="8,0,0,0"
Style="{StaticResource Style.ToggleButton.SplitDirection}" Style="{StaticResource Style.ToggleButton.SplitDirection}"
ToolTip="Toggle One-Side/Two-Sides" ToolTip="Toggle One-Side/Two-Sides"
IsChecked="{Binding Source={x:Static sourcegit:App.Preference}, Path=UIUseOneSideDiff, Mode=TwoWay}" IsChecked="{Binding Source={x:Static sourcegit:App.Setting}, Path=UI.UseCombinedDiff, Mode=TwoWay}"
Checked="ChangeDiffMode" Unchecked="ChangeDiffMode"/> Checked="ChangeDiffMode" Unchecked="ChangeDiffMode"/>
</StackPanel> </StackPanel>
</Grid> </Grid>

View file

@ -160,7 +160,7 @@ namespace SourceGit.UI {
var lastOldLine = ""; var lastOldLine = "";
var lastNewLine = ""; var lastNewLine = "";
if (App.Preference.UIUseOneSideDiff) { if (App.Setting.UI.UseCombinedDiff) {
var blocks = new List<ChangeBlock>(); var blocks = new List<ChangeBlock>();
foreach (var line in lineChanges) { foreach (var line in lineChanges) {
@ -510,7 +510,7 @@ namespace SourceGit.UI {
if (editors.Count == 0) return; if (editors.Count == 0) return;
var total = editorContainer.ActualWidth; var total = editorContainer.ActualWidth;
if (App.Preference.UIUseOneSideDiff) { if (App.Setting.UI.UseCombinedDiff) {
var editor = editors[0]; var editor = editors[0];
var minWidth = total - editor.NonFrozenColumnsViewportHorizontalOffset; var minWidth = total - editor.NonFrozenColumnsViewportHorizontalOffset;
var scroller = GetVisualChild<ScrollViewer>(editor); var scroller = GetVisualChild<ScrollViewer>(editor);

View file

@ -12,12 +12,12 @@ namespace SourceGit.UI {
public static readonly DependencyProperty ModeProperty = public static readonly DependencyProperty ModeProperty =
DependencyProperty.Register( DependencyProperty.Register(
"Mode", "Mode",
typeof(Git.Preference.FilesDisplayMode), typeof(Preference.FilesDisplayMode),
typeof(FilesDisplayModeSwitch), typeof(FilesDisplayModeSwitch),
new PropertyMetadata(Git.Preference.FilesDisplayMode.Grid)); new PropertyMetadata(Preference.FilesDisplayMode.Grid));
public Git.Preference.FilesDisplayMode Mode { public Preference.FilesDisplayMode Mode {
get { return (Git.Preference.FilesDisplayMode)GetValue(ModeProperty); } get { return (Preference.FilesDisplayMode)GetValue(ModeProperty); }
set { SetValue(ModeProperty, value); } set { SetValue(ModeProperty, value); }
} }
@ -32,15 +32,15 @@ namespace SourceGit.UI {
} }
private void UseGrid(object sender, RoutedEventArgs e) { private void UseGrid(object sender, RoutedEventArgs e) {
Mode = Git.Preference.FilesDisplayMode.Grid; Mode = Preference.FilesDisplayMode.Grid;
} }
private void UseList(object sender, RoutedEventArgs e) { private void UseList(object sender, RoutedEventArgs e) {
Mode = Git.Preference.FilesDisplayMode.List; Mode = Preference.FilesDisplayMode.List;
} }
private void UseTree(object sender, RoutedEventArgs e) { private void UseTree(object sender, RoutedEventArgs e) {
Mode = Git.Preference.FilesDisplayMode.Tree; Mode = Preference.FilesDisplayMode.Tree;
} }
} }
} }

View file

@ -189,7 +189,7 @@
<ToggleButton <ToggleButton
Style="{StaticResource Style.ToggleButton.Orientation}" Style="{StaticResource Style.ToggleButton.Orientation}"
ToolTip="Toggle Horizontal/Vertical Layout" ToolTip="Toggle Horizontal/Vertical Layout"
IsChecked="{Binding Source={x:Static sourcegit:App.Preference}, Path=UIUseHorizontalLayout, Mode=TwoWay}" IsChecked="{Binding Source={x:Static sourcegit:App.Setting}, Path=UI.MoveCommitViewerRight, Mode=TwoWay}"
Checked="ChangeOrientation" Unchecked="ChangeOrientation"/> Checked="ChangeOrientation" Unchecked="ChangeOrientation"/>
<!-- Tips to Histories Panel --> <!-- Tips to Histories Panel -->

View file

@ -630,7 +630,7 @@ namespace SourceGit.UI {
layout.RowDefinitions.Clear(); layout.RowDefinitions.Clear();
layout.ColumnDefinitions.Clear(); layout.ColumnDefinitions.Clear();
if (App.Preference.UIUseHorizontalLayout) { if (App.Setting.UI.MoveCommitViewerRight) {
layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 }); layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });
layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2) }); layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(2) });
layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 }); layout.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star), MinWidth = 200 });

View file

@ -36,13 +36,13 @@ namespace SourceGit.UI {
if (errs != null) { if (errs != null) {
App.RaiseError(errs); App.RaiseError(errs);
} else { } else {
App.Preference.AddRepository(workingDir, ""); App.Setting.AddRepository(workingDir, "");
} }
}); });
popup.Close(true); popup.Close(true);
var repo = App.Preference.FindRepository(workingDir); var repo = App.Setting.FindRepository(workingDir);
if (repo != null) repo.Open(); if (repo != null) repo.Open();
} }

View file

@ -42,8 +42,8 @@ namespace SourceGit.UI {
public static List<InteractiveRebaseModeInfo> Supported = new List<InteractiveRebaseModeInfo>() { public static List<InteractiveRebaseModeInfo> Supported = new List<InteractiveRebaseModeInfo>() {
new InteractiveRebaseModeInfo(InteractiveRebaseMode.Pick, "Pick", "Use this commit", Brushes.Green), new InteractiveRebaseModeInfo(InteractiveRebaseMode.Pick, "Pick", "Use this commit", Brushes.Green),
new InteractiveRebaseModeInfo(InteractiveRebaseMode.Reword, "Reword", "Edit the commit message", Brushes.Yellow), new InteractiveRebaseModeInfo(InteractiveRebaseMode.Reword, "Reword", "Edit the commit message", Brushes.Yellow),
new InteractiveRebaseModeInfo(InteractiveRebaseMode.Squash, "Squash", "Meld into previous commit", App.Preference.UseLightTheme ? Brushes.Gray : Brushes.White), new InteractiveRebaseModeInfo(InteractiveRebaseMode.Squash, "Squash", "Meld into previous commit", App.Setting.UI.UseLightTheme ? Brushes.Gray : Brushes.White),
new InteractiveRebaseModeInfo(InteractiveRebaseMode.Fixup, "Fixup", "Like 'Squash' but discard log message", App.Preference.UseLightTheme ? Brushes.Gray : Brushes.White), new InteractiveRebaseModeInfo(InteractiveRebaseMode.Fixup, "Fixup", "Like 'Squash' but discard log message", App.Setting.UI.UseLightTheme? Brushes.Gray : Brushes.White),
new InteractiveRebaseModeInfo(InteractiveRebaseMode.Drop, "Drop", "Remove commit", Brushes.Red), new InteractiveRebaseModeInfo(InteractiveRebaseMode.Drop, "Drop", "Remove commit", Brushes.Red),
}; };
} }

View file

@ -10,9 +10,9 @@
mc:Ignorable="d" mc:Ignorable="d"
MinWidth="800" MinHeight="600" MinWidth="800" MinHeight="600"
Title="Source Git" Title="Source Git"
Width="{Binding Source={x:Static source:App.Preference}, Path=UIMainWindowWidth, Mode=TwoWay}" Width="{Binding Source={x:Static source:App.Setting}, Path=UI.WindowWidth, Mode=TwoWay}"
Height="{Binding Source={x:Static source:App.Preference}, Path=UIMainWindowHeight, Mode=TwoWay}" Height="{Binding Source={x:Static source:App.Setting}, Path=UI.WindowHeight, Mode=TwoWay}"
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterScreen">
<!-- Enable WindowChrome Feature --> <!-- Enable WindowChrome Feature -->
<WindowChrome.WindowChrome> <WindowChrome.WindowChrome>

View file

@ -95,7 +95,7 @@ namespace SourceGit.UI {
Tabs.Add(new ManagerTab()); Tabs.Add(new ManagerTab());
InitializeComponent(); InitializeComponent();
openedTabs.SelectedItem = Tabs[0]; openedTabs.SelectedItem = Tabs[0];
if (App.Preference.CheckUpdate) Task.Run(CheckUpdate); if (App.Setting.CheckUpdate) Task.Run(CheckUpdate);
} }
/// <summary> /// <summary>
@ -233,7 +233,7 @@ namespace SourceGit.UI {
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void ShowPreference(object sender, RoutedEventArgs e) { private void ShowPreference(object sender, RoutedEventArgs e) {
var dialog = new Preference(); var dialog = new SettingDialog();
dialog.Owner = this; dialog.Owner = this;
dialog.ShowDialog(); dialog.ShowDialog();
} }

View file

@ -130,7 +130,7 @@ namespace SourceGit.UI {
var delete = new MenuItem(); var delete = new MenuItem();
delete.Header = "Delete"; delete.Header = "Delete";
delete.Click += (o, ev) => { delete.Click += (o, ev) => {
App.Preference.RemoveRepository(repo.Path); App.Setting.RemoveRepository(repo.Path);
UpdateRecentOpened(); UpdateRecentOpened();
UpdateTree(); UpdateTree();
HideBrief(); HideBrief();
@ -157,7 +157,7 @@ namespace SourceGit.UI {
var addFolder = new MenuItem(); var addFolder = new MenuItem();
addFolder.Header = "Add Folder"; addFolder.Header = "Add Folder";
addFolder.Click += (o, ev) => { addFolder.Click += (o, ev) => {
var group = App.Preference.AddGroup("New Group", ""); var group = App.Setting.AddGroup("New Group", "");
UpdateTree(group.Id); UpdateTree(group.Id);
ev.Handled = true; ev.Handled = true;
}; };
@ -195,7 +195,7 @@ namespace SourceGit.UI {
foreach (var path in paths) { foreach (var path in paths) {
FileInfo info = new FileInfo(path); FileInfo info = new FileInfo(path);
if (info.Attributes == FileAttributes.Directory && Git.Repository.IsValid(path)) { if (info.Attributes == FileAttributes.Directory && Git.Repository.IsValid(path)) {
App.Preference.AddRepository(path, group); App.Setting.AddRepository(path, group);
needRebuild = true; needRebuild = true;
} }
} }
@ -207,7 +207,7 @@ namespace SourceGit.UI {
var group = ""; var group = "";
var to = (sender as TreeViewItem)?.DataContext as Node; var to = (sender as TreeViewItem)?.DataContext as Node;
if (to != null) group = to.IsRepo ? to.ParentId : to.Id; if (to != null) group = to.IsRepo ? to.ParentId : to.Id;
App.Preference.FindRepository(node.Id).GroupId = group; App.Setting.FindRepository(node.Id).GroupId = group;
needRebuild = true; needRebuild = true;
} }
@ -222,7 +222,7 @@ namespace SourceGit.UI {
var node = selectedTreeViewItem.DataContext as Node; var node = selectedTreeViewItem.DataContext as Node;
if (node.IsRepo) { if (node.IsRepo) {
ShowBrief(App.Preference.FindRepository(node.Id)); ShowBrief(App.Setting.FindRepository(node.Id));
} else { } else {
HideBrief(); HideBrief();
} }
@ -254,7 +254,7 @@ namespace SourceGit.UI {
var node = item.DataContext as Node; var node = item.DataContext as Node;
if (node != null && !node.IsRepo) { if (node != null && !node.IsRepo) {
var group = App.Preference.FindGroup(node.Id); var group = App.Setting.FindGroup(node.Id);
group.IsExpended = item.IsExpanded; group.IsExpended = item.IsExpanded;
e.Handled = true; e.Handled = true;
} }
@ -298,9 +298,9 @@ namespace SourceGit.UI {
var node = text.DataContext as Node; var node = text.DataContext as Node;
if (node != null) { if (node != null) {
if (node.IsRepo) { if (node.IsRepo) {
App.Preference.RenameRepository(node.Id, text.Text); App.Setting.RenameRepository(node.Id, text.Text);
} else { } else {
App.Preference.RenameGroup(node.Id, text.Text); App.Setting.RenameGroup(node.Id, text.Text);
} }
UpdateRecentOpened(); UpdateRecentOpened();
@ -345,7 +345,7 @@ namespace SourceGit.UI {
var refIdx = i; var refIdx = i;
mark.Click += (o, e) => { mark.Click += (o, e) => {
var repo = App.Preference.FindRepository(node.Id); var repo = App.Setting.FindRepository(node.Id);
if (repo != null) { if (repo != null) {
repo.Color = refIdx; repo.Color = refIdx;
UpdateRecentOpened(); UpdateRecentOpened();
@ -364,10 +364,10 @@ namespace SourceGit.UI {
var addSubFolder = new MenuItem(); var addSubFolder = new MenuItem();
addSubFolder.Header = "Add Sub-Folder"; addSubFolder.Header = "Add Sub-Folder";
addSubFolder.Click += (o, ev) => { addSubFolder.Click += (o, ev) => {
var parent = App.Preference.FindGroup(node.Id); var parent = App.Setting.FindGroup(node.Id);
if (parent != null) parent.IsExpended = true; if (parent != null) parent.IsExpended = true;
var group = App.Preference.AddGroup("New Group", node.Id); var group = App.Setting.AddGroup("New Group", node.Id);
UpdateTree(group.Id); UpdateTree(group.Id);
ev.Handled = true; ev.Handled = true;
}; };
@ -404,7 +404,7 @@ namespace SourceGit.UI {
popupManager.Show(new Init(popupManager, repo.Path)); popupManager.Show(new Init(popupManager, repo.Path));
} else { } else {
App.RaiseError("Path is NOT valid git repository or has been removed."); App.RaiseError("Path is NOT valid git repository or has been removed.");
App.Preference.RemoveRepository(repo.Path); App.Setting.RemoveRepository(repo.Path);
UpdateRecentOpened(); UpdateRecentOpened();
UpdateTree(); UpdateTree();
} }
@ -485,7 +485,7 @@ namespace SourceGit.UI {
return; return;
} }
var repo = App.Preference.AddRepository(path, ""); var repo = App.Setting.AddRepository(path, "");
App.Open(repo); App.Open(repo);
} }
@ -493,7 +493,7 @@ namespace SourceGit.UI {
/// Update recent opened repositories. /// Update recent opened repositories.
/// </summary> /// </summary>
private void UpdateRecentOpened() { private void UpdateRecentOpened() {
var sorted = App.Preference.Repositories.OrderByDescending(a => a.LastOpenTime).ToList(); var sorted = App.Setting.Repositories.OrderByDescending(a => a.LastOpenTime).ToList();
var top5 = new List<Git.Repository>(); var top5 = new List<Git.Repository>();
for (int i = 0; i < sorted.Count && i < 5; i++) { for (int i = 0; i < sorted.Count && i < 5; i++) {
@ -512,7 +512,7 @@ namespace SourceGit.UI {
var groupNodes = new Dictionary<string, Node>(); var groupNodes = new Dictionary<string, Node>();
var nodes = new List<Node>(); var nodes = new List<Node>();
foreach (var group in App.Preference.Groups) { foreach (var group in App.Setting.Groups) {
Node node = new Node() { Node node = new Node() {
Id = group.Id, Id = group.Id,
ParentId = group.ParentId, ParentId = group.ParentId,
@ -536,7 +536,7 @@ namespace SourceGit.UI {
} }
} }
foreach (var repo in App.Preference.Repositories) { foreach (var repo in App.Setting.Repositories) {
Node node = new Node() { Node node = new Node() {
Id = repo.Path, Id = repo.Path,
ParentId = repo.GroupId, ParentId = repo.GroupId,
@ -563,10 +563,10 @@ namespace SourceGit.UI {
/// <param name="node"></param> /// <param name="node"></param>
private void DeleteNode(Node node) { private void DeleteNode(Node node) {
if (node.IsRepo) { if (node.IsRepo) {
App.Preference.RemoveRepository(node.Id); App.Setting.RemoveRepository(node.Id);
UpdateRecentOpened(); UpdateRecentOpened();
} else { } else {
App.Preference.RemoveGroup(node.Id); App.Setting.RemoveGroup(node.Id);
} }
UpdateTree(); UpdateTree();

View file

@ -1,4 +1,4 @@
<Window x:Class="SourceGit.UI.Preference" <Window x:Class="SourceGit.UI.SettingDialog"
x:Name="me" x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@ -89,14 +89,14 @@
<CheckBox <CheckBox
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
IsChecked="{Binding Source={x:Static app:App.Preference}, Path=UseLightTheme, Mode=TwoWay}" IsChecked="{Binding Source={x:Static app:App.Setting}, Path=UI.UseLightTheme, Mode=TwoWay}"
Content="Restart required" Content="Restart required"
TextElement.FontStyle="Italic"/> TextElement.FontStyle="Italic"/>
<Label Grid.Row="2" Grid.Column="0" Content="Check for Update :" HorizontalAlignment="Right"/> <Label Grid.Row="2" Grid.Column="0" Content="Check for Update :" HorizontalAlignment="Right"/>
<CheckBox <CheckBox
Grid.Row="2" Grid.Row="2"
Grid.Column="1" Grid.Column="1"
IsChecked="{Binding Source={x:Static app:App.Preference}, Path=CheckUpdate, Mode=TwoWay}" IsChecked="{Binding Source={x:Static app:App.Setting}, Path=CheckUpdate, Mode=TwoWay}"
TextElement.FontStyle="Italic"/> TextElement.FontStyle="Italic"/>
<!-- GIT相关配置 --> <!-- GIT相关配置 -->
@ -111,7 +111,7 @@
<TextBox Grid.Column="0" <TextBox Grid.Column="0"
x:Name="txtGitPath" x:Name="txtGitPath"
Height="24" Height="24"
Text="{Binding Source={x:Static app:App.Preference}, Path=GitExecutable, Mode=TwoWay}" Text="{Binding Source={x:Static app:App.Setting}, Path=Tools.GitExecutable, Mode=TwoWay}"
helpers:TextBoxHelper.Placeholder="Input path for git.exe"/> helpers:TextBoxHelper.Placeholder="Input path for git.exe"/>
<Button Grid.Column="1" Width="24" Height="24" Click="SelectGitPath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}"> <Button Grid.Column="1" Width="24" Height="24" Click="SelectGitPath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}">
<Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/> <Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/>
@ -127,7 +127,7 @@
<TextBox Grid.Column="0" <TextBox Grid.Column="0"
x:Name="txtGitCloneDir" x:Name="txtGitCloneDir"
Height="24" Height="24"
Text="{Binding Source={x:Static app:App.Preference}, Path=GitDefaultCloneDir, Mode=TwoWay}" Text="{Binding Source={x:Static app:App.Setting}, Path=Tools.GitDefaultCloneDir, Mode=TwoWay}"
helpers:TextBoxHelper.Placeholder="Default path to clone repo into"/> helpers:TextBoxHelper.Placeholder="Default path to clone repo into"/>
<Button Grid.Column="1" Width="24" Height="24" Click="SelectDefaultClonePath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}"> <Button Grid.Column="1" Width="24" Height="24" Click="SelectDefaultClonePath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}">
<Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/> <Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/>
@ -165,7 +165,7 @@
Padding="2,0,0,0" Padding="2,0,0,0"
HorizontalContentAlignment="Left" HorizontalContentAlignment="Left"
VerticalContentAlignment="Center" VerticalContentAlignment="Center"
SelectedIndex="{Binding Source={x:Static app:App.Preference}, Path=MergeTool, Mode=TwoWay}" SelectedIndex="{Binding Source={x:Static app:App.Setting}, Path=Tools.MergeTool, Mode=TwoWay}"
ItemsSource="{Binding Source={x:Static git:MergeTool.Supported}}" ItemsSource="{Binding Source={x:Static git:MergeTool.Supported}}"
DisplayMemberPath="Name" DisplayMemberPath="Name"
SelectionChanged="ChangeMergeTool"/> SelectionChanged="ChangeMergeTool"/>
@ -179,7 +179,7 @@
<TextBox Grid.Column="0" <TextBox Grid.Column="0"
x:Name="txtMergePath" x:Name="txtMergePath"
Height="24" Height="24"
Text="{Binding Source={x:Static app:App.Preference}, Path=MergeExecutable, Mode=TwoWay}" Text="{Binding Source={x:Static app:App.Setting}, Path=Tools.MergeExecutable, Mode=TwoWay}"
helpers:TextBoxHelper.Placeholder="Input path for merge tool"/> helpers:TextBoxHelper.Placeholder="Input path for merge tool"/>
<Button Grid.Column="1" Width="24" Height="24" Click="SelectMergeToolPath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}"> <Button Grid.Column="1" Width="24" Height="24" Click="SelectMergeToolPath" Padding="0" BorderThickness="1" Style="{StaticResource Style.Button.Bordered}">
<Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/> <Path Width="14" Style="{StaticResource Style.Icon}" Data="{StaticResource Icon.Folder}"/>

View file

@ -11,7 +11,7 @@ namespace SourceGit.UI {
/// <summary> /// <summary>
/// Preference window. /// Preference window.
/// </summary> /// </summary>
public partial class Preference : Window { public partial class SettingDialog : Window {
/// <summary> /// <summary>
/// Git global user name. /// Git global user name.
@ -53,7 +53,7 @@ namespace SourceGit.UI {
/// <summary> /// <summary>
/// Constructor. /// Constructor.
/// </summary> /// </summary>
public Preference() { public SettingDialog() {
GlobalUser = GetConfig("user.name"); GlobalUser = GetConfig("user.name");
GlobalUserEmail = GetConfig("user.email"); GlobalUserEmail = GetConfig("user.email");
AutoCRLF = GetConfig("core.autocrlf"); AutoCRLF = GetConfig("core.autocrlf");
@ -61,7 +61,7 @@ namespace SourceGit.UI {
InitializeComponent(); InitializeComponent();
int mergeType = App.Preference.MergeTool; int mergeType = App.Setting.Tools.MergeTool;
var merger = Git.MergeTool.Supported[mergeType]; var merger = Git.MergeTool.Supported[mergeType];
txtMergePath.IsReadOnly = !merger.IsConfigured; txtMergePath.IsReadOnly = !merger.IsConfigured;
txtMergeParam.Text = merger.Parameter; txtMergeParam.Text = merger.Parameter;
@ -106,7 +106,7 @@ namespace SourceGit.UI {
if (dialog.ShowDialog() == true) { if (dialog.ShowDialog() == true) {
txtGitPath.Text = dialog.FileName; txtGitPath.Text = dialog.FileName;
App.Preference.GitExecutable = dialog.FileName; App.Setting.Tools.GitExecutable = dialog.FileName;
} }
} }
@ -118,7 +118,7 @@ namespace SourceGit.UI {
private void SelectDefaultClonePath(object sender, RoutedEventArgs e) { private void SelectDefaultClonePath(object sender, RoutedEventArgs e) {
FolderDailog.Open("Select default clone path", path => { FolderDailog.Open("Select default clone path", path => {
txtGitCloneDir.Text = path; txtGitCloneDir.Text = path;
App.Preference.GitDefaultCloneDir = path; App.Setting.Tools.GitDefaultCloneDir = path;
}); });
} }
@ -129,11 +129,11 @@ namespace SourceGit.UI {
/// <param name="e"></param> /// <param name="e"></param>
private void ChangeMergeTool(object sender, SelectionChangedEventArgs e) { private void ChangeMergeTool(object sender, SelectionChangedEventArgs e) {
if (IsLoaded) { if (IsLoaded) {
var t = Git.MergeTool.Supported[App.Preference.MergeTool]; var t = Git.MergeTool.Supported[App.Setting.Tools.MergeTool];
App.Preference.MergeExecutable = t.Finder(); App.Setting.Tools.MergeExecutable = t.Finder();
txtMergePath.Text = App.Preference.MergeExecutable; txtMergePath.Text = App.Setting.Tools.MergeExecutable;
txtMergeParam.Text = t.Parameter; txtMergeParam.Text = t.Parameter;
txtMergePath.IsReadOnly = !t.IsConfigured; txtMergePath.IsReadOnly = !t.IsConfigured;
} }
@ -145,7 +145,7 @@ namespace SourceGit.UI {
/// <param name="sender"></param> /// <param name="sender"></param>
/// <param name="e"></param> /// <param name="e"></param>
private void SelectMergeToolPath(object sender, RoutedEventArgs e) { private void SelectMergeToolPath(object sender, RoutedEventArgs e) {
int mergeType = App.Preference.MergeTool; int mergeType = App.Setting.Tools.MergeTool;
if (mergeType == 0) return; if (mergeType == 0) return;
var merger = Git.MergeTool.Supported[mergeType]; var merger = Git.MergeTool.Supported[mergeType];
@ -157,7 +157,7 @@ namespace SourceGit.UI {
if (dialog.ShowDialog() == true) { if (dialog.ShowDialog() == true) {
txtMergePath.Text = dialog.FileName; txtMergePath.Text = dialog.FileName;
App.Preference.MergeExecutable = dialog.FileName; App.Setting.Tools.MergeExecutable = dialog.FileName;
} }
} }
@ -180,7 +180,7 @@ namespace SourceGit.UI {
if (!App.IsGitConfigured) return ""; if (!App.IsGitConfigured) return "";
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = App.Preference.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = $"config --global {key}"; startInfo.Arguments = $"config --global {key}";
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true; startInfo.CreateNoWindow = true;
@ -200,7 +200,7 @@ namespace SourceGit.UI {
if (!App.IsGitConfigured) return; if (!App.IsGitConfigured) return;
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.FileName = App.Preference.GitExecutable; startInfo.FileName = App.Setting.Tools.GitExecutable;
startInfo.Arguments = $"config --global {key} \"{val}\""; startInfo.Arguments = $"config --global {key} \"{val}\"";
startInfo.UseShellExecute = false; startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true; startInfo.CreateNoWindow = true;

View file

@ -51,7 +51,7 @@
Margin="4,0,0,0" Margin="4,0,0,0"
ToolTip="SWITCH TO LIST/TREE VIEW" ToolTip="SWITCH TO LIST/TREE VIEW"
Style="{StaticResource Style.ToggleButton.ListOrTree}" Style="{StaticResource Style.ToggleButton.ListOrTree}"
IsChecked="{Binding Source={x:Static source:App.Preference}, Path=UIUseListInChanges, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static source:App.Setting}, Path=UI.UseListInChanges, Mode=TwoWay}"/>
</Grid> </Grid>
<TreeView <TreeView

View file

@ -59,7 +59,7 @@
<local:FilesDisplayModeSwitch <local:FilesDisplayModeSwitch
Grid.Column="0" Grid.Column="0"
Mode="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Mode=TwoWay}" Mode="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Mode=TwoWay}"
Opacity=".4"/> Opacity=".4"/>
<Label Grid.Column="1" Content="UNSTAGED" FontWeight="Bold" Foreground="{StaticResource Brush.FG}" Opacity=".4"/> <Label Grid.Column="1" Content="UNSTAGED" FontWeight="Bold" Foreground="{StaticResource Brush.FG}" Opacity=".4"/>
<Button Grid.Column="3" Click="Stage" Margin="4,0" ToolTip="STAGE" Background="Transparent"> <Button Grid.Column="3" Click="Stage" Margin="4,0" ToolTip="STAGE" Background="Transparent">
@ -74,7 +74,7 @@
Grid.Row="1" Grid.Row="1"
x:Name="unstagedTree" x:Name="unstagedTree"
Background="{StaticResource Brush.BG2}" Background="{StaticResource Brush.BG2}"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Converter={StaticResource FilesDisplayModeToTree}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Converter={StaticResource FilesDisplayModeToTree}}"
FontFamily="Consolas" FontFamily="Consolas"
PreviewMouseWheel="TreeMouseWheel" PreviewMouseWheel="TreeMouseWheel"
helpers:TreeViewHelper.EnableMultiSelection="True" helpers:TreeViewHelper.EnableMultiSelection="True"
@ -127,7 +127,7 @@
<DataGrid <DataGrid
Grid.Row="1" Grid.Row="1"
x:Name="unstagedList" x:Name="unstagedList"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Converter={StaticResource FilesDisplayModeToList}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Converter={StaticResource FilesDisplayModeToList}}"
RowHeight="24" RowHeight="24"
SelectionChanged="UnstagedListSelectionChanged" SelectionChanged="UnstagedListSelectionChanged"
SelectionMode="Extended" SelectionMode="Extended"
@ -163,7 +163,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="Auto" Width="Auto"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}"
Binding="{Binding Path, Converter={StaticResource PathToFileName}}" Binding="{Binding Path, Converter={StaticResource PathToFileName}}"
Foreground="{StaticResource Brush.FG}" Foreground="{StaticResource Brush.FG}"
FontFamily="Consolas" FontFamily="Consolas"
@ -171,7 +171,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}"
Binding="{Binding Path, Converter={StaticResource PathToFolderName}}" Binding="{Binding Path, Converter={StaticResource PathToFolderName}}"
Foreground="{StaticResource Brush.FG2}" Foreground="{StaticResource Brush.FG2}"
FontFamily="Consolas" FontFamily="Consolas"
@ -179,7 +179,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIUnstageDisplayMode, Converter={StaticResource FilesDisplayModeToListOnly}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.UnstageFileDisplayMode, Converter={StaticResource FilesDisplayModeToListOnly}}"
Binding="{Binding Path}" Binding="{Binding Path}"
Foreground="{StaticResource Brush.FG}" Foreground="{StaticResource Brush.FG}"
FontFamily="Consolas" FontFamily="Consolas"
@ -215,7 +215,7 @@
<local:FilesDisplayModeSwitch <local:FilesDisplayModeSwitch
Grid.Column="0" Grid.Column="0"
Mode="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Mode=TwoWay}" Mode="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Mode=TwoWay}"
Opacity=".4"/> Opacity=".4"/>
<Label Grid.Column="1" Content="STAGED" FontWeight="Bold" Foreground="{StaticResource Brush.FG}" Opacity=".4"/> <Label Grid.Column="1" Content="STAGED" FontWeight="Bold" Foreground="{StaticResource Brush.FG}" Opacity=".4"/>
<Button Grid.Column="3" Click="Unstage" ToolTip="UNSTAGE" Margin="4,0" Background="Transparent"> <Button Grid.Column="3" Click="Unstage" ToolTip="UNSTAGE" Margin="4,0" Background="Transparent">
@ -229,7 +229,7 @@
<TreeView <TreeView
Grid.Row="1" Grid.Row="1"
x:Name="stageTree" x:Name="stageTree"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Converter={StaticResource FilesDisplayModeToTree}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Converter={StaticResource FilesDisplayModeToTree}}"
Background="{StaticResource Brush.BG2}" Background="{StaticResource Brush.BG2}"
FontFamily="Consolas" FontFamily="Consolas"
PreviewMouseWheel="TreeMouseWheel" PreviewMouseWheel="TreeMouseWheel"
@ -284,7 +284,7 @@
Grid.Row="1" Grid.Row="1"
x:Name="stageList" x:Name="stageList"
RowHeight="24" RowHeight="24"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Converter={StaticResource FilesDisplayModeToList}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Converter={StaticResource FilesDisplayModeToList}}"
SelectionChanged="StagedListSelectionChanged" SelectionChanged="StagedListSelectionChanged"
SelectionMode="Extended" SelectionMode="Extended"
SelectionUnit="FullRow" SelectionUnit="FullRow"
@ -319,7 +319,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="Auto" Width="Auto"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}"
Binding="{Binding Path, Converter={StaticResource PathToFileName}}" Binding="{Binding Path, Converter={StaticResource PathToFileName}}"
Foreground="{StaticResource Brush.FG}" Foreground="{StaticResource Brush.FG}"
FontFamily="Consolas" FontFamily="Consolas"
@ -327,7 +327,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Converter={StaticResource FilesDisplayModeToGrid}}"
Binding="{Binding Path, Converter={StaticResource PathToFolderName}}" Binding="{Binding Path, Converter={StaticResource PathToFolderName}}"
Foreground="{StaticResource Brush.FG2}" Foreground="{StaticResource Brush.FG2}"
FontFamily="Consolas" FontFamily="Consolas"
@ -335,7 +335,7 @@
<DataGridTextColumn <DataGridTextColumn
Width="*" Width="*"
Visibility="{Binding Source={x:Static source:App.Preference}, Path=UIStagedDisplayMode, Converter={StaticResource FilesDisplayModeToListOnly}}" Visibility="{Binding Source={x:Static source:App.Setting}, Path=UI.StagedFileDisplayMode, Converter={StaticResource FilesDisplayModeToListOnly}}"
Binding="{Binding Path}" Binding="{Binding Path}"
Foreground="{StaticResource Brush.FG}" Foreground="{StaticResource Brush.FG}"
FontFamily="Consolas" FontFamily="Consolas"

View file

@ -507,7 +507,7 @@ namespace SourceGit.UI {
private async void Stage(object sender, RoutedEventArgs e) { private async void Stage(object sender, RoutedEventArgs e) {
var files = new List<string>(); var files = new List<string>();
if (App.Preference.UIUnstageDisplayMode != Git.Preference.FilesDisplayMode.Tree) { if (App.Setting.UI.UnstageFileDisplayMode != Preference.FilesDisplayMode.Tree) {
var selected = unstagedList.SelectedItems; var selected = unstagedList.SelectedItems;
foreach (var one in selected) { foreach (var one in selected) {
var node = one as Git.Change; var node = one as Git.Change;
@ -707,7 +707,7 @@ namespace SourceGit.UI {
private async void Unstage(object sender, RoutedEventArgs e) { private async void Unstage(object sender, RoutedEventArgs e) {
var files = new List<string>(); var files = new List<string>();
if (App.Preference.UIStagedDisplayMode != Git.Preference.FilesDisplayMode.Tree) { if (App.Setting.UI.StagedFileDisplayMode != Preference.FilesDisplayMode.Tree) {
var selected = stageList.SelectedItems; var selected = stageList.SelectedItems;
foreach (var one in selected) { foreach (var one in selected) {
var node = one as Git.Change; var node = one as Git.Change;
@ -870,8 +870,8 @@ namespace SourceGit.UI {
#region MERGE #region MERGE
private async void OpenMergeTool(object sender, RoutedEventArgs e) { private async void OpenMergeTool(object sender, RoutedEventArgs e) {
var mergeExe = App.Preference.MergeExecutable; var mergeExe = App.Setting.Tools.MergeExecutable;
var mergeParam = Git.MergeTool.Supported[App.Preference.MergeTool].Parameter; var mergeParam = Git.MergeTool.Supported[App.Setting.Tools.MergeTool].Parameter;
if (!File.Exists(mergeExe) || mergeParam.IndexOf("$MERGED") < 0) { if (!File.Exists(mergeExe) || mergeParam.IndexOf("$MERGED") < 0) {
App.RaiseError("Invalid merge tool in preference setting!"); App.RaiseError("Invalid merge tool in preference setting!");
@ -879,7 +879,7 @@ namespace SourceGit.UI {
} }
string file = null; string file = null;
if (App.Preference.UIUnstageDisplayMode != Git.Preference.FilesDisplayMode.Tree) { if (App.Setting.UI.UnstageFileDisplayMode != Preference.FilesDisplayMode.Tree) {
var selected = unstagedList.SelectedItems; var selected = unstagedList.SelectedItems;
if (selected.Count <= 0) return; if (selected.Count <= 0) return;
@ -906,7 +906,7 @@ namespace SourceGit.UI {
private async void UseTheirs(object sender, RoutedEventArgs e) { private async void UseTheirs(object sender, RoutedEventArgs e) {
var files = new List<string>(); var files = new List<string>();
if (App.Preference.UIUnstageDisplayMode != Git.Preference.FilesDisplayMode.Tree) { if (App.Setting.UI.UnstageFileDisplayMode != Preference.FilesDisplayMode.Tree) {
var selected = unstagedList.SelectedItems; var selected = unstagedList.SelectedItems;
foreach (var one in selected) { foreach (var one in selected) {
var node = one as Git.Change; var node = one as Git.Change;
@ -935,7 +935,7 @@ namespace SourceGit.UI {
private async void UseMine(object sender, RoutedEventArgs e) { private async void UseMine(object sender, RoutedEventArgs e) {
var files = new List<string>(); var files = new List<string>();
if (App.Preference.UIUnstageDisplayMode != Git.Preference.FilesDisplayMode.Tree) { if (App.Setting.UI.UnstageFileDisplayMode != Preference.FilesDisplayMode.Tree) {
var selected = unstagedList.SelectedItems; var selected = unstagedList.SelectedItems;
foreach (var one in selected) { foreach (var one in selected) {
var node = one as Git.Change; var node = one as Git.Change;