From bfd722d362519a643e62271a83de2641cdaa6db0 Mon Sep 17 00:00:00 2001 From: azakhi Date: Fri, 7 Sep 2018 15:26:12 +0300 Subject: [PATCH] Add add/delete block group support to blocks --- .../ItemFilterBlockGroup.cs | 57 ++++++++- .../ItemFilterBlockGroupViewModel.cs | 6 +- .../ViewModels/ItemFilterBlockViewModel.cs | 115 +++++++++++++++++- .../ToolPanes/BlockGroupBrowserViewModel.cs | 7 +- Filtration/Views/ItemFilterBlockView.xaml | 45 ++++++- Filtration/Views/ItemFilterBlockView.xaml.cs | 10 ++ 6 files changed, 230 insertions(+), 10 deletions(-) diff --git a/Filtration.ObjectModel/ItemFilterBlockGroup.cs b/Filtration.ObjectModel/ItemFilterBlockGroup.cs index 3a24984..1c0ab43 100644 --- a/Filtration.ObjectModel/ItemFilterBlockGroup.cs +++ b/Filtration.ObjectModel/ItemFilterBlockGroup.cs @@ -17,14 +17,14 @@ namespace Filtration.ObjectModel IsLeafNode = isLeafNode; } - public event EventHandler BlockGroupStatusChanged; - public string GroupName { get; } - public ItemFilterBlockGroup ParentGroup { get; } + public ItemFilterBlockGroup ParentGroup { get; set; } public List ChildGroups { get; } public bool Advanced { get; } public bool IsLeafNode { get; } + public event EventHandler BlockGroupStatusChanged; + public bool? IsShowChecked { get { return _isShowChecked; } @@ -55,6 +55,57 @@ namespace Filtration.ObjectModel } } + public void ClearStatusChangeSubscribers() + { + BlockGroupStatusChanged = null; + } + + public void AddOrJoinBlockGroup(ItemFilterBlockGroup blockGroup) + { + var childIndex = ChildGroups.FindIndex(item => item.GroupName.Equals(blockGroup.GroupName)); + if (!blockGroup.IsLeafNode && childIndex >= 0) + { + while(blockGroup.ChildGroups.Count > 0) + { + ChildGroups[childIndex].AddOrJoinBlockGroup(blockGroup.ChildGroups[0]); + } + } + else + { + if(blockGroup.ParentGroup != null) + { + blockGroup.ParentGroup.ChildGroups.Remove(blockGroup); + } + blockGroup.ParentGroup = this; + ChildGroups.Add(blockGroup); + } + } + + public void DetachSelf(bool keepChildren) + { + if(ParentGroup == null) + return; + + if(IsLeafNode && ParentGroup.ParentGroup != null && ParentGroup.ChildGroups.Count < 2) + { + ParentGroup.DetachSelf(false); + } + else + { + ParentGroup.ChildGroups.Remove(this); + + if (keepChildren) + { + foreach(var child in ChildGroups) + { + ParentGroup.AddOrJoinBlockGroup(child); + } + } + + ParentGroup = null; + } + } + public override string ToString() { if(ParentGroup == null) diff --git a/Filtration/ViewModels/ItemFilterBlockGroupViewModel.cs b/Filtration/ViewModels/ItemFilterBlockGroupViewModel.cs index d6558bd..d4fd44b 100644 --- a/Filtration/ViewModels/ItemFilterBlockGroupViewModel.cs +++ b/Filtration/ViewModels/ItemFilterBlockGroupViewModel.cs @@ -28,6 +28,7 @@ namespace Filtration.ViewModels ParentGroup = parent; Advanced = itemFilterBlockGroup.Advanced; SourceBlockGroup = itemFilterBlockGroup; + SourceBlockGroup.ClearStatusChangeSubscribers(); SourceBlockGroup.BlockGroupStatusChanged += OnSourceBlockGroupStatusChanged; IsShowChecked = itemFilterBlockGroup.IsShowChecked; IsEnableChecked = itemFilterBlockGroup.IsEnableChecked; @@ -205,8 +206,9 @@ namespace Filtration.ViewModels private void UpdateChildrenCheckState(bool isShowCheck) { - // Update children only when state is not null - if(isShowCheck && IsShowChecked != null) + // Update children only when state is not null which means update is either from children + // (all children must have same value to be not null) or from user + if (isShowCheck && IsShowChecked != null) { foreach (var childGroup in ChildGroups.Where(c => IsShowChecked != null)) { diff --git a/Filtration/ViewModels/ItemFilterBlockViewModel.cs b/Filtration/ViewModels/ItemFilterBlockViewModel.cs index 5bf50e3..59bdf3f 100644 --- a/Filtration/ViewModels/ItemFilterBlockViewModel.cs +++ b/Filtration/ViewModels/ItemFilterBlockViewModel.cs @@ -12,6 +12,7 @@ using Filtration.ObjectModel.Enums; using Filtration.Services; using Filtration.Views; using GalaSoft.MvvmLight.CommandWpf; +using GalaSoft.MvvmLight.Messaging; using Microsoft.Win32; using Xceed.Wpf.Toolkit; @@ -52,6 +53,8 @@ namespace Filtration.ViewModels PlayPositionalSoundCommand = new RelayCommand(OnPlayPositionalSoundCommand, () => HasPositionalSound); PlayCustomSoundCommand = new RelayCommand(OnPlayCustomSoundCommand, () => HasCustomSound); CustomSoundFileDialogCommand = new RelayCommand(OnCustomSoundFileDialog); + AddBlockGroupCommand = new RelayCommand(OnAddBlockGroupCommand); + DeleteBlockGroupCommand = new RelayCommand(OnDeleteBlockGroupCommand, () => BlockGroups.Count > 0); } public override void Initialise(IItemFilterBlockBase itemFilterBlockBase, IItemFilterScriptViewModel parentScriptViewModel) @@ -62,6 +65,8 @@ namespace Filtration.ViewModels throw new ArgumentNullException(nameof(itemFilterBlock)); } + BlockGroups = new ObservableCollection(); + _parentScriptViewModel = parentScriptViewModel; Block = itemFilterBlock; @@ -74,6 +79,8 @@ namespace Filtration.ViewModels blockItem.PropertyChanged += OnBlockItemChanged; } base.Initialise(itemFilterBlock, parentScriptViewModel); + + UpdateBlockGroups(); } public RelayCommand CopyBlockStyleCommand { get; } @@ -87,9 +94,16 @@ namespace Filtration.ViewModels public RelayCommand SwitchBlockItemsViewCommand { get; } public RelayCommand CustomSoundFileDialogCommand { get; } public RelayCommand PlayCustomSoundCommand { get; } + public RelayCommand AddBlockGroupCommand { get; } + public RelayCommand DeleteBlockGroupCommand { get; } public IItemFilterBlock Block { get; private set; } + public ObservableCollection BlockGroups { get; internal set; } + + public ObservableCollection BlockGroupSuggestions { get; internal set; } + + public string BlockGroupSearch { get; set; } public bool IsExpanded { @@ -118,7 +132,7 @@ namespace Filtration.ViewModels get { return Block.BlockItems.Where(b => b is IAudioVisualBlockItem); } } - public bool AdvancedBlockGroup => Block.BlockGroup != null && Block.BlockGroup.Advanced; + public bool AdvancedBlockGroup => Block.BlockGroup?.ParentGroup != null && Block.BlockGroup.ParentGroup.Advanced; public bool AudioVisualBlockItemsGridVisible { @@ -535,5 +549,104 @@ namespace Filtration.ViewModels MessageBox.Show("Couldn't play the file. Please be sure it is a valid audio file."); } } + + private void OnAddBlockGroupCommand() + { + var baseBlock = Block as ItemFilterBlock; + if (baseBlock == null) + return; + + if (!string.IsNullOrWhiteSpace(BlockGroupSearch)) + { + var blockToAdd = _parentScriptViewModel.Script.ItemFilterBlockGroups.First(); + if(BlockGroups.Count > 0) + { + blockToAdd = BlockGroups.Last(); + } + + var newGroup = new ItemFilterBlockGroup(BlockGroupSearch, null, AdvancedBlockGroup, false); + if (baseBlock.BlockGroup == null) + { + baseBlock.BlockGroup = new ItemFilterBlockGroup("", null, false, true); + baseBlock.BlockGroup.IsShowChecked = baseBlock.Action == BlockAction.Show; + baseBlock.BlockGroup.IsEnableChecked = BlockEnabled; + } + newGroup.AddOrJoinBlockGroup(baseBlock.BlockGroup); + blockToAdd.AddOrJoinBlockGroup(newGroup); + + Block.IsEdited = true; + _parentScriptViewModel.SetDirtyFlag(); + + Messenger.Default.Send(new NotificationMessage(_parentScriptViewModel.ShowAdvanced, "BlockGroupsChanged")); + UpdateBlockGroups(); + } + + BlockGroupSearch = ""; + RaisePropertyChanged(nameof(BlockGroupSearch)); + } + + private void OnDeleteBlockGroupCommand() + { + if(BlockGroups.Count > 0) + { + Block.BlockGroup.DetachSelf(false); + BlockGroups.RemoveAt(BlockGroups.Count - 1); + + var blockToAdd = _parentScriptViewModel.Script.ItemFilterBlockGroups.First(); + if (BlockGroups.Count > 0) + { + blockToAdd = BlockGroups.Last(); + } + blockToAdd.AddOrJoinBlockGroup(Block.BlockGroup); + + Block.IsEdited = true; + _parentScriptViewModel.SetDirtyFlag(); + + Messenger.Default.Send(new NotificationMessage(_parentScriptViewModel.ShowAdvanced, "BlockGroupsChanged")); + UpdateBlockGroups(); + } + } + + private void UpdateBlockGroups() + { + var baseBlock = Block as ItemFilterBlock; + if (baseBlock == null) + return; + + var currentGroup = baseBlock.BlockGroup; + var groupList = new List(); + while (currentGroup != null) + { + groupList.Add(currentGroup); + currentGroup = currentGroup.ParentGroup; + } + + var topGroup = _parentScriptViewModel.Script.ItemFilterBlockGroups.First(); + if (groupList.Count > 1) + { + groupList.Reverse(); + groupList.RemoveAt(0); + groupList.RemoveAt(groupList.Count - 1); + + if(groupList.Count > 0) + { + topGroup = groupList.Last(); + } + } + + BlockGroups = new ObservableCollection(groupList); + BlockGroupSuggestions = new ObservableCollection(); + + foreach(var child in topGroup.ChildGroups) + { + if(!child.IsLeafNode) + { + BlockGroupSuggestions.Add(child.GroupName); + } + } + + RaisePropertyChanged(nameof(BlockGroups)); + RaisePropertyChanged(nameof(BlockGroupSuggestions)); + } } } diff --git a/Filtration/ViewModels/ToolPanes/BlockGroupBrowserViewModel.cs b/Filtration/ViewModels/ToolPanes/BlockGroupBrowserViewModel.cs index df6aa24..b8fccb5 100644 --- a/Filtration/ViewModels/ToolPanes/BlockGroupBrowserViewModel.cs +++ b/Filtration/ViewModels/ToolPanes/BlockGroupBrowserViewModel.cs @@ -43,6 +43,11 @@ namespace Filtration.ViewModels.ToolPanes OnShowAdvancedToggled(message.Content); break; } + case "BlockGroupsChanged": + { + BlockGroupViewModels = RebuildBlockGroupViewModels(message.Content); + break; + } } }); @@ -107,7 +112,7 @@ namespace Filtration.ViewModels.ToolPanes // This assumes that there will only ever be a single root node. return new ObservableCollection ( - new ItemFilterBlockGroupViewModel(AvalonDockWorkspaceViewModel.ActiveScriptViewModel.Script.ItemFilterBlockGroups.First(), showAdvanced, null).ChildGroups + new ItemFilterBlockGroupViewModel(AvalonDockWorkspaceViewModel.ActiveScriptViewModel.Script.ItemFilterBlockGroups.First(), showAdvanced, null).VisibleChildGroups ); } diff --git a/Filtration/Views/ItemFilterBlockView.xaml b/Filtration/Views/ItemFilterBlockView.xaml index d2d61fa..e7d1929 100644 --- a/Filtration/Views/ItemFilterBlockView.xaml +++ b/Filtration/Views/ItemFilterBlockView.xaml @@ -5,6 +5,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:viewModels="clr-namespace:Filtration.ViewModels" xmlns:userControls="clr-namespace:Filtration.UserControls" + xmlns:toolkit="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Input.Toolkit" xmlns:views="clr-namespace:Filtration.Views" xmlns:converters="clr-namespace:Filtration.Converters" xmlns:blockItemBaseTypes="clr-namespace:Filtration.ObjectModel.BlockItemBaseTypes;assembly=Filtration.ObjectModel" @@ -200,9 +201,47 @@ + + + + + + + + + + + + + + + + + + + + + +