From 2c6caec76889f2784483dda7466e1b9d58eba1a6 Mon Sep 17 00:00:00 2001 From: "Vassiliy.Kudryashov" Date: Wed, 18 May 2016 22:33:13 +0300 Subject: [PATCH] IDEA-98634 Favorites List: sort entries: add manual (DnD) sorting --- .../favoritesTreeView/FavoritesManager.java | 39 +++++++++++-- .../ide/favoritesTreeView/FavoritesPanel.java | 58 +++++++++++++++++-- .../FavoritesTreeViewPanel.java | 1 - 3 files changed, 85 insertions(+), 13 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java index 5d00ea730bf5..09e521960f4f 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesManager.java @@ -40,7 +40,6 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.ArrayUtil; import com.intellij.util.Consumer; -import com.intellij.util.Function; import com.intellij.util.TreeItem; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; @@ -57,6 +56,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { // fav list name -> list of (root: root url, root class) private final Map>>> myName2FavoritesRoots = new TreeMap>>>(); + private final List myFavoritesRootsOrder = new ArrayList<>(); private final Map myDescriptions = new HashMap(); private final Project myProject; private final List myListeners = ContainerUtil.createLockFreeCopyOnWriteList(); @@ -134,7 +134,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { List createRootNodes() { List result = new ArrayList(); - for (String listName : myName2FavoritesRoots.keySet()) { + for (String listName : myFavoritesRootsOrder) { result.add(new FavoritesListNode(myProject, listName, myDescriptions.get(listName))); } ArrayList providers = new ArrayList(myProviders.values()); @@ -155,11 +155,12 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { @NotNull public List getAvailableFavoritesListNames() { - return new ArrayList(myName2FavoritesRoots.keySet()); + return new ArrayList(myFavoritesRootsOrder); } public synchronized void createNewList(@NotNull String listName) { myName2FavoritesRoots.put(listName, new ArrayList>>()); + myFavoritesRootsOrder.add(listName); listAdded(listName); } @@ -173,6 +174,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { public synchronized boolean removeFavoritesList(@NotNull String name) { boolean result = myName2FavoritesRoots.remove(name) != null; + myFavoritesRootsOrder.remove(name); myDescriptions.remove(name); listRemoved(name); return result; @@ -373,6 +375,12 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { private boolean renameFavoritesList(@NotNull String oldName, @NotNull String newName) { List>> list = myName2FavoritesRoots.remove(oldName); + int index = myFavoritesRootsOrder.indexOf(oldName); + if (index != -1 && newName.length() > 0) { + myFavoritesRootsOrder.remove(oldName); + myFavoritesRootsOrder.remove(newName); + myFavoritesRootsOrder.add(index, newName); + } if (list != null && newName.length() > 0) { myName2FavoritesRoots.put(newName, list); String description = myDescriptions.remove(oldName); @@ -385,6 +393,24 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { return false; } + public void setOrder(String nameToOrder, String anchorName, boolean above) { + if (!canReorder(nameToOrder, anchorName, above)) return; + int index = myFavoritesRootsOrder.indexOf(anchorName); + int toRemove = myFavoritesRootsOrder.indexOf(nameToOrder); + myFavoritesRootsOrder.add(above? index : index +1, nameToOrder); + myFavoritesRootsOrder.remove(toRemove > index ? toRemove+1 : toRemove); + rootsChanged(); + } + + public boolean canReorder(String nameToOrder, String anchorName, boolean above) { + int index = myFavoritesRootsOrder.indexOf(anchorName); + int toReorder = myFavoritesRootsOrder.indexOf(nameToOrder); + if (index ==-1 || toReorder ==-1 || index == toReorder) return false; + if (toReorder == index -1 && above) return false; + if (toReorder == index + 1 && !above) return false; + return true; + } + @Override public void initComponent() { } @@ -437,6 +463,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { final String name = ((Element)list).getAttributeValue(ATTRIBUTE_NAME); List>> roots = readRoots((Element)list, myProject); myName2FavoritesRoots.put(name, roots); + myFavoritesRootsOrder.add(name); } DefaultJDOMExternalizer.readExternal(this, element); } @@ -507,7 +534,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { @Override public void writeExternal(Element element) throws WriteExternalException { - for (final String name : myName2FavoritesRoots.keySet()) { + for (final String name : myFavoritesRootsOrder) { Element list = new Element(ELEMENT_FAVORITES_LIST); list.setAttribute(ATTRIBUTE_NAME, name); writeRoots(list, myName2FavoritesRoots.get(name)); @@ -681,7 +708,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { new DirectoryUrl(((PsiDirectory)newParent).getVirtualFile().getUrl() + "/" + ((PsiDirectory)child).getName(), module.getName()); } - for (String listName : myName2FavoritesRoots.keySet()) { + for (String listName : myFavoritesRootsOrder) { final List>> roots = myName2FavoritesRoots.get(listName); final AbstractUrl finalChildUrl = childUrl; iterateTreeItems(roots, item -> { @@ -715,7 +742,7 @@ public class FavoritesManager implements ProjectComponent, JDOMExternalizable { final String url = ((PsiDirectory)psiElement.getParent()).getVirtualFile().getUrl() + "/" + event.getNewValue(); final AbstractUrl childUrl = psiElement instanceof PsiFile ? new PsiFileUrl(url) : new DirectoryUrl(url, module.getName()); - for (String listName : myName2FavoritesRoots.keySet()) { + for (String listName : myFavoritesRootsOrder) { final List>> roots = myName2FavoritesRoots.get(listName); iterateTreeItems(roots, item -> { final Pair root = item.getData(); diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesPanel.java index 2ee4e3509a4f..4daee4665334 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesPanel.java @@ -28,7 +28,6 @@ import com.intellij.psi.PsiFileSystemItem; import com.intellij.psi.PsiManager; import com.intellij.psi.SmartPsiElementPointer; import com.intellij.ui.awt.RelativeRectangle; -import com.intellij.util.Function; import com.intellij.util.IconUtil; import org.jetbrains.annotations.Nullable; @@ -86,6 +85,18 @@ public class FavoritesPanel { } } } + if (path != null && path.getPathCount() == 2) { + Object o = path.getLastPathComponent(); + if (o instanceof DefaultMutableTreeNode) { + o = ((DefaultMutableTreeNode)o).getUserObject(); + if (o instanceof FavoritesTreeNodeDescriptor) { + FavoritesTreeNodeDescriptor root = ((FavoritesTreeNodeDescriptor)o).getFavoritesRoot(); + if (root == o) { + return new DnDDragStartBean(path); + } + } + } + } return new DnDDragStartBean("") { @Override public boolean isEmpty() { @@ -102,17 +113,25 @@ public class FavoritesPanel { event.setDropPossible(false); return false; } - if (obj instanceof TreePath && ((TreePath)obj).getPathCount() <= 2) { - event.setDropPossible(false); - return true; + int pathCount = 0; + if (obj instanceof TreePath) { + pathCount = ((TreePath)obj).getPathCount(); + if (pathCount < 2) { + event.setDropPossible(false); + return true; + } } FavoritesListNode node = myViewPanel.findFavoritesListNode(event.getPoint()); - if ((obj instanceof TreePath && myViewPanel.myTree.getPath(node).isDescendant((TreePath)obj)) || + if ((obj instanceof TreePath && pathCount == 3 && myViewPanel.myTree.getPath(node).isDescendant((TreePath)obj)) || (node != null && node.getProvider() != null)) { event.setDropPossible(false); return false; } highlight(node, event); + if (obj instanceof TreePath && pathCount == 2 && node != null && node.getProvider() == null) { + event.setDropPossible(true); + return true; + } if (node != null) { event.setDropPossible(true); return true; @@ -146,6 +165,12 @@ public class FavoritesPanel { } mgr.addRoots(listTo, null, element); } + if (path.getPathCount() == 2) {//favorites lists manual sorting + Rectangle bounds = myTree.getPathBounds(myTree.getPath(node)); + if (bounds != null) { + mgr.setOrder(listFrom, listTo, event.getPoint().y < bounds.y + bounds.height / 2); + } + } } else if (obj instanceof TransferableWrapper) { myViewPanel.dropPsiElements(mgr, node, ((TransferableWrapper)obj).getPsiElements()); @@ -164,6 +189,11 @@ public class FavoritesPanel { } private void highlight(FavoritesListNode node, DnDEvent event) { + int pathCount = 0; + Object object = event.getAttachedObject(); + if (object instanceof TreePath) { + pathCount = ((TreePath)object).getPathCount(); + } if (node != null) { TreePath pathToList = myTree.getPath(node); while (pathToList != null) { @@ -181,7 +211,23 @@ public class FavoritesPanel { if (pathToList != null) { Rectangle bounds = myTree.getPathBounds(pathToList); if (bounds != null) { - event.setHighlighting(new RelativeRectangle(myTree, bounds), DnDEvent.DropTargetHighlightingType.RECTANGLE); + if (pathCount == 2) { + FavoritesListNode pathToReorder = FavoritesTreeViewPanel.getListNodeFromPath((TreePath)object); + FavoritesListNode anchorPath = FavoritesTreeViewPanel.getListNodeFromPath(pathToList); + boolean below = event.getPoint().y >= bounds.y + bounds.height / 2; + if (pathToReorder == null || anchorPath == null || !FavoritesManager.getInstance(myProject).canReorder(pathToReorder.getValue(), anchorPath.getValue(), !below)) { + event.hideHighlighter(); + return; + } + if (below) { + bounds.y+=bounds.height - 2; + } + bounds.height = 2; + event.setHighlighting(new RelativeRectangle(myTree, bounds), DnDEvent.DropTargetHighlightingType.RECTANGLE); + } + else { + event.setHighlighting(new RelativeRectangle(myTree, bounds), DnDEvent.DropTargetHighlightingType.RECTANGLE); + } } } } diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java index ec2f2c292738..ed5a5d0c2274 100644 --- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/FavoritesTreeViewPanel.java @@ -32,7 +32,6 @@ import com.intellij.ide.ui.customization.CustomizationUtil; import com.intellij.ide.util.DirectoryChooserUtil; import com.intellij.ide.util.EditorHelper; import com.intellij.ide.util.treeView.AbstractTreeNode; -import com.intellij.ide.util.treeView.NodeDescriptor; import com.intellij.ide.util.treeView.NodeRenderer; import com.intellij.navigation.ItemPresentation; import com.intellij.openapi.Disposable;