From f5354d3403b67b0a681e9f21f49da94e38f5d702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20L=C3=A4ubrich?= Date: Mon, 22 Jan 2024 13:19:40 +0100 Subject: [PATCH] Support selection of Bndtools Template in PDE Project Wizards PDE already offers a templating mechanism based on extension points, BndTools has one as well that is based on services. This is an attempt to make BndTools based items available for the new automatic manifest generation that currently lacks any wizards. Fix eclipse-pde#704 --- .../META-INF/MANIFEST.MF | 8 +- .../pde/bnd/ui/internal/TemplateAdapter.java | 81 +++++++++ .../templating/RepoTemplateLabelProvider.java | 60 ++++--- ui/org.eclipse.pde.ui/.settings/.api_filters | 121 +++++++++++++ ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF | 2 + ui/org.eclipse.pde.ui/plugin.properties | 1 + ui/org.eclipse.pde.ui/plugin.xml | 6 + .../pde/internal/ui/PDEUIMessages.java | 4 + .../ui/bndtools/BndCompletionProcessor.java | 5 +- .../pde/internal/ui/pderesources.properties | 2 + .../internal/ui/wizards/WizardElement.java | 82 ++++++++- .../ui/wizards/WizardListSelectionPage.java | 6 +- .../plugin/NewPluginProjectWizard.java | 82 +++++++++ .../plugin/TemplateListSelectionPage.java | 78 +++++++- .../plugin/TemplatePluginContentWizard.java | 168 ++++++++++++++++++ .../wizards/plugin/TemplateWizardHelper.java | 3 + 16 files changed, 661 insertions(+), 48 deletions(-) create mode 100644 ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/TemplateAdapter.java create mode 100644 ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/plugin/TemplatePluginContentWizard.java diff --git a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF index 71b9288c49..b76661324a 100644 --- a/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.bnd.ui/META-INF/MANIFEST.MF @@ -4,7 +4,10 @@ Bundle-Name: Generic UI components related to BND Bundle-SymbolicName: org.eclipse.pde.bnd.ui;singleton:=true Bundle-Vendor: Eclipse.org Bundle-Version: 1.0.0.qualifier -Export-Package: org.eclipse.pde.bnd.ui;version="1.0.0";x-friends:="org.eclipse.pde.ui" +Export-Package: org.eclipse.pde.bnd.ui;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.preferences;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.templating;version="1.0.0";x-friends:="org.eclipse.pde.ui", + org.eclipse.pde.bnd.ui.wizards;version="1.0.0";x-friends:="org.eclipse.pde.ui" Import-Package: aQute.bnd.build;version="4.5.0", aQute.bnd.build.model;version="4.3.0", aQute.bnd.build.model.clauses;version="2.5.0", @@ -37,5 +40,6 @@ Automatic-Module-Name: org.eclipse.pde.bnd.ui Bundle-Activator: org.eclipse.pde.bnd.ui.Resources Bundle-RequiredExecutionEnvironment: JavaSE-17 Service-Component: OSGI-INF/org.bndtools.templating.repos.xml, - OSGI-INF/org.eclipse.pde.bnd.ui.internal.Auxiliary.xml + OSGI-INF/org.eclipse.pde.bnd.ui.internal.Auxiliary.xml, + OSGI-INF/org.eclipse.pde.bnd.ui.internal.TemplateAdapter.xml Bundle-ActivationPolicy: lazy diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/TemplateAdapter.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/TemplateAdapter.java new file mode 100644 index 0000000000..a962623661 --- /dev/null +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/internal/TemplateAdapter.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2023 Christoph Läubrich and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Christoph Läubrich - initial API and implementation + *******************************************************************************/ +package org.eclipse.pde.bnd.ui.internal; + +import java.net.MalformedURLException; +import java.net.URI; + +import org.bndtools.templating.Template; +import org.eclipse.core.runtime.AdapterTypes; +import org.eclipse.core.runtime.IAdapterFactory; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.pde.bnd.ui.templating.RepoTemplateLabelProvider; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; + +@Component +@AdapterTypes(adaptableClass = Template.class, adapterNames = { ILabelProvider.class, Image.class }) +public class TemplateAdapter implements IAdapterFactory { + + private RepoTemplateLabelProvider labelProvider = new RepoTemplateLabelProvider(); + private ImageRegistry imageRegistry; + + @Override + public T getAdapter(Object adaptableObject, Class adapterType) { + if (adaptableObject instanceof Template template) { + if (adapterType == ILabelProvider.class) { + return adapterType.cast(labelProvider); + } + if (adapterType == Image.class) { + URI icon = template.getIcon(); + ImageRegistry registry = getImageRegistry(); + String key = icon.toASCIIString(); + ImageDescriptor descriptor = registry.getDescriptor(key); + if (descriptor == null) { + try { + registry.put(key, ImageDescriptor.createFromURL(icon.toURL())); + } catch (MalformedURLException e) { + return null; + } + } + return adapterType.cast(registry.get(key)); + } + } + return null; + } + + @Deactivate + void dispose() { + labelProvider.dispose(); + synchronized (this) { + if (imageRegistry != null) { + imageRegistry.dispose(); + } + } + } + + private ImageRegistry getImageRegistry() { + synchronized (this) { + if (imageRegistry == null) { + imageRegistry = new ImageRegistry(Display.getCurrent()); + } + return imageRegistry; + } + } + +} diff --git a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java index 8961796584..c043adfb4c 100644 --- a/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java +++ b/ui/org.eclipse.pde.bnd.ui/src/org/eclipse/pde/bnd/ui/templating/RepoTemplateLabelProvider.java @@ -15,44 +15,38 @@ *******************************************************************************/ package org.eclipse.pde.bnd.ui.templating; -import java.util.Map; - import org.bndtools.templating.Category; import org.bndtools.templating.Template; +import org.eclipse.core.runtime.Adapters; +import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.StyledCellLabelProvider; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.ViewerCell; import org.eclipse.pde.bnd.ui.BoldStyler; +import org.eclipse.pde.bnd.ui.Resources; +import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.PlatformUI; import org.osgi.framework.Version; -public class RepoTemplateLabelProvider extends StyledCellLabelProvider { - - private static final Image IMG_FOLDER = PlatformUI.getWorkbench() - .getSharedImages() - .getImage(ISharedImages.IMG_OBJ_FOLDER); +public class RepoTemplateLabelProvider extends StyledCellLabelProvider implements ILabelProvider { - private final Map loadedImages; - private final Image defaultIcon; - - public RepoTemplateLabelProvider(Map loadedImages, Image defaultIcon) { - this.loadedImages = loadedImages; - this.defaultIcon = defaultIcon; - } + private static final Image IMG_FOLDER = PlatformUI.getWorkbench().getSharedImages() + .getImage(ISharedImages.IMG_OBJ_FOLDER); @Override public void update(ViewerCell cell) { Object element = cell.getElement(); - - if (element instanceof Category) { - Category cat = (Category) element; + Category cat = Adapters.adapt(element, Category.class); + if (cat != null) { cell.setText(cat.getName()); cell.setImage(IMG_FOLDER); - } else if (element instanceof Template) { - Template template = (Template) element; - + cell.setStyleRanges(new StyleRange[0]); + return; + } + Template template = Adapters.adapt(element, Template.class); + if (template != null) { // Name StyledString label = new StyledString(template.getName(), BoldStyler.INSTANCE_DEFAULT); @@ -61,7 +55,7 @@ public void update(ViewerCell cell) { if (version != null) { label.append(" "); label.append(String.format("%d.%d.%d", version.getMajor(), version.getMinor(), version.getMicro()), - BoldStyler.INSTANCE_COUNTER); + BoldStyler.INSTANCE_COUNTER); String q = version.getQualifier(); if (q != null && !q.isEmpty()) label.append("." + q, StyledString.COUNTER_STYLER); @@ -70,19 +64,33 @@ public void update(ViewerCell cell) { String description = template.getShortDescription(); if (description != null) { label.append(" \u2014 [", StyledString.QUALIFIER_STYLER) - .append(template.getShortDescription(), StyledString.QUALIFIER_STYLER) - .append("]", StyledString.QUALIFIER_STYLER); + .append(template.getShortDescription(), StyledString.QUALIFIER_STYLER) + .append("]", StyledString.QUALIFIER_STYLER); } cell.setText(label.toString()); cell.setStyleRanges(label.getStyleRanges()); - Image image = loadedImages.get(template); + Image image = Adapters.adapt(template, Image.class); if (image == null) - cell.setImage(defaultIcon); + cell.setImage(Resources.getImage("/icons/template.gif")); else cell.setImage(image); + return; } + cell.setStyleRanges(new StyleRange[0]); + cell.setText(getText(element)); + cell.setImage(getImage(element)); + } + + @Override + public Image getImage(Object element) { + return null; + } + + @Override + public String getText(Object element) { + return null; } -} +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.ui/.settings/.api_filters b/ui/org.eclipse.pde.ui/.settings/.api_filters index 6499fc7159..4ef7528f55 100644 --- a/ui/org.eclipse.pde.ui/.settings/.api_filters +++ b/ui/org.eclipse.pde.ui/.settings/.api_filters @@ -1,5 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -8,6 +47,14 @@ + + + + + + + + @@ -16,6 +63,14 @@ + + + + + + + + @@ -32,6 +87,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -66,6 +163,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF b/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF index 6a024241ea..891e3f30f1 100644 --- a/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF +++ b/ui/org.eclipse.pde.ui/META-INF/MANIFEST.MF @@ -131,7 +131,9 @@ Import-Package: aQute.bnd.build;version="4.5.0", aQute.bnd.properties;version="[2.0.0,3.0.0)", aQute.bnd.service;version="[4.8.0,5.0.0)", aQute.bnd.version;version="[2.2.0,3.0.0)", + aQute.service.reporter;version="1.2.0", biz.aQute.resolve;version="[9.0.0,10.0.0)", + org.bndtools.templating;version="[2.0.0,3.0.0)", org.eclipse.jdt.debug.ui.console, org.eclipse.ui.internal.genericeditor, org.osgi.service.event;version="[1.4,2.0.0)", diff --git a/ui/org.eclipse.pde.ui/plugin.properties b/ui/org.eclipse.pde.ui/plugin.properties index 10565a463f..bb1089d176 100644 --- a/ui/org.eclipse.pde.ui/plugin.properties +++ b/ui/org.eclipse.pde.ui/plugin.properties @@ -40,6 +40,7 @@ preferences.main.name= Plug-in Development preferences.target.name = Target Platform preferences.compilers.name = Compilers preferences.editor.name = Editors +preferences.bnd.templaterepo.name = Bnd Template Repositories preferenceKeywords.PDE=Plug-in plugin Development PDE preferenceKeywords.MainPreferencePage=java search target source dependencies JUnit launch workspace configuration plug-in fragment bundle diff --git a/ui/org.eclipse.pde.ui/plugin.xml b/ui/org.eclipse.pde.ui/plugin.xml index 87b0b9a1df..5467aac110 100644 --- a/ui/org.eclipse.pde.ui/plugin.xml +++ b/ui/org.eclipse.pde.ui/plugin.xml @@ -84,6 +84,12 @@ id="org.eclipse.pde.ui.TargetPlatformPreferencePage"> + + diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java index fbf66eab27..4e83d3ea13 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/PDEUIMessages.java @@ -645,6 +645,8 @@ public class PDEUIMessages extends NLS { public static String BaseWizardSelectionPage_noDesc; + public static String BaseWizardSelectionPage_loadingDesc; + public static String ChooseClassXMLResolution_label; public static String ChooseManifestClassResolution_label; @@ -1194,6 +1196,8 @@ public class PDEUIMessages extends NLS { public static String NewPluginProjectFromTemplateWizard_1; + public static String NewPluginProjectWizard_0; + public static String NewProjectWizard_MainPage_ftitle; public static String NewProductFileWizard_windowTitle; public static String NewProjectWizard_MainPage_fdesc; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/bndtools/BndCompletionProcessor.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/bndtools/BndCompletionProcessor.java index 55add9d025..075fa865a5 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/bndtools/BndCompletionProcessor.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/bndtools/BndCompletionProcessor.java @@ -32,6 +32,7 @@ import org.eclipse.jface.text.contentassist.IContentAssistProcessor; import org.eclipse.jface.text.contentassist.IContextInformation; import org.eclipse.jface.text.contentassist.IContextInformationValidator; +import org.eclipse.swt.widgets.Display; import aQute.bnd.help.Syntax; @@ -52,8 +53,8 @@ public ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int ICompletionProposal[] found = proposals(prefix, offset); if (found.length == 1) { found[0].apply(document); - viewer.setSelectedRange(offset + (found[0].getDisplayString().length() - prefix.length() + 2), - 0); + Display.getDefault().execute(() -> viewer.setSelectedRange( + offset + (found[0].getDisplayString().length() - prefix.length() + 2), 0)); return new ICompletionProposal[0]; } return found; diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties index 1e2ae5e188..47a847d77d 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/pderesources.properties @@ -723,6 +723,7 @@ SourceBlock_remove = &Remove NewFragmentProjectWizard_title = New Fragment Project NewPluginProjectFromTemplateWizard_0=Could not load the template {0} NewPluginProjectFromTemplateWizard_1=Problem loading plug-in template +NewPluginProjectWizard_0=Loading Templates... NewProjectWizard_MainPage_ftitle = Fragment Project NewProductFileWizard_windowTitle=New Product Configuration NewProjectWizard_MainPage_fdesc = Create a new fragment project @@ -1003,6 +1004,7 @@ BaseExtensionPoint_pluginId = &Plug-in ID: BaseExtensionPoint_id = &Extension Point ID: BaseExtensionPoint_name = Extension Point &Name: BaseWizardSelectionPage_noDesc=No Description available. +BaseWizardSelectionPage_loadingDesc=Loading Description... BaseExtensionPoint_schema = Extension Point &Schema: BaseExtensionPoint_schemaLocation = C&ontainer: BaseExtensionPoint_edit = E&dit extension point schema when done diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardElement.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardElement.java index 1a485b2ade..1a29c7cd0a 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardElement.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardElement.java @@ -16,19 +16,25 @@ import java.util.MissingResourceException; import java.util.ResourceBundle; +import org.bndtools.templating.Template; +import org.eclipse.core.runtime.Adapters; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.pde.internal.ui.PDEPlugin; import org.eclipse.pde.internal.ui.elements.NamedElement; +import org.eclipse.pde.internal.ui.wizards.plugin.TemplatePluginContentWizard; +import org.eclipse.pde.internal.ui.wizards.plugin.TemplateWizardHelper; import org.eclipse.swt.graphics.Image; import org.eclipse.ui.IPluginContribution; import org.osgi.framework.Bundle; +import org.osgi.framework.Version; /** * Handle to a configuration element representing a wizard class. */ -public class WizardElement extends NamedElement implements IPluginContribution { +public class WizardElement extends NamedElement implements IPluginContribution, IAdaptable { public static final String ATT_NAME = "name"; //$NON-NLS-1$ public static final String TAG_DESCRIPTION = "description"; //$NON-NLS-1$ @@ -39,16 +45,27 @@ public class WizardElement extends NamedElement implements IPluginContribution { public static final String ATT_POINT = "point"; //$NON-NLS-1$ private String description; - protected IConfigurationElement configurationElement; + private IConfigurationElement configurationElement; private IConfigurationElement template; + private Template bndTemplate; + private String id; WizardElement(IConfigurationElement config) { super(config.getAttribute(ATT_NAME)); this.configurationElement = config; } + WizardElement(Template template, String id) { + super(template.getName()); + this.bndTemplate = template; + this.id = id; + } + public Object createExecutableExtension() throws CoreException { - return configurationElement.createExecutableExtension(ATT_CLASS); + if (configurationElement != null) { + return configurationElement.createExecutableExtension(ATT_CLASS); + } + return new TemplatePluginContentWizard(bndTemplate); } public IConfigurationElement getConfigurationElement() { @@ -56,12 +73,15 @@ public IConfigurationElement getConfigurationElement() { } public String getDescription() { - if (description == null) { + if (description == null && configurationElement != null) { IConfigurationElement[] children = configurationElement.getChildren(TAG_DESCRIPTION); if (children.length > 0) { description = expandDescription(children[0].getValue()); } } + if (description == null && bndTemplate != null) { + description = bndTemplate.getShortDescription(); + } return description; } @@ -81,10 +101,23 @@ public boolean getFlag(String name, boolean defaultValue) { if (value != null) { return value.equalsIgnoreCase("true"); //$NON-NLS-1$ } + } else if (bndTemplate != null) { + return TemplateWizardHelper.FLAG_BND.equals(name); } return defaultValue; } + public String getName() { + return getLabel(); + } + + public Version getVersion() { + if (bndTemplate != null) { + return bndTemplate.getVersion(); + } + return Version.emptyVersion; + } + /** * We allow replacement variables in description values as well. This is to * allow extension template description reuse in project template wizards. @@ -138,15 +171,29 @@ private String expandDescription(String source) { } public String getID() { - return configurationElement.getAttribute(ATT_ID); + if (configurationElement != null) { + return configurationElement.getAttribute(ATT_ID); + } + return id; } public void setImage(Image image) { this.image = image; } + @Override + public Image getImage() { + if (this.image == null && bndTemplate != null) { + setImage(Adapters.adapt(bndTemplate, Image.class)); + } + return this.image; + } + public String getTemplateId() { - return configurationElement.getAttribute(ATT_TEMPLATE); + if (configurationElement != null) { + return configurationElement.getAttribute(ATT_TEMPLATE); + } + return null; } public boolean isTemplate() { @@ -154,7 +201,7 @@ public boolean isTemplate() { } public IConfigurationElement getTemplateElement() { - if (template == null) + if (template == null && configurationElement != null) template = findTemplateElement(); return template; } @@ -163,7 +210,8 @@ private IConfigurationElement findTemplateElement() { String templateId = getTemplateId(); if (templateId == null) return null; - IConfigurationElement[] templates = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.pde.ui.templates"); //$NON-NLS-1$ + IConfigurationElement[] templates = Platform.getExtensionRegistry() + .getConfigurationElementsFor("org.eclipse.pde.ui.templates"); //$NON-NLS-1$ for (IConfigurationElement template : templates) { String id = template.getAttribute("id"); //$NON-NLS-1$ if (id != null && id.equals(templateId)) @@ -203,4 +251,20 @@ public static WizardElement create(IConfigurationElement config, String... requi return element; } -} + public static WizardElement create(Template template, String id) { + String name = template.getName(); + if (name == null || name.isBlank()) { + return null; + } + return new WizardElement(template, id); + } + + @Override + public T getAdapter(Class adapter) { + if (adapter == Template.class) { + return adapter.cast(bndTemplate); + } + return null; + } + +} \ No newline at end of file diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardListSelectionPage.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardListSelectionPage.java index 52082e235d..bda7ebab1d 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardListSelectionPage.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/WizardListSelectionPage.java @@ -135,10 +135,14 @@ public void selectionChanged(SelectionChangedEvent event) { } final WizardElement finalSelection = currentWizardSelection; setSelectedNode(createWizardNode(finalSelection)); - setDescriptionText(finalSelection.getDescription()); + setDescriptionText(getWizardDescription(finalSelection)); getContainer().updateButtons(); } + protected String getWizardDescription(final WizardElement element) { + return element.getDescription(); + } + public IWizardPage getNextPage(boolean shouldCreate) { if (!shouldCreate) return super.getNextPage(); diff --git a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/plugin/NewPluginProjectWizard.java b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/plugin/NewPluginProjectWizard.java index e3598827a3..543fff02f1 100644 --- a/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/plugin/NewPluginProjectWizard.java +++ b/ui/org.eclipse.pde.ui/src/org/eclipse/pde/internal/ui/wizards/plugin/NewPluginProjectWizard.java @@ -14,7 +14,19 @@ package org.eclipse.pde.internal.ui.wizards.plugin; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Comparator; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Objects; +import java.util.SortedMap; +import java.util.stream.Collectors; +import org.bndtools.templating.Template; +import org.bndtools.templating.TemplateLoader; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -23,8 +35,12 @@ import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.dialogs.IDialogSettings; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.wizard.IWizardContainer; import org.eclipse.jface.wizard.IWizardPage; import org.eclipse.pde.internal.core.PDECore; import org.eclipse.pde.internal.ui.PDEPlugin; @@ -37,6 +53,12 @@ import org.eclipse.pde.ui.IPluginContentWizard; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceReference; +import org.osgi.util.promise.Promise; +import org.osgi.util.tracker.ServiceTracker; + +import aQute.bnd.osgi.Processor; public class NewPluginProjectWizard extends NewWizard implements IExecutableExtension { public static final String PLUGIN_POINT = "pluginContent"; //$NON-NLS-1$ @@ -177,6 +199,66 @@ public ElementList getAvailableCodegenWizards() { } } } + try { + IWizardContainer container = getContainer(); + if (container == null) { + // can happen in tests or when the wizard is not setup + // properly... + return wizards; + } + container.run(true, true, new IRunnableWithProgress() { + + @Override + public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { + ServiceTracker tracker = new ServiceTracker<>( + PDEPlugin.getDefault().getBundle().getBundleContext(), TemplateLoader.class, null); + tracker.open(); + try { + SortedMap, TemplateLoader> tracked = tracker.getTracked(); + SubMonitor subMonitor = SubMonitor.convert(monitor, PDEUIMessages.NewPluginProjectWizard_0, + tracked.size()); + Map> templatesByCategory = new HashMap<>(); + for (Entry, TemplateLoader> entry : tracked.entrySet()) { + ServiceReference reference = entry.getKey(); + TemplateLoader templateLoader = entry.getValue(); + String label = (String) reference.getProperty(Constants.SERVICE_DESCRIPTION); + if (label == null) { + label = (String) reference.getProperty("component.name"); //$NON-NLS-1$ + } + if (label == null) { + label = "Template Loader " + templateLoader.getClass().getSimpleName(); //$NON-NLS-1$ + } + subMonitor.subTask(label); + Promise> templates = templateLoader.findTemplates("project", //$NON-NLS-1$ + new Processor()); + Collection