From cbc61c0f1334decba1a47f087d645eecc087efe5 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 3 Jan 2013 12:28:05 +0100 Subject: [PATCH] Finder like sorting + IDEA-80435 Project file sorting --- .../impl/GroupByTypeComparator.java | 72 ++++++++++--------- .../ide/projectView/impl/ProjectViewImpl.java | 44 +++++++++++- .../impl/nodes/PsiDirectoryNode.java | 8 ++- .../ide/util/treeView/AlphaComparator.java | 29 +++++++- 4 files changed, 116 insertions(+), 37 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java index 162f1ee76be0..10131d29cfaf 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/GroupByTypeComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ import com.intellij.ide.projectView.ProjectViewNode; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.ide.util.treeView.AlphaComparator; import com.intellij.ide.util.treeView.NodeDescriptor; +import com.intellij.openapi.project.Project; import java.util.Collection; import java.util.Comparator; @@ -60,41 +61,46 @@ public class GroupByTypeComparator implements Comparator { } if (descriptor1 instanceof ProjectViewNode && descriptor2 instanceof ProjectViewNode) { - ProjectViewNode node1 = (ProjectViewNode) descriptor1; - ProjectViewNode node2 = (ProjectViewNode) descriptor2; - int typeWeight1 = node1.getTypeSortWeight(isSortByType()); - int typeWeight2 = node2.getTypeSortWeight(isSortByType()); - if (typeWeight1 != 0 && typeWeight2 == 0) { - return -1; - } - if (typeWeight1 == 0 && typeWeight2 != 0) { - return 1; - } - if (typeWeight1 != 0 && typeWeight2 != typeWeight1) { - return typeWeight1 - typeWeight2; - } - - if (isSortByType()) { - final Comparable typeSortKey1 = node1.getTypeSortKey(); - final Comparable typeSortKey2 = node2.getTypeSortKey(); - if (typeSortKey1 != null && typeSortKey2 != null) { - final int result = typeSortKey1.compareTo(typeSortKey2); - if (result != 0) return result; + final Project project = descriptor1.getProject(); + final ProjectView projectView = ProjectView.getInstance(project); + if (!(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop())) { + ProjectViewNode node1 = (ProjectViewNode)descriptor1; + ProjectViewNode node2 = (ProjectViewNode)descriptor2; + int typeWeight1 = node1.getTypeSortWeight(isSortByType()); + int typeWeight2 = node2.getTypeSortWeight(isSortByType()); + if (typeWeight1 != 0 && typeWeight2 == 0) { + return -1; } - } else { - final Comparable typeSortKey1 = node1.getSortKey(); - final Comparable typeSortKey2 = node2.getSortKey(); - if (typeSortKey1 != null && typeSortKey2 != null) { - final int result = typeSortKey1.compareTo(typeSortKey2); - if (result != 0) return result; + if (typeWeight1 == 0 && typeWeight2 != 0) { + return 1; + } + if (typeWeight1 != 0 && typeWeight2 != typeWeight1) { + return typeWeight1 - typeWeight2; } - } - if (isAbbreviateQualifiedNames()) { - String key1 = node1.getQualifiedNameSortKey(); - String key2 = node2.getQualifiedNameSortKey(); - if (key1 != null && key2 != null) { - return key1.compareToIgnoreCase(key2); + if (isSortByType()) { + final Comparable typeSortKey1 = node1.getTypeSortKey(); + final Comparable typeSortKey2 = node2.getTypeSortKey(); + if (typeSortKey1 != null && typeSortKey2 != null) { + final int result = typeSortKey1.compareTo(typeSortKey2); + if (result != 0) return result; + } + } + else { + final Comparable typeSortKey1 = node1.getSortKey(); + final Comparable typeSortKey2 = node2.getSortKey(); + if (typeSortKey1 != null && typeSortKey2 != null) { + final int result = typeSortKey1.compareTo(typeSortKey2); + if (result != 0) return result; + } + } + + if (isAbbreviateQualifiedNames()) { + String key1 = node1.getQualifiedNameSortKey(); + String key2 = node2.getQualifiedNameSortKey(); + if (key1 != null && key2 != null) { + return key1.compareToIgnoreCase(key2); + } } } } diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java index 5452650d5e9f..841862ffed7f 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -175,6 +175,8 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo @NonNls private static final String ELEMENT_AUTOSCROLL_TO_SOURCE = "autoscrollToSource"; @NonNls private static final String ELEMENT_AUTOSCROLL_FROM_SOURCE = "autoscrollFromSource"; @NonNls private static final String ELEMENT_SORT_BY_TYPE = "sortByType"; + @NonNls private static final String ELEMENT_FOLDERS_ALWAYS_ON_TOP = "foldersAlwaysOnTop"; + private static final String ATTRIBUTE_ID = "id"; private JPanel myViewContentPanel; private static final Comparator PANE_WEIGHT_COMPARATOR = new Comparator() { @@ -190,6 +192,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo private final Map myUninitializedPaneState = new HashMap(); private final Map mySelectInTargets = new HashMap(); private ContentManager myContentManager; + private boolean myFoldersAlwaysOnTop = true; public ProjectViewImpl(Project project, final FileEditorManager fileEditorManager, final ToolWindowManagerEx toolWindowManager) { myProject = project; @@ -681,6 +684,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo myActionGroup.addAction(myAutoScrollToSourceHandler.createToggleAction()).setAsSecondary(true); myActionGroup.addAction(myAutoScrollFromSourceHandler.createToggleAction()).setAsSecondary(true); myActionGroup.addAction(new SortByTypeAction()).setAsSecondary(true); + myActionGroup.addAction(new FoldersAlwaysOnTopAction()).setAsSecondary(true); if (!myAutoScrollFromSourceHandler.isAutoScrollEnabled()) { myActionGroup.addAction(new ScrollFromSourceAction()); @@ -1438,6 +1442,21 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo setPaneOption(myFlattenPackages, flattenPackages, paneId, true); } + public boolean isFoldersAlwaysOnTop() { + return myFoldersAlwaysOnTop; + } + + public void setFoldersAlwaysOnTop(boolean foldersAlwaysOnTop) { + if (myFoldersAlwaysOnTop != foldersAlwaysOnTop) { + myFoldersAlwaysOnTop = foldersAlwaysOnTop; + for (AbstractProjectViewPane pane : myId2Pane.values()) { + if (pane.getTree() != null) { + pane.updateFromRoot(false); + } + } + } + } + @Override public boolean isShowMembers(String paneId) { return getPaneOptionValue(myShowMembers, paneId, ourShowMembersDefaults); @@ -1777,6 +1796,29 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo } } + private class FoldersAlwaysOnTopAction extends ToggleAction { + private FoldersAlwaysOnTopAction() { + super("Folders Always on Top"); + } + + @Override + public boolean isSelected(AnActionEvent event) { + return isFoldersAlwaysOnTop(); + } + + @Override + public void setSelected(AnActionEvent event, boolean flag) { + setFoldersAlwaysOnTop(flag); + } + + @Override + public void update(final AnActionEvent e) { + super.update(e); + final Presentation presentation = e.getPresentation(); + presentation.setVisible(getCurrentProjectViewPane() != null); + } + } + private class ScrollFromSourceAction extends AnAction implements DumbAware { private ScrollFromSourceAction() { super("Scroll from Source", "Select the file open in the active editor", AllIcons.General.Locate); diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java index 501080820c3c..8cd1a62d4451 100644 --- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java +++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/PsiDirectoryNode.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,10 @@ import com.intellij.ide.IconProvider; import com.intellij.ide.bookmarks.Bookmark; import com.intellij.ide.bookmarks.BookmarkManager; import com.intellij.ide.projectView.PresentationData; +import com.intellij.ide.projectView.ProjectView; import com.intellij.ide.projectView.ViewSettings; import com.intellij.ide.projectView.impl.ProjectRootsUtil; +import com.intellij.ide.projectView.impl.ProjectViewImpl; import com.intellij.ide.util.treeView.AbstractTreeNode; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.module.Module; @@ -262,6 +264,10 @@ public class PsiDirectoryNode extends BasePsiNode implements Navig @Override public int getWeight() { + final ProjectView projectView = ProjectView.getInstance(myProject); + if (projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop()) { + return 20; + } return isFQNameShown() ? 70 : 0; } diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AlphaComparator.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AlphaComparator.java index 88a8a3b7a704..b5a71e4375d2 100644 --- a/platform/platform-api/src/com/intellij/ide/util/treeView/AlphaComparator.java +++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AlphaComparator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,6 +15,7 @@ */ package com.intellij.ide.util.treeView; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.text.StringUtil; import java.util.Comparator; @@ -37,6 +38,30 @@ public class AlphaComparator implements Comparator{ if (s1 == null) return s2 == null ? 0 : -1; if (s2 == null) return +1; - return StringUtil.naturalCompare(s1, s2); + //for super natural comparison (IDEA-80435) + Pair normalized = normalize(s1, s2); + return StringUtil.naturalCompare(normalized.first, normalized.second); + } + + private static Pair normalize(String s1, String s2) { + final int minLen = Math.min(s1.length(), s2.length()); + final StringBuilder sb1 = new StringBuilder(s1); + final StringBuilder sb2 = new StringBuilder(s2); + for (int i = 0; i < minLen; i++) { + final char ch1 = s1.charAt(i); + final char ch2 = sb2.charAt(i); + if (ch1 == ch2 && ch1 == '-') { + sb1.setCharAt(i, '_'); + sb2.setCharAt(i, '_'); + } else if (ch1 == '-' && ch2 != '_') { + sb1.setCharAt(i, '_'); + } else if (ch2 == '-' && ch1 != '_') { + sb2.setCharAt(i, '_'); + } + } + + s1 = sb1.toString(); + s2 = sb2.toString(); + return Pair.create(s1, s2); } }