ability to set predefined text in choose by name popup
[fedora-idea.git] / platform / lang-impl / src / com / intellij / ide / util / TreeFileChooserDialog.java
blob8f1b0e827bca0faa52e424b5cca3e9894e044836
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package com.intellij.ide.util;
19 import com.intellij.ide.IdeBundle;
20 import com.intellij.ide.projectView.BaseProjectTreeBuilder;
21 import com.intellij.ide.projectView.ProjectViewNode;
22 import com.intellij.ide.projectView.TreeStructureProvider;
23 import com.intellij.ide.projectView.impl.AbstractProjectTreeStructure;
24 import com.intellij.ide.projectView.impl.ProjectAbstractTreeStructureBase;
25 import com.intellij.ide.projectView.impl.ProjectTreeBuilder;
26 import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
27 import com.intellij.ide.util.gotoByName.ChooseByNameModel;
28 import com.intellij.ide.util.gotoByName.ChooseByNamePanel;
29 import com.intellij.ide.util.gotoByName.ChooseByNamePopupComponent;
30 import com.intellij.ide.util.gotoByName.GotoFileCellRenderer;
31 import com.intellij.ide.util.treeView.AlphaComparator;
32 import com.intellij.ide.util.treeView.NodeRenderer;
33 import com.intellij.openapi.application.ApplicationManager;
34 import com.intellij.openapi.application.ModalityState;
35 import com.intellij.openapi.fileTypes.FileType;
36 import com.intellij.openapi.fileTypes.FileTypeManager;
37 import com.intellij.openapi.project.Project;
38 import com.intellij.openapi.ui.DialogWrapper;
39 import com.intellij.openapi.util.Condition;
40 import com.intellij.openapi.util.Disposer;
41 import com.intellij.openapi.vfs.VirtualFile;
42 import com.intellij.openapi.wm.ex.WindowManagerEx;
43 import com.intellij.psi.PsiElement;
44 import com.intellij.psi.PsiFile;
45 import com.intellij.psi.PsiManager;
46 import com.intellij.psi.search.FilenameIndex;
47 import com.intellij.psi.search.GlobalSearchScope;
48 import com.intellij.ui.TabbedPaneWrapper;
49 import com.intellij.ui.TreeSpeedSearch;
50 import com.intellij.ui.treeStructure.Tree;
51 import com.intellij.util.ArrayUtil;
52 import com.intellij.util.ui.UIUtil;
53 import gnu.trove.THashSet;
54 import org.jetbrains.annotations.NotNull;
55 import org.jetbrains.annotations.Nullable;
57 import javax.swing.*;
58 import javax.swing.event.ChangeEvent;
59 import javax.swing.event.ChangeListener;
60 import javax.swing.event.TreeSelectionEvent;
61 import javax.swing.event.TreeSelectionListener;
62 import javax.swing.tree.DefaultMutableTreeNode;
63 import javax.swing.tree.DefaultTreeModel;
64 import javax.swing.tree.TreePath;
65 import javax.swing.tree.TreeSelectionModel;
66 import java.awt.*;
67 import java.awt.event.KeyAdapter;
68 import java.awt.event.KeyEvent;
69 import java.awt.event.MouseAdapter;
70 import java.awt.event.MouseEvent;
71 import java.util.ArrayList;
72 import java.util.Arrays;
73 import java.util.List;
74 import java.util.Set;
76 /**
77 * @author Anton Katilin
78 * @author Vladimir Kondratyev
80 public final class TreeFileChooserDialog extends DialogWrapper implements TreeFileChooser {
81 private Tree myTree;
82 private PsiFile mySelectedFile = null;
83 private final Project myProject;
84 private BaseProjectTreeBuilder myBuilder;
85 private TabbedPaneWrapper myTabbedPane;
86 private ChooseByNamePanel myGotoByNamePanel;
87 @Nullable private final PsiFile myInitialFile;
88 @Nullable private final PsiFileFilter myFilter;
89 @Nullable private final FileType myFileType;
91 private final boolean myDisableStructureProviders;
92 private final boolean myShowLibraryContents;
94 public TreeFileChooserDialog(final Project project,
95 String title,
96 @Nullable final PsiFile initialFile,
97 @Nullable FileType fileType,
98 @Nullable PsiFileFilter filter,
99 final boolean disableStructureProviders,
100 final boolean showLibraryContents) {
101 super(project, true);
102 myInitialFile = initialFile;
103 myFilter = filter;
104 myFileType = fileType;
105 myDisableStructureProviders = disableStructureProviders;
106 myShowLibraryContents = showLibraryContents;
107 setTitle(title);
108 myProject = project;
109 init();
110 if (initialFile != null) {
111 // dialog does not exist yet
112 SwingUtilities.invokeLater(new Runnable(){
113 public void run() {
114 selectFile(initialFile);
119 SwingUtilities.invokeLater(new Runnable(){
120 public void run() {
121 handleSelectionChanged();
126 protected JComponent createCenterPanel() {
127 final DefaultTreeModel model = new DefaultTreeModel(new DefaultMutableTreeNode());
128 myTree = new Tree(model);
130 final ProjectAbstractTreeStructureBase treeStructure = new AbstractProjectTreeStructure(myProject) {
131 public boolean isFlattenPackages() {
132 return false;
135 public boolean isShowMembers() {
136 return false;
139 public boolean isHideEmptyMiddlePackages() {
140 return true;
143 public Object[] getChildElements(final Object element) {
144 return filterFiles(super.getChildElements(element));
147 public boolean isAbbreviatePackageNames() {
148 return false;
151 public boolean isShowLibraryContents() {
152 return myShowLibraryContents;
155 public boolean isShowModules() {
156 return false;
159 public List<TreeStructureProvider> getProviders() {
160 return myDisableStructureProviders ? null : super.getProviders();
163 myBuilder = new ProjectTreeBuilder(myProject, myTree, model, AlphaComparator.INSTANCE, treeStructure);
165 myTree.setRootVisible(false);
166 myTree.expandRow(0);
167 myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
168 myTree.setCellRenderer(new NodeRenderer());
169 UIUtil.setLineStyleAngled(myTree);
171 final JScrollPane scrollPane = new JScrollPane(myTree);
172 scrollPane.setPreferredSize(new Dimension(500, 300));
174 myTree.addKeyListener(new KeyAdapter() {
175 public void keyPressed(final KeyEvent e) {
176 if (KeyEvent.VK_ENTER == e.getKeyCode()) {
177 doOKAction();
182 myTree.addMouseListener(new MouseAdapter() {
183 public void mouseClicked(final MouseEvent e) {
184 if (e.getClickCount() == 2) {
185 final TreePath path = myTree.getPathForLocation(e.getX(), e.getY());
186 if (path != null && myTree.isPathSelected(path)) {
187 doOKAction();
193 myTree.addTreeSelectionListener(
194 new TreeSelectionListener() {
195 public void valueChanged(final TreeSelectionEvent e) {
196 handleSelectionChanged();
201 new TreeSpeedSearch(myTree);
203 myTabbedPane = new TabbedPaneWrapper(getDisposable());
205 final JPanel dummyPanel = new JPanel(new BorderLayout());
206 String name = null;
207 if (myInitialFile != null) {
208 name = myInitialFile.getName();
210 PsiElement context = myInitialFile == null ? null : myInitialFile;
211 myGotoByNamePanel = new ChooseByNamePanel(myProject, new MyGotoFileModel(), name, true, context) {
212 protected void close(final boolean isOk) {
213 super.close(isOk);
215 if (isOk) {
216 doOKAction();
218 else {
219 doCancelAction();
223 protected void initUI(final ChooseByNamePopupComponent.Callback callback,
224 final ModalityState modalityState,
225 boolean allowMultipleSelection) {
226 super.initUI(callback, modalityState, allowMultipleSelection);
227 dummyPanel.add(myGotoByNamePanel.getPanel(), BorderLayout.CENTER);
228 //IdeFocusTraversalPolicy.getPreferredFocusedComponent(myGotoByNamePanel.getPanel()).requestFocus();
231 protected void choosenElementMightChange() {
232 handleSelectionChanged();
236 myTabbedPane.addTab(IdeBundle.message("tab.chooser.project"), scrollPane);
237 myTabbedPane.addTab(IdeBundle.message("tab.chooser.search.by.name"), dummyPanel);
239 SwingUtilities.invokeLater(new Runnable() {
240 public void run() {
241 myGotoByNamePanel.invoke(new MyCallback(), ModalityState.stateForComponent(getRootPane()), false);
245 myTabbedPane.addChangeListener(
246 new ChangeListener() {
247 public void stateChanged(final ChangeEvent e) {
248 handleSelectionChanged();
253 return myTabbedPane.getComponent();
256 private void handleSelectionChanged(){
257 final PsiFile selection = calcSelectedClass();
258 setOKActionEnabled(selection != null);
261 protected void doOKAction() {
262 mySelectedFile = calcSelectedClass();
263 if (mySelectedFile == null) return;
264 super.doOKAction();
267 public void doCancelAction() {
268 mySelectedFile = null;
269 super.doCancelAction();
272 public PsiFile getSelectedFile(){
273 return mySelectedFile;
276 public void selectFile(@NotNull final PsiFile file) {
277 // Select element in the tree
278 ApplicationManager.getApplication().invokeLater(new Runnable() {
279 public void run() {
280 if (myBuilder != null) {
281 myBuilder.select(file, file.getVirtualFile(), true);
284 }, ModalityState.stateForComponent(getWindow()));
287 public void showDialog() {
288 show();
291 private PsiFile calcSelectedClass() {
292 if (myTabbedPane.getSelectedIndex() == 1) {
293 return (PsiFile)myGotoByNamePanel.getChosenElement();
295 else {
296 final TreePath path = myTree.getSelectionPath();
297 if (path == null) return null;
298 final DefaultMutableTreeNode node = (DefaultMutableTreeNode)path.getLastPathComponent();
299 final Object userObject = node.getUserObject();
300 if (!(userObject instanceof ProjectViewNode)) return null;
301 ProjectViewNode pvNode = (ProjectViewNode) userObject;
302 VirtualFile vFile = pvNode.getVirtualFile();
303 if (vFile != null && !vFile.isDirectory()) {
304 return PsiManager.getInstance(myProject).findFile(vFile);
307 return null;
312 public void dispose() {
313 if (myBuilder != null) {
314 Disposer.dispose(myBuilder);
315 myBuilder = null;
317 super.dispose();
320 protected String getDimensionServiceKey() {
321 return "#com.intellij.ide.util.TreeFileChooserDialog";
324 public JComponent getPreferredFocusedComponent() {
325 return myTree;
328 private final class MyGotoFileModel implements ChooseByNameModel {
329 private final int myMaxSize = WindowManagerEx.getInstanceEx().getFrame(myProject).getSize().width;
330 public Object[] getElementsByName(final String name, final boolean checkBoxState, final String pattern) {
331 final PsiFile[] psiFiles = FilenameIndex.getFilesByName(myProject, name, GlobalSearchScope.projectScope(myProject));
332 return filterFiles(psiFiles);
335 public String getPromptText() {
336 return IdeBundle.message("prompt.filechooser.enter.file.name");
339 public String getCheckBoxName() {
340 return null;
343 public char getCheckBoxMnemonic() {
344 return 0;
347 public String getNotInMessage() {
348 return "";
351 public String getNotFoundMessage() {
352 return "";
355 public boolean loadInitialCheckBoxState() {
356 return true;
359 public void saveInitialCheckBoxState(final boolean state) {
362 public PsiElementListCellRenderer getListCellRenderer() {
363 return new GotoFileCellRenderer(myMaxSize);
366 public String[] getNames(final boolean checkBoxState) {
367 final String[] fileNames = FilenameIndex.getAllFilenames(myProject);
369 final Set<String> array = new THashSet<String>();
370 FileTypeManager fileTypeManager = FileTypeManager.getInstance();
371 for (String fileName : fileNames) {
373 if (myFileType != null && fileTypeManager.getFileTypeByFileName(fileName) != myFileType) {
374 continue;
377 if (!array.contains(fileName)) {
378 array.add(fileName);
382 final String[] result = ArrayUtil.toStringArray(array);
383 Arrays.sort(result);
384 return result;
387 public String getElementName(final Object element) {
388 if (!(element instanceof PsiFile)) return null;
389 return ((PsiFile)element).getName();
392 @Nullable
393 public String getFullName(final Object element) {
394 if (element instanceof PsiFile) {
395 final VirtualFile virtualFile = ((PsiFile)element).getVirtualFile();
396 return virtualFile != null ? virtualFile.getPath() : null;
399 return getElementName(element);
402 public String getHelpId() {
403 return null;
406 @NotNull
407 public String[] getSeparators() {
408 return new String[] {"/", "\\"};
412 private final class MyCallback extends ChooseByNamePopupComponent.Callback {
413 public void elementChosen(final Object element) {
414 mySelectedFile = (PsiFile)element;
415 close(OK_EXIT_CODE);
419 private Object[] filterFiles(final Object[] list) {
420 Condition<PsiFile> condition = new Condition<PsiFile>() {
421 public boolean value(final PsiFile psiFile) {
422 if (myFilter != null && !myFilter.accept(psiFile)) {
423 return false;
425 return myFileType == null || psiFile.getFileType() == myFileType;
428 final List<Object> result = new ArrayList<Object>(list.length);
429 for (Object o : list) {
430 final PsiFile psiFile;
431 if (o instanceof PsiFile) {
432 psiFile = (PsiFile)o;
434 else if (o instanceof PsiFileNode) {
435 psiFile = ((PsiFileNode)o).getValue();
437 else {
438 psiFile = null;
440 if (psiFile != null && !condition.value(psiFile)) {
441 continue;
443 else {
444 if (o instanceof ProjectViewNode) {
445 final ProjectViewNode projectViewNode = (ProjectViewNode)o;
446 if (!projectViewNode.canHaveChildrenMatching(condition)) {
447 continue;
451 result.add(o);
453 return ArrayUtil.toObjectArray(result);