From 80ea252b636b2231675a293e10ba5620e180f7ec Mon Sep 17 00:00:00 2001 From: Adele Reed Date: Mon, 13 Mar 2023 13:31:31 -0700 Subject: [PATCH] feat: enable drag-n-drop --- src/Lumper.UI/App.axaml.cs | 6 ++- .../ViewModels/MainWindowViewModel.IO.cs | 2 +- .../ViewModels/MainWindowViewModel.cs | 53 +++++++++++++++++++ src/Lumper.UI/Views/MainWindow.axaml | 1 + src/Lumper.UI/Views/MainWindow.axaml.cs | 16 ++++++ 5 files changed, 76 insertions(+), 2 deletions(-) diff --git a/src/Lumper.UI/App.axaml.cs b/src/Lumper.UI/App.axaml.cs index 22bf68a3..ab50865e 100644 --- a/src/Lumper.UI/App.axaml.cs +++ b/src/Lumper.UI/App.axaml.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; using Avalonia.Markup.Xaml; using Lumper.UI.ViewModels; using Lumper.UI.Views; @@ -17,10 +18,13 @@ public override void OnFrameworkInitializationCompleted() { if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + var vm = new MainWindowViewModel(); desktop.MainWindow = new MainWindow { - DataContext = new MainWindowViewModel() + DataContext = vm, }; + } base.OnFrameworkInitializationCompleted(); } diff --git a/src/Lumper.UI/ViewModels/MainWindowViewModel.IO.cs b/src/Lumper.UI/ViewModels/MainWindowViewModel.IO.cs index 5f3199a5..15081367 100644 --- a/src/Lumper.UI/ViewModels/MainWindowViewModel.IO.cs +++ b/src/Lumper.UI/ViewModels/MainWindowViewModel.IO.cs @@ -163,7 +163,7 @@ private async Task LoadBsp(IStorageFile file) if(!file.TryGetUri(out var path)) { throw new Exception("Failed to get file path"); - + } LoadBsp(path.AbsolutePath); } diff --git a/src/Lumper.UI/ViewModels/MainWindowViewModel.cs b/src/Lumper.UI/ViewModels/MainWindowViewModel.cs index c23e767d..903502ff 100644 --- a/src/Lumper.UI/ViewModels/MainWindowViewModel.cs +++ b/src/Lumper.UI/ViewModels/MainWindowViewModel.cs @@ -1,6 +1,10 @@ using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; using Lumper.UI.ViewModels.Bsp; using ReactiveUI; @@ -27,6 +31,11 @@ public MainWindowViewModel() SearchInit(); TabsInit(); IOInit(); + + if (desktop.Args?.Length > 0) + { + LoadBsp(desktop.Args[0]); + } } public IClassicDesktopStyleApplicationLifetime Desktop @@ -45,4 +54,48 @@ public BspNodeBase? SelectedNode get => _selectedNode; set => this.RaiseAndSetIfChanged(ref _selectedNode, value); } + + internal static void DragOver(object? sender, DragEventArgs e) + { + e.DragEffects = DragDropEffects.Link; + + var names = e.Data.GetFileNames() ?? new List(); + + if (!e.Data.Contains(DataFormats.FileNames) || !names.FirstOrDefault("").ToLower().EndsWith(".bsp")) + e.DragEffects = DragDropEffects.None; + } + + internal void Drop(object? sender, DragEventArgs e) + { + if (!e.Data.Contains(DataFormats.FileNames)) + return; + + var names = e.Data.GetFileNames() ?? new List(); + foreach (string target in names) + { + if (!target.ToLower().EndsWith(".bsp")) + continue; + + if (BspModel == null) + { + // if nothing is open, open it. + LoadBsp(target); + } + else + { + // Otherwise, open a brand new Lumper instance with it. + string? executableFileName = Process.GetCurrentProcess().MainModule?.FileName; + if (executableFileName == null) + return; + + ProcessStartInfo startInfo = new() + { + ArgumentList = { $"{target}" }, + FileName = executableFileName, + }; + + Process.Start(startInfo); + } + } + } } diff --git a/src/Lumper.UI/Views/MainWindow.axaml b/src/Lumper.UI/Views/MainWindow.axaml index f222b67d..90c5c525 100644 --- a/src/Lumper.UI/Views/MainWindow.axaml +++ b/src/Lumper.UI/Views/MainWindow.axaml @@ -14,6 +14,7 @@ TransparencyLevelHint="AcrylicBlur" ExtendClientAreaToDecorationsHint="True" WindowStartupLocation="CenterScreen" + DragDrop.AllowDrop="True" Background="Transparent"> diff --git a/src/Lumper.UI/Views/MainWindow.axaml.cs b/src/Lumper.UI/Views/MainWindow.axaml.cs index fd614ab1..6516d8c4 100644 --- a/src/Lumper.UI/Views/MainWindow.axaml.cs +++ b/src/Lumper.UI/Views/MainWindow.axaml.cs @@ -1,12 +1,28 @@ using System; using System.ComponentModel; using Avalonia.Controls; +using Avalonia.Input; using Lumper.UI.ViewModels; namespace Lumper.UI.Views; public partial class MainWindow : Window { + // Quietly shadow DataContext to add initializer + public new object? DataContext + { + init // DataContext is never overwritten-- It's ok to not defensively remove the Drop handler, and do DragOver here. + { + var dc = value as MainWindowViewModel; // It must be (as of 3/16/23) + AddHandler(DragDrop.DropEvent, dc!.Drop); + AddHandler(DragDrop.DragOverEvent, MainWindowViewModel.DragOver); + + base.DataContext = value; + } + + get => base.DataContext; + } + public MainWindow() { InitializeComponent();