0c00a68dc00a6264ecb4edc5c47b1e96542bc0b0
[idea/community.git] / platform / lang-impl / src / com / intellij / refactoring / move / moveFilesOrDirectories / MoveFilesOrDirectoriesDialog.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 package com.intellij.refactoring.move.moveFilesOrDirectories;
18
19 import com.intellij.ide.util.DirectoryUtil;
20 import com.intellij.openapi.actionSystem.ActionManager;
21 import com.intellij.openapi.actionSystem.IdeActions;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.command.CommandProcessor;
24 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
25 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
26 import com.intellij.openapi.fileChooser.FileChooserFactory;
27 import com.intellij.openapi.help.HelpManager;
28 import com.intellij.openapi.keymap.KeymapUtil;
29 import com.intellij.openapi.project.Project;
30 import com.intellij.openapi.ui.ComponentWithBrowseButton;
31 import com.intellij.openapi.ui.DialogWrapper;
32 import com.intellij.openapi.ui.TextComponentAccessor;
33 import com.intellij.openapi.util.Disposer;
34 import com.intellij.psi.PsiDirectory;
35 import com.intellij.psi.PsiElement;
36 import com.intellij.psi.PsiFile;
37 import com.intellij.psi.PsiManager;
38 import com.intellij.refactoring.RefactoringBundle;
39 import com.intellij.refactoring.RefactoringSettings;
40 import com.intellij.refactoring.util.CommonRefactoringUtil;
41 import com.intellij.ui.DocumentAdapter;
42 import com.intellij.ui.NonFocusableCheckBox;
43 import com.intellij.util.IncorrectOperationException;
44 import com.intellij.util.ui.UIUtil;
45 import org.jetbrains.annotations.NonNls;
46
47 import javax.swing.*;
48 import javax.swing.event.DocumentEvent;
49 import java.awt.*;
50 import java.io.File;
51
52 public class MoveFilesOrDirectoriesDialog extends DialogWrapper{
53   @NonNls private static final String RECENT_KEYS = "MoveFile.RECENT_KEYS";
54
55   public interface Callback {
56     void run(MoveFilesOrDirectoriesDialog dialog);
57   }
58
59   private JLabel myNameLabel;
60   private ComponentWithBrowseButton<JTextField> myTargetDirectoryField;
61   private String myHelpID;
62   private final Project myProject;
63   private final Callback myCallback;
64   private PsiDirectory myTargetDirectory;
65   private JCheckBox myCbSearchForReferences;
66
67   public MoveFilesOrDirectoriesDialog(Project project, Callback callback) {
68     super(project, true);
69     myProject = project;
70     myCallback = callback;
71     setTitle(RefactoringBundle.message("move.title"));
72     init();
73   }
74
75   protected Action[] createActions(){
76     return new Action[]{getOKAction(),getCancelAction(),getHelpAction()};
77   }
78
79   public JComponent getPreferredFocusedComponent() {
80     return myTargetDirectoryField.getChildComponent();
81   }
82
83   protected JComponent createCenterPanel() {
84     return null;
85   }
86
87   protected JComponent createNorthPanel() {
88     JPanel panel = new JPanel(new GridBagLayout());
89     final GridBagConstraints c = new GridBagConstraints();
90     c.gridx = 0;
91     c.gridy = 0;
92     c.fill = GridBagConstraints.HORIZONTAL;
93     c.insets = new Insets(0, 2, 0, 0);
94
95     myNameLabel = new JLabel();
96     panel.add(myNameLabel, c);
97     c.insets.top = 10;
98     c.gridy++;    
99     panel.add(new JLabel(RefactoringBundle.message("move.files.to.directory.label")), c);
100     c.insets.top = 0;
101     
102     myTargetDirectoryField = new ComponentWithBrowseButton<JTextField>(new JTextField(), null);
103     final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
104     myTargetDirectoryField.addBrowseFolderListener(RefactoringBundle.message("select.target.directory"),
105                                                    RefactoringBundle.message("the.file.will.be.moved.to.this.directory"),
106                                                    myProject,
107                                                    descriptor,
108                                                    TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
109     final JTextField textField = myTargetDirectoryField.getChildComponent();
110     FileChooserFactory.getInstance().installFileCompletion(textField, descriptor, true, getDisposable());
111     myTargetDirectoryField.setTextFieldPreferredWidth(60);
112     c.insets.left = 0;
113     c.gridy++;
114     panel.add(myTargetDirectoryField, c);
115     String shortcutText = KeymapUtil.getFirstKeyboardShortcutText(ActionManager.getInstance().getAction(IdeActions.ACTION_CODE_COMPLETION));
116     final JLabel label = new JLabel(RefactoringBundle.message("path.completion.shortcut", shortcutText));
117     UIUtil.applyStyle(UIUtil.ComponentStyle.MINI, label);
118     c.insets.left = 6;
119     c.gridy++;
120     panel.add(label, c);
121
122     myCbSearchForReferences = new NonFocusableCheckBox(RefactoringBundle.message("search.for.references"));
123     myCbSearchForReferences.setSelected(RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE);
124     c.insets.top = 10;
125     c.insets.left = 0;
126     c.gridy++;
127     panel.add(myCbSearchForReferences, c);
128
129     textField.getDocument().addDocumentListener(new DocumentAdapter() {
130       @Override
131       protected void textChanged(DocumentEvent e) {
132         validateOKButton();
133       }
134     });
135     Disposer.register(getDisposable(), myTargetDirectoryField);
136
137     return panel;
138   }
139
140   public void setData(PsiElement[] psiElements, PsiDirectory initialTargetDirectory, @NonNls String helpID) {
141     if (psiElements.length == 1) {
142       String text;
143       if (psiElements[0] instanceof PsiFile) {
144         text = RefactoringBundle.message("move.file.0",
145                                          ((PsiFile)psiElements[0]).getVirtualFile().getPresentableUrl());
146       }
147       else {
148         text = RefactoringBundle.message("move.directory.0",
149                                          ((PsiDirectory)psiElements[0]).getVirtualFile().getPresentableUrl());
150       }
151       myNameLabel.setText(text);
152     }
153     else {
154       boolean isFile = true;
155       boolean isDirectory = true;
156       for (PsiElement psiElement : psiElements) {
157         isFile &= psiElement instanceof PsiFile;
158         isDirectory &= psiElement instanceof PsiDirectory;
159       }
160       myNameLabel.setText(isFile ?
161                           RefactoringBundle.message("move.specified.files") :
162                           isDirectory ?
163                           RefactoringBundle.message("move.specified.directories") :
164                           RefactoringBundle.message("move.specified.elements"));
165     }
166
167     myTargetDirectoryField.getChildComponent().setText(initialTargetDirectory == null ? "" : initialTargetDirectory.getVirtualFile().getPresentableUrl());
168
169     validateOKButton();
170     myHelpID = helpID;
171   }
172
173   protected void doHelpAction() {
174     HelpManager.getInstance().invokeHelp(myHelpID);
175   }
176
177   private void validateOKButton() {
178     setOKActionEnabled(myTargetDirectoryField.getChildComponent().getText().length() > 0);
179   }
180
181   protected void doOKAction() {
182     //myTargetDirectoryField.getChildComponent().addCurrentTextToHistory();
183     RefactoringSettings.getInstance().MOVE_SEARCH_FOR_REFERENCES_FOR_FILE = myCbSearchForReferences.isSelected();
184     CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
185       public void run() {
186         final Runnable action = new Runnable() {
187           public void run() {
188             String directoryName = myTargetDirectoryField.getChildComponent().getText().replace(File.separatorChar, '/');
189             try {
190               myTargetDirectory = DirectoryUtil.mkdirs(PsiManager.getInstance(myProject), directoryName);
191             }
192             catch (IncorrectOperationException e) {
193               // ignore
194             }
195           }
196         };
197
198         ApplicationManager.getApplication().runWriteAction(action);
199         if (myTargetDirectory == null) {
200           CommonRefactoringUtil.showErrorMessage(getTitle(),
201                                                  RefactoringBundle.message("cannot.create.directory"), myHelpID, myProject);
202           return;
203         }
204         myCallback.run(MoveFilesOrDirectoriesDialog.this);
205       }
206     }, RefactoringBundle.message("move.title"), null);
207   }
208
209   public PsiDirectory getTargetDirectory() {
210     return myTargetDirectory;
211   }
212 }