Completed initial implementation of Theme Editor

This commit is contained in:
Ben 2015-06-26 21:54:20 +01:00
parent 71ad5f2d05
commit 5b4c622345
8 changed files with 159 additions and 21 deletions

View File

@ -95,6 +95,7 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Providers\ThemeProvider.cs" /> <Compile Include="Providers\ThemeProvider.cs" />
<Compile Include="Services\ThemePersistenceService.cs" /> <Compile Include="Services\ThemePersistenceService.cs" />
<Compile Include="Services\ThemeService.cs" />
<Compile Include="ViewModels\IThemeViewModelFactory.cs" /> <Compile Include="ViewModels\IThemeViewModelFactory.cs" />
<Compile Include="ViewModels\ThemeComponentViewModel.cs" /> <Compile Include="ViewModels\ThemeComponentViewModel.cs" />
<Compile Include="ViewModels\ThemeViewModel.cs" /> <Compile Include="ViewModels\ThemeViewModel.cs" />

View File

@ -1,7 +1,6 @@
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using AutoMapper; using AutoMapper;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.ObjectModel.Enums;
using Filtration.ObjectModel.ThemeEditor; using Filtration.ObjectModel.ThemeEditor;
using Filtration.ThemeEditor.Services; using Filtration.ThemeEditor.Services;
using Filtration.ThemeEditor.ViewModels; using Filtration.ThemeEditor.ViewModels;
@ -12,6 +11,7 @@ namespace Filtration.ThemeEditor.Providers
{ {
IThemeViewModel NewThemeForScript(ItemFilterScript script); IThemeViewModel NewThemeForScript(ItemFilterScript script);
IThemeViewModel LoadThemeFromFile(string filePath); IThemeViewModel LoadThemeFromFile(string filePath);
Theme LoadThemeModelFromFile(string filePath);
void SaveTheme(IThemeViewModel themeViewModel, string filePath); void SaveTheme(IThemeViewModel themeViewModel, string filePath);
} }
@ -29,7 +29,6 @@ namespace Filtration.ThemeEditor.Providers
public IThemeViewModel NewThemeForScript(ItemFilterScript script) public IThemeViewModel NewThemeForScript(ItemFilterScript script)
{ {
Mapper.CreateMap<ThemeComponent, ThemeComponentViewModel>(); Mapper.CreateMap<ThemeComponent, ThemeComponentViewModel>();
//Mapper.CreateMap<ThemeComponentType, ThemeComponentType>();
var themeComponentViewModels = Mapper.Map<ObservableCollection<ThemeComponentViewModel>>(script.ThemeComponents); var themeComponentViewModels = Mapper.Map<ObservableCollection<ThemeComponentViewModel>>(script.ThemeComponents);
var themeViewModel = _themeViewModelFactory.Create(); var themeViewModel = _themeViewModelFactory.Create();
@ -43,7 +42,6 @@ namespace Filtration.ThemeEditor.Providers
{ {
Mapper.CreateMap<Theme, IThemeViewModel>().ConstructUsingServiceLocator(); Mapper.CreateMap<Theme, IThemeViewModel>().ConstructUsingServiceLocator();
Mapper.CreateMap<ThemeComponent, ThemeComponentViewModel>(); Mapper.CreateMap<ThemeComponent, ThemeComponentViewModel>();
//Mapper.CreateMap<ThemeComponentType, ThemeComponentType>();
var model = _themePersistenceService.LoadTheme(filePath); var model = _themePersistenceService.LoadTheme(filePath);
var viewModel = Mapper.Map<IThemeViewModel>(model); var viewModel = Mapper.Map<IThemeViewModel>(model);
@ -51,11 +49,15 @@ namespace Filtration.ThemeEditor.Providers
return viewModel; return viewModel;
} }
public Theme LoadThemeModelFromFile(string filePath)
{
return _themePersistenceService.LoadTheme(filePath);
}
public void SaveTheme(IThemeViewModel themeViewModel, string filePath) public void SaveTheme(IThemeViewModel themeViewModel, string filePath)
{ {
Mapper.CreateMap<IThemeViewModel, Theme>(); Mapper.CreateMap<IThemeViewModel, Theme>();
Mapper.CreateMap<ThemeComponentViewModel, ThemeComponent>(); Mapper.CreateMap<ThemeComponentViewModel, ThemeComponent>();
//Mapper.CreateMap<ThemeComponentType, ThemeComponentType>();
var theme = Mapper.Map<Theme>(themeViewModel); var theme = Mapper.Map<Theme>(themeViewModel);
_themePersistenceService.SaveTheme(theme, filePath); _themePersistenceService.SaveTheme(theme, filePath);

View File

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

View File

@ -10,7 +10,7 @@
d:DesignHeight="300" d:DesignWidth="300"> d:DesignHeight="300" d:DesignWidth="300">
<Grid> <Grid>
<ScrollViewer HorizontalScrollBarVisibility="Disabled"> <ScrollViewer HorizontalScrollBarVisibility="Disabled">
<ItemsControl ItemsSource="{Binding Components}"> <ItemsControl ItemsSource="{Binding Components}" Margin="10">
<ItemsControl.ItemsPanel> <ItemsControl.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<WrapPanel /> <WrapPanel />
@ -18,7 +18,7 @@
</ItemsControl.ItemsPanel> </ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate> <ItemsControl.ItemTemplate>
<DataTemplate> <DataTemplate>
<views:ThemeComponentControl DataContext="{Binding}" Margin="10" /> <views:ThemeComponentControl DataContext="{Binding}" Margin="10,5,10,5" />
</DataTemplate> </DataTemplate>
</ItemsControl.ItemTemplate> </ItemsControl.ItemTemplate>
</ItemsControl> </ItemsControl>

View File

@ -13,6 +13,11 @@ namespace Filtration.ThemeEditor.WindsorInstallers
Component.For<IThemePersistenceService>() Component.For<IThemePersistenceService>()
.ImplementedBy<ThemePersistenceService>() .ImplementedBy<ThemePersistenceService>()
.LifeStyle.Singleton); .LifeStyle.Singleton);
container.Register(
Component.For<IThemeService>()
.ImplementedBy<ThemeService>()
.LifeStyle.Singleton);
} }
} }
} }

View File

@ -7,7 +7,6 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using Castle.Core.Internal; using Castle.Core.Internal;
using Filtration.Common.ViewModels; using Filtration.Common.ViewModels;
@ -15,7 +14,6 @@ using Filtration.Interface;
using Filtration.ObjectModel; using Filtration.ObjectModel;
using Filtration.Services; using Filtration.Services;
using Filtration.Translators; using Filtration.Translators;
using Filtration.ViewModels.ToolPanes;
using GalaSoft.MvvmLight.CommandWpf; using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging; using GalaSoft.MvvmLight.Messaging;
using Clipboard = System.Windows.Clipboard; using Clipboard = System.Windows.Clipboard;
@ -37,6 +35,7 @@ namespace Filtration.ViewModels
void Initialise(ItemFilterScript itemFilterScript, bool newScript); void Initialise(ItemFilterScript itemFilterScript, bool newScript);
void RemoveDirtyFlag(); void RemoveDirtyFlag();
void SetDirtyFlag();
void AddSection(IItemFilterBlockViewModel targetBlockViewModel); void AddSection(IItemFilterBlockViewModel targetBlockViewModel);
void AddBlock(IItemFilterBlockViewModel targetBlockViewModel); void AddBlock(IItemFilterBlockViewModel targetBlockViewModel);
@ -238,7 +237,14 @@ namespace Filtration.ViewModels
RaisePropertyChanged("Filename"); RaisePropertyChanged("Filename");
RaisePropertyChanged("DisplayName"); RaisePropertyChanged("DisplayName");
} }
public void SetDirtyFlag()
{
IsDirty = true;
RaisePropertyChanged("Filename");
RaisePropertyChanged("DisplayName");
}
public string DisplayName public string DisplayName
{ {
get { return !string.IsNullOrEmpty(Filename) ? Filename : Description; } get { return !string.IsNullOrEmpty(Filename) ? Filename : Description; }

View File

@ -4,8 +4,10 @@ using System.Reflection;
using System.Windows.Forms; using System.Windows.Forms;
using Filtration.Common.ViewModels; using Filtration.Common.ViewModels;
using Filtration.Interface; using Filtration.Interface;
using Filtration.ObjectModel.ThemeEditor;
using Filtration.Repositories; using Filtration.Repositories;
using Filtration.ThemeEditor.Providers; using Filtration.ThemeEditor.Providers;
using Filtration.ThemeEditor.Services;
using Filtration.ThemeEditor.ViewModels; using Filtration.ThemeEditor.ViewModels;
using Filtration.Translators; using Filtration.Translators;
using Filtration.Views; using Filtration.Views;
@ -30,6 +32,7 @@ namespace Filtration.ViewModels
private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel; private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel;
private readonly ISettingsWindowViewModel _settingsWindowViewModel; private readonly ISettingsWindowViewModel _settingsWindowViewModel;
private readonly IThemeProvider _themeProvider; private readonly IThemeProvider _themeProvider;
private readonly IThemeService _themeService;
private IDocument _activeDocument; private IDocument _activeDocument;
@ -38,7 +41,8 @@ namespace Filtration.ViewModels
IReplaceColorsViewModel replaceColorsViewModel, IReplaceColorsViewModel replaceColorsViewModel,
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel, IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel,
ISettingsWindowViewModel settingsWindowViewModel, ISettingsWindowViewModel settingsWindowViewModel,
IThemeProvider themeProvider) IThemeProvider themeProvider,
IThemeService themeService)
{ {
_itemFilterScriptRepository = itemFilterScriptRepository; _itemFilterScriptRepository = itemFilterScriptRepository;
_itemFilterScriptTranslator = itemFilterScriptTranslator; _itemFilterScriptTranslator = itemFilterScriptTranslator;
@ -46,12 +50,14 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel; _avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel;
_settingsWindowViewModel = settingsWindowViewModel; _settingsWindowViewModel = settingsWindowViewModel;
_themeProvider = themeProvider; _themeProvider = themeProvider;
_themeService = themeService;
NewScriptCommand = new RelayCommand(OnNewScriptCommand); NewScriptCommand = new RelayCommand(OnNewScriptCommand);
CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, ActiveDocumentIsScript); CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, ActiveDocumentIsScript);
OpenScriptCommand = new RelayCommand(OnOpenScriptCommand); OpenScriptCommand = new RelayCommand(OnOpenScriptCommand);
OpenThemeCommand = new RelayCommand(OnOpenThemeCommand); OpenThemeCommand = new RelayCommand(OnOpenThemeCommand);
SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable); SaveCommand = new RelayCommand(OnSaveDocumentCommand, ActiveDocumentIsEditable);
SaveAsCommand = new RelayCommand(OnSaveAsCommand, ActiveDocumentIsEditable); SaveAsCommand = new RelayCommand(OnSaveAsCommand, ActiveDocumentIsEditable);
CloseCommand = new RelayCommand(OnCloseDocumentCommand, () => AvalonDockWorkspaceViewModel.ActiveDocument != null); CloseCommand = new RelayCommand(OnCloseDocumentCommand, () => AvalonDockWorkspaceViewModel.ActiveDocument != null);
@ -63,6 +69,7 @@ namespace Filtration.ViewModels
OpenSettingsWindowCommand = new RelayCommand(OnOpenSettingsWindowCommand); OpenSettingsWindowCommand = new RelayCommand(OnOpenSettingsWindowCommand);
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, ActiveDocumentIsScript); ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, ActiveDocumentIsScript);
CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, ActiveDocumentIsScript); CreateThemeCommand = new RelayCommand(OnCreateThemeCommand, ActiveDocumentIsScript);
ApplyThemeToScriptCommand = new RelayCommand(OnApplyThemeToScriptCommand, ActiveDocumentIsScript);
//LoadScriptFromFile("C:\\ThioleLootFilter.txt"); //LoadScriptFromFile("C:\\ThioleLootFilter.txt");
@ -78,14 +85,16 @@ namespace Filtration.ViewModels
case "ActiveDocumentChanged": case "ActiveDocumentChanged":
{ {
_activeDocument = _avalonDockWorkspaceViewModel.ActiveDocument; _activeDocument = _avalonDockWorkspaceViewModel.ActiveDocument;
CopyScriptCommand.RaiseCanExecuteChanged();
SaveCommand.RaiseCanExecuteChanged(); SaveCommand.RaiseCanExecuteChanged();
SaveAsCommand.RaiseCanExecuteChanged(); SaveAsCommand.RaiseCanExecuteChanged();
CopyScriptCommand.RaiseCanExecuteChanged(); CloseCommand.RaiseCanExecuteChanged();
CopyBlockCommand.RaiseCanExecuteChanged(); CopyBlockCommand.RaiseCanExecuteChanged();
PasteCommand.RaiseCanExecuteChanged(); PasteCommand.RaiseCanExecuteChanged();
NewScriptCommand.RaiseCanExecuteChanged();
CloseCommand.RaiseCanExecuteChanged();
ReplaceColorsCommand.RaiseCanExecuteChanged(); ReplaceColorsCommand.RaiseCanExecuteChanged();
ApplyThemeToScriptCommand.RaiseCanExecuteChanged();
CreateThemeCommand.RaiseCanExecuteChanged();
break; break;
} }
case "NewScript": case "NewScript":
@ -115,6 +124,7 @@ namespace Filtration.ViewModels
public RelayCommand OpenSettingsWindowCommand { get; private set; } public RelayCommand OpenSettingsWindowCommand { get; private set; }
public RelayCommand ReplaceColorsCommand { get; private set; } public RelayCommand ReplaceColorsCommand { get; private set; }
public RelayCommand CreateThemeCommand { get; private set; } public RelayCommand CreateThemeCommand { get; private set; }
public RelayCommand ApplyThemeToScriptCommand { get; private set; }
public IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel public IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel
{ {
@ -201,19 +211,18 @@ namespace Filtration.ViewModels
private void OnOpenThemeCommand() private void OnOpenThemeCommand()
{ {
var openFileDialog = new OpenFileDialog
var filePath = ShowOpenThemeDialog();
if (string.IsNullOrEmpty(filePath))
{ {
Filter = "Filter Theme Files (*.filtertheme)|*.filtertheme|All Files (*.*)|*.*", return;
InitialDirectory = _itemFilterScriptRepository.GetItemFilterScriptDirectory() }
};
if (openFileDialog.ShowDialog() != true) return;
IThemeViewModel loadedViewModel; IThemeViewModel loadedViewModel;
try try
{ {
loadedViewModel = _themeProvider.LoadThemeFromFile(openFileDialog.FileName); loadedViewModel = _themeProvider.LoadThemeFromFile(filePath);
} }
catch (IOException e) catch (IOException e)
{ {
@ -226,6 +235,53 @@ namespace Filtration.ViewModels
_avalonDockWorkspaceViewModel.AddDocument(loadedViewModel); _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() private void SetItemFilterScriptDirectory()
{ {
var dlg = new FolderBrowserDialog var dlg = new FolderBrowserDialog

View File

@ -9,7 +9,7 @@
xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock" xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock"
mc:Ignorable="d" mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}" 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">
<DockPanel> <DockPanel>
<Menu DockPanel.Dock="Top"> <Menu DockPanel.Dock="Top">
<MenuItem Header="_File"> <MenuItem Header="_File">
@ -33,6 +33,7 @@
<MenuItem Header="Block Group Browser" IsCheckable="True" IsChecked="{Binding AvalonDockWorkspaceViewModel.BlockGroupBrowserViewModel.IsVisible}" Icon="{StaticResource BlockGroupBrowserIcon}" /> <MenuItem Header="Block Group Browser" IsCheckable="True" IsChecked="{Binding AvalonDockWorkspaceViewModel.BlockGroupBrowserViewModel.IsVisible}" Icon="{StaticResource BlockGroupBrowserIcon}" />
</MenuItem> </MenuItem>
<MenuItem Header="_Tools"> <MenuItem Header="_Tools">
<MenuItem Header="_Apply Theme to Script" Command="{Binding ApplyThemeToScriptCommand}" Icon="{StaticResource ThemeIcon}" />
<MenuItem Header="_Replace Colors" Command="{Binding ReplaceColorsCommand}" Icon="{StaticResource ReplaceColorsIcon}" /> <MenuItem Header="_Replace Colors" Command="{Binding ReplaceColorsCommand}" Icon="{StaticResource ReplaceColorsIcon}" />
<MenuItem Header="_Settings" Command="{Binding OpenSettingsWindowCommand}" /> <MenuItem Header="_Settings" Command="{Binding OpenSettingsWindowCommand}" />
</MenuItem> </MenuItem>