diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
index 680468047b02..000469cc2a44 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
@@ -28,15 +28,9 @@
-
+
-
-
-
-
-
-
-
+
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
index 64feffc6a93f..b4d33c7ed4e3 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
@@ -36,23 +36,18 @@ import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.platform.ProjectTemplate;
-import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.components.JBLabel;
-import com.intellij.ui.treeStructure.Tree;
+import com.intellij.ui.components.JBList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.DefaultMutableTreeNode;
-import javax.swing.tree.DefaultTreeModel;
-import javax.swing.tree.TreePath;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.util.*;
import java.util.List;
@@ -70,8 +65,9 @@ public class ProjectTypeStep extends ModuleWizardStep {
private final ModulesProvider myModulesProvider;
private JPanel myPanel;
private JPanel myOptionsPanel;
- private Tree myProjectTypeTree;
private JBLabel myGroupDescriptionLabel;
+ private JBList myProjectTypeList;
+ private final ProjectTypesList myList;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final FactoryMap myBuilders = new FactoryMap() {
@@ -113,55 +109,27 @@ public class ProjectTypeStep extends ModuleWizardStep {
categories.putValue(category.getGroupName(), category);
}
- List list = new ArrayList();
- DefaultMutableTreeNode root = new DefaultMutableTreeNode();
MultiMap templatesMap = CreateFromTemplateMode.getTemplatesMap(context, false);
List groups = new ArrayList(templatesMap.keySet());
Collections.sort(groups);
+ MultiMap map = new MultiMap();
for (TemplatesGroup group : groups) {
- DefaultMutableTreeNode groupNode = new DefaultMutableTreeNode(group);
- root.add(groupNode);
+ String name = group.getName();
for (ProjectTemplate template : templatesMap.get(group)) {
TemplateBasedProjectType projectType = new TemplateBasedProjectType(template);
- groupNode.add(new DefaultMutableTreeNode(projectType));
- list.add(projectType);
+ map.putValue(name, projectType);
}
- Collection collection = categories.get(group.getName());
- for (ProjectCategory category : collection) {
- groupNode.add(new DefaultMutableTreeNode(category));
- list.add(category);
+ for (ProjectCategory category : categories.get(name)) {
+ map.putValue(name, category);
}
}
- myProjectTypeTree.setModel(new DefaultTreeModel(root));
- TreeUtil.expandAll(myProjectTypeTree);
+ myList = new ProjectTypesList(myProjectTypeList, map, context);
- myProjectTypeTree.setCellRenderer(new ColoredTreeCellRenderer() {
- @Override
- public void customizeCellRenderer(JTree tree,
- Object value,
- boolean selected,
- boolean expanded,
- boolean leaf,
- int row,
- boolean hasFocus) {
- Object object = ((DefaultMutableTreeNode)value).getUserObject();
- if (object instanceof ProjectCategory) {
- ProjectCategory category = (ProjectCategory)object;
- append(category.getDisplayName());
- setIcon(category.getIcon());
- }
- else {
- TemplatesGroup group = (TemplatesGroup)object;
- append(group.getName());
- setIcon(group.getIcon());
- }
- }
- });
+ myProjectTypeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
- myProjectTypeTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
@Override
- public void valueChanged(TreeSelectionEvent e) {
+ public void valueChanged(ListSelectionEvent e) {
ModuleBuilder builder = getSelectedBuilder();
if (builder != null) {
myContext.setProjectBuilder(builder);
@@ -172,29 +140,25 @@ public class ProjectTypeStep extends ModuleWizardStep {
}
});
- for (ProjectCategory category : list) {
- myWizard.getSequence().addStepsForBuilder(myBuilders.get(category), context, modulesProvider, true);
+ for (ProjectCategory category : map.values()) {
+ myWizard.getSequence().addStepsForBuilder(myBuilders.get(category), context, modulesProvider, false);
}
myFrameworksPanel = new AddSupportForFrameworksPanel(Collections.emptyList(), model, true);
Disposer.register(wizard.getDisposable(), myFrameworksPanel);
myOptionsPanel.add(myFrameworksPanel.getMainPanel(), FRAMEWORKS_CARD);
-
- // todo save selection
- myProjectTypeTree.addSelectionRow(1);
}
@Nullable
- public Object getSelectedObject() {
- TreePath path = myProjectTypeTree.getSelectionPath();
- return path == null ? null : ((DefaultMutableTreeNode)path.getLastPathComponent()).getUserObject();
+ public ProjectCategory getSelectedObject() {
+ return myList.getSelectedTemplate();
}
@Nullable
private ModuleBuilder getSelectedBuilder() {
- Object object = getSelectedObject();
- return object instanceof ProjectCategory ? myBuilders.get(object) : null;
+ ProjectCategory object = getSelectedObject();
+ return object == null ? null : myBuilders.get(object);
}
private void updateOptionsPanel(Object object) {
@@ -284,13 +248,28 @@ public class ProjectTypeStep extends ModuleWizardStep {
myWizard.getSequence().addStepsForBuilder(builder, myContext, myModulesProvider, true);
}
+ @Override
+ public void updateStep() {
+ myList.resetSelection();
+ }
+
+ @Override
+ public void onStepLeaving() {
+ myList.saveSelection();
+ }
+
@Override
public JComponent getPreferredFocusedComponent() {
- return myProjectTypeTree;
+ return myProjectTypeList;
}
@TestOnly
public AddSupportForFrameworksPanel getFrameworksPanel() {
return myFrameworksPanel;
}
+
+ @TestOnly
+ public boolean setSelectedProjectType(String group, String name) {
+ return myList.setSelectedTemplate(group, name);
+ }
}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java
new file mode 100644
index 000000000000..26d49ea782b4
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.projectWizard;
+
+import com.intellij.ide.util.newProjectWizard.SelectTemplateSettings;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
+import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.util.Pair;
+import com.intellij.ui.CollectionListModel;
+import com.intellij.ui.ListSpeedSearch;
+import com.intellij.ui.SpeedSearchComparator;
+import com.intellij.ui.components.JBList;
+import com.intellij.ui.popup.list.GroupedItemsListRenderer;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 11/21/12
+ */
+public class ProjectTypesList implements Disposable {
+
+ private final JBList myList;
+ private final CollectionListModel myModel;
+ private Pair myBestMatch;
+
+ public ProjectTypesList(JBList list, MultiMap map, final WizardContext context) {
+ myList = list;
+
+ new ListSpeedSearch(myList) {
+ @Override
+ protected String getElementText(Object element) {
+ return super.getElementText(element);
+ }
+ }.setComparator(new SpeedSearchComparator(false));
+ List items = buildItems(map);
+ myModel = new CollectionListModel(items);
+
+ myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() {
+ @Nullable
+ @Override
+ public String getTextFor(Object value) {
+ return ((TemplateItem)value).getName();
+ }
+
+ @Nullable
+ @Override
+ public String getTooltipFor(Object value) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Icon getIconFor(Object value) {
+ return ((TemplateItem)value).getIcon();
+ }
+
+ @Override
+ public boolean hasSeparatorAboveOf(Object value) {
+ TemplateItem item = (TemplateItem)value;
+ int index = myModel.getElementIndex(item);
+ return index == 0 || !myModel.getElementAt(index - 1).getGroupName().equals(item.getGroupName());
+ }
+
+ @Nullable
+ @Override
+ public String getCaptionAboveOf(Object value) {
+ return ((TemplateItem)value).getGroupName();
+ }
+ }));
+
+ myList.setModel(myModel);
+ }
+
+ void installKeyAction(JComponent component) {
+ new AnAction() {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ InputEvent event = e.getInputEvent();
+ if (event instanceof KeyEvent) {
+ int row = myList.getSelectedIndex();
+ int toSelect;
+ switch (((KeyEvent)event).getKeyCode()) {
+ case KeyEvent.VK_UP:
+ toSelect = row == 0 ? myList.getItemsCount() - 1 : row - 1;
+ myList.setSelectedIndex(toSelect);
+ myList.ensureIndexIsVisible(toSelect);
+ break;
+ case KeyEvent.VK_DOWN:
+ toSelect = row < myList.getItemsCount() - 1 ? row + 1 : 0;
+ myList.setSelectedIndex(toSelect);
+ myList.ensureIndexIsVisible(toSelect);
+ break;
+ }
+ }
+ }
+ }.registerCustomShortcutSet(new CustomShortcutSet(KeyEvent.VK_UP, KeyEvent.VK_DOWN), component);
+ }
+
+ void resetSelection() {
+ if (myList.getSelectedIndex() != -1) return;
+ SelectTemplateSettings settings = SelectTemplateSettings.getInstance();
+ if (settings.getLastGroup() == null || !setSelectedTemplate(settings.getLastGroup(), settings.getLastTemplate())) {
+ myList.setSelectedIndex(0);
+ }
+ }
+
+ void saveSelection() {
+ TemplateItem item = (TemplateItem)myList.getSelectedValue();
+ if (item != null) {
+ SelectTemplateSettings.getInstance().setLastTemplate(item.getGroupName(), item.getName());
+ }
+ }
+
+ private List buildItems(MultiMap map) {
+ List items = new ArrayList();
+ List groups = new ArrayList(map.keySet());
+ Collections.sort(groups);
+ for (String group : groups) {
+ for (ProjectCategory template : map.get(group)) {
+ TemplateItem templateItem = new TemplateItem(template, group);
+ items.add(templateItem);
+ }
+ }
+ return items;
+ }
+
+ @Nullable
+ public ProjectCategory getSelectedTemplate() {
+ Object value = myList.getSelectedValue();
+ return value instanceof TemplateItem ? ((TemplateItem)value).myTemplate : null;
+ }
+
+ public boolean setSelectedTemplate(@Nullable String group, @Nullable String name) {
+ for (int i = 0; i < myList.getModel().getSize(); i++) {
+ Object o = myList.getModel().getElementAt(i);
+ if (o instanceof TemplateItem && ((TemplateItem)o).myGroup.equals(group) && ((TemplateItem)o).getName().equals(name)) {
+ myList.setSelectedIndex(i);
+ myList.ensureIndexIsVisible(i);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ class TemplateItem {
+
+ private final ProjectCategory myTemplate;
+ private final String myGroup;
+
+ TemplateItem(ProjectCategory template, String group) {
+ myTemplate = template;
+ myGroup = group;
+ }
+
+ String getName() {
+ return myTemplate.getDisplayName();
+ }
+
+ public String getGroupName() {
+ return myGroup;
+ }
+
+ Icon getIcon() {
+ return myTemplate.createModuleBuilder().getNodeIcon();
+ }
+
+ @Nullable
+ String getDescription() {
+ return myTemplate.getDescription();
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " " + getGroupName();
+ }
+ }
+}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
index 10465cfb6f50..5b933b1d1f9d 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalProjectSettingsControl.java
@@ -76,8 +76,9 @@ public abstract class AbstractExternalProjectSettingsControl
+
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
index 31c9f5a91fc4..36922d3806f9 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
@@ -22,7 +22,7 @@ import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModule
import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
-import com.intellij.openapi.projectRoots.JavaSdk;
+import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -76,7 +76,7 @@ public class GradleModuleBuilder extends AbstractExternalModuleBuilder() {
+ @Override
+ public void consume(Step step) {
+ if (step instanceof ProjectTypeStep) {
+ assertTrue(((ProjectTypeStep)step).setSelectedProjectType("Java", "Gradle"));
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ setupJdk();
+ }
+}