From 32523787d28942e9cf1598490cd653427bf0267a Mon Sep 17 00:00:00 2001 From: azakhi Date: Thu, 13 Sep 2018 17:34:16 +0300 Subject: [PATCH] Improve commands & add multiple selection feature --- .../ItemFilterScript/MoveBlockDownCommand.cs | 39 - .../MoveBlockToBottomCommand.cs | 30 - .../ItemFilterScript/MoveBlockToTopCommand.cs | 30 - .../ItemFilterScript/MoveBlockUpCommand.cs | 39 - .../MoveBlocksToBottomCommand.cs | 60 ++ .../MoveBlocksToIndexCommand.cs | 64 ++ .../MoveBlocksToTopCommand.cs | 59 ++ .../MoveSectionToIndexCommand.cs | 49 - .../ItemFilterScript/PasteBlockCommand.cs | 37 - ...BlocksCommand.cs => PasteBlocksCommand.cs} | 13 +- .../ItemFilterScript/RemoveBlockCommand.cs | 29 - .../ItemFilterScript/RemoveBlocksCommand.cs | 50 + .../ItemFilterScript/RemoveSectionCommand.cs | 42 - .../Filtration.ObjectModel.csproj | 14 +- Filtration/Filtration.csproj | 1 + .../ItemFilterBlockViewModelBase.cs | 40 +- .../ItemFilterCommentBlockViewModel.cs | 29 +- .../ViewModels/ItemFilterScriptViewModel.cs | 949 +++++++++--------- Filtration/ViewModels/MainWindowViewModel.cs | 24 +- .../ToolPanes/BlockOutputPreviewViewModel.cs | 12 +- .../SelectedItemsAttachedProperty.cs | 93 ++ .../Views/ItemFilterCommentBlockView.xaml | 2 +- Filtration/Views/ItemFilterScriptView.xaml | 2 +- 23 files changed, 893 insertions(+), 814 deletions(-) delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockDownCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToBottomCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToTopCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockUpCommand.cs create mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToBottomCommand.cs create mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToIndexCommand.cs create mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToTopCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/MoveSectionToIndexCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlockCommand.cs rename Filtration.ObjectModel/Commands/ItemFilterScript/{PasteMultipleBlocksCommand.cs => PasteBlocksCommand.cs} (68%) delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlockCommand.cs create mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlocksCommand.cs delete mode 100644 Filtration.ObjectModel/Commands/ItemFilterScript/RemoveSectionCommand.cs create mode 100644 Filtration/Views/AttachedProperties/SelectedItemsAttachedProperty.cs diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockDownCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockDownCommand.cs deleted file mode 100644 index 0f837e6..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockDownCommand.cs +++ /dev/null @@ -1,39 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToBottomCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToBottomCommand.cs deleted file mode 100644 index 3b680a7..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToBottomCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -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(); - } -} diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToTopCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToTopCommand.cs deleted file mode 100644 index 49ac04a..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockToTopCommand.cs +++ /dev/null @@ -1,30 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockUpCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockUpCommand.cs deleted file mode 100644 index 44b7fec..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlockUpCommand.cs +++ /dev/null @@ -1,39 +0,0 @@ -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(); - } -} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToBottomCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToBottomCommand.cs new file mode 100644 index 0000000..86850da --- /dev/null +++ b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToBottomCommand.cs @@ -0,0 +1,60 @@ +using System.Collections.Generic; + +namespace Filtration.ObjectModel.Commands.ItemFilterScript +{ + public class MoveBlocksToBottomCommand : IUndoableCommand + { + private readonly IItemFilterScript _itemFilterScript; + private readonly List _sourceIndexes; + + public MoveBlocksToBottomCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase block) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = new List { _itemFilterScript.ItemFilterBlocks.IndexOf(block) }; + } + + public MoveBlocksToBottomCommand(IItemFilterScript itemFilterScript, List sourceIndexes) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = sourceIndexes; + _sourceIndexes.Sort(); + } + + public void Execute() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_sourceIndexes[i]]); + } + + for (var i = _sourceIndexes.Count - 1; i >= 0; i--) + { + _itemFilterScript.ItemFilterBlocks.RemoveAt(_sourceIndexes[i]); + } + + foreach (var block in blocksToMove) + { + _itemFilterScript.ItemFilterBlocks.Add(block); + } + } + + public void Undo() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + var movedIndex = _itemFilterScript.ItemFilterBlocks.Count - _sourceIndexes.Count; + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[movedIndex]); + _itemFilterScript.ItemFilterBlocks.RemoveAt(movedIndex); + } + + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(_sourceIndexes[i], blocksToMove[i]); + } + } + + public void Redo() => Execute(); + } +} diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToIndexCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToIndexCommand.cs new file mode 100644 index 0000000..aef80ac --- /dev/null +++ b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToIndexCommand.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Filtration.ObjectModel.Commands.ItemFilterScript +{ + public class MoveBlocksToIndexCommand : IUndoableCommand + { + private readonly IItemFilterScript _itemFilterScript; + private List _sourceIndexes; + private int _targetIndex; + + public MoveBlocksToIndexCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase block, int targetIndex) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = new List { _itemFilterScript.ItemFilterBlocks.IndexOf(block) }; + _targetIndex = targetIndex; + } + + public MoveBlocksToIndexCommand(IItemFilterScript itemFilterScript, List sourceIndexes, int targetIndex) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = sourceIndexes; + _sourceIndexes.Sort(); + _targetIndex = targetIndex; + } + + public void Execute() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_sourceIndexes[i]]); + } + + for (var i = _sourceIndexes.Count - 1; i >= 0; i--) + { + _itemFilterScript.ItemFilterBlocks.RemoveAt(_sourceIndexes[i]); + } + + for (var i = 0; i < blocksToMove.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(_targetIndex + i, blocksToMove[i]); + } + } + + public void Undo() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_targetIndex]); + _itemFilterScript.ItemFilterBlocks.RemoveAt(_targetIndex); + } + + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(_sourceIndexes[i], blocksToMove[i]); + } + } + + public void Redo() => Execute(); + } +} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToTopCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToTopCommand.cs new file mode 100644 index 0000000..c426c05 --- /dev/null +++ b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveBlocksToTopCommand.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; + +namespace Filtration.ObjectModel.Commands.ItemFilterScript +{ + public class MoveBlocksToTopCommand : IUndoableCommand + { + private readonly IItemFilterScript _itemFilterScript; + private readonly List _sourceIndexes; + + public MoveBlocksToTopCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase block) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = new List { _itemFilterScript.ItemFilterBlocks.IndexOf(block) }; + } + + public MoveBlocksToTopCommand(IItemFilterScript itemFilterScript, List sourceIndexes) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = sourceIndexes; + _sourceIndexes.Sort(); + } + + public void Execute() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_sourceIndexes[i]]); + } + + for (var i = _sourceIndexes.Count - 1; i >= 0; i--) + { + _itemFilterScript.ItemFilterBlocks.RemoveAt(_sourceIndexes[i]); + } + + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(i, blocksToMove[i]); + } + } + + public void Undo() + { + List blocksToMove = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[0]); + _itemFilterScript.ItemFilterBlocks.RemoveAt(0); + } + + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(_sourceIndexes[i], blocksToMove[i]); + } + } + + public void Redo() => Execute(); + } +} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveSectionToIndexCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/MoveSectionToIndexCommand.cs deleted file mode 100644 index 40d0bae..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/MoveSectionToIndexCommand.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System.Collections.Generic; - -namespace Filtration.ObjectModel.Commands.ItemFilterScript -{ - public class MoveSectionToIndexCommand : IUndoableCommand - { - private readonly IItemFilterScript _itemFilterScript; - private int _sectionStart; - private int _sectionSize; - private int _index; - - public MoveSectionToIndexCommand(IItemFilterScript itemFilterScript, int sectionStart, int sectionSize, int index) - { - _itemFilterScript = itemFilterScript; - _sectionStart = sectionStart; - _sectionSize = sectionSize; - _index = index; - } - public void Execute() - { - List blocksToMove = new List(); - for(var i = 0; i < _sectionSize; i++) - { - blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_sectionStart]); - _itemFilterScript.ItemFilterBlocks.RemoveAt(_sectionStart); - } - for (var i = 0; i < _sectionSize; i++) - { - _itemFilterScript.ItemFilterBlocks.Insert(_index + i, blocksToMove[i]); - } - } - - public void Undo() - { - List blocksToMove = new List(); - for (var i = 0; i < _sectionSize; i++) - { - blocksToMove.Add(_itemFilterScript.ItemFilterBlocks[_index]); - _itemFilterScript.ItemFilterBlocks.RemoveAt(_index); - } - for (var i = 0; i < _sectionSize; i++) - { - _itemFilterScript.ItemFilterBlocks.Insert(_sectionStart + i, blocksToMove[i]); - } - } - - public void Redo() => Execute(); - } -} \ No newline at end of file diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlockCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlockCommand.cs deleted file mode 100644 index 7d7c680..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlockCommand.cs +++ /dev/null @@ -1,37 +0,0 @@ -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(); - } -} diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/PasteMultipleBlocksCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlocksCommand.cs similarity index 68% rename from Filtration.ObjectModel/Commands/ItemFilterScript/PasteMultipleBlocksCommand.cs rename to Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlocksCommand.cs index d563e02..f7027b2 100644 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/PasteMultipleBlocksCommand.cs +++ b/Filtration.ObjectModel/Commands/ItemFilterScript/PasteBlocksCommand.cs @@ -3,13 +3,20 @@ using System.Collections.Generic; namespace Filtration.ObjectModel.Commands.ItemFilterScript { - public class PasteMultipleBlocksCommand : IUndoableCommand + public class PasteBlocksCommand : IUndoableCommand { private readonly IItemFilterScript _itemFilterScript; private readonly List _pastedItemFilterBlocks; private readonly IItemFilterBlockBase _addAfterItemFilterBlock; - public PasteMultipleBlocksCommand(IItemFilterScript itemFilterScript, List pastedItemFilterBlocks, IItemFilterBlockBase addAfterItemFilterBlock) + public PasteBlocksCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase block, IItemFilterBlockBase addAfterItemFilterBlock) + { + _itemFilterScript = itemFilterScript; + _pastedItemFilterBlocks = new List { block }; + _addAfterItemFilterBlock = addAfterItemFilterBlock; + } + + public PasteBlocksCommand(IItemFilterScript itemFilterScript, List pastedItemFilterBlocks, IItemFilterBlockBase addAfterItemFilterBlock) { _itemFilterScript = itemFilterScript; _pastedItemFilterBlocks = pastedItemFilterBlocks; @@ -21,7 +28,7 @@ namespace Filtration.ObjectModel.Commands.ItemFilterScript if (_addAfterItemFilterBlock != null) { var lastAddedBlock = _addAfterItemFilterBlock; - foreach(var block in _pastedItemFilterBlocks) + foreach (var block in _pastedItemFilterBlocks) { _itemFilterScript.ItemFilterBlocks.Insert(_itemFilterScript.ItemFilterBlocks.IndexOf(lastAddedBlock) + 1, block); lastAddedBlock = block; diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlockCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlockCommand.cs deleted file mode 100644 index 07e61ac..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlockCommand.cs +++ /dev/null @@ -1,29 +0,0 @@ -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(); - } -} diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlocksCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlocksCommand.cs new file mode 100644 index 0000000..ec8020b --- /dev/null +++ b/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveBlocksCommand.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Filtration.ObjectModel.Commands.ItemFilterScript +{ + public class RemoveBlocksCommand : IUndoableCommand + { + private readonly IItemFilterScript _itemFilterScript; + private List _removedItemFilterBlocks; + private List _sourceIndexes; + + public RemoveBlocksCommand(IItemFilterScript itemFilterScript, IItemFilterBlockBase block) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = new List { _itemFilterScript.ItemFilterBlocks.IndexOf(block) }; + _removedItemFilterBlocks = new List { block }; + } + + public RemoveBlocksCommand(IItemFilterScript itemFilterScript, List sourceIndexes) + { + _itemFilterScript = itemFilterScript; + _sourceIndexes = sourceIndexes; + _sourceIndexes.Sort(); + _removedItemFilterBlocks = new List(); + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _removedItemFilterBlocks.Add(_itemFilterScript.ItemFilterBlocks[_sourceIndexes[i]]); + } + } + + public void Execute() + { + for (var i = _sourceIndexes.Count - 1; i >= 0; i--) + { + _itemFilterScript.ItemFilterBlocks.RemoveAt(_sourceIndexes[i]); + } + } + + public void Undo() + { + for (var i = 0; i < _sourceIndexes.Count; i++) + { + _itemFilterScript.ItemFilterBlocks.Insert(_sourceIndexes[i], _removedItemFilterBlocks[i]); + } + } + + public void Redo() => Execute(); + } +} diff --git a/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveSectionCommand.cs b/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveSectionCommand.cs deleted file mode 100644 index 2718eb3..0000000 --- a/Filtration.ObjectModel/Commands/ItemFilterScript/RemoveSectionCommand.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Filtration.ObjectModel.Commands.ItemFilterScript -{ - public class RemoveSectionCommand : IUndoableCommand - { - private readonly IItemFilterScript _itemFilterScript; - private List _removedItemFilterBlocks; - private int _sectionStart; - private int _sectionSize; - - public RemoveSectionCommand(IItemFilterScript itemFilterScript, int sectionStart, int sectionSize) - { - _itemFilterScript = itemFilterScript; - _sectionStart = sectionStart; - _sectionSize = sectionSize; - _removedItemFilterBlocks = new List(); - for(var i = 0; i < _sectionSize; i++) - { - _removedItemFilterBlocks.Add(_itemFilterScript.ItemFilterBlocks[_sectionStart + i]); - } - } - public void Execute() - { - for (var i = 0; i < _sectionSize; i++) - { - _itemFilterScript.ItemFilterBlocks.RemoveAt(_sectionStart); - } - } - - public void Undo() - { - for (var i = 0; i < _sectionSize; i++) - { - _itemFilterScript.ItemFilterBlocks.Insert(_sectionStart + i, _removedItemFilterBlocks[i]); - } - } - - public void Redo() => Execute(); - } -} diff --git a/Filtration.ObjectModel/Filtration.ObjectModel.csproj b/Filtration.ObjectModel/Filtration.ObjectModel.csproj index 9600d14..f01ad71 100644 --- a/Filtration.ObjectModel/Filtration.ObjectModel.csproj +++ b/Filtration.ObjectModel/Filtration.ObjectModel.csproj @@ -110,17 +110,13 @@ - - - + + - - - - - + + + - diff --git a/Filtration/Filtration.csproj b/Filtration/Filtration.csproj index 87de2e0..f2d679c 100644 --- a/Filtration/Filtration.csproj +++ b/Filtration/Filtration.csproj @@ -191,6 +191,7 @@ ThemeComponentSelectionControl.xaml + diff --git a/Filtration/ViewModels/ItemFilterBlockViewModelBase.cs b/Filtration/ViewModels/ItemFilterBlockViewModelBase.cs index 395bbe1..b04053f 100644 --- a/Filtration/ViewModels/ItemFilterBlockViewModelBase.cs +++ b/Filtration/ViewModels/ItemFilterBlockViewModelBase.cs @@ -21,16 +21,6 @@ namespace Filtration.ViewModels public ItemFilterBlockViewModelBase() { - CopyBlockCommand = new RelayCommand(OnCopyBlockCommand); - PasteBlockCommand = new RelayCommand(OnPasteBlockCommand); - AddBlockCommand = new RelayCommand(OnAddBlockCommand); - AddSectionCommand = new RelayCommand(OnAddSectionCommand); - DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand); - MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand); - MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand); - MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand); - MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand); - _isVisible = true; } @@ -38,7 +28,17 @@ namespace Filtration.ViewModels public virtual void Initialise(IItemFilterBlockBase itemfilterBlock, IItemFilterScriptViewModel itemFilterScriptViewModel) { BaseBlock = itemfilterBlock; - _parentScriptViewModel = itemFilterScriptViewModel; + _parentScriptViewModel = itemFilterScriptViewModel; + + CopyBlockCommand = new RelayCommand(OnCopyBlockCommand); + PasteBlockCommand = new RelayCommand(OnPasteBlockCommand); + AddBlockCommand = new RelayCommand(OnAddBlockCommand); + AddSectionCommand = new RelayCommand(OnAddSectionCommand); + DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => _parentScriptViewModel.CanModifyBlock(this)); + MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand); + MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand); + MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand); + MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand); } public event EventHandler BlockBecameDirty; @@ -46,15 +46,15 @@ namespace Filtration.ViewModels public IItemFilterBlockBase BaseBlock { get; protected set; } public IItemFilterScriptViewModel _parentScriptViewModel; - public RelayCommand CopyBlockCommand { get; } - public RelayCommand PasteBlockCommand { get; } - public RelayCommand AddBlockCommand { get; } - public RelayCommand AddSectionCommand { get; } - public RelayCommand DeleteBlockCommand { get; } - public RelayCommand MoveBlockUpCommand { get; } - public RelayCommand MoveBlockDownCommand { get; } - public RelayCommand MoveBlockToTopCommand { get; } - public RelayCommand MoveBlockToBottomCommand { get; } + public RelayCommand CopyBlockCommand { get; private set; } + public RelayCommand PasteBlockCommand { get; private set; } + public RelayCommand AddBlockCommand { get; private set; } + public RelayCommand AddSectionCommand { get; private set; } + public RelayCommand DeleteBlockCommand { get; private set; } + public RelayCommand MoveBlockUpCommand { get; private set; } + public RelayCommand MoveBlockDownCommand { get; private set; } + public RelayCommand MoveBlockToTopCommand { get; private set; } + public RelayCommand MoveBlockToBottomCommand { get; private set; } public bool IsDirty { diff --git a/Filtration/ViewModels/ItemFilterCommentBlockViewModel.cs b/Filtration/ViewModels/ItemFilterCommentBlockViewModel.cs index 90bb853..d4ab381 100644 --- a/Filtration/ViewModels/ItemFilterCommentBlockViewModel.cs +++ b/Filtration/ViewModels/ItemFilterCommentBlockViewModel.cs @@ -10,17 +10,20 @@ namespace Filtration.ViewModels IItemFilterCommentBlock ItemFilterCommentBlock { get; } string Comment { get; } bool IsExpanded { get; set; } - bool HasChild { get; set; } + bool HasVisibleChild { get; } } internal class ItemFilterCommentBlockViewModel : ItemFilterBlockViewModelBase, IItemFilterCommentBlockViewModel { private bool _isExpanded; - private bool _hasChild; + private int _childCount; + private int _visibleChildCount; public ItemFilterCommentBlockViewModel() { _isExpanded = true; + _childCount = 0; + _visibleChildCount = 0; ToggleSectionCommand = new RelayCommand(OnToggleSectionCommand); } @@ -92,16 +95,32 @@ namespace Filtration.ViewModels } } - public bool HasChild + public int ChildCount { - get => _hasChild; + get => _childCount; set { - _hasChild = value; + _childCount = value; RaisePropertyChanged(); } } + public int VisibleChildCount + { + get => _visibleChildCount; + set + { + _visibleChildCount = value; + RaisePropertyChanged(); + RaisePropertyChanged(nameof(HasVisibleChild)); + } + } + + public bool HasVisibleChild + { + get => (_visibleChildCount > 0); + } + private void OnToggleSectionCommand() { _parentScriptViewModel.ToggleSection(this); diff --git a/Filtration/ViewModels/ItemFilterScriptViewModel.cs b/Filtration/ViewModels/ItemFilterScriptViewModel.cs index 8c73cc4..bcc2f72 100644 --- a/Filtration/ViewModels/ItemFilterScriptViewModel.cs +++ b/Filtration/ViewModels/ItemFilterScriptViewModel.cs @@ -21,7 +21,7 @@ using Filtration.ObjectModel.BlockItemTypes; using Filtration.ObjectModel.Commands; using Filtration.ObjectModel.Commands.ItemFilterScript; using Filtration.Parser.Interface.Services; -using Filtration.Properties; +using Filtration.Properties; using Filtration.Services; using Filtration.ViewModels.Factories; using GalaSoft.MvvmLight.CommandWpf; @@ -33,7 +33,8 @@ namespace Filtration.ViewModels internal interface IItemFilterScriptViewModel : IEditableDocument { IItemFilterScript Script { get; } - IItemFilterBlockViewModelBase SelectedBlockViewModel { get; set; } + IItemFilterBlockViewModelBase LastSelectedBlockViewModel { get; } + ObservableCollection SelectedBlockViewModels { get; } IItemFilterCommentBlockViewModel CommentBlockBrowserBrowserSelectedBlockViewModel { get; set; } IEnumerable ItemFilterCommentBlockViewModels { get; } ObservableCollection CustomSoundsAvailable { get; } @@ -49,6 +50,8 @@ namespace Filtration.ViewModels bool HasSelectedEnabledBlock(); bool HasSelectedDisabledBlock(); bool HasSelectedCommentBlock(); + bool CanModifySelectedBlocks(); + bool CanModifyBlock(IItemFilterBlockViewModelBase itemFilterBlock); RelayCommand AddBlockCommand { get; } RelayCommand AddSectionCommand { get; } @@ -74,18 +77,22 @@ namespace Filtration.ViewModels RelayCommand ToggleShowAdvancedCommand { get; } RelayCommand ClearFilterCommand { get; } - void AddCommentBlock(IItemFilterBlockViewModelBase targetBlockViewModel); - void AddBlock(IItemFilterBlockViewModelBase targetBlockViewModel); - void CopyBlock(IItemFilterBlockViewModelBase targetBlockViewModel); + void AddCommentBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void AddBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void CopyBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void CopyBlocks(IEnumerable targetBlockViewModels); void CopyBlockStyle(IItemFilterBlockViewModel targetBlockViewModel); - void PasteBlock(IItemFilterBlockViewModelBase targetBlockViewModel); + void PasteBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase); void PasteBlockStyle(IItemFilterBlockViewModel targetBlockViewModel); void DeleteBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase); - void MoveBlockToTop(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void DeleteBlocks(IEnumerable targetBlockViewModels); void MoveBlockUp(IItemFilterBlockViewModelBase targetBlockViewModelBase); void MoveBlockDown(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void MoveBlockToTop(IItemFilterBlockViewModelBase targetBlockViewModelBase); + void MoveBlocksToTop(IEnumerable targetBlockViewModels); void MoveBlockToBottom(IItemFilterBlockViewModelBase targetBlockViewModelBase); - void ToggleSection(IItemFilterCommentBlockViewModel targetCommentBlockViewModelBase, bool deferPropertyChanged = false); + void MoveBlocksToBottom(IEnumerable targetBlockViewModels); + void ToggleSection(IItemFilterCommentBlockViewModel targetCommentBlockViewModelBase, bool deferViewUpdate = false); } internal class ItemFilterScriptViewModel : PaneViewModel, IItemFilterScriptViewModel @@ -102,13 +109,15 @@ namespace Filtration.ViewModels private readonly IBlockGroupHierarchyBuilder _blockGroupHierarchyBuilder; private bool _isDirty; - private IItemFilterBlockViewModelBase _selectedBlockViewModel; + private readonly ObservableCollection _selectedBlockViewModels; private IItemFilterCommentBlockViewModel _sectionBrowserSelectedBlockViewModel; private readonly ObservableCollection _itemFilterBlockViewModels; private Predicate _blockFilterPredicate; private ICommandManager _scriptCommandManager; private ObservableCollection _customSoundsAvailable; + private ListCollectionView _viewItemFilterBlockViewModels; + private readonly List _lastAddedBlocks; public ItemFilterScriptViewModel(IItemFilterBlockBaseViewModelFactory itemFilterBlockBaseViewModelFactory, IItemFilterBlockTranslator blockTranslator, @@ -129,6 +138,13 @@ namespace Filtration.ViewModels _clipboardService = clipboardService; _blockGroupHierarchyBuilder = blockGroupHierarchyBuilder; _itemFilterBlockViewModels = new ObservableCollection(); + _selectedBlockViewModels = new ObservableCollection(); + _selectedBlockViewModels.CollectionChanged += (s, e) => + { + RaisePropertyChanged(nameof(SelectedBlockViewModels)); + RaisePropertyChanged(nameof(LastSelectedBlockViewModel)); + }; + _lastAddedBlocks = new List(); _showAdvanced = Settings.Default.ShowAdvanced; _avalonDockWorkspaceViewModel.ActiveDocumentChanged += (s, e) => @@ -139,23 +155,23 @@ namespace Filtration.ViewModels ToggleShowAdvancedCommand = new RelayCommand(OnToggleShowAdvancedCommand); ClearFilterCommand = new RelayCommand(OnClearFilterCommand, () => BlockFilterPredicate != null); CloseCommand = new RelayCommand(async () => await OnCloseCommand()); - DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => SelectedBlockViewModel != null); - MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => SelectedBlockViewModel != null && ItemFilterBlockViewModels.IndexOf(SelectedBlockViewModel) > 0); - MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => SelectedBlockViewModel != null && ItemFilterBlockViewModels.IndexOf(SelectedBlockViewModel) > 0); - MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => SelectedBlockViewModel != null && ItemFilterBlockViewModels.IndexOf(SelectedBlockViewModel) < ItemFilterBlockViewModels.Count); - MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => SelectedBlockViewModel != null && ItemFilterBlockViewModels.IndexOf(SelectedBlockViewModel) < ItemFilterBlockViewModels.Count); + DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => CanModifySelectedBlocks()); + MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => SelectedBlockViewModels.Count > 0 && CanModifySelectedBlocks()); + MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => SelectedBlockViewModels.Count > 0 && CanModifySelectedBlocks()); + MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => SelectedBlockViewModels.Count == 1 && ViewItemFilterBlockViewModels.IndexOf(LastSelectedBlockViewModel) > 0); + MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => SelectedBlockViewModels.Count == 1 && ViewItemFilterBlockViewModels.IndexOf(LastSelectedBlockViewModel) < (ViewItemFilterBlockViewModels.Count - 1)); AddBlockCommand = new RelayCommand(OnAddBlockCommand); - AddSectionCommand = new RelayCommand(OnAddCommentBlockCommand, () => SelectedBlockViewModel != null); - DisableBlockCommand = new RelayCommand(OnDisableBlockCommand, HasSelectedEnabledBlock); - EnableBlockCommand = new RelayCommand(OnEnableBlockCommand, HasSelectedDisabledBlock); - DisableSectionCommand = new RelayCommand(OnDisableSectionCommand, HasSelectedCommentBlock); - EnableSectionCommand = new RelayCommand(OnEnableSectionCommand, HasSelectedCommentBlock); + AddSectionCommand = new RelayCommand(OnAddCommentBlockCommand); + DisableBlockCommand = new RelayCommand(OnDisableBlockCommand, () => HasSelectedEnabledBlock() && CanModifySelectedBlocks()); + EnableBlockCommand = new RelayCommand(OnEnableBlockCommand, () => HasSelectedDisabledBlock() && CanModifySelectedBlocks()); + DisableSectionCommand = new RelayCommand(OnDisableSectionCommand, () => HasSelectedCommentBlock() && CanModifySelectedBlocks()); + EnableSectionCommand = new RelayCommand(OnEnableSectionCommand, () => HasSelectedCommentBlock() && CanModifySelectedBlocks()); ExpandSectionCommand = new RelayCommand(OnExpandSectionCommand, HasSelectedCommentBlock); CollapseSectionCommand = new RelayCommand(OnCollapseSectionCommand, HasSelectedCommentBlock); - CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => SelectedBlockViewModel != null); - CopyBlockStyleCommand = new RelayCommand(OnCopyBlockStyleCommand, () => SelectedBlockViewModel != null); - PasteBlockCommand = new RelayCommand(OnPasteBlockCommand, () => SelectedBlockViewModel != null); - PasteBlockStyleCommand = new RelayCommand(OnPasteBlockStyleCommand, () => SelectedBlockViewModel != null); + CopyBlockCommand = new RelayCommand(OnCopyBlockCommand, () => SelectedBlockViewModels.Count > 0); + CopyBlockStyleCommand = new RelayCommand(OnCopyBlockStyleCommand, () => LastSelectedBlockViewModel != null); + PasteBlockCommand = new RelayCommand(OnPasteBlockCommand, () => LastSelectedBlockViewModel != null); + PasteBlockStyleCommand = new RelayCommand(OnPasteBlockStyleCommand, () => LastSelectedBlockViewModel != null); ExpandAllBlocksCommand = new RelayCommand(OnExpandAllBlocksCommand); CollapseAllBlocksCommand = new RelayCommand(OnCollapseAllBlocksCommand); ExpandAllSectionsCommand = new RelayCommand(ExpandAllSections); @@ -193,7 +209,10 @@ namespace Filtration.ViewModels _scriptCommandManager = Script.CommandManager; AddItemFilterBlockViewModels(Script.ItemFilterBlocks, -1); - foreach(var block in Script.ItemFilterBlocks.OfType()) + UpdateChildCount(); + UpdateFilteredBlockList(); + + foreach (var block in Script.ItemFilterBlocks.OfType()) { foreach (var customSoundBlockItem in block.BlockItems.OfType()) { @@ -241,7 +260,8 @@ namespace Filtration.ViewModels } } - RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); + UpdateChildCount(); + UpdateFilteredBlockList(); } private void CustomSoundsAvailableOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) @@ -251,8 +271,6 @@ namespace Filtration.ViewModels private void AddItemFilterBlockViewModels(IEnumerable itemFilterBlocks, int addAtIndex) { - var firstNewViewModel = true; - foreach (var itemFilterBlock in itemFilterBlocks) { var vm = _itemFilterBlockBaseViewModelFactory.Create(itemFilterBlock); @@ -268,11 +286,7 @@ namespace Filtration.ViewModels ItemFilterBlockViewModels.Insert(addAtIndex, vm); } - if (firstNewViewModel) - { - SelectedBlockViewModel = vm; - firstNewViewModel = false; - } + _lastAddedBlocks.Add(vm); var itemBlock = itemFilterBlock as IItemFilterBlock; if (itemBlock != null) @@ -299,9 +313,74 @@ namespace Filtration.ViewModels } ItemFilterBlockViewModels.Remove(itemFilterBlockViewModel); - if (SelectedBlockViewModel == itemFilterBlockViewModel) + } + } + + private void UpdateFilteredBlockList() + { + ICollectionView filteredBlocks = CollectionViewSource.GetDefaultView(_itemFilterBlockViewModels); + filteredBlocks.Filter = BlockFilter; + + ItemFilterCommentBlockViewModel previousSection = new ItemFilterCommentBlockViewModel(); + foreach (IItemFilterBlockViewModelBase block in filteredBlocks) + { + if (block is IItemFilterBlockViewModel) { - SelectedBlockViewModel = null; + previousSection.VisibleChildCount++; + } + else if (block is ItemFilterCommentBlockViewModel) + { + previousSection = block as ItemFilterCommentBlockViewModel; + previousSection.VisibleChildCount = 0; + } + } + + _viewItemFilterBlockViewModels = (ListCollectionView)CollectionViewSource.GetDefaultView( + filteredBlocks.Cast().ToList()); + _viewItemFilterBlockViewModels.Filter = BlockVisibilityFilter; + + Messenger.Default.Send(new NotificationMessage("SectionsChanged")); + SelectedBlockViewModels.Clear(); + RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); + } + + private void UpdateChildCount() + { + ItemFilterCommentBlockViewModel previousSection = new ItemFilterCommentBlockViewModel(); + foreach (IItemFilterBlockViewModelBase block in ItemFilterBlockViewModels) + { + if (block is IItemFilterBlockViewModel) + { + previousSection.ChildCount++; + block.IsVisible = previousSection.IsExpanded; + } + else if (block is ItemFilterCommentBlockViewModel) + { + previousSection = block as ItemFilterCommentBlockViewModel; + previousSection.ChildCount = 0; + } + } + } + + private List getChildren(IItemFilterCommentBlockViewModel targetBlockViewModel) + { + return ItemFilterBlockViewModels.ToList().GetRange(ItemFilterBlockViewModels.IndexOf(targetBlockViewModel) + 1, + (targetBlockViewModel as ItemFilterCommentBlockViewModel).ChildCount); + } + + private List getChildrenIndexes(IItemFilterCommentBlockViewModel targetBlockViewModel) + { + return Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModel) + 1, + (targetBlockViewModel as ItemFilterCommentBlockViewModel).ChildCount).ToList(); + } + + private void ValidateSelectedBlocks() + { + for (var i = 0; i < SelectedBlockViewModels.Count; i++) + { + if (!ViewItemFilterBlockViewModels.Contains(SelectedBlockViewModels[i])) + { + SelectedBlockViewModels.RemoveAt(i--); } } } @@ -353,35 +432,9 @@ namespace Filtration.ViewModels } } - public ICollectionView ViewItemFilterBlockViewModels + public ListCollectionView ViewItemFilterBlockViewModels { - get - { - ICollectionView filteredView = CollectionViewSource.GetDefaultView(ItemFilterBlockViewModels); - filteredView.Filter = BlockFilter; - - IItemFilterBlockViewModelBase previousBlock = null; - foreach (IItemFilterBlockViewModelBase block in filteredView) - { - if (block is IItemFilterBlockViewModel) - { - if (previousBlock is IItemFilterCommentBlockViewModel) - { - (previousBlock as IItemFilterCommentBlockViewModel).HasChild = true; - } - } - else if (block is IItemFilterCommentBlockViewModel) - { - (block as IItemFilterCommentBlockViewModel).HasChild = false; - } - previousBlock = block; - } - - ICollectionView visibilityView = CollectionViewSource.GetDefaultView(filteredView.Cast()); - visibilityView.Filter = BlockVisibilityFilter; - - return visibilityView; - } + get => _viewItemFilterBlockViewModels; } public ObservableCollection ItemFilterBlockViewModels @@ -408,7 +461,13 @@ namespace Filtration.ViewModels private bool BlockVisibilityFilter(object item) { - return (bool)(item as IItemFilterBlockViewModelBase)?.IsVisible; + if (!(item is IItemFilterBlockViewModelBase)) + return false; + + if (Script.ItemFilterScriptSettings.BlockGroupsEnabled && BlockFilterPredicate != null && item is IItemFilterCommentBlockViewModel && !(item as IItemFilterCommentBlockViewModel).HasVisibleChild) + return false; + + return (item as IItemFilterBlockViewModelBase).IsVisible; } private bool ShowBlockBasedOnAdvanced(IItemFilterBlockViewModel blockViewModel) @@ -433,11 +492,11 @@ namespace Filtration.ViewModels set { _blockFilterPredicate = value; - RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); + UpdateFilteredBlockList(); } } - public IEnumerable ItemFilterCommentBlockViewModels => ItemFilterBlockViewModels.OfType(); + public IEnumerable ItemFilterCommentBlockViewModels => ViewItemFilterBlockViewModels.OfType(); public bool IsScript => true; public bool IsTheme => false; @@ -455,51 +514,82 @@ namespace Filtration.ViewModels { _showAdvanced = value; RaisePropertyChanged(); - RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); + RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); Settings.Default.ShowAdvanced = value; + UpdateFilteredBlockList(); } } public bool HasSelectedEnabledBlock() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; - if (selectedBlockViewModel == null) return false; + foreach (var block in SelectedBlockViewModels.OfType()) + { + if (block.BlockEnabled) + { + return true; + } + } - return HasSelectedBlock() && selectedBlockViewModel.BlockEnabled; + return false; } public bool HasSelectedDisabledBlock() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; - if (selectedBlockViewModel == null) return false; + foreach (var block in SelectedBlockViewModels.OfType()) + { + if (!block.BlockEnabled) + { + return true; + } + } - return HasSelectedBlock() && !selectedBlockViewModel.BlockEnabled; - } - - private bool HasSelectedBlock() - { - return SelectedBlockViewModel != null; + return false; } public bool HasSelectedCommentBlock() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - - return selectedBlockViewModel != null; + return SelectedBlockViewModels.OfType().Count() > 0; } - public IItemFilterBlockViewModelBase SelectedBlockViewModel + public bool CanModifySelectedBlocks() { - get => _selectedBlockViewModel; - set + if (SelectedBlockViewModels.Count < 1) + return false; + + foreach (var block in SelectedBlockViewModels) { - if (value != _selectedBlockViewModel) + if (!CanModifyBlock(block)) { - _selectedBlockViewModel = value; - Messenger.Default.Send(new NotificationMessage("SelectedBlockChanged")); - RaisePropertyChanged(); + return false; } } + + return true; + } + + public bool CanModifyBlock(IItemFilterBlockViewModelBase itemFilterBlock) + { + if (itemFilterBlock is IItemFilterBlockViewModel) + return true; + + var itemFilterCommentBlock = itemFilterBlock as ItemFilterCommentBlockViewModel; + if (itemFilterCommentBlock.IsExpanded) + return true; + + return itemFilterCommentBlock.ChildCount == itemFilterCommentBlock.VisibleChildCount; + } + + public ObservableCollection SelectedBlockViewModels + { + get => _selectedBlockViewModels; + } + + public IItemFilterBlockViewModelBase LastSelectedBlockViewModel + { + get + { + return SelectedBlockViewModels.Count > 0 ? SelectedBlockViewModels.Last() : null; + } } public IItemFilterCommentBlockViewModel CommentBlockBrowserBrowserSelectedBlockViewModel @@ -508,7 +598,8 @@ namespace Filtration.ViewModels set { _sectionBrowserSelectedBlockViewModel = value; - SelectedBlockViewModel = value; + SelectedBlockViewModels.Clear(); + SelectedBlockViewModels.Add(value); RaisePropertyChanged(); } } @@ -763,37 +854,45 @@ namespace Filtration.ViewModels private void OnCopyBlockCommand() { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (commentBlockViewModel == null || commentBlockViewModel.IsExpanded) + var blocksToCopy = new List(); + foreach (var block in SelectedBlockViewModels.OfType()) { - CopyBlock(SelectedBlockViewModel); + blocksToCopy.Add(block); + if (block is IItemFilterCommentBlockViewModel && !(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + blocksToCopy.AddRange(getChildren(block as IItemFilterCommentBlockViewModel)); + } + } + + CopyBlocks(blocksToCopy); + } + + public void CopyBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase) + { + if (!(targetBlockViewModelBase is IItemFilterCommentBlockViewModel) || + (targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) + { + CopyBlocks(new List { targetBlockViewModelBase }); } else { - CopySection(commentBlockViewModel); + var blocksToCopy = new List { targetBlockViewModelBase }; + blocksToCopy.AddRange(getChildren(targetBlockViewModelBase as IItemFilterCommentBlockViewModel)); + CopyBlocks(blocksToCopy); } } - public void CopyBlock(IItemFilterBlockViewModelBase targetBlockViewModel) + public void CopyBlocks(IEnumerable targetBlockViewModels) { - try + if (targetBlockViewModels.Count() < 1) { - _clipboardService.SetClipboardText(_blockTranslator.TranslateItemFilterBlockBaseToString(SelectedBlockViewModel.BaseBlock)); + return; } - catch - { - _messageBoxService.Show("Clipboard Error", "Failed to access the clipboard, copy command not completed.", MessageBoxButton.OK, MessageBoxImage.Error); - } - } - public void CopySection(IItemFilterCommentBlockViewModel targetCommentBlockViewModel) - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModel) + 1; - var copyText = _blockTranslator.TranslateItemFilterBlockBaseToString(targetCommentBlockViewModel.BaseBlock); - while (sectionStart < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionStart] as IItemFilterCommentBlockViewModel == null) + var copyText = ""; + foreach (var block in targetBlockViewModels) { - copyText += Environment.NewLine + Environment.NewLine + _blockTranslator.TranslateItemFilterBlockBaseToString(ItemFilterBlockViewModels[sectionStart].BaseBlock); - sectionStart++; + copyText += Environment.NewLine + _blockTranslator.TranslateItemFilterBlockBaseToString(block.BaseBlock) + Environment.NewLine; } try @@ -808,7 +907,7 @@ namespace Filtration.ViewModels private void OnCopyBlockStyleCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; + var selectedBlockViewModel = LastSelectedBlockViewModel as IItemFilterBlockViewModel; if (selectedBlockViewModel != null) { CopyBlockStyle(selectedBlockViewModel); @@ -840,7 +939,7 @@ namespace Filtration.ViewModels private void OnPasteBlockStyleCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; + var selectedBlockViewModel = LastSelectedBlockViewModel as IItemFilterBlockViewModel; if (selectedBlockViewModel != null) { PasteBlockStyle(selectedBlockViewModel); @@ -861,21 +960,18 @@ namespace Filtration.ViewModels private void OnPasteBlockCommand() { - PasteBlock(SelectedBlockViewModel); + PasteBlock(LastSelectedBlockViewModel); } public void PasteBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase) { var commentBlock = targetBlockViewModelBase as IItemFilterCommentBlockViewModel; - if(commentBlock != null && !commentBlock.IsExpanded) + if (commentBlock != null && !commentBlock.IsExpanded) { - var blockIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase) + 1; - while (blockIndex < ItemFilterBlockViewModels.Count && (ItemFilterBlockViewModels[blockIndex] as IItemFilterCommentBlockViewModel) == null) - { - blockIndex++; - } - targetBlockViewModelBase = ItemFilterBlockViewModels[blockIndex - 1]; + targetBlockViewModelBase = ItemFilterBlockViewModels[ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase) + + (commentBlock as ItemFilterCommentBlockViewModel).ChildCount]; } + try { var clipboardText = _clipboardService.GetClipboardText(); @@ -894,17 +990,19 @@ namespace Filtration.ViewModels Script.ItemFilterBlockGroups.First().ChildGroups.Add(blockGroup); } - _scriptCommandManager.ExecuteCommand(new PasteMultipleBlocksCommand(Script, pastedScript.ItemFilterBlocks.ToList(), - targetBlockViewModelBase.BaseBlock)); + ExecuteCommandAndSelectAdded(new PasteBlocksCommand(Script, pastedScript.ItemFilterBlocks.ToList(), targetBlockViewModelBase.BaseBlock)); Messenger.Default.Send(new NotificationMessage(ShowAdvanced, "BlockGroupsChanged")); - var lastBlockIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase) + pastedScript.ItemFilterBlocks.Count; - var lastBlock = ItemFilterBlockViewModels[lastBlockIndex]; - if(ViewItemFilterBlockViewModels.Contains(lastBlock)) + + if (_lastAddedBlocks.Count > 0 && !(_lastAddedBlocks[0] is IItemFilterCommentBlockViewModel)) { - SelectedBlockViewModel = lastBlock; + if (commentBlock != null && !commentBlock.IsExpanded) + { + ToggleSection(commentBlock); + } } - RaisePropertyChanged(nameof(SelectedBlockViewModel)); + + SetDirtyFlag(); } catch (Exception e) { @@ -915,342 +1013,260 @@ namespace Filtration.ViewModels } } - private string PrepareBlockForParsing(string inputString) - { - inputString = inputString.Replace("\t", ""); - var lines = Regex.Split(inputString, "\r\n|\r|\n").ToList(); - for (var i = 0; i < lines.Count; i++) - { - if (lines[i].Length == 0) - { - lines.RemoveAt(i--); - } - else - break; - } - for (var i = lines.Count - 1; i >= 0; i--) - { - if (lines[i].Length == 0) - { - lines.RemoveAt(i++); - } - else - break; - } - var allCommented = true; - for (var i = 0; i < lines.Count; i++) - { - lines[i] = Regex.Replace(lines[i], @"\s+", " "); - if(lines[i][0] == '#') - { - if (lines[i].Length > 1 && lines[i][1] != ' ') - { - lines[i] = "# " + lines[i].Substring(1); - } - } - else - { - allCommented = false; - } - } - - var disabledBlock = -1; - if (allCommented) - { - for (var i = 0; i < lines.Count; i++) - { - if (lines[i].StartsWith("#")) - { - string curLine = Regex.Replace(lines[i].Substring(1), @"\s+", ""); - if ((curLine.StartsWith("Show") || curLine.StartsWith("Hide")) && (curLine.Length == 4 || curLine[4] == '#')) - { - lines[i] = lines[i].Substring(0, 6) + "Disabled" + lines[i].Substring(6); - disabledBlock = i; - break; - } - } - } - } - - if(disabledBlock >= 0) - { - for (var i = disabledBlock; i < lines.Count; i++) - { - lines[i] = lines[i].Substring(2); - } - } - - return string.Join(Environment.NewLine, lines); - } - - private void OnMoveBlockToTopCommand() - { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (commentBlockViewModel == null || commentBlockViewModel.IsExpanded) - { - MoveBlockToTop(SelectedBlockViewModel); - } - else - { - MoveSectionToTop(commentBlockViewModel); - } - } - private void OnMoveBlockUpCommand() { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if(commentBlockViewModel == null || commentBlockViewModel.IsExpanded) - { - MoveBlockUp(SelectedBlockViewModel); - } - else - { - MoveSectionUp(commentBlockViewModel); - } + MoveBlockUp(LastSelectedBlockViewModel); } public void MoveBlockUp(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - var blockIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase); - if (ItemFilterBlockViewModels[blockIndex - 1].IsVisible) + var blockIndex = ViewItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase); + if (blockIndex < 1) + return; + + var indexToMove = ItemFilterBlockViewModels.IndexOf( + ViewItemFilterBlockViewModels.GetItemAt(blockIndex - 1) as IItemFilterBlockViewModelBase); + + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && + !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) { - _scriptCommandManager.ExecuteCommand(new MoveBlockUpCommand(Script, targetBlockViewModelBase?.BaseBlock)); - SelectedBlockViewModel = ItemFilterBlockViewModels[blockIndex - 1]; + ExecuteCommandAndSelectAdded(new MoveBlocksToIndexCommand(Script, + Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase), + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount + 1).ToList(), indexToMove)); + if (_lastAddedBlocks.Count > 0) + { + ToggleSection(_lastAddedBlocks[0] as IItemFilterCommentBlockViewModel); + } } else { - var aboveSectionStart = blockIndex - 1; - while(ItemFilterBlockViewModels[aboveSectionStart] as IItemFilterCommentBlockViewModel == null) + var parent = blockIndex > 1 ? ViewItemFilterBlockViewModels.GetItemAt(blockIndex - 2) as IItemFilterCommentBlockViewModel : null; + if (parent != null && !parent.IsExpanded) { - aboveSectionStart--; + ToggleSection(parent); } - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, blockIndex, 1, aboveSectionStart)); - SelectedBlockViewModel = ItemFilterBlockViewModels[aboveSectionStart]; + ExecuteCommandAndSelectAdded(new MoveBlocksToIndexCommand(Script, targetBlockViewModelBase.BaseBlock, indexToMove)); } - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } - - public void MoveSectionUp(IItemFilterCommentBlockViewModel targetCommentBlockViewModel) - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModel); - var sectionEnd = sectionStart + 1; - while(sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) - { - sectionEnd++; - } - - var newLocation = sectionStart - 1; - if (ItemFilterBlockViewModels[newLocation].IsVisible) - { - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionEnd - sectionStart, newLocation)); - } - else - { - while (ItemFilterBlockViewModels[newLocation] as IItemFilterCommentBlockViewModel == null) - { - newLocation--; - } - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionEnd - sectionStart, newLocation)); - } - - ToggleSection(ItemFilterBlockViewModels[newLocation] as IItemFilterCommentBlockViewModel); - SelectedBlockViewModel = ItemFilterBlockViewModels[newLocation]; - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); + SetDirtyFlag(); } private void OnMoveBlockDownCommand() { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (commentBlockViewModel == null || commentBlockViewModel.IsExpanded) - { - MoveBlockDown(SelectedBlockViewModel); - } - else - { - MoveSectionDown(commentBlockViewModel); - } + MoveBlockDown(LastSelectedBlockViewModel); } public void MoveBlockDown(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - var blockIndex = ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase); - var beloveBlockAsComment = ItemFilterBlockViewModels[blockIndex + 1] as IItemFilterCommentBlockViewModel; - if (beloveBlockAsComment == null || beloveBlockAsComment.IsExpanded) - { - _scriptCommandManager.ExecuteCommand(new MoveBlockDownCommand(Script, targetBlockViewModelBase?.BaseBlock)); - SelectedBlockViewModel = ItemFilterBlockViewModels[blockIndex + 1]; - } - else - { - var beloveSectionEnd = blockIndex + 2; - while (beloveSectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[beloveSectionEnd] as IItemFilterCommentBlockViewModel == null) - { - beloveSectionEnd++; - } - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, blockIndex, 1, beloveSectionEnd - 1)); - SelectedBlockViewModel = ItemFilterBlockViewModels[beloveSectionEnd - 1]; - } - - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } - - public void MoveSectionDown(IItemFilterCommentBlockViewModel targetCommentBlockViewModel) - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModel); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) - { - sectionEnd++; - } - - if (sectionEnd >= ItemFilterBlockViewModels.Count) + var blockIndex = ViewItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase); + if (blockIndex >= ViewItemFilterBlockViewModels.Count - 1) return; - var sectionSize = sectionEnd - sectionStart; - - var newLocation = sectionStart + 1; - var beloveBlockAsComment = ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel; - if (beloveBlockAsComment == null || beloveBlockAsComment.IsExpanded) + var belowBlock = ViewItemFilterBlockViewModels.GetItemAt(blockIndex + 1) as IItemFilterBlockViewModelBase; + var indexToMove = ItemFilterBlockViewModels.IndexOf(belowBlock); + if (belowBlock is ItemFilterCommentBlockViewModel && !(belowBlock as ItemFilterCommentBlockViewModel).IsExpanded) { - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionSize, newLocation)); + indexToMove += (belowBlock as ItemFilterCommentBlockViewModel).ChildCount; } - else + + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && + !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) { - while ((newLocation + sectionSize) < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[newLocation + sectionSize] as IItemFilterCommentBlockViewModel == null) + indexToMove -= (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount; + ExecuteCommandAndSelectAdded(new MoveBlocksToIndexCommand(Script, + Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase), + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount + 1).ToList(), indexToMove)); + if (_lastAddedBlocks.Count > 0) { - newLocation++; + ToggleSection(_lastAddedBlocks[0] as IItemFilterCommentBlockViewModel); } - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionEnd - sectionStart, newLocation)); - } - - ToggleSection(ItemFilterBlockViewModels[newLocation] as IItemFilterCommentBlockViewModel); - SelectedBlockViewModel = ItemFilterBlockViewModels[newLocation]; - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } - - private void OnMoveBlockToBottomCommand() - { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (commentBlockViewModel == null || commentBlockViewModel.IsExpanded) - { - MoveBlockToBottom(SelectedBlockViewModel); } else { - MoveSectionToBottom(commentBlockViewModel); + if (belowBlock is ItemFilterCommentBlockViewModel && !(belowBlock as ItemFilterCommentBlockViewModel).IsExpanded) + { + ToggleSection(belowBlock as IItemFilterCommentBlockViewModel); + } + ExecuteCommandAndSelectAdded(new MoveBlocksToIndexCommand(Script, targetBlockViewModelBase.BaseBlock, indexToMove)); } + + SetDirtyFlag(); } private void OnAddBlockCommand() { - var selectedBlockAsCommentBlock = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if(selectedBlockAsCommentBlock == null || selectedBlockAsCommentBlock.IsExpanded) - { - AddBlock(SelectedBlockViewModel); - } - else - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(selectedBlockAsCommentBlock); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) - { - sectionEnd++; - } - AddBlock(ItemFilterBlockViewModels[sectionEnd - 1]); - } + AddBlock(LastSelectedBlockViewModel); } public void AddBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - _scriptCommandManager.ExecuteCommand(new AddBlockCommand(Script, targetBlockViewModelBase?.BaseBlock)); - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - // TODO: Expand new viewmodel - } + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) + { + ToggleSection(targetBlockViewModelBase as IItemFilterCommentBlockViewModel); + targetBlockViewModelBase = ItemFilterBlockViewModels[ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase) + + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount]; + } + + ExecuteCommandAndSelectAdded(new AddBlockCommand(Script, targetBlockViewModelBase?.BaseBlock)); + SetDirtyFlag(); + } + + private void OnAddCommentBlockCommand() + { + AddCommentBlock(LastSelectedBlockViewModel); + } public void AddCommentBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - _scriptCommandManager.ExecuteCommand(new AddCommentBlockCommand(Script, targetBlockViewModelBase.BaseBlock)); - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) + { + targetBlockViewModelBase = ItemFilterBlockViewModels[ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase) + + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount]; + } + + ExecuteCommandAndSelectAdded(new AddCommentBlockCommand(Script, targetBlockViewModelBase?.BaseBlock)); + SetDirtyFlag(); + } + + private void OnDeleteBlockCommand() + { + var blocksToDelete = new List(); + foreach (var block in SelectedBlockViewModels.OfType()) + { + blocksToDelete.Add(block); + if (block is IItemFilterCommentBlockViewModel && !(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + blocksToDelete.AddRange(getChildren(block as IItemFilterCommentBlockViewModel)); + } + } + + DeleteBlocks(blocksToDelete); + } public void DeleteBlock(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - var commentBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (commentBlockViewModel == null || commentBlockViewModel.IsExpanded) + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) { - _scriptCommandManager.ExecuteCommand(new RemoveBlockCommand(Script, targetBlockViewModelBase.BaseBlock)); + _scriptCommandManager.ExecuteCommand(new RemoveBlocksCommand(Script, + Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase), + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount + 1).ToList())); } else { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) - { - sectionEnd++; - } - - _scriptCommandManager.ExecuteCommand(new RemoveSectionCommand(Script, sectionStart, sectionEnd - sectionStart)); + _scriptCommandManager.ExecuteCommand(new RemoveBlocksCommand(Script, targetBlockViewModelBase.BaseBlock)); } - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } + SetDirtyFlag(); + } + + public void DeleteBlocks(IEnumerable targetBlockViewModels) + { + var blockIndexes = new List(); + foreach (var block in targetBlockViewModels) + { + blockIndexes.Add(ItemFilterBlockViewModels.IndexOf(block)); + } + + _scriptCommandManager.ExecuteCommand(new RemoveBlocksCommand(Script, blockIndexes)); + SetDirtyFlag(); + } + + private void OnMoveBlockToBottomCommand() + { + MoveBlocksToBottom(SelectedBlockViewModels.OfType()); + } public void MoveBlockToBottom(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - _scriptCommandManager.ExecuteCommand(new MoveBlockToBottomCommand(Script, targetBlockViewModelBase.BaseBlock)); - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } - - public void MoveSectionToBottom(IItemFilterCommentBlockViewModel targetCommentBlockViewModel) - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModel); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) { - sectionEnd++; + ExecuteCommandAndSelectAdded(new MoveBlocksToBottomCommand(Script, + Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase), + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount + 1).ToList())); + if (_lastAddedBlocks.Count > 0) + { + ToggleSection(_lastAddedBlocks[0] as IItemFilterCommentBlockViewModel); + } + } + else + { + _scriptCommandManager.ExecuteCommand(new MoveBlocksToBottomCommand(Script, targetBlockViewModelBase.BaseBlock)); + } + + SetDirtyFlag(); + } + + public void MoveBlocksToBottom(IEnumerable targetCommentBlockViewModels) + { + var sourceIndexes = new List(); + foreach (var block in targetCommentBlockViewModels) + { + sourceIndexes.Add(ItemFilterBlockViewModels.IndexOf(block)); + if (block is IItemFilterCommentBlockViewModel && !(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + sourceIndexes.AddRange(getChildrenIndexes(block as IItemFilterCommentBlockViewModel)); + } } - var newLocation = ItemFilterBlockViewModels.Count - (sectionEnd - sectionStart); - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionEnd - sectionStart, newLocation)); + ExecuteCommandAndSelectAdded(new MoveBlocksToBottomCommand(Script, sourceIndexes)); + for (var i = ItemFilterBlockViewModels.Count - sourceIndexes.Count; i < ItemFilterBlockViewModels.Count; i++) + { + if (ItemFilterBlockViewModels[i] as IItemFilterCommentBlockViewModel != null) + { + ToggleSection(ItemFilterBlockViewModels[i] as IItemFilterCommentBlockViewModel); + } + } - ToggleSection(ItemFilterBlockViewModels[newLocation] as IItemFilterCommentBlockViewModel); - SelectedBlockViewModel = ItemFilterBlockViewModels[newLocation]; - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } + SetDirtyFlag(); + } + + private void OnMoveBlockToTopCommand() + { + MoveBlocksToTop(SelectedBlockViewModels.OfType()); + } public void MoveBlockToTop(IItemFilterBlockViewModelBase targetBlockViewModelBase) { - _scriptCommandManager.ExecuteCommand(new MoveBlockToTopCommand(Script, targetBlockViewModelBase.BaseBlock)); - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); - } - - public void MoveSectionToTop(IItemFilterCommentBlockViewModel targetCommentBlockViewModel) - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModel); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) + if (targetBlockViewModelBase is IItemFilterCommentBlockViewModel && !(targetBlockViewModelBase as IItemFilterCommentBlockViewModel).IsExpanded) { - sectionEnd++; + ExecuteCommandAndSelectAdded(new MoveBlocksToTopCommand(Script, + Enumerable.Range(ItemFilterBlockViewModels.IndexOf(targetBlockViewModelBase), + (targetBlockViewModelBase as ItemFilterCommentBlockViewModel).ChildCount + 1).ToList())); + if (_lastAddedBlocks.Count > 0) + { + ToggleSection(_lastAddedBlocks[0] as IItemFilterCommentBlockViewModel); + } + } + else + { + ExecuteCommandAndSelectAdded(new MoveBlocksToTopCommand(Script, targetBlockViewModelBase.BaseBlock)); } - var newLocation = 0; - _scriptCommandManager.ExecuteCommand(new MoveSectionToIndexCommand(Script, sectionStart, sectionEnd - sectionStart, newLocation)); + SetDirtyFlag(); + } - ToggleSection(ItemFilterBlockViewModels[newLocation] as IItemFilterCommentBlockViewModel); - SelectedBlockViewModel = ItemFilterBlockViewModels[newLocation]; - RaisePropertyChanged("SelectedBlockViewModel"); - SetDirtyFlag(); + public void MoveBlocksToTop(IEnumerable targetCommentBlockViewModels) + { + var sourceIndexes = new List(); + foreach (var block in targetCommentBlockViewModels) + { + sourceIndexes.Add(ItemFilterBlockViewModels.IndexOf(block)); + if (block is IItemFilterCommentBlockViewModel && !(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + sourceIndexes.AddRange(getChildrenIndexes(block as IItemFilterCommentBlockViewModel)); + } + } + + ExecuteCommandAndSelectAdded(new MoveBlocksToTopCommand(Script, sourceIndexes)); + for (var i = 0; i < sourceIndexes.Count; i++) + { + if (ItemFilterBlockViewModels[i] as IItemFilterCommentBlockViewModel != null) + { + ToggleSection(ItemFilterBlockViewModels[i] as IItemFilterCommentBlockViewModel); + } + } + + SetDirtyFlag(); } private void OnBlockBecameDirty(object sender, EventArgs e) @@ -1258,25 +1274,6 @@ namespace Filtration.ViewModels SetDirtyFlag(); } - private void OnAddCommentBlockCommand() - { - var selectedBlockAsCommentBlock = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (selectedBlockAsCommentBlock == null || selectedBlockAsCommentBlock.IsExpanded) - { - AddCommentBlock(SelectedBlockViewModel); - } - else - { - var sectionStart = ItemFilterBlockViewModels.IndexOf(selectedBlockAsCommentBlock); - var sectionEnd = sectionStart + 1; - while (sectionEnd < ItemFilterBlockViewModels.Count && ItemFilterBlockViewModels[sectionEnd] as IItemFilterCommentBlockViewModel == null) - { - sectionEnd++; - } - AddCommentBlock(ItemFilterBlockViewModels[sectionEnd - 1]); - } - } - private void OnExpandAllBlocksCommand() { foreach (var blockViewModel in ItemFilterBlockViewModels.OfType()) @@ -1293,103 +1290,107 @@ namespace Filtration.ViewModels } } - private void OnDeleteBlockCommand() - { - DeleteBlock(SelectedBlockViewModel); - } - private void OnDisableBlockCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; - if (selectedBlockViewModel != null) + foreach (var block in SelectedBlockViewModels) { - selectedBlockViewModel.BlockEnabled = false; + if (block is IItemFilterCommentBlockViewModel) + { + if (!(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + foreach (var child in getChildren(block as IItemFilterCommentBlockViewModel)) + { + ((IItemFilterBlockViewModel)child).BlockEnabled = false; + } + } + } + else + { + (block as IItemFilterBlockViewModel).BlockEnabled = false; + } } } private void OnEnableBlockCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterBlockViewModel; - if (selectedBlockViewModel != null) + foreach (var block in SelectedBlockViewModels) { - selectedBlockViewModel.BlockEnabled = true; + if (block is IItemFilterCommentBlockViewModel) + { + if (!(block as IItemFilterCommentBlockViewModel).IsExpanded) + { + foreach (var child in getChildren(block as IItemFilterCommentBlockViewModel)) + { + ((IItemFilterBlockViewModel)child).BlockEnabled = true; + } + } + } + else + { + (block as IItemFilterBlockViewModel).BlockEnabled = true; + } } } private void OnDisableSectionCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (selectedBlockViewModel != null) + foreach (var block in SelectedBlockViewModels.OfType()) { - var sectionIndex = ItemFilterBlockViewModels.IndexOf(selectedBlockViewModel); - for (int i = sectionIndex + 1; i < ItemFilterBlockViewModels.Count; i++) + foreach (var child in getChildren(block as IItemFilterCommentBlockViewModel)) { - var block = ItemFilterBlockViewModels[i] as IItemFilterBlockViewModel; - if (block != null) - { - block.BlockEnabled = false; - } - else - break; + ((IItemFilterBlockViewModel)child).BlockEnabled = false; } } } private void OnEnableSectionCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (selectedBlockViewModel != null) + foreach (var block in SelectedBlockViewModels.OfType()) { - var sectionIndex = ItemFilterBlockViewModels.IndexOf(selectedBlockViewModel); - for (int i = sectionIndex + 1; i < ItemFilterBlockViewModels.Count; i++) + foreach (var child in getChildren(block as IItemFilterCommentBlockViewModel)) { - var block = ItemFilterBlockViewModels[i] as IItemFilterBlockViewModel; - if (block != null) - { - block.BlockEnabled = true; - } - else - break; + ((IItemFilterBlockViewModel)child).BlockEnabled = true; } } } private void OnExpandSectionCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (selectedBlockViewModel != null && !selectedBlockViewModel.IsExpanded) + foreach (var block in SelectedBlockViewModels.OfType()) { - ToggleSection(selectedBlockViewModel); + if (!block.IsExpanded) + { + ToggleSection(block); + } } } private void OnCollapseSectionCommand() { - var selectedBlockViewModel = SelectedBlockViewModel as IItemFilterCommentBlockViewModel; - if (selectedBlockViewModel != null && selectedBlockViewModel.IsExpanded) + foreach (var block in SelectedBlockViewModels.OfType()) { - ToggleSection(selectedBlockViewModel); + if (block.IsExpanded) + { + ToggleSection(block); + } } } - public void ToggleSection(IItemFilterCommentBlockViewModel targetCommentBlockViewModelBase, bool deferPropertyChanged = false) + public void ToggleSection(IItemFilterCommentBlockViewModel targetCommentBlockViewModelBase, bool deferViewUpdate = false) { var newState = !targetCommentBlockViewModelBase.IsExpanded; targetCommentBlockViewModelBase.IsExpanded = newState; - var sectionIndex = ItemFilterBlockViewModels.IndexOf(targetCommentBlockViewModelBase); - for (int i = sectionIndex + 1; i < ItemFilterBlockViewModels.Count; i++) + foreach (var child in getChildren(targetCommentBlockViewModelBase)) { - var block = ItemFilterBlockViewModels[i] as IItemFilterBlockViewModel; - if (block != null) - { - block.IsVisible = newState; - } - else - break; + child.IsVisible = newState; } - if (!deferPropertyChanged) + if (!deferViewUpdate) + { + ViewItemFilterBlockViewModels.Refresh(); + ValidateSelectedBlocks(); RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); + } } private void CollapseAllSections() @@ -1405,7 +1406,9 @@ namespace Filtration.ViewModels } } } - + + ViewItemFilterBlockViewModels.Refresh(); + ValidateSelectedBlocks(); RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); } @@ -1419,8 +1422,26 @@ namespace Filtration.ViewModels ToggleSection(block, true); } } - + + ViewItemFilterBlockViewModels.Refresh(); + ValidateSelectedBlocks(); RaisePropertyChanged(nameof(ViewItemFilterBlockViewModels)); } + + private void ExecuteCommandAndSelectAdded(ICommand command) + { + _lastAddedBlocks.Clear(); + _scriptCommandManager.ExecuteCommand(command); + SelectedBlockViewModels.Clear(); + foreach (var block in _lastAddedBlocks) + { + if (ViewItemFilterBlockViewModels.Contains(block)) + { + SelectedBlockViewModels.Add(block); + } + } + + ValidateSelectedBlocks(); + } } } diff --git a/Filtration/ViewModels/MainWindowViewModel.cs b/Filtration/ViewModels/MainWindowViewModel.cs index 997302b..be5f314 100644 --- a/Filtration/ViewModels/MainWindowViewModel.cs +++ b/Filtration/ViewModels/MainWindowViewModel.cs @@ -97,18 +97,18 @@ namespace Filtration.ViewModels RedoCommand = new RelayCommand(OnRedoCommand, () => ActiveDocumentIsScript); - MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); - MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); - MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); - MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); + MoveBlockUpCommand = new RelayCommand(OnMoveBlockUpCommand, () => ActiveDocumentIsScript && ActiveScriptHasSingleSelectedeBlock); + MoveBlockDownCommand = new RelayCommand(OnMoveBlockDownCommand, () => ActiveDocumentIsScript && ActiveScriptHasSingleSelectedeBlock); + MoveBlockToTopCommand = new RelayCommand(OnMoveBlockToTopCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock && ActiveScriptCanModifySelectedBlocks); + MoveBlockToBottomCommand = new RelayCommand(OnMoveBlockToBottomCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock && ActiveScriptCanModifySelectedBlocks); AddBlockCommand = new RelayCommand(OnAddBlockCommand, () => ActiveDocumentIsScript); AddSectionCommand = new RelayCommand(OnAddSectionCommand, () => ActiveDocumentIsScript); - DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedBlock); - DisableBlockCommand = new RelayCommand(OnDisableBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedEnabledBlock); - EnableBlockCommand = new RelayCommand(OnEnableBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedDisabledBlock); - DisableSectionCommand = new RelayCommand(OnDisableSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock); - EnableSectionCommand = new RelayCommand(OnEnableSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock); + DeleteBlockCommand = new RelayCommand(OnDeleteBlockCommand, () => ActiveDocumentIsScript && ActiveScriptCanModifySelectedBlocks); + DisableBlockCommand = new RelayCommand(OnDisableBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedEnabledBlock && ActiveScriptCanModifySelectedBlocks); + EnableBlockCommand = new RelayCommand(OnEnableBlockCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedDisabledBlock && ActiveScriptCanModifySelectedBlocks); + DisableSectionCommand = new RelayCommand(OnDisableSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock && ActiveScriptCanModifySelectedBlocks); + EnableSectionCommand = new RelayCommand(OnEnableSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock && ActiveScriptCanModifySelectedBlocks); ExpandSectionCommand = new RelayCommand(OnExpandSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock); CollapseSectionCommand = new RelayCommand(OnCollapseSectionCommand, () => ActiveDocumentIsScript && ActiveScriptHasSelectedCommentBlock); OpenAboutWindowCommand = new RelayCommand(OnOpenAboutWindowCommand); @@ -329,7 +329,9 @@ namespace Filtration.ViewModels public bool ActiveDocumentIsTheme => _avalonDockWorkspaceViewModel.ActiveDocument!= null && _avalonDockWorkspaceViewModel.ActiveDocument.IsTheme; - public bool ActiveScriptHasSelectedBlock => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel != null; + public bool ActiveScriptHasSelectedBlock => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.LastSelectedBlockViewModel != null; + + public bool ActiveScriptHasSingleSelectedeBlock => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModels.Count == 1; public bool ActiveScriptHasSelectedEnabledBlock => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.HasSelectedEnabledBlock(); @@ -337,6 +339,8 @@ namespace Filtration.ViewModels public bool ActiveScriptHasSelectedCommentBlock => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.HasSelectedCommentBlock(); + public bool ActiveScriptCanModifySelectedBlocks => AvalonDockWorkspaceViewModel.ActiveScriptViewModel.CanModifySelectedBlocks(); + public bool ActiveThemeIsEditable => AvalonDockWorkspaceViewModel.ActiveThemeViewModel.IsMasterTheme; diff --git a/Filtration/ViewModels/ToolPanes/BlockOutputPreviewViewModel.cs b/Filtration/ViewModels/ToolPanes/BlockOutputPreviewViewModel.cs index 13b08e3..6567855 100644 --- a/Filtration/ViewModels/ToolPanes/BlockOutputPreviewViewModel.cs +++ b/Filtration/ViewModels/ToolPanes/BlockOutputPreviewViewModel.cs @@ -30,14 +30,14 @@ namespace Filtration.ViewModels.ToolPanes { switch (message.Notification) { - case "SelectedBlockChanged": + case "LastSelectedBlockChanged": { - OnSelectedBlockChanged(this, EventArgs.Empty); + OnLastSelectedBlockChanged(this, EventArgs.Empty); break; } case "ActiveDocumentChanged": { - OnSelectedBlockChanged(this, EventArgs.Empty); + OnLastSelectedBlockChanged(this, EventArgs.Empty); break; } } @@ -62,9 +62,9 @@ namespace Filtration.ViewModels.ToolPanes PreviewText = string.Empty; } - private void OnSelectedBlockChanged(object sender, EventArgs e) + private void OnLastSelectedBlockChanged(object sender, EventArgs e) { - if (AvalonDockWorkspaceViewModel.ActiveScriptViewModel?.SelectedBlockViewModel == null) + if (AvalonDockWorkspaceViewModel.ActiveScriptViewModel?.LastSelectedBlockViewModel == null) { PreviewText = string.Empty; return; @@ -72,7 +72,7 @@ namespace Filtration.ViewModels.ToolPanes PreviewText = _itemFilterBlockTranslator.TranslateItemFilterBlockBaseToString( - AvalonDockWorkspaceViewModel.ActiveScriptViewModel.SelectedBlockViewModel.BaseBlock); + AvalonDockWorkspaceViewModel.ActiveScriptViewModel.LastSelectedBlockViewModel.BaseBlock); } } } diff --git a/Filtration/Views/AttachedProperties/SelectedItemsAttachedProperty.cs b/Filtration/Views/AttachedProperties/SelectedItemsAttachedProperty.cs new file mode 100644 index 0000000..6caee1c --- /dev/null +++ b/Filtration/Views/AttachedProperties/SelectedItemsAttachedProperty.cs @@ -0,0 +1,93 @@ +using System.Collections; +using System.Collections.Specialized; +using System.Windows; +using System.Windows.Controls; + +namespace Filtration.Views.AttachedProperties +{ + public static class SelectedItemsAttachedProperty + { + public static readonly DependencyProperty SelectedItemsProperty = + DependencyProperty.RegisterAttached("SelectedItems", typeof(IList), typeof(SelectedItemsAttachedProperty), + new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnSelectedItemsChanged))); + + public static IList GetSelectedItems(DependencyObject obj) + { + return (IList)obj.GetValue(SelectedItemsProperty); + } + + public static void SetSelectedItems(DependencyObject obj, IList value) + { + obj.SetValue(SelectedItemsProperty, value); + } + + private static void OnSelectedItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + var listbox = d as ListBox; + if (listbox != null) + { + listbox.SelectedItems.Clear(); + var selectedItems = e.NewValue as IList; + if (selectedItems != null) + { + foreach (var item in selectedItems) + { + listbox.SelectedItems.Add(item); + } + + listbox.SelectionChanged += (s, ev) => + { + if (null != ev.RemovedItems) + { + foreach (var item in ev.RemovedItems) + { + selectedItems.Remove(item); + } + } + if (null != ev.AddedItems) + { + foreach (var item in ev.AddedItems) + { + if (!selectedItems.Contains(item)) + { + selectedItems.Add(item); + } + } + } + }; + + if (selectedItems is INotifyCollectionChanged) + { + (selectedItems as INotifyCollectionChanged).CollectionChanged += (s, ev) => + { + // If this is the case, list requires re-adding all + if (ev.Action == NotifyCollectionChangedAction.Reset) + { + listbox.SelectedItems.Clear(); + } + + if (null != ev.OldItems) + { + foreach (var item in ev.OldItems) + { + listbox.SelectedItems.Remove(item); + } + } + + if (null != ev.NewItems) + { + foreach (var item in ev.NewItems) + { + if (!listbox.SelectedItems.Contains(item)) + { + listbox.SelectedItems.Add(item); + } + } + } + }; + } + } + } + } + } +} diff --git a/Filtration/Views/ItemFilterCommentBlockView.xaml b/Filtration/Views/ItemFilterCommentBlockView.xaml index e8a521e..7663edb 100644 --- a/Filtration/Views/ItemFilterCommentBlockView.xaml +++ b/Filtration/Views/ItemFilterCommentBlockView.xaml @@ -89,7 +89,7 @@