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
{
bool IsScript { 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
{
bool IsDirty { get; }
void Save();
void SaveAs();
Task SaveAsync();
Task SaveAsAsync();
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -94,6 +94,10 @@
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<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">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\WPFToolkit.dll</HintPath>
@ -365,6 +369,7 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<Resource Include="Resources\loading_spinner.gif" />
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<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.ViewModels;
@ -6,7 +7,7 @@ namespace Filtration.Repositories
{
internal interface IItemFilterScriptRepository
{
IItemFilterScriptViewModel LoadScriptFromFile(string path);
Task<IItemFilterScriptViewModel> LoadScriptFromFileAsync(string path);
IItemFilterScriptViewModel NewScript();
string GetItemFilterScriptDirectory();
void SetItemFilterScriptDirectory(string path);
@ -24,9 +25,9 @@ namespace Filtration.Repositories
_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();
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.Threading.Tasks;
using Filtration.Common.Services;
using Filtration.ObjectModel;
using Filtration.Properties;
@ -10,8 +11,8 @@ namespace Filtration.Services
{
void SetItemFilterScriptDirectory(string path);
string ItemFilterScriptDirectory { get; }
ItemFilterScript LoadItemFilterScript(string filePath);
void SaveItemFilterScript(ItemFilterScript script);
Task<ItemFilterScript> LoadItemFilterScriptAsync(string filePath);
Task SaveItemFilterScriptAsync(ItemFilterScript script);
string DefaultPathOfExileDirectory();
}
@ -58,20 +59,30 @@ namespace Filtration.Services
Settings.Default.DefaultFilterDirectory = path;
}
public ItemFilterScript LoadItemFilterScript(string filePath)
public async Task<ItemFilterScript> LoadItemFilterScriptAsync(string filePath)
{
var script =
_itemFilterScriptTranslator.TranslateStringToItemFilterScript(
ItemFilterScript loadedScript = null;
await Task.Run(() =>
{
loadedScript = _itemFilterScriptTranslator.TranslateStringToItemFilterScript(
_fileSystemService.ReadFileAsString(filePath));
});
script.FilePath = filePath;
return script;
if (loadedScript != null)
{
loadedScript.FilePath = filePath;
}
public void SaveItemFilterScript(ItemFilterScript script)
return loadedScript;
}
public async Task SaveItemFilterScriptAsync(ItemFilterScript script)
{
await Task.Run(() =>
{
_fileSystemService.WriteFileFromString(script.FilePath,
_itemFilterScriptTranslator.TranslateItemFilterScriptToString(script));
});
}
}
}

View File

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

View File

@ -123,7 +123,6 @@ namespace Filtration.ViewModels
private List<IToolViewModel> _tools;
public IEnumerable<IToolViewModel> Tools
{
get

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Windows.Media.Imaging;
using GalaSoft.MvvmLight.Messaging;
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.EndInit();
IconSource = icon;
Messenger.Default.Register<NotificationMessage>(this, message =>
{
switch (message.Notification)
{
case "SectionsChanged":
{
OnActiveDocumentChanged(this, EventArgs.Empty);
break;
}
}
});
}
public const string ToolContentId = "SectionBrowserTool";

View File

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

View File

@ -8,6 +8,7 @@
xmlns:viewModels="clr-namespace:Filtration.ViewModels"
xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock"
xmlns:views="clr-namespace:Filtration.Views"
xmlns:gif="http://wpfanimatedgif.codeplex.com"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}"
Title="{Binding WindowTitle}" Height="762" Width="1126" IsIconVisible="True"
@ -18,7 +19,7 @@
<KeyBinding Command="{Binding NewScriptCommand}" Modifiers="Control" Key="N" />
</fluent:RibbonWindow.InputBindings>
<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:Backstage>
<fluent:BackstageTabControl>
@ -118,6 +119,30 @@
</fluent:Ribbon>
<Grid>
<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>
</DockPanel>
</fluent:RibbonWindow>

View File

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

View File

@ -11,5 +11,6 @@
<package id="NLog" 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="WpfAnimatedGif" version="1.4.13" targetFramework="net451" />
<package id="WPFToolkit" version="3.5.50211.1" targetFramework="net451" />
</packages>