Implemented script-level undo/redo (currently hidden in UI)

This commit is contained in:
Ben Wallis
2017-12-07 18:14:47 +00:00
parent fee2a4dd99
commit d84b17ced3
36 changed files with 888 additions and 384 deletions

View File

@@ -28,8 +28,7 @@ namespace Filtration.ObjectModel.Commands
public void ExecuteCommand(ICommand command)
{
command.Execute();
var undoableCommand = command as IUndoableCommand;
if (undoableCommand != null)
if (command is IUndoableCommand undoableCommand)
{
_undoCommandStack.Push(undoableCommand);
_redoCommandStack.Clear();

View File

@@ -0,0 +1,37 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class AddBlockCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _addAfterItemFilterBlock;
private IItemFilterBlock _newItemFilterBlock;
public AddBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase addAfterItemFilterBlock)
{
_itemFilterScript = itemFilterScript;
_addAfterItemFilterBlock = addAfterItemFilterBlock;
}
public void Execute()
{
_newItemFilterBlock = new ItemFilterBlock(_itemFilterScript);
if (_addAfterItemFilterBlock != null)
{
_itemFilterScript.ItemFilterBlocks.Insert(_itemFilterScript.ItemFilterBlocks.IndexOf(_addAfterItemFilterBlock) + 1, _newItemFilterBlock);
}
else
{
_itemFilterScript.ItemFilterBlocks.Add(_newItemFilterBlock);
}
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_newItemFilterBlock);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class AddCommentBlockCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _addAfterItemFilterBlock;
private IItemFilterCommentBlock _newItemFilterBlock;
public AddCommentBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase addAfterItemFilterBlock)
{
_itemFilterScript = itemFilterScript;
_addAfterItemFilterBlock = addAfterItemFilterBlock;
}
public void Execute()
{
_newItemFilterBlock = new ItemFilterCommentBlock(_itemFilterScript);
if (_addAfterItemFilterBlock != null)
{
_itemFilterScript.ItemFilterBlocks.Insert(_itemFilterScript.ItemFilterBlocks.IndexOf(_addAfterItemFilterBlock) + 1, _newItemFilterBlock);
}
else
{
_itemFilterScript.ItemFilterBlocks.Add(_newItemFilterBlock);
}
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_newItemFilterBlock);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,39 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class MoveBlockDownCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _blockToMove;
private int _indexMovedFrom;
public MoveBlockDownCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase blockToMove)
{
_itemFilterScript = itemFilterScript;
_blockToMove = blockToMove;
}
public void Execute()
{
_indexMovedFrom = _itemFilterScript.ItemFilterBlocks.IndexOf(_blockToMove);
if (_indexMovedFrom >= _itemFilterScript.ItemFilterBlocks.Count)
{
throw new InvalidOperationException("Cannot move the bottom block down");
}
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom + 1, _blockToMove);
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom, _blockToMove);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,30 @@
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class MoveBlockToBottomCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _blockToMove;
private int _indexMovedFrom;
public MoveBlockToBottomCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase blockToMove)
{
_itemFilterScript = itemFilterScript;
_blockToMove = blockToMove;
}
public void Execute()
{
_indexMovedFrom = _itemFilterScript.ItemFilterBlocks.IndexOf(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Add(_blockToMove);
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom, _blockToMove);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,30 @@
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class MoveBlockToTopCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _blockToMove;
private int _indexMovedFrom;
public MoveBlockToTopCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase blockToMove)
{
_itemFilterScript = itemFilterScript;
_blockToMove = blockToMove;
}
public void Execute()
{
_indexMovedFrom = _itemFilterScript.ItemFilterBlocks.IndexOf(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(0, _blockToMove);
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom, _blockToMove);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,39 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class MoveBlockUpCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _blockToMove;
private int _indexMovedFrom;
public MoveBlockUpCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase blockToMove)
{
_itemFilterScript = itemFilterScript;
_blockToMove = blockToMove;
}
public void Execute()
{
_indexMovedFrom = _itemFilterScript.ItemFilterBlocks.IndexOf(_blockToMove);
if (_indexMovedFrom <= 0)
{
throw new InvalidOperationException("Cannot move the top block up");
}
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom-1, _blockToMove);
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_blockToMove);
_itemFilterScript.ItemFilterBlocks.Insert(_indexMovedFrom, _blockToMove);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,37 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class PasteBlockCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly IItemFilterBlockBase _pastedItemFilterBlock;
private readonly IItemFilterBlockBase _addAfterItemFilterBlock;
public PasteBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase pastedItemFilterBlock, IItemFilterBlockBase addAfterItemFilterBlock)
{
_itemFilterScript = itemFilterScript;
_pastedItemFilterBlock = pastedItemFilterBlock;
_addAfterItemFilterBlock = addAfterItemFilterBlock;
}
public void Execute()
{
if (_addAfterItemFilterBlock != null)
{
_itemFilterScript.ItemFilterBlocks.Insert(_itemFilterScript.ItemFilterBlocks.IndexOf(_addAfterItemFilterBlock) + 1, _pastedItemFilterBlock);
}
else
{
_itemFilterScript.ItemFilterBlocks.Add(_pastedItemFilterBlock);
}
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Remove(_pastedItemFilterBlock);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,29 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class RemoveBlockCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private IItemFilterBlockBase _removedItemFilterBlock;
private int _indexRemovedFrom;
public RemoveBlockCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase itemFilterBlockBase)
{
_itemFilterScript = itemFilterScript;
_removedItemFilterBlock = itemFilterBlockBase;
}
public void Execute()
{
_indexRemovedFrom = _itemFilterScript.ItemFilterBlocks.IndexOf(_removedItemFilterBlock);
_itemFilterScript.ItemFilterBlocks.Remove(_removedItemFilterBlock);
}
public void Undo()
{
_itemFilterScript.ItemFilterBlocks.Insert(_indexRemovedFrom, _removedItemFilterBlock);
}
public void Redo() => Execute();
}
}

View File

@@ -0,0 +1,30 @@
using System;
namespace Filtration.ObjectModel.Commands.ItemFilterScript
{
public class SetScriptDescriptionCommand : IUndoableCommand
{
private readonly IItemFilterScript _itemFilterScript;
private readonly string _newDescription;
private string _oldDescription;
public SetScriptDescriptionCommand(IItemFilterScript itemFilterScript, string newDescription)
{
_itemFilterScript = itemFilterScript;
_newDescription = newDescription;
}
public void Execute()
{
_oldDescription = _itemFilterScript.Description;
_itemFilterScript.Description = _newDescription;
}
public void Undo()
{
_itemFilterScript.Description = _oldDescription;
}
public void Redo() => Execute();
}
}

View File

@@ -76,6 +76,15 @@
<Compile Include="BlockItemTypes\WidthBlockItem.cs" />
<Compile Include="Commands\CommandManager.cs" />
<Compile Include="Commands\ICommand.cs" />
<Compile Include="Commands\ItemFilterScript\PasteBlockCommand.cs" />
<Compile Include="Commands\ItemFilterScript\MoveBlockToBottomCommand.cs" />
<Compile Include="Commands\ItemFilterScript\AddCommentBlockCommand.cs" />
<Compile Include="Commands\ItemFilterScript\MoveBlockDownCommand.cs" />
<Compile Include="Commands\ItemFilterScript\MoveBlockUpCommand.cs" />
<Compile Include="Commands\ItemFilterScript\MoveBlockToTopCommand.cs" />
<Compile Include="Commands\ItemFilterScript\SetScriptDescriptionCommand.cs" />
<Compile Include="Commands\ItemFilterScript\RemoveBlockCommand.cs" />
<Compile Include="Commands\ItemFilterScript\AddBlockCommand.cs" />
<Compile Include="Commands\IUndoableCommand.cs" />
<Compile Include="Enums\BlockAction.cs" />
<Compile Include="Enums\BlockItemType.cs" />

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Windows.Media;
using Filtration.ObjectModel.BlockItemBaseTypes;
using Filtration.ObjectModel.BlockItemTypes;
using Filtration.ObjectModel.Commands;
using Filtration.ObjectModel.Enums;
using Filtration.ObjectModel.Extensions;
@@ -29,9 +30,20 @@ namespace Filtration.ObjectModel
{
}
public class ItemFilterBlockBase : IItemFilterBlockBase
public abstract class ItemFilterBlockBase : IItemFilterBlockBase
{
protected ItemFilterBlockBase()
{
}
protected ItemFilterBlockBase(IItemFilterScript parentScript)
{
CommandManager = parentScript.CommandManager;
ParentScript = parentScript;
}
public ICommandManager CommandManager { get; }
public IItemFilterScript ParentScript { get; set; }
}
public interface IItemFilterCommentBlock : IItemFilterBlockBase
@@ -41,6 +53,10 @@ namespace Filtration.ObjectModel
public class ItemFilterCommentBlock : ItemFilterBlockBase, IItemFilterCommentBlock
{
public ItemFilterCommentBlock(IItemFilterScript parentScript) : base(parentScript)
{
}
public string Comment { get; set; }
}
@@ -48,14 +64,19 @@ namespace Filtration.ObjectModel
{
private ItemFilterBlockGroup _blockGroup;
public ItemFilterBlock()
internal ItemFilterBlock()
{
ActionBlockItem = new ActionBlockItem(BlockAction.Show);
BlockItems = new ObservableCollection<IItemFilterBlockItem> {ActionBlockItem};
Enabled = true;
BlockItems = new ObservableCollection<IItemFilterBlockItem> { ActionBlockItem };
}
public bool Enabled { get; set; }
public ItemFilterBlock(IItemFilterScript parentScript) : base(parentScript)
{
BlockItems = new ObservableCollection<IItemFilterBlockItem> { ActionBlockItem };
}
public ICommandManager CommandManager { get; }
public bool Enabled { get; set; } = true;
public string Description { get; set; }
public ItemFilterBlockGroup BlockGroup
@@ -98,7 +119,7 @@ namespace Filtration.ObjectModel
}
}
public ActionBlockItem ActionBlockItem { get; }
public ActionBlockItem ActionBlockItem { get; } = new ActionBlockItem(BlockAction.Show);
public ObservableCollection<IItemFilterBlockItem> BlockItems { get; }

View File

@@ -37,6 +37,7 @@ namespace Filtration.ObjectModel
public class ItemFilterScript : IItemFilterScriptInternal
{
private bool _isDirty;
private string _description;
internal ItemFilterScript()
{
@@ -65,7 +66,18 @@ namespace Filtration.ObjectModel
public IItemFilterScriptSettings ItemFilterScriptSettings { get; }
public string FilePath { get; set; }
public string Description { get; set; }
public string Description
{
get => _description;
set
{
if (value == _description) return;
_description = value;
OnPropertyChanged();
}
}
public DateTime DateModified { get; set; }
public bool IsDirty