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.
16 package com
.intellij
.ide
.util
.projectWizard
;
18 import com
.intellij
.ide
.IdeBundle
;
19 import com
.intellij
.ide
.highlighter
.ModuleFileType
;
20 import com
.intellij
.ide
.util
.BrowseFilesListener
;
21 import com
.intellij
.openapi
.diagnostic
.Logger
;
22 import com
.intellij
.openapi
.module
.Module
;
23 import com
.intellij
.openapi
.module
.ModuleType
;
24 import com
.intellij
.openapi
.roots
.ModuleRootModel
;
25 import com
.intellij
.openapi
.roots
.ui
.configuration
.ModulesProvider
;
26 import com
.intellij
.openapi
.ui
.Messages
;
27 import com
.intellij
.openapi
.ui
.MultiLineLabelUI
;
28 import com
.intellij
.openapi
.vfs
.VfsUtil
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.ui
.DocumentAdapter
;
31 import com
.intellij
.ui
.FieldPanel
;
32 import org
.jetbrains
.annotations
.NonNls
;
35 import javax
.swing
.event
.DocumentEvent
;
36 import javax
.swing
.event
.DocumentListener
;
38 import java
.awt
.event
.ActionEvent
;
42 * @author Eugene Zhuravlev
45 public class NameLocationStep
extends ModuleWizardStep
{
46 private static final Logger LOG
= Logger
.getInstance("#com.intellij.ide.util.projectWizard.NameLocationStep");
47 private final JPanel myPanel
;
48 private final NamePathComponent myNamePathComponent
;
49 private final WizardContext myWizardContext
;
50 private final JavaModuleBuilder myBuilder
;
51 private final ModulesProvider myModulesProvider
;
52 private final Icon myIcon
;
53 private final String myHelpId
;
54 private boolean myModuleFileDirectoryChangedByUser
= false;
55 private final JTextField myTfModuleFilePath
;
56 private boolean myFirstTimeInitializationDone
= false;
58 public NameLocationStep(WizardContext wizardContext
, JavaModuleBuilder builder
,
59 ModulesProvider modulesProvider
,
61 @NonNls String helpId
) {
62 myWizardContext
= wizardContext
;
64 myModulesProvider
= modulesProvider
;
67 myPanel
= new JPanel(new GridBagLayout());
68 myPanel
.setBorder(BorderFactory
.createEtchedBorder());
70 final String text
= IdeBundle
.message("prompt.please.specify.module.name.and.content.root");
71 final JLabel textLabel
= new JLabel(text
);
72 textLabel
.setUI(new MultiLineLabelUI());
73 myPanel
.add(textLabel
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 2, 1, 1.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.NONE
, new Insets(8, 10, 8, 10), 0, 0));
75 myNamePathComponent
= new NamePathComponent(IdeBundle
.message("label.module.name"), IdeBundle
.message("label.module.content.root"), 'M', 'r',
76 IdeBundle
.message("title.select.module.content.root"), "");
77 //if (ModuleType.J2EE_APPLICATION.equals(moduleType)) {
78 // myNamePathComponent.setPathComponentVisible(false);
81 myPanel
.add(myNamePathComponent
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 2, 1, 1.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.HORIZONTAL
, new Insets(8, 10, 0, 10), 0, 0));
83 final JLabel label
= new JLabel(IdeBundle
.message("label.module.file.will.be.saved.in"));
84 //label.setFont(UIManager.getFont("Label.font").deriveFont(Font.BOLD));
85 myPanel
.add(label
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 2, 1, 1.0, 1.0, GridBagConstraints
.SOUTHWEST
, GridBagConstraints
.HORIZONTAL
, new Insets(30, 10, 0, 10), 0, 0));
87 myTfModuleFilePath
= new JTextField();
88 myTfModuleFilePath
.setEditable(false);
89 final Insets borderInsets
= myTfModuleFilePath
.getBorder().getBorderInsets(myTfModuleFilePath
);
90 myTfModuleFilePath
.setBorder(BorderFactory
.createEmptyBorder(borderInsets
.top
, borderInsets
.left
, borderInsets
.bottom
, borderInsets
.right
));
91 final FieldPanel fieldPanel
= createFieldPanel(myTfModuleFilePath
, null, null);
92 myPanel
.add(fieldPanel
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 1, 1, 1.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.HORIZONTAL
, new Insets(0, 10, 10, 0), 0, 0));
94 JButton browseButton
= new JButton(IdeBundle
.message("button.change.directory"));
95 browseButton
.addActionListener(new BrowseModuleFileDirectoryListener(myTfModuleFilePath
));
96 myPanel
.add(browseButton
, new GridBagConstraints(1, GridBagConstraints
.RELATIVE
, 1, 1, 0.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.NONE
, new Insets(0, 0, 10, 10), 0, 0));
98 final DocumentListener documentListener
= new DocumentAdapter() {
99 protected void textChanged(DocumentEvent e
) {
100 updateModuleFilePathField();
103 myNamePathComponent
.getNameComponent().getDocument().addDocumentListener(documentListener
);
104 myNamePathComponent
.getPathComponent().getDocument().addDocumentListener(documentListener
);
105 myNamePathComponent
.getPathComponent().getDocument().addDocumentListener(new DocumentAdapter() {
106 public void textChanged(DocumentEvent event
) {
107 myWizardContext
.requestWizardButtonsUpdate();
112 @SuppressWarnings({"HardCodedStringLiteral"})
113 private String
suggestModuleName(ModuleType moduleType
) {
117 public void updateStep() {
120 // initial UI settings
121 if (!myFirstTimeInitializationDone
) {
122 if (myWizardContext
.isCreatingNewProject()) {
123 setSyncEnabled(false);
125 else { // project already exists
126 final VirtualFile baseDir
= myWizardContext
.getProject().getBaseDir();
127 final String projectFileDirectory
= baseDir
!= null ? VfsUtil
.virtualToIoFile(baseDir
).getPath() : null;
128 if (projectFileDirectory
!= null) {
129 final String name
= ProjectWizardUtil
.findNonExistingFileName(projectFileDirectory
, suggestModuleName(myBuilder
.getModuleType()), "");
131 setContentEntryPath(projectFileDirectory
+ File
.separatorChar
+ name
);
136 if (myWizardContext
.isCreatingNewProject()) { // creating new project
137 // in this mode we depend on the settings of the "project name" step
138 if (!isPathChangedByUser()) {
139 setContentEntryPath(myWizardContext
.getProjectFileDirectory().replace('/', File
.separatorChar
));
141 if (!isNameChangedByUser()) {
142 setModuleName(myWizardContext
.getProjectName());
146 if (!myFirstTimeInitializationDone
) {
147 myNamePathComponent
.getNameComponent().selectAll();
149 myFirstTimeInitializationDone
= true;
152 public JComponent
getComponent() {
156 public String
getModuleName() {
157 return myNamePathComponent
.getNameValue();
160 public void setModuleName(String name
) {
161 myNamePathComponent
.setNameValue(name
);
164 public String
getContentEntryPath() {
165 final String path
= myNamePathComponent
.getPath();
166 return path
.length() == 0?
null : path
;
169 public void setContentEntryPath(String path
) {
170 myNamePathComponent
.setPath(path
);
173 public String
getModuleFilePath() {
174 return getModuleFileDirectory() + "/" + myNamePathComponent
.getNameValue() + ModuleFileType
.DOT_DEFAULT_EXTENSION
;
177 public boolean isSyncEnabled() {
178 return myNamePathComponent
.isSyncEnabled();
181 public void setSyncEnabled(boolean isSyncEnabled
) {
182 myNamePathComponent
.setSyncEnabled(isSyncEnabled
);
185 public String
getModuleFileDirectory() {
186 return myTfModuleFilePath
.getText().trim().replace(File
.separatorChar
, '/');
189 public boolean validate() {
190 final String moduleName
= getModuleName();
191 if (moduleName
.length() == 0) {
192 Messages
.showErrorDialog(myNamePathComponent
.getNameComponent(), IdeBundle
.message("prompt.please.specify.module.name"),
193 IdeBundle
.message("title.module.name.not.specified"));
196 if (isAlreadyExists(moduleName
)) {
197 Messages
.showErrorDialog(IdeBundle
.message("error.module.with.name.already.exists", moduleName
), IdeBundle
.message("title.module.already.exists"));
200 final String moduleLocation
= getModuleFileDirectory();
201 if (moduleLocation
.length() == 0) {
202 Messages
.showErrorDialog(myNamePathComponent
.getPathComponent(), IdeBundle
.message("error.please.specify.module.file.location"),
203 IdeBundle
.message("title.module.file.location.not.specified"));
207 final String contentEntryPath
= getContentEntryPath();
208 if (contentEntryPath
!= null) {
209 // the check makes sence only for non-null module root
210 Module
[] modules
= myModulesProvider
.getModules();
211 for (final Module module
: modules
) {
212 ModuleRootModel rootModel
= myModulesProvider
.getRootModel(module
);
213 LOG
.assertTrue(rootModel
!= null);
214 final VirtualFile
[] moduleContentRoots
= rootModel
.getContentRoots();
215 final String moduleContentRoot
= contentEntryPath
.replace(File
.separatorChar
, '/');
216 for (final VirtualFile root
: moduleContentRoots
) {
217 if (moduleContentRoot
.equals(root
.getPath())) {
218 Messages
.showErrorDialog(myNamePathComponent
.getPathComponent(),
219 IdeBundle
.message("error.content.root.already.defined.for.module", contentEntryPath
, module
.getName()),
220 IdeBundle
.message("title.module.content.root.already.exists"));
225 if (!ProjectWizardUtil
.createDirectoryIfNotExists(IdeBundle
.message("directory.module.content.root"), contentEntryPath
, myNamePathComponent
.isPathChangedByUser())) {
229 final String moduleFileDirectory
= getModuleFileDirectory();
230 return ProjectWizardUtil
.createDirectoryIfNotExists(IdeBundle
.message("directory.module.file"), moduleFileDirectory
, myModuleFileDirectoryChangedByUser
);
233 public void updateDataModel() {
234 myBuilder
.setName(getModuleName());
235 myBuilder
.setModuleFilePath(getModuleFilePath());
236 myBuilder
.setContentEntryPath(getContentEntryPath());
239 public JComponent
getPreferredFocusedComponent() {
240 return myNamePathComponent
.getNameComponent();
243 private boolean isAlreadyExists(String moduleName
) {
244 final Module
[] modules
= myModulesProvider
.getModules();
245 for (Module module
: modules
) {
246 if (moduleName
.equals(module
.getName())) {
253 private void updateModuleFilePathField() {
254 if (!myModuleFileDirectoryChangedByUser
) {
255 final String dir
= myNamePathComponent
.getPath().replace('/', File
.separatorChar
);
256 myTfModuleFilePath
.setText(dir
);
260 public boolean isNameChangedByUser() {
261 return myNamePathComponent
.isNameChangedByUser();
264 public boolean isPathChangedByUser() {
265 return myNamePathComponent
.isPathChangedByUser();
268 private class BrowseModuleFileDirectoryListener
extends BrowseFilesListener
{
269 private BrowseModuleFileDirectoryListener(final JTextField textField
) {
270 super(textField
, IdeBundle
.message("title.select.module.file.location"),
271 IdeBundle
.message("description.select.module.file.location"), SINGLE_DIRECTORY_DESCRIPTOR
);
274 public void actionPerformed(ActionEvent e
) {
275 final String pathBefore
= myTfModuleFilePath
.getText().trim();
276 super.actionPerformed(e
);
277 final String path
= myTfModuleFilePath
.getText().trim();
278 if (!path
.equals(pathBefore
)) {
279 myModuleFileDirectoryChangedByUser
= true;
284 public Icon
getIcon() {
288 public String
getHelpId() {