diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.form b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.form
new file mode 100644
index 000000000000..b6804c1570f9
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.form
@@ -0,0 +1,58 @@
+
+
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
new file mode 100644
index 000000000000..378989e50b02
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2012 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.util.newProjectWizard;
+
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.openapi.util.Condition;
+import com.intellij.platform.DirectoryProjectGenerator;
+import com.intellij.platform.WebProjectGenerator;
+import com.intellij.psi.codeStyle.MinusculeMatcher;
+import com.intellij.psi.codeStyle.NameUtil;
+import com.intellij.ui.CollectionListModel;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.SearchTextField;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.*;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 9/26/12
+ */
+public class SelectTemplateStep extends ModuleWizardStep {
+
+ private JPanel myPanel;
+ private JBList myTemplatesList;
+ private JPanel mySettingsPanel;
+ private SearchTextField mySearchField;
+ private FactoryMap myPeers = new FactoryMap() {
+ @Nullable
+ @Override
+ protected WebProjectGenerator.GeneratorPeer create(WebProjectGenerator key) {
+ return key.createPeer();
+ }
+ };
+
+ public SelectTemplateStep() {
+ final DirectoryProjectGenerator[] extensions = DirectoryProjectGenerator.EP_NAME.getExtensions();
+ myTemplatesList.setModel(new CollectionListModel(extensions));
+ myTemplatesList.setCellRenderer(new ColoredListCellRenderer() {
+ @Override
+ protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ append(((DirectoryProjectGenerator)value).getName());
+ }
+ });
+ myTemplatesList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ if (mySettingsPanel.getComponentCount() > 0) {
+ mySettingsPanel.remove(0);
+ }
+ DirectoryProjectGenerator generator = getSelectedGenerator();
+ if (generator instanceof WebProjectGenerator) {
+ WebProjectGenerator.GeneratorPeer peer = myPeers.get(generator);
+ mySettingsPanel.add(peer.getComponent(), BorderLayout.NORTH);
+ }
+ mySettingsPanel.revalidate();
+ }
+ });
+ if (myTemplatesList.getModel().getSize() > 0) {
+ myTemplatesList.setSelectedIndex(0);
+ }
+ mySearchField.addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ final MinusculeMatcher matcher = NameUtil.buildMatcher(mySearchField.getText(), NameUtil.MatchingCaseSensitivity.NONE);
+ DirectoryProjectGenerator generator = getSelectedGenerator();
+ List list = ContainerUtil.filter(extensions, new Condition() {
+ @Override
+ public boolean value(DirectoryProjectGenerator generator) {
+ String name = generator.getName();
+ String[] words = NameUtil.nameToWords(name);
+ for (String word : words) {
+ if (matcher.matches(word)) return true;
+ }
+ return false;
+ }
+ });
+ myTemplatesList.setModel(new CollectionListModel(list));
+ if (!list.isEmpty()) {
+ if (list.contains(generator)) {
+ myTemplatesList.setSelectedValue(generator, true);
+ }
+ else {
+ myTemplatesList.setSelectedIndex(0);
+ }
+ }
+ }
+ });
+ }
+
+ public DirectoryProjectGenerator getSelectedGenerator() {
+ return (DirectoryProjectGenerator)myTemplatesList.getSelectedValue();
+ }
+
+ public WebProjectGenerator.GeneratorPeer getPeer(DirectoryProjectGenerator generator) {
+ return myPeers.get(generator);
+ }
+
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return mySearchField;
+ }
+
+ @Override
+ public void updateDataModel() {
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/StepSequence.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/StepSequence.java
index 93e79b8c81b1..c2536ef25c59 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/StepSequence.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/StepSequence.java
@@ -36,6 +36,10 @@ public class StepSequence {
@NonNls private List myTypes = new ArrayList();
private List mySelectedSteps;
+ public StepSequence(ModuleWizardStep... commonSteps) {
+ myCommonSteps.addAll(Arrays.asList(commonSteps));
+ }
+
public void addCommonStep(@NotNull ModuleWizardStep step){
myCommonSteps.add(step);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
new file mode 100644
index 000000000000..6205001d18de
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2012 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.util.newProjectWizard.modes;
+
+import com.intellij.ide.util.newProjectWizard.ProjectNameStep;
+import com.intellij.ide.util.newProjectWizard.SelectTemplateStep;
+import com.intellij.ide.util.newProjectWizard.StepSequence;
+import com.intellij.ide.util.projectWizard.ProjectBuilder;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.openapi.module.ModifiableModuleModel;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.WebModuleBuilder;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectBundle;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.platform.DirectoryProjectGenerator;
+import com.intellij.platform.WebProjectGenerator;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 9/26/12
+ */
+public class CreateFromTemplateMode extends WizardMode {
+
+ private final SelectTemplateStep mySelectTemplateStep = new SelectTemplateStep();
+
+ @NotNull
+ @Override
+ public String getDisplayName(WizardContext context) {
+ return ProjectBundle.message("project.new.wizard.from.template.title", context.getPresentationName());
+ }
+
+ @NotNull
+ @Override
+ public String getDescription(WizardContext context) {
+ return ProjectBundle.message("project.new.wizard.from.template.description", context.getPresentationName());
+ }
+
+ @Override
+ public boolean isAvailable(WizardContext context) {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ protected StepSequence createSteps(WizardContext context, @NotNull ModulesProvider modulesProvider) {
+ return new StepSequence(mySelectTemplateStep, new ProjectNameStep(context, this));
+ }
+
+ @Nullable
+ @Override
+ public ProjectBuilder getModuleBuilder() {
+ return new WebModuleBuilder() {
+ @Nullable
+ @Override
+ public List commit(Project project, ModifiableModuleModel model, ModulesProvider modulesProvider) {
+ List modules = super.commit(project, model, modulesProvider);
+ if (modules != null && modules.size() == 1) {
+ Module module = modules.get(0);
+ DirectoryProjectGenerator generator = mySelectTemplateStep.getSelectedGenerator();
+ WebProjectGenerator.GeneratorPeer peer = mySelectTemplateStep.getPeer(generator);
+ generator.generateProject(project, project.getBaseDir(), peer.getSettings(), module);
+ }
+ return modules;
+ }
+ };
+ }
+
+ @Override
+ public void onChosen(boolean enabled) {
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java
new file mode 100644
index 000000000000..34d199c3910e
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2012 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.openapi.module;
+
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.roots.ModifiableRootModel;
+
+/**
+* @author Dmitry Avdeev
+* Date: 9/27/12
+*/
+public class WebModuleBuilder extends ModuleBuilder {
+ @Override
+ public void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException {
+ doAddContentEntry(modifiableRootModel);
+ }
+
+ @Override
+ public ModuleType getModuleType() {
+ return WebModuleType.getInstance();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleType.java b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleType.java
index 426686827d0e..cd048d659cf2 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleType.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleType.java
@@ -4,8 +4,6 @@ import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WebModuleGenerationStep;
import com.intellij.ide.util.projectWizard.WizardContext;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import org.jetbrains.annotations.NotNull;
@@ -29,16 +27,6 @@ public class WebModuleType extends WebModuleTypeBase {
}
public ModuleBuilder createModuleBuilder() {
- return new ModuleBuilder() {
- @Override
- public void setupRootModel(ModifiableRootModel modifiableRootModel) throws ConfigurationException {
- doAddContentEntry(modifiableRootModel);
- }
-
- @Override
- public ModuleType getModuleType() {
- return getInstance();
- }
- };
+ return new WebModuleBuilder();
}
}
diff --git a/platform/projectModel-impl/src/messages/ProjectBundle.properties b/platform/projectModel-impl/src/messages/ProjectBundle.properties
index 1fcf28787663..9e8bd0e600cb 100644
--- a/platform/projectModel-impl/src/messages/ProjectBundle.properties
+++ b/platform/projectModel-impl/src/messages/ProjectBundle.properties
@@ -402,6 +402,9 @@ project.new.wizard.import.title=Import {0} from external &model
project.new.wizard.import.description=Create {0} {1} from external model ({2})
project.new.wizard.from.existent.sources.title=Create {0} from &existing sources
project.new.wizard.from.existent.sources.description=Create {0} {1} structure over existing sources
+project.new.wizard.from.template.title=Create {0} from &template
+project.new.wizard.from.template.description=Create {0} with pre-defined support for your favourite framework/technology
+
project.new.wizard.module.name.title=Module na&me:
project.new.wizard.module.root.title=Content &root:
project.new.wizard.module.file.title=Module &file location:
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 0ba816b6ea7a..c1995d226f29 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -1310,9 +1310,12 @@
+
+
+