4a2be96f500aceab3ec17158c72cfb441a6f854b
[idea/community.git] / platform / lang-impl / src / com / intellij / refactoring / copy / CopyFilesOrDirectoriesDialog.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.copy;
18
19 import com.intellij.ide.util.DirectoryUtil;
20 import com.intellij.openapi.application.ApplicationManager;
21 import com.intellij.openapi.command.CommandProcessor;
22 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
23 import com.intellij.openapi.help.HelpManager;
24 import com.intellij.openapi.project.Project;
25 import com.intellij.openapi.ui.DialogWrapper;
26 import com.intellij.openapi.ui.Messages;
27 import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl;
28 import com.intellij.psi.PsiDirectory;
29 import com.intellij.psi.PsiElement;
30 import com.intellij.psi.PsiFile;
31 import com.intellij.psi.PsiManager;
32 import com.intellij.refactoring.RefactoringBundle;
33 import com.intellij.ui.*;
34 import com.intellij.util.IncorrectOperationException;
35 import org.jetbrains.annotations.NonNls;
36
37 import javax.swing.*;
38 import javax.swing.event.DocumentEvent;
39 import javax.swing.event.DocumentListener;
40 import java.awt.*;
41 import java.io.File;
42
43 class CopyFilesOrDirectoriesDialog extends DialogWrapper{
44   private JLabel myInformationLabel;
45   private EditorComboWithBrowseButton myTargetDirectoryField;
46   private JTextField myNewNameField;
47   private final Project myProject;
48   private final boolean myShowDirectoryField;
49   private final boolean myShowNewNameField;
50
51   private PsiDirectory myTargetDirectory;
52   @NonNls private static final String RECENT_KEYS = "CopyFile.RECENT_KEYS";
53
54   public CopyFilesOrDirectoriesDialog(PsiElement[] elements, PsiDirectory defaultTargetDirectory, Project project, boolean doClone) {
55     super(project, true);
56     myProject = project;
57     myShowDirectoryField = !doClone;
58     myShowNewNameField = elements.length == 1;
59
60     if (doClone && elements.length != 1) {
61       throw new IllegalArgumentException("wrong number of elements to clone: " + elements.length);
62     }
63
64     setTitle(doClone ?
65              RefactoringBundle.message("copy.files.clone.title") :
66              RefactoringBundle.message("copy.files.copy.title"));
67     init();
68
69     if (elements.length == 1) {
70       String text;
71       if (elements[0] instanceof PsiFile) {
72         PsiFile file = (PsiFile)elements[0];
73         text = doClone ?
74                RefactoringBundle.message("copy.files.clone.file.0", file.getVirtualFile().getPresentableUrl()) :
75                RefactoringBundle.message("copy.files.copy.file.0", file.getVirtualFile().getPresentableUrl());
76         final String fileName = file.getName();
77         myNewNameField.setText(fileName);
78         final int dotIdx = fileName.lastIndexOf(".");
79         if (dotIdx > -1) {
80           myNewNameField.select(0, dotIdx);
81           myNewNameField.putClientProperty(DialogWrapperPeerImpl.HAVE_INITIAL_SELECTION, true);
82         }
83       }
84       else {
85         PsiDirectory directory = (PsiDirectory)elements[0];
86         text = doClone ?
87                RefactoringBundle.message("copy.files.clone.directory.0", directory.getVirtualFile().getPresentableUrl()) :
88                RefactoringBundle.message("copy.files.copy.directory.0", directory.getVirtualFile().getPresentableUrl());
89         myNewNameField.setText(directory.getName());
90       }
91       myInformationLabel.setText(text);
92     }
93     else {
94       setMultipleElementCopyLabel(elements);
95     }
96
97     if (myShowDirectoryField) {
98       myTargetDirectoryField.prependItem(defaultTargetDirectory == null ? "" : defaultTargetDirectory.getVirtualFile().getPresentableUrl());
99     }
100     validateOKButton();
101   }
102
103   private void setMultipleElementCopyLabel(PsiElement[] elements) {
104     boolean allFiles = true;
105     boolean allDirectories = true;
106     for (PsiElement element : elements) {
107       if (element instanceof PsiDirectory) {
108         allFiles = false;
109       }
110       else {
111         allDirectories = false;
112       }
113     }
114     if (allFiles) {
115       myInformationLabel.setText(RefactoringBundle.message("copy.files.copy.specified.files.label"));
116     }
117     else if (allDirectories) {
118       myInformationLabel.setText(RefactoringBundle.message("copy.files.copy.specified.directories.label"));
119     }
120     else {
121       myInformationLabel.setText(RefactoringBundle.message("copy.files.copy.specified.mixed.label"));
122     }
123   }
124
125   protected Action[] createActions(){
126     return new Action[]{getOKAction(),getCancelAction(),getHelpAction()};
127   }
128
129   public JComponent getPreferredFocusedComponent() {
130     return myShowNewNameField ? myNewNameField : myTargetDirectoryField.getChildComponent();
131   }
132
133   protected JComponent createCenterPanel() {
134     return new JPanel(new BorderLayout());
135   }
136
137   protected JComponent createNorthPanel() {
138     JPanel panel = new JPanel(new GridBagLayout());
139
140     myInformationLabel = new JLabel();
141
142     panel.add(myInformationLabel, new GridBagConstraints(0,0,2,1,1,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,8,4,8),0,0));
143
144     DocumentListener documentListener = new DocumentAdapter() {
145       public void textChanged(DocumentEvent event) {
146         validateOKButton();
147       }
148     };
149     if (myShowNewNameField) {
150       myNewNameField = new JTextField();
151       Dimension size = myNewNameField.getPreferredSize();
152       FontMetrics fontMetrics = myNewNameField.getFontMetrics(myNewNameField.getFont());
153       size.width = fontMetrics.charWidth('a') * 60;
154       myNewNameField.setPreferredSize(size);
155
156       panel.add(new JLabel(RefactoringBundle.message("copy.files.new.name.label")), new GridBagConstraints(0,1,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,8,4,8),0,0));
157
158       panel.add(myNewNameField, new GridBagConstraints(1,1,1,1,1,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,0,4,8),0,0));
159
160       myNewNameField.getDocument().addDocumentListener(documentListener);
161     }
162
163     if (myShowDirectoryField) {
164       panel.add(new JLabel(RefactoringBundle.message("copy.files.to.directory.label")), new GridBagConstraints(0,2,1,1,0,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,8,4,8),0,0));
165
166       myTargetDirectoryField = new EditorComboWithBrowseButton(null, "", myProject,
167                                                                RECENT_KEYS);
168       myTargetDirectoryField.addBrowseFolderListener(RefactoringBundle.message("select.target.directory"),
169                                                                             RefactoringBundle.message("the.file.will.be.copied.to.this.directory"),
170                                                                             myProject, FileChooserDescriptorFactory.createSingleFolderDescriptor(),
171                                                                             EditorComboBox.COMPONENT_ACCESSOR);
172       myTargetDirectoryField.setTextFieldPreferredWidth(60);
173       panel.add(myTargetDirectoryField, new GridBagConstraints(1,2,1,1,1,0,GridBagConstraints.WEST,GridBagConstraints.HORIZONTAL,new Insets(4,0,4,8),0,0));
174
175       myTargetDirectoryField.getChildComponent().getDocument().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
176         @Override
177         public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
178           validateOKButton();
179         }
180       });
181     }
182
183     return panel;
184   }
185
186   public PsiDirectory getTargetDirectory() {
187     return myTargetDirectory;
188   }
189
190   public String getNewName() {
191     return myNewNameField != null ? myNewNameField.getText().trim() : null;
192   }
193
194   protected void doOKAction(){
195     if (myShowNewNameField) {
196       String newName = getNewName();
197
198       if (newName.length() == 0) {
199         Messages.showMessageDialog(myProject, RefactoringBundle.message("no.new.name.specified"), RefactoringBundle.message("error.title"), Messages.getErrorIcon());
200         return;
201       }
202     }
203
204     if (myShowDirectoryField) {
205       final String targetDirectoryName = myTargetDirectoryField.getText();
206
207       if (targetDirectoryName.length() == 0) {
208         Messages.showMessageDialog(myProject, RefactoringBundle.message("no.target.directory.specified"), RefactoringBundle.message("error.title"), Messages.getErrorIcon());
209         return;
210       }
211
212       RecentsManager.getInstance(myProject).registerRecentEntry(RECENT_KEYS, targetDirectoryName);
213
214       CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
215         public void run() {
216           ApplicationManager.getApplication().runWriteAction(new Runnable() {
217             public void run() {
218               try {
219                 myTargetDirectory = DirectoryUtil.mkdirs(PsiManager.getInstance(myProject), targetDirectoryName.replace(File.separatorChar, '/'));
220               }
221               catch (IncorrectOperationException e) {
222               }
223             }
224           });
225         }
226       }, RefactoringBundle.message("create.directory"), null);
227
228       if (myTargetDirectory == null) {
229         Messages.showMessageDialog(myProject, RefactoringBundle.message("cannot.create.directory"), RefactoringBundle.message("error.title"), Messages.getErrorIcon());
230         return;
231       }
232     }
233
234     super.doOKAction();
235   }
236
237   private void validateOKButton() {
238     if (myShowDirectoryField) {
239       if (myTargetDirectoryField.getText().length() == 0) {
240         setOKActionEnabled(false);
241         return;
242       }
243     }
244     if (myShowNewNameField) {
245       if (getNewName().length() == 0) {
246         setOKActionEnabled(false);
247         return;
248       }
249     }
250     setOKActionEnabled(true);
251   }
252
253   protected void doHelpAction() {
254     HelpManager.getInstance().invokeHelp("refactoring.copyClass");
255   }
256 }