Project view: support manual oder

This commit is contained in:
Anton Makeev
2014-10-20 16:49:15 +02:00
parent eb6dc97f79
commit 78df394d95
19 changed files with 271 additions and 1 deletions

View File

@@ -15,19 +15,30 @@
*/
package com.intellij.projectView;
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.*;
import com.intellij.ide.projectView.impl.AbstractProjectViewPSIPane;
import com.intellij.ide.projectView.impl.ProjectViewImpl;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
private ProjectView myProjectView;
private AbstractProjectViewPSIPane myPane;
private boolean myOriginalManualOrder;
private boolean myOriginalSortByType;
private boolean myOriginalFoldersAlwaysOnTop;
@@ -41,6 +52,7 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
myProjectView = ProjectView.getInstance(myProject);
myProjectView.addProjectPane(myPane);
myOriginalManualOrder = myProjectView.isManualOrder(myPane.getId());
myOriginalSortByType = myProjectView.isSortByType(myPane.getId());
myOriginalFoldersAlwaysOnTop = ((ProjectViewImpl)myProjectView).isFoldersAlwaysOnTop();
@@ -49,6 +61,7 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
@Override
public void tearDown() throws Exception {
myProjectView.setManualOrder(myPane.getId(), myOriginalManualOrder);
myProjectView.setSortByType(myPane.getId(), myOriginalSortByType);
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(myOriginalFoldersAlwaysOnTop);
myProjectView.removeProjectPane(myPane);
@@ -151,9 +164,195 @@ public class ProjectTreeSortingTest extends BaseProjectViewTestCase {
" +b_folder\n");
}
public void testManualOrder() throws Exception {
MyOrderProvider provider = new MyOrderProvider(myProject);
provider.setOrder("b_ordered.java",
"a_folder_ordered",
"b_ordered.txt",
"a_ordered.txt",
"b_folder_ordered",
"a_ordered.java");
getProjectTreeStructure().setProviders(provider);
myProjectView.setManualOrder(myPane.getId(), true);
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(true);
myProjectView.setSortByType(myPane.getId(), false);
assertTree("-manualOrder\n" +
" b_ordered.java\n" +
" +a_folder_ordered\n" +
" b_ordered.txt\n" +
" a_ordered.txt\n" +
" +b_folder_ordered\n" +
" a_ordered.java\n" +
" +a_folder_unordered\n" +
" +b_folder_unordered\n" +
" a_unordered.java\n" +
" a_unordered.txt\n" +
" b_unordered.java\n" +
" b_unordered.txt\n");
myProjectView.setSortByType(myPane.getId(), true);
assertTree("-manualOrder\n" +
" b_ordered.java\n" +
" +a_folder_ordered\n" +
" b_ordered.txt\n" +
" a_ordered.txt\n" +
" +b_folder_ordered\n" +
" a_ordered.java\n" +
" +a_folder_unordered\n" +
" +b_folder_unordered\n" +
" a_unordered.java\n" +
" b_unordered.java\n" +
" a_unordered.txt\n" +
" b_unordered.txt\n");
((ProjectViewImpl)myProjectView).setFoldersAlwaysOnTop(false);
myProjectView.setSortByType(myPane.getId(), false);
assertTree("-manualOrder\n" +
" b_ordered.java\n" +
" +a_folder_ordered\n" +
" b_ordered.txt\n" +
" a_ordered.txt\n" +
" +b_folder_ordered\n" +
" a_ordered.java\n" +
" +a_folder_unordered\n" +
" a_unordered.java\n" +
" a_unordered.txt\n" +
" +b_folder_unordered\n" +
" b_unordered.java\n" +
" b_unordered.txt\n");
myProjectView.setSortByType(myPane.getId(), true);
assertTree("-manualOrder\n" +
" b_ordered.java\n" +
" +a_folder_ordered\n" +
" b_ordered.txt\n" +
" a_ordered.txt\n" +
" +b_folder_ordered\n" +
" a_ordered.java\n" +
" a_unordered.java\n" +
" b_unordered.java\n" +
" a_unordered.txt\n" +
" b_unordered.txt\n" +
" +a_folder_unordered\n" +
" +b_folder_unordered\n");
}
private void assertTree(String expected) {
DefaultMutableTreeNode element = myPane.getTreeBuilder().getNodeForElement(getContentDirectory());
assertNotNull("Element for " + getContentDirectory() + " not found", element);
assertEquals(expected, PlatformTestUtil.print(myPane.getTree(), element, new Queryable.PrintInfo(), false));
}
static class MyOrderProvider implements TreeStructureProvider {
private final Project myProject;
private final Map<String, Integer> myOrder = new LinkedHashMap<String, Integer>();
public MyOrderProvider(Project project) {
myProject = project;
}
void setOrder(String... fileNames) {
int i = 0;
for (String each : fileNames) {
myOrder.put(each, i++);
}
}
@NotNull
@Override
public Collection<AbstractTreeNode> modify(@NotNull AbstractTreeNode parent,
@NotNull Collection<AbstractTreeNode> children,
ViewSettings settings) {
ArrayList<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
for (final AbstractTreeNode child : children) {
ProjectViewNode treeNode = (ProjectViewNode)child;
final Object o = treeNode.getValue();
if (o instanceof PsiFileSystemItem) {
final Integer order = myOrder.get(((PsiFileSystemItem)o).getVirtualFile().getName());
treeNode = new ProjectViewNode<PsiFileSystemItem>(myProject, (PsiFileSystemItem)o, settings) {
@Override
@NotNull
public Collection<AbstractTreeNode> getChildren() {
return child.getChildren();
}
@Override
public String toTestString(Queryable.PrintInfo printInfo) {
return child.toTestString(printInfo);
}
@Override
public int getWeight() {
return ((ProjectViewNode)child).getWeight();
}
@Nullable
@Override
public Comparable getSortKey() {
return ((ProjectViewNode)child).getSortKey();
}
@Nullable
@Override
public Comparable getManualOrderKey() {
return order == null ? null : order;
}
@Nullable
@Override
public String getQualifiedNameSortKey() {
return ((ProjectViewNode)child).getQualifiedNameSortKey();
}
@Nullable
@Override
public Comparable getTypeSortKey() {
return ((ProjectViewNode)child).getTypeSortKey();
}
@Override
public int getTypeSortWeight(boolean sortByType) {
return ((ProjectViewNode)child).getTypeSortWeight(sortByType);
}
@Override
public String getTestPresentation() {
return child.getTestPresentation();
}
@Override
public boolean contains(@NotNull VirtualFile file) {
return ((ProjectViewNode)child).contains(file);
}
@Override
public void update(PresentationData presentation) {
}
@Override
public String toString() {
return ((PsiFileSystemItem)o).getName();
}
};
}
result.add(treeNode);
}
return result;
}
@Override
public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
return null;
}
}
}

View File

@@ -253,6 +253,11 @@ public abstract class ProjectViewNode <Value> extends AbstractTreeNode<Value> im
return null;
}
@Nullable
public Comparable getManualOrderKey() {
return null;
}
@Nullable
public String getQualifiedNameSortKey() {
return null;

View File

@@ -87,6 +87,9 @@ public abstract class ProjectView {
public abstract void selectPsiElement(PsiElement element, boolean requestFocus);
public abstract boolean isManualOrder(String paneId);
public abstract void setManualOrder(@NotNull String paneId, final boolean enabled);
public abstract boolean isSortByType(String paneId);
public abstract void setSortByType(@NotNull String paneId, final boolean sortByType);

View File

@@ -155,6 +155,10 @@ public abstract class AbstractProjectViewPane implements DataProvider, Disposabl
return true;
}
public boolean supportsManualOrder() {
return false;
}
/**
* @return all supported sub views IDs.
* should return empty array if there is no subViews as in Project/Packages view.

View File

@@ -66,6 +66,18 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
ProjectViewNode node1 = (ProjectViewNode)descriptor1;
ProjectViewNode node2 = (ProjectViewNode)descriptor2;
if (isManualOrder()) {
final Comparable key1 = node1.getManualOrderKey();
final Comparable key2 = node2.getManualOrderKey();
if (!(key1 == null && key2 == null)) {
if (key1 == null) return 1;
if (key2 == null) return -1;
//noinspection unchecked
final int result = key1.compareTo(key2);
if (result != 0) return result;
}
}
boolean isFoldersOnTop = !(projectView instanceof ProjectViewImpl && !((ProjectViewImpl)projectView).isFoldersAlwaysOnTop());
if (isFoldersOnTop) {
@@ -116,6 +128,13 @@ public class GroupByTypeComparator implements Comparator<NodeDescriptor> {
return AlphaComparator.INSTANCE.compare(descriptor1, descriptor2);
}
protected boolean isManualOrder() {
if (myProjectView != null) {
return myProjectView.isManualOrder(myPaneId);
}
return true;
}
protected boolean isSortByType() {
if (myProjectView != null) {
return myProjectView.isSortByType(myPaneId);

View File

@@ -126,6 +126,8 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
private static final boolean ourFlattenPackagesDefaults = false;
private final Map<String, Boolean> myShowMembers = new THashMap<String, Boolean>();
private static final boolean ourShowMembersDefaults = false;
private final Map<String, Boolean> myManualOrder = new THashMap<String, Boolean>();
private static final boolean ourManualOrderDefaults = false;
private final Map<String, Boolean> mySortByType = new THashMap<String, Boolean>();
private static final boolean ourSortByTypeDefaults = false;
private final Map<String, Boolean> myShowModules = new THashMap<String, Boolean>();
@@ -703,6 +705,7 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
myActionGroup.addAction(myAutoScrollToSourceHandler.createToggleAction()).setAsSecondary(true);
myActionGroup.addAction(myAutoScrollFromSourceHandler.createToggleAction()).setAsSecondary(true);
myActionGroup.addAction(new ManualOrderAction()).setAsSecondary(true);
myActionGroup.addAction(new SortByTypeAction()).setAsSecondary(true);
myActionGroup.addAction(new FoldersAlwaysOnTopAction()).setAsSecondary(true);
@@ -1783,6 +1786,18 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
}
}
@Override
public boolean isManualOrder(String paneId) {
return getPaneOptionValue(myManualOrder, paneId, ourManualOrderDefaults);
}
@Override
public void setManualOrder(@NotNull String paneId, final boolean enabled) {
setPaneOption(myManualOrder, enabled, paneId, false);
final AbstractProjectViewPane pane = getProjectViewPaneById(paneId);
pane.installComparator();
}
@Override
public boolean isSortByType(String paneId) {
return getPaneOptionValue(mySortByType, paneId, ourSortByTypeDefaults);
@@ -1795,6 +1810,30 @@ public class ProjectViewImpl extends ProjectView implements PersistentStateCompo
pane.installComparator();
}
private class ManualOrderAction extends ToggleAction {
private ManualOrderAction() {
super(IdeBundle.message("action.manual.order"), IdeBundle.message("action.manual.order"), AllIcons.ObjectBrowser.Sorted);
}
@Override
public boolean isSelected(AnActionEvent event) {
return isManualOrder(getCurrentViewId());
}
@Override
public void setSelected(AnActionEvent event, boolean flag) {
setManualOrder(getCurrentViewId(), flag);
}
@Override
public void update(final AnActionEvent e) {
super.update(e);
final Presentation presentation = e.getPresentation();
AbstractProjectViewPane pane = getCurrentProjectViewPane();
presentation.setVisible(pane != null && pane.supportsManualOrder());
}
}
private class SortByTypeAction extends ToggleAction {
private SortByTypeAction() {
super(IdeBundle.message("action.sort.by.type"), IdeBundle.message("action.sort.by.type"), AllIcons.ObjectBrowser.SortByType);

View File

@@ -561,6 +561,7 @@ action.show.libraries.contents=Show Libraries Contents
action.show.hide.library.contents=Show/Hide Library Contents
action.show.excluded.files=Show Excluded Files
action.show.hide.excluded.files=Show/Hide Excluded Files
action.manual.order=Manual Order
action.sort.by.type=Sort by Type
action.show.structure=Show Structure
action.description.show.structure=Show structure view