mirror of
https://github.com/sourcegit-scm/sourcegit
synced 2025-05-22 12:45:00 +00:00
341 lines
11 KiB
C#
341 lines
11 KiB
C#
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using System.Text.Json;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
|
|
namespace SourceGit.UI {
|
|
|
|
/// <summary>
|
|
/// Main window for this app.
|
|
/// </summary>
|
|
public partial class Launcher : Window {
|
|
|
|
/// <summary>
|
|
/// Tab data.
|
|
/// </summary>
|
|
public class Tab : INotifyPropertyChanged {
|
|
private bool isActive = false;
|
|
|
|
public string Title { get; set; }
|
|
public string Tooltip { get; set; }
|
|
public Git.Repository Repo { get; set; }
|
|
public object Page { get; set; }
|
|
|
|
public bool IsRepo {
|
|
get { return Repo != null; }
|
|
}
|
|
|
|
public int Color {
|
|
get { return Repo == null ? 0 : Repo.Color; }
|
|
set {
|
|
if (Repo == null || Repo.Color == value) return;
|
|
Repo.Color = value;
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
|
|
}
|
|
}
|
|
|
|
public bool IsActive {
|
|
get { return isActive; }
|
|
set {
|
|
if (isActive == value) return;
|
|
isActive = value;
|
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsActive"));
|
|
}
|
|
}
|
|
|
|
public event PropertyChangedEventHandler PropertyChanged;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Manager tab
|
|
/// </summary>
|
|
public class ManagerTab : Tab {
|
|
public ManagerTab() {
|
|
Title = "HOME";
|
|
Tooltip = "Repositories Manager";
|
|
IsActive = true;
|
|
Page = new Manager();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Repository tab.
|
|
/// </summary>
|
|
public class RepoTab : Tab {
|
|
public RepoTab(Git.Repository repo, Dashboard page) {
|
|
Title = repo.Parent == null ? repo.Name : $"{repo.Parent.Name} : {repo.Name}";
|
|
Tooltip = repo.Path;
|
|
Repo = repo;
|
|
IsActive = false;
|
|
Page = page;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Alerts.
|
|
/// </summary>
|
|
public ObservableCollection<string> Errors { get; set; } = new ObservableCollection<string>();
|
|
|
|
/// <summary>
|
|
/// Opened tabs.
|
|
/// </summary>
|
|
public ObservableCollection<Tab> Tabs { get; set; } = new ObservableCollection<Tab>();
|
|
|
|
/// <summary>
|
|
/// Constructor
|
|
/// </summary>
|
|
public Launcher() {
|
|
Tabs.Add(new ManagerTab());
|
|
InitializeComponent();
|
|
openedTabs.SelectedItem = Tabs[0];
|
|
if (App.Setting.CheckUpdate) Task.Run(CheckUpdate);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open repository
|
|
/// </summary>
|
|
/// <param name="repo"></param>
|
|
public void Open(Git.Repository repo) {
|
|
for (int i = 1; i < Tabs.Count; i++) {
|
|
var opened = Tabs[i];
|
|
if (opened.Repo.Path == repo.Path) {
|
|
openedTabs.SelectedItem = opened;
|
|
return;
|
|
}
|
|
}
|
|
|
|
repo.Open();
|
|
var page = new Dashboard(repo);
|
|
var tab = new RepoTab(repo, page);
|
|
repo.SetPopupManager(page.popupManager);
|
|
Tabs.Add(tab);
|
|
openedTabs.SelectedItem = tab;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checking for update.
|
|
/// </summary>
|
|
public void CheckUpdate() {
|
|
try {
|
|
var web = new WebClient();
|
|
var raw = web.DownloadString("https://gitee.com/api/v5/repos/sourcegit/SourceGit/releases/latest");
|
|
var ver = JsonSerializer.Deserialize<Git.Version>(raw);
|
|
var cur = Assembly.GetExecutingAssembly().GetName().Version;
|
|
|
|
var matches = Regex.Match(ver.TagName, @"^v(\d+)\.(\d+).*");
|
|
if (!matches.Success) return;
|
|
|
|
var major = int.Parse(matches.Groups[1].Value);
|
|
var minor = int.Parse(matches.Groups[2].Value);
|
|
if (major > cur.Major || (major == cur.Major && minor > cur.Minor)) {
|
|
Dispatcher.Invoke(() => {
|
|
var dialog = new UpdateAvailable(ver);
|
|
dialog.Owner = this;
|
|
dialog.ShowDialog();
|
|
});
|
|
}
|
|
} catch {
|
|
// IGNORE
|
|
}
|
|
}
|
|
|
|
#region LAYOUT_CONTENT
|
|
/// <summary>
|
|
/// Close repository.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void CloseRepo(object sender, RoutedEventArgs e) {
|
|
var tab = (sender as Button).DataContext as Tab;
|
|
if (tab == null || tab.Repo == null) {
|
|
e.Handled = true;
|
|
return;
|
|
}
|
|
|
|
Tabs.Remove(tab);
|
|
|
|
tab.Page = null;
|
|
tab.Repo.RemovePopup();
|
|
tab.Repo.Close();
|
|
tab.Repo = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Context menu for tab items.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void TabsContextMenuOpening(object sender, ContextMenuEventArgs ev) {
|
|
var tab = (sender as TabItem).DataContext as Tab;
|
|
if (tab == null || tab.Repo == null) {
|
|
ev.Handled = true;
|
|
return;
|
|
}
|
|
|
|
var repo = tab.Repo;
|
|
|
|
var refresh = new MenuItem();
|
|
refresh.Header = "Refresh";
|
|
refresh.Click += (o, e) => {
|
|
repo.AssertCommand(null);
|
|
e.Handled = true;
|
|
};
|
|
|
|
var iconBookmark = FindResource("Icon.Bookmark") as Geometry;
|
|
var bookmark = new MenuItem();
|
|
bookmark.Header = "Bookmark";
|
|
for (int i = 0; i < Converters.IntToRepoColor.Colors.Length; i++) {
|
|
var icon = new System.Windows.Shapes.Path();
|
|
icon.Style = FindResource("Style.Icon") as Style;
|
|
icon.Data = iconBookmark;
|
|
icon.Fill = Converters.IntToRepoColor.Colors[i];
|
|
icon.Width = 8;
|
|
|
|
var mark = new MenuItem();
|
|
mark.Icon = icon;
|
|
mark.Header = $"{i}";
|
|
|
|
var refIdx = i;
|
|
mark.Click += (o, e) => {
|
|
tab.Color = refIdx;
|
|
e.Handled = true;
|
|
};
|
|
|
|
bookmark.Items.Add(mark);
|
|
}
|
|
|
|
var copyPath = new MenuItem();
|
|
copyPath.Header = "Copy path";
|
|
copyPath.Click += (o, e) => {
|
|
Clipboard.SetText(repo.Path);
|
|
e.Handled = true;
|
|
};
|
|
|
|
var menu = new ContextMenu();
|
|
menu.Items.Add(refresh);
|
|
menu.Items.Add(bookmark);
|
|
menu.Items.Add(copyPath);
|
|
menu.IsOpen = true;
|
|
|
|
ev.Handled = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open preference dialog.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void ShowPreference(object sender, RoutedEventArgs e) {
|
|
var dialog = new SettingDialog();
|
|
dialog.Owner = this;
|
|
dialog.ShowDialog();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Open about dialog.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void ShowAbout(object sender, RoutedEventArgs e) {
|
|
var about = new About();
|
|
about.Owner = this;
|
|
about.ShowDialog();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Remove an alert.
|
|
/// </summary>
|
|
/// <param name="sender"></param>
|
|
/// <param name="e"></param>
|
|
private void RemoveError(object sender, RoutedEventArgs e) {
|
|
var alert = (sender as Button).DataContext as string;
|
|
Errors.Remove(alert);
|
|
}
|
|
#endregion
|
|
|
|
#region WINDOW_COMMANDS
|
|
/// <summary>
|
|
/// Minimize
|
|
/// </summary>
|
|
private void Minimize(object sender, RoutedEventArgs e) {
|
|
SystemCommands.MinimizeWindow(this);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Maximize/Restore
|
|
/// </summary>
|
|
private void MaximizeOrRestore(object sender, RoutedEventArgs e) {
|
|
if (WindowState == WindowState.Normal) {
|
|
SystemCommands.MaximizeWindow(this);
|
|
} else {
|
|
SystemCommands.RestoreWindow(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Quit
|
|
/// </summary>
|
|
private void Quit(object sender, RoutedEventArgs e) {
|
|
App.Current.Shutdown();
|
|
}
|
|
#endregion
|
|
|
|
#region DRAG_DROP
|
|
private void TabsMouseMove(object sender, MouseEventArgs e) {
|
|
var item = e.Source as TabItem;
|
|
if (item == null) return;
|
|
|
|
var tab = item.DataContext as Tab;
|
|
if (tab == null || tab.Repo == null) return;
|
|
|
|
if (Mouse.LeftButton == MouseButtonState.Pressed) {
|
|
DragDrop.DoDragDrop(item, item, DragDropEffects.All);
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void TabsDrop(object sender, DragEventArgs e) {
|
|
var tabItemSrc = e.Data.GetData(typeof(TabItem)) as TabItem;
|
|
var tabItemDst = e.Source as TabItem;
|
|
if (tabItemSrc.Equals(tabItemDst)) return;
|
|
|
|
var tabSrc = tabItemSrc.DataContext as Tab;
|
|
var tabDst = tabItemDst.DataContext as Tab;
|
|
if (tabDst.Repo == null) {
|
|
Tabs.Remove(tabSrc);
|
|
Tabs.Insert(1, tabSrc);
|
|
} else {
|
|
int dstIdx = Tabs.IndexOf(tabDst);
|
|
|
|
Tabs.Remove(tabSrc);
|
|
Tabs.Insert(dstIdx, tabSrc);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region TAB_SCROLL
|
|
private void OpenedTabsSizeChanged(object sender, SizeChangedEventArgs e) {
|
|
if (openedTabs.ActualWidth > openedTabsColumn.ActualWidth) {
|
|
openedTabsOpts.Visibility = Visibility.Visible;
|
|
} else {
|
|
openedTabsOpts.Visibility = Visibility.Collapsed;
|
|
}
|
|
}
|
|
|
|
private void ScrollToLeft(object sender, RoutedEventArgs e) {
|
|
openedTabsScroller.LineLeft();
|
|
}
|
|
|
|
private void ScrollToRight(object sender, RoutedEventArgs e) {
|
|
openedTabsScroller.LineRight();
|
|
}
|
|
#endregion
|
|
}
|
|
}
|