/******************************************************************************* * Copyright (c) 2012, 2013 GoPivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * GoPivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.wizard.template; import java.util.ArrayList; import java.util.List; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jdt.internal.ui.workingsets.IWorkingSetIDs; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.ui.IWorkingSet; import org.eclipse.ui.dialogs.WorkingSetGroup; import org.springframework.ide.eclipse.wizard.template.infrastructure.Template; import org.springsource.ide.eclipse.commons.content.core.util.Descriptor; /** * Creates a base Spring project based on a Java project creation. * */ public class NewSpringProjectWizardMainPage extends WizardPage implements IWizardPageStatusHandler { private SpringVersion version; private TemplateSelectionPart part; private SpringVersionArea springArea; private final NewSpringProjectWizardModel model; private WorkingSetGroup workingSetGroup; private final List<WizardPageArea> wizardAreas = new ArrayList<WizardPageArea>(); public SpringVersion getVersion() { return version; } public NewSpringProjectWizardMainPage(NewSpringProjectWizardModel model) { super(NewSpringProjectWizardMessages.NewProject_title, "Create a Spring project by selecting a template or simple project type.", null); this.model = model; } public void refreshTemplateInUI() { if (part != null) { part.refreshSelectedTemplateInViewer(); } } public void createControl(Composite parent) { initializeDialogUnits(parent); Composite mainArea = new Composite(parent, SWT.NULL); mainArea.setFont(parent.getFont()); mainArea.setLayout(initGridLayout(new GridLayout(1, false), true)); GridDataFactory.fillDefaults().grab(true, true).applyTo(mainArea); new ProjectNameLocationArea(model, this, getShell()).createArea(mainArea); (springArea = new SpringVersionArea()).createArea(mainArea); (part = new TemplateSelectionPart(getWizard(), model, this)).createArea(mainArea); // No need to create an area that handles error events for the working // set, as the working set controls do not set error messages, // nor do they accept error handlers. String[] workingSetIds = new String[] { IWorkingSetIDs.JAVA, IWorkingSetIDs.RESOURCE }; IStructuredSelection selection = ((NewSpringProjectWizard) getWizard()).getSelection(); createWorkingSetGroup(mainArea, selection, workingSetIds); setControl(mainArea); refreshUI(); } public WorkingSetGroup createWorkingSetGroup(Composite composite, IStructuredSelection selection, String[] supportedWorkingSetTypes) { workingSetGroup = new WorkingSetGroup(composite, selection, supportedWorkingSetTypes); return workingSetGroup; } public IWorkingSet[] getSelectedWorkingSets() { return workingSetGroup != null ? workingSetGroup.getSelectedWorkingSets() : new IWorkingSet[0]; } @Override public boolean canFlipToNextPage() { // Override the default behaviour so that instead of asking the wizard // to get the next page, which may // involve downloading a template content, ask the wizard if there are // further pages // which may rely on template metadata rather than actual // downloaded template content. return isPageComplete() && ((NewSpringProjectWizard) getWizard()).hasPages(this); } protected Combo createLabeledCombo(Composite parent, String labelValue, String labelTooltip) { Label label = new Label(parent, SWT.NONE); GridDataFactory.fillDefaults().grab(false, false).align(SWT.FILL, SWT.CENTER).applyTo(label); label.setText(labelValue); if (labelTooltip != null) { label.setToolTipText(labelTooltip); } final Combo combo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); GridDataFactory.fillDefaults().grab(false, false).applyTo(combo); combo.setEnabled(true); return combo; } protected GridLayout initGridLayout(GridLayout layout, boolean margins) { layout.horizontalSpacing = 0; layout.verticalSpacing = 0; if (margins) { layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); } else { layout.marginWidth = 0; layout.marginHeight = 0; } return layout; } protected void update() { // This will trigger validation of all wizard pages getWizard().getContainer().updateButtons(); } protected void refreshUI() { if (springArea != null) { springArea.refreshUI(); } } protected void displayStatus(WizardPageArea area) { IStatus status = area.getValidationStatus(); if (status == null || status.getSeverity() == IStatus.OK) { setErrorMessage(null); setMessage(null); return; } // Some error messages can be very long which may result in the wizard // expanding. Instead, do the following: // 1. Show full error in a separate dialogue if it is too long // 2. Show shortened error in Wizard // 3. Log the error in Eclipse so that it can be accessed by the user // for bug reports if (status.getSeverity() == IStatus.ERROR) { setMessage(null); String errorMessage = status.getMessage(); if (errorMessage == null) { errorMessage = "Unknown error occurred in template project wizard. Unable to determine the nature of the error."; } // If the error message is short enough, show it in the wizard // dialogue. // Otherwise, open another dialogue to show the full message. if (ErrorUtils.isWithinWizardErrorMaximum(errorMessage)) { setErrorMessage(errorMessage); } else { // No need to pass the error message, as the dialog retrieves // the // message from the status ErrorDialog.openError(getShell(), NewSpringProjectWizardMessages.NewProject_errorMessage, null, status); } } else { setErrorMessage(null); setMessage(status.getMessage(), status.getSeverity()); } } public void addPageArea(WizardPageArea area) { if (area == null || wizardAreas.contains(area)) { return; } wizardAreas.add(area); } protected WizardPageArea getAreaBySeverity(int severity) { // Get an updated status for each area for (WizardPageArea area : wizardAreas) { IStatus areaStatus = area.getValidationStatus(true); if (areaStatus != null && areaStatus.getSeverity() == severity) { return area; } } return null; } public void notifyStatusChange(WizardPageArea currentArea) { // See if there are any other errors, and display them WizardPageArea nonOKArea = getAreaBySeverity(IStatus.ERROR); if (nonOKArea == null) { nonOKArea = getAreaBySeverity(IStatus.WARNING); if (nonOKArea == null) { nonOKArea = getAreaBySeverity(IStatus.INFO); } } if (nonOKArea != null) { displayStatus(nonOKArea); setPageComplete(nonOKArea.isAreaComplete()); } else { // Otherwise Handle the OK status of the current Area. boolean isPageComplete = currentArea.isAreaComplete(); setErrorMessage(null); IStatus status = currentArea.getValidationStatus(); if (status == null) { setMessage(null); } else { // If the message is "OK", set message to null, so that // the "OK" // message doesn't get displayed in the wizard. if (status.getMessage().equals(Status.OK_STATUS.getMessage())) { setMessage(null); } else { setMessage(status.getMessage()); } } setPageComplete(isPageComplete); } refreshUI(); } @Override public void dispose() { super.dispose(); if (part != null) { part.dispose(); } } protected class SpringVersionArea extends WizardPageArea { private Combo springVersionCombo; public SpringVersionArea() { super(NewSpringProjectWizardMainPage.this); // For now, any Spring version selection won't block the wizard // completion setPageComplete(true); } @Override public Control createArea(Composite parent) { Composite container = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 2; container.setLayout(layout); springVersionCombo = createLabeledCombo( container, "Select Spring version:", "Select a Spring version when building the project. Use 'Default' when using the template-defined Spring version. Spring version selection may not be available on all templates."); List<SpringVersion> versions = SpringVersion.getVersions(); int length = versions.size(); String[] versionValues = new String[length]; int i = 0; for (SpringVersion version : versions) { if (i < length) { versionValues[i++] = version.getDisplay(); } } springVersionCombo.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { // should always parse correctly int selectionIndex = springVersionCombo.getSelectionIndex(); if (selectionIndex != -1) { List<SpringVersion> versions = SpringVersion.getVersions(); if (selectionIndex < versions.size()) { SpringVersion selectedVersion = versions.get(selectionIndex); if (SpringVersion.DEFAULT.equals(selectedVersion)) { version = null; } else { version = selectedVersion; } } } } }); springVersionCombo.setItems(versionValues); springVersionCombo.select(0); GridDataFactory.fillDefaults().grab(true, false).applyTo(container); return container; } @Override public void refreshUI() { if (springVersionCombo == null || springVersionCombo.isDisposed()) { return; } String descriptorVersion = null; Template template = ((NewSpringProjectWizard) getWizard()).getModel().selectedTemplate.getValue(); if (template != null) { Descriptor descriptor = template.getItem().getLocalDescriptor(); if (descriptor == null) { descriptor = template.getItem().getRemoteDescriptor(); } if (descriptor != null) { descriptorVersion = descriptor.getSpringVersion(); } } // Whether the spring version is in the combo list or not, the fact // that // there is a spring version in the descriptor should be enough // criteria // to enable // the widget to allow users to select other versions. Otherwise // disable the widget. if (descriptorVersion != null) { springVersionCombo.setEnabled(true); } else { springVersionCombo.select(0); springVersionCombo.setEnabled(false); } } @Override protected IStatus validateArea() { return Status.OK_STATUS; } } }