From 4f93b7d31485a4a976ec8608374ba2b86e9c45b1 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Tue, 24 Dec 2013 12:07:13 +0400 Subject: [PATCH] ProjectTemplateList --- .../projectWizard/ProjectTemplateList.form | 55 ++++ .../projectWizard/ProjectTemplateList.java | 149 +++++++++++ .../ide/projectWizard/ProjectTypeStep.form | 38 +-- .../ide/projectWizard/ProjectTypeStep.java | 78 +++--- .../ide/projectWizard/ProjectTypesList.java | 243 ------------------ .../openapi/ui/popup/ListItemDescriptor.java | 12 +- 6 files changed, 245 insertions(+), 330 deletions(-) create mode 100644 java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form create mode 100644 java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java delete mode 100644 java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form new file mode 100644 index 000000000000..60af5653a56a --- /dev/null +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form @@ -0,0 +1,55 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java new file mode 100644 index 000000000000..1acf03349249 --- /dev/null +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java @@ -0,0 +1,149 @@ +/* + * 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.openapi.ui.Messages; +import com.intellij.openapi.ui.popup.ListItemDescriptor; +import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.SystemInfo; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.platform.ProjectTemplate; +import com.intellij.platform.templates.ArchivedProjectTemplate; +import com.intellij.ui.CollectionListModel; +import com.intellij.ui.components.JBList; +import com.intellij.ui.popup.list.GroupedItemsListRenderer; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; +import java.awt.*; +import java.util.*; +import java.util.List; + +/** + * @author Dmitry Avdeev + * Date: 12/24/13 + */ +public class ProjectTemplateList extends JPanel { + + private JBList myList; + private JPanel myPanel; + private JTextPane myDescriptionPane; + private ProjectTemplate myFirstArchivedTemplate; + + public ProjectTemplateList() { + super(new BorderLayout()); + add(myPanel, BorderLayout.CENTER); + + myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() { + @Nullable + @Override + public String getTextFor(ProjectTemplate value) { + return value.getName(); + } + + @Nullable + @Override + public String getTooltipFor(ProjectTemplate value) { + return null; + } + + @Nullable + @Override + public Icon getIconFor(ProjectTemplate value) { + return value.getIcon(); + } + + @Override + public boolean hasSeparatorAboveOf(ProjectTemplate value) { + return value == myFirstArchivedTemplate; + } + + @Nullable + @Override + public String getCaptionAboveOf(ProjectTemplate value) { + return "Project Templates"; + } + })); + + + myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent e) { + myDescriptionPane.setText(""); + ProjectTemplate template = getSelectedTemplate(); + if (template != null) { + String description = template.getDescription(); + if (StringUtil.isNotEmpty(description)) { + description = "' + description + + ""; + myDescriptionPane.setText(description); + } + } + } + }); + + Messages.installHyperlinkSupport(myDescriptionPane); + } + + public void setTemplates(List list) { + Collections.sort(list, new Comparator() { + @Override + public int compare(ProjectTemplate o1, ProjectTemplate o2) { + return Comparing.compare(o1 instanceof ArchivedProjectTemplate, o2 instanceof ArchivedProjectTemplate); + } + }); + myFirstArchivedTemplate = ContainerUtil.find(list, new Condition() { + @Override + public boolean value(ProjectTemplate template) { + return template instanceof ArchivedProjectTemplate; + } + }); + + int index = myList.getSelectedIndex(); + //noinspection unchecked + myList.setModel(new CollectionListModel(list)); + myList.setSelectedIndex(index == -1 ? 0 : index); + } + + public ProjectTemplate getSelectedTemplate() { + return (ProjectTemplate)myList.getSelectedValue(); + } + + public void addListSelectionListener(ListSelectionListener listener) { + myList.addListSelectionListener(listener); + } + + public boolean setSelectedTemplate(String name) { + ListModel model1 = myList.getModel(); + for (int j = 0; j < model1.getSize(); j++) { + if (name.equals(((ProjectTemplate)model1.getElementAt(j)).getName())) { + myList.setSelectedIndex(j); + return true; + } + } + + return false; + } + + public void setPaintBusy(boolean b) { + myList.setPaintBusy(b); + } +} 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 b9956d276498..10682f75335f 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form @@ -55,43 +55,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 9fcbd21b7771..f13e3ea38fb8 100644 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java +++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java @@ -25,11 +25,8 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.roots.ui.configuration.ModulesProvider; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.SystemInfo; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.platform.ProjectTemplate; import com.intellij.platform.ProjectTemplateEP; import com.intellij.platform.templates.ArchivedProjectTemplate; @@ -71,8 +68,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act private JPanel myPanel; private JPanel myOptionsPanel; private JBList myProjectTypeList; - private JTextPane myDescription; - private JBList myTemplatesList; + private ProjectTemplateList myTemplatesList; @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") private final FactoryMap myBuilders = new FactoryMap() { @@ -83,8 +79,8 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act } }; private final Set myCards = new HashSet(); - private final MultiMap myTemplatesMap; + private boolean myRemoteTemplatesLoaded; public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) { myContext = context; @@ -154,23 +150,17 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act } }); - myTemplatesList.setCellRenderer(new ColoredListCellRenderer() { - @Override - protected void customizeCellRenderer(JList list, ProjectTemplate value, int index, boolean selected, boolean hasFocus) { - append(value.getName()).setIcon(value.getIcon()); - } - }); - myTemplatesList.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + myTemplatesList.addListSelectionListener(new ListSelectionListener() { @Override public void valueChanged(ListSelectionEvent e) { updateSelection(); } }); + for (ProjectTemplate category : myTemplatesMap.values()) { myWizard.getSequence().addStepsForBuilder(myBuilders.get(category), context, modulesProvider); } - Messages.installHyperlinkSupport(myDescription); myProjectTypeList.setSelectedIndex(0); } @@ -180,21 +170,39 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act TemplatesGroup group = getSelectedGroup(); if (group == null) return; Collection templates = myTemplatesMap.get(group); - String card = DEFAULT_CARD; + if (!selectCustomOptions(templates)) { + setTemplatesList(group, templates); + ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, DEFAULT_CARD); + } + updateSelection(); + } + + private void setTemplatesList(TemplatesGroup group, Collection templates) { + ArrayList list = new ArrayList(templates); + if (group.getParentGroup() == null) { + for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) { + if (group.getName().equals(templatesGroup.getParentGroup())) { + list.addAll(myTemplatesMap.get(templatesGroup)); + } + } + } + myTemplatesList.setTemplates(list); + } + + private boolean selectCustomOptions(Collection templates) { if (templates.size() == 1) { ModuleBuilder builder = myBuilders.get(templates.iterator().next()); JComponent panel = builder.getCustomOptionsPanel(this); if (panel != null) { - card = builder.getBuilderId(); + String card = builder.getBuilderId(); if (myCards.add(card)) { myOptionsPanel.add(panel, card); } + ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, card); + return true; } } - myTemplatesList.setModel(new CollectionListModel(templates)); - myTemplatesList.setSelectedIndex(0); - ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, card); - updateSelection(); + return false; } private TemplatesGroup getSelectedGroup() { @@ -212,7 +220,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act return template; } } - return (ProjectTemplate)myTemplatesList.getSelectedValue(); + return myTemplatesList.getSelectedTemplate(); } @Nullable @@ -236,7 +244,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act @Override public void updateStep() { - if (myContext.isCreatingNewProject()) { + if (myContext.isCreatingNewProject() && !myRemoteTemplatesLoaded) { loadRemoteTemplates(); } } @@ -256,13 +264,7 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act for (int i = 0; i < model.getSize(); i++) { if (group.equals(((TemplatesGroup)model.getElementAt(i)).getName())) { myProjectTypeList.setSelectedIndex(i); - ListModel model1 = myTemplatesList.getModel(); - for (int j = 0; j < model1.getSize(); j++) { - if (name.equals(((ProjectTemplate)model1.getElementAt(j)).getName())) { - myTemplatesList.setSelectedIndex(j); - return true; - } - } + return myTemplatesList.setSelectedTemplate(name); } } return false; @@ -315,14 +317,13 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act TemplatesGroup group = getSelectedGroup(); if (group == null) return; Collection templates = myTemplatesMap.get(group); - int index = myTemplatesList.getSelectedIndex(); - myTemplatesList.setModel(new CollectionListModel(templates)); - myTemplatesList.setSelectedIndex(index); + setTemplatesList(group, templates); } }); } finally { myTemplatesList.setPaintBusy(false); + myRemoteTemplatesLoaded = true; } } }); @@ -334,19 +335,6 @@ public class ProjectTypeStep extends ModuleWizardStep implements Disposable, Act } private void updateSelection() { - ProjectTemplate template = getSelectedTemplate(); - if (template != null) { - String description = template.getDescription(); - if (StringUtil.isNotEmpty(description)) { - description = "' + description + - ""; - myDescription.setText(description); - } - } - else { - myDescription.setText(""); - } ModuleBuilder builder = getSelectedBuilder(); if (builder != null) { myContext.setProjectBuilder(builder); diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java deleted file mode 100644 index d557a89c3883..000000000000 --- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * 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.newProjectWizard.TemplatesGroup; -import com.intellij.ide.util.projectWizard.ModuleBuilder; -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.module.ModuleType; -import com.intellij.openapi.ui.popup.ListItemDescriptor; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Pair; -import com.intellij.platform.ProjectTemplatesFactory; -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.FactoryMap; -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.*; - -/** - * @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, FactoryMap builders) { - - myList = list; - myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - - new ListSpeedSearch(myList) { - @Override - protected String getElementText(Object element) { - return super.getElementText(element); - } - }.setComparator(new SpeedSearchComparator(false)); - List items = buildItems(map, builders); - 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 || !setSelectedType(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 static List buildItems(final MultiMap map, final FactoryMap builders) { - List items = new ArrayList(); - List groups = new ArrayList(map.keySet()); - - final Map moduleTypeMap = new HashMap(); - for (ProjectCategory category : map.values()) { - ModuleType type = builders.get(category).getModuleType(); - Integer integer = moduleTypeMap.get(type); - moduleTypeMap.put(type, integer == null ? 0 : integer + 1); - } - - Collections.sort(groups, new Comparator() { - @Override - public int compare(TemplatesGroup o1, TemplatesGroup o2) { - int weight = Comparing.compare(o1.getName().equals(ProjectTemplatesFactory.OTHER_GROUP), o2.getName().equals(ProjectTemplatesFactory.OTHER_GROUP)); - if (weight != 0) return weight; - int byModuleType = getModuleTypePopularity(o2, map, builders, moduleTypeMap) - getModuleTypePopularity(o1, map, builders, moduleTypeMap); - if (byModuleType != 0) return byModuleType; - int i = map.get(o2).size() - map.get(o1).size(); // compare group size - return i == 0 ? o1.compareTo(o2) : i; - } - }); - - for (TemplatesGroup group : groups) { - for (ProjectCategory template : map.get(group)) { - TemplateItem templateItem = new TemplateItem(template, group.getName()); - items.add(templateItem); - } - } - return items; - } - - private static int getModuleTypePopularity(TemplatesGroup group, - MultiMap map, - FactoryMap builders, - Map moduleTypeMap) { - int moduleTypePopularity = 0; - for (ProjectCategory category : map.get(group)) { - ModuleType type = builders.get(category).getModuleType(); - moduleTypePopularity = Math.max(moduleTypePopularity, moduleTypeMap.get(type)); - } - return moduleTypePopularity; - } - - @Nullable - public ProjectCategory getSelectedType() { - Object value = myList.getSelectedValue(); - return value instanceof TemplateItem ? ((TemplateItem)value).myTemplate : null; - } - - public boolean setSelectedType(@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() { - } - - static 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/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java index e77761706495..ae9dee1448a5 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java @@ -22,18 +22,18 @@ import javax.swing.*; /** * @author kir */ -public interface ListItemDescriptor { +public interface ListItemDescriptor { @Nullable - String getTextFor(Object value); + String getTextFor(T value); @Nullable - String getTooltipFor(Object value); + String getTooltipFor(T value); @Nullable - Icon getIconFor(Object value); + Icon getIconFor(T value); - boolean hasSeparatorAboveOf(Object value); + boolean hasSeparatorAboveOf(T value); @Nullable - String getCaptionAboveOf(Object value); + String getCaptionAboveOf(T value); }