From 675500b54d64fcf466792000a477fb0af4db099c Mon Sep 17 00:00:00 2001 From: ReMinoer Date: Tue, 26 Jul 2022 18:57:50 +0200 Subject: [PATCH] Implement insert above/below in data tree --- Calame.Icons/Providers/CalameIconProvider.cs | 2 + Calame/Icons/CalameIconKey.cs | 2 + Calame/Utils/AddCollectionItemCommand.cs | 57 +++++++++++++++---- .../ViewModels/DataModelTreeViewModel.cs | 34 ++++++++--- 4 files changed, 78 insertions(+), 17 deletions(-) diff --git a/Calame.Icons/Providers/CalameIconProvider.cs b/Calame.Icons/Providers/CalameIconProvider.cs index 098758d..31eed48 100644 --- a/Calame.Icons/Providers/CalameIconProvider.cs +++ b/Calame.Icons/Providers/CalameIconProvider.cs @@ -44,6 +44,8 @@ protected override PackIconMaterialKind GetTargetKey(CalameIconKey key) case CalameIconKey.Folder: return PackIconMaterialKind.FolderOpen; case CalameIconKey.Add: return PackIconMaterialKind.PlusCircle; case CalameIconKey.AddFromList: return PackIconMaterialKind.PlaylistPlus; + case CalameIconKey.InsertAbove: return PackIconMaterialKind.ArrowUpRightBold; + case CalameIconKey.InsertBelow: return PackIconMaterialKind.ArrowDownRightBold; case CalameIconKey.Delete: return PackIconMaterialKind.CloseCircle; case CalameIconKey.Select: return PackIconMaterialKind.ArrowTopRightThick; case CalameIconKey.OpenWith: return PackIconMaterialKind.ApplicationImport; diff --git a/Calame/Icons/CalameIconKey.cs b/Calame/Icons/CalameIconKey.cs index f675995..2bed6b8 100644 --- a/Calame/Icons/CalameIconKey.cs +++ b/Calame/Icons/CalameIconKey.cs @@ -36,6 +36,8 @@ public enum CalameIconKey Folder, Add, AddFromList, + InsertAbove, + InsertBelow, Delete, Select, OpenWith, diff --git a/Calame/Utils/AddCollectionItemCommand.cs b/Calame/Utils/AddCollectionItemCommand.cs index 4024f53..194b481 100644 --- a/Calame/Utils/AddCollectionItemCommand.cs +++ b/Calame/Utils/AddCollectionItemCommand.cs @@ -17,6 +17,8 @@ public class AddCollectionItemCommand : ICommand private readonly IList _newTypeRegistry; private readonly IIconProvider _iconProvider; private readonly IIconDescriptor _iconDescriptor; + private readonly object _targetItem; + private readonly bool _afterTarget; private IList _newItemTypes; private readonly ICommand _addItemCommand; @@ -25,29 +27,54 @@ public class AddCollectionItemCommand : ICommand public event EventHandler CanExecuteChanged; - public AddCollectionItemCommand(IList list, Action insertItemAction, IList newTypeRegistry, IIconProvider iconProvider, IIconDescriptor iconDescriptor) + public AddCollectionItemCommand(IList list, + Action insertItemAction, + IList newTypeRegistry, + IIconProvider iconProvider, + IIconDescriptor iconDescriptor, + object targetItem = null, + bool afterTarget = false) { _list = list; _insertItemAction = insertItemAction; _newTypeRegistry = newTypeRegistry; _iconProvider = iconProvider; _iconDescriptor = iconDescriptor; - _addItemCommand = new RelayCommand(x => InsertItemOfType(_list.Count, (Type)x)); + _targetItem = targetItem; + _afterTarget = afterTarget; + _addItemCommand = new RelayCommand(x => InsertItemOfType((Type)x)); RefreshNewItemTypes(); } - public bool CanExecute(object _) => _newItemTypes != null && _newItemTypes.Count > 0; - public void Execute(object _) + public bool CanExecute(object obj) => _newItemTypes != null && _newItemTypes.Count > 0; + public void Execute(object obj) { if (_newItemTypes.Count == 1) { - InsertItemOfType(_list.Count, _newItemTypes[0]); + InsertItemOfType(_newItemTypes[0]); return; } var contextMenu = new ContextMenu(); + BuildMenuItems(contextMenu.Items); + contextMenu.IsOpen = true; + } + + public void SetupMenuItem(MenuItem menuItem) + { + if (_newItemTypes.Count == 1) + { + menuItem.Command = _addItemCommand; + menuItem.CommandParameter = _newItemTypes[0]; + return; + } + + BuildMenuItems(menuItem.Items); + } + public void BuildMenuItems(IList menuItems) + { string[] typeNames = _newItemTypes.Select(x => x.Name).ToArray(); ReduceTypeNamePatterns(typeNames); @@ -61,14 +88,24 @@ public void Execute(object _) Icon = _iconProvider.GetControl(_iconDescriptor.GetTypeIcon(_newItemTypes[i]), 16) }; - contextMenu.Items.Add(menuItem); + menuItems.Add(menuItem); } - - contextMenu.IsOpen = true; } - private void InsertItemOfType(int index, Type itemType) => InsertItem(index, CreateItem(itemType)); - private void InsertItem(int index, object item) => _insertItemAction?.Invoke(index, item); + private void InsertItemOfType(Type itemType) => InsertItem(CreateItem(itemType)); + private void InsertItem(object item) => _insertItemAction?.Invoke(GetTargetIndex(), item); + + private int GetTargetIndex() + { + if (_targetItem is null) + return _list.Count; + + int index = _list.IndexOf(_targetItem); + if (_afterTarget) + index++; + + return index; + } private object CreateItem(Type type) { diff --git a/Modules/Calame.DataModelTree/ViewModels/DataModelTreeViewModel.cs b/Modules/Calame.DataModelTree/ViewModels/DataModelTreeViewModel.cs index f1397ea..464341b 100644 --- a/Modules/Calame.DataModelTree/ViewModels/DataModelTreeViewModel.cs +++ b/Modules/Calame.DataModelTree/ViewModels/DataModelTreeViewModel.cs @@ -93,18 +93,19 @@ public DataModelTreeViewModel(IShell shell, IEventAggregator eventAggregator, II .ChildrenSource(x => new EnumerableReadOnlyObservableList(x.Children), nameof(IGlyphDataChildrenSource.Children)) .IconDescription(x => IconDescriptor.GetIcon(x.Children), nameof(IGlyphDataChildrenSource.Children)) .IsHeader(_ => true) - .QuickCommand(CreateAddCommand, nameof(IGlyphDataChildrenSource.Children)) + .QuickCommand(x => CreateAddCommand(x), nameof(IGlyphDataChildrenSource.Children)) .QuickCommandIconDescription(_ => new IconDescription(CalameIconKey.Add, Brushes.DarkGreen, margin: 0.5)) .QuickCommandLabel(_ => "Add") .QuickCommandToolTip(_ => "Add"); } - private ICommand CreateAddCommand(IGlyphDataChildrenSource childrenSource) + private AddCollectionItemCommand CreateAddCommand(IGlyphDataChildrenSource childrenSource, IGlyphData insertTarget = null, bool afterTarget = false) { if (!(childrenSource.Children is IList list)) return null; - return new AddCollectionItemCommand(list, (i, x) => AddDataChild(childrenSource, i, (IGlyphData)x), _newTypeRegistry, IconProvider, IconDescriptor); + return new AddCollectionItemCommand(list, + (i, x) => AddDataChild(childrenSource, i, (IGlyphData)x), _newTypeRegistry, IconProvider, IconDescriptor, insertTarget, afterTarget); } private void AddDataChild(IGlyphDataChildrenSource childrenSource, int index, IGlyphData child) @@ -130,9 +131,31 @@ private IEnumerable GetContextMenuItems(IGlyphData data) { if (data.ParentSource != null) { + if (data.ParentSource is IGlyphDataChildrenSource childrenSource) + { + var insertAboveItem = new MenuItem + { + Header = "Insert _Above", + Icon = IconProvider.GetControl(IconDescriptor.GetIcon(CalameIconKey.InsertAbove), 16) + }; + + var insertBelowItem = new MenuItem + { + Header = "_Insert Below", + Icon = IconProvider.GetControl(IconDescriptor.GetIcon(CalameIconKey.InsertBelow), 16) + }; + + CreateAddCommand(childrenSource, insertTarget: data).SetupMenuItem(insertAboveItem); + CreateAddCommand(childrenSource, insertTarget: data, afterTarget: true).SetupMenuItem(insertBelowItem); + + yield return insertAboveItem; + yield return insertBelowItem; + yield return new Separator(); + } + yield return new MenuItem { - Header = "Remove", + Header = "_Remove", Command = _removeCommand, CommandParameter = data, Icon = IconProvider.GetControl(IconDescriptor.GetIcon(CalameIconKey.Delete), 16) @@ -148,9 +171,6 @@ private void OnRemove(object obj) var child = (IGlyphData)obj; - if (Selection == child) - Selection = null; - IGlyphDataSource childrenSource = child.ParentSource; int index = childrenSource.IndexOf(child);