39 Commits
0.7 ... 0.11

Author SHA1 Message Date
Ben
94146467a3 Removed async from a test that didn't need it 2015-07-31 21:43:33 +01:00
Ben
da9fad05a6 Changed maximum PlayAlertSound volume from 100 to 300 as per latest patch.
Updated version to 0.11
2015-07-31 19:52:19 +01:00
Ben
eb73767560 Merge branch 'master' of https://github.com/ben-wallis/Filtration.git 2015-07-31 19:45:57 +01:00
Ben
2954cfe259 Fixed async tests 2015-07-31 19:45:51 +01:00
Ben Wallis
3694e6fa0c Updated release to 0.10 2015-07-26 17:19:53 +01:00
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
Ben
e80295cb69 Removed Thrusting One Hand Swords from Base Types 2015-07-15 19:48:51 +01:00
Ben
f3ed386845 Removed Stackable Currency from ItemClasses 2015-07-15 19:48:33 +01:00
Ben
89e0c717e8 Bumped version to 0.9 2015-07-15 19:45:49 +01:00
Ben
8924637b98 Added hint text when no audio visual block items are added. 2015-07-15 19:41:31 +01:00
Ben
b0b912c676 Added save check on close 2015-07-15 19:36:42 +01:00
Ben
92ebc51e7b Switched file save encoding to UTF-8 2015-07-15 19:17:19 +01:00
Ben
95e7581a5b Fixed Delete Theme Component button being enabled for non-master themes 2015-07-15 19:12:19 +01:00
Ben
9cb854b584 Fixed Usages: 0 being visible when editing a non-master theme 2015-07-15 19:10:51 +01:00
Ben
61c2902f0c Merge branch 'master' of https://github.com/ben-wallis/Filtration.git 2015-07-15 19:02:34 +01:00
Ben
dc157713f3 Fixed Issue #8 - Crash when Filtration cannot perform the update check on startup 2015-07-15 19:02:29 +01:00
Ben Wallis
16fe837544 updated to 0.8 2015-07-13 15:17:53 +01:00
Ben
58de6f06b9 Added Jewel to ItemClasses.txt 2015-07-10 18:13:12 +01:00
Ben
af2dace29a Fixed crash when opening a script after Filtration is invoked via file association (Issue #7) 2015-07-10 18:11:03 +01:00
Ben
59cf604430 Revert "Increased the size of the Item Preview control to cater for FontSize 45"
This reverts commit 93a51e7829.
2015-07-10 17:54:42 +01:00
Ben
93a51e7829 Increased the size of the Item Preview control to cater for FontSize 45 2015-07-10 17:52:10 +01:00
Ben
9d928a374a Fixed crash when clicking Close menu option with no script/theme open
Fixed memory leak when documents are closed.
2015-07-10 17:48:34 +01:00
Ben
b5788504cb Fixed Disabled Block Block Group Bug (Issue #6) 2015-07-10 17:29:37 +01:00
Ben
6e71005e93 Merge branch 'master' of https://github.com/ben-wallis/Filtration.git 2015-07-09 18:58:27 +01:00
Ben
56e163e3e0 Fix for line description being lost when reading disabled blocks 2015-07-09 18:58:22 +01:00
Ben Wallis
c856bbcee7 updated screenshots 2015-07-06 19:14:28 +01:00
Ben Wallis
490496f2f7 Updated release to 0.7 2015-07-06 18:41:14 +01:00
Ben
9fcb609a51 Implemented disabled block support 2015-07-06 18:19:05 +01:00
43 changed files with 1011 additions and 278 deletions

View File

@@ -1,5 +1,6 @@
using System;
using System.IO;
using System.Text;
namespace Filtration.Common.Services
{
@@ -20,7 +21,7 @@ namespace Filtration.Common.Services
public void WriteFileFromString(string filePath, string inputString)
{
File.WriteAllText(filePath, inputString);
File.WriteAllText(filePath, inputString, Encoding.UTF8);
}
public bool DirectoryExists(string directoryPath)

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

@@ -13,8 +13,10 @@ namespace Filtration.ObjectModel
public ItemFilterBlock()
{
BlockItems = new ObservableCollection<IItemFilterBlockItem> {new ActionBlockItem(BlockAction.Show)};
Enabled = true;
}
public bool Enabled { get; set; }
public string Description { get; set; }
public ItemFilterBlockGroup BlockGroup

View File

@@ -1,4 +1,6 @@
using System.IO;
using System.Threading.Tasks;
using Filtration.ObjectModel;
using Filtration.Repositories;
using Filtration.Services;
using Filtration.ViewModels;
@@ -11,14 +13,14 @@ namespace Filtration.Tests.Repositories
public class TestItemFilterScriptRepository
{
[Test]
public void LoadScriptFromFile_CallsPersistenceServiceUsingPathAndReturnsViewModel()
public async Task LoadScriptFromFile_CallsPersistenceServiceUsingPathAndReturnsViewModel()
{
// Arrange
var testInputPath = "C:\\TestPath.filter";
var mockPersistenceService = new Mock<IItemFilterPersistenceService>();
mockPersistenceService.Setup(p => p.LoadItemFilterScript(testInputPath)).Verifiable();
mockPersistenceService.Setup(p => p.LoadItemFilterScriptAsync(testInputPath)).ReturnsAsync(new ItemFilterScript()).Verifiable();
var mockItemFilterScriptViewModel = new Mock<IItemFilterScriptViewModel>();
@@ -28,7 +30,7 @@ namespace Filtration.Tests.Repositories
var repository = new ItemFilterScriptRepository(mockPersistenceService.Object, mockItemFilterScriptViewModelFactory.Object);
// Act
var result = repository.LoadScriptFromFile(testInputPath);
var result = await repository.LoadScriptFromFileAsync(testInputPath);
// Assert
mockPersistenceService.Verify();
@@ -42,7 +44,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 +53,7 @@ namespace Filtration.Tests.Repositories
// Act
// Assert
Assert.Throws<IOException>(() => repository.LoadScriptFromFile(testInputPath));
Assert.Throws<IOException>(async () => await repository.LoadScriptFromFileAsync(testInputPath));
}
[Test]

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Threading.Tasks;
using Filtration.Common.Services;
using Filtration.ObjectModel;
using Filtration.Services;
@@ -12,7 +13,7 @@ namespace Filtration.Tests.Services
public class TestItemFilterPersistenceService
{
[Test]
public void LoadItemFilterScript_CallsTranslatorAndFileSystemService()
public async Task LoadItemFilterScript_CallsTranslatorAndFileSystemService()
{
// Arrange
const string TestInputPath = "C:\\Test Path\\Script.Filter";
@@ -28,7 +29,7 @@ namespace Filtration.Tests.Services
var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object);
// Act
var script = service.LoadItemFilterScript(TestInputPath);
var script = await service.LoadItemFilterScriptAsync(TestInputPath);
// Assert
mockFileSystemService.Verify();
@@ -37,7 +38,7 @@ namespace Filtration.Tests.Services
}
[Test]
public void SaveItemFilterScript_CallsTranslatorAndFileSystemService()
public async Task SaveItemFilterScript_CallsTranslatorAndFileSystemService()
{
// Arrange
var testFilePath = "C:\\Test\\File.txt";
@@ -53,7 +54,7 @@ namespace Filtration.Tests.Services
var service = new ItemFilterPersistenceService(mockFileSystemService.Object, mockItemFilterScriptTranslator.Object);
// Act
service.SaveItemFilterScript(testScript);
await service.SaveItemFilterScriptAsync(testScript);
// Assert
mockFileSystemService.Verify();

View File

@@ -25,6 +25,36 @@ namespace Filtration.Tests.Translators
_testUtility = new ItemFilterBlockTranslatorTestUtility();
}
[Test]
public void TranslateStringToItemFilterBlock_NotDisabled_SetsBlockEnabledTrue()
{
// Arrange
var inputString = "Show" + Environment.NewLine +
" ItemLevel >= 55";
// Act
var result = _testUtility.Translator.TranslateStringToItemFilterBlock(inputString, null);
// Assert
Assert.AreEqual(true, result.Enabled);
}
[Test]
public void TranslateStringToItemFilterBlock_DisabledBlock_SetsBlockEnabledFalse()
{
// Arrange
var inputString = "HideDisabled" + Environment.NewLine +
" ItemLevel >= 55";
// Act
var result = _testUtility.Translator.TranslateStringToItemFilterBlock(inputString, null);
// Assert
Assert.AreEqual(2, result.BlockItems.Count);
Assert.AreEqual(BlockAction.Hide, result.Action);
Assert.AreEqual(false, result.Enabled);
}
[Test]
public void TranslateStringToItemFilterBlock_NoDescriptionComment_ReturnsCorrectObject()
{
@@ -1264,6 +1294,26 @@ namespace Filtration.Tests.Translators
Assert.AreEqual(expectedResult, result);
}
[Test]
public void TranslateItemFilterBlockToString_DisabledBlock_ReturnsCorrectString()
{
// Arrange
var expectedResult = "#Disabled Block Start" + Environment.NewLine +
"#Show" + Environment.NewLine +
"# Width = 4" + Environment.NewLine +
"#Disabled Block End";
_testUtility.TestBlock.Enabled = false;
_testUtility.TestBlock.BlockItems.Add(new WidthBlockItem(FilterPredicateOperator.Equal, 4));
// Act
var result = _testUtility.Translator.TranslateItemFilterBlockToString(_testUtility.TestBlock);
// Assert
Assert.AreEqual(expectedResult, result);
}
[Test]
public void TranslateItemFilterBlockToString_Everything_ReturnsCorrectString()
{

View File

@@ -253,6 +253,139 @@ namespace Filtration.Tests.Translators
Assert.IsNullOrEmpty(firstBlock.Description);
}
[Test]
public void TranslateStringToItemFilterScript_DisabledBlock_ReturnsCorrectBlockCount()
{
// Arrange
var testInputScript = "Show" + Environment.NewLine +
" ItemLevel > 2" + Environment.NewLine +
" SetTextColor 255 40 0" + Environment.NewLine +
Environment.NewLine +
"#Disabled Block Start" + Environment.NewLine +
"#Show" + Environment.NewLine +
"# ItemLevel > 2" + Environment.NewLine +
"# SetTextColor 255 215 0" + Environment.NewLine +
"# SetBorderColor 255 105 180" + Environment.NewLine +
"# SetFontSize 32" + Environment.NewLine +
"#Disabled Block End" + Environment.NewLine +
Environment.NewLine +
"Show" + Environment.NewLine +
" ItemLevel > 20" + Environment.NewLine +
" SetTextColor 255 255 0";
var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object);
var translator = new ItemFilterScriptTranslator(blockTranslator,
_testUtility.MockBlockGroupHierarchyBuilder.Object);
// Act
var result = translator.TranslateStringToItemFilterScript(testInputScript);
// Assert
Assert.AreEqual(3, result.ItemFilterBlocks.Count);
}
[Test]
public void TranslateStringToItemFilterScript_DisabledBlock_ReturnsCorrectBlocks()
{
// Arrange
var testInputScript = "Show" + Environment.NewLine +
" ItemLevel > 2" + Environment.NewLine +
" SetTextColor 255 40 0" + Environment.NewLine +
Environment.NewLine +
"#Disabled Block Start" + Environment.NewLine +
"#Show" + Environment.NewLine +
"# ItemLevel > 2" + Environment.NewLine +
"# SetTextColor 255 215 0" + Environment.NewLine +
"# SetBorderColor 255 105 180" + Environment.NewLine +
"# SetFontSize 32" + Environment.NewLine +
"#Disabled Block End" + Environment.NewLine +
Environment.NewLine +
"Show" + Environment.NewLine +
" ItemLevel > 20" + Environment.NewLine +
" SetTextColor 255 255 0";
var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object);
var translator = new ItemFilterScriptTranslator(blockTranslator,
_testUtility.MockBlockGroupHierarchyBuilder.Object);
// Act
var result = translator.TranslateStringToItemFilterScript(testInputScript);
// Assert
Assert.AreEqual(3, result.ItemFilterBlocks.Count);
var firstBlock = result.ItemFilterBlocks.First();
var secondBlock = result.ItemFilterBlocks.Skip(1).First();
var thirdBlock = result.ItemFilterBlocks.Skip(2).First();
Assert.AreEqual(3, firstBlock.BlockItems.Count);
Assert.AreEqual(5, secondBlock.BlockItems.Count);
Assert.AreEqual(3, thirdBlock.BlockItems.Count);
}
[Test]
public void TranslateStringToItemFilterScript_DisabledBlock_BlockDescriptionNotLost()
{
// Arrange
var testInputScript = "Show" + Environment.NewLine +
" ItemLevel > 2" + Environment.NewLine +
" SetTextColor 255 40 0" + Environment.NewLine +
Environment.NewLine +
"#Disabled Block Start" + Environment.NewLine +
"# This is a disabled block" + Environment.NewLine +
"#Show" + Environment.NewLine +
"# ItemLevel > 2" + Environment.NewLine +
"#Disabled Block End";
var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object);
var translator = new ItemFilterScriptTranslator(blockTranslator,
_testUtility.MockBlockGroupHierarchyBuilder.Object);
// Act
var result = translator.TranslateStringToItemFilterScript(testInputScript);
// Assert
Assert.AreEqual(2, result.ItemFilterBlocks.Count);
var secondBlock = result.ItemFilterBlocks.Skip(1).First();
Assert.AreEqual("This is a disabled block", secondBlock.Description);
}
[Test]
public void TranslateStringToItemFilterScript_DisabledBlockWithBlockGroup_ReturnsCorrectBlock()
{
// Arrange
var testInputScript = "Show" + Environment.NewLine +
" ItemLevel > 2" + Environment.NewLine +
" SetTextColor 255 40 0" + Environment.NewLine +
Environment.NewLine +
"#Disabled Block Start" + Environment.NewLine +
"# This is a disabled block" + Environment.NewLine +
"#Show#My Block Group" + Environment.NewLine +
"# ItemLevel > 2" + Environment.NewLine +
"#Disabled Block End";
var blockTranslator = new ItemFilterBlockTranslator(_testUtility.MockBlockGroupHierarchyBuilder.Object);
_testUtility.MockBlockGroupHierarchyBuilder.Setup(
b => b.IntegrateStringListIntoBlockGroupHierarchy(It.IsAny<IEnumerable<string>>()))
.Returns(new ItemFilterBlockGroup("My Block Group", null));
var translator = new ItemFilterScriptTranslator(blockTranslator,
_testUtility.MockBlockGroupHierarchyBuilder.Object);
// Act
var result = translator.TranslateStringToItemFilterScript(testInputScript);
// Assert
Assert.AreEqual(2, result.ItemFilterBlocks.Count);
var secondBlock = result.ItemFilterBlocks.Skip(1).First();
Assert.AreEqual("This is a disabled block", secondBlock.Description);
Assert.AreEqual("My Block Group", secondBlock.BlockGroup.GroupName);
}
private class ItemFilterScriptTranslatorTestUtility
{
public ItemFilterScriptTranslatorTestUtility()

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

@@ -21,30 +21,29 @@
</Grid.RowDefinitions>
<Grid.Resources>
<DataTemplate x:Key="EditableComponentNameTemplate">
<TextBox Text="{Binding ComponentName}" />
<StackPanel>
<TextBlock Text="{Binding UsageCount, StringFormat='Usages: {0}'}"
FontSize="10"
HorizontalAlignment="Right"
Visibility="{Binding Path=DataContext.EditEnabled, RelativeSource={RelativeSource AncestorType={x:Type views:ThemeEditorView}}, Converter={StaticResource BooleanVisibilityConverter}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding UsageCount}" Value="0">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Foreground" Value="SteelBlue" />
</Style>
</TextBlock.Style>
</TextBlock>
<TextBox Text="{Binding ComponentName}" />
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="ViewOnlyComponentNameTemplate">
<TextBlock Text="{Binding ComponentName}" ToolTip="{Binding ComponentName}" />
</DataTemplate>
</Grid.Resources>
<DockPanel LastChildFill="True">
<TextBlock DockPanel.Dock="Left"
Text="{Binding UsageCount, StringFormat='Usages: {0}'}"
FontSize="10"
HorizontalAlignment="Right"
Visibility="{Binding Path=DataContext.EditEnabled, RelativeSource={RelativeSource AncestorType={x:Type views:ThemeEditorView}}, Converter={StaticResource BooleanVisibilityConverter}}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding UsageCount}" Value="0">
<Setter Property="Foreground" Value="Red" />
</DataTrigger>
</Style.Triggers>
<Setter Property="Foreground" Value="SteelBlue" />
</Style>
</TextBlock.Style>
</TextBlock>
</DockPanel>
<ContentControl Grid.Row="1" Content="{Binding}">
<ContentControl.Style>
<Style TargetType="ContentControl">
@@ -59,7 +58,6 @@
</Style>
</ContentControl.Style>
</ContentControl>
<xctk:ColorPicker Grid.Row="2" SelectedColor="{Binding Color}" />
</Grid>
</UserControl>

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>
@@ -429,6 +434,8 @@
<Resource Include="Resources\Icons\filtration_icon.png" />
<Resource Include="Resources\Icons\Add.ico" />
<Resource Include="Resources\Icons\ThemeComponentDelete.ico" />
<Resource Include="Resources\Icons\standby_disabled_icon.png" />
<Resource Include="Resources\Icons\standby_enabled_icon.png" />
<Content Include="Resources\ItemBaseTypes.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>

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.6.*")]
[assembly: AssemblyVersion("0.11.*")]
[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);

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

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

@@ -34,4 +34,5 @@ Fishing Rods
Map Fragments
Hideout Doodads
Microtransactions
Divination Card
Divination Card
Jewel

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

@@ -1,6 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using Filtration.Common.Services;
using Filtration.Utilities;
@@ -28,10 +30,10 @@ namespace Filtration.Services
private void PopulateStaticData()
{
var itemBaseTypes = _fileSystemService.ReadFileAsString("Resources\\ItemBaseTypes.txt");
var itemBaseTypes = _fileSystemService.ReadFileAsString(AppDomain.CurrentDomain.BaseDirectory + "\\Resources\\ItemBaseTypes.txt");
ItemBaseTypes = new LineReader(() => new StringReader(itemBaseTypes)).ToList();
var itemClasses = _fileSystemService.ReadFileAsString("Resources\\ItemClasses.txt");
var itemClasses = _fileSystemService.ReadFileAsString(AppDomain.CurrentDomain.BaseDirectory + "\\Resources\\ItemClasses.txt");
ItemClasses = new LineReader(() => new StringReader(itemClasses)).ToList();
}
}

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

@@ -28,6 +28,7 @@ namespace Filtration.Translators
private readonly IBlockGroupHierarchyBuilder _blockGroupHierarchyBuilder;
private const string Indent = " ";
private readonly string _newLine = Environment.NewLine + Indent;
private readonly string _disabledNewLine = Environment.NewLine + "#" + Indent;
private ThemeComponentCollection _masterComponentCollection;
public ItemFilterBlockTranslator(IBlockGroupHierarchyBuilder blockGroupHierarchyBuilder)
@@ -42,6 +43,7 @@ namespace Filtration.Translators
_masterComponentCollection = masterComponentCollection;
var block = new ItemFilterBlock();
var showHideFound = false;
foreach (var line in new LineReader(() => new StringReader(inputString)))
{
@@ -62,6 +64,7 @@ namespace Filtration.Translators
var adjustedLine = line.Replace("#", " # ");
var trimmedLine = adjustedLine.TrimStart(' ');
var spaceOrEndOfLinePos = trimmedLine.IndexOf(" ", StringComparison.Ordinal) > 0 ? trimmedLine.IndexOf(" ", StringComparison.Ordinal) : trimmedLine.Length;
var lineOption = trimmedLine.Substring(0, spaceOrEndOfLinePos);
@@ -70,11 +73,25 @@ namespace Filtration.Translators
case "Show":
showHideFound = true;
block.Action = BlockAction.Show;
block.Enabled = true;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "Hide":
showHideFound = true;
block.Action = BlockAction.Hide;
block.Enabled = true;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "ShowDisabled":
showHideFound = true;
block.Action = BlockAction.Show;
block.Enabled = false;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "HideDisabled":
showHideFound = true;
block.Action = BlockAction.Hide;
block.Enabled = false;
AddBlockGroupToBlock(block, trimmedLine);
break;
case "ItemLevel":
@@ -399,12 +416,17 @@ namespace Filtration.Translators
var outputString = string.Empty;
if (!block.Enabled)
{
outputString += "#Disabled Block Start" + Environment.NewLine;
}
if (!string.IsNullOrEmpty(block.Description))
{
outputString += "# " + block.Description + Environment.NewLine;
}
outputString += block.Action.GetAttributeDescription();
outputString += (!block.Enabled ? "#" : string.Empty) + block.Action.GetAttributeDescription();
if (block.BlockGroup != null)
{
@@ -416,9 +438,14 @@ namespace Filtration.Translators
{
if (blockItem.OutputText != string.Empty)
{
outputString += _newLine + blockItem.OutputText;
outputString += (!block.Enabled ? _disabledNewLine : _newLine) + blockItem.OutputText;
}
}
if (!block.Enabled)
{
outputString += Environment.NewLine + "#Disabled Block End";
}
return outputString;
}

View File

@@ -28,12 +28,77 @@ namespace Filtration.Translators
_blockGroupHierarchyBuilder = blockGroupHierarchyBuilder;
}
public string PreprocessDisabledBlocks(string inputString)
{
bool inDisabledBlock = false;
var showHideFound = false;
var lines = Regex.Split(inputString, "\r\n|\r|\n").ToList();
var linesToRemove = new List<int>();
for (var i = 0; i < lines.Count; i++)
{
if (lines[i].StartsWith("#Disabled Block Start"))
{
inDisabledBlock = true;
linesToRemove.Add(i);
continue;
}
if (inDisabledBlock)
{
if (lines[i].StartsWith("#Disabled Block End"))
{
inDisabledBlock = false;
showHideFound = false;
linesToRemove.Add(i);
continue;
}
lines[i] = lines[i].TrimStart('#');
lines[i] = lines[i].Replace("#", " # ");
var spaceOrEndOfLinePos = lines[i].IndexOf(" ", StringComparison.Ordinal) > 0 ? lines[i].IndexOf(" ", StringComparison.Ordinal) : lines[i].Length;
var lineOption = lines[i].Substring(0, spaceOrEndOfLinePos);
// If we haven't found a Show or Hide line yet, then this is probably the block comment.
// Put its # back on and skip to the next line.
if (lineOption != "Show" && lineOption != "Hide" && showHideFound == false)
{
lines[i] = "#" + lines[i];
continue;
}
if (lineOption == "Show")
{
lines[i] = lines[i].Replace("Show", "ShowDisabled");
showHideFound = true;
}
else if (lineOption == "Hide")
{
lines[i] = lines[i].Replace("Hide", "HideDisabled");
showHideFound = true;
}
}
}
for (var i = linesToRemove.Count - 1; i >= 0; i--)
{
lines.RemoveAt(linesToRemove[i]);
}
return lines.Aggregate((c, n) => c + Environment.NewLine + n);
}
public ItemFilterScript TranslateStringToItemFilterScript(string inputString)
{
var script = new ItemFilterScript();
_blockGroupHierarchyBuilder.Initialise(script.ItemFilterBlockGroups.First());
inputString = inputString.Replace("\t", "");
if (inputString.Contains("#Disabled Block Start"))
{
inputString = PreprocessDisabledBlocks(inputString);
}
var conditionBoundaries = IdentifyBlockBoundaries(inputString);
var lines = Regex.Split(inputString, "\r\n|\r|\n");
@@ -85,7 +150,10 @@ namespace Filtration.Translators
// as it represents the block description.
// currentLine > 2 caters for an edge case where the script description is a single line and the first
// block has no description. This prevents the script description from being assigned to the first block's description.
blockBoundaries.AddLast(previousLine.StartsWith("#") && !previousLine.StartsWith("# Section:") && currentLine > 2 ? currentLine - 2 : currentLine - 1);
blockBoundaries.AddLast(previousLine.StartsWith("#") && !previousLine.StartsWith("# Section:") &&
currentLine > 2
? currentLine - 2
: currentLine - 1);
}
previousLine = line;
}

View File

@@ -100,7 +100,7 @@
<Image Source="/Filtration;component/Resources/Icons/speaker_icon.png" VerticalAlignment="Center" HorizontalAlignment="Center" />
</Button>
<ComboBox ItemsSource="{Binding ElementName=BlockItemContentControl, Path=DataContext.SoundsAvailable}" SelectedValue="{Binding Value}" Style="{StaticResource MetroComboBox}" />
<xctk:ShortUpDown Value="{Binding Path=SecondValue}" Minimum="1" Maximum="100" HorizontalAlignment="Right" ToolTip="Volume"/>
<xctk:ShortUpDown Value="{Binding Path=SecondValue}" Minimum="1" Maximum="300" HorizontalAlignment="Right" ToolTip="Volume"/>
</WrapPanel>
</DataTemplate>
</ContentControl.Resources>

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
{
@@ -171,6 +170,19 @@ namespace Filtration.ViewModels
{
_activeDocument = null;
}
// TODO: Replace _activeScriptViewModel and _activeThemeViewModel with a better solution.
if (document.IsScript && _activeScriptViewModel == (IItemFilterScriptViewModel) document)
{
_activeScriptViewModel = null;
}
if (document.IsTheme && _activeThemeViewModel == (IThemeEditorViewModel)document)
{
_activeThemeViewModel = null;
}
}
public void SwitchActiveDocument(IDocument document)

View File

@@ -21,6 +21,7 @@ namespace Filtration.ViewModels
bool IsDirty { get; set; }
bool IsExpanded { get; set; }
ItemFilterBlock Block { get; }
bool BlockEnabled { get; set; }
void RefreshBlockPreview();
}
@@ -209,6 +210,20 @@ namespace Filtration.ViewModels
}
}
public bool BlockEnabled
{
get { return Block.Enabled; }
set
{
if (Block.Enabled != value)
{
Block.Enabled = value;
IsDirty = true;
RaisePropertyChanged();
}
}
}
public string BlockDescription
{
get
@@ -302,6 +317,12 @@ namespace Filtration.ViewModels
get { return Block.HasBlockItemOfType<SoundBlockItem>(); }
}
public bool HasAudioVisualBlockItems
{
get { return AudioVisualBlockItems.Any(); }
}
private void OnSwitchBlockItemsViewCommand()
{
AudioVisualBlockItemsGridVisible = !AudioVisualBlockItemsGridVisible;
@@ -444,6 +465,7 @@ namespace Filtration.ViewModels
RaisePropertyChanged("RegularBlockItems");
RaisePropertyChanged("SummaryBlockItems");
RaisePropertyChanged("AudioVisualBlockItems");
RaisePropertyChanged("HasAudioVisualBlockItems");
}
}
}

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
{
@@ -38,9 +37,13 @@ namespace Filtration.ViewModels
void Initialise(ItemFilterScript itemFilterScript, bool newScript);
void RemoveDirtyFlag();
void SetDirtyFlag();
bool HasSelectedEnabledBlock();
bool HasSelectedDisabledBlock();
RelayCommand AddBlockCommand { get; }
RelayCommand AddSectionCommand { get; }
RelayCommand DisableBlockCommand { get; }
RelayCommand EnableBlockCommand { get; }
RelayCommand DeleteBlockCommand { get; }
RelayCommand MoveBlockUpCommand { get; }
RelayCommand MoveBlockDownCommand { get; }
@@ -72,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;
@@ -84,7 +89,9 @@ namespace Filtration.ViewModels
IItemFilterBlockTranslator blockTranslator,
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel,
IItemFilterPersistenceService persistenceService,
IMessageBoxService messageBoxService)
IMessageBoxService messageBoxService,
IClipboardService clipboardService,
IBlockGroupHierarchyBuilder blockGroupHierarchyBuilder)
{
_itemFilterBlockViewModelFactory = itemFilterBlockViewModelFactory;
_blockTranslator = blockTranslator;
@@ -92,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);
@@ -104,6 +113,8 @@ namespace Filtration.ViewModels
MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => SelectedBlockViewModel != null);
AddBlockCommand = new RelayCommand(OnAddBlockCommand);
AddSectionCommand = new RelayCommand(OnAddSectionCommand, () => SelectedBlockViewModel != null);
DisableBlockCommand = new RelayCommand(OnDisableBlockCommand, HasSelectedEnabledBlock);
EnableBlockCommand = new RelayCommand(OnEnableBlockCommand, HasSelectedDisabledBlock);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => SelectedBlockViewModel != null);
CopyBlockStyleCommand = new RelayCommand(OnCopyBlockStyleCommand, () => SelectedBlockViewModel != null);
PasteBlockCommand = new RelayCommand(OnPasteBlockCommand, () => SelectedBlockViewModel != null);
@@ -128,6 +139,8 @@ namespace Filtration.ViewModels
public RelayCommand MoveBlockToBottomCommand { get; private set; }
public RelayCommand AddBlockCommand { get; private set; }
public RelayCommand AddSectionCommand { get; private set; }
public RelayCommand EnableBlockCommand { get; private set; }
public RelayCommand DisableBlockCommand { get; private set; }
public RelayCommand CopyBlockCommand { get; private set; }
public RelayCommand CopyBlockStyleCommand { get; private set; }
public RelayCommand PasteBlockCommand { get; private set; }
@@ -215,6 +228,21 @@ namespace Filtration.ViewModels
}
}
public bool HasSelectedBlock()
{
return SelectedBlockViewModel != null;
}
public bool HasSelectedEnabledBlock()
{
return HasSelectedBlock() && !(SelectedBlockViewModel.Block is ItemFilterSection) && SelectedBlockViewModel.BlockEnabled;
}
public bool HasSelectedDisabledBlock()
{
return HasSelectedBlock() && !(SelectedBlockViewModel.Block is ItemFilterSection) && !SelectedBlockViewModel.BlockEnabled;
}
public IItemFilterBlockViewModel SelectedBlockViewModel
{
get { return _selectedBlockViewModel; }
@@ -324,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)
@@ -350,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;
@@ -367,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();
@@ -388,6 +425,10 @@ namespace Filtration.ViewModels
MessageBoxImage.Error);
Script.FilePath = previousFilePath;
}
finally
{
Messenger.Default.Send(new NotificationMessage("HideLoadingBanner"));
}
}
private bool CheckForUnusedThemeComponents()
@@ -453,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)
{
@@ -467,25 +508,25 @@ namespace Filtration.ViewModels
else
{
var result = _messageBoxService.Show("Filtration",
"Want to save your changes to this script?", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
"Save script \"" + Filename + "\"?", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes:
{
Save();
CloseScript();
break;
}
{
await SaveAsync();
CloseScript();
break;
}
case MessageBoxResult.No:
{
CloseScript();
break;
}
{
CloseScript();
break;
}
case MessageBoxResult.Cancel:
{
return;
}
{
return;
}
}
}
}
@@ -521,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()
@@ -541,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()
@@ -552,7 +609,7 @@ namespace Filtration.ViewModels
public void PasteBlockStyle(IItemFilterBlockViewModel targetBlockViewModel)
{
var clipboardText = Clipboard.GetText();
var clipboardText = _clipboardService.GetClipboardText();
if (string.IsNullOrEmpty(clipboardText))
{
return;
@@ -571,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;
@@ -598,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);
}
}
@@ -730,6 +791,7 @@ namespace Filtration.ViewModels
IsDirty = true;
SelectedBlockViewModel = vm;
RaisePropertyChanged("ItemFilterSectionViewModels");
Messenger.Default.Send(new NotificationMessage("SectionsChanged"));
}
private void OnExpandAllBlocksCommand()
@@ -761,11 +823,39 @@ 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;
}
private void OnDisableBlockCommand()
{
DisableBlock(SelectedBlockViewModel);
}
private void DisableBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
targetBlockViewModel.BlockEnabled = false;
}
private void OnEnableBlockCommand()
{
EnableBlock(SelectedBlockViewModel);
}
private void EnableBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
targetBlockViewModel.BlockEnabled = true;
}
}
}

View File

@@ -1,9 +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;
@@ -24,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
@@ -33,6 +36,8 @@ namespace Filtration.ViewModels
{
RelayCommand OpenScriptCommand { get; }
RelayCommand NewScriptCommand { get; }
Task<bool> CloseAllDocumentsAsync();
Task OpenDroppedFilesAsync(List<string> filenames);
}
internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel
@@ -49,8 +54,8 @@ namespace Filtration.ViewModels
private readonly IUpdateCheckService _updateCheckService;
private readonly IUpdateAvailableViewModel _updateAvailableViewModel;
private readonly IMessageBoxService _messageBoxService;
private bool _activeDocumentIsScript;
private bool _activeDocumentIsTheme;
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,50 +79,54 @@ 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);
CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, () => ActiveDocumentIsScript);
OpenScriptCommand = new RelayCommand(async () => await OnOpenScriptCommand());
OpenThemeCommand = new RelayCommand(async () => await OnOpenThemeCommandAsync());
SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable);
SaveAsCommand = new RelayCommand(OnSaveAsCommand, ActiveDocumentIsEditable);
CloseCommand = new RelayCommand(OnCloseDocumentCommand, () => AvalonDockWorkspaceViewModel.ActiveDocument != null);
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);
CopyBlockStyleCommand = new RelayCommand(OnCopyBlockStyleCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
PasteCommand = new RelayCommand(OnPasteCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
PasteBlockStyleCommand = new RelayCommand(OnPasteBlockStyleCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
CopyBlockStyleCommand = new RelayCommand(OnCopyBlockStyleCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
PasteCommand = new RelayCommand(OnPasteCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
PasteBlockStyleCommand = new RelayCommand(OnPasteBlockStyleCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
AddBlockCommand = new RelayCommand(OnAddBlockCommand, () => _activeDocumentIsScript);
AddSectionCommand = new RelayCommand(OnAddSectionCommand, () => _activeDocumentIsScript);
DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => _activeDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
AddBlockCommand = new RelayCommand(OnAddBlockCommand, () => ActiveDocumentIsScript);
AddSectionCommand = new RelayCommand(OnAddSectionCommand, () => ActiveDocumentIsScript);
DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock);
DisableBlockCommand = new RelayCommand(OnDisableBlockCommand,
() => ActiveDocumentIsScript && ActiveScriptHasSelectedEnabledBlock);
EnableBlockCommand = new RelayCommand(OnEnableBlockCommand,
() => ActiveDocumentIsScript && ActiveScriptHasSelectedDisabledBlock);
OpenAboutWindowCommand = new RelayCommand(OnOpenAboutWindowCommand);
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => _activeDocumentIsScript);
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocumentIsScript);
CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => _activeDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(OnApplyThemeToScriptCommand, () => _activeDocumentIsScript);
EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => _activeDocumentIsScript);
CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, () => ActiveDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(async () => await OnApplyThemeToScriptCommandAsync(), () => ActiveDocumentIsScript);
EditMasterThemeCommand = new RelayCommand(OnEditMasterThemeCommand, () => ActiveDocumentIsScript);
AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => _activeDocumentIsTheme && ActiveThemeIsEditable);
AddBackgroundColorThemeComponentCommand = new RelayCommand(OnAddBackgroundColorThemeComponentCommand, () => _activeDocumentIsTheme && ActiveThemeIsEditable);
AddBorderColorThemeComponentCommand = new RelayCommand(OnAddBorderColorThemeComponentCommand, () => _activeDocumentIsTheme && ActiveThemeIsEditable);
AddTextColorThemeComponentCommand = new RelayCommand(OnAddTextColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable);
AddBackgroundColorThemeComponentCommand = new RelayCommand(OnAddBackgroundColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable);
AddBorderColorThemeComponentCommand = new RelayCommand(OnAddBorderColorThemeComponentCommand, () => ActiveDocumentIsTheme && ActiveThemeIsEditable);
DeleteThemeComponentCommand = new RelayCommand(OnDeleteThemeComponentCommand,
() =>
ActiveDocumentIsTheme && _activeDocumentIsTheme &&
ActiveDocumentIsTheme && ActiveThemeIsEditable &&
_avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent != null);
ExpandAllBlocksCommand = new RelayCommand(OnExpandAllBlocksCommand, () => _activeDocumentIsScript);
CollapseAllBlocksCommand = new RelayCommand(OnCollapseAllBlocksCommand, () => _activeDocumentIsScript);
ExpandAllBlocksCommand = new RelayCommand(OnExpandAllBlocksCommand, () => ActiveDocumentIsScript);
CollapseAllBlocksCommand = new RelayCommand(OnCollapseAllBlocksCommand, () => ActiveDocumentIsScript);
ToggleShowAdvancedCommand = new RelayCommand<bool>(OnToggleShowAdvancedCommand, s => _activeDocumentIsScript);
ClearFiltersCommand = new RelayCommand(OnClearFiltersCommand, () => _activeDocumentIsScript);
ToggleShowAdvancedCommand = new RelayCommand<bool>(OnToggleShowAdvancedCommand, s => ActiveDocumentIsScript);
ClearFiltersCommand = new RelayCommand(OnClearFiltersCommand, () => ActiveDocumentIsScript);
if (string.IsNullOrEmpty(_itemFilterScriptRepository.GetItemFilterScriptDirectory()))
{
@@ -151,7 +161,8 @@ namespace Filtration.ViewModels
ApplyThemeToScriptCommand.RaiseCanExecuteChanged();
EditMasterThemeCommand.RaiseCanExecuteChanged();
CreateThemeCommand.RaiseCanExecuteChanged();
SetActiveDocumentStatusProperties();
RaisePropertyChanged("ActiveDocumentIsScript");
RaisePropertyChanged("ActiveDocumentIsTheme");
RaisePropertyChanged("ShowAdvancedStatus");
break;
}
@@ -162,14 +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();
ActiveDocumentIsScript = false;
ActiveDocumentIsTheme = false;
Task.Run(async () =>
{
await CheckForUpdatesAsync();
}).Wait();
}
public RelayCommand OpenScriptCommand { get; private set; }
@@ -198,6 +223,8 @@ namespace Filtration.ViewModels
public RelayCommand AddBlockCommand { get; private set; }
public RelayCommand AddSectionCommand { get; private set; }
public RelayCommand DeleteBlockCommand { get; private set; }
public RelayCommand DisableBlockCommand { get; private set; }
public RelayCommand EnableBlockCommand { get; private set; }
public RelayCommand MoveBlockUpCommand { get; private set; }
public RelayCommand MoveBlockDownCommand { get; private set; }
@@ -211,14 +238,14 @@ namespace Filtration.ViewModels
public RelayCommand ClearFiltersCommand { get; private set; }
public async void CheckForUpdates()
public async Task CheckForUpdatesAsync()
{
var assemblyVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location);
var result = await _updateCheckService.GetUpdateData();
try
{
var result = await _updateCheckService.GetUpdateDataAsync();
if (result.LatestVersionMajorPart >= assemblyVersion.FileMajorPart &&
result.LatestVersionMinorPart > assemblyVersion.FileMinorPart)
{
@@ -275,36 +302,40 @@ namespace Filtration.ViewModels
}
}
private void SetActiveDocumentStatusProperties()
public bool ShowLoadingBanner
{
ActiveDocumentIsScript = AvalonDockWorkspaceViewModel.ActiveDocument is ItemFilterScriptViewModel;
ActiveDocumentIsTheme = AvalonDockWorkspaceViewModel.ActiveDocument is ThemeEditorViewModel;
get { return _showLoadingBanner; }
private set
{
_showLoadingBanner = value;
RaisePropertyChanged();
}
}
public bool ActiveDocumentIsScript
{
get { return _activeDocumentIsScript; }
private set
{
_activeDocumentIsScript = value;
RaisePropertyChanged();
}
get { return _avalonDockWorkspaceViewModel.ActiveDocument != null && _avalonDockWorkspaceViewModel.ActiveDocument.IsScript; }
}
public bool ActiveDocumentIsTheme
{
get { return _activeDocumentIsTheme; }
private set
{
_activeDocumentIsTheme = value;
RaisePropertyChanged();
}
get { return _avalonDockWorkspaceViewModel.ActiveDocument!= null && _avalonDockWorkspaceViewModel.ActiveDocument.IsTheme; }
}
public bool ActiveScriptHasSelectedBlock
{
get { return AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel != null; }
}
public bool ActiveScriptHasSelectedEnabledBlock
{
get { return AvalonDockWorkspaceViewModel.ActiveScriptViewModel.HasSelectedEnabledBlock(); }
}
public bool ActiveScriptHasSelectedDisabledBlock
{
get { return AvalonDockWorkspaceViewModel.ActiveScriptViewModel.HasSelectedDisabledBlock(); }
}
public bool ActiveThemeIsEditable
{
@@ -324,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);
@@ -364,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);
@@ -392,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)
{
@@ -421,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))
@@ -437,7 +503,7 @@ namespace Filtration.ViewModels
try
{
loadedTheme = _themeProvider.LoadThemeModelFromFile(filePath);
loadedTheme = await _themeProvider.LoadThemeModelFromFile(filePath);
}
catch (IOException e)
{
@@ -463,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()
{
@@ -475,8 +551,6 @@ namespace Filtration.ViewModels
return openFileDialog.ShowDialog() != true ? string.Empty : openFileDialog.FileName;
}
private void SetItemFilterScriptDirectory()
{
var dlg = new FolderBrowserDialog
@@ -492,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()
@@ -511,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()
@@ -580,6 +665,16 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.DeleteBlockCommand.Execute(null);
}
private void OnDisableBlockCommand()
{
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.DisableBlockCommand.Execute(null);
}
private void OnEnableBlockCommand()
{
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.EnableBlockCommand.Execute(null);
}
private void OnExpandAllBlocksCommand()
{
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.ExpandAllBlocksCommand.Execute(null);
@@ -620,5 +715,22 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.ActiveThemeViewModel.DeleteThemeComponentCommand.Execute(
_avalonDockWorkspaceViewModel.ActiveThemeViewModel.SelectedThemeComponent);
}
public async Task<bool> CloseAllDocumentsAsync()
{
var openDocuments = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().ToList();
foreach (var document in openDocuments)
{
var docCount = _avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count();
await document.Close();
if (_avalonDockWorkspaceViewModel.OpenDocuments.OfType<IEditableDocument>().Count() == docCount)
{
return false;
}
}
return true;
}
}
}

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

@@ -31,4 +31,6 @@
<Image Source="/Filtration;component/Resources/Icons/filtration_icon.png" x:Key="FiltrationIcon" x:Shared="False" />
<Image Source="/Filtration;component/Resources/Icons/Add.ico" x:Key="AddIcon" x:Shared="False" />
<Image Source="/Filtration;component/Resources/Icons/ThemeComponentDelete.ico" x:Key="ThemeComponentDeleteIcon" x:Shared="False" />
<Image Source="/Filtration;component/Resources/Icons/standby_enabled_icon.png" x:Key="StandbyEnabledIcon" x:Shared="False" />
<Image Source="/Filtration;component/Resources/Icons/standby_disabled_icon.png" x:Key="StandbyDisabledIcon" x:Shared="False" />
</ResourceDictionary>

View File

@@ -41,6 +41,11 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="TopLevelGrid">
<Grid x:Name="DisabledBlockOverlay" IsHitTestVisible="False" Panel.ZIndex="1000" Visibility="{Binding BlockEnabled, Converter={StaticResource InverseBooleanVisibilityConverter}}">
<Grid.Background>
<SolidColorBrush Color="Gray" Opacity=".5" />
</Grid.Background>
</Grid>
<Border BorderThickness="1" BorderBrush="SlateGray" CornerRadius="2" Background="White">
<Grid>
<Grid.ColumnDefinitions>
@@ -62,8 +67,8 @@
<Expander.ContextMenu>
<ContextMenu>
<ContextMenu.Items>
<MenuItem Header="Copy" Command="{Binding CopyBlockCommand}" Icon="{StaticResource CopyIcon}" />
<MenuItem Header="Paste" Command="{Binding PasteBlockCommand}" Icon="{StaticResource PasteIcon}" />
<MenuItem Header="Copy Block" Command="{Binding CopyBlockCommand}" Icon="{StaticResource CopyIcon}" />
<MenuItem Header="Paste Block" Command="{Binding PasteBlockCommand}" Icon="{StaticResource PasteIcon}" />
<Separator />
<MenuItem Header="Block Style">
<MenuItem Header="Copy Block Style" Command="{Binding CopyBlockStyleCommand}" Icon="{StaticResource CopyIcon}" />
@@ -89,6 +94,7 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- BlockItems Summary Panel -->
<StackPanel Grid.Row="0" Grid.Column="0" VerticalAlignment="Center">
@@ -121,9 +127,9 @@
</ItemsControl.Resources>
</ItemsControl>
</StackPanel>
<!-- Item Preview Box -->
<WrapPanel Grid.Row="0" Grid.Column="1" VerticalAlignment="Center">
<WrapPanel Grid.Row="0" Grid.Column="2" VerticalAlignment="Center">
<Button Command="{Binding PlaySoundCommand}"
Width="25"
Height="25"
@@ -160,6 +166,10 @@
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right">
<Hyperlink Command="{Binding SwitchBlockItemsViewCommand}">
Switch to Appearance Block Items
@@ -167,7 +177,7 @@
</TextBlock>
<!-- Add Block Item Links -->
<ItemsControl ItemsSource="{Binding BlockItemTypesAvailable}" Grid.Row="0" Margin="0,0,0,10">
<ItemsControl Grid.Column="0" ItemsSource="{Binding BlockItemTypesAvailable}" Grid.Row="0" Margin="0,0,0,10">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel></WrapPanel>
@@ -183,9 +193,35 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Enable/Disable Block Button -->
<ToggleButton Grid.Row="0"
Grid.Column="1"
Style="{StaticResource ChromelessToggleButton}"
IsChecked="{Binding BlockEnabled}"
Margin="0,0,5,0"
ToolTip="Enable/Disable Block"
Cursor="Hand"
Width="25"
Height="25">
<Image RenderOptions.BitmapScalingMode="HighQuality">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Style.Triggers>
<DataTrigger Binding="{Binding BlockEnabled}" Value="true">
<Setter Property="Source" Value="/Filtration;component/Resources/Icons/standby_enabled_icon.png"/>
</DataTrigger>
<DataTrigger Binding="{Binding BlockEnabled}" Value="false">
<Setter Property="Source" Value="/Filtration;component/Resources/Icons/standby_disabled_icon.png"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
</ToggleButton>
<!-- Block Items -->
<WrapPanel Grid.Row="1" MaxHeight="200">
<WrapPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" MaxHeight="200">
<WrapPanel.Resources>
<CollectionViewSource Source="{Binding RegularBlockItems}" x:Key="BlockItemsCollectionViewSource">
<CollectionViewSource.SortDescriptions>
@@ -235,7 +271,9 @@
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<TextBlock Grid.Row="1" FontStyle="Italic" Visibility="{Binding HasAudioVisualBlockItems, Converter={StaticResource InverseBooleanVisibilityConverter}}">To change the appearance of this block, add a Text, Background or Border Block Item above.</TextBlock>
<!-- Block Items -->
<WrapPanel Grid.Row="1" MaxHeight="200">
<WrapPanel.Resources>

View File

@@ -8,15 +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" >
Title="{Binding WindowTitle}" Height="762" Width="1126" IsIconVisible="True"
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>
@@ -29,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 />
@@ -71,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">
@@ -85,6 +88,8 @@
<fluent:Button Header="Move Up" Command="{Binding MoveBlockUpCommand}" SizeDefinition="Middle" Icon="{StaticResource MoveUpIcon}" />
<fluent:Button Header="Move Down" Command="{Binding MoveBlockDownCommand}" SizeDefinition="Middle" Icon="{StaticResource MoveDownIcon}" />
<fluent:Button Header="Move To Bottom" Command="{Binding MoveBlockToBottomCommand}" SizeDefinition="Middle" Icon="{StaticResource MoveToBottomIcon}" />
<fluent:Button Header="Enable Block" Command="{Binding EnableBlockCommand}" SizeDefinition="Middle" Icon="{StaticResource StandbyEnabledIcon}" />
<fluent:Button Header="Disable Block" Command="{Binding DisableBlockCommand}" SizeDefinition="Middle" Icon="{StaticResource StandbyDisabledIcon}" />
</fluent:RibbonGroupBox>
<fluent:RibbonGroupBox Header="Expand / Collapse">
<fluent:Button Header="Expand All" Command="{Binding ExpandAllBlocksCommand}" SizeDefinition="Middle" Icon="{StaticResource ExpandIcon}" />
@@ -114,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,4 +1,8 @@
using System.Windows;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using Filtration.ViewModels;
namespace Filtration.Views
@@ -10,8 +14,11 @@ namespace Filtration.Views
internal partial class MainWindow : IMainWindow
{
private readonly IMainWindowViewModel _mainWindowViewModel;
public MainWindow(IMainWindowViewModel mainWindowViewModel)
{
_mainWindowViewModel = mainWindowViewModel;
InitializeComponent();
DataContext = mainWindowViewModel;
}
@@ -31,5 +38,38 @@ namespace Filtration.Views
RibbonRoot.SelectedTabItem = ThemeToolsTabItem;
}
}
private void MainWindow_OnClosing(object sender, CancelEventArgs e)
{
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
<b>Installer (6.01mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.5/filtration_0.5_setup.exe">filtration_0.5_setup.exe</a>
## Current Release (Released 2015-07-26)
<b>Installer (6.37mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.10/filtration_0.10_setup.exe">filtration_0.10_setup.exe</a>
<b>Zip File (7.54mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.5/filtration_0.5.zip">filtration_0.5.zip</a>
<b>Zip File (7.97mb)</b> <a href="https://github.com/ben-wallis/Filtration/releases/download/0.10/filtration_0.10.zip">filtration_0.10.zip</a>
## System Requirements
Filtration requires .NET Framework 4.5.1 installed.
@@ -26,19 +26,10 @@ If you'd like to make your script fully compatible with Filtration, please take
## Screenshots
##### Main Window
<img src="http://i.imgur.com/s2lNHCm.png" />
##### Block Editor
<img src="http://i.imgur.com/BqWGxs7.png" />
<img src="http://i.imgur.com/eAsMoSo.png" />
##### Theme Editor
<img src="http://i.imgur.com/R2w7Hf2.png" />
##### Block Color Editor
<img src="http://i.imgur.com/nlBGiG4.png" />
##### Replace Colors Tool
<img src="http://i.imgur.com/oY1q6hq.png" />
<img src="http://i.imgur.com/FJWJknO.png" />
## Contact