Explorar el Código

Added version of Progress.ShowModal with cancel button

Kenric Nugteren hace 1 año
padre
commit
2ac318ff45

+ 3 - 1
InABox.Client.RPC/Transports/IRPCClientTransport.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Threading;
 using InABox.Clients;
 using InABox.Core;
 
@@ -13,8 +14,9 @@ namespace InABox.Rpc
         /// <summary>
         /// Connect to remote server.
         /// </summary>
+        /// <param name="ct">Cancellation token to cancel the connection.</param>
         /// <returns><see langword="true"/> if connection success, <see langword="false"/> otherwise.</returns>
-        bool Connect();
+        bool Connect(CancellationToken ct = default);
 
         void Send(RpcMessage message);
         

+ 4 - 3
InABox.Client.RPC/Transports/Pipe/RPCClientPipeTransport.cs

@@ -1,4 +1,5 @@
 using System;
+using System.Threading;
 using H.Pipes;
 using InABox.Core;
 
@@ -7,7 +8,7 @@ namespace InABox.Rpc
     public class RpcClientPipeTransport : RpcClientTransport, IDisposable
     {
         private PipeClient<RpcMessage> _pipe;
-        private String _name;
+        private string _name;
         
         public RpcClientPipeTransport(string name)
         {
@@ -19,9 +20,9 @@ namespace InABox.Rpc
             _pipe.ExceptionOccurred += PipeExceptionOccurred;
         }
 
-        public override bool Connect()
+        public override bool Connect(CancellationToken ct)
         {
-            _pipe.ConnectAsync().Wait();
+            _pipe.ConnectAsync(ct).Wait();
             return _pipe.IsConnected;
         }
 

+ 1 - 1
InABox.Client.RPC/Transports/RPCClientTransport.cs

@@ -39,7 +39,7 @@ namespace InABox.Rpc
         public event RpcTransportMessageEvent? OnMessage;
         protected void DoMessage(RpcMessage message) => OnMessage?.Invoke(this, new RpcTransportMessageArgs(_session, message));
         
-        public abstract bool Connect();
+        public abstract bool Connect(CancellationToken ct = default);
         public abstract bool IsConnected();
         public abstract bool IsSecure();
         public abstract string? ServerName();

+ 7 - 7
InABox.Client.RPC/Transports/Socket/RPCClientSocketTransport.cs

@@ -99,7 +99,7 @@ namespace InABox.Rpc
             return true;
         }*/
         
-        private WebSocket? CreateSocket(string url, bool secure)
+        private WebSocket? CreateSocket(string url, bool secure, CancellationToken ct)
         {
             //WebsocketClient client;
 
@@ -127,7 +127,7 @@ namespace InABox.Rpc
             client.DataReceived += Client_DataReceived;
             client.Open();
 
-            openEvent.Wait();
+            openEvent.Wait(ct);
 
             if (!open)
             {
@@ -198,13 +198,13 @@ namespace InABox.Rpc
             openEvent.Set();
         }
 
-        public override bool Connect()
+        public override bool Connect(CancellationToken ct)
         {
-            if(_socket != null)
+            if (_socket != null)
             {
                 openEvent.Reset();
                 _socket.Open();
-                openEvent.Wait();
+                openEvent.Wait(ct);
                 return _connected;
             }
             else
@@ -212,8 +212,8 @@ namespace InABox.Rpc
                 var tasks = new List<Task<WebSocket?>>();
                 foreach (var url in _urls)
                 {
-                    tasks.Add(Task.Run(() => CreateSocket(url, true)));
-                    tasks.Add(Task.Run(() => CreateSocket(url, false)));
+                    tasks.Add(Task.Run(() => CreateSocket(url, true, ct)));
+                    tasks.Add(Task.Run(() => CreateSocket(url, false, ct)));
                 }
                 while (tasks.Count > 0)
                 {

+ 52 - 2
inabox.wpf/ProgressWindow/Progress.cs

@@ -1,6 +1,7 @@
 using System;
 using System.ComponentModel;
 using System.Linq;
+using System.Threading;
 using System.Windows.Media.Imaging;
 
 namespace InABox.WPF
@@ -51,16 +52,65 @@ namespace InABox.WPF
             progress.ShowDialog();
         }
 
+        private static void RunShowModal(ProgressForm progress, Action<IProgress<string>> work)
+        {
+        }
+
+        /// <summary>
+        /// Shows progress dialog modally, with a cancel button.
+        /// </summary>
+        /// <param name="message"></param>
+        /// <param name="cancelButtonText"></param>
+        /// <param name="work"></param>
+        /// <returns>Whether the progress was completed without cancelling.</returns>
+        public static bool ShowModal(string message, string cancelButtonText, Action<IProgress<string>, CancellationToken> work)
+        {
+            var cancellationTokenSource = new CancellationTokenSource();
+
+            var progress = new ProgressForm(cancelButtonText)
+            {
+                DisplayImage = DisplayImage
+            };
+            progress.Progress.Content = message;
+
+            progress.Loaded += (_, args) =>
+            {
+                var worker = new BackgroundWorker();
+                var update = new Progress<string>(data => progress.Progress.Content = data);
+
+                progress.OnCancelled += () =>
+                {
+                    cancellationTokenSource.Cancel();
+                    progress.Close();
+                };
+
+                worker.DoWork += (o, e) => work(update, cancellationTokenSource.Token);
+                worker.RunWorkerCompleted +=
+                    (o, e) => progress.Close();
+                worker.RunWorkerAsync();
+            };
+
+            progress.ShowDialog();
+            return !cancellationTokenSource.IsCancellationRequested;
+        }
+
         public static void ShowModal(string message, Action<IProgress<string>> work)
         {
-            var progress = new ProgressForm();
-            progress.DisplayImage = DisplayImage;
+            var progress = new ProgressForm
+            {
+                DisplayImage = DisplayImage
+            };
             progress.Progress.Content = message;
             progress.Loaded += (_, args) =>
             {
                 var worker = new BackgroundWorker();
                 var update = new Progress<string>(data => progress.Progress.Content = data);
 
+                progress.OnCancelled += () =>
+                {
+                    worker.CancelAsync();
+                };
+
                 worker.DoWork += (o, e) => work(update);
                 worker.RunWorkerCompleted +=
                     (o, e) => progress.Close();

+ 29 - 4
inabox.wpf/ProgressWindow/ProgressForm.xaml

@@ -13,17 +13,34 @@
         AllowsTransparency="True"
         Background="Transparent"
         MouseDown="Window_MouseDown"
-        Width="350" Height="200">
+        Width="350" Height="200"
+                    x:Name="Window">
+    <Window.Resources>
+        <Style TargetType="Button" x:Key="RoundButton">
+            <Style.Resources>
+                <Style TargetType="Border">
+                    <Setter Property="CornerRadius" Value="10"/>
+                </Style>
+            </Style.Resources>
+        </Style>
+    </Window.Resources>
     <Border CornerRadius="10" BorderBrush="Gray" BorderThickness="0.75" Padding="5,5,5,0" Background="White">
         <Grid Margin="5">
             <Grid.RowDefinitions>
                 <RowDefinition Height="*" />
                 <RowDefinition Height="Auto" />
+                <RowDefinition Height="Auto" />
             </Grid.RowDefinitions>
-            <Image x:Name="Splash" Margin="20,10,20,10" Stretch="Uniform" Source="../Resources/splash.png" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
-            
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="*"/>
+                <ColumnDefinition Width="Auto"/>
+                <ColumnDefinition Width="*"/>
+            </Grid.ColumnDefinitions>
+            <Image Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3"
+                   x:Name="Splash" Margin="20,10,20,10" Stretch="Uniform" Source="../Resources/splash.png" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
+
             <Label
-                Grid.Row="1"
+                Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3"
                 FontSize="14"
                 FontStyle="Oblique"
                 x:Name="Progress"
@@ -33,6 +50,14 @@
                 HorizontalContentAlignment="Center"
                 VerticalContentAlignment="Center"
                 Background="Transparent" />
+
+            <Button x:Name="CancelButton" Style="{StaticResource RoundButton}"
+                    Background="Transparent"
+                    Content="{Binding ElementName=Window,Path=CancelText}"
+                    Visibility="{Binding ElementName=Window,Path=CancelButtonVisibility}"
+                    Padding="5" Margin="5"
+                    Grid.Row="2" Grid.Column="1"
+                    Click="CancelButton_Click"/>
         </Grid>
     </Border>
 </wpf:ThemableWindow>

+ 22 - 1
inabox.wpf/ProgressWindow/ProgressForm.xaml.cs

@@ -16,8 +16,20 @@ namespace InABox.WPF
 
         private DoubleAnimation _fader = new DoubleAnimation(1d, 0.3d, new Duration(TimeSpan.FromMilliseconds(3000))) { AutoReverse = true };
 
-        public ProgressForm()
+        public string CancelText { get; init; }
+        public bool HasCancelButton { get; init; }
+
+        public delegate void CancelledEvent();
+
+        public event CancelledEvent? OnCancelled;
+
+        public Visibility CancelButtonVisibility => HasCancelButton ? Visibility.Visible : Visibility.Collapsed;
+
+        private ProgressForm(string cancelText, bool hasCancelButton)
         {
+            CancelText = cancelText;
+            HasCancelButton = hasCancelButton;
+
             InitializeComponent();
             Topmost = true;
             Loaded += (sender, args) =>
@@ -26,6 +38,10 @@ namespace InABox.WPF
                 Splash.BeginAnimation(Image.OpacityProperty, _fader);
             };
         }
+
+        public ProgressForm(): this("", false) { }
+
+        public ProgressForm(string cancelText): this(cancelText, true) { }
         
         public ImageSource? DisplayImage
         {
@@ -61,5 +77,10 @@ namespace InABox.WPF
                 DragMove();
             }
         }
+
+        private void CancelButton_Click(object sender, RoutedEventArgs e)
+        {
+            OnCancelled?.Invoke();
+        }
     }
 }