1 /*******************************************************************************
2  *  Copyright (c) 2005, 2015 IBM Corporation and others.
3  *
4  *  This program and the accompanying materials
5  *  are made available under the terms of the Eclipse Public License 2.0
6  *  which accompanies this distribution, and is available at
7  *  https://www.eclipse.org/legal/epl-2.0/
8  *
9  *  SPDX-License-Identifier: EPL-2.0
10  *
11  *  Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.pde.internal.ui.wizards.product;
15 
16 import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
17 
18 import java.util.TreeSet;
19 import org.eclipse.core.resources.IProject;
20 import org.eclipse.core.runtime.IConfigurationElement;
21 import org.eclipse.core.runtime.IExtension;
22 import org.eclipse.jface.dialogs.Dialog;
23 import org.eclipse.jface.window.Window;
24 import org.eclipse.jface.wizard.WizardPage;
25 import org.eclipse.pde.core.plugin.*;
26 import org.eclipse.pde.internal.core.PDECore;
27 import org.eclipse.pde.internal.core.iproduct.IProduct;
28 import org.eclipse.pde.internal.ui.IHelpContextIds;
29 import org.eclipse.pde.internal.ui.PDEUIMessages;
30 import org.eclipse.pde.internal.ui.dialogs.PluginSelectionDialog;
31 import org.eclipse.pde.internal.ui.search.ShowDescriptionAction;
32 import org.eclipse.pde.internal.ui.util.SWTUtil;
33 import org.eclipse.swt.SWT;
34 import org.eclipse.swt.events.*;
35 import org.eclipse.swt.layout.GridData;
36 import org.eclipse.swt.layout.GridLayout;
37 import org.eclipse.swt.widgets.*;
38 import org.eclipse.ui.PlatformUI;
39 import org.eclipse.ui.forms.events.HyperlinkEvent;
40 import org.eclipse.ui.forms.events.IHyperlinkListener;
41 import org.eclipse.ui.forms.widgets.FormText;
42 import org.eclipse.ui.forms.widgets.FormToolkit;
43 
44 public class ProductIntroWizardPage extends WizardPage implements IHyperlinkListener {
45 
46 	private Text fPluginText;
47 	private Text fIntroIdText;
48 	private TreeSet<String> fIntroIds;
49 	private IProduct fProduct;
50 
51 	private ModifyListener fListener = e -> validatePage();
52 
ProductIntroWizardPage(String pageName, IProduct product)53 	public ProductIntroWizardPage(String pageName, IProduct product) {
54 		super(pageName);
55 		setTitle(PDEUIMessages.ProductIntroWizardPage_title);
56 		setDescription(PDEUIMessages.ProductIntroWizardPage_description);
57 		fIntroIds = getCurrentIntroIds();
58 		fProduct = product;
59 	}
60 
61 	@Override
createControl(Composite parent)62 	public void createControl(Composite parent) {
63 		Composite comp = new Composite(parent, SWT.NONE);
64 		GridLayout layout = new GridLayout();
65 		layout.verticalSpacing = 20;
66 		comp.setLayout(layout);
67 
68 		FormToolkit toolkit = new FormToolkit(parent.getDisplay());
69 		createProductGroup(toolkit, comp);
70 		toolkit.dispose();
71 
72 		setControl(comp);
73 		setPageComplete(getPluginId() != null);
74 		Dialog.applyDialogFont(comp);
75 		PlatformUI.getWorkbench().getHelpSystem().setHelp(comp, IHelpContextIds.PRODUCT_DEFINITIONS_WIZARD);
76 	}
77 
createProductGroup(FormToolkit toolkit, Composite comp)78 	private void createProductGroup(FormToolkit toolkit, Composite comp) {
79 		Group group = new Group(comp, SWT.NONE);
80 		group.setText(PDEUIMessages.ProductIntroWizardPage_groupText);
81 		group.setLayout(new GridLayout(3, false));
82 		group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
83 
84 		FormText text = toolkit.createFormText(group, false);
85 		text.setText(PDEUIMessages.ProductIntroWizardPage_formText, true, false);
86 		GridData gd = new GridData(GridData.FILL_HORIZONTAL);
87 		gd.horizontalSpan = 3;
88 		gd.widthHint = 400;
89 		text.setLayoutData(gd);
90 		text.setBackground(null);
91 		text.addHyperlinkListener(this);
92 
93 		Label label = new Label(group, SWT.NONE);
94 		label.setText(PDEUIMessages.ProductIntroWizardPage_targetLabel);
95 
96 		fPluginText = new Text(group, SWT.SINGLE | SWT.BORDER);
97 		fPluginText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
98 
99 		Button button = new Button(group, SWT.PUSH);
100 		button.setText(PDEUIMessages.ProductIntroWizardPage_browse);
101 		SWTUtil.setButtonDimensionHint(button);
102 		button.addSelectionListener(widgetSelectedAdapter(e -> handleBrowse()));
103 
104 		label = new Label(group, SWT.NONE);
105 		label.setText(PDEUIMessages.ProductIntroWizardPage_introLabel);
106 
107 		fIntroIdText = new Text(group, SWT.SINGLE | SWT.BORDER);
108 		gd = new GridData(GridData.FILL_HORIZONTAL);
109 		gd.horizontalSpan = 2;
110 		fIntroIdText.setLayoutData(gd);
111 
112 		String pluginId = getPluginId();
113 		if (pluginId != null) {
114 			fPluginText.setText(pluginId);
115 			fIntroIdText.setText(getAvailableIntroId(pluginId));
116 		}
117 		fPluginText.addModifyListener(fListener);
118 		fIntroIdText.addModifyListener(fListener);
119 	}
120 
121 	@Override
setVisible(boolean visible)122 	public void setVisible(boolean visible) {
123 		super.setVisible(visible);
124 		if (visible) {
125 			fPluginText.setVisible(visible);
126 			fPluginText.setFocus();
127 		}
128 	}
129 
validatePage()130 	private void validatePage() {
131 		String error = null;
132 		String pluginId = getDefiningPlugin();
133 		IPluginModelBase model = PluginRegistry.findModel(pluginId);
134 		if (model == null) {
135 			error = PDEUIMessages.ProductDefinitonWizardPage_noPlugin;
136 		} else if (model.getUnderlyingResource() == null) {
137 			error = PDEUIMessages.ProductDefinitonWizardPage_notInWorkspace;
138 		} else if (pluginId.length() == 0) {
139 			error = PDEUIMessages.ProductIntroWizardPage_targetNotSet;
140 		}
141 		validateId(error);
142 
143 	}
144 
validateId(String error)145 	private void validateId(String error) {
146 		if (error == null) {
147 			String id = fIntroIdText.getText().trim();
148 
149 			if (id.length() == 0)
150 				error = PDEUIMessages.ProductIntroWizardPage_introNotSet;
151 
152 			if (error == null)
153 				for (int i = 0; i < id.length(); i++)
154 					if (!id.substring(i, i + 1).matches("[a-zA-Z0-9.]")) //$NON-NLS-1$
155 						error = PDEUIMessages.ProductIntroWizardPage_invalidIntroId;
156 
157 			if (error == null && fIntroIds.contains(id))
158 				error = PDEUIMessages.ProductIntroWizardPage_introIdExists;
159 		}
160 		setErrorMessage(error);
161 		setPageComplete(error == null);
162 	}
163 
handleBrowse()164 	private void handleBrowse() {
165 		PluginSelectionDialog dialog = new PluginSelectionDialog(getShell(), PluginRegistry.getWorkspaceModels(), false);
166 		if (dialog.open() == Window.OK) {
167 			IPluginModelBase model = (IPluginModelBase) dialog.getFirstResult();
168 			String id = model.getPluginBase().getId();
169 			fPluginText.setText(id);
170 			fIntroIdText.setText(getAvailableIntroId(id));
171 		}
172 	}
173 
getAvailableIntroId(String id)174 	private String getAvailableIntroId(String id) {
175 		String introId = "intro"; //$NON-NLS-1$
176 		String numString = ""; //$NON-NLS-1$
177 		int idNum = 1;
178 		while (fIntroIds.contains(id + "." + introId + numString)) { //$NON-NLS-1$
179 			numString = Integer.toString(idNum++);
180 		}
181 		return id + "." + introId + numString; //$NON-NLS-1$
182 	}
183 
getCurrentIntroIds()184 	private TreeSet<String> getCurrentIntroIds() {
185 		String introId;
186 		TreeSet<String> result = new TreeSet<>();
187 		IExtension[] extensions = PDECore.getDefault().getExtensionsRegistry().findExtensions("org.eclipse.ui.intro", true); //$NON-NLS-1$
188 		for (IExtension extension : extensions) {
189 			IConfigurationElement[] children = extension.getConfigurationElements();
190 			for (IConfigurationElement element : children) {
191 				if ("intro".equals(element.getName())) {//$NON-NLS-1$
192 					introId = element.getAttribute("id"); //$NON-NLS-1$
193 					if (introId != null)
194 						result.add(introId);
195 				}
196 			}
197 		}
198 		return result;
199 	}
200 
getDefiningPlugin()201 	public String getDefiningPlugin() {
202 		return fPluginText.getText().trim();
203 	}
204 
getIntroId()205 	public String getIntroId() {
206 		return fIntroIdText.getText().trim();
207 	}
208 
getPluginId()209 	private String getPluginId() {
210 		IProject project = fProduct.getModel().getUnderlyingResource().getProject();
211 		IPluginModelBase model = PluginRegistry.findModel(project);
212 		return (model == null) ? null : model.getPluginBase().getId();
213 	}
214 
215 	@Override
linkEntered(HyperlinkEvent e)216 	public void linkEntered(HyperlinkEvent e) {
217 	}
218 
219 	@Override
linkExited(HyperlinkEvent e)220 	public void linkExited(HyperlinkEvent e) {
221 	}
222 
223 	@Override
linkActivated(HyperlinkEvent e)224 	public void linkActivated(HyperlinkEvent e) {
225 		String extPoint = "org.eclipse.ui." + e.getHref().toString(); //$NON-NLS-1$
226 		IPluginExtensionPoint point = PDECore.getDefault().getExtensionsRegistry().findExtensionPoint(extPoint);
227 		if (point != null)
228 			new ShowDescriptionAction(point, true).run();
229 
230 	}
231 }
232