From 5b4c6223455e725f554926a076a46994a3fcec1c Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 26 Jun 2015 21:54:20 +0100 Subject: [PATCH] Completed initial implementation of Theme Editor --- .../Filtration.ThemeEditor.csproj | 1 + .../Providers/ThemeProvider.cs | 10 ++- .../Services/ThemeService.cs | 67 ++++++++++++++++ .../Views/ThemeControl.xaml | 4 +- .../WindsorInstallers/ServicesInstaller.cs | 5 ++ .../ViewModels/ItemFilterScriptViewModel.cs | 12 ++- Filtration/ViewModels/MainWindowViewModel.cs | 78 ++++++++++++++++--- Filtration/Views/MainWindow.xaml | 3 +- 8 files changed, 159 insertions(+), 21 deletions(-) create mode 100644 Filtration.ThemeEditor/Services/ThemeService.cs diff --git a/Filtration.ThemeEditor/Filtration.ThemeEditor.csproj b/Filtration.ThemeEditor/Filtration.ThemeEditor.csproj index 65fc4f7..57cb908 100644 --- a/Filtration.ThemeEditor/Filtration.ThemeEditor.csproj +++ b/Filtration.ThemeEditor/Filtration.ThemeEditor.csproj @@ -95,6 +95,7 @@ + diff --git a/Filtration.ThemeEditor/Providers/ThemeProvider.cs b/Filtration.ThemeEditor/Providers/ThemeProvider.cs index 3ffb8bd..b072c02 100644 --- a/Filtration.ThemeEditor/Providers/ThemeProvider.cs +++ b/Filtration.ThemeEditor/Providers/ThemeProvider.cs @@ -1,7 +1,6 @@ using System.Collections.ObjectModel; using AutoMapper; using Filtration.ObjectModel; -using Filtration.ObjectModel.Enums; using Filtration.ObjectModel.ThemeEditor; using Filtration.ThemeEditor.Services; using Filtration.ThemeEditor.ViewModels; @@ -12,6 +11,7 @@ namespace Filtration.ThemeEditor.Providers { IThemeViewModel NewThemeForScript(ItemFilterScript script); IThemeViewModel LoadThemeFromFile(string filePath); + Theme LoadThemeModelFromFile(string filePath); void SaveTheme(IThemeViewModel themeViewModel, string filePath); } @@ -29,7 +29,6 @@ namespace Filtration.ThemeEditor.Providers public IThemeViewModel NewThemeForScript(ItemFilterScript script) { Mapper.CreateMap(); - //Mapper.CreateMap(); var themeComponentViewModels = Mapper.Map>(script.ThemeComponents); var themeViewModel = _themeViewModelFactory.Create(); @@ -43,7 +42,6 @@ namespace Filtration.ThemeEditor.Providers { Mapper.CreateMap().ConstructUsingServiceLocator(); Mapper.CreateMap(); - //Mapper.CreateMap(); var model = _themePersistenceService.LoadTheme(filePath); var viewModel = Mapper.Map(model); @@ -51,11 +49,15 @@ namespace Filtration.ThemeEditor.Providers return viewModel; } + public Theme LoadThemeModelFromFile(string filePath) + { + return _themePersistenceService.LoadTheme(filePath); + } + public void SaveTheme(IThemeViewModel themeViewModel, string filePath) { Mapper.CreateMap(); Mapper.CreateMap(); - //Mapper.CreateMap(); var theme = Mapper.Map(themeViewModel); _themePersistenceService.SaveTheme(theme, filePath); diff --git a/Filtration.ThemeEditor/Services/ThemeService.cs b/Filtration.ThemeEditor/Services/ThemeService.cs new file mode 100644 index 0000000..8b82018 --- /dev/null +++ b/Filtration.ThemeEditor/Services/ThemeService.cs @@ -0,0 +1,67 @@ +using System; +using System.Linq; +using System.Windows; +using Filtration.ObjectModel; +using Filtration.ObjectModel.BlockItemBaseTypes; +using Filtration.ObjectModel.BlockItemTypes; +using Filtration.ObjectModel.Enums; +using Filtration.ObjectModel.ThemeEditor; + +namespace Filtration.ThemeEditor.Services +{ + public interface IThemeService + { + void ApplyThemeToScript(Theme theme, ItemFilterScript script); + } + + public class ThemeService : IThemeService + { + public void ApplyThemeToScript(Theme theme, ItemFilterScript script) + { + var mismatchedComponents = false; + foreach (var component in theme.Components) + { + var componentMatched = false; + Type targetType = null; + switch (component.ComponentType) + { + case ThemeComponentType.BackgroundColor: + targetType = typeof (BackgroundColorBlockItem); + break; + case ThemeComponentType.TextColor: + targetType = typeof (TextColorBlockItem); + break; + case ThemeComponentType.BorderColor: + targetType = typeof (BorderColorBlockItem); + break; + } + + foreach (var block in script.ItemFilterBlocks) + { + foreach (var blockItem in block.BlockItems.Where(i => i.GetType() == targetType)) + { + var colorBlockItem = (ColorBlockItem) blockItem; + if (colorBlockItem.ThemeComponent != null && + colorBlockItem.ThemeComponent.ComponentName == component.ComponentName) + { + colorBlockItem.Color = component.Color; + componentMatched = true; + } + } + } + + if (!componentMatched) + { + mismatchedComponents = true; + } + } + + if (mismatchedComponents) + { + MessageBox.Show( + "Not all theme components had matches - are you sure this theme is designed for this script?", + "Possible Theme Mismatch", MessageBoxButton.OK, MessageBoxImage.Exclamation); + } + } + } +} diff --git a/Filtration.ThemeEditor/Views/ThemeControl.xaml b/Filtration.ThemeEditor/Views/ThemeControl.xaml index 254e2db..2b21c2b 100644 --- a/Filtration.ThemeEditor/Views/ThemeControl.xaml +++ b/Filtration.ThemeEditor/Views/ThemeControl.xaml @@ -10,7 +10,7 @@ d:DesignHeight="300" d:DesignWidth="300"> - + @@ -18,7 +18,7 @@ - + diff --git a/Filtration.ThemeEditor/WindsorInstallers/ServicesInstaller.cs b/Filtration.ThemeEditor/WindsorInstallers/ServicesInstaller.cs index 26ada59..a0de0ee 100644 --- a/Filtration.ThemeEditor/WindsorInstallers/ServicesInstaller.cs +++ b/Filtration.ThemeEditor/WindsorInstallers/ServicesInstaller.cs @@ -13,6 +13,11 @@ namespace Filtration.ThemeEditor.WindsorInstallers Component.For() .ImplementedBy() .LifeStyle.Singleton); + + container.Register( + Component.For() + .ImplementedBy() + .LifeStyle.Singleton); } } } diff --git a/Filtration/ViewModels/ItemFilterScriptViewModel.cs b/Filtration/ViewModels/ItemFilterScriptViewModel.cs index de5a02f..d27f934 100644 --- a/Filtration/ViewModels/ItemFilterScriptViewModel.cs +++ b/Filtration/ViewModels/ItemFilterScriptViewModel.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Windows; using System.Windows.Data; using System.Windows.Forms; -using System.Windows.Media; using System.Windows.Media.Imaging; using Castle.Core.Internal; using Filtration.Common.ViewModels; @@ -15,7 +14,6 @@ using Filtration.Interface; using Filtration.ObjectModel; using Filtration.Services; using Filtration.Translators; -using Filtration.ViewModels.ToolPanes; using GalaSoft.MvvmLight.CommandWpf; using GalaSoft.MvvmLight.Messaging; using Clipboard = System.Windows.Clipboard; @@ -37,6 +35,7 @@ namespace Filtration.ViewModels void Initialise(ItemFilterScript itemFilterScript, bool newScript); void RemoveDirtyFlag(); + void SetDirtyFlag(); void AddSection(IItemFilterBlockViewModel targetBlockViewModel); void AddBlock(IItemFilterBlockViewModel targetBlockViewModel); @@ -238,7 +237,14 @@ namespace Filtration.ViewModels RaisePropertyChanged("Filename"); RaisePropertyChanged("DisplayName"); } - + + public void SetDirtyFlag() + { + IsDirty = true; + RaisePropertyChanged("Filename"); + RaisePropertyChanged("DisplayName"); + } + public string DisplayName { get { return !string.IsNullOrEmpty(Filename) ? Filename : Description; } diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index f945d15..c68e14d 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -4,8 +4,10 @@ using System.Reflection; using System.Windows.Forms; using Filtration.Common.ViewModels; using Filtration.Interface; +using Filtration.ObjectModel.ThemeEditor; using Filtration.Repositories; using Filtration.ThemeEditor.Providers; +using Filtration.ThemeEditor.Services; using Filtration.ThemeEditor.ViewModels; using Filtration.Translators; using Filtration.Views; @@ -30,6 +32,7 @@ namespace Filtration.ViewModels private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel; private readonly ISettingsWindowViewModel _settingsWindowViewModel; private readonly IThemeProvider _themeProvider; + private readonly IThemeService _themeService; private IDocument _activeDocument; @@ -38,7 +41,8 @@ namespace Filtration.ViewModels IReplaceColorsViewModel replaceColorsViewModel, IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel, ISettingsWindowViewModel settingsWindowViewModel, - IThemeProvider themeProvider) + IThemeProvider themeProvider, + IThemeService themeService) { _itemFilterScriptRepository = itemFilterScriptRepository; _itemFilterScriptTranslator = itemFilterScriptTranslator; @@ -46,12 +50,14 @@ namespace Filtration.ViewModels _avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel; _settingsWindowViewModel = settingsWindowViewModel; _themeProvider = themeProvider; + _themeService = themeService; NewScriptCommand = new RelayCommand(OnNewScriptCommand); CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, ActiveDocumentIsScript); OpenScriptCommand = new RelayCommand(OnOpenScriptCommand); OpenThemeCommand = new RelayCommand(OnOpenThemeCommand); + SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable); SaveAsCommand = new RelayCommand(OnSaveAsCommand, ActiveDocumentIsEditable); CloseCommand = new RelayCommand(OnCloseDocumentCommand, () => AvalonDockWorkspaceViewModel.ActiveDocument != null); @@ -63,6 +69,7 @@ namespace Filtration.ViewModels OpenSettingsWindowCommand = new RelayCommand(OnOpenSettingsWindowCommand); ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, ActiveDocumentIsScript); CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, ActiveDocumentIsScript); + ApplyThemeToScriptCommand = new RelayCommand(OnApplyThemeToScriptCommand, ActiveDocumentIsScript); //LoadScriptFromFile("C:\\ThioleLootFilter.txt"); @@ -78,14 +85,16 @@ namespace Filtration.ViewModels case "ActiveDocumentChanged": { _activeDocument = _avalonDockWorkspaceViewModel.ActiveDocument; + + CopyScriptCommand.RaiseCanExecuteChanged(); SaveCommand.RaiseCanExecuteChanged(); SaveAsCommand.RaiseCanExecuteChanged(); - CopyScriptCommand.RaiseCanExecuteChanged(); + CloseCommand.RaiseCanExecuteChanged(); CopyBlockCommand.RaiseCanExecuteChanged(); PasteCommand.RaiseCanExecuteChanged(); - NewScriptCommand.RaiseCanExecuteChanged(); - CloseCommand.RaiseCanExecuteChanged(); ReplaceColorsCommand.RaiseCanExecuteChanged(); + ApplyThemeToScriptCommand.RaiseCanExecuteChanged(); + CreateThemeCommand.RaiseCanExecuteChanged(); break; } case "NewScript": @@ -115,6 +124,7 @@ namespace Filtration.ViewModels public RelayCommand OpenSettingsWindowCommand { get; private set; } public RelayCommand ReplaceColorsCommand { get; private set; } public RelayCommand CreateThemeCommand { get; private set; } + public RelayCommand ApplyThemeToScriptCommand { get; private set; } public IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel { @@ -201,19 +211,18 @@ namespace Filtration.ViewModels private void OnOpenThemeCommand() { - var openFileDialog = new OpenFileDialog + + var filePath = ShowOpenThemeDialog(); + if (string.IsNullOrEmpty(filePath)) { - Filter = "Filter Theme Files (*.filtertheme)|*.filtertheme|All Files (*.*)|*.*", - InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() - }; - - if (openFileDialog.ShowDialog() != true) return; + return; + } IThemeViewModel loadedViewModel; try { - loadedViewModel = _themeProvider.LoadThemeFromFile(openFileDialog.FileName); + loadedViewModel = _themeProvider.LoadThemeFromFile(filePath); } catch (IOException e) { @@ -226,6 +235,53 @@ namespace Filtration.ViewModels _avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); } + private void OnApplyThemeToScriptCommand() + { + var filePath = ShowOpenThemeDialog(); + if (string.IsNullOrEmpty(filePath)) + { + return; + } + + Theme loadedTheme; + + try + { + loadedTheme = _themeProvider.LoadThemeModelFromFile(filePath); + } + catch (IOException e) + { + MessageBox.Show(@"Error loading filter theme - " + e.Message, @"Theme Load Error", + MessageBoxButtons.OK, + MessageBoxIcon.Error); + return; + } + + var result = MessageBox.Show(@"Are you sure you wish to apply this theme to the current filter script?", + @"Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question); + if (result == DialogResult.No) + { + return; + } + + _themeService.ApplyThemeToScript(loadedTheme, AvalonDockWorkspaceViewModel.ActiveScriptViewModel.Script); + AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SetDirtyFlag(); + } + + + private string ShowOpenThemeDialog() + { + var openFileDialog = new OpenFileDialog + { + Filter = "Filter Theme Files (*.filtertheme)|*.filtertheme|All Files (*.*)|*.*", + InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() + }; + + return openFileDialog.ShowDialog() != true ? string.Empty : openFileDialog.FileName; + } + + + private void SetItemFilterScriptDirectory() { var dlg = new FolderBrowserDialog diff --git a/Filtration/Views/MainWindow.xaml b/Filtration/Views/MainWindow.xaml index ec43b54..a582a5a 100644 --- a/Filtration/Views/MainWindow.xaml +++ b/Filtration/Views/MainWindow.xaml @@ -9,7 +9,7 @@ xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock" mc:Ignorable="d" d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}" - Title="{Binding WindowTitle}" Height="768" Width="1024" BorderThickness="1" BorderBrush="Black"> + Title="{Binding WindowTitle}" Height="768" Width="1100" BorderThickness="1" BorderBrush="Black"> @@ -33,6 +33,7 @@ +