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
.BrowserUtil
;
19 import com
.intellij
.ide
.IdeBundle
;
20 import com
.intellij
.ide
.util
.BrowseFilesListener
;
21 import com
.intellij
.openapi
.application
.ApplicationNamesInfo
;
22 import com
.intellij
.openapi
.fileChooser
.FileChooserDescriptor
;
23 import com
.intellij
.openapi
.fileTypes
.FileTypeManager
;
24 import com
.intellij
.openapi
.fileTypes
.StdFileTypes
;
25 import com
.intellij
.openapi
.module
.ModuleType
;
26 import com
.intellij
.openapi
.module
.ModuleTypeManager
;
27 import com
.intellij
.openapi
.module
.StdModuleTypes
;
28 import com
.intellij
.openapi
.ui
.Messages
;
29 import com
.intellij
.openapi
.vfs
.VirtualFile
;
30 import com
.intellij
.ui
.FieldPanel
;
31 import com
.intellij
.ui
.ScrollPaneFactory
;
32 import com
.intellij
.util
.EventDispatcher
;
33 import com
.intellij
.util
.ui
.UIUtil
;
36 import javax
.swing
.event
.HyperlinkEvent
;
37 import javax
.swing
.event
.HyperlinkListener
;
38 import javax
.swing
.event
.ListSelectionEvent
;
39 import javax
.swing
.event
.ListSelectionListener
;
41 import java
.awt
.event
.ItemEvent
;
42 import java
.awt
.event
.ItemListener
;
43 import java
.awt
.event
.MouseAdapter
;
44 import java
.awt
.event
.MouseEvent
;
46 import java
.util
.EventListener
;
49 * @author Eugene Zhuravlev
53 public class ModuleTypeStep
extends ModuleWizardStep
{
54 private final JPanel myPanel
;
55 private final JRadioButton myRbCreateNewModule
;
56 private final JRadioButton myRbImportModule
;
57 private final FieldPanel myModulePathFieldPanel
;
58 private final JList myTypesList
;
59 private final JEditorPane myModuleDescriptionPane
;
61 private ModuleType myModuleType
= StdModuleTypes
.JAVA
;
62 private Runnable myDoubleClickAction
= null;
64 final EventDispatcher
<UpdateListener
> myEventDispatcher
= EventDispatcher
.create(UpdateListener
.class);
65 private final ButtonGroup myButtonGroup
;
67 public static interface UpdateListener
extends EventListener
{
68 void moduleTypeSelected(ModuleType type
);
69 void importModuleOptionSelected(boolean selected
);
72 public ModuleTypeStep(boolean createNewProject
) {
73 myPanel
= new JPanel(new GridBagLayout());
74 myPanel
.setBorder(BorderFactory
.createEtchedBorder());
76 myModuleDescriptionPane
= new JEditorPane();
77 myModuleDescriptionPane
.setContentType(UIUtil
.HTML_MIME
);
78 myModuleDescriptionPane
.addHyperlinkListener(new HyperlinkListener() {
79 public void hyperlinkUpdate(HyperlinkEvent e
) {
80 if (e
.getEventType() == HyperlinkEvent
.EventType
.ACTIVATED
) {
82 BrowserUtil
.launchBrowser(e
.getURL().toString());
84 catch (IllegalThreadStateException ex
) {
85 // it's nnot a problem
90 myModuleDescriptionPane
.setEditable(false);
92 final ModuleType
[] allModuleTypes
= ModuleTypeManager
.getInstance().getRegisteredTypes();
94 myTypesList
= new JList(allModuleTypes
);
95 myTypesList
.setSelectionModel(new PermanentSingleSelectionModel());
96 myTypesList
.setCellRenderer(new ModuleTypesListCellRenderer());
97 myTypesList
.addListSelectionListener(new ListSelectionListener() {
98 public void valueChanged(ListSelectionEvent e
) {
99 if (e
.getValueIsAdjusting()) {
102 final ModuleType typeSelected
= (ModuleType
)myTypesList
.getSelectedValue();
103 myModuleType
= typeSelected
;
104 //noinspection HardCodedStringLiteral
105 myModuleDescriptionPane
.setText("<html><body><font face=\"verdana\" size=\"-1\">"+typeSelected
.getDescription()+"</font></body></html>");
106 myEventDispatcher
.getMulticaster().moduleTypeSelected(typeSelected
);
109 myTypesList
.setSelectedIndex(0);
110 myTypesList
.addMouseListener(
112 public void mouseClicked(MouseEvent e
) {
113 if (e
.getClickCount() == 2){
114 if (myDoubleClickAction
!= null) {
115 if (myTypesList
.getSelectedValue() != null) {
116 myDoubleClickAction
.run();
124 myRbCreateNewModule
= new JRadioButton(IdeBundle
.message("radio.create.new.module"), true);
125 myRbImportModule
= new JRadioButton(IdeBundle
.message("radio.import.existing.module"));
126 myButtonGroup
= new ButtonGroup();
127 myButtonGroup
.add(myRbCreateNewModule
);
128 myButtonGroup
.add(myRbImportModule
);
129 ModulesRbListener listener
= new ModulesRbListener();
130 myRbCreateNewModule
.addItemListener(listener
);
131 myRbImportModule
.addItemListener(listener
);
133 JTextField tfModuleFilePath
= new JTextField();
134 final String productName
= ApplicationNamesInfo
.getInstance().getProductName();
135 myModulePathFieldPanel
= createFieldPanel(tfModuleFilePath
, IdeBundle
.message("label.path.to.module.file", productName
),
136 new BrowseFilesListener( tfModuleFilePath
,
137 IdeBundle
.message("prompt.select.module.file.to.import", productName
), null,
138 new ModuleFileChooserDescriptor()));
139 myModulePathFieldPanel
.setEnabled(false);
141 if (createNewProject
) {
142 final JLabel moduleTypeLabel
= new JLabel(IdeBundle
.message("label.select.module.type"));
143 moduleTypeLabel
.setFont(UIUtil
.getLabelFont().deriveFont(Font
.BOLD
));
144 myPanel
.add(moduleTypeLabel
, LABEL_CONSTRAINT
);
147 myPanel
.add(myRbCreateNewModule
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 1, 1, 0.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.NONE
, new Insets(8, 10, 8, 10), 0, 0));
149 final JLabel descriptionLabel
= new JLabel(IdeBundle
.message("label.description"));
150 descriptionLabel
.setFont(UIUtil
.getLabelFont().deriveFont(Font
.BOLD
));
151 myPanel
.add(descriptionLabel
, new GridBagConstraints(1, GridBagConstraints
.RELATIVE
, 1, 1, 0.0, 0.0, GridBagConstraints
.SOUTHWEST
, GridBagConstraints
.NONE
, new Insets(0, 0, 0, 0), 0, 0));
153 final JScrollPane typesListScrollPane
= ScrollPaneFactory
.createScrollPane(myTypesList
);
154 final Dimension preferredSize
= calcTypeListPreferredSize(allModuleTypes
);
155 typesListScrollPane
.setPreferredSize(preferredSize
);
156 typesListScrollPane
.setMinimumSize(preferredSize
);
157 myPanel
.add(typesListScrollPane
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 1, 1, 0.2, (createNewProject?
1.0 : 0.0), GridBagConstraints
.NORTHWEST
, GridBagConstraints
.BOTH
, new Insets(0, createNewProject?
10 : 30, 0, 10), 0, 0));
159 final JScrollPane descriptionScrollPane
= ScrollPaneFactory
.createScrollPane(myModuleDescriptionPane
);
160 descriptionScrollPane
.setPreferredSize(new Dimension(preferredSize
.width
* 3, preferredSize
.height
));
161 myPanel
.add(descriptionScrollPane
, new GridBagConstraints(1, GridBagConstraints
.RELATIVE
, 1, 1, 0.8, (createNewProject?
1.0 : 0.0), GridBagConstraints
.CENTER
, GridBagConstraints
.BOTH
, new Insets(0, 0, 0, 10), 0, 0));
163 if (!createNewProject
) {
164 myPanel
.add(myRbImportModule
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 2, 1, 1.0, 0.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.NONE
, new Insets(16, 10, 0, 10), 0, 0));
165 myPanel
.add(myModulePathFieldPanel
, new GridBagConstraints(0, GridBagConstraints
.RELATIVE
, 2, 1, 1.0, 1.0, GridBagConstraints
.NORTHWEST
, GridBagConstraints
.HORIZONTAL
, new Insets(8, 30, 0, 10), 0, 0));
170 private Dimension
calcTypeListPreferredSize(final ModuleType
[] allModuleTypes
) {
173 final FontMetrics fontMetrics
= myTypesList
.getFontMetrics(myTypesList
.getFont());
174 final int fontHeight
= fontMetrics
.getMaxAscent() + fontMetrics
.getMaxDescent();
175 for (final ModuleType type
: allModuleTypes
) {
176 final Icon icon
= type
.getBigIcon();
177 final int iconHeight
= icon
!= null ? icon
.getIconHeight() : 0;
178 final int iconWidth
= icon
!= null ? icon
.getIconWidth() : 0;
179 height
+= Math
.max(iconHeight
, fontHeight
) + 6;
180 width
= Math
.max(width
, iconWidth
+ fontMetrics
.stringWidth(type
.getName()) + 10);
182 return new Dimension(width
, height
);
185 public String
getHelpId() {
186 return "project.creatingModules.page1";
189 public void setModuleListDoubleClickAction(Runnable runnable
) {
190 myDoubleClickAction
= runnable
;
193 public JComponent
getComponent() {
197 public Icon
getIcon() {
201 public boolean validate() {
202 if (myRbImportModule
.isSelected()) {
203 final String path
= myModulePathFieldPanel
.getText().trim();
204 if (path
.length() == 0) {
205 Messages
.showErrorDialog(
206 IdeBundle
.message("error.please.specify.path.to.module.file", ApplicationNamesInfo
.getInstance().getProductName()),
207 IdeBundle
.message("title.module.file.path.not.specified"));
208 myModulePathFieldPanel
.getTextField().requestFocus();
211 final File file
= new File(path
);
212 if (!file
.exists()) {
213 Messages
.showErrorDialog(IdeBundle
.message("error.module.file.does.not.exist"), IdeBundle
.message("title.module.file.does.not.exist"));
214 myModulePathFieldPanel
.getTextField().requestFocus();
217 if (!StdFileTypes
.IDEA_MODULE
.equals(FileTypeManager
.getInstance().getFileTypeByFileName(file
.getName()))) {
218 Messages
.showErrorDialog(IdeBundle
.message("error.module.not.iml", path
, ApplicationNamesInfo
.getInstance().getProductName()),
219 IdeBundle
.message("title.incorrect.file.type"));
220 myModulePathFieldPanel
.getTextField().requestFocus();
227 public boolean isNextButtonEnabled() {
228 return !myRbImportModule
.isSelected();
230 public boolean isCreateNewModule() {
231 return myRbCreateNewModule
.isSelected();
233 public boolean isImportExistingModule() {
234 return myRbImportModule
.isSelected();
237 public String
getModuleFilePath() {
238 return myModulePathFieldPanel
.getText().trim().replace(File
.separatorChar
, '/');
241 public ModuleType
getModuleType() {
245 public void addUpdateListener(UpdateListener listener
) {
246 myEventDispatcher
.addListener(listener
);
249 public void removeUpdateListener(UpdateListener listener
) {
250 myEventDispatcher
.removeListener(listener
);
253 public void updateDataModel() {
256 public JComponent
getPreferredFocusedComponent() {
260 private class ModulesRbListener
implements ItemListener
{
261 public void itemStateChanged(ItemEvent e
) {
262 final JComponent toFocus
;
263 ButtonModel selection
= myButtonGroup
.getSelection();
264 setControlsEnabled(selection
);
265 if (selection
== myRbCreateNewModule
.getModel()) {
266 toFocus
= myTypesList
;
267 myEventDispatcher
.getMulticaster().importModuleOptionSelected(false);
269 else if (selection
== myRbImportModule
.getModel()) { // import existing
270 toFocus
= myModulePathFieldPanel
.getTextField();
271 myEventDispatcher
.getMulticaster().importModuleOptionSelected(true);
277 if (toFocus
!= null) {
278 SwingUtilities
.invokeLater(new Runnable() {
280 toFocus
.requestFocus();
287 private void setControlsEnabled(ButtonModel selection
) {
288 boolean newModuleEnabled
= selection
== myRbCreateNewModule
.getModel();
289 myTypesList
.setEnabled(newModuleEnabled
);
290 myModuleDescriptionPane
.setEnabled(newModuleEnabled
);
292 boolean importModuleEnabled
= selection
== myRbImportModule
.getModel();
293 myModulePathFieldPanel
.setEnabled(importModuleEnabled
);
296 private static class ModuleFileChooserDescriptor
extends FileChooserDescriptor
{
297 public ModuleFileChooserDescriptor() {
298 super(true, false, false, false, false, false);
299 setHideIgnored(false);
302 public boolean isFileVisible(VirtualFile file
, boolean showHiddenFiles
) {
303 final boolean isVisible
= super.isFileVisible(file
, showHiddenFiles
);
304 if (!isVisible
|| file
.isDirectory()) {
307 return StdFileTypes
.IDEA_MODULE
.equals(FileTypeManager
.getInstance().getFileTypeByFile(file
));
311 private static class ModuleTypesListCellRenderer
extends DefaultListCellRenderer
{
312 public Component
getListCellRendererComponent(JList list
,
316 boolean cellHasFocus
) {
317 final Component rendererComponent
= super.getListCellRendererComponent(list
, value
, index
, isSelected
, cellHasFocus
);
318 final ModuleType moduleType
= (ModuleType
)value
;
319 setIcon(moduleType
.getBigIcon());
320 setDisabledIcon(moduleType
.getBigIcon());
321 setText(moduleType
.getName());
322 return rendererComponent
;
326 private static class PermanentSingleSelectionModel
extends DefaultListSelectionModel
{
327 public PermanentSingleSelectionModel() {
328 super.setSelectionMode(SINGLE_SELECTION
);
331 public final void setSelectionMode(int selectionMode
) {
334 public final void removeSelectionInterval(int index0
, int index1
) {