From 7f027d59013424c8f24a73fb29a21fa416661dc3 Mon Sep 17 00:00:00 2001 From: Dean Edis Date: Sat, 3 Feb 2024 16:10:43 +0000 Subject: [PATCH] Feature: Supported files can now be opened using drag and drop into the app window. Issue #17 --- .../CSharp.Utils/Commands/FileOpenCommand.cs | 4 ++-- .../Extensions/IStorageItemExtensions.cs | 23 +++++++++++++++++++ .../ViewModels/MainWindowViewModel.cs | 10 ++++++-- Speculator/Speculator/Views/MainWindow.axaml | 1 + .../Speculator/Views/MainWindow.axaml.cs | 13 +++++++++-- 5 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 Speculator/CSharp.Utils/Extensions/IStorageItemExtensions.cs diff --git a/Speculator/CSharp.Utils/Commands/FileOpenCommand.cs b/Speculator/CSharp.Utils/Commands/FileOpenCommand.cs index 53705e8..4d5297f 100644 --- a/Speculator/CSharp.Utils/Commands/FileOpenCommand.cs +++ b/Speculator/CSharp.Utils/Commands/FileOpenCommand.cs @@ -55,9 +55,9 @@ await TopLevel } } }); - var selectedFile = files.FirstOrDefault(); + var selectedFile = files.FirstOrDefault()?.ToFileInfo(); if (selectedFile != null) - FileSelected?.Invoke(this, new FileInfo(selectedFile.Path.LocalPath)); + FileSelected?.Invoke(this, selectedFile); else Cancelled?.Invoke(this, null); } diff --git a/Speculator/CSharp.Utils/Extensions/IStorageItemExtensions.cs b/Speculator/CSharp.Utils/Extensions/IStorageItemExtensions.cs new file mode 100644 index 0000000..af657e1 --- /dev/null +++ b/Speculator/CSharp.Utils/Extensions/IStorageItemExtensions.cs @@ -0,0 +1,23 @@ +// Code authored by Dean Edis (DeanTheCoder). +// Anyone is free to copy, modify, use, compile, or distribute this software, +// either in source code form or as a compiled binary, for any non-commercial +// purpose. +// +// If you modify the code, please retain this copyright header, +// and consider contributing back to the repository or letting us know +// about your modifications. Your contributions are valued! +// +// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND. + +using Avalonia.Platform.Storage; + +namespace CSharp.Utils.Extensions; + +public static class IStorageItemExtensions +{ + public static FileInfo ToFileInfo(this IStorageFile storageFile) => + storageFile != null ? new FileInfo(storageFile.Path.LocalPath) : null; + + public static DirectoryInfo ToDirectoryInfo(this IStorageFolder storageFolder) => + storageFolder != null ? new DirectoryInfo(storageFolder.Path.LocalPath) : null; +} \ No newline at end of file diff --git a/Speculator/Speculator/ViewModels/MainWindowViewModel.cs b/Speculator/Speculator/ViewModels/MainWindowViewModel.cs index f43fb6a..0bad185 100644 --- a/Speculator/Speculator/ViewModels/MainWindowViewModel.cs +++ b/Speculator/Speculator/ViewModels/MainWindowViewModel.cs @@ -10,6 +10,7 @@ // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND. using System; +using System.IO; using Avalonia; using Avalonia.Threading; using CSharp.Utils.Commands; @@ -67,8 +68,7 @@ public void LoadGameRom() { try { - Speccy.LoadRom(info); - Mru.Add(info); + LoadGameRomDirect(info); } finally { @@ -79,6 +79,12 @@ public void LoadGameRom() command.Execute(null); } + public void LoadGameRomDirect(FileInfo info) + { + Speccy.LoadRom(info); + Mru.Add(info); + } + public void SaveGameRom() { var keyBlocker = Speccy.PortHandler.CreateKeyBlocker(); diff --git a/Speculator/Speculator/Views/MainWindow.axaml b/Speculator/Speculator/Views/MainWindow.axaml index 3fe9667..2178dd7 100644 --- a/Speculator/Speculator/Views/MainWindow.axaml +++ b/Speculator/Speculator/Views/MainWindow.axaml @@ -15,6 +15,7 @@ Title="ZX Speculator" Width="1066" Height="634" MinWidth="520" MinHeight="320" + DragDrop.AllowDrop="True" x:Name="Self"> diff --git a/Speculator/Speculator/Views/MainWindow.axaml.cs b/Speculator/Speculator/Views/MainWindow.axaml.cs index 7c3fa42..b70c8c6 100644 --- a/Speculator/Speculator/Views/MainWindow.axaml.cs +++ b/Speculator/Speculator/Views/MainWindow.axaml.cs @@ -10,14 +10,16 @@ // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND. using System; -using System.Threading.Tasks; +using System.Linq; using Avalonia.Controls; using Avalonia.Input; using Avalonia.Interactivity; -using Avalonia.Threading; +using Avalonia.Platform.Storage; +using CSharp.Utils.Extensions; using CSharp.Utils.UI; using Material.Icons.Avalonia; using Speculator.ViewModels; + // ReSharper disable UnusedParameter.Local namespace Speculator.Views; @@ -31,6 +33,7 @@ public MainWindow() { InitializeComponent(); + AddHandler(DragDrop.DropEvent, OnDrop); Closing += (_, args) => AppCloseHandler.Instance.OnMainWindowClosing(args); Closed += (_, _) => (DataContext as IDisposable)?.Dispose(); } @@ -77,4 +80,10 @@ private void OnKeyboardIconLoaded(object sender, RoutedEventArgs e) }; icon.PointerExited += (_, _) => Keyboard.Opacity = 0.0; } + + private void OnDrop(object sender, DragEventArgs e) + { + if (e.Data.GetFiles()?.FirstOrDefault() is IStorageFile file) + ((MainWindowViewModel)DataContext)?.LoadGameRomDirect(file.ToFileInfo()); + } } \ No newline at end of file