diff --git a/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorTreeView.cs b/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorTreeView.cs index 2bff38b..3b327ee 100644 --- a/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorTreeView.cs +++ b/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorTreeView.cs @@ -13,7 +13,6 @@ namespace uPalette.Editor.Core.PaletteEditor internal abstract class PaletteEditorTreeView : TreeViewBase { private const string DragType = "PaletteEditorTreeView"; - public char FolderDelimiter => UPaletteProjectSettings.instance.FolderDelimiter; private readonly Dictionary _columnIndexToThemeIdMap = new Dictionary(); private readonly Dictionary _entryIdToItemIdMap = new Dictionary(); @@ -42,6 +41,8 @@ protected PaletteEditorTreeView(TreeViewState state) : base(state) SetupColumnStates(); } + public char FolderDelimiter => UPaletteProjectSettings.instance.FolderDelimiter; + public IObservable<(PaletteEditorTreeViewEntryItem item, int newIndex)> ItemIndexChangedAsObservable => _itemIndexChangedSubject; @@ -75,8 +76,7 @@ public PaletteEditorTreeViewEntryItem AddItem(string entryId, string name, Di { var entryItem = new PaletteEditorTreeViewEntryItem(entryId, name, values) { - id = _currentItemId++, - displayName = name + id = _currentItemId++ }; _entryIdToItemIdMap.Add(entryId, entryItem.id); AddItemAndSetParent(entryItem, -1); @@ -84,7 +84,11 @@ public PaletteEditorTreeViewEntryItem AddItem(string entryId, string name, Di return entryItem; } - private void SetHierarchy(int entryItemId) + /// + /// Set the item as a child item of the appropriate parent item. If there is no parent item, create it. + /// + /// + public void SetHierarchy(int entryItemId) { var entryItem = (PaletteEditorTreeViewEntryItem)GetItem(entryItemId); @@ -126,17 +130,11 @@ private void SetHierarchy(int entryItemId) } // Parenting - var oldFolderPath = entryItem.Name.Value; // cache for removing empty folder - var oldParent = entryItem.parent; // cache for removing empty folder var folderItemId = string.IsNullOrEmpty(folderPath) ? -1 : _folderPathToItemIdMap[folderPath]; SetParent(entryItemId, folderItemId); - // Remove empty folder - if (oldParent.id != -1 && !oldParent.hasChildren) - { - _folderPathToItemIdMap.Remove(oldFolderPath); - RemoveItem(oldParent.id, false); - } + // Remove empty folders + RemoveEmptyFolders(); // Set display name var nonFolderName = hasFolder @@ -154,6 +152,41 @@ private void SetHierarchy(int entryItemId) } } + private void RemoveEmptyFolders() + { + // Process in order of long folder path (from the end folder) + var orderedFolderPaths = _folderPathToItemIdMap.Keys + .OrderByDescending(x => x.Length) + .ToArray(); + + var removeTargetFolders = new List<(string path, int itemId)>(); + foreach (var folderPath in orderedFolderPaths) + { + var folderItemId = _folderPathToItemIdMap[folderPath]; + var folderItem = GetItem(folderItemId); + + // if folder has no children, remove it. + if (!folderItem.hasChildren) + { + removeTargetFolders.Add((folderPath, folderItemId)); + continue; + } + + // if all children are remove target, remove it. + var allChildrenAreRemoveTarget = folderItem.children + .All(x => removeTargetFolders.Any(y => y.itemId == x.id)); + if (allChildrenAreRemoveTarget) + removeTargetFolders.Add((folderPath, folderItemId)); + } + + foreach (var removeTargetFolder in removeTargetFolders) + { + var removeTargetFolderItemId = removeTargetFolder.itemId; + _folderPathToItemIdMap.Remove(removeTargetFolder.path); + RemoveItem(removeTargetFolderItemId, false); + } + } + public void SetFolderMode(bool folderMode, bool reload = true) { if (FolderMode == folderMode) @@ -197,7 +230,7 @@ private void RemoveParentItemsIfEmpty(TreeViewItem item) RemoveParentItemsIfEmpty(parent); } } - + protected override bool CanRename(TreeViewItem item) { // Rename is not supported for folder. @@ -207,7 +240,7 @@ protected override bool CanRename(TreeViewItem item) // Set displayName to full name during rename. if (FolderMode) item.displayName = ((PaletteEditorTreeViewEntryItem)item).Name.Value; - + return true; } @@ -217,6 +250,7 @@ protected override void RenameEnded(RenameEndedArgs args) if (args.acceptedRename) item.SetName(args.newName, true); + // Set displayName to non-folder name after rename. if (FolderMode) { var name = item.Name.Value; @@ -226,11 +260,6 @@ protected override void RenameEnded(RenameEndedArgs args) : name; item.displayName = nonFolderName; } - - SetHierarchy(item.id); - if (FolderMode) - OrderItemsByName(item.parent, true); - Reload(); } protected override void CellGUI(int columnIndex, Rect cellRect, RowGUIArgs args) @@ -312,7 +341,7 @@ protected override bool CanStartDrag(CanStartDragArgs args) // Index is not supported in folder mode because items are sorted by name. if (FolderMode) return false; - + return string.IsNullOrEmpty(searchString); } @@ -342,7 +371,7 @@ protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) // Index is not supported in folder mode because items are sorted by name. if (FolderMode) return DragAndDropVisualMode.None; - + if (args.performDrop) { var data = DragAndDrop.GetGenericData(DragType); @@ -378,6 +407,12 @@ protected override DragAndDropVisualMode HandleDragAndDrop(DragAndDropArgs args) return DragAndDropVisualMode.Move; } + /// + /// Sort items by specifying index + /// + /// + /// + /// public void SetItemIndex(PaletteEditorTreeViewEntryItem entryItem, int index, bool notify) { var children = RootItem.children; @@ -388,6 +423,10 @@ public void SetItemIndex(PaletteEditorTreeViewEntryItem entryItem, int index, _itemIndexChangedSubject.OnNext((entryItem, index)); } + /// + /// Sort items according to name + /// + /// public void SetItemIndexByName(TreeViewItem item) { var children = item.parent.children; @@ -401,6 +440,11 @@ public void SetItemIndexByName(TreeViewItem item) children.Insert(index, item); } + /// + /// Sort all items under according to name + /// + /// + /// public void OrderItemsByName(TreeViewItem parent, bool recursive) { if (parent.children == null) diff --git a/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorWindowContentsViewPresenter.cs b/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorWindowContentsViewPresenter.cs index 67741d3..e811bbf 100644 --- a/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorWindowContentsViewPresenter.cs +++ b/Assets/uPalette/Editor/Core/PaletteEditor/PaletteEditorWindowContentsViewPresenter.cs @@ -59,9 +59,11 @@ public PaletteEditorWindowContentsViewPresenter(Palette palette, PaletteEdito foreach (var entry in sortedEntries) { var index = _palette.GetEntryOrder(entry.Id); - AddTreeViewItem(entry, index); + AddTreeViewItem(entry, index, false); } + _view.TreeView.OrderItemsByName(_view.TreeView.RootItem, true); + view.TreeView.Reload(); } @@ -98,7 +100,7 @@ private void OnThemeOrderChanged() RefreshTreeViewColumns(); } - private void AddTreeViewItem(Entry entry, int index) + private void AddTreeViewItem(Entry entry, int index, bool doSort = true) { var treeView = _view.TreeView; @@ -112,10 +114,13 @@ private void AddTreeViewItem(Entry entry, int index) } var item = treeView.AddItem(entry.Id, entry.Name.Value, values); - if (treeView.FolderMode) - treeView.SetItemIndexByName(item); - else - treeView.SetItemIndex(item, index, false); + if (doSort) + { + if (treeView.FolderMode) + treeView.SetItemIndexByName(item); + else + treeView.SetItemIndex(item, index, false); + } // Observe entry. var disposable = new CompositeDisposable(); @@ -152,6 +157,17 @@ private void AddTreeViewItem(Entry entry, int index) .Subscribe(x => item.ClearValues()) .DisposeWith(disposable); + entry.Name.Subscribe(x => + { + treeView.SetHierarchy(item.id); + if (treeView.FolderMode) + treeView.SetItemIndexByName(item); + else + treeView.SetItemIndex(item, index, false); + treeView.Reload(); + }) + .DisposeWith(disposable); + _perItemDisposables.Add(entry.Id, disposable); treeView.Reload(); }