This commit is contained in:
Dmitry Avdeev
2013-10-21 15:27:41 +04:00
parent db19bf71b3
commit 315db0823d
7 changed files with 296 additions and 68 deletions
@@ -28,15 +28,9 @@
<properties/>
<border type="none"/>
<children>
<component id="15c1e" class="com.intellij.ui.treeStructure.Tree" binding="myProjectTypeTree">
<component id="5df9f" class="com.intellij.ui.components.JBList" binding="myProjectTypeList">
<constraints/>
<properties>
<rootVisible value="false"/>
<showsRootHandles value="false"/>
</properties>
<clientProperties>
<JTree.lineStyle class="java.lang.String" value="None"/>
</clientProperties>
<properties/>
</component>
</children>
</scrollpane>
@@ -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<ProjectCategory, ModuleBuilder> myBuilders = new FactoryMap<ProjectCategory, ModuleBuilder>() {
@@ -113,55 +109,27 @@ public class ProjectTypeStep extends ModuleWizardStep {
categories.putValue(category.getGroupName(), category);
}
List<ProjectCategory> list = new ArrayList<ProjectCategory>();
DefaultMutableTreeNode root = new DefaultMutableTreeNode();
MultiMap<TemplatesGroup,ProjectTemplate> templatesMap = CreateFromTemplateMode.getTemplatesMap(context, false);
List<TemplatesGroup> groups = new ArrayList<TemplatesGroup>(templatesMap.keySet());
Collections.sort(groups);
MultiMap<String, ProjectCategory> map = new MultiMap<String, ProjectCategory>();
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<ProjectCategory> 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.<FrameworkSupportInModuleProvider>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);
}
}
@@ -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<TemplateItem> myModel;
private Pair<TemplateItem, Integer> myBestMatch;
public ProjectTypesList(JBList list, MultiMap<String, ProjectCategory> map, final WizardContext context) {
myList = list;
new ListSpeedSearch(myList) {
@Override
protected String getElementText(Object element) {
return super.getElementText(element);
}
}.setComparator(new SpeedSearchComparator(false));
List<TemplateItem> items = buildItems(map);
myModel = new CollectionListModel<TemplateItem>(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<TemplateItem> buildItems(MultiMap<String, ProjectCategory> map) {
List<TemplateItem> items = new ArrayList<TemplateItem>();
List<String> groups = new ArrayList<String>(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();
}
}
}
@@ -76,8 +76,9 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
@Override
public void apply(@NotNull S settings) {
settings.setUseAutoImport(myUseAutoImportBox.isSelected());
myInitialSettings.setUseAutoImport(myUseAutoImportBox.isSelected());
settings.setExternalProjectPath(myInitialSettings.getExternalProjectPath());
if (myInitialSettings.getExternalProjectPath() != null) {
settings.setExternalProjectPath(myInitialSettings.getExternalProjectPath());
}
applyExtraSettings(settings);
}
+1
View File
@@ -175,6 +175,7 @@
<SOURCES />
</library>
</orderEntry>
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
</component>
</module>
@@ -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<GradlePro
@Override
public boolean isSuitableSdkType(SdkTypeId sdk) {
return sdk == JavaSdk.getInstance();
return sdk instanceof JavaSdkType;
}
@Override
@@ -0,0 +1,46 @@
/*
* 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 org.jetbrains.plugins.gradle;
import com.intellij.ide.projectWizard.NewProjectWizardTestCase;
import com.intellij.ide.projectWizard.ProjectTypeStep;
import com.intellij.ide.wizard.Step;
import com.intellij.openapi.project.Project;
import com.intellij.util.Consumer;
/**
* @author Dmitry Avdeev
* Date: 18.10.13
*/
public class GradleProjectWizardTest extends NewProjectWizardTestCase {
public void testGradleProject() throws Exception {
Project project = createProject(new Consumer<Step>() {
@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();
}
}