new project wizard: adding project templates

This commit is contained in:
Dmitry Avdeev
2013-11-08 12:37:07 +04:00
parent 25e633cdb2
commit 62eeca9c70
7 changed files with 153 additions and 62 deletions
@@ -45,29 +45,7 @@
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="none"/>
<children>
<grid id="4ffce" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<card name="group description card"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="3c23c" class="com.intellij.ui.components.JBLabel" binding="myGroupDescriptionLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
<vspacer id="617a5">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</children>
<children/>
</grid>
</children>
</grid>
@@ -39,9 +39,18 @@ import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.platform.ProjectTemplate;
import com.intellij.ui.components.JBLabel;
import com.intellij.platform.ProjectTemplateEP;
import com.intellij.platform.templates.LocalArchivedTemplate;
import com.intellij.ui.CollectionListModel;
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.components.JBList;
import com.intellij.ui.tabs.TabInfo;
import com.intellij.ui.tabs.TabsListener;
import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.MultiMap;
@@ -53,6 +62,7 @@ import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.net.URL;
import java.util.*;
import java.util.List;
@@ -60,7 +70,7 @@ import java.util.List;
* @author Dmitry Avdeev
* Date: 04.09.13
*/
public class ProjectTypeStep extends ModuleWizardStep {
public class ProjectTypeStep extends ModuleWizardStep implements Disposable {
private static final String FRAMEWORKS_CARD = "frameworks card";
private static final String GROUP_CARD = "group description card";
@@ -69,9 +79,12 @@ public class ProjectTypeStep extends ModuleWizardStep {
private final ModulesProvider myModulesProvider;
private JPanel myPanel;
private JPanel myOptionsPanel;
private JBLabel myGroupDescriptionLabel;
private JBList myProjectTypeList;
private final ProjectTypesList myList;
private final ProjectTypesList myProjectTypesList;
private final JBList myTemplatesList;
private final TabInfo myFrameworksTab;
private final TabInfo myTemplatesTab;
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
private final FactoryMap<ProjectCategory, ModuleBuilder> myBuilders = new FactoryMap<ProjectCategory, ModuleBuilder>() {
@@ -86,6 +99,7 @@ public class ProjectTypeStep extends ModuleWizardStep {
private final AddSupportForFrameworksPanel myFrameworksPanel;
private final ModuleBuilder.ModuleConfigurationUpdater myConfigurationUpdater;
private boolean myCommitted;
private final JBTabsImpl myTabs;
public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) {
myContext = context;
@@ -129,19 +143,12 @@ public class ProjectTypeStep extends ModuleWizardStep {
}
}
myList = new ProjectTypesList(myProjectTypeList, map);
myProjectTypesList = new ProjectTypesList(myProjectTypeList, map);
myProjectTypeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
ModuleBuilder builder = getSelectedBuilder();
if (builder != null) {
myContext.setProjectBuilder(builder);
myWizard.getSequence().setType(builder.getBuilderId());
builder.addModuleConfigurationUpdater(myConfigurationUpdater);
}
updateOptionsPanel(getSelectedObject());
projectTypeChanged(true);
}
});
@@ -152,17 +159,59 @@ public class ProjectTypeStep extends ModuleWizardStep {
myFrameworksPanel = new AddSupportForFrameworksPanel(Collections.<FrameworkSupportInModuleProvider>emptyList(), model, true);
Disposer.register(wizard.getDisposable(), myFrameworksPanel);
myOptionsPanel.add(myFrameworksPanel.getMainPanel(), FRAMEWORKS_CARD);
myTemplatesList = new JBList();
myTemplatesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myTemplatesList.setCellRenderer(new ColoredListCellRenderer<ProjectCategory>() {
@Override
protected void customizeCellRenderer(JList list, ProjectCategory value, int index, boolean selected, boolean hasFocus) {
append(value.getDisplayName()).setIcon(value.getIcon());
}
});
myTemplatesList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
projectTypeChanged(false);
}
});
myTabs = new JBTabsImpl(null, IdeFocusManager.findInstance(), this);
myTabs.addListener(new TabsListener.Adapter() {
@Override
public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
projectTypeChanged(false);
}
});
myFrameworksTab = new TabInfo(myFrameworksPanel.getMainPanel()).setText(" Frameworks ");
myTabs.addTab(myFrameworksTab);
myTemplatesTab = new TabInfo(ScrollPaneFactory.createScrollPane(myTemplatesList)).setText(" Templates ");
myTabs.addTab(myTemplatesTab);
myOptionsPanel.add(myTabs.getComponent(), FRAMEWORKS_CARD);
}
public void projectTypeChanged(boolean updatePanel) {
ModuleBuilder builder = getSelectedBuilder();
if (builder != null) {
myContext.setProjectBuilder(builder);
myWizard.getSequence().setType(builder.getBuilderId());
if (myFrameworksTab == myTabs.getSelectedInfo()) {
builder.addModuleConfigurationUpdater(myConfigurationUpdater);
}
}
if (updatePanel) {
updateOptionsPanel(getSelectedProjectType());
}
}
@Nullable
public ProjectCategory getSelectedObject() {
return myList.getSelectedTemplate();
public ProjectCategory getSelectedProjectType() {
return myTabs.getSelectedInfo() == myFrameworksTab ?
myProjectTypesList.getSelectedTemplate() :
(ProjectCategory)myTemplatesList.getSelectedValue();
}
@Nullable
private ModuleBuilder getSelectedBuilder() {
ProjectCategory object = getSelectedObject();
ProjectCategory object = getSelectedProjectType();
return object == null ? null : myBuilders.get(object);
}
@@ -197,11 +246,17 @@ public class ProjectTypeStep extends ModuleWizardStep {
myFrameworksPanel.setProviders(matched,
new HashSet<String>(Arrays.asList(projectCategory.getAssociatedFrameworkIds())),
new HashSet<String>(Arrays.asList(projectCategory.getPreselectedFrameworkIds())));
List<ProjectCategory> templates = getTemplates(projectCategory.getId());
myFrameworksTab.setHidden(matched.isEmpty() && !templates.isEmpty());
//noinspection unchecked
myTemplatesList.setModel(new CollectionListModel<ProjectCategory>(templates));
myTemplatesTab.setHidden(templates.isEmpty());
if (!templates.isEmpty()) {
myTemplatesList.setSelectedIndex(0);
}
}
}
else if (object instanceof TemplatesGroup) {
myGroupDescriptionLabel.setText(((TemplatesGroup)object).getDescription());
}
((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, card);
}
@@ -230,17 +285,17 @@ public class ProjectTypeStep extends ModuleWizardStep {
@Override
public void updateStep() {
myList.resetSelection();
myProjectTypesList.resetSelection();
}
@Override
public void onStepLeaving() {
myList.saveSelection();
myProjectTypesList.saveSelection();
}
@Override
public void onWizardFinished() throws CommitStepException {
if (!myCommitted) {
if (!myCommitted && myTabs.getSelectedInfo() == myFrameworksTab) {
boolean ok = myFrameworksPanel.downloadLibraries();
if (!ok) {
int answer = Messages.showYesNoDialog(getComponent(),
@@ -266,6 +321,28 @@ public class ProjectTypeStep extends ModuleWizardStep {
@TestOnly
public boolean setSelectedProjectType(String group, String name) {
return myList.setSelectedTemplate(group, name);
return myProjectTypesList.setSelectedTemplate(group, name);
}
@Override
public void dispose() {
}
private static List<ProjectCategory> getTemplates(final String projectType) {
ProjectTemplateEP[] extensions = ProjectTemplateEP.EP_NAME.getExtensions();
return ContainerUtil.mapNotNull(extensions, new NullableFunction<ProjectTemplateEP, ProjectCategory>() {
@Nullable
@Override
public ProjectCategory fun(ProjectTemplateEP ep) {
if (!projectType.equals(ep.projectType)) {
return null;
}
ClassLoader classLoader = ep.getLoaderForClass();
URL url = classLoader.getResource(ep.templatePath);
return url == null ? null : new TemplateBasedProjectType(new LocalArchivedTemplate(url, classLoader));
}
});
}
}
@@ -17,12 +17,10 @@ package com.intellij.ide.projectWizard;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.templates.ArchivedTemplatesFactory;
import com.intellij.platform.templates.LocalArchivedTemplate;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
import java.net.URL;
/**
@@ -36,8 +34,7 @@ public class TemplateBasedProjectType extends ProjectCategory {
public TemplateBasedProjectType(String templatePath) {
URL resource = getClass().getResource(templatePath);
assert resource != null : templatePath;
String name = ArchivedTemplatesFactory.getTemplateName(new File(templatePath).getName());
myTemplate = new LocalArchivedTemplate(name, resource, getClass().getClassLoader());
myTemplate = new LocalArchivedTemplate(resource, getClass().getClassLoader());
}
public TemplateBasedProjectType(ProjectTemplate template) {
@@ -41,7 +41,7 @@ import java.util.*;
*/
public class ArchivedTemplatesFactory extends ProjectTemplatesFactory {
private static final String ZIP = ".zip";
static final String ZIP = ".zip";
private final ClearableLazyValue<MultiMap<String, Pair<URL, ClassLoader>>> myGroups = new ClearableLazyValue<MultiMap<String, Pair<URL, ClassLoader>>>() {
@NotNull
@@ -83,7 +83,8 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory {
if (index != -1) {
child = child.substring(0, index);
}
map.putValue(child.replace('_', ' '), Pair.create(new URL(url.getKey().toExternalForm() + "/" + child), url.getValue()));
String name = child.replace('_', ' ');
map.putValue(name, Pair.create(new URL(url.getKey().toExternalForm() + "/" + child), url.getValue()));
}
}
catch (IOException e) {
@@ -132,8 +133,7 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory {
for (String child : children) {
if (child.endsWith(ZIP)) {
URL templateUrl = new URL(url.first.toExternalForm() + "/" + child);
String name = getTemplateName(child);
templates.add(new LocalArchivedTemplate(name, templateUrl, url.second));
templates.add(new LocalArchivedTemplate(templateUrl, url.second));
}
}
}
@@ -144,10 +144,6 @@ public class ArchivedTemplatesFactory extends ProjectTemplatesFactory {
return templates.toArray(new ProjectTemplate[templates.size()]);
}
public static String getTemplateName(String child) {
return child.substring(0, child.length() - ZIP.length()).replace('_', ' ');
}
@Override
public int getGroupWeight(String group) {
return CUSTOM_GROUP.equals(group) ? -2 : 0;
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Collections;
@@ -52,10 +53,9 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate {
private List<WizardInputField> myInputFields = Collections.emptyList();
private Icon myIcon;
public LocalArchivedTemplate(@NotNull String displayName,
@NotNull URL archivePath,
public LocalArchivedTemplate(@NotNull URL archivePath,
@NotNull ClassLoader classLoader) {
super(displayName);
super(getTemplateName(archivePath));
myArchivePath = archivePath;
myModuleType = computeModuleType(this);
@@ -80,6 +80,11 @@ public class LocalArchivedTemplate extends ArchivedProjectTemplate {
}
}
private static String getTemplateName(URL url) {
String fileName = new File(url.getPath()).getName();
return fileName.substring(0, fileName.length() - ArchivedTemplatesFactory.ZIP.length()).replace('_', ' ');
}
@Override
public String getDescription() {
return readEntry(new Condition<ZipEntry>() {