optimize<Popup>: remove popup from welcome page

This commit is contained in:
leo 2022-10-19 15:20:58 +08:00
parent b1102ac035
commit 8520786b7e
13 changed files with 443 additions and 368 deletions

View file

@ -7,11 +7,13 @@ namespace SourceGit.Commands {
/// </summary> /// </summary>
public class Clone : Command { public class Clone : Command {
private Action<string> handler = null; private Action<string> handler = null;
private Action<string> onError = null;
public Clone(string path, string url, string localName, string sshKey, string extraArgs, Action<string> outputHandler) { public Clone(string path, string url, string localName, string sshKey, string extraArgs, Action<string> outputHandler, Action<string> errHandler) {
Cwd = path; Cwd = path;
TraitErrorAsOutput = true; TraitErrorAsOutput = true;
handler = outputHandler; handler = outputHandler;
onError = errHandler;
if (!string.IsNullOrEmpty(sshKey)) { if (!string.IsNullOrEmpty(sshKey)) {
Envs.Add("GIT_SSH_COMMAND", $"ssh -i '{sshKey}'"); Envs.Add("GIT_SSH_COMMAND", $"ssh -i '{sshKey}'");
@ -30,5 +32,9 @@ namespace SourceGit.Commands {
public override void OnReadline(string line) { public override void OnReadline(string line) {
handler?.Invoke(line); handler?.Invoke(line);
} }
public override void OnException(string message) {
onError?.Invoke(message);
}
} }
} }

View file

@ -112,7 +112,7 @@ namespace SourceGit.Commands {
try { try {
proc.Start(); proc.Start();
} catch (Exception e) { } catch (Exception e) {
if (!DontRaiseError) Models.Exception.Raise(e.Message); if (!DontRaiseError) OnException(e.Message);
return false; return false;
} }
@ -124,7 +124,7 @@ namespace SourceGit.Commands {
proc.Close(); proc.Close();
if (!isCancelled && exitCode != 0 && errs.Count > 0) { if (!isCancelled && exitCode != 0 && errs.Count > 0) {
if (!DontRaiseError) Models.Exception.Raise(string.Join("\n", errs)); if (!DontRaiseError) OnException(string.Join("\n", errs));
return false; return false;
} else { } else {
return true; return true;
@ -173,6 +173,15 @@ namespace SourceGit.Commands {
/// 调用Exec时的读取函数 /// 调用Exec时的读取函数
/// </summary> /// </summary>
/// <param name="line"></param> /// <param name="line"></param>
public virtual void OnReadline(string line) { } public virtual void OnReadline(string line) {
}
/// <summary>
/// 默认异常处理函数
/// </summary>
/// <param name="message"></param>
public virtual void OnException(string message) {
Models.Exception.Raise(message);
}
} }
} }

256
src/Views/Clone.xaml Normal file
View file

@ -0,0 +1,256 @@
<controls:Window
x:Class="SourceGit.Views.Clone"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
xmlns:validations="clr-namespace:SourceGit.Views.Validations"
mc:Ignorable="d"
WindowStartupLocation="CenterOwner"
Title="{DynamicResource Text.Clone}"
Width="500" SizeToContent="Height"
ResizeMode="NoResize">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"/>
<RowDefinition Height="1"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title bar -->
<Grid Grid.Row="0" Background="{DynamicResource Brush.TitleBar}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Icon -->
<Path Grid.Column="0" Margin="6,0" Width="16" Height="16" Data="{StaticResource Icon.Pull}"/>
<!-- Title -->
<TextBlock Grid.Column="1" Text="{DynamicResource Text.Clone}"/>
<!-- Close -->
<controls:IconButton
Grid.Column="3"
Click="OnQuit"
Width="28"
Padding="8"
Icon="{StaticResource Icon.Close}"
HoverBackground="Red"
WindowChrome.IsHitTestVisibleInChrome="True"/>
</Grid>
<Rectangle
Grid.Row="1"
Height="1"
HorizontalAlignment="Stretch"
Fill="{DynamicResource Brush.Border0}"/>
<Grid Grid.Row="2">
<!-- Body -->
<Grid Margin="8">
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition x:Name="rowSSHKey" Height="0"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="48"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Clone.RemoteURL}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="0" Grid.Column="1"
x:Name="txtUrl"
Height="24"
Placeholder="{DynamicResource Text.Clone.RemoteURL.Placeholder}"
TextChanged="OnUrlChanged">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="Uri" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:GitURL/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.SSHKey}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<controls:TextEdit
Grid.Column="0"
x:Name="txtSSHKey"
Height="24"
Placeholder="{DynamicResource Text.SSHKey.Placeholder}"/>
<controls:IconButton
Grid.Column="1"
Click="OnSelectSSHKey"
Width="24" Height="24"
Margin="2,0,0,0" Padding="4"
BorderBrush="{DynamicResource Brush.Border1}"
BorderThickness="1"
Icon="{StaticResource Icon.Folder.Open}"/>
</Grid>
<TextBlock
Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Clone.Folder}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<controls:TextEdit
Grid.Column="0"
x:Name="txtFolder"
Height="24"
Placeholder="{DynamicResource Text.Clone.Folder.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="Folder" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:CloneDir/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<controls:IconButton
Grid.Column="1"
Click="OnFolderSelectorClick"
Width="24" Height="24"
Margin="2,0,0,0" Padding="4"
BorderBrush="{DynamicResource Brush.Border1}"
BorderThickness="1"
Icon="{StaticResource Icon.Folder.Open}"/>
</Grid>
<TextBlock
Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Clone.LocalName}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="3" Grid.Column="1"
Height="24"
x:Name="txtLocal"
Placeholder="{DynamicResource Text.Clone.LocalName.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="LocalName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:LocalRepositoryName/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="4" Grid.Column="0"
Text="{DynamicResource Text.Clone.RemoteName}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="4" Grid.Column="1"
x:Name="txtRemote"
Height="24"
Placeholder="{DynamicResource Text.Clone.RemoteName.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="RemoteName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:RemoteName x:Name="ruleRemote"/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="5" Grid.Column="0"
Text="{DynamicResource Text.Clone.AdditionalParam}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="5" Grid.Column="1"
Height="24"
Placeholder="{DynamicResource Text.Clone.AdditionalParam.Placeholder}"
Text="{Binding ElementName=me, Path=ExtraArgs, Mode=TwoWay}"/>
<StackPanel
Grid.Row="6" Grid.Column="0" Grid.ColumnSpan="2"
Height="32"
Orientation="Horizontal"
HorizontalAlignment="Right" VerticalAlignment="Center">
<Button Click="OnStart" Width="80" Content="{DynamicResource Text.Sure}" BorderBrush="{DynamicResource Brush.FG1}" Background="{DynamicResource Brush.Accent1}" FontWeight="Bold"/>
<Button Click="OnQuit" Width="80" Margin="8,0,0,0" Content="{DynamicResource Text.Cancel}" FontWeight="Bold"/>
</StackPanel>
</Grid>
<!-- Progress -->
<Border x:Name="progress" Visibility="Collapsed" Background="{DynamicResource Brush.Popup}" Opacity=".9">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<controls:Loading x:Name="processing" Width="48" Height="48"/>
<TextBlock x:Name="txtProgress" Margin="0,16,0,0"/>
</StackPanel>
</Border>
<!-- Exception -->
<Grid x:Name="exception" Margin="8" Visibility="Collapsed" Background="{DynamicResource Brush.Window}">
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition Height="*"/>
<RowDefinition Height="48"/>
</Grid.RowDefinitions>
<TextBlock
Grid.Row="0"
Text="{DynamicResource Text.Launcher.Error}"
FontWeight="Bold"/>
<controls:TextEdit
Grid.Row="1"
x:Name="txtError"
IsReadOnly="true"
BorderThickness="0"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto"
MaxHeight="80"
Margin="0,8"
VerticalAlignment="Top"/>
<Button
Grid.Row="2"
Height="26"
Margin="4,0" Padding="8,0"
Click="OnCloseException"
Content="{DynamicResource Text.Sure}"
Background="{DynamicResource Brush.Accent1}"
BorderBrush="{DynamicResource Brush.FG1}"
BorderThickness="1"
HorizontalAlignment="Right"/>
</Grid>
</Grid>
</Grid>
</controls:Window>

View file

@ -1,16 +1,17 @@
using Microsoft.Win32; using Microsoft.Win32;
using SourceGit.Views.Validations;
using System; using System;
using System.IO; 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;
namespace SourceGit.Views.Popups { namespace SourceGit.Views {
/// <summary> /// <summary>
/// 克隆 /// 克隆
/// </summary> /// </summary>
public partial class Clone : Controls.PopupWidget { public partial class Clone : Controls.Window {
public string Uri { get; set; } public string Uri { get; set; }
public string Folder { get; set; } public string Folder { get; set; }
@ -24,24 +25,32 @@ namespace SourceGit.Views.Popups {
ruleRemote.IsOptional = true; ruleRemote.IsOptional = true;
} }
public override string GetTitle() { #region EVENTS
return App.Text("Clone"); private void OnQuit(object sender, RoutedEventArgs e) {
Close();
} }
public override Task<bool> Start() { private async void OnStart(object s, RoutedEventArgs e) {
var checks = new Controls.TextEdit[] { txtUrl, txtFolder, txtLocal, txtRemote }; var checks = new Controls.TextEdit[] { txtUrl, txtFolder, txtLocal, txtRemote };
foreach (var edit in checks) { foreach (var edit in checks) {
edit.GetBindingExpression(TextBox.TextProperty).UpdateSource(); edit.GetBindingExpression(TextBox.TextProperty).UpdateSource();
if (Validation.GetHasError(edit)) return null; if (Validation.GetHasError(edit)) return;
} }
var sshKey = txtSSHKey.Text; progress.Visibility = Visibility.Visible;
processing.IsAnimating = true;
return Task.Run(() => { var sshKey = txtSSHKey.Text;
var succ = await Task.Run(() => {
var extras = string.IsNullOrEmpty(ExtraArgs) ? "" : ExtraArgs; var extras = string.IsNullOrEmpty(ExtraArgs) ? "" : ExtraArgs;
if (!string.IsNullOrEmpty(RemoteName)) extras += $" --origin {RemoteName}"; if (!string.IsNullOrEmpty(RemoteName)) extras += $" --origin {RemoteName}";
var succ = new Commands.Clone(Folder, Uri, LocalName, sshKey, extras, UpdateProgress).Exec(); var succ = new Commands.Clone(Folder, Uri, LocalName, sshKey, extras, msg => {
Dispatcher.Invoke(() => txtProgress.Text = msg);
}, err => {
Dispatcher.Invoke(() => txtError.Text = err);
}).Exec();
if (!succ) return false; if (!succ) return false;
var path = Folder; var path = Folder;
@ -70,6 +79,14 @@ namespace SourceGit.Views.Popups {
if (repo != null) Dispatcher.Invoke(() => Models.Watcher.Open(repo)); if (repo != null) Dispatcher.Invoke(() => Models.Watcher.Open(repo));
return true; return true;
}); });
progress.Visibility = Visibility.Collapsed;
processing.IsAnimating = false;
if (succ) {
Close();
} else {
exception.Visibility = Visibility.Visible;
}
} }
private void OnFolderSelectorClick(object sender, RoutedEventArgs e) { private void OnFolderSelectorClick(object sender, RoutedEventArgs e) {
@ -101,5 +118,11 @@ namespace SourceGit.Views.Popups {
rowSSHKey.Height = new GridLength(0, GridUnitType.Pixel); rowSSHKey.Height = new GridLength(0, GridUnitType.Pixel);
} }
} }
private void OnCloseException(object s, RoutedEventArgs e) {
exception.Visibility = Visibility.Collapsed;
e.Handled = true;
}
#endregion
} }
} }

View file

@ -12,6 +12,7 @@ namespace SourceGit.Views.Controls {
void Show(PopupWidget widget); void Show(PopupWidget widget);
void ShowAndStart(PopupWidget widget); void ShowAndStart(PopupWidget widget);
void UpdateProgress(string message); void UpdateProgress(string message);
void ClosePopups(bool unlock);
} }
/// <summary> /// <summary>
@ -45,7 +46,7 @@ namespace SourceGit.Views.Controls {
/// </summary> /// </summary>
/// <param name="id">容器ID</param> /// <param name="id">容器ID</param>
public static void SetCurrentContainer(string id) { public static void SetCurrentContainer(string id) {
currentContainer = id; if (containers.ContainsKey(id)) currentContainer = id;
} }
/// <summary> /// <summary>

View file

@ -145,7 +145,6 @@ namespace SourceGit.Views {
private void OnTabAdding(object sender, Widgets.PageTabBar.TabEventArgs e) { private void OnTabAdding(object sender, Widgets.PageTabBar.TabEventArgs e) {
var page = new Widgets.Welcome(); var page = new Widgets.Welcome();
container.Add(e.TabId, page); container.Add(e.TabId, page);
Controls.PopupWidget.RegisterContainer(e.TabId, page);
} }
private void OnTabSelected(object sender, Widgets.PageTabBar.TabEventArgs e) { private void OnTabSelected(object sender, Widgets.PageTabBar.TabEventArgs e) {
@ -211,16 +210,8 @@ namespace SourceGit.Views {
} }
if (Keyboard.IsKeyDown(Key.Escape)) { if (Keyboard.IsKeyDown(Key.Escape)) {
var page = container.Get(tabs.Current); var popup = container.Get(tabs.Current) as Controls.IPopupContainer;
popup?.ClosePopups(false);
var popup = null as Widgets.PopupPanel;
if (page is Widgets.Dashboard) {
popup = (page as Widgets.Dashboard).popup;
} else if (page is Widgets.Welcome) {
popup = (page as Widgets.Welcome).popup;
}
popup?.CancelDirectly();
} }
} }
#endregion #endregion

View file

@ -1,157 +0,0 @@
<controls:PopupWidget x:Class="SourceGit.Views.Popups.Clone"
x:Name="me"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
xmlns:validations="clr-namespace:SourceGit.Views.Validations"
mc:Ignorable="d"
d:DesignWidth="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition x:Name="rowSSHKey" Height="0"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
<RowDefinition Height="32"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Clone.RemoteURL}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="0" Grid.Column="1"
x:Name="txtUrl"
Height="24"
Placeholder="{DynamicResource Text.Clone.RemoteURL.Placeholder}"
TextChanged="OnUrlChanged">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="Uri" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:GitURL/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="1" Grid.Column="0"
Text="{DynamicResource Text.SSHKey}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<Grid Grid.Row="1" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<controls:TextEdit
Grid.Column="0"
x:Name="txtSSHKey"
Height="24"
Placeholder="{DynamicResource Text.SSHKey.Placeholder}"/>
<controls:IconButton
Grid.Column="1"
Click="OnSelectSSHKey"
Width="24" Height="24"
Margin="2,0,0,0" Padding="4"
BorderBrush="{DynamicResource Brush.Border1}"
BorderThickness="1"
Icon="{StaticResource Icon.Folder.Open}"/>
</Grid>
<TextBlock
Grid.Row="2" Grid.Column="0"
Text="{DynamicResource Text.Clone.Folder}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="30"/>
</Grid.ColumnDefinitions>
<controls:TextEdit
Grid.Column="0"
x:Name="txtFolder"
Height="24"
Placeholder="{DynamicResource Text.Clone.Folder.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="Folder" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:CloneDir/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<controls:IconButton
Grid.Column="1"
Click="OnFolderSelectorClick"
Width="24" Height="24"
Margin="2,0,0,0" Padding="4"
BorderBrush="{DynamicResource Brush.Border1}"
BorderThickness="1"
Icon="{StaticResource Icon.Folder.Open}"/>
</Grid>
<TextBlock
Grid.Row="3" Grid.Column="0"
Text="{DynamicResource Text.Clone.LocalName}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="3" Grid.Column="1"
Height="24"
x:Name="txtLocal"
Placeholder="{DynamicResource Text.Clone.LocalName.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="LocalName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:LocalRepositoryName/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="4" Grid.Column="0"
Text="{DynamicResource Text.Clone.RemoteName}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="4" Grid.Column="1"
x:Name="txtRemote"
Height="24"
Placeholder="{DynamicResource Text.Clone.RemoteName.Placeholder}">
<controls:TextEdit.Text>
<Binding ElementName="me" Path="RemoteName" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay">
<Binding.ValidationRules>
<validations:RemoteName x:Name="ruleRemote"/>
</Binding.ValidationRules>
</Binding>
</controls:TextEdit.Text>
</controls:TextEdit>
<TextBlock
Grid.Row="5" Grid.Column="0"
Text="{DynamicResource Text.Clone.AdditionalParam}"
Margin="0,0,4,0"
HorizontalAlignment="Right"/>
<controls:TextEdit
Grid.Row="5" Grid.Column="1"
Height="24"
Placeholder="{DynamicResource Text.Clone.AdditionalParam.Placeholder}"
Text="{Binding ElementName=me, Path=ExtraArgs, Mode=TwoWay}"/>
</Grid>
</controls:PopupWidget>

View file

@ -571,6 +571,43 @@
</Grid> </Grid>
<!-- Popup --> <!-- Popup -->
<widgets:PopupPanel x:Name="popup" Grid.Row="1"/> <Grid Grid.Row="1" x:Name="popupArea" Visibility="Collapsed" ClipToBounds="True">
<!-- Background to close -->
<Border Background="Transparent" MouseLeftButtonDown="OnPopupCancelClicked"/>
<!-- Popup panel -->
<Border
Background="{DynamicResource Brush.Window}"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Width="500"
Height="Auto">
<Border.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="0" Color="Black" Opacity=".8"/>
</Border.Effect>
<Grid>
<!-- Custom panel -->
<Border x:Name="popupBody">
<StackPanel Margin="8" Orientation="Vertical">
<TextBlock Margin="8,8,0,18" x:Name="txtPopupTitle" FontSize="18" FontWeight="DemiBold" TextOptions.TextFormattingMode="Ideal" RenderOptions.ClearTypeHint="Enabled"/>
<ContentControl x:Name="popupWidget"/>
<StackPanel Margin="0,16,0,0" Height="32" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Click="OnPopupSureClicked" Width="80" Content="{DynamicResource Text.Sure}" BorderBrush="{DynamicResource Brush.FG1}" Background="{DynamicResource Brush.Accent1}" FontWeight="Bold"/>
<Button Click="OnPopupCancelClicked" Width="80" Margin="8,0,0,0" Content="{DynamicResource Text.Cancel}" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Progress mask -->
<Border x:Name="popupProgressMask" Visibility="Collapsed" Background="{DynamicResource Brush.Popup}" Opacity=".9">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<controls:Loading x:Name="processing" Width="48" Height="48"/>
<TextBlock x:Name="txtPopupProgress" Margin="0,16,0,0"/>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</Grid> </Grid>
</UserControl> </UserControl>

View file

@ -1,14 +1,18 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net.Sockets;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Xml.Linq;
namespace SourceGit.Views.Widgets { namespace SourceGit.Views.Widgets {
@ -20,6 +24,8 @@ namespace SourceGit.Views.Widgets {
private List<BranchNode> localBranches = new List<BranchNode>(); private List<BranchNode> localBranches = new List<BranchNode>();
private List<BranchNode> remoteBranches = new List<BranchNode>(); private List<BranchNode> remoteBranches = new List<BranchNode>();
private bool isFirstLoaded = false; private bool isFirstLoaded = false;
private bool isPopupLocked = false;
private Controls.PopupWidget curPopup = null;
/// <summary> /// <summary>
/// 节点类型 /// 节点类型
@ -85,15 +91,90 @@ namespace SourceGit.Views.Widgets {
#region POPUP #region POPUP
public void Show(Controls.PopupWidget widget) { public void Show(Controls.PopupWidget widget) {
popup.Show(widget); if (isPopupLocked) return;
curPopup = widget;
txtPopupTitle.Text = widget.GetTitle();
popupArea.Visibility = Visibility.Hidden;
popupWidget.Content = curPopup;
popupBody.Margin = new Thickness(0, 0, 0, 0);
popupBody.UpdateLayout();
var gone = new Thickness(0, -popupBody.ActualHeight, 0, 0);
popupBody.Margin = gone;
ThicknessAnimation anim = new ThicknessAnimation();
anim.Duration = TimeSpan.FromMilliseconds(150);
anim.From = gone;
anim.To = new Thickness(0);
popupArea.Visibility = Visibility.Visible;
popupBody.BeginAnimation(MarginProperty, anim);
} }
public void ShowAndStart(Controls.PopupWidget widget) { public void ShowAndStart(Controls.PopupWidget widget) {
popup.ShowAndStart(widget); if (isPopupLocked) return;
Show(widget);
OnPopupSureClicked(this, null);
} }
public void UpdateProgress(string message) { public void UpdateProgress(string message) {
popup.UpdateProgress(message); Dispatcher.Invoke(() => {
txtPopupProgress.Text = message;
});
}
public void ClosePopups(bool unlock) {
if (!unlock && isPopupLocked) return;
if (popupArea.Visibility != Visibility.Visible) return;
ThicknessAnimation anim = new ThicknessAnimation();
anim.Duration = TimeSpan.FromMilliseconds(150);
anim.From = new Thickness(0);
anim.To = new Thickness(0, -popupBody.ActualHeight, 0, 0);
anim.Completed += (obj, ev) => {
popupArea.Visibility = Visibility.Collapsed;
popupWidget.Content = null;
curPopup = null;
isPopupLocked = false;
popupProgressMask.Visibility = Visibility.Collapsed;
processing.IsAnimating = false;
txtPopupProgress.Text = "";
};
popupBody.BeginAnimation(MarginProperty, anim);
}
private async void OnPopupSureClicked(object s, RoutedEventArgs e) {
if (popupArea.Visibility != Visibility.Visible) return;
if (curPopup == null) {
ClosePopups(true);
return;
}
if (isPopupLocked) return;
isPopupLocked = true;
popupProgressMask.Visibility = Visibility.Visible;
processing.IsAnimating = true;
var task = curPopup.Start();
if (task != null) {
var close = await task;
if (close) {
ClosePopups(true);
return;
}
}
isPopupLocked = false;
popupProgressMask.Visibility = Visibility.Collapsed;
processing.IsAnimating = false;
txtPopupProgress.Text = "";
}
private void OnPopupCancelClicked(object s, RoutedEventArgs e) {
ClosePopups(false);
} }
#endregion #endregion
@ -386,8 +467,8 @@ namespace SourceGit.Views.Widgets {
} }
public void OpenSearch(object sender, RoutedEventArgs e) { public void OpenSearch(object sender, RoutedEventArgs e) {
if (popup.IsLocked) return; if (isPopupLocked) return;
popup.Close(); ClosePopups(false);
workspace.SelectedIndex = 0; workspace.SelectedIndex = 0;
(pages.Get("histories") as Histories).ToggleSearch(); (pages.Get("histories") as Histories).ToggleSearch();

View file

@ -1,47 +0,0 @@
<UserControl x:Class="SourceGit.Views.Widgets.PopupPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:SourceGit.Views.Controls"
mc:Ignorable="d" Visibility="Collapsed">
<Grid ClipToBounds="True">
<!-- Background to close -->
<Border Background="Transparent" MouseLeftButtonDown="Cancel"/>
<!-- Popup panel -->
<Border
Background="{DynamicResource Brush.Window}"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Width="500"
Height="Auto">
<Border.Effect>
<DropShadowEffect BlurRadius="4" ShadowDepth="0" Color="Black" Opacity=".8"/>
</Border.Effect>
<Grid>
<!-- Custom panel -->
<Border x:Name="body">
<StackPanel Margin="8" Orientation="Vertical">
<TextBlock Margin="8,8,0,18" x:Name="txtTitle" FontSize="18" FontWeight="DemiBold" TextOptions.TextFormattingMode="Ideal" RenderOptions.ClearTypeHint="Enabled"/>
<ContentControl x:Name="container"/>
<StackPanel Margin="0,16,0,0" Height="32" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Click="Sure" Width="80" Content="{DynamicResource Text.Sure}" BorderBrush="{DynamicResource Brush.FG1}" Background="{DynamicResource Brush.Accent1}" FontWeight="Bold"/>
<Button Click="Cancel" Width="80" Margin="8,0,0,0" Content="{DynamicResource Text.Cancel}" FontWeight="Bold"/>
</StackPanel>
</StackPanel>
</Border>
<!-- Progress mask -->
<Border x:Name="mask" Visibility="Collapsed" Background="{DynamicResource Brush.Popup}" Opacity=".9">
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center">
<controls:Loading x:Name="processing" Width="48" Height="48"/>
<TextBlock x:Name="txtMsg" Margin="0,16,0,0"/>
</StackPanel>
</Border>
</Grid>
</Border>
</Grid>
</UserControl>

View file

@ -1,111 +0,0 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
namespace SourceGit.Views.Widgets {
/// <summary>
/// 统一的下拉弹出窗体面板
/// </summary>
public partial class PopupPanel : UserControl {
private Controls.PopupWidget view = null;
private bool locked = false;
public bool IsLocked {
get { return locked; }
}
public PopupPanel() {
InitializeComponent();
}
public void Show(Controls.PopupWidget widget) {
if (locked) return;
view = widget;
txtTitle.Text = widget.GetTitle();
Visibility = Visibility.Hidden;
container.Content = view;
body.Margin = new Thickness(0, 0, 0, 0);
body.UpdateLayout();
var gone = new Thickness(0, -body.ActualHeight, 0, 0);
body.Margin = gone;
ThicknessAnimation anim = new ThicknessAnimation();
anim.Duration = TimeSpan.FromMilliseconds(150);
anim.From = gone;
anim.To = new Thickness(0);
Visibility = Visibility.Visible;
body.BeginAnimation(MarginProperty, anim);
}
public void ShowAndStart(Controls.PopupWidget widget) {
if (locked) return;
Show(widget);
Sure(null, null);
}
public void UpdateProgress(string message) {
Dispatcher.Invoke(() => txtMsg.Text = message);
}
public void CancelDirectly() {
if (Visibility == Visibility.Visible) Cancel(this, null);
}
public void Close() {
if (Visibility != Visibility.Visible) return;
ThicknessAnimation anim = new ThicknessAnimation();
anim.Duration = TimeSpan.FromMilliseconds(150);
anim.From = new Thickness(0);
anim.To = new Thickness(0, -body.ActualHeight, 0, 0);
anim.Completed += (obj, ev) => {
Visibility = Visibility.Collapsed;
container.Content = null;
view = null;
locked = false;
mask.Visibility = Visibility.Collapsed;
processing.IsAnimating = false;
txtMsg.Text = "";
};
body.BeginAnimation(MarginProperty, anim);
}
private async void Sure(object sender, RoutedEventArgs e) {
if (Visibility != Visibility.Visible) return;
if (view == null) {
Close();
return;
}
if (locked) return;
locked = true;
mask.Visibility = Visibility.Visible;
processing.IsAnimating = true;
var task = view.Start();
if (task != null) {
var close = await task;
if (close) {
Close();
return;
}
}
locked = false;
mask.Visibility = Visibility.Collapsed;
processing.IsAnimating = false;
txtMsg.Text = "";
}
private void Cancel(object sender, RoutedEventArgs e) {
if (locked) return;
Close();
}
}
}

View file

@ -165,8 +165,5 @@
</ItemsControl> </ItemsControl>
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>
<!-- Popup -->
<widgets:PopupPanel x:Name="popup" Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" Grid.ColumnSpan="3"/>
</Grid> </Grid>
</UserControl> </UserControl>

View file

@ -7,14 +7,13 @@ using System.Windows.Controls;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Xml.Linq;
namespace SourceGit.Views.Widgets { namespace SourceGit.Views.Widgets {
/// <summary> /// <summary>
/// 新标签页 /// 新标签页
/// </summary> /// </summary>
public partial class Welcome : UserControl, Controls.IPopupContainer { public partial class Welcome : UserControl {
public Welcome() { public Welcome() {
InitializeComponent(); InitializeComponent();
@ -22,20 +21,6 @@ namespace SourceGit.Views.Widgets {
Models.Theme.AddListener(this, UpdateVisibles); Models.Theme.AddListener(this, UpdateVisibles);
} }
#region POPUP_CONTAINER
public void Show(Controls.PopupWidget widget) {
popup.Show(widget);
}
public void ShowAndStart(Controls.PopupWidget widget) {
popup.ShowAndStart(widget);
}
public void UpdateProgress(string message) {
popup.UpdateProgress(message);
}
#endregion
#region FUNC_EVENTS #region FUNC_EVENTS
private void OnOpenClicked(object sender, RoutedEventArgs e) { private void OnOpenClicked(object sender, RoutedEventArgs e) {
var dialog = new Controls.FolderDialog(); var dialog = new Controls.FolderDialog();
@ -60,7 +45,11 @@ namespace SourceGit.Views.Widgets {
} }
private void OnCloneClicked(object sender, RoutedEventArgs e) { private void OnCloneClicked(object sender, RoutedEventArgs e) {
if (MakeSureReady()) new Popups.Clone().Show(); if (MakeSureReady()) {
var dialog = new Clone();
dialog.Owner = App.Current.MainWindow;
dialog.ShowDialog();
}
} }
private void FillSortMenu(ContextMenu menu, Models.Preference.SortMethod desired, string label) { private void FillSortMenu(ContextMenu menu, Models.Preference.SortMethod desired, string label) {