| /* |
| * Copyright 2017 The Bazel Authors. All rights reserved. |
| * |
| * 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.google.idea.blaze.base.ui; |
| |
| import com.google.common.collect.ImmutableMap; |
| import com.google.idea.blaze.base.model.primitives.WorkspacePath; |
| import com.google.idea.blaze.base.sync.workspace.WorkspacePathResolver; |
| import com.intellij.openapi.Disposable; |
| import com.intellij.openapi.fileChooser.FileChooserDescriptor; |
| import com.intellij.openapi.fileChooser.FileTextField; |
| import com.intellij.openapi.fileChooser.ex.FileTextFieldImpl; |
| import com.intellij.openapi.fileChooser.ex.LocalFsFinder.FileChooserFilter; |
| import com.intellij.openapi.fileChooser.ex.LocalFsFinder.IoFile; |
| import com.intellij.openapi.fileChooser.ex.LocalFsFinder.VfsFile; |
| import com.intellij.openapi.vfs.LocalFileSystem; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.ui.components.JBTextField; |
| import java.io.File; |
| import javax.annotation.Nullable; |
| import javax.swing.JTextField; |
| |
| /** A text field that auto-completes paths in the workspace root. */ |
| // This outer class basically a copy of FileTextFieldImpl.Vfs but we can't use that directly because |
| // we need to specify our own custom Finder. |
| public final class WorkspaceFileTextField extends FileTextFieldImpl { |
| |
| private WorkspaceFileTextField( |
| WorkspacePathResolver pathResolver, |
| JTextField textField, |
| LookupFilter filter, |
| Disposable parent) { |
| super(textField, new WorkspaceFinder(pathResolver), filter, ImmutableMap.of(), parent); |
| } |
| |
| public static FileTextField create( |
| WorkspacePathResolver pathResolver, |
| FileChooserDescriptor descriptor, |
| int columns, |
| Disposable parent) { |
| JTextField textField = new WorkspacePathTextField(pathResolver, columns); |
| return new WorkspaceFileTextField( |
| pathResolver, textField, new FileChooserFilter(descriptor, /* showHidden */ true), parent); |
| } |
| |
| @Nullable |
| @Override |
| public VirtualFile getSelectedFile() { |
| LookupFile lookupFile = getFile(); |
| return lookupFile != null ? ((VfsFile) lookupFile).getFile() : null; |
| } |
| |
| private static class WorkspaceFinder implements Finder { |
| |
| private final WorkspacePathResolver pathResolver; |
| |
| private WorkspaceFinder(WorkspacePathResolver pathResolver) { |
| this.pathResolver = pathResolver; |
| } |
| |
| @Nullable |
| @Override |
| public LookupFile find(String path) { |
| File file = new File(normalize(path)); |
| VirtualFile vFile = LocalFileSystem.getInstance().findFileByIoFile(file); |
| if (vFile != null) { |
| return new VfsFile(/* unused LocalFsFinder */ null, vFile); |
| } else if (file.isAbsolute()) { |
| return new IoFile(new File(path)); |
| } |
| return null; |
| } |
| |
| @Override |
| public String normalize(String path) { |
| File file = new File(path); |
| if (!file.isAbsolute()) { |
| file = pathResolver.resolveToFile(path); |
| } |
| |
| return file.getAbsolutePath(); |
| } |
| |
| @Override |
| public String getSeparator() { |
| return File.separator; |
| } |
| } |
| |
| // FileTextFieldImpl calls setText with the absolute path after every filename autocomplete. But |
| // we don't want to swap in the absolute path, we'd rather just show the path relative to the |
| // workspace root. So we override setText(). |
| private static class WorkspacePathTextField extends JBTextField { |
| |
| final WorkspacePathResolver pathResolver; |
| |
| WorkspacePathTextField(WorkspacePathResolver pathResolver, int columns) { |
| super(columns); |
| this.pathResolver = pathResolver; |
| } |
| |
| @Override |
| public void setText(String path) { |
| WorkspacePath workspacePath = pathResolver.getWorkspacePath(new File(path)); |
| if (workspacePath == null) { |
| super.setText(path); |
| return; |
| } |
| |
| String relativePath = workspacePath.relativePath(); |
| if (path.endsWith(File.separator) && !relativePath.endsWith(File.separator)) { |
| relativePath += File.separator; |
| } |
| super.setText(relativePath); |
| } |
| } |
| } |