Implemented async saving and loading

This commit is contained in:
Ben 2015-07-25 19:02:42 +01:00
parent e54730d693
commit 32b0a0199f
22 changed files with 245 additions and 119 deletions

View File

@ -1,9 +1,11 @@
namespace Filtration.Interface using System.Threading.Tasks;
namespace Filtration.Interface
{ {
public interface IDocument public interface IDocument
{ {
bool IsScript { get; } bool IsScript { get; }
bool IsTheme { get; } bool IsTheme { get; }
void Close(); Task Close();
} }
} }

View File

@ -1,9 +1,11 @@
namespace Filtration.Interface using System.Threading.Tasks;
namespace Filtration.Interface
{ {
public interface IEditableDocument : IDocument public interface IEditableDocument : IDocument
{ {
bool IsDirty { get; } bool IsDirty { get; }
void Save(); Task SaveAsync();
void SaveAs(); Task SaveAsAsync();
} }
} }

View File

@ -18,7 +18,7 @@ namespace Filtration.Tests.Repositories
var mockPersistenceService = new Mock<IItemFilterPersistenceService>(); var mockPersistenceService = new Mock<IItemFilterPersistenceService>();
mockPersistenceService.Setup(p => p.LoadItemFilterScript(testInputPath)).Verifiable(); mockPersistenceService.Setup(p => p.LoadItemFilterScriptAsync(testInputPath)).Verifiable();
var mockItemFilterScriptViewModel = new Mock<IItemFilterScriptViewModel>(); var mockItemFilterScriptViewModel = new Mock<IItemFilterScriptViewModel>();
@ -28,7 +28,7 @@ namespace Filtration.Tests.Repositories
var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object); var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object);
// Act // Act
var result = repository.LoadScriptFromFile(testInputPath); var result = repository.LoadScriptFromFileAsync(testInputPath);
// Assert // Assert
mockPersistenceService.Verify(); mockPersistenceService.Verify();
@ -42,7 +42,7 @@ namespace Filtration.Tests.Repositories
var testInputPath = "C:\\TestPath.filter"; var testInputPath = "C:\\TestPath.filter";
var mockPersistenceService = new Mock<IItemFilterPersistenceService>(); var mockPersistenceService = new Mock<IItemFilterPersistenceService>();
mockPersistenceService.Setup(p => p.LoadItemFilterScript(testInputPath)).Throws<IOException>(); mockPersistenceService.Setup(p => p.LoadItemFilterScriptAsync(testInputPath)).Throws<IOException>();
var mockItemFilterScriptViewModelFactory = new Mock<IItemFilterScriptViewModelFactory>(); var mockItemFilterScriptViewModelFactory = new Mock<IItemFilterScriptViewModelFactory>();
@ -51,7 +51,7 @@ namespace Filtration.Tests.Repositories
// Act // Act
// Assert // Assert
Assert.Throws<IOException>(() => repository.LoadScriptFromFile(testInputPath)); Assert.Throws<IOException>(() => repository.LoadScriptFromFileAsync(testInputPath));
} }
[Test] [Test]

View File

@ -28,7 +28,7 @@ namespace Filtration.Tests.Services
var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object); var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object);
// Act // Act
var script = service.LoadItemFilterScript(TestInputPath); var script = service.LoadItemFilterScriptAsync(TestInputPath);
// Assert // Assert
mockFileSystemService.Verify(); mockFileSystemService.Verify();
@ -53,7 +53,7 @@ namespace Filtration.Tests.Services
var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object); var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object);
// Act // Act
service.SaveItemFilterScript(testScript); service.SaveItemFilterScriptAsync(testScript);
// Assert // Assert
mockFileSystemService.Verify(); mockFileSystemService.Verify();

View File

@ -1,6 +1,7 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using AutoMapper; using AutoMapper;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.ThemeEditor; using Filtration.ObjectModel.ThemeEditor;
@ -13,9 +14,9 @@ namespace Filtration.ThemeEditor.Providers
{ {
IThemeEditorViewModel NewThemeForScript(ItemFilterScript script); IThemeEditorViewModel NewThemeForScript(ItemFilterScript script);
IThemeEditorViewModel MasterThemeForScript(ItemFilterScript script); IThemeEditorViewModel MasterThemeForScript(ItemFilterScript script);
IThemeEditorViewModel LoadThemeFromFile(string filePath); Task<IThemeEditorViewModel> LoadThemeFromFile(string filePath);
Theme LoadThemeModelFromFile(string filePath); Task<Theme> LoadThemeModelFromFile(string filePath);
void SaveTheme(IThemeEditorViewModel themeEditorViewModel, string filePath); Task SaveThemeAsync(IThemeEditorViewModel themeEditorViewModel, string filePath);
} }
internal class ThemeProvider : IThemeProvider internal class ThemeProvider : IThemeProvider
@ -54,23 +55,26 @@ namespace Filtration.ThemeEditor.Providers
return themeViewModel; return themeViewModel;
} }
public IThemeEditorViewModel LoadThemeFromFile(string filePath) public async Task<IThemeEditorViewModel> LoadThemeFromFile(string filePath)
{ {
var model = _themePersistenceService.LoadTheme(filePath); var model = await _themePersistenceService.LoadThemeAsync(filePath);
var viewModel = Mapper.Map<IThemeEditorViewModel>(model); var viewModel = Mapper.Map<IThemeEditorViewModel>(model);
viewModel.FilePath = filePath; viewModel.FilePath = filePath;
return viewModel; return viewModel;
} }
public Theme LoadThemeModelFromFile(string filePath) public async Task<Theme> LoadThemeModelFromFile(string filePath)
{ {
return _themePersistenceService.LoadTheme(filePath); return await _themePersistenceService.LoadThemeAsync(filePath);
} }
public void SaveTheme(IThemeEditorViewModel themeEditorViewModel, string filePath) public async Task SaveThemeAsync(IThemeEditorViewModel themeEditorViewModel, string filePath)
{ {
var theme = Mapper.Map<Theme>(themeEditorViewModel); await Task.Run(() =>
_themePersistenceService.SaveTheme(theme, filePath); {
var theme = Mapper.Map<Theme>(themeEditorViewModel);
_themePersistenceService.SaveThemeAsync(theme, filePath);
});
} }
} }
} }

View File

@ -1,4 +1,5 @@
using System.IO; using System.IO;
using System.Threading.Tasks;
using System.Xml.Serialization; using System.Xml.Serialization;
using Filtration.ObjectModel.ThemeEditor; using Filtration.ObjectModel.ThemeEditor;
@ -6,35 +7,42 @@ namespace Filtration.ThemeEditor.Services
{ {
internal interface IThemePersistenceService internal interface IThemePersistenceService
{ {
Theme LoadTheme(string filePath); Task<Theme> LoadThemeAsync(string filePath);
void SaveTheme(Theme theme, string filePath); Task SaveThemeAsync(Theme theme, string filePath);
} }
internal class ThemePersistenceService : IThemePersistenceService internal class ThemePersistenceService : IThemePersistenceService
{ {
public Theme LoadTheme(string filePath) public async Task<Theme> LoadThemeAsync(string filePath)
{ {
var xmlSerializer = new XmlSerializer(typeof(Theme)); Theme loadedTheme = null;
Theme loadedTheme; await Task.Run(() =>
using (Stream reader = new FileStream(filePath, FileMode.Open))
{ {
loadedTheme = (Theme)xmlSerializer.Deserialize(reader); var xmlSerializer = new XmlSerializer(typeof (Theme));
}
using (Stream reader = new FileStream(filePath, FileMode.Open))
{
loadedTheme = (Theme) xmlSerializer.Deserialize(reader);
}
loadedTheme.FilePath = filePath;
});
loadedTheme.FilePath = filePath;
return loadedTheme; return loadedTheme;
} }
public void SaveTheme(Theme theme, string filePath) public async Task SaveThemeAsync(Theme theme, string filePath)
{ {
var xmlSerializer = new XmlSerializer(typeof(Theme)); await Task.Run(() =>
using (Stream writer = new FileStream(filePath, FileMode.Create))
{ {
xmlSerializer.Serialize(writer, theme); var xmlSerializer = new XmlSerializer(typeof (Theme));
}
using (Stream writer = new FileStream(filePath, FileMode.Create))
{
xmlSerializer.Serialize(writer, theme);
}
});
} }
} }
} }

View File

@ -1,5 +1,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media; using System.Windows.Media;
@ -55,7 +56,7 @@ namespace Filtration.ThemeEditor.ViewModels
AddThemeComponentCommand = new RelayCommand<ThemeComponentType>(OnAddThemeComponentCommand, t => IsMasterTheme); AddThemeComponentCommand = new RelayCommand<ThemeComponentType>(OnAddThemeComponentCommand, t => IsMasterTheme);
DeleteThemeComponentCommand = new RelayCommand<ThemeComponent>(OnDeleteThemeComponentCommand, DeleteThemeComponentCommand = new RelayCommand<ThemeComponent>(OnDeleteThemeComponentCommand,
t => IsMasterTheme && SelectedThemeComponent != null); t => IsMasterTheme && SelectedThemeComponent != null);
CloseCommand = new RelayCommand(OnCloseCommand); CloseCommand = new RelayCommand(async () => await OnCloseCommand());
var icon = new BitmapImage(); var icon = new BitmapImage();
icon.BeginInit(); icon.BeginInit();
@ -123,19 +124,19 @@ namespace Filtration.ThemeEditor.ViewModels
} }
} }
public void Save() public async Task SaveAsync()
{ {
if (IsMasterTheme) return; if (IsMasterTheme) return;
if (_filenameIsFake) if (_filenameIsFake)
{ {
SaveAs(); await SaveAsAsync();
return; return;
} }
try try
{ {
_themeProvider.SaveTheme(this, FilePath); await _themeProvider.SaveThemeAsync(this, FilePath);
//RemoveDirtyFlag(); //RemoveDirtyFlag();
} }
catch (Exception e) catch (Exception e)
@ -149,7 +150,7 @@ namespace Filtration.ThemeEditor.ViewModels
} }
} }
public void SaveAs() public async Task SaveAsAsync()
{ {
if (IsMasterTheme) return; if (IsMasterTheme) return;
@ -167,7 +168,7 @@ namespace Filtration.ThemeEditor.ViewModels
try try
{ {
FilePath = saveDialog.FileName; FilePath = saveDialog.FileName;
_themeProvider.SaveTheme(this, FilePath); await _themeProvider.SaveThemeAsync(this, FilePath);
_filenameIsFake = false; _filenameIsFake = false;
Title = Filename; Title = Filename;
//RemoveDirtyFlag(); //RemoveDirtyFlag();
@ -185,14 +186,16 @@ namespace Filtration.ThemeEditor.ViewModels
} }
} }
public void OnCloseCommand() public async Task OnCloseCommand()
{ {
Close(); await Close();
} }
public void Close() #pragma warning disable 1998
public async Task Close()
#pragma warning restore 1998
{ {
Messenger.Default.Send(new ThemeClosedMessage { ClosedViewModel = this }); Messenger.Default.Send(new ThemeClosedMessage {ClosedViewModel = this});
} }
private void OnAddThemeComponentCommand(ThemeComponentType themeComponentType) private void OnAddThemeComponentCommand(ThemeComponentType themeComponentType)

View File

@ -17,7 +17,7 @@ using NLog;
namespace Filtration namespace Filtration
{ {
public partial class App : Application public partial class App
{ {
private IWindsorContainer _container; private IWindsorContainer _container;
private static readonly Logger _logger = LogManager.GetCurrentClassLogger(); private static readonly Logger _logger = LogManager.GetCurrentClassLogger();

View File

@ -94,6 +94,10 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
<Reference Include="PresentationCore" /> <Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" /> <Reference Include="PresentationFramework" />
<Reference Include="WpfAnimatedGif, Version=1.4.13.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\WpfAnimatedGif.1.4.13\lib\net\WpfAnimatedGif.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\WPFToolkit.dll</HintPath> <HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\WPFToolkit.dll</HintPath>
@ -365,6 +369,7 @@
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile> </Compile>
<Resource Include="Resources\loading_spinner.gif" />
<EmbeddedResource Include="Properties\Resources.resx"> <EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator> <Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput> <LastGenOutput>Resources.Designer.cs</LastGenOutput>

View File

@ -1,4 +1,5 @@
using Filtration.ObjectModel; using System.Threading.Tasks;
using Filtration.ObjectModel;
using Filtration.Services; using Filtration.Services;
using Filtration.ViewModels; using Filtration.ViewModels;
@ -6,7 +7,7 @@ namespace Filtration.Repositories
{ {
internal interface IItemFilterScriptRepository internal interface IItemFilterScriptRepository
{ {
IItemFilterScriptViewModel LoadScriptFromFile(string path); Task<IItemFilterScriptViewModel> LoadScriptFromFileAsync(string path);
IItemFilterScriptViewModel NewScript(); IItemFilterScriptViewModel NewScript();
string GetItemFilterScriptDirectory(); string GetItemFilterScriptDirectory();
void SetItemFilterScriptDirectory(string path); void SetItemFilterScriptDirectory(string path);
@ -24,9 +25,9 @@ namespace Filtration.Repositories
_itemFilterScriptViewModelFactory = itemFilterScriptViewModelFactory; _itemFilterScriptViewModelFactory = itemFilterScriptViewModelFactory;
} }
public IItemFilterScriptViewModel LoadScriptFromFile(string path) public async Task<IItemFilterScriptViewModel> LoadScriptFromFileAsync(string path)
{ {
var loadedScript = _itemFilterPersistenceService.LoadItemFilterScript(path); var loadedScript = await _itemFilterPersistenceService.LoadItemFilterScriptAsync(path);
var newViewModel = _itemFilterScriptViewModelFactory.Create(); var newViewModel = _itemFilterScriptViewModelFactory.Create();
newViewModel.Initialise(loadedScript, false); newViewModel.Initialise(loadedScript, false);

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -1,4 +1,5 @@
using System.IO; using System.IO;
using System.Threading.Tasks;
using Filtration.Common.Services; using Filtration.Common.Services;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.Properties; using Filtration.Properties;
@ -10,8 +11,8 @@ namespace Filtration.Services
{ {
void SetItemFilterScriptDirectory(string path); void SetItemFilterScriptDirectory(string path);
string ItemFilterScriptDirectory { get; } string ItemFilterScriptDirectory { get; }
ItemFilterScript LoadItemFilterScript(string filePath); Task<ItemFilterScript> LoadItemFilterScriptAsync(string filePath);
void SaveItemFilterScript(ItemFilterScript script); Task SaveItemFilterScriptAsync(ItemFilterScript script);
string DefaultPathOfExileDirectory(); string DefaultPathOfExileDirectory();
} }
@ -58,20 +59,30 @@ namespace Filtration.Services
Settings.Default.DefaultFilterDirectory = path; Settings.Default.DefaultFilterDirectory = path;
} }
public ItemFilterScript LoadItemFilterScript(string filePath) public async Task<ItemFilterScript> LoadItemFilterScriptAsync(string filePath)
{ {
var script = ItemFilterScript loadedScript = null;
_itemFilterScriptTranslator.TranslateStringToItemFilterScript( await Task.Run(() =>
{
loadedScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(
_fileSystemService.ReadFileAsString(filePath)); _fileSystemService.ReadFileAsString(filePath));
});
script.FilePath = filePath; if (loadedScript != null)
return script; {
loadedScript.FilePath = filePath;
}
return loadedScript;
} }
public void SaveItemFilterScript(ItemFilterScript script) public async Task SaveItemFilterScriptAsync(ItemFilterScript script)
{ {
_fileSystemService.WriteFileFromString(script.FilePath, await Task.Run(() =>
_itemFilterScriptTranslator.TranslateItemFilterScriptToString(script)); {
_fileSystemService.WriteFileFromString(script.FilePath,
_itemFilterScriptTranslator.TranslateItemFilterScriptToString(script));
});
} }
} }
} }

View File

@ -7,7 +7,7 @@ namespace Filtration.Services
{ {
internal interface IUpdateCheckService internal interface IUpdateCheckService
{ {
Task<UpdateData> GetUpdateData(); Task<UpdateData> GetUpdateDataAsync();
} }
internal class UpdateCheckService : IUpdateCheckService internal class UpdateCheckService : IUpdateCheckService
@ -20,7 +20,7 @@ namespace Filtration.Services
_httpService = httpService; _httpService = httpService;
} }
public async Task<UpdateData> GetUpdateData() public async Task<UpdateData> GetUpdateDataAsync()
{ {
var updateXml = await _httpService.GetContentAsync(UpdateDataUrl); var updateXml = await _httpService.GetContentAsync(UpdateDataUrl);
return (DeserializeUpdateData(updateXml)); return (DeserializeUpdateData(updateXml));

View File

@ -39,9 +39,9 @@ namespace Filtration.ViewModels
private readonly ReadOnlyObservableCollection<IDocument> _readOnlyOpenDocuments; private readonly ReadOnlyObservableCollection<IDocument> _readOnlyOpenDocuments;
public AvalonDockWorkspaceViewModel(ISectionBrowserViewModel sectionBrowserViewModel, public AvalonDockWorkspaceViewModel(ISectionBrowserViewModel sectionBrowserViewModel,
IBlockGroupBrowserViewModel blockGroupBrowserViewModel, IBlockGroupBrowserViewModel blockGroupBrowserViewModel,
IStartPageViewModel startPageViewModel, IStartPageViewModel startPageViewModel,
IBlockOutputPreviewViewModel blockOutputPreviewViewModel) IBlockOutputPreviewViewModel blockOutputPreviewViewModel)
{ {
_sectionBrowserViewModel = sectionBrowserViewModel; _sectionBrowserViewModel = sectionBrowserViewModel;
_blockGroupBrowserViewModel = blockGroupBrowserViewModel; _blockGroupBrowserViewModel = blockGroupBrowserViewModel;
@ -123,7 +123,6 @@ namespace Filtration.ViewModels
private List<IToolViewModel> _tools; private List<IToolViewModel> _tools;
public IEnumerable<IToolViewModel> Tools public IEnumerable<IToolViewModel> Tools
{ {
get get

View File

@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
using System.ComponentModel; using System.ComponentModel;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Forms; using System.Windows.Forms;
@ -104,7 +105,7 @@ namespace Filtration.ViewModels
ToggleShowAdvancedCommand = new RelayCommand<bool>(OnToggleShowAdvancedCommand); ToggleShowAdvancedCommand = new RelayCommand<bool>(OnToggleShowAdvancedCommand);
ClearFilterCommand = new RelayCommand(OnClearFilterCommand, () => BlockFilterPredicate != null); ClearFilterCommand = new RelayCommand(OnClearFilterCommand, () => BlockFilterPredicate != null);
CloseCommand = new RelayCommand(OnCloseCommand); CloseCommand = new RelayCommand(async () => await OnCloseCommand());
DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => SelectedBlockViewModel != null); DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => SelectedBlockViewModel != null);
MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => SelectedBlockViewModel != null); MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => SelectedBlockViewModel != null);
MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => SelectedBlockViewModel != null); MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => SelectedBlockViewModel != null);
@ -351,20 +352,21 @@ namespace Filtration.ViewModels
ContentId = "ScriptContentId"; ContentId = "ScriptContentId";
} }
public void Save() public async Task SaveAsync()
{ {
if (!ValidateScript()) return; if (!ValidateScript()) return;
if (!CheckForUnusedThemeComponents()) return; if (!CheckForUnusedThemeComponents()) return;
if (_filenameIsFake) if (_filenameIsFake)
{ {
SaveAs(); await SaveAsAsync();
return; return;
} }
Messenger.Default.Send(new NotificationMessage("ShowLoadingBanner"));
try try
{ {
_persistenceService.SaveItemFilterScript(Script); await _persistenceService.SaveItemFilterScriptAsync(Script);
RemoveDirtyFlag(); RemoveDirtyFlag();
} }
catch (Exception e) catch (Exception e)
@ -377,9 +379,15 @@ namespace Filtration.ViewModels
_messageBoxService.Show("Save Error", "Error saving filter file - " + e.Message, MessageBoxButton.OK, _messageBoxService.Show("Save Error", "Error saving filter file - " + e.Message, MessageBoxButton.OK,
MessageBoxImage.Error); MessageBoxImage.Error);
} }
finally
{
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
}
return;
} }
public void SaveAs() public async Task SaveAsAsync()
{ {
if (!ValidateScript()) return; if (!ValidateScript()) return;
if (!CheckForUnusedThemeComponents()) return; if (!CheckForUnusedThemeComponents()) return;
@ -395,11 +403,13 @@ namespace Filtration.ViewModels
if (result != DialogResult.OK) return; if (result != DialogResult.OK) return;
Messenger.Default.Send(new NotificationMessage("ShowLoadingBanner"));
var previousFilePath = Script.FilePath; var previousFilePath = Script.FilePath;
try try
{ {
Script.FilePath = saveDialog.FileName; Script.FilePath = saveDialog.FileName;
_persistenceService.SaveItemFilterScript(Script); await _persistenceService.SaveItemFilterScriptAsync(Script);
_filenameIsFake = false; _filenameIsFake = false;
Title = Filename; Title = Filename;
RemoveDirtyFlag(); RemoveDirtyFlag();
@ -415,6 +425,10 @@ namespace Filtration.ViewModels
MessageBoxImage.Error); MessageBoxImage.Error);
Script.FilePath = previousFilePath; Script.FilePath = previousFilePath;
} }
finally
{
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
}
} }
private bool CheckForUnusedThemeComponents() private bool CheckForUnusedThemeComponents()
@ -480,12 +494,12 @@ namespace Filtration.ViewModels
return false; return false;
} }
private void OnCloseCommand() private async Task OnCloseCommand()
{ {
Close(); await Close();
} }
public void Close() public async Task Close()
{ {
if (!IsDirty) if (!IsDirty)
{ {
@ -499,20 +513,20 @@ namespace Filtration.ViewModels
switch (result) switch (result)
{ {
case MessageBoxResult.Yes: case MessageBoxResult.Yes:
{ {
Save(); await SaveAsync();
CloseScript(); CloseScript();
break; break;
} }
case MessageBoxResult.No: case MessageBoxResult.No:
{ {
CloseScript(); CloseScript();
break; break;
} }
case MessageBoxResult.Cancel: case MessageBoxResult.Cancel:
{ {
return; return;
} }
} }
} }
} }
@ -777,6 +791,7 @@ namespace Filtration.ViewModels
IsDirty = true; IsDirty = true;
SelectedBlockViewModel = vm; SelectedBlockViewModel = vm;
RaisePropertyChanged("ItemFilterSectionViewModels"); RaisePropertyChanged("ItemFilterSectionViewModels");
Messenger.Default.Send(new NotificationMessage("SectionsChanged"));
} }
private void OnExpandAllBlocksCommand() private void OnExpandAllBlocksCommand()
@ -808,9 +823,17 @@ namespace Filtration.ViewModels
if (result == MessageBoxResult.Yes) if (result == MessageBoxResult.Yes)
{ {
var isSection = targetBlockViewModel.Block is ItemFilterSection;
Script.ItemFilterBlocks.Remove(targetBlockViewModel.Block); Script.ItemFilterBlocks.Remove(targetBlockViewModel.Block);
ItemFilterBlockViewModels.Remove(targetBlockViewModel); ItemFilterBlockViewModels.Remove(targetBlockViewModel);
IsDirty = true; IsDirty = true;
if (isSection)
{
Messenger.Default.Send(new NotificationMessage("SectionsChanged"));
}
} }
SelectedBlockViewModel = null; SelectedBlockViewModel = null;
} }

View File

@ -3,6 +3,7 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media; using System.Windows.Media;
@ -34,7 +35,7 @@ namespace Filtration.ViewModels
{ {
RelayCommand OpenScriptCommand { get; } RelayCommand OpenScriptCommand { get; }
RelayCommand NewScriptCommand { get; } RelayCommand NewScriptCommand { get; }
bool CloseAllDocuments(); Task<bool> CloseAllDocuments();
} }
internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel
@ -51,6 +52,7 @@ namespace Filtration.ViewModels
private readonly IUpdateCheckService _updateCheckService; private readonly IUpdateCheckService _updateCheckService;
private readonly IUpdateAvailableViewModel _updateAvailableViewModel; private readonly IUpdateAvailableViewModel _updateAvailableViewModel;
private readonly IMessageBoxService _messageBoxService; private readonly IMessageBoxService _messageBoxService;
private bool _showLoadingBanner;
public MainWindowViewModel(IItemFilterScriptRepository itemFilterScriptRepository, public MainWindowViewModel(IItemFilterScriptRepository itemFilterScriptRepository,
IItemFilterScriptTranslator itemFilterScriptTranslator, IItemFilterScriptTranslator itemFilterScriptTranslator,
@ -76,11 +78,11 @@ namespace Filtration.ViewModels
NewScriptCommand = new RelayCommand(OnNewScriptCommand); NewScriptCommand = new RelayCommand(OnNewScriptCommand);
CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, () => ActiveDocumentIsScript); CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, () => ActiveDocumentIsScript);
OpenScriptCommand = new RelayCommand(OnOpenScriptCommand); OpenScriptCommand = new RelayCommand(async () => await OnOpenScriptCommand());
OpenThemeCommand = new RelayCommand(OnOpenThemeCommand); OpenThemeCommand = new RelayCommand(async () => await OnOpenThemeCommand());
SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable); SaveCommand = new RelayCommand(async () => await OnSaveDocumentCommand(), ActiveDocumentIsEditable);
SaveAsCommand = new RelayCommand(OnSaveAsCommand, ActiveDocumentIsEditable); SaveAsCommand = new RelayCommand(async () => await OnSaveAsCommand(), ActiveDocumentIsEditable);
CloseCommand = new RelayCommand(OnCloseDocumentCommand, ActiveDocumentIsEditable); CloseCommand = new RelayCommand(OnCloseDocumentCommand, ActiveDocumentIsEditable);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
@ -104,7 +106,7 @@ namespace Filtration.ViewModels
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocumentIsScript); ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocumentIsScript);
CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => ActiveDocumentIsScript); CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => ActiveDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(OnApplyThemeToScriptCommand, () => ActiveDocumentIsScript); ApplyThemeToScriptCommand = new RelayCommand(async () => await OnApplyThemeToScriptCommand(), () => ActiveDocumentIsScript);
EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => ActiveDocumentIsScript); EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => ActiveDocumentIsScript);
AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable); AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable);
@ -166,7 +168,19 @@ namespace Filtration.ViewModels
} }
case "OpenScript": case "OpenScript":
{ {
#pragma warning disable 4014
OnOpenScriptCommand(); OnOpenScriptCommand();
#pragma warning restore 4014
break;
}
case "ShowLoadingBanner":
{
ShowLoadingBanner = true;
break;
}
case "HideLoadingBanner":
{
ShowLoadingBanner = false;
break; break;
} }
} }
@ -221,7 +235,7 @@ namespace Filtration.ViewModels
try try
{ {
var result = await _updateCheckService.GetUpdateData(); var result = await _updateCheckService.GetUpdateDataAsync();
if (result.LatestVersionMajorPart >= assemblyVersion.FileMajorPart && if (result.LatestVersionMajorPart >= assemblyVersion.FileMajorPart &&
result.LatestVersionMinorPart > assemblyVersion.FileMinorPart) result.LatestVersionMinorPart > assemblyVersion.FileMinorPart)
@ -279,6 +293,16 @@ namespace Filtration.ViewModels
} }
} }
public bool ShowLoadingBanner
{
get { return _showLoadingBanner; }
private set
{
_showLoadingBanner = value;
RaisePropertyChanged();
}
}
public bool ActiveDocumentIsScript public bool ActiveDocumentIsScript
{ {
get { return _avalonDockWorkspaceViewModel.ActiveDocument != null && _avalonDockWorkspaceViewModel.ActiveDocument.IsScript; } get { return _avalonDockWorkspaceViewModel.ActiveDocument != null && _avalonDockWorkspaceViewModel.ActiveDocument.IsScript; }
@ -362,7 +386,8 @@ namespace Filtration.ViewModels
var aboutWindow = new AboutWindow(); var aboutWindow = new AboutWindow();
aboutWindow.ShowDialog(); aboutWindow.ShowDialog();
} }
private void OnOpenScriptCommand()
private async Task OnOpenScriptCommand()
{ {
var openFileDialog = new OpenFileDialog var openFileDialog = new OpenFileDialog
{ {
@ -374,12 +399,14 @@ namespace Filtration.ViewModels
IItemFilterScriptViewModel loadedViewModel; IItemFilterScriptViewModel loadedViewModel;
Messenger.Default.Send(new NotificationMessage("ShowLoadingBanner"));
try try
{ {
loadedViewModel = _itemFilterScriptRepository.LoadScriptFromFile(openFileDialog.FileName); loadedViewModel = await _itemFilterScriptRepository.LoadScriptFromFileAsync(openFileDialog.FileName);
} }
catch(IOException e) catch(IOException e)
{ {
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
if (_logger.IsErrorEnabled) if (_logger.IsErrorEnabled)
{ {
_logger.Error(e); _logger.Error(e);
@ -390,10 +417,11 @@ namespace Filtration.ViewModels
return; return;
} }
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
_avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel);
} }
private void OnOpenThemeCommand() private async Task OnOpenThemeCommand()
{ {
var filePath = ShowOpenThemeDialog(); var filePath = ShowOpenThemeDialog();
@ -406,7 +434,7 @@ namespace Filtration.ViewModels
try try
{ {
loadedViewModel = _themeProvider.LoadThemeFromFile(filePath); loadedViewModel = await _themeProvider.LoadThemeFromFile(filePath);
} }
catch (IOException e) catch (IOException e)
{ {
@ -423,7 +451,7 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel);
} }
private void OnApplyThemeToScriptCommand() private async Task OnApplyThemeToScriptCommand()
{ {
var filePath = ShowOpenThemeDialog(); var filePath = ShowOpenThemeDialog();
if (string.IsNullOrEmpty(filePath)) if (string.IsNullOrEmpty(filePath))
@ -435,7 +463,7 @@ namespace Filtration.ViewModels
try try
{ {
loadedTheme = _themeProvider.LoadThemeModelFromFile(filePath); loadedTheme = await _themeProvider.LoadThemeModelFromFile(filePath);
} }
catch (IOException e) catch (IOException e)
{ {
@ -490,14 +518,14 @@ namespace Filtration.ViewModels
} }
} }
private void OnSaveDocumentCommand() private async Task OnSaveDocumentCommand()
{ {
((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).Save(); await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsync();
} }
private void OnSaveAsCommand() private async Task OnSaveAsCommand()
{ {
((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAs(); await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsAsync();
} }
private void OnReplaceColorsCommand() private void OnReplaceColorsCommand()
@ -629,14 +657,14 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent); _avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent);
} }
public bool CloseAllDocuments() public async Task<bool> CloseAllDocuments()
{ {
var openDocuments = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().ToList(); var openDocuments = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().ToList();
foreach (var document in openDocuments) foreach (var document in openDocuments)
{ {
var docCount = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count(); var docCount = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count();
document.Close(); await document.Close();
if (_avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count() == docCount) if (_avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count() == docCount)
{ {
return false; return false;

View File

@ -1,4 +1,5 @@
using Filtration.Common.ViewModels; using System.Threading.Tasks;
using Filtration.Common.ViewModels;
using Filtration.Interface; using Filtration.Interface;
using GalaSoft.MvvmLight.CommandWpf; using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging; using GalaSoft.MvvmLight.Messaging;
@ -25,7 +26,7 @@ namespace Filtration.ViewModels
public bool IsScript { get { return false; } } public bool IsScript { get { return false; } }
public bool IsTheme { get { return false; } } public bool IsTheme { get { return false; } }
public void Close() public Task Close()
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using GalaSoft.MvvmLight.Messaging;
namespace Filtration.ViewModels.ToolPanes namespace Filtration.ViewModels.ToolPanes
{ {
@ -23,6 +24,18 @@ namespace Filtration.ViewModels.ToolPanes
icon.UriSource = new Uri("pack://application:,,,/Filtration;component/Resources/Icons/add_section_icon.png"); icon.UriSource = new Uri("pack://application:,,,/Filtration;component/Resources/Icons/add_section_icon.png");
icon.EndInit(); icon.EndInit();
IconSource = icon; IconSource = icon;
Messenger.Default.Register<NotificationMessage>(this, message =>
{
switch (message.Notification)
{
case "SectionsChanged":
{
OnActiveDocumentChanged(this, EventArgs.Empty);
break;
}
}
});
} }
public const string ToolContentId = "SectionBrowserTool"; public const string ToolContentId = "SectionBrowserTool";

View File

@ -10,9 +10,10 @@
xmlns:converters="clr-namespace:Filtration.Converters" xmlns:converters="clr-namespace:Filtration.Converters"
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock" xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:themeEditorViews="clr-namespace:Filtration.ThemeEditor.Views;assembly=Filtration.ThemeEditor" xmlns:themeEditorViews="clr-namespace:Filtration.ThemeEditor.Views;assembly=Filtration.ThemeEditor"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance d:Type=viewModels:AvalonDockWorkspaceViewModel}" d:DataContext="{d:DesignInstance d:Type=viewModels:AvalonDockWorkspaceViewModel}"
d:DesignHeight="300" d:DesignWidth="300"> d:DesignHeight="300" d:DesignWidth="700">
<UserControl.Resources> <UserControl.Resources>
<xcad:BoolToVisibilityConverter x:Key="AvalonBoolToVisibilityConverter" /> <xcad:BoolToVisibilityConverter x:Key="AvalonBoolToVisibilityConverter" />
<converters:ActiveDocumentConverter x:Key="ActiveDocumentConverter" /> <converters:ActiveDocumentConverter x:Key="ActiveDocumentConverter" />

View File

@ -8,6 +8,7 @@
xmlns:viewModels="clr-namespace:Filtration.ViewModels" xmlns:viewModels="clr-namespace:Filtration.ViewModels"
xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock" xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock"
xmlns:views="clr-namespace:Filtration.Views" xmlns:views="clr-namespace:Filtration.Views"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}" d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}"
Title="{Binding WindowTitle}" Height="762" Width="1126" IsIconVisible="True" Title="{Binding WindowTitle}" Height="762" Width="1126" IsIconVisible="True"
@ -18,7 +19,7 @@
<KeyBinding Command="{Binding NewScriptCommand}" Modifiers="Control" Key="N" /> <KeyBinding Command="{Binding NewScriptCommand}" Modifiers="Control" Key="N" />
</fluent:RibbonWindow.InputBindings> </fluent:RibbonWindow.InputBindings>
<DockPanel x:Name="RootDockPanel"> <DockPanel x:Name="RootDockPanel">
<fluent:Ribbon DockPanel.Dock="Top" x:Name="RibbonRoot"> <fluent:Ribbon DockPanel.Dock="Top" x:Name="RibbonRoot" IsEnabled="{Binding ShowLoadingBanner, Converter={StaticResource BoolInverterConverter}}">
<fluent:Ribbon.Menu> <fluent:Ribbon.Menu>
<fluent:Backstage> <fluent:Backstage>
<fluent:BackstageTabControl> <fluent:BackstageTabControl>
@ -118,6 +119,30 @@
</fluent:Ribbon> </fluent:Ribbon>
<Grid> <Grid>
<viewsAvalonDock:AvalonDockWorkspaceView DataContext="{Binding AvalonDockWorkspaceViewModel}" /> <viewsAvalonDock:AvalonDockWorkspaceView DataContext="{Binding AvalonDockWorkspaceViewModel}" />
<Grid ZIndex="9999" Visibility="{Binding ShowLoadingBanner, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}">
<Grid.Background>
<SolidColorBrush Color="Black" Opacity="0.5" />
</Grid.Background>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Border Grid.Row="1" Grid.Column="1" BorderBrush="Black" BorderThickness="1" Background="White" Padding="20">
<StackPanel Orientation="Horizontal">
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="20" FontWeight="DemiBold">Working...</TextBlock>
<Image gif:ImageBehavior.AnimatedSource="/Filtration;component/Resources/loading_spinner.gif" Height="32" Margin="10,0,0,0"/>
</StackPanel>
</Border>
</Grid>
</Grid>
</Grid> </Grid>
</DockPanel> </DockPanel>
</fluent:RibbonWindow> </fluent:RibbonWindow>

View File

@ -1,7 +1,6 @@
using System; using System.ComponentModel;
using System.ComponentModel; using System.Threading.Tasks;
using System.Windows; using System.Windows;
using Filtration.Annotations;
using Filtration.ViewModels; using Filtration.ViewModels;
namespace Filtration.Views namespace Filtration.Views
@ -13,7 +12,7 @@ namespace Filtration.Views
internal partial class MainWindow : IMainWindow internal partial class MainWindow : IMainWindow
{ {
private IMainWindowViewModel _mainWindowViewModel; private readonly IMainWindowViewModel _mainWindowViewModel;
public MainWindow(IMainWindowViewModel mainWindowViewModel) public MainWindow(IMainWindowViewModel mainWindowViewModel)
{ {
@ -40,11 +39,11 @@ namespace Filtration.Views
private void MainWindow_OnClosing(object sender, CancelEventArgs e) private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{ {
var allDocumentsClosed = _mainWindowViewModel.CloseAllDocuments(); var allDocumentsClosed = _mainWindowViewModel.CloseAllDocuments().Result;
if (!allDocumentsClosed) if (!allDocumentsClosed)
{ {
e.Cancel = true; e.Cancel = true;
} }
} }
} }

View File

@ -11,5 +11,6 @@
<package id="NLog" version="4.0.1" targetFramework="net451" /> <package id="NLog" version="4.0.1" targetFramework="net451" />
<package id="NLog.Config" version="4.0.1" targetFramework="net451" /> <package id="NLog.Config" version="4.0.1" targetFramework="net451" />
<package id="NLog.Schema" version="4.0.1" targetFramework="net451" /> <package id="NLog.Schema" version="4.0.1" targetFramework="net451" />
<package id="WpfAnimatedGif" version="1.4.13" targetFramework="net451" />
<package id="WPFToolkit" version="3.5.50211.1" targetFramework="net451" /> <package id="WPFToolkit" version="3.5.50211.1" targetFramework="net451" />
</packages> </packages>