Filtration/Filtration/ViewModels/ItemFilterScriptViewModel.cs

581 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Data;
using System.Windows.Forms;
using Castle.Core.Internal;
using Filtration.Enums;
using Filtration.Models;
using Filtration.Services;
using Filtration.Translators;
using GalaSoft.MvvmLight.CommandWpf;
using Clipboard = System.Windows.Clipboard;
using MessageBox = System.Windows.MessageBox;
namespace Filtration.ViewModels
{
internal interface IItemFilterScriptViewModel : IDocument
{
ItemFilterScript Script { get; }
IItemFilterBlockViewModel SelectedBlockViewModel { get; set; }
IItemFilterBlockViewModel SectionBrowserSelectedBlockViewModel { get; set; }
IEnumerable<ItemFilterBlockGroup> BlockGroups { get; }
IEnumerable<IItemFilterBlockViewModel> ItemFilterSectionViewModels { get; }
Predicate<IItemFilterBlockViewModel> BlockFilterPredicate { get; set; }
bool IsDirty { get; }
string Description { get; set; }
string DisplayName { get; }
void Initialise(ItemFilterScript itemFilterScript, bool newScript);
void RemoveDirtyFlag();
void SaveScript();
void SaveScriptAs();
void Close();
void AddSection(IItemFilterBlockViewModel targetBlockViewModel);
void AddBlock(IItemFilterBlockViewModel targetBlockViewModel);
void CopyBlock(IItemFilterBlockViewModel targetBlockViewModel);
void PasteBlock(IItemFilterBlockViewModel targetBlockViewModel);
}
internal class ItemFilterScriptViewModel : PaneViewModel, IItemFilterScriptViewModel
{
private readonly IItemFilterBlockViewModelFactory _itemFilterBlockViewModelFactory;
private readonly IItemFilterBlockTranslator _blockTranslator;
private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel;
private readonly IItemFilterPersistenceService _persistenceService;
private bool _isDirty;
private IItemFilterBlockViewModel _selectedBlockViewModel;
private IItemFilterBlockViewModel _sectionBrowserSelectedBlockViewModel;
private readonly ObservableCollection<IItemFilterBlockViewModel> _itemFilterBlockViewModels;
private ICollectionView _itemFilterBlockViewModelsCollectionView;
private Predicate<IItemFilterBlockViewModel> _blockFilterPredicate;
public ItemFilterScriptViewModel(IItemFilterBlockViewModelFactory itemFilterBlockViewModelFactory,
IItemFilterBlockTranslator blockTranslator,
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel,
IItemFilterPersistenceService persistenceService)
{
_itemFilterBlockViewModelFactory = itemFilterBlockViewModelFactory;
_blockTranslator = blockTranslator;
_avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel;
_avalonDockWorkspaceViewModel.ActiveDocumentChanged += OnActiveDocumentChanged;
_persistenceService = persistenceService;
_itemFilterBlockViewModels = new ObservableCollection<IItemFilterBlockViewModel>();
ClearFilterCommand = new RelayCommand(OnClearFilterCommand, () => BlockFilterPredicate != null);
CloseCommand = new RelayCommand(OnCloseCommand);
DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => SelectedBlockViewModel != null);
MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => SelectedBlockViewModel != null);
MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => SelectedBlockViewModel != null);
MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => SelectedBlockViewModel != null);
MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => SelectedBlockViewModel != null);
AddBlockCommand = new RelayCommand(OnAddBlockCommand);
AddSectionCommand = new RelayCommand(OnAddSectionCommand, () => SelectedBlockViewModel != null);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => SelectedBlockViewModel != null);
PasteBlockCommand = new RelayCommand(OnPasteBlockCommand, () => SelectedBlockViewModel != null);
}
public RelayCommand ClearFilterCommand { get; private set; }
public RelayCommand CloseCommand { get; private set; }
public RelayCommand DeleteBlockCommand { get; private set; }
public RelayCommand MoveBlockToTopCommand { get; private set; }
public RelayCommand MoveBlockUpCommand { get; private set; }
public RelayCommand MoveBlockDownCommand { get; private set; }
public RelayCommand MoveBlockToBottomCommand { get; private set; }
public RelayCommand AddBlockCommand { get; private set; }
public RelayCommand AddSectionCommand { get; private set; }
public RelayCommand CopyBlockCommand { get; private set; }
public RelayCommand PasteBlockCommand { get; private set; }
public ObservableCollection<IItemFilterBlockViewModel> ItemFilterBlockViewModels
{
get
{
_itemFilterBlockViewModelsCollectionView =
CollectionViewSource.GetDefaultView(_itemFilterBlockViewModels);
if (BlockFilterPredicate != null)
{
_itemFilterBlockViewModelsCollectionView.Filter = BlockFilter;
}
else
{
_itemFilterBlockViewModelsCollectionView.Filter = null;
}
return _itemFilterBlockViewModels;
}
}
private bool BlockFilter(object item)
{
var blockViewModel = item as IItemFilterBlockViewModel;
return BlockFilterPredicate(blockViewModel);
}
public Predicate<IItemFilterBlockViewModel> BlockFilterPredicate
{
get { return _blockFilterPredicate; }
set
{
_blockFilterPredicate = value;
RaisePropertyChanged("ItemFilterBlockViewModels");
}
}
public ObservableCollection<IItemFilterBlockViewModel> DisplayedItemFilterBlockViewModels { get; private set; }
public IEnumerable<IItemFilterBlockViewModel> ItemFilterSectionViewModels
{
get { return ItemFilterBlockViewModels.Where(b => b.Block.GetType() == typeof (ItemFilterSection)); }
}
public bool IsScript
{
get { return true; }
}
public string Description
{
get { return Script.Description; }
set
{
Script.Description = value;
IsDirty = true;
RaisePropertyChanged();
}
}
public IItemFilterBlockViewModel SelectedBlockViewModel
{
get { return _selectedBlockViewModel; }
set
{
_selectedBlockViewModel = value;
RaisePropertyChanged();
}
}
public IItemFilterBlockViewModel SectionBrowserSelectedBlockViewModel
{
get { return _sectionBrowserSelectedBlockViewModel; }
set
{
_sectionBrowserSelectedBlockViewModel = value;
SelectedBlockViewModel = value;
RaisePropertyChanged();
}
}
public ItemFilterScript Script { get; private set; }
public IEnumerable<ItemFilterBlockGroup> BlockGroups
{
get { return Script.ItemFilterBlockGroups; }
}
public bool IsDirty
{
get { return _isDirty || HasDirtyChildren; }
set
{
if (_isDirty != value)
{
_isDirty = value;
if (_isDirty)
{
Title = Filename + "*";
}
else
{
Title = Filename;
}
}
}
}
public void RemoveDirtyFlag()
{
CleanChildren();
IsDirty = false;
RaisePropertyChanged("Filename");
RaisePropertyChanged("DisplayName");
}
public string DisplayName
{
get { return !string.IsNullOrEmpty(Filename) ? Filename : Description; }
}
public string Filename
{
get { return Path.GetFileName(Script.FilePath); }
}
public string Filepath
{
get { return Script.FilePath; }
}
private bool _filenameIsFake;
public void Initialise(ItemFilterScript itemFilterScript, bool newScript)
{
ItemFilterBlockViewModels.Clear();
Script = itemFilterScript;
foreach (var block in Script.ItemFilterBlocks)
{
var vm = _itemFilterBlockViewModelFactory.Create();
vm.Initialise(block, this);
ItemFilterBlockViewModels.Add(vm);
}
_filenameIsFake = newScript;
if (newScript)
{
Script.FilePath = "Untitled.filter";
}
Title = Filename;
ContentId = "testcontentid";
}
public void SaveScript()
{
if (!ValidateScript()) return;
if (_filenameIsFake)
{
SaveScriptAs();
return;
}
try
{
_persistenceService.SaveItemFilterScript(Script);
RemoveDirtyFlag();
}
catch (Exception e)
{
MessageBox.Show(@"Error saving filter file - " + e.Message, @"Save Error", MessageBoxButton.OK,
MessageBoxImage.Error);
}
}
public void SaveScriptAs()
{
if (!ValidateScript()) return;
var saveDialog = new SaveFileDialog
{
DefaultExt = ".filter",
Filter = @"Filter Files (*.filter)|*.filter|All Files (*.*)|*.*",
InitialDirectory = _persistenceService.ItemFilterScriptDirectory
};
var result = saveDialog.ShowDialog();
if (result != DialogResult.OK) return;
var previousFilePath = Script.FilePath;
try
{
Script.FilePath = saveDialog.FileName;
_persistenceService.SaveItemFilterScript(Script);
_filenameIsFake = false;
Title = Filename;
RemoveDirtyFlag();
}
catch (Exception e)
{
MessageBox.Show(@"Error saving filter file - " + e.Message, @"Save Error", MessageBoxButton.OK,
MessageBoxImage.Error);
Script.FilePath = previousFilePath;
}
}
private void OnActiveDocumentChanged(object sender, EventArgs e)
{
if (_avalonDockWorkspaceViewModel.ActiveScriptViewModel != this)
{
BlockFilterPredicate = null;
}
}
private bool HasDirtyChildren
{
get { return ItemFilterBlockViewModels.Any(vm => vm.IsDirty); }
}
private void CleanChildren()
{
foreach (var vm in ItemFilterBlockViewModels)
{
vm.IsDirty = false;
}
}
private bool ValidateScript()
{
var result = Script.Validate();
if (result.Count == 0) return true;
var failures = string.Empty;
// ReSharper disable once LoopCanBeConvertedToQuery
foreach (string failure in result)
{
failures += failure + Environment.NewLine;
}
var messageText = "The following script validation errors occurred:" + Environment.NewLine + failures;
MessageBox.Show(messageText, "Script Validation Failure", MessageBoxButton.OK, MessageBoxImage.Exclamation);
return false;
}
private void OnCloseCommand()
{
Close();
}
public void Close()
{
if (!IsDirty)
{
CloseScript();
}
else
{
var result = MessageBox.Show(@"Want to save your changes to this script?",
@"Filtration", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes:
{
SaveScript();
CloseScript();
break;
}
case MessageBoxResult.No:
{
CloseScript();
break;
}
case MessageBoxResult.Cancel:
{
return;
}
}
}
}
private void CloseScript()
{
_avalonDockWorkspaceViewModel.ActiveDocumentChanged -= OnActiveDocumentChanged;
_avalonDockWorkspaceViewModel.CloseDocument(this);
}
private void OnClearFilterCommand()
{
BlockFilterPredicate = null;
}
private void OnCopyBlockCommand()
{
CopyBlock(SelectedBlockViewModel);
}
public void CopyBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
Clipboard.SetText(_blockTranslator.TranslateItemFilterBlockToString(SelectedBlockViewModel.Block));
}
private void OnPasteBlockCommand()
{
PasteBlock(SelectedBlockViewModel);
}
public void PasteBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
var clipboardText = Clipboard.GetText();
if (clipboardText.IsNullOrEmpty()) return;
var translatedBlock = _blockTranslator.TranslateStringToItemFilterBlock(clipboardText);
if (translatedBlock == null) return;
var vm = _itemFilterBlockViewModelFactory.Create();
vm.Initialise(translatedBlock, this);
if (ItemFilterBlockViewModels.Count > 0)
{
Script.ItemFilterBlocks.Insert(Script.ItemFilterBlocks.IndexOf(targetBlockViewModel.Block) + 1, translatedBlock);
ItemFilterBlockViewModels.Insert(ItemFilterBlockViewModels.IndexOf(targetBlockViewModel) + 1, vm);
}
else
{
Script.ItemFilterBlocks.Add(translatedBlock);
ItemFilterBlockViewModels.Add(vm);
}
SelectedBlockViewModel = vm;
IsDirty = true;
}
private void OnMoveBlockToTopCommand()
{
MoveBlockToTop(SelectedBlockViewModel);
}
public void MoveBlockToTop(IItemFilterBlockViewModel targetBlockViewModel)
{
var currentIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModel);
if (currentIndex > 0)
{
var block = targetBlockViewModel.Block;
Script.ItemFilterBlocks.Remove(block);
Script.ItemFilterBlocks.Insert(0, block);
ItemFilterBlockViewModels.Move(currentIndex, 0);
IsDirty = true;
RaisePropertyChanged("ItemFilterSectionViewModels");
}
}
private void OnMoveBlockUpCommand()
{
MoveBlockUp(SelectedBlockViewModel);
}
public void MoveBlockUp(IItemFilterBlockViewModel targetBlockViewModel)
{
var currentIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModel);
if (currentIndex > 0)
{
var block = targetBlockViewModel.Block;
var blockPos = Script.ItemFilterBlocks.IndexOf(block);
Script.ItemFilterBlocks.RemoveAt(blockPos);
Script.ItemFilterBlocks.Insert(blockPos - 1, block);
ItemFilterBlockViewModels.Move(currentIndex, currentIndex - 1);
IsDirty = true;
RaisePropertyChanged("ItemFilterSectionViewModels");
}
}
private void OnMoveBlockDownCommand()
{
MoveBlockDown(SelectedBlockViewModel);
}
public void MoveBlockDown(IItemFilterBlockViewModel targetBlockViewModel)
{
var currentIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModel);
if (currentIndex < ItemFilterBlockViewModels.Count - 1)
{
var block = targetBlockViewModel.Block;
var blockPos = Script.ItemFilterBlocks.IndexOf(block);
Script.ItemFilterBlocks.RemoveAt(blockPos);
Script.ItemFilterBlocks.Insert(blockPos + 1, block);
ItemFilterBlockViewModels.Move(currentIndex, currentIndex + 1);
IsDirty = true;
RaisePropertyChanged("ItemFilterSectionViewModels");
}
}
private void OnMoveBlockToBottomCommand()
{
MoveBlockToBottom(SelectedBlockViewModel);
}
public void MoveBlockToBottom(IItemFilterBlockViewModel targetBlockViewModel)
{
var currentIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModel);
if (currentIndex < ItemFilterBlockViewModels.Count - 1)
{
var block = targetBlockViewModel.Block;
Script.ItemFilterBlocks.Remove(block);
Script.ItemFilterBlocks.Add(block);
ItemFilterBlockViewModels.Move(currentIndex, ItemFilterBlockViewModels.Count - 1);
IsDirty = true;
RaisePropertyChanged("ItemFilterSectionViewModels");
}
}
private void OnAddBlockCommand()
{
AddBlock(SelectedBlockViewModel);
}
public void AddBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
var vm = _itemFilterBlockViewModelFactory.Create();
var newBlock = new ItemFilterBlock();
vm.Initialise(newBlock, this);
if (targetBlockViewModel != null)
{
Script.ItemFilterBlocks.Insert(Script.ItemFilterBlocks.IndexOf(targetBlockViewModel.Block) + 1, newBlock);
ItemFilterBlockViewModels.Insert(ItemFilterBlockViewModels.IndexOf(targetBlockViewModel) + 1, vm);
}
else
{
Script.ItemFilterBlocks.Add(newBlock);
ItemFilterBlockViewModels.Add(vm);
}
SelectedBlockViewModel = vm;
IsDirty = true;
}
private void OnAddSectionCommand()
{
AddSection(SelectedBlockViewModel);
}
public void AddSection(IItemFilterBlockViewModel targetBlockViewModel)
{
var vm = _itemFilterBlockViewModelFactory.Create();
var newSection = new ItemFilterSection { Description = "New Section" };
vm.Initialise(newSection, this);
Script.ItemFilterBlocks.Insert(Script.ItemFilterBlocks.IndexOf(targetBlockViewModel.Block) + 1, newSection);
ItemFilterBlockViewModels.Insert(ItemFilterBlockViewModels.IndexOf(targetBlockViewModel) + 1, vm);
IsDirty = true;
SelectedBlockViewModel = vm;
RaisePropertyChanged("ItemFilterSectionViewModels");
}
private void OnDeleteBlockCommand()
{
DeleteBlock(SelectedBlockViewModel);
}
public void DeleteBlock(IItemFilterBlockViewModel targetBlockViewModel)
{
var result = MessageBox.Show("Are you sure you wish to delete this block?", "Delete Confirmation",
MessageBoxButton.YesNo, MessageBoxImage.Question);
if (result == MessageBoxResult.Yes)
{
Script.ItemFilterBlocks.Remove(targetBlockViewModel.Block);
ItemFilterBlockViewModels.Remove(targetBlockViewModel);
IsDirty = true;
}
SelectedBlockViewModel = null;
}
}
}