12 Commits
0.9 ... 0.10

Author SHA1 Message Date
Ben
37258e563a Added Divination Cards to base types 2015-07-26 17:12:51 +01:00
Ben
71e1f2bf78 Revert "Removed Stackable Currency from ItemClasses"
This reverts commit f3ed386845.
2015-07-26 17:03:12 +01:00
Ben
b2b412a73c Revert "Removed Thrusting One Hand Swords from Base Types"
This reverts commit e80295cb69.
2015-07-26 17:03:06 +01:00
Ben
ae948c83a5 Updated version number to 0.10 2015-07-26 17:02:54 +01:00
Ben
3727166a44 Added drag and drop to open script/theme functionality 2015-07-26 11:48:54 +01:00
Ben
32b0a0199f Implemented async saving and loading 2015-07-25 19:02:42 +01:00
Ben
e54730d693 Added Tooltips for keyboard shortcuts and added Ctrl+N shortcut 2015-07-25 15:46:38 +01:00
Ben
d11eefaeab Fixed crash when pasting blocks with block groups assigned 2015-07-24 18:41:13 +01:00
Ben
da5b2c73a0 Moved clipboard operations to ClipboardService 2015-07-24 16:52:31 +01:00
Ben
2ff1373c6b Merge branch 'master' of https://github.com/ben-wallis/Filtration.git 2015-07-24 14:47:52 +01:00
Ben
1882687601 Fixed BlockGroupBrowser indeterminate checkbox state bug 2015-07-24 14:47:47 +01:00
Ben Wallis
3ba25b8f07 Updated release to 0.9 2015-07-15 19:55:52 +01:00
31 changed files with 481 additions and 187 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)
{
var theme = Mapper.Map<Theme>(themeEditorViewModel);
_themePersistenceService.SaveTheme(theme, filePath);
await Task.Run(() =>
{
var theme = Mapper.Map<Theme>(themeEditorViewModel);
_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,35 +7,42 @@ 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)
{
var xmlSerializer = new XmlSerializer(typeof(Theme));
Theme loadedTheme = null;
Theme loadedTheme;
using (Stream reader = new FileStream(filePath, FileMode.Open))
await Task.Run(() =>
{
loadedTheme = (Theme)xmlSerializer.Deserialize(reader);
}
loadedTheme.FilePath = filePath;
var xmlSerializer = new XmlSerializer(typeof (Theme));
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)
{
var xmlSerializer = new XmlSerializer(typeof(Theme));
using (Stream writer = new FileStream(filePath, FileMode.Create))
await Task.Run(() =>
{
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.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,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)

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>
@@ -145,6 +149,7 @@
<Compile Include="Models\UpdateData.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Repositories\ItemFilterScriptRepository.cs" />
<Compile Include="Services\ClipboardService.cs" />
<Compile Include="Services\HTTPService.cs" />
<Compile Include="Services\ItemFilterPersistenceService.cs" />
<Compile Include="Services\StaticDataService.cs" />
@@ -243,7 +248,6 @@
<Compile Include="Views\UpdateAvailableView.xaml.cs">
<DependentUpon>UpdateAvailableView.xaml</DependentUpon>
</Compile>
<Compile Include="WindsorInstallers\ModelsInstaller.cs" />
<Compile Include="WindsorInstallers\RepositoriesInstaller.cs" />
<Compile Include="WindsorInstallers\ServicesInstaller.cs" />
<Compile Include="WindsorInstallers\TranslatorsInstaller.cs" />
@@ -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

@@ -7,7 +7,7 @@ using System.Windows;
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Filtration")]
[assembly: AssemblyDescription("An item filter script manager for Path of Exile")]
[assembly: AssemblyDescription("An item filter script editor for Path of Exile")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("XVar Industries Inc.")]
[assembly: AssemblyProduct("Filtration")]
@@ -50,7 +50,7 @@ using System.Windows;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("0.9.*")]
[assembly: AssemblyVersion("0.10.*")]
[assembly: InternalsVisibleTo("Filtration.Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]

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);

View File

@@ -1069,31 +1069,54 @@ Sage Wand
Serpent Wand
Spiraled Wand
Tornado Wand
Emperor's Luck
Abandoned Wealth
The Avenger
The Brittle Emperor
Hope
The Battle Born
Birth of the Three
The Brittle Emperor
The Carrion Crow
The Cataclysm
The Celestial Justicar
The Chains that Bind
Chaotic Disposition
Coveted Possession
The Dark Mage
The Doctor
The Drunken Aristocrat
Emperor's Luck
The Explorer
The Feast
The Fiend
The Gambler
The Gemcutter
Gemcutter's Promise
The Gladiator
The Hermit
The Hoarder
Hope
The Hunger
Humility
The Incantation
The Inventor
Jack in the Box
The King's Heart
Lantador's Lost Love
The Lover
Lucky Connections
The Metalsmith's Gift
The Pact
The Poet
The Queen
Rain of Chaos
The Road to Power
The Scarred Meadow
The Scholar
The Summoner
Vinia's Token
Three Faces in the Dark
The Hermit
Lantador's Lost Love
Birth of the Three
The Lover
Chaotic Disposition
Eternal Sword
The Sun
The Gemcutter
The Warden
Three Faces in the Dark
Time-Lost Relic
The Union
Vinia's Token
The Warden
The Watcher
The Wind

View File

@@ -8,6 +8,7 @@ Claws
Daggers
Wands
One Hand Swords
Thrusting One Hand Swords
One Hand Axes
One Hand Maces
Bows
@@ -24,6 +25,7 @@ Boots
Body Armours
Helmets
Shields
Stackable Currency
Quest Items
Sceptres
Utility Flasks

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,43 @@
using System;
using System.Threading;
using System.Windows;
using NLog;
namespace Filtration.Services
{
internal interface IClipboardService
{
void SetClipboardText(string inputText);
string GetClipboardText();
}
internal class ClipboardService : IClipboardService
{
private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
public void SetClipboardText(string inputText)
{
for (var i = 0; i < 10; i++)
{
try
{
Clipboard.SetText(inputText);
return;
}
catch (Exception e)
{
_logger.Error(e);
}
Thread.Sleep(10);
}
throw new Exception("Failed to copy to clipboard");
}
public string GetClipboardText()
{
return Clipboard.GetText();
}
}
}

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;
}
return loadedScript;
}
public void SaveItemFilterScript(ItemFilterScript script)
public async Task SaveItemFilterScriptAsync(ItemFilterScript script)
{
_fileSystemService.WriteFileFromString(script.FilePath,
_itemFilterScriptTranslator.TranslateItemFilterScriptToString(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

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Documents;
using Castle.Core.Internal;
using Filtration.ObjectModel;
using Filtration.Properties;

View File

@@ -17,7 +17,8 @@ namespace Filtration.Utilities
if (viewModel.ChildGroups.All(g => g.IsChecked == true))
{
viewModel.IsChecked = true;
} else if (viewModel.ChildGroups.Any(g => g.IsChecked == true))
}
else if (viewModel.ChildGroups.Any(g => g.IsChecked == true || g.IsChecked == null))
{
viewModel.IsChecked = null;
}

View File

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

View File

@@ -4,11 +4,11 @@ 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;
using System.Windows.Media.Imaging;
using Castle.Core.Internal;
using Filtration.Common.Services;
using Filtration.Common.ViewModels;
using Filtration.Interface;
@@ -19,7 +19,6 @@ using Filtration.Translators;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging;
using NLog;
using Clipboard = System.Windows.Clipboard;
namespace Filtration.ViewModels
{
@@ -76,6 +75,8 @@ namespace Filtration.ViewModels
private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel;
private readonly IItemFilterPersistenceService _persistenceService;
private readonly IMessageBoxService _messageBoxService;
private readonly IClipboardService _clipboardService;
private readonly IBlockGroupHierarchyBuilder _blockGroupHierarchyBuilder;
private bool _isDirty;
private IItemFilterBlockViewModel _selectedBlockViewModel;
@@ -88,7 +89,9 @@ namespace Filtration.ViewModels
IItemFilterBlockTranslator blockTranslator,
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel,
IItemFilterPersistenceService persistenceService,
IMessageBoxService messageBoxService)
IMessageBoxService messageBoxService,
IClipboardService clipboardService,
IBlockGroupHierarchyBuilder blockGroupHierarchyBuilder)
{
_itemFilterBlockViewModelFactory = itemFilterBlockViewModelFactory;
_blockTranslator = blockTranslator;
@@ -96,11 +99,13 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.ActiveDocumentChanged += OnActiveDocumentChanged;
_persistenceService = persistenceService;
_messageBoxService = messageBoxService;
_clipboardService = clipboardService;
_blockGroupHierarchyBuilder = blockGroupHierarchyBuilder;
_itemFilterBlockViewModels = new ObservableCollection<IItemFilterBlockViewModel>();
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);
@@ -347,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)
@@ -373,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"));
}
return;
}
public void SaveAs()
public async Task SaveAsAsync()
{
if (!ValidateScript()) return;
if (!CheckForUnusedThemeComponents()) return;
@@ -390,12 +402,14 @@ namespace Filtration.ViewModels
var result = saveDialog.ShowDialog();
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();
@@ -411,6 +425,10 @@ namespace Filtration.ViewModels
MessageBoxImage.Error);
Script.FilePath = previousFilePath;
}
finally
{
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
}
}
private bool CheckForUnusedThemeComponents()
@@ -476,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)
{
@@ -495,20 +513,20 @@ namespace Filtration.ViewModels
switch (result)
{
case MessageBoxResult.Yes:
{
Save();
CloseScript();
break;
}
{
await SaveAsync();
CloseScript();
break;
}
case MessageBoxResult.No:
{
CloseScript();
break;
}
{
CloseScript();
break;
}
case MessageBoxResult.Cancel:
{
return;
}
{
return;
}
}
}
}
@@ -544,7 +562,16 @@ namespace Filtration.ViewModels
public void CopyBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
Clipboard.SetText(_blockTranslator.TranslateItemFilterBlockToString(SelectedBlockViewModel.Block));
try
{
_clipboardService.SetClipboardText(
_blockTranslator.TranslateItemFilterBlockToString(SelectedBlockViewModel.Block));
}
catch
{
_messageBoxService.Show("Clipboard Error", "Failed to access the clipboard, copy command not completed.",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void OnCopyBlockStyleCommand()
@@ -564,8 +591,15 @@ namespace Filtration.ViewModels
}
outputText += blockItem.OutputText;
}
Clipboard.SetText(outputText);
try
{
_clipboardService.SetClipboardText(outputText);
}
catch
{
_messageBoxService.Show("Clipboard Error", "Failed to access the clipboard, copy command not completed.",
MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void OnPasteBlockStyleCommand()
@@ -575,7 +609,7 @@ namespace Filtration.ViewModels
public void PasteBlockStyle(IItemFilterBlockViewModel targetBlockViewModel)
{
var clipboardText = Clipboard.GetText();
var clipboardText = _clipboardService.GetClipboardText();
if (string.IsNullOrEmpty(clipboardText))
{
return;
@@ -594,8 +628,9 @@ namespace Filtration.ViewModels
{
try
{
var clipboardText = Clipboard.GetText();
if (clipboardText.IsNullOrEmpty()) return;
var clipboardText = _clipboardService.GetClipboardText();
if (string.IsNullOrEmpty(clipboardText)) return;
_blockGroupHierarchyBuilder.Initialise(Script.ItemFilterBlockGroups.First());
var translatedBlock = _blockTranslator.TranslateStringToItemFilterBlock(clipboardText, Script.ThemeComponents);
if (translatedBlock == null) return;
@@ -621,9 +656,12 @@ namespace Filtration.ViewModels
catch (Exception e)
{
_logger.Error(e);
var innerException = e.InnerException != null
? e.InnerException.Message
: string.Empty;
_messageBoxService.Show("Paste Error",
e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine +
e.InnerException.Message + Environment.NewLine + e.InnerException.StackTrace, MessageBoxButton.OK,
e.Message + Environment.NewLine + innerException, MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
@@ -753,6 +791,7 @@ namespace Filtration.ViewModels
IsDirty = true;
SelectedBlockViewModel = vm;
RaisePropertyChanged("ItemFilterSectionViewModels");
Messenger.Default.Send(new NotificationMessage("SectionsChanged"));
}
private void OnExpandAllBlocksCommand()
@@ -784,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

@@ -1,10 +1,13 @@
using System;
using System.Collections.Generic;
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.Forms.VisualStyles;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Filtration.Common.Services;
@@ -25,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
@@ -34,7 +36,8 @@ namespace Filtration.ViewModels
{
RelayCommand OpenScriptCommand { get; }
RelayCommand NewScriptCommand { get; }
bool CloseAllDocuments();
Task<bool> CloseAllDocumentsAsync();
Task OpenDroppedFilesAsync(List<string> filenames);
}
internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel
@@ -51,6 +54,8 @@ 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,
IItemFilterScriptTranslator itemFilterScriptTranslator,
@@ -61,7 +66,8 @@ namespace Filtration.ViewModels
IThemeService themeService,
IUpdateCheckService updateCheckService,
IUpdateAvailableViewModel updateAvailableViewModel,
IMessageBoxService messageBoxService)
IMessageBoxService messageBoxService,
IClipboardService clipboardService)
{
_itemFilterScriptRepository = itemFilterScriptRepository;
_itemFilterScriptTranslator = itemFilterScriptTranslator;
@@ -73,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(OnOpenScriptCommand);
OpenThemeCommand = new RelayCommand(OnOpenThemeCommand);
OpenScriptCommand = new RelayCommand(async () => await OnOpenScriptCommand());
OpenThemeCommand = new RelayCommand(async () => await OnOpenThemeCommandAsync());
SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable);
SaveAsCommand = new RelayCommand(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);
@@ -104,7 +111,7 @@ namespace Filtration.ViewModels
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocumentIsScript);
CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => ActiveDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(OnApplyThemeToScriptCommand, () => ActiveDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(async () => await OnApplyThemeToScriptCommandAsync(), () => ActiveDocumentIsScript);
EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => ActiveDocumentIsScript);
AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable);
@@ -166,12 +173,28 @@ 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;
}
}
});
CheckForUpdates();
Task.Run(async () =>
{
await CheckForUpdatesAsync();
}).Wait();
}
public RelayCommand OpenScriptCommand { get; private set; }
@@ -215,13 +238,13 @@ namespace Filtration.ViewModels
public RelayCommand ClearFiltersCommand { get; private set; }
public async void CheckForUpdates()
public async Task CheckForUpdatesAsync()
{
var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
try
{
var result = await _updateCheckService.GetUpdateData();
var result = await _updateCheckService.GetUpdateDataAsync();
if (result.LatestVersionMajorPart >= assemblyVersion.FileMajorPart &&
result.LatestVersionMinorPart > assemblyVersion.FileMinorPart)
@@ -279,6 +302,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; }
@@ -322,6 +355,29 @@ namespace Filtration.ViewModels
}
}
public async Task OpenDroppedFilesAsync(List<string> 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);
@@ -362,24 +418,31 @@ namespace Filtration.ViewModels
var aboutWindow = new AboutWindow();
aboutWindow.ShowDialog();
}
private void OnOpenScriptCommand()
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 = _itemFilterScriptRepository.LoadScriptFromFile(openFileDialog.FileName);
loadedViewModel = await _itemFilterScriptRepository.LoadScriptFromFileAsync(scriptFilename);
}
catch(IOException e)
catch (IOException e)
{
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
if (_logger.IsErrorEnabled)
{
_logger.Error(e);
@@ -390,23 +453,28 @@ namespace Filtration.ViewModels
return;
}
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
_avalonDockWorkspaceViewModel.AddDocument(loadedViewModel);
}
private void 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 = _themeProvider.LoadThemeFromFile(filePath);
loadedViewModel = await _themeProvider.LoadThemeFromFile(themeFilename);
}
catch (IOException e)
{
@@ -419,11 +487,11 @@ namespace Filtration.ViewModels
MessageBoxImage.Error);
return;
}
_avalonDockWorkspaceViewModel.AddDocument(loadedViewModel);
}
private void OnApplyThemeToScriptCommand()
private async Task OnApplyThemeToScriptCommandAsync()
{
var filePath = ShowOpenThemeDialog();
if (string.IsNullOrEmpty(filePath))
@@ -435,7 +503,7 @@ namespace Filtration.ViewModels
try
{
loadedTheme = _themeProvider.LoadThemeModelFromFile(filePath);
loadedTheme = await _themeProvider.LoadThemeModelFromFile(filePath);
}
catch (IOException e)
{
@@ -461,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()
{
@@ -473,8 +551,6 @@ namespace Filtration.ViewModels
return openFileDialog.ShowDialog() != true ? string.Empty : openFileDialog.FileName;
}
private void SetItemFilterScriptDirectory()
{
var dlg = new FolderBrowserDialog
@@ -490,14 +566,14 @@ namespace Filtration.ViewModels
}
}
private void OnSaveDocumentCommand()
private async Task OnSaveDocumentCommandAsync()
{
((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).Save();
await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsync();
}
private void OnSaveAsCommand()
private async Task OnSaveAsCommandAsync()
{
((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAs();
await ((IEditableDocument)_avalonDockWorkspaceViewModel.ActiveDocument).SaveAsAsync();
}
private void OnReplaceColorsCommand()
@@ -509,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()
@@ -629,14 +716,14 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent);
}
public bool CloseAllDocuments()
public async Task<bool> CloseAllDocumentsAsync()
{
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,16 +8,18 @@
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"
Closing="MainWindow_OnClosing">
Closing="MainWindow_OnClosing" Drop="MainWindow_OnDrop" AllowDrop="True">
<fluent:RibbonWindow.InputBindings>
<KeyBinding Command="{Binding SaveCommand}" Modifiers="Control" Key="S" />
<KeyBinding Command="{Binding OpenScriptCommand}" Modifiers="Control" Key="O" />
<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>
@@ -30,10 +32,10 @@
</DataTemplate>
</fluent:BackstageTabItem.ContentTemplate>
</fluent:BackstageTabItem>
<fluent:Button Header="New Script" Command="{Binding NewScriptCommand}" Icon="{StaticResource NewIcon}" />
<fluent:Button Header="Open Script" Command="{Binding OpenScriptCommand}" Icon="{StaticResource OpenIcon}" />
<fluent:Button Header="New Script" Command="{Binding NewScriptCommand}" Icon="{StaticResource NewIcon}" ToolTip="New Script (Ctrl+N)" />
<fluent:Button Header="Open Script" Command="{Binding OpenScriptCommand}" Icon="{StaticResource OpenIcon}" ToolTip="Open Script (Ctrl+O)" />
<fluent:Button Header="Open Theme" Command="{Binding OpenThemeCommand}" Icon="{StaticResource OpenIcon}" />
<fluent:Button Header="Save" Command="{Binding SaveCommand}" Icon="{StaticResource SaveIcon}" />
<fluent:Button Header="Save" Command="{Binding SaveCommand}" Icon="{StaticResource SaveIcon}" ToolTip="Save (Ctrl+S)" />
<fluent:Button Header="Save As" Command="{Binding SaveAsCommand}" Icon="{StaticResource SaveIcon}" />
<fluent:Button Header="Close" Command="{Binding CloseCommand}" />
<fluent:SeparatorTabItem />
@@ -72,10 +74,10 @@
</fluent:RibbonTabItem>
<fluent:RibbonTabItem x:Name="ScriptToolsTabItem" Header="Script Tools" Group="{Binding ElementName=ScriptToolsGroup}" Visibility="{Binding ActiveDocumentIsScript, Converter={StaticResource BooleanVisibilityConverter}, Mode=OneWay}" >
<fluent:RibbonGroupBox Header="Clipboard">
<fluent:Button Header="Copy Block" Command="{Binding CopyBlockCommand}" Icon="{StaticResource CopyIcon}" LargeIcon="{StaticResource CopyIcon}"/>
<fluent:Button Header="Paste Block" Command="{Binding PasteCommand}" Icon="{StaticResource PasteIcon}" LargeIcon="{StaticResource PasteIcon}" />
<fluent:Button Header="Copy Style" Command="{Binding CopyBlockStyleCommand}" Icon="{StaticResource CopyIcon}" LargeIcon="{StaticResource CopyIcon}" SizeDefinition="Middle" />
<fluent:Button Header="Paste Style" Command="{Binding PasteBlockStyleCommand}" Icon="{StaticResource PasteStyleIcon}" LargeIcon="{StaticResource PasteIcon}" SizeDefinition="Middle" />
<fluent:Button Header="Copy Block" Command="{Binding CopyBlockCommand}" Icon="{StaticResource CopyIcon}" LargeIcon="{StaticResource CopyIcon}" ToolTip="Copy Block (Ctrl+C)"/>
<fluent:Button Header="Paste Block" Command="{Binding PasteCommand}" Icon="{StaticResource PasteIcon}" LargeIcon="{StaticResource PasteIcon}" ToolTip="Paste Block (Ctrl+V)"/>
<fluent:Button Header="Copy Style" Command="{Binding CopyBlockStyleCommand}" Icon="{StaticResource CopyIcon}" LargeIcon="{StaticResource CopyIcon}" SizeDefinition="Middle" ToolTip="Copy Style (Ctrl+Shift+C)" />
<fluent:Button Header="Paste Style" Command="{Binding PasteBlockStyleCommand}" Icon="{StaticResource PasteStyleIcon}" LargeIcon="{StaticResource PasteIcon}" SizeDefinition="Middle" ToolTip="Paste Style (Ctrl+Shift+V)" />
<fluent:Button Header="Copy Script" Command="{Binding CopyScriptCommand}" Icon="{StaticResource CopyIcon}" LargeIcon="{StaticResource PasteIcon}" SizeDefinition="Middle" />
</fluent:RibbonGroupBox>
<fluent:RibbonGroupBox Header="Blocks">
@@ -117,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,8 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using Filtration.Annotations;
using Filtration.ViewModels;
namespace Filtration.Views
@@ -13,7 +14,7 @@ namespace Filtration.Views
internal partial class MainWindow : IMainWindow
{
private IMainWindowViewModel _mainWindowViewModel;
private readonly IMainWindowViewModel _mainWindowViewModel;
public MainWindow(IMainWindowViewModel mainWindowViewModel)
{
@@ -40,11 +41,34 @@ namespace Filtration.Views
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
var allDocumentsClosed = _mainWindowViewModel.CloseAllDocuments();
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<string>();
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);
}
}
}

View File

@@ -1,14 +0,0 @@
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace Filtration.WindsorInstallers
{
public class ModelsInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
}
}
}

View File

@@ -34,6 +34,11 @@ namespace Filtration.WindsorInstallers
Component.For<IUpdateCheckService>()
.ImplementedBy<UpdateCheckService>()
.LifeStyle.Singleton);
container.Register(
Component.For<IClipboardService>()
.ImplementedBy<ClipboardService>()
.LifeStyle.Singleton);
}
}
}

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>

View File

@@ -2,10 +2,10 @@
Filtration is an editor for Path of Exile item filter scripts.
## Current Release (Released 2015-07-10)
<b>Installer (6.31mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.8/filtration_0.8_setup.exe">filtration_0.8_setup.exe</a>
## Current Release (Released 2015-07-15)
<b>Installer (6.3mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.9/filtration_0.9_setup.exe">filtration_0.9_setup.exe</a>
<b>Zip File (7.9mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.8/filtration_0.8.zip">filtration_0.8.zip</a>
<b>Zip File (7.89mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.9/filtration_0.9.zip">filtration_0.9.zip</a>
## System Requirements
Filtration requires .NET Framework 4.5.1 installed.