diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index 83ee8a3..f059eae 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -6,6 +7,7 @@ using System.Reflection; using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; +using System.Windows.Forms.VisualStyles; using System.Windows.Media; using System.Windows.Media.Imaging; using Filtration.Common.Services; @@ -26,7 +28,6 @@ using Filtration.Views; using GalaSoft.MvvmLight.CommandWpf; using GalaSoft.MvvmLight.Messaging; using NLog; -using Clipboard = System.Windows.Clipboard; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; namespace Filtration.ViewModels @@ -35,7 +36,8 @@ namespace Filtration.ViewModels { RelayCommand OpenScriptCommand { get; } RelayCommand NewScriptCommand { get; } - Task CloseAllDocuments(); + Task CloseAllDocumentsAsync(); + Task OpenDroppedFilesAsync(List filenames); } internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel @@ -52,6 +54,7 @@ namespace Filtration.ViewModels private readonly IUpdateCheckService _updateCheckService; private readonly IUpdateAvailableViewModel _updateAvailableViewModel; private readonly IMessageBoxService _messageBoxService; + private readonly IClipboardService _clipboardService; private bool _showLoadingBanner; public MainWindowViewModel(IItemFilterScriptRepository itemFilterScriptRepository, @@ -63,7 +66,8 @@ namespace Filtration.ViewModels IThemeService themeService, IUpdateCheckService updateCheckService, IUpdateAvailableViewModel updateAvailableViewModel, - IMessageBoxService messageBoxService) + IMessageBoxService messageBoxService, + IClipboardService clipboardService) { _itemFilterScriptRepository = itemFilterScriptRepository; _itemFilterScriptTranslator = itemFilterScriptTranslator; @@ -75,14 +79,15 @@ namespace Filtration.ViewModels _updateCheckService = updateCheckService; _updateAvailableViewModel = updateAvailableViewModel; _messageBoxService = messageBoxService; + _clipboardService = clipboardService; NewScriptCommand = new RelayCommand(OnNewScriptCommand); CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, () => ActiveDocumentIsScript); OpenScriptCommand = new RelayCommand(async () => await OnOpenScriptCommand()); - OpenThemeCommand = new RelayCommand(async () => await OnOpenThemeCommand()); + OpenThemeCommand = new RelayCommand(async () => await OnOpenThemeCommandAsync()); - SaveCommand = new RelayCommand(async () => await OnSaveDocumentCommand(), ActiveDocumentIsEditable); - SaveAsCommand = new RelayCommand(async () => await OnSaveAsCommand(), ActiveDocumentIsEditable); + SaveCommand = new RelayCommand(async () => await OnSaveDocumentCommandAsync(), ActiveDocumentIsEditable); + SaveAsCommand = new RelayCommand(async () => await OnSaveAsCommandAsync(), ActiveDocumentIsEditable); CloseCommand = new RelayCommand(OnCloseDocumentCommand, ActiveDocumentIsEditable); CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); @@ -106,7 +111,7 @@ namespace Filtration.ViewModels ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocumentIsScript); CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => ActiveDocumentIsScript); - ApplyThemeToScriptCommand = new RelayCommand(async () => await OnApplyThemeToScriptCommand(), () => ActiveDocumentIsScript); + ApplyThemeToScriptCommand = new RelayCommand(async () => await OnApplyThemeToScriptCommandAsync(), () => ActiveDocumentIsScript); EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => ActiveDocumentIsScript); AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable); @@ -185,7 +190,11 @@ namespace Filtration.ViewModels } } }); - CheckForUpdates(); + + Task.Run(async () => + { + await CheckForUpdatesAsync(); + }).Wait(); } public RelayCommand OpenScriptCommand { get; private set; } @@ -229,7 +238,7 @@ namespace Filtration.ViewModels public RelayCommand ClearFiltersCommand { get; private set; } - public async void CheckForUpdates() + public async Task CheckForUpdatesAsync() { var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location); @@ -346,6 +355,29 @@ namespace Filtration.ViewModels } } + public async Task OpenDroppedFilesAsync(List filenames) + { + foreach (var filename in filenames) + { + var extension = Path.GetExtension(filename); + if (extension == null) continue; + + switch (extension.ToUpperInvariant()) + { + case ".FILTER": + { + await LoadScriptAsync(filename); + break; + } + case ".FILTERTHEME": + { + await LoadThemeAsync(filename); + break; + } + } + } + } + private void OnCreateThemeCommand() { var themeViewModel = _themeProvider.NewThemeForScript(AvalonDockWorkspaceViewModel.ActiveScriptViewModel.Script); @@ -389,22 +421,26 @@ namespace Filtration.ViewModels private async Task OnOpenScriptCommand() { - var openFileDialog = new OpenFileDialog + var filePath = ShowOpenScriptDialog(); + + if (string.IsNullOrEmpty(filePath)) { - Filter = "Filter Files (*.filter)|*.filter|All Files (*.*)|*.*", - InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() - }; + return; + } - if (openFileDialog.ShowDialog() != true) return; + await LoadScriptAsync(filePath); + } + private async Task LoadScriptAsync(string scriptFilename) + { IItemFilterScriptViewModel loadedViewModel; Messenger.Default.Send(new NotificationMessage("ShowLoadingBanner")); try { - loadedViewModel = await _itemFilterScriptRepository.LoadScriptFromFileAsync(openFileDialog.FileName); + loadedViewModel = await _itemFilterScriptRepository.LoadScriptFromFileAsync(scriptFilename); } - catch(IOException e) + catch (IOException e) { Messenger.Default.Send(new NotificationMessage("HideLoadingBanner")); if (_logger.IsErrorEnabled) @@ -421,20 +457,24 @@ namespace Filtration.ViewModels _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); } - private async Task OnOpenThemeCommand() + private async Task OnOpenThemeCommandAsync() { - var filePath = ShowOpenThemeDialog(); if (string.IsNullOrEmpty(filePath)) { return; } + await LoadThemeAsync(filePath); + } + + private async Task LoadThemeAsync(string themeFilename) + { IThemeEditorViewModel loadedViewModel; try { - loadedViewModel = await _themeProvider.LoadThemeFromFile(filePath); + loadedViewModel = await _themeProvider.LoadThemeFromFile(themeFilename); } catch (IOException e) { @@ -447,11 +487,11 @@ namespace Filtration.ViewModels MessageBoxImage.Error); return; } - + _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); } - private async Task OnApplyThemeToScriptCommand() + private async Task OnApplyThemeToScriptCommandAsync() { var filePath = ShowOpenThemeDialog(); if (string.IsNullOrEmpty(filePath)) @@ -489,6 +529,16 @@ namespace Filtration.ViewModels AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SetDirtyFlag(); } + private string ShowOpenScriptDialog() + { + var openFileDialog = new OpenFileDialog + { + Filter = "Filter Files (*.filter)|*.filter|All Files (*.*)|*.*", + InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() + }; + + return openFileDialog.ShowDialog() != true ? string.Empty : openFileDialog.FileName; + } private string ShowOpenThemeDialog() { @@ -501,8 +551,6 @@ namespace Filtration.ViewModels return openFileDialog.ShowDialog() != true ? string.Empty : openFileDialog.FileName; } - - private void SetItemFilterScriptDirectory() { var dlg = new FolderBrowserDialog @@ -518,12 +566,12 @@ namespace Filtration.ViewModels } } - private async Task OnSaveDocumentCommand() + private async Task OnSaveDocumentCommandAsync() { await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsync(); } - private async Task OnSaveAsCommand() + private async Task OnSaveAsCommandAsync() { await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsAsync(); } @@ -537,7 +585,18 @@ namespace Filtration.ViewModels private void OnCopyScriptCommand() { - Clipboard.SetText(_itemFilterScriptTranslator.TranslateItemFilterScriptToString(_avalonDockWorkspaceViewModel.ActiveScriptViewModel.Script)); + try + { + + _clipboardService.SetClipboardText( + _itemFilterScriptTranslator.TranslateItemFilterScriptToString( + _avalonDockWorkspaceViewModel.ActiveScriptViewModel.Script)); + } + catch + { + _messageBoxService.Show("Clipboard Error", "Failed to access the clipboard, copy command not completed.", + MessageBoxButton.OK, MessageBoxImage.Error); + } } private void OnCopyBlockCommand() @@ -657,7 +716,7 @@ namespace Filtration.ViewModels _avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent); } - public async Task CloseAllDocuments() + public async Task CloseAllDocumentsAsync() { var openDocuments = _avalonDockWorkspaceViewModel.OpenDocuments.OfType().ToList(); diff --git a/Filtration/Views/MainWindow.xaml b/Filtration/Views/MainWindow.xaml index 43b3e2d..46b6ac2 100644 --- a/Filtration/Views/MainWindow.xaml +++ b/Filtration/Views/MainWindow.xaml @@ -12,7 +12,7 @@ mc:Ignorable="d" d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}" Title="{Binding WindowTitle}" Height="762" Width="1126" IsIconVisible="True" - Closing="MainWindow_OnClosing"> + Closing="MainWindow_OnClosing" Drop="MainWindow_OnDrop" AllowDrop="True"> diff --git a/Filtration/Views/MainWindow.xaml.cs b/Filtration/Views/MainWindow.xaml.cs index 414ab6b..30c06ec 100644 --- a/Filtration/Views/MainWindow.xaml.cs +++ b/Filtration/Views/MainWindow.xaml.cs @@ -1,4 +1,6 @@ -using System.ComponentModel; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; using System.Threading.Tasks; using System.Windows; using Filtration.ViewModels; @@ -39,12 +41,35 @@ namespace Filtration.Views private void MainWindow_OnClosing(object sender, CancelEventArgs e) { - var allDocumentsClosed = _mainWindowViewModel.CloseAllDocuments().Result; + var allDocumentsClosed = _mainWindowViewModel.CloseAllDocumentsAsync().Result; if (!allDocumentsClosed) { e.Cancel = true; } } + + private async void MainWindow_OnDrop(object sender, DragEventArgs e) + { + if (!e.Data.GetDataPresent(DataFormats.FileDrop)) return; + + var filenames = (string[])e.Data.GetData(DataFormats.FileDrop); + var droppedFilterFiles = new List(); + + foreach (var filename in filenames) + { + var extension = Path.GetExtension(filename); + if (extension != null && + (extension.ToUpperInvariant() == ".FILTER" || extension.ToUpperInvariant() == ".FILTERTHEME")) + { + droppedFilterFiles.Add(filename); + } + } + + if (droppedFilterFiles.Count > 0) + { + await _mainWindowViewModel.OpenDroppedFilesAsync(droppedFilterFiles); + } + } } }