From 9a26bf5df27cf6129bf2307d10d42c7a91f1ecb3 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Tue, 14 Feb 2012 16:07:29 +0100 Subject: [PATCH] File chooser: return logical paths along with chosen files --- .../openapi/fileChooser/FileChooserUtil.java | 53 ++++++++++++ .../openapi/fileChooser/FileSystemTree.java | 9 +-- .../fileChooser/ex/FileChooserDialogImpl.java | 31 ++++--- .../fileChooser/ex/FileSystemTreeImpl.java | 81 ++++++++++++------- 4 files changed, 124 insertions(+), 50 deletions(-) create mode 100644 platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserUtil.java diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserUtil.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserUtil.java new file mode 100644 index 000000000000..f6514e44135e --- /dev/null +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserUtil.java @@ -0,0 +1,53 @@ +/* + * Copyright 2000-2012 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.openapi.fileChooser; + +import com.intellij.openapi.util.Key; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.ArrayUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Temporary class, do not use. + * Will be removed after migration from file choosing to path choosing (approx. in IDEA 13). + * + * @author Roman Shevchenko + */ +public final class FileChooserUtil { + private static final Key PATH_KEY = Key.create("FileChooser.Path"); + + @NotNull + public static String getSelectionPath(@NotNull final VirtualFile file) { + final String path = file.getUserData(PATH_KEY); + return path != null ? path : file.getPath(); + } + + public static void setSelectionPath(@NotNull final VirtualFile file, @Nullable final String path) { + file.putUserData(PATH_KEY, path); + } + + @NotNull + public static String[] getPaths(@NotNull final VirtualFile[] files) { + if (files.length == 0) return ArrayUtil.EMPTY_STRING_ARRAY; + + final String[] paths = new String[files.length]; + for (int i = 0; i < files.length; i++) { + paths[i] = getSelectionPath(files[i]); + } + return paths; + } +} diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java index 3bde5bf497da..0fac828c721f 100644 --- a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java +++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileSystemTree.java @@ -17,8 +17,8 @@ package com.intellij.openapi.fileChooser; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.DataKey; -import com.intellij.openapi.util.Key; import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -26,7 +26,6 @@ import java.util.List; public interface FileSystemTree extends Disposable { DataKey DATA_KEY = DataKey.create("FileSystemTree"); - Key PATH_KEY = Key.create("FileSystemTree.Path"); JTree getTree(); @@ -35,11 +34,13 @@ public interface FileSystemTree extends Disposable { @Nullable VirtualFile getSelectedFile(); + @NotNull + VirtualFile[] getSelectedFiles(); + @Nullable VirtualFile getNewFileParent(); void select(VirtualFile file, @Nullable Runnable onDone); - void select(VirtualFile[] files, @Nullable Runnable onDone); void expand(VirtualFile file, @Nullable Runnable onDone); @@ -50,8 +51,6 @@ public interface FileSystemTree extends Disposable { boolean selectionExists(); - VirtualFile[] getSelectedFiles(); - boolean areHiddensShown(); void showHiddens(boolean showHidden); diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java index 3d75d48384f7..42086dc2fceb 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java @@ -24,10 +24,7 @@ import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.application.ApplicationActivationListener; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.fileChooser.FileChooserDescriptor; -import com.intellij.openapi.fileChooser.FileChooserDialog; -import com.intellij.openapi.fileChooser.FileElement; -import com.intellij.openapi.fileChooser.FileSystemTree; +import com.intellij.openapi.fileChooser.*; import com.intellij.openapi.fileChooser.impl.FileChooserFactoryImpl; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; @@ -269,8 +266,12 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } } - final VirtualFile[] selectedFiles = getSelectedFiles(); + if (selectedFiles.length == 0) { + close(CANCEL_EXIT_CODE); + return; + } + try { myChooserDescriptor.validateSelectedFiles(selectedFiles); } @@ -280,16 +281,15 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } myChosenFiles = selectedFiles; - if (selectedFiles.length == 0) { - close(CANCEL_EXIT_CODE); - return; - } - //noinspection AssignmentToStaticFieldFromInstanceMethod - ourLastFile = selectedFiles[selectedFiles.length - 1]; + setLastSelectedFile(selectedFiles[selectedFiles.length - 1]); super.doOKAction(); } + private static void setLastSelectedFile(final VirtualFile selectedFile) { + ourLastFile = selectedFile; + } + public final void doCancelAction() { myChosenFiles = VirtualFile.EMPTY_ARRAY; super.doCancelAction(); @@ -502,13 +502,9 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD }); } + // todo[r.sh] correct path if archive is picked via symlink private static String getFilePath(final VirtualFile file) { - final String path = file.getUserData(FileSystemTree.PATH_KEY); - if (path != null) { - return path; - } - - return file.isInLocalFileSystem() ? file.getPresentableUrl() : file.getUrl(); + return file.isInLocalFileSystem() ? FileChooserUtil.getSelectionPath(file) : file.getUrl(); } private void updateTreeFromPath(final String text) { @@ -545,6 +541,7 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD } } + // todo[r.sh] fix symlink selection private void selectInTree(final VirtualFile[] vFile, final boolean requestFocus) { myTreeIsUpdating = true; if (!Arrays.asList(myFileSystemTree.getSelectedFiles()).contains(vFile)) { diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java index 8e16d2d2e79a..16ececb7cdf0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSystemTreeImpl.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.fileChooser.ex; +import com.google.common.collect.Lists; import com.intellij.ide.util.treeView.AbstractTreeBuilder; import com.intellij.ide.util.treeView.AbstractTreeStructure; import com.intellij.ide.util.treeView.NodeDescriptor; @@ -26,6 +27,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.fileChooser.FileChooserDescriptor; +import com.intellij.openapi.fileChooser.FileChooserUtil; import com.intellij.openapi.fileChooser.FileElement; import com.intellij.openapi.fileChooser.FileSystemTree; import com.intellij.openapi.fileChooser.impl.FileComparator; @@ -46,9 +48,11 @@ import com.intellij.ui.SimpleTextAttributes; import com.intellij.ui.TreeSpeedSearch; import com.intellij.ui.UIBundle; import com.intellij.ui.treeStructure.Tree; -import com.intellij.util.containers.ConvertingIterator; +import com.intellij.util.Function; +import com.intellij.util.NullableFunction; import com.intellij.util.containers.Convertor; import com.intellij.util.ui.tree.TreeUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -332,12 +336,15 @@ public class FileSystemTreeImpl implements FileSystemTree { public VirtualFile getSelectedFile() { final TreePath path = myTree.getSelectionPath(); if (path == null) return null; - DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); if (!(node.getUserObject() instanceof FileNodeDescriptor)) return null; - FileNodeDescriptor descriptor = (FileNodeDescriptor)node.getUserObject(); - return descriptor.getElement().getFile(); + final FileElement element = ((FileNodeDescriptor)node.getUserObject()).getElement(); + final VirtualFile file = element.getFile(); + FileChooserUtil.setSelectionPath(file, element.getPath()); + return file; } + @Nullable public VirtualFile getNewFileParent() { if (getSelectedFile() != null) return getSelectedFile(); @@ -345,35 +352,53 @@ public class FileSystemTreeImpl implements FileSystemTree { return roots.size() > 0 ? roots.get(0) : null; } + @NotNull public VirtualFile[] getSelectedFiles() { - return collectSelectedFiles(new ConvertingIterator.IdConvertor()); - } - - public VirtualFile[] getChosenFiles() { - return collectSelectedFiles(new Convertor() { - @Nullable - public VirtualFile convert(VirtualFile file) { + final List files = collectSelectedElements(new NullableFunction() { + @Override + public VirtualFile fun(final FileElement element) { + final VirtualFile file = element.getFile(); if (file == null || !file.isValid()) return null; - return myTreeStructure.getChooserDescriptor().getFileToSelect(file); + FileChooserUtil.setSelectionPath(file, element.getPath()); + return file; } }); + return VfsUtil.toVirtualFileArray(files); } - private VirtualFile[] collectSelectedFiles(Convertor fileConverter) { - TreePath[] paths = myTree.getSelectionPaths(); - if (paths == null) return VirtualFile.EMPTY_ARRAY; - ArrayList files = new ArrayList(paths.length); - - for (TreePath path : paths) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); - if (!(node.getUserObject() instanceof FileNodeDescriptor)) return VirtualFile.EMPTY_ARRAY; - FileNodeDescriptor descriptor = (FileNodeDescriptor)node.getUserObject(); - VirtualFile file = fileConverter.convert(descriptor.getElement().getFile()); - if (file != null && file.isValid()) files.add(file); - } + @NotNull + public VirtualFile[] getChosenFiles() { + final List files = collectSelectedElements(new NullableFunction() { + @Override + public VirtualFile fun(final FileElement element) { + VirtualFile file = element.getFile(); + if (file == null || !file.isValid()) return null; + file = myTreeStructure.getChooserDescriptor().getFileToSelect(file); + FileChooserUtil.setSelectionPath(file, element.getPath()); + return file; + } + }); return VfsUtil.toVirtualFileArray(files); } + private List collectSelectedElements(final Function converter) { + final TreePath[] paths = myTree.getSelectionPaths(); + if (paths == null) return Collections.emptyList(); + + final List elements = Lists.newArrayList(); + for (TreePath path : paths) { + final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent(); + final Object userObject = node.getUserObject(); + if (userObject instanceof FileNodeDescriptor) { + final T element = converter.fun(((FileNodeDescriptor)userObject).getElement()); + if (element != null) { + elements.add(element); + } + } + } + return elements; + } + public boolean selectionExists() { TreePath[] selectedPaths = myTree.getSelectionPaths(); return selectedPaths != null && selectedPaths.length != 0; @@ -422,7 +447,7 @@ public class FileSystemTreeImpl implements FileSystemTree { final FileElement element = ((FileNodeDescriptor)object).getElement(); final VirtualFile file = element.getFile(); if (file != null) { - file.putUserData(PATH_KEY, element.getPath()); + FileChooserUtil.setSelectionPath(file, element.getPath()); selection.add(file); } } @@ -452,7 +477,8 @@ public class FileSystemTreeImpl implements FileSystemTree { } - boolean async = myTreeBuilder.getTreeStructure().isToBuildChildrenInBackground(virtualFile); + AbstractTreeStructure treeStructure = myTreeBuilder.getTreeStructure(); + boolean async = treeStructure != null && treeStructure.isToBuildChildrenInBackground(virtualFile); if (virtualFile instanceof NewVirtualFile) { RefreshQueue.getInstance().refresh(async, false, null, ModalityState.stateForComponent(myTree), virtualFile); } @@ -463,7 +489,6 @@ public class FileSystemTreeImpl implements FileSystemTree { } } - public void treeCollapsed(TreeExpansionEvent event) { - } + public void treeCollapsed(TreeExpansionEvent event) { } } }