0ec0403a2492525f1acb3b2e184585b71906b127
[idea/community.git] / platform / platform-impl / src / com / intellij / platform / NewDirectoryProjectDialog.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 package com.intellij.platform;
17
18 import com.intellij.facet.ui.FacetEditorValidator;
19 import com.intellij.facet.ui.FacetValidatorsManager;
20 import com.intellij.facet.ui.ValidationResult;
21 import com.intellij.ide.GeneralSettings;
22 import com.intellij.ide.ui.ListCellRendererWrapper;
23 import com.intellij.openapi.application.ApplicationNamesInfo;
24 import com.intellij.openapi.extensions.Extensions;
25 import com.intellij.openapi.fileChooser.FileChooserDescriptor;
26 import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
27 import com.intellij.openapi.project.Project;
28 import com.intellij.openapi.ui.ComponentWithBrowseButton;
29 import com.intellij.openapi.ui.DialogWrapper;
30 import com.intellij.openapi.ui.TextComponentAccessor;
31 import com.intellij.openapi.ui.TextFieldWithBrowseButton;
32 import com.intellij.openapi.util.io.FileUtil;
33 import com.intellij.openapi.vfs.VirtualFile;
34 import com.intellij.ui.DocumentAdapter;
35 import com.intellij.util.SystemProperties;
36 import org.jetbrains.annotations.Nullable;
37
38 import javax.swing.*;
39 import javax.swing.event.DocumentEvent;
40 import java.awt.event.ActionEvent;
41 import java.awt.event.ActionListener;
42 import java.io.File;
43
44 /**
45  * @author yole
46  */
47 public class NewDirectoryProjectDialog extends DialogWrapper {
48   private JTextField myProjectNameTextField;
49   private TextFieldWithBrowseButton myLocationField;
50   private JPanel myRootPane;
51   private JComboBox myProjectTypeComboBox;
52   private JPanel myProjectTypePanel;
53   private JLabel myLocationLabel;
54   private String myBaseDir;
55   private boolean myModifyingLocation = false;
56   private boolean myModifyingProjectName = false;
57
58   private static final Object EMPTY_PROJECT_GENERATOR = new Object();
59
60   protected NewDirectoryProjectDialog(Project project) {
61     super(project, true);
62     setTitle("Create New Project");
63     init();
64
65     myLocationLabel.setLabelFor(myLocationField.getChildComponent());
66
67     myBaseDir = getBaseDir();
68     File projectName = FileUtil.findSequentNonexistentFile(new File(myBaseDir), "untitled", "");
69     myLocationField.setText(projectName.toString());
70     myProjectNameTextField.setText(projectName.getName());
71
72     FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
73     ComponentWithBrowseButton.BrowseFolderActionListener<JTextField> listener =
74       new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>("Select Location for Project Directory", "", myLocationField,
75                                                                            project,
76                                                                            descriptor,
77                                                                            TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
78
79         protected void onFileChoosen(VirtualFile chosenFile) {
80           super.onFileChoosen(chosenFile);
81           myBaseDir = chosenFile.getPath();
82           myLocationField.setText(new File(chosenFile.getPath(), myProjectNameTextField.getText()).toString());
83         }
84       };
85     myLocationField.addActionListener(listener);
86     myLocationField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
87       @Override
88       protected void textChanged(DocumentEvent e) {
89         myModifyingLocation = true;
90         String path = myLocationField.getText().trim();
91         if (path.endsWith(File.separator)) {
92           path = path.substring(0, path.length() - File.separator.length());
93         }
94         int ind = path.lastIndexOf(File.separator);
95         if (ind != -1) {
96           String projectName = path.substring(ind + 1, path.length());
97           if (!myProjectNameTextField.getText().trim().isEmpty()) {
98             myBaseDir = path.substring(0, ind);
99           }
100           if (!projectName.equals(myProjectNameTextField.getText())) {
101             if (!myModifyingProjectName) {
102               myProjectNameTextField.setText(projectName);
103             }
104           }
105         }
106         myModifyingLocation = false;
107       }
108     });
109
110     myProjectNameTextField.getDocument().addDocumentListener(new DocumentAdapter() {
111       protected void textChanged(final DocumentEvent e) {
112         if (!myModifyingLocation) {
113           myModifyingProjectName = true;
114           File f = new File(myBaseDir);
115           myLocationField.setText(new File(f, myProjectNameTextField.getText()).getPath());
116           myModifyingProjectName = false;
117         }
118       }
119     });
120
121     myProjectNameTextField.selectAll();
122
123     final DirectoryProjectGenerator[] generators = Extensions.getExtensions(DirectoryProjectGenerator.EP_NAME);
124     if (generators.length == 0) {
125       myProjectTypePanel.setVisible(false);
126     }
127     else {
128       DefaultComboBoxModel model = new DefaultComboBoxModel();
129       model.addElement(EMPTY_PROJECT_GENERATOR);
130       for (DirectoryProjectGenerator generator : generators) {
131         model.addElement(generator);
132       }
133       myProjectTypeComboBox.setModel(model);
134       myProjectTypeComboBox.setRenderer(new ListCellRendererWrapper(myProjectTypeComboBox.getRenderer()) {
135         @Override
136         public void customize(final JList list, final Object value, final int index, final boolean selected, final boolean cellHasFocus) {
137           if (value == null) return;
138           if (value == EMPTY_PROJECT_GENERATOR) {
139             setText("Empty project");
140           }
141           else {
142             setText(((DirectoryProjectGenerator)value).getName());
143           }
144         }
145       });
146     }
147
148     registerValidators(new FacetValidatorsManager() {
149       public void registerValidator(FacetEditorValidator validator, JComponent... componentsToWatch) {
150       }
151
152       public void validate() {
153         checkValid();
154       }
155     });
156   }
157
158   private void checkValid() {
159     String projectName = myProjectNameTextField.getText();
160     if (projectName.trim().isEmpty()) {
161       setOKActionEnabled(false);
162       setErrorText("Project name can't be empty");
163       return;
164     }
165     DirectoryProjectGenerator generator = getProjectGenerator();
166     if (generator != null) {
167       String baseDirPath = myLocationField.getTextField().getText();
168       ValidationResult validationResult = generator.validate(baseDirPath);
169       if (!validationResult.isOk()) {
170         setOKActionEnabled(false);
171         setErrorText(validationResult.getErrorMessage());
172         return;
173       }
174     }
175     setOKActionEnabled(true);
176     setErrorText(null);
177   }
178
179   private void registerValidators(final FacetValidatorsManager validatorsManager) {
180     validateOnTextChange(validatorsManager, myLocationField.getTextField());
181     validateOnSelectionChange(validatorsManager, myProjectTypeComboBox);
182   }
183
184   private static void validateOnSelectionChange(final FacetValidatorsManager validatorsManager, final JComboBox projectNameTextField) {
185     projectNameTextField.addActionListener(new ActionListener() {
186       @Override
187       public void actionPerformed(ActionEvent e) {
188         validatorsManager.validate();
189       }
190     });
191   }
192
193   private static void validateOnTextChange(final FacetValidatorsManager validatorsManager, final JTextField textField) {
194     textField.getDocument().addDocumentListener(new DocumentAdapter() {
195       @Override
196       protected void textChanged(DocumentEvent e) {
197         validatorsManager.validate();
198       }
199     });
200   }
201
202   public static String getBaseDir() {
203     final String lastProjectLocation = GeneralSettings.getInstance().getLastProjectLocation();
204     if (lastProjectLocation != null) {
205       return lastProjectLocation.replace('/', File.separatorChar);
206     }
207     final String userHome = SystemProperties.getUserHome();
208     //noinspection HardCodedStringLiteral
209     return userHome.replace('/', File.separatorChar) + File.separator + ApplicationNamesInfo.getInstance().getLowercaseProductName() +
210            "Projects";
211   }
212
213   protected JComponent createCenterPanel() {
214     return myRootPane;
215   }
216
217   public String getNewProjectLocation() {
218     return myLocationField.getText();
219   }
220
221   public String getNewProjectName() {
222     return myProjectNameTextField.getText();
223   }
224
225   @Nullable
226   public DirectoryProjectGenerator getProjectGenerator() {
227     final Object selItem = myProjectTypeComboBox.getSelectedItem();
228     if (selItem == EMPTY_PROJECT_GENERATOR) return null;
229     return (DirectoryProjectGenerator)selItem;
230   }
231
232   public JComponent getPreferredFocusedComponent() {
233     return myProjectNameTextField;
234   }
235
236   @Override
237   protected String getHelpId() {
238     return "create_new_project_dialog";
239   }
240 }