diff --git a/src/Gemini/Gemini.csproj b/src/Gemini/Gemini.csproj index f6148ae6..5cfbb94d 100644 --- a/src/Gemini/Gemini.csproj +++ b/src/Gemini/Gemini.csproj @@ -187,6 +187,7 @@ SettingsView.xaml + diff --git a/src/Gemini/Modules/Shell/Behaviors/DropFilesBehavior.cs b/src/Gemini/Modules/Shell/Behaviors/DropFilesBehavior.cs new file mode 100644 index 00000000..aaf2409f --- /dev/null +++ b/src/Gemini/Modules/Shell/Behaviors/DropFilesBehavior.cs @@ -0,0 +1,105 @@ +using Caliburn.Micro; +using Gemini.Framework; +using Gemini.Framework.Commands; +using Gemini.Framework.Services; +using Gemini.Modules.Shell.Commands; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Input; + +namespace Gemini.Modules.Shell.Behaviors +{ + /// + /// Attached behaviour to implement the drop event + /// source: http://social.msdn.microsoft.com/Forums/de-DE/wpf/thread/21bed380-c485-44fb-8741-f9245524d0ae + /// http://stackoverflow.com/questions/1034374/drag-and-drop-in-mvvm-with-scatterview + /// + public class DropFilesBehavior : DependencyObject + { + public static readonly DependencyProperty AllowOpenProperty = DependencyProperty.RegisterAttached( + "AllowOpen", + typeof(bool), + typeof(DropFilesBehavior), + new PropertyMetadata(false, OnAllowOpenChanged)); + + public static bool GetAllowOpen(DependencyObject source) + { + return (bool)source.GetValue(AllowOpenProperty); + } + + public static void SetAllowOpen(DependencyObject source, bool value) + { + source.SetValue(AllowOpenProperty, value); + } + + private static void OnAllowOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + UIElement uiElement = d as UIElement; + uiElement.Drop -= UIElement_Drop; + + if ((bool)e.NewValue) + { + uiElement.Drop += UIElement_Drop; + } + } + + private static void UIElement_Drop(object sender, DragEventArgs e) + { + UIElement uiElement = sender as UIElement; + + // Sanity check just in case this was somehow send by something else + if (uiElement == null) + return; + + if (e.Data.GetDataPresent(DataFormats.FileDrop)) + { + string[] droppedFilePaths = e.Data.GetData(DataFormats.FileDrop, true) as string[]; + Task.Run(() => OpenDocument(droppedFilePaths)); + } + } + + public static async Task OpenDocument(string[] droppedFilePaths) + { + var shell = IoC.Get(); + var providers = IoC.GetAllInstances(typeof(IEditorProvider)).Cast(); + + foreach (var newPath in droppedFilePaths) + { + // Check if file type is supprted + if (providers.FirstOrDefault(p => p.Handles(newPath)) == null) + continue; + + // Check if the document is already open + bool foundInShell = false; + foreach (var document in shell.Documents.OfType().Where(d => !d.IsNew)) + { + if (string.IsNullOrEmpty(document.FilePath)) + continue; + + var docPath = Path.GetFullPath(document.FilePath); + if (string.Equals(newPath, docPath, System.StringComparison.OrdinalIgnoreCase)) + { + shell.OpenDocument(document); + foundInShell = true; + break; + } + } + + if (!foundInShell) + { + shell.OpenDocument(await OpenFileCommandHandler.GetEditor(newPath)); + + // Add the file to the recent documents list + //shell.RecentFiles.Update(newPath); + } + } + } + + } +} diff --git a/src/Gemini/Modules/Shell/Views/ShellView.xaml b/src/Gemini/Modules/Shell/Views/ShellView.xaml index d2bd5b79..77079d34 100644 --- a/src/Gemini/Modules/Shell/Views/ShellView.xaml +++ b/src/Gemini/Modules/Shell/Views/ShellView.xaml @@ -6,6 +6,7 @@ xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock" xmlns:converters="clr-namespace:Gemini.Modules.Shell.Converters" xmlns:toolbarcontrols="clr-namespace:Gemini.Modules.ToolBars.Controls" + xmlns:b="clr-namespace:Gemini.Modules.Shell.Behaviors" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" @@ -28,7 +29,9 @@ + LayoutUpdated="OnManagerLayoutUpdated" + b:DropFilesBehavior.AllowOpen="True" + AllowDrop="True">