Refactored AvalonDock workspace into separate ViewModel

This commit is contained in:
Ben 2015-06-11 20:33:45 +01:00
parent f4eaba016f
commit 6d9edbda98
20 changed files with 456 additions and 436 deletions

View File

@ -25,9 +25,10 @@ namespace Filtration.Extensions
var hyperlink = sender as Hyperlink;
if ((bool)args.NewValue)
hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
else
hyperlink.RequestNavigate -= Hyperlink_RequestNavigate;
{
if (hyperlink != null) hyperlink.RequestNavigate += Hyperlink_RequestNavigate;
}
else if (hyperlink != null) hyperlink.RequestNavigate -= Hyperlink_RequestNavigate;
}
private static void Hyperlink_RequestNavigate(object sender, RequestNavigateEventArgs e)

View File

@ -60,6 +60,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.ObjectModel" />
<Reference Include="System.Windows.Controls.Input.Toolkit">
<HintPath>..\packages\WPFToolkit.3.5.50211.1\lib\System.Windows.Controls.Input.Toolkit.dll</HintPath>
</Reference>
@ -170,6 +171,7 @@
<DependentUpon>ItemPreviewControl.xaml</DependentUpon>
</Compile>
<Compile Include="Utilities\LineReader.cs" />
<Compile Include="ViewModels\AvalonDockWorkspaceViewModel.cs" />
<Compile Include="ViewModels\BlockGroupBrowserViewModel.cs" />
<Compile Include="ViewModels\FiltrationViewModelBase.cs" />
<Compile Include="ViewModels\IDocument.cs" />
@ -183,8 +185,11 @@
<Compile Include="ViewModels\StartPageViewModel.cs" />
<Compile Include="ViewModels\ToolViewModel.cs" />
<Compile Include="Views\AttachedProperties\SelectingItemAttachedProperty.cs" />
<Compile Include="Views\AvalonDock\AvalonDockWorkspaceView.xaml.cs">
<DependentUpon>AvalonDockWorkspaceView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\BindingProxy.cs" />
<Compile Include="Views\BlockGroupBrowserView.xaml.cs">
<Compile Include="Views\ToolPanes\BlockGroupBrowserView.xaml.cs">
<DependentUpon>BlockGroupBrowserView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\BlockTemplateSelector.cs" />
@ -212,7 +217,7 @@
<Compile Include="Views\ReplaceColorsWindow.xaml.cs">
<DependentUpon>ReplaceColorsWindow.xaml</DependentUpon>
</Compile>
<Compile Include="Views\SectionBrowserView.xaml.cs">
<Compile Include="Views\ToolPanes\SectionBrowserView.xaml.cs">
<DependentUpon>SectionBrowserView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\StartPageView.xaml.cs">
@ -227,7 +232,11 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\BlockGroupBrowserView.xaml">
<Page Include="Views\AvalonDock\AvalonDockWorkspaceView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ToolPanes\BlockGroupBrowserView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
@ -251,7 +260,7 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\SectionBrowserView.xaml">
<Page Include="Views\ToolPanes\SectionBrowserView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View File

@ -0,0 +1,130 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using GalaSoft.MvvmLight.Messaging;
namespace Filtration.ViewModels
{
internal interface IAvalonDockWorkspaceViewModel
{
event EventHandler ActiveDocumentChanged;
IDocument ActiveDocument { get; set; }
IItemFilterScriptViewModel ActiveScriptViewModel { get; }
void AddDocument(IDocument document);
void CloseDocument(IDocument document);
void SwitchActiveDocument(IDocument document);
}
internal class AvalonDockWorkspaceViewModel : FiltrationViewModelBase, IAvalonDockWorkspaceViewModel
{
private readonly ISectionBrowserViewModel _sectionBrowserViewModel;
private readonly IBlockGroupBrowserViewModel _blockGroupBrowserViewModel;
private IDocument _activeDocument;
private IItemFilterScriptViewModel _activeScriptViewModel;
private readonly ObservableCollection<IDocument> _openDocuments;
public AvalonDockWorkspaceViewModel(ISectionBrowserViewModel sectionBrowserViewModel,
IBlockGroupBrowserViewModel blockGroupBrowserViewModel,
IStartPageViewModel startPageViewModel)
{
_sectionBrowserViewModel = sectionBrowserViewModel;
_blockGroupBrowserViewModel = blockGroupBrowserViewModel;
_sectionBrowserViewModel.Initialise(this);
_blockGroupBrowserViewModel.Initialise(this);
_openDocuments = new ObservableCollection<IDocument> {startPageViewModel};
ActiveDocument = startPageViewModel;
}
public event EventHandler ActiveDocumentChanged;
public ObservableCollection<IDocument> OpenDocuments
{
get { return _openDocuments; }
}
public IDocument ActiveDocument
{
get { return _activeDocument; }
set
{
_activeDocument = value;
RaisePropertyChanged();
if (value.IsScript)
{
_activeScriptViewModel = (IItemFilterScriptViewModel) value;
}
else
{
_activeScriptViewModel = null;
}
if (ActiveDocumentChanged != null)
{
ActiveDocumentChanged(this, EventArgs.Empty);
}
Messenger.Default.Send(new NotificationMessage("ActiveDocumentChanged"));
}
}
public IItemFilterScriptViewModel ActiveScriptViewModel
{
get { return _activeScriptViewModel; }
}
private List<IToolViewModel> _tools;
public IEnumerable<IToolViewModel> Tools
{
get
{
if (_tools == null)
{
_tools = new List<IToolViewModel> { _sectionBrowserViewModel, _blockGroupBrowserViewModel };
}
return _tools;
}
}
public void AddDocument(IDocument document)
{
if (document.IsScript)
{
_activeScriptViewModel = (IItemFilterScriptViewModel)document;
}
OpenDocuments.Add(document);
ActiveDocument = document;
}
public void CloseDocument(IDocument document)
{
if (!OpenDocuments.Contains(document))
{
throw new ArgumentException("CloseDocument called with non-existant document");
}
if (document.IsScript)
{
_sectionBrowserViewModel.ClearDown();
}
OpenDocuments.Remove(document);
}
public void SwitchActiveDocument(IDocument document)
{
if (!OpenDocuments.Contains(document))
{
throw new ArgumentException("SwitchActiveDocument called with non-existant document");
}
ActiveDocument = document;
}
}
}

View File

@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Filtration.ViewModels
namespace Filtration.ViewModels
{
interface IDocument
{

View File

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using Filtration.Models;
using Filtration.Models.BlockItemBaseTypes;

View File

@ -1,43 +1,57 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using Castle.Core.Internal;
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
internal interface IItemFilterScriptViewModel : IDocument
{
ItemFilterScript Script { get; }
IItemFilterBlockViewModel SelectedBlockViewModel { get; set; }
IItemFilterBlockViewModel SectionBrowserSelectedBlockViewModel { get; set; }
IEnumerable<ItemFilterBlockGroup> BlockGroups { get; }
IEnumerable<IItemFilterBlockViewModel> ItemFilterSectionViewModels { get; }
bool IsDirty { get; }
string Description { get; set; }
string DisplayName { get; }
void Initialise(ItemFilterScript itemFilterScript);
IItemFilterBlockViewModel SelectedBlockViewModel { get; set; }
IItemFilterBlockViewModel SectionBrowserSelectedBlockViewModel { get; set; }
void RemoveDirtyFlag();
IEnumerable<ItemFilterBlockGroup> BlockGroups { get; }
IEnumerable<IItemFilterBlockViewModel> ItemFilterSectionViewModels { get; }
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, IDocument
internal class ItemFilterScriptViewModel : PaneViewModel, IItemFilterScriptViewModel
{
private readonly IItemFilterBlockViewModelFactory _itemFilterBlockViewModelFactory;
private readonly IItemFilterBlockTranslator _blockTranslator;
private readonly IMainWindowViewModel _mainWindowViewModel;
private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel;
private readonly IItemFilterPersistenceService _persistenceService;
private bool _isDirty;
private IItemFilterBlockViewModel _selectedBlockViewModel;
private IItemFilterBlockViewModel _sectionBrowserSelectedBlockViewModel;
public ItemFilterScriptViewModel(IItemFilterBlockViewModelFactory itemFilterBlockViewModelFactory, IItemFilterBlockTranslator blockTranslator, IMainWindowViewModel mainWindowViewModel)
public ItemFilterScriptViewModel(IItemFilterBlockViewModelFactory itemFilterBlockViewModelFactory,
IItemFilterBlockTranslator blockTranslator,
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel,
IItemFilterPersistenceService persistenceService)
{
CloseCommand = new RelayCommand(OnCloseCommand);
DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => SelectedBlockViewModel != null);
@ -51,15 +65,11 @@ namespace Filtration.ViewModels
PasteBlockCommand = new RelayCommand(OnPasteBlockCommand, () => SelectedBlockViewModel != null);
_itemFilterBlockViewModelFactory = itemFilterBlockViewModelFactory;
_blockTranslator = blockTranslator;
_mainWindowViewModel = mainWindowViewModel;
_avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel;
_persistenceService = persistenceService;
ItemFilterBlockViewModels = new ObservableCollection<IItemFilterBlockViewModel>();
}
public bool IsScript
{
get { return true; }
}
public RelayCommand CloseCommand { get; private set; }
public RelayCommand DeleteBlockCommand { get; private set; }
public RelayCommand MoveBlockToTopCommand { get; private set; }
@ -77,7 +87,12 @@ namespace Filtration.ViewModels
{
get { return ItemFilterBlockViewModels.Where(b => b.Block.GetType() == typeof (ItemFilterSection)); }
}
public bool IsScript
{
get { return true; }
}
public string Description
{
get { return Script.Description; }
@ -178,10 +193,114 @@ namespace Filtration.ViewModels
ContentId = "testcontentid";
}
public void SaveScript()
{
if (!ValidateScript()) return;
if (string.IsNullOrEmpty(Script.FilePath))
{
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);
RemoveDirtyFlag();
}
catch (Exception e)
{
MessageBox.Show(@"Error saving filter file - " + e.Message, @"Save Error", MessageBoxButton.OK,
MessageBoxImage.Error);
Script.FilePath = previousFilePath;
}
}
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;
}
public void Close()
{
if (!IsDirty)
{
_avalonDockWorkspaceViewModel.CloseDocument(this);
}
else
{
var result = MessageBox.Show(@"Want to save your changes to this script?",
@"Filtration", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
switch (result)
{
case MessageBoxResult.Yes:
{
SaveScript();
_avalonDockWorkspaceViewModel.CloseDocument(this);
break;
}
case MessageBoxResult.No:
{
_avalonDockWorkspaceViewModel.CloseDocument(this);
break;
}
case MessageBoxResult.Cancel:
{
return;
}
}
}
}
private void OnCloseCommand()
{
_mainWindowViewModel.Close(this);
Close();
}
private void OnCopyBlockCommand()
{
CopyBlock(SelectedBlockViewModel);

View File

@ -1,86 +1,83 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Forms;
using Castle.Core;
using Filtration.Models;
using Filtration.Services;
using Filtration.Translators;
using Filtration.Views;
using GalaSoft.MvvmLight.CommandWpf;
using GalaSoft.MvvmLight.Messaging;
using Clipboard = System.Windows.Clipboard;
using MessageBox = System.Windows.Forms.MessageBox;
using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
namespace Filtration.ViewModels
{
internal interface IMainWindowViewModel
{
IDocument ActiveDocument { get; set; }
IItemFilterScriptViewModel ActiveScriptViewModel { get; }
event EventHandler ActiveDocumentChanged;
void LoadScriptFromFile(string path);
RelayCommand OpenScriptCommand { get; }
RelayCommand NewScriptCommand { get; }
void Close(IDocument scriptToClose);
}
internal class MainWindowViewModel : FiltrationViewModelBase, IMainWindowViewModel
{
private ItemFilterScript _loadedScript;
private readonly IItemFilterScriptViewModelFactory _itemFilterScriptViewModelFactory;
private readonly IItemFilterPersistenceService _persistenceService;
private readonly IItemFilterScriptTranslator _itemFilterScriptTranslator;
private readonly IReplaceColorsViewModel _replaceColorsViewModel;
private readonly IAvalonDockWorkspaceViewModel _avalonDockWorkspaceViewModel;
private IDocument _activeDocument;
private IItemFilterScriptViewModel _activeScriptViewModel;
private readonly ObservableCollection<IDocument> _openDocuments;
private readonly ISectionBrowserViewModel _sectionBrowserViewModel;
private readonly IBlockGroupBrowserViewModel _blockGroupBrowserViewModel;
private readonly IStartPageViewModel _startPageViewModel;
public MainWindowViewModel(IItemFilterScriptViewModelFactory itemFilterScriptViewModelFactory,
IItemFilterPersistenceService persistenceService,
IItemFilterScriptTranslator itemFilterScriptTranslator,
IReplaceColorsViewModel replaceColorsViewModel,
ISectionBrowserViewModel sectionBrowserViewModel,
IBlockGroupBrowserViewModel blockGroupBrowserViewModel,
IStartPageViewModel startPageViewModel)
IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel)
{
_itemFilterScriptViewModelFactory = itemFilterScriptViewModelFactory;
_persistenceService = persistenceService;
_itemFilterScriptTranslator = itemFilterScriptTranslator;
_replaceColorsViewModel = replaceColorsViewModel;
_sectionBrowserViewModel = sectionBrowserViewModel;
_blockGroupBrowserViewModel = blockGroupBrowserViewModel;
_startPageViewModel = startPageViewModel;
_avalonDockWorkspaceViewModel = avalonDockWorkspaceViewModel;
_sectionBrowserViewModel.Initialise(this);
_blockGroupBrowserViewModel.Initialise(this);
_startPageViewModel.Initialise(this);
_openDocuments = new ObservableCollection<IDocument>();
OpenAboutWindowCommand = new RelayCommand(OnOpenAboutWindowCommand);
OpenScriptCommand = new RelayCommand(OnOpenScriptCommand);
SaveScriptCommand = new RelayCommand(OnSaveScriptCommand, () => ActiveDocument != null && ActiveDocument.IsScript);
SaveScriptAsCommand = new RelayCommand(OnSaveScriptAsCommand, () => ActiveDocument != null && ActiveDocument.IsScript);
CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, () => ActiveDocument != null && ActiveDocument.IsScript);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocument != null && ActiveDocument.IsScript && ((IItemFilterScriptViewModel)ActiveDocument).SelectedBlockViewModel != null);
PasteCommand = new RelayCommand(OnPasteCommand, () => ActiveDocument != null && ActiveDocument.IsScript && ((IItemFilterScriptViewModel)ActiveDocument).SelectedBlockViewModel != null);
SaveScriptCommand = new RelayCommand(OnSaveScriptCommand, ActiveDocumentIsScript);
SaveScriptAsCommand = new RelayCommand(OnSaveScriptAsCommand, ActiveDocumentIsScript);
CopyScriptCommand = new RelayCommand(OnCopyScriptCommand, ActiveDocumentIsScript);
CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => ActiveDocumentIsScript() && (_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel != null));
PasteCommand = new RelayCommand(OnPasteCommand, () => ActiveDocumentIsScript() && (_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel != null));
NewScriptCommand = new RelayCommand(OnNewScriptCommand);
CloseScriptCommand = new RelayCommand<IDocument>(OnCloseScriptCommand, v => ActiveDocument != null && ActiveDocument.IsScript);
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, () => ActiveDocument != null && ActiveDocument.IsScript);
CloseScriptCommand = new RelayCommand(OnCloseScriptCommand, ActiveDocumentIsScript);
ReplaceColorsCommand = new RelayCommand(OnReplaceColorsCommand, ActiveDocumentIsScript);
//LoadScriptFromFile("C:\\ThioleLootFilter.txt");
SetItemFilterScriptDirectory();
_openDocuments.Add(_startPageViewModel);
ActiveDocument = startPageViewModel;
Messenger.Default.Register<NotificationMessage>(this, message =>
{
switch (message.Notification)
{
case "ActiveDocumentChanged":
{
_activeDocument = _avalonDockWorkspaceViewModel.ActiveDocument;
SaveScriptCommand.RaiseCanExecuteChanged();
SaveScriptAsCommand.RaiseCanExecuteChanged();
CopyScriptCommand.RaiseCanExecuteChanged();
CopyBlockCommand.RaiseCanExecuteChanged();
PasteCommand.RaiseCanExecuteChanged();
NewScriptCommand.RaiseCanExecuteChanged();
CloseScriptCommand.RaiseCanExecuteChanged();
ReplaceColorsCommand.RaiseCanExecuteChanged();
break;
}
}
});
}
public RelayCommand OpenScriptCommand { get; private set; }
@ -90,28 +87,13 @@ namespace Filtration.ViewModels
public RelayCommand PasteCommand { get; private set; }
public RelayCommand CopyScriptCommand { get; private set; }
public RelayCommand NewScriptCommand { get; private set; }
public RelayCommand<IDocument> CloseScriptCommand { get; private set; }
public RelayCommand CloseScriptCommand { get; private set; }
public RelayCommand OpenAboutWindowCommand { get; private set; }
public RelayCommand ReplaceColorsCommand { get; private set; }
public ObservableCollection<IDocument> OpenDocuments
public IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel
{
get { return _openDocuments; }
}
private List<IToolViewModel> _tools;
public IEnumerable<IToolViewModel> Tools
{
get
{
if (_tools == null)
{
_tools = new List<IToolViewModel> {_sectionBrowserViewModel, _blockGroupBrowserViewModel};
}
return _tools;
}
get { return _avalonDockWorkspaceViewModel; }
}
public string WindowTitle
@ -124,43 +106,11 @@ namespace Filtration.ViewModels
}
}
public IDocument ActiveDocument
private bool ActiveDocumentIsScript()
{
get { return _activeDocument; }
set
{
_activeDocument = value;
RaisePropertyChanged();
if (value.IsScript)
{
_activeScriptViewModel = (IItemFilterScriptViewModel)value;
}
if (ActiveDocumentChanged != null)
{
ActiveDocumentChanged(this, EventArgs.Empty);
}
RaisePropertyChanged("NoScriptsOpen");
SaveScriptCommand.RaiseCanExecuteChanged();
SaveScriptAsCommand.RaiseCanExecuteChanged();
}
}
public IItemFilterScriptViewModel ActiveScriptViewModel
{
get { return _activeScriptViewModel; }
return _activeDocument != null && _activeDocument.IsScript;
}
public event EventHandler ActiveDocumentChanged;
public bool NoScriptsOpen
{
get { return _activeDocument == null; }
}
private void OnOpenAboutWindowCommand()
{
var aboutWindow = new AboutWindow();
@ -182,9 +132,10 @@ namespace Filtration.ViewModels
public void LoadScriptFromFile(string path)
{
var loadedScript = _persistenceService.LoadItemFilterScript(path);
try
{
_loadedScript = _persistenceService.LoadItemFilterScript(path);
}
catch (Exception e)
{
@ -194,10 +145,8 @@ namespace Filtration.ViewModels
}
var newViewModel = _itemFilterScriptViewModelFactory.Create();
newViewModel.Initialise(_loadedScript);
_activeScriptViewModel = newViewModel;
OpenDocuments.Add((IDocument)newViewModel);
ActiveDocument = (IDocument)newViewModel;
newViewModel.Initialise(loadedScript);
_avalonDockWorkspaceViewModel.AddDocument(newViewModel);
}
private void SetItemFilterScriptDirectory()
@ -225,96 +174,34 @@ namespace Filtration.ViewModels
private void OnSaveScriptCommand()
{
if (!ValidateScript()) return;
if (string.IsNullOrEmpty(_activeScriptViewModel.Script.FilePath))
{
OnSaveScriptAsCommand();
return;
}
try
{
_persistenceService.SaveItemFilterScript(_activeScriptViewModel.Script);
_activeScriptViewModel.RemoveDirtyFlag();
}
catch (Exception e)
{
MessageBox.Show(@"Error saving filter file - " + e.Message, @"Save Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SaveScript();
}
private void OnSaveScriptAsCommand()
{
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 = _activeScriptViewModel.Script.FilePath;
try
{
_activeScriptViewModel.Script.FilePath = saveDialog.FileName;
_persistenceService.SaveItemFilterScript(_activeScriptViewModel.Script);
_activeScriptViewModel.RemoveDirtyFlag();
}
catch (Exception e)
{
MessageBox.Show(@"Error saving filter file - " + e.Message, @"Save Error", MessageBoxButtons.OK,
MessageBoxIcon.Error);
_activeScriptViewModel.Script.FilePath = previousFilePath;
}
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SaveScriptAs();
}
private void OnReplaceColorsCommand()
{
_replaceColorsViewModel.Initialise(_activeScriptViewModel.Script);
_replaceColorsViewModel.Initialise(_avalonDockWorkspaceViewModel.ActiveScriptViewModel.Script);
var replaceColorsWindow = new ReplaceColorsWindow {DataContext = _replaceColorsViewModel};
replaceColorsWindow.ShowDialog();
}
private bool ValidateScript()
{
var result = _activeScriptViewModel.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;
}
MessageBox.Show(@"The following script validation errors occurred:" + Environment.NewLine + failures,
@"Script Validation Failure", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
private void OnCopyScriptCommand()
{
Clipboard.SetText(_itemFilterScriptTranslator.TranslateItemFilterScriptToString(_activeScriptViewModel.Script));
Clipboard.SetText(_itemFilterScriptTranslator.TranslateItemFilterScriptToString(_avalonDockWorkspaceViewModel.ActiveScriptViewModel.Script));
}
private void OnCopyBlockCommand()
{
_activeScriptViewModel.CopyBlock(_activeScriptViewModel.SelectedBlockViewModel);
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.CopyBlock(_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel);
}
private void OnPasteCommand()
{
_activeScriptViewModel.PasteBlock(_activeScriptViewModel.SelectedBlockViewModel);
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.PasteBlock(_avalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel);
}
private void OnNewScriptCommand()
@ -323,66 +210,12 @@ namespace Filtration.ViewModels
var newViewModel = _itemFilterScriptViewModelFactory.Create();
newViewModel.Initialise(newScript);
newViewModel.Description = "New Script";
_activeScriptViewModel = newViewModel;
OpenDocuments.Add((IDocument)newViewModel);
ActiveDocument = (IDocument)newViewModel;
_avalonDockWorkspaceViewModel.AddDocument(newViewModel);
}
private void OnCloseScriptCommand(IDocument documentToClose)
private void OnCloseScriptCommand()
{
Close(documentToClose);
_avalonDockWorkspaceViewModel.ActiveScriptViewModel.Close();
}
public void Close(IDocument documentToClose)
{
ActiveDocument = documentToClose;
if (ActiveDocument.IsScript)
{
if (!_activeScriptViewModel.IsDirty)
{
RemoveDocument(ActiveDocument);
}
else
{
var result = MessageBox.Show(@"Want to save your changes to this script?",
@"Filtration", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
switch (result)
{
case DialogResult.Yes:
{
OnSaveScriptCommand();
RemoveDocument(ActiveDocument);
break;
}
case DialogResult.No:
{
RemoveDocument(ActiveDocument);
break;
}
case DialogResult.Cancel:
{
return;
}
}
}
}
else
{
RemoveDocument(documentToClose);
}
}
private void RemoveDocument(IDocument documentToRemove)
{
if (documentToRemove.IsScript)
{
_sectionBrowserViewModel.ClearDown();
}
OpenDocuments.Remove(documentToRemove);
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Filtration.ViewModels
@ -27,12 +26,6 @@ namespace Filtration.ViewModels
public const string ToolContentId = "SectionBrowserTool";
public override void Initialise(IMainWindowViewModel mainWindowViewModel)
{
base.Initialise(mainWindowViewModel);
MainWindowViewModel.ActiveDocumentChanged += OnActiveDocumentChanged;
}
public IEnumerable<IItemFilterBlockViewModel> SectionBlockViewModels
{
get { return _sectionBlockViewModels; }
@ -49,19 +42,19 @@ namespace Filtration.ViewModels
set
{
_selectedSectionBlockViewModel = value;
if (MainWindowViewModel.ActiveDocument.IsScript)
if (AvalonDockWorkspaceViewModel.ActiveDocument.IsScript)
{
MainWindowViewModel.ActiveScriptViewModel.SectionBrowserSelectedBlockViewModel = value;
AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SectionBrowserSelectedBlockViewModel = value;
}
RaisePropertyChanged();
}
}
private void OnActiveDocumentChanged(object sender, EventArgs e)
protected override void OnActiveDocumentChanged(object sender, EventArgs e)
{
if (MainWindowViewModel.ActiveScriptViewModel != null && MainWindowViewModel.ActiveDocument.IsScript)
if (AvalonDockWorkspaceViewModel.ActiveScriptViewModel != null && AvalonDockWorkspaceViewModel.ActiveDocument.IsScript)
{
SectionBlockViewModels = MainWindowViewModel.ActiveScriptViewModel.ItemFilterSectionViewModels;
SectionBlockViewModels = AvalonDockWorkspaceViewModel.ActiveScriptViewModel.ItemFilterSectionViewModels;
}
else
{

View File

@ -4,25 +4,19 @@ namespace Filtration.ViewModels
{
internal interface IStartPageViewModel : IDocument
{
void Initialise(IMainWindowViewModel mainWindowViewModel);
}
internal class StartPageViewModel : PaneViewModel, IStartPageViewModel
{
private IMainWindowViewModel _mainWindowViewModel;
public StartPageViewModel()
{
Title = "Start Page";
}
public void Initialise(IMainWindowViewModel mainWindowViewModel)
{
_mainWindowViewModel = mainWindowViewModel;
}
public RelayCommand OpenScriptCommand { get { return _mainWindowViewModel.OpenScriptCommand; } }
public RelayCommand NewScriptCommand { get { return _mainWindowViewModel.NewScriptCommand; } }
// TODO: Replace with MVVMLight ViewModel Messages
public RelayCommand OpenScriptCommand { get { return null; } }
public RelayCommand NewScriptCommand { get { return null; } }
public bool IsScript { get { return false; } }
}

View File

@ -1,8 +1,10 @@
namespace Filtration.ViewModels
using System;
namespace Filtration.ViewModels
{
internal interface IToolViewModel
{
void Initialise(IMainWindowViewModel mainWindowViewModel);
void Initialise(IAvalonDockWorkspaceViewModel avalonDockWorkspaceViewModel);
}
class ToolViewModel : PaneViewModel, IToolViewModel
@ -29,11 +31,16 @@
}
}
protected IMainWindowViewModel MainWindowViewModel { get; private set; }
protected IAvalonDockWorkspaceViewModel AvalonDockWorkspaceViewModel{ get; private set; }
public virtual void Initialise(IMainWindowViewModel mainWindowViewModel)
protected virtual void OnActiveDocumentChanged(object sender, EventArgs e)
{
MainWindowViewModel = mainWindowViewModel;
}
public virtual void Initialise(IAvalonDockWorkspaceViewModel avalonDockWorkSpaceViewModel)
{
AvalonDockWorkspaceViewModel = avalonDockWorkSpaceViewModel;
avalonDockWorkSpaceViewModel.ActiveDocumentChanged += OnActiveDocumentChanged;
}
}
}

View File

@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using Filtration.ViewModels;

View File

@ -0,0 +1,87 @@
<UserControl x:Class="Filtration.Views.AvalonDock.AvalonDockWorkspaceView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:Filtration.ViewModels"
xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock"
xmlns:views="clr-namespace:Filtration.Views"
xmlns:toolPanes="clr-namespace:Filtration.Views.ToolPanes"
xmlns:xcad="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:converters="clr-namespace:Filtration.Converters"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:AvalonDockWorkspaceViewModel}"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:ActiveDocumentConverter x:Key="ActiveDocumentConverter" />
</UserControl.Resources>
<Grid>
<!-- ReSharper disable once InconsistentNaming -->
<xcad:DockingManager x:Name="dockManager"
AnchorablesSource="{Binding Tools}"
AllowMixedOrientation="True"
DocumentsSource="{Binding OpenDocuments}"
ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}">
<xcad:DockingManager.LayoutItemTemplateSelector>
<viewsAvalonDock:PanesTemplateSelector>
<viewsAvalonDock:PanesTemplateSelector.ItemFilterScriptTemplate>
<DataTemplate>
<views:ItemFilterScriptView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.ItemFilterScriptTemplate>
<viewsAvalonDock:PanesTemplateSelector.BlockGroupBrowserTemplate>
<DataTemplate>
<toolPanes:BlockGroupBrowserView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.BlockGroupBrowserTemplate>
<viewsAvalonDock:PanesTemplateSelector.SectionBrowserTemplate>
<DataTemplate>
<toolPanes:SectionBrowserView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.SectionBrowserTemplate>
<viewsAvalonDock:PanesTemplateSelector.StartPageTemplate>
<DataTemplate>
<views:StartPageView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.StartPageTemplate>
</viewsAvalonDock:PanesTemplateSelector>
</xcad:DockingManager.LayoutItemTemplateSelector>
<xcad:DockingManager.LayoutItemContainerStyleSelector>
<viewsAvalonDock:PanesStyleSelector>
<viewsAvalonDock:PanesStyleSelector.ToolStyle>
<Style TargetType="{x:Type xcad:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
</Style>
</viewsAvalonDock:PanesStyleSelector.ToolStyle>
<viewsAvalonDock:PanesStyleSelector.DocumentStyle>
<Style TargetType="{x:Type xcad:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<!--<Setter Property="ToolTip" Value="{Binding Model.FilePath}"/> -->
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
</Style>
</viewsAvalonDock:PanesStyleSelector.DocumentStyle>
</viewsAvalonDock:PanesStyleSelector>
</xcad:DockingManager.LayoutItemContainerStyleSelector>
<xcad:DockingManager.LayoutUpdateStrategy>
<viewsAvalonDock:LayoutInitializer></viewsAvalonDock:LayoutInitializer>
</xcad:DockingManager.LayoutUpdateStrategy>
<xcad:LayoutRoot>
<xcad:LayoutPanel Orientation="Horizontal">
<xcad:LayoutAnchorablePane Name="SectionBrowserPane" DockWidth="150" />
<xcad:LayoutDocumentPane/>
<xcad:LayoutAnchorablePane Name="BlockGroupBrowserPane" DockWidth="150" />
</xcad:LayoutPanel>
</xcad:LayoutRoot>
</xcad:DockingManager>
</Grid>
</UserControl>

View File

@ -1,5 +1,4 @@
using System.Linq;
using Xceed.Wpf.AvalonDock.Layout;
using Xceed.Wpf.AvalonDock.Layout;
namespace Filtration.Views.AvalonDock
{

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Filtration.Views
{
/// <summary>
/// Interaction logic for BlockGroupBrowserView.xaml
/// </summary>
public partial class BlockGroupBrowserView : UserControl
{
public BlockGroupBrowserView()
{
InitializeComponent();
}
}
}

View File

@ -6,18 +6,10 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
xmlns:viewModels="clr-namespace:Filtration.ViewModels"
xmlns:avalonDock="http://schemas.xceed.com/wpf/xaml/avalondock"
xmlns:converters="clr-namespace:Filtration.Converters"
xmlns:views="clr-namespace:Filtration.Views"
xmlns:viewsAvalonDock="clr-namespace:Filtration.Views.AvalonDock"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:MainWindowViewModel}"
Title="{Binding WindowTitle}" Height="707" Width="930" BorderThickness="1" BorderBrush="Black">
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<converters:ActiveDocumentConverter x:Key="ActiveDocumentConverter" />
</Window.Resources>
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
@ -25,7 +17,7 @@
<MenuItem Header="_Open Script" Command="{Binding OpenScriptCommand}" Icon="{StaticResource OpenIcon}"/>
<MenuItem Header="_Save Script" Command="{Binding SaveScriptCommand}" Icon="{StaticResource SaveIcon}"/>
<MenuItem Header="Save Script _As" Command="{Binding SaveScriptAsCommand}" Icon="{StaticResource SaveIcon}"/>
<MenuItem Header="_Close Script" Command="{Binding CloseScriptCommand}" CommandParameter="{Binding ActiveDocument}"/>
<MenuItem Header="_Close Script" Command="{Binding CloseScriptCommand}" />
<MenuItem Header="E_xit"/>
</MenuItem>
<MenuItem Header="_Edit">
@ -49,71 +41,7 @@
</ToolBar>
</ToolBarTray>
<Grid>
<avalonDock:DockingManager x:Name="dockManager"
AnchorablesSource="{Binding Tools}"
AllowMixedOrientation="True"
DocumentsSource="{Binding OpenDocuments}"
ActiveContent="{Binding ActiveDocument, Mode=TwoWay, Converter={StaticResource ActiveDocumentConverter}}">
<avalonDock:DockingManager.LayoutItemTemplateSelector>
<viewsAvalonDock:PanesTemplateSelector>
<viewsAvalonDock:PanesTemplateSelector.ItemFilterScriptTemplate>
<DataTemplate>
<views:ItemFilterScriptView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.ItemFilterScriptTemplate>
<viewsAvalonDock:PanesTemplateSelector.BlockGroupBrowserTemplate>
<DataTemplate>
<views:BlockGroupBrowserView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.BlockGroupBrowserTemplate>
<viewsAvalonDock:PanesTemplateSelector.SectionBrowserTemplate>
<DataTemplate>
<views:SectionBrowserView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.SectionBrowserTemplate>
<viewsAvalonDock:PanesTemplateSelector.StartPageTemplate>
<DataTemplate>
<views:StartPageView DataContext="{Binding}" />
</DataTemplate>
</viewsAvalonDock:PanesTemplateSelector.StartPageTemplate>
</viewsAvalonDock:PanesTemplateSelector>
</avalonDock:DockingManager.LayoutItemTemplateSelector>
<avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<viewsAvalonDock:PanesStyleSelector>
<viewsAvalonDock:PanesStyleSelector.ToolStyle>
<Style TargetType="{x:Type avalonDock:LayoutAnchorableItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
<Setter Property="Visibility" Value="{Binding Model.IsVisible, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}, ConverterParameter={x:Static Visibility.Hidden}}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
<Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
<Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
</Style>
</viewsAvalonDock:PanesStyleSelector.ToolStyle>
<viewsAvalonDock:PanesStyleSelector.DocumentStyle>
<Style TargetType="{x:Type avalonDock:LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<!--<Setter Property="ToolTip" Value="{Binding Model.FilePath}"/> -->
<Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
<Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
</Style>
</viewsAvalonDock:PanesStyleSelector.DocumentStyle>
</viewsAvalonDock:PanesStyleSelector>
</avalonDock:DockingManager.LayoutItemContainerStyleSelector>
<avalonDock:DockingManager.LayoutUpdateStrategy>
<viewsAvalonDock:LayoutInitializer></viewsAvalonDock:LayoutInitializer>
</avalonDock:DockingManager.LayoutUpdateStrategy>
<avalonDock:LayoutRoot>
<avalonDock:LayoutPanel Orientation="Horizontal">
<avalonDock:LayoutAnchorablePane Name="SectionBrowserPane" DockWidth="150" />
<avalonDock:LayoutDocumentPane/>
<avalonDock:LayoutAnchorablePane Name="BlockGroupBrowserPane" DockWidth="150" />
</avalonDock:LayoutPanel>
</avalonDock:LayoutRoot>
</avalonDock:DockingManager>
<viewsAvalonDock:AvalonDockWorkspaceView DataContext="{Binding AvalonDockWorkspaceViewModel}" />
</Grid>
</DockPanel>
</controls:MetroWindow>

View File

@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Filtration.Views
{
/// <summary>
/// Interaction logic for SectionBrowserView.xaml
/// </summary>
public partial class SectionBrowserView : UserControl
{
public SectionBrowserView()
{
InitializeComponent();
}
}
}

View File

@ -1,24 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Filtration.Views
namespace Filtration.Views
{
/// <summary>
/// Interaction logic for StartPageView.xaml
/// </summary>
public partial class StartPageView : UserControl
public partial class StartPageView
{
public StartPageView()
{

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Filtration.Views.BlockGroupBrowserView"
<UserControl x:Class="Filtration.Views.ToolPanes.BlockGroupBrowserView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View File

@ -1,4 +1,4 @@
<UserControl x:Class="Filtration.Views.SectionBrowserView"
<UserControl x:Class="Filtration.Views.ToolPanes.SectionBrowserView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

View File

@ -15,6 +15,11 @@ namespace Filtration.WindsorInstallers
.ImplementedBy<MainWindowViewModel>()
.LifeStyle.Singleton);
container.Register(
Component.For<IAvalonDockWorkspaceViewModel>()
.ImplementedBy<AvalonDockWorkspaceViewModel>()
.LifeStyle.Singleton);
container.Register(
Component.For<IItemFilterBlockViewModel>()
.ImplementedBy<ItemFilterBlockViewModel>()