plugins/org.symbian.tools.tmw.ui/src/org/symbian/tools/tmw/internal/ui/importwizard/ApplicationImportWizardPage.java
/*******************************************************************************
* Copyright (c) 2010 Symbian Foundation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Symbian Foundation - initial contribution.
* Contributors:
* Description:
* Overview:
* Details:
* Platforms/Drives/Compatibility:
* Assumptions/Requirement/Pre-requisites:
* Failures and causes:
*******************************************************************************/
package org.symbian.tools.tmw.internal.ui.importwizard;
import java.io.File;
import java.net.URI;
import java.text.MessageFormat;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea;
import org.eclipse.ui.internal.ide.dialogs.ProjectContentsLocationArea.IErrorMessageReporter;
import org.symbian.tools.tmw.core.runtimes.IMobileWebRuntime;
import org.symbian.tools.tmw.ui.TMWCoreUI;
import org.symbian.tools.tmw.ui.project.IApplicationImporter;
@SuppressWarnings("restriction")
public class ApplicationImportWizardPage extends WizardPage {
private static final class MapContentProvider implements IStructuredContentProvider {
public void dispose() {
// Do nothing
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// Do nothing
}
@SuppressWarnings("unchecked")
public Object[] getElements(Object inputElement) {
return ((Map<String, IApplicationImporter>) inputElement).entrySet().toArray();
}
}
// constants
private static final int SIZING_TEXT_FIELD_WIDTH = 250;
private final IFile file;
// initial value stores
private String initialProjectFieldValue;
private ProjectContentsLocationArea locationArea;
private final Listener nameModifyListener = new Listener() {
public void handleEvent(Event e) {
setLocationForSelection();
boolean valid = validatePage();
setPageComplete(valid);
}
};
// widgets
private Text projectNameField;
private Text fileName;
private ComboViewer runtimes;
protected ApplicationImportWizardPage(IFile file) {
super("ImportApplication");
this.file = file;
setTitle("Import Mobile Web Application");
setDescription("Create mobile web application project from application package file");
setPageComplete(false);
}
protected void browse() {
FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
String path = fileName.getText();
path = path.trim().length() > 0 ? path.trim() : TMWCoreUI.getDefault().getPreferenceStore()
.getString(ApplicationImportWizard.RECENT_IMPORT_PATH);
fileDialog.setFilterPath(path);
final Map<String, String> filters = new TreeMap<String, String>();
filters.put("*", "All files (*.*)");
final IApplicationImporter[] importers = TMWCoreUI.getApplicationImporters();
for (IApplicationImporter importer : importers) {
filters.putAll(importer.getFileFilters());
}
final String[] extensions = filters.keySet().toArray(new String[filters.size()]);
final String[] names = filters.values().toArray(new String[filters.size()]);
fileDialog.setFilterExtensions(extensions);
fileDialog.setFilterNames(names);
String res = fileDialog.open();
if (res != null) {
updateWgzName(path.trim(), res);
fileName.setText(res);
setPageComplete(validatePage());
}
}
public void createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NULL);
initializeDialogUnits(parent);
composite.setLayout(new GridLayout());
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
createProjectNameGroup(composite);
locationArea = new ProjectContentsLocationArea(getErrorReporter(), composite);
if (initialProjectFieldValue != null) {
locationArea.updateProjectName(initialProjectFieldValue);
}
// Scale the button based on the rest of the dialog
setButtonLayoutData(locationArea.getBrowseButton());
if (file != null) {
fileName.setText(file.getLocation().toOSString());
}
setPageComplete(validatePage());
// Show description on opening
setErrorMessage(null);
setMessage(null);
setControl(composite);
Dialog.applyDialogFont(composite);
setControl(composite);
}
/**
* Creates the project name specification controls.
*
* @param parent
* the parent composite
*/
private void createProjectNameGroup(Composite parent) {
// project specification group
Composite projectGroup = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 2;
projectGroup.setLayout(layout);
projectGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
Label label = new Label(projectGroup, SWT.NONE);
label.setText("WGZ archive:");
Composite buttonText = new Composite(projectGroup, SWT.NONE);
buttonText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
buttonText.setLayout(gridLayout);
fileName = new Text(buttonText, SWT.BORDER);
fileName.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
fileName.addModifyListener(new ModifyListener() {
public void modifyText(ModifyEvent e) {
String val = fileName.getData() != null ? fileName.getData().toString() : "";
String name = fileName.getText().trim();
updateWgzName(val, name);
fileName.setData(name);
setPageComplete(validatePage());
}
});
Button browse = new Button(buttonText, SWT.NONE);
browse.setText("Browse...");
browse.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
browse();
}
});
new Label(projectGroup, SWT.NONE).setText("Targeted runtime:");
runtimes = new ComboViewer(projectGroup, SWT.BORDER | SWT.READ_ONLY);
runtimes.getCombo().setEnabled(false);
runtimes.setContentProvider(new MapContentProvider());
runtimes.setLabelProvider(new LabelProvider() {
@SuppressWarnings("unchecked")
@Override
public String getText(Object element) {
return ((Map.Entry<String, IApplicationImporter>) element).getKey().toString();
}
});
runtimes.getControl().setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
runtimes.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
setPageComplete(validatePage());
}
});
Label separator = new Label(projectGroup, SWT.NONE);
GridDataFactory.generate(separator, 2, 2);
// new project label
Label projectLabel = new Label(projectGroup, SWT.NONE);
projectLabel.setText(IDEWorkbenchMessages.WizardNewProjectCreationPage_nameLabel);
projectLabel.setFont(parent.getFont());
// new project name entry field
projectNameField = new Text(projectGroup, SWT.BORDER);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
data.widthHint = SIZING_TEXT_FIELD_WIDTH;
projectNameField.setLayoutData(data);
projectNameField.setFont(parent.getFont());
// Set the initial value first before listener
// to avoid handling an event during the creation.
if (initialProjectFieldValue != null) {
projectNameField.setText(initialProjectFieldValue);
}
projectNameField.addListener(SWT.Modify, nameModifyListener);
}
public String getArchiveFile() {
return fileName.getText().trim();
}
/**
* Get an error reporter for the receiver.
*
* @return IErrorMessageReporter
*/
private IErrorMessageReporter getErrorReporter() {
return new IErrorMessageReporter() {
public void reportError(String errorMessage, boolean infoOnly) {
if (infoOnly) {
setMessage(errorMessage, IStatus.INFO);
setErrorMessage(null);
} else {
setErrorMessage(errorMessage);
}
boolean valid = errorMessage == null;
if (valid) {
valid = validatePage();
}
setPageComplete(valid);
}
};
}
/**
* Returns the current project location path as entered by the user, or its
* anticipated initial value. Note that if the default has been returned the
* path in a project description used to create a project should not be set.
*
* @return the project location path or its anticipated initial value.
*/
public IPath getLocationPath() {
return new Path(locationArea.getProjectLocation());
}
/**
* /** Returns the current project location URI as entered by the user, or
* <code>null</code> if a valid project location has not been entered.
*
* @return the project location URI, or <code>null</code>
* @since 3.2
*/
public URI getLocationURI() {
return locationArea.getProjectLocationURI();
}
/**
* Creates a project resource handle for the current project name field
* value. The project handle is created relative to the workspace root.
* <p>
* This method does not create the project resource; this is the
* responsibility of <code>IProject::create</code> invoked by the new
* project resource wizard.
* </p>
*
* @return the new project resource handle
*/
public IProject getProjectHandle() {
return ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectName());
}
/**
* Returns the current project name as entered by the user, or its
* anticipated initial value.
*
* @return the project name, its anticipated initial value, or
* <code>null</code> if no project name is known
*/
public String getProjectName() {
if (projectNameField == null) {
return initialProjectFieldValue;
}
return getProjectNameFieldValue();
}
/**
* Returns the value of the project name field with leading and trailing
* spaces removed.
*
* @return the project name in the field
*/
private String getProjectNameFieldValue() {
if (projectNameField == null) {
return ""; //$NON-NLS-1$
}
return projectNameField.getText().trim();
}
/**
* Sets the initial project name that this page will use when created. The
* name is ignored if the createControl(Composite) method has already been
* called. Leading and trailing spaces in the name are ignored. Providing
* the name of an existing project will not necessarily cause the wizard to
* warn the user. Callers of this method should first check if the project
* name passed already exists in the workspace.
*
* @param name
* initial project name for this page
*
* @see IWorkspace#validateName(String, int)
*
*/
public void setInitialProjectName(String name) {
if (name == null) {
initialProjectFieldValue = null;
} else {
initialProjectFieldValue = name.trim();
if (locationArea != null) {
locationArea.updateProjectName(name.trim());
}
}
}
/**
* Set the location to the default location if we are set to useDefaults.
*/
void setLocationForSelection() {
locationArea.updateProjectName(getProjectNameFieldValue());
}
private void updateWgzName(String oldValue, String newValue) {
String project = projectNameField.getText().trim();
if (project.length() == 0 || project.equals(new Path(oldValue).removeFileExtension().lastSegment())) {
String projectName = new Path(newValue).removeFileExtension().lastSegment();
projectNameField.setText(projectName);
locationArea.updateProjectName(projectName);
}
}
/**
* Returns the useDefaults.
*
* @return boolean
*/
public boolean useDefaults() {
return locationArea.isDefault();
}
private boolean validating = false;
/**
* Returns whether this page's controls currently all contain valid values.
*
* @return <code>true</code> if all controls are valid, and
* <code>false</code> if at least one is invalid
*/
protected synchronized boolean validatePage() {
if (validating) {
return true;
}
validating = true;
try {
final IWorkspace workspace = IDEWorkbenchPlugin.getPluginWorkspace();
final String archive = fileName.getText().trim();
if (archive.equals("")) {
setErrorMessage(null);
setMessage("Archive name must be specified");
return false;
}
final File f = new File(archive);
if (!isValidArchive(f)) {
setErrorMessage(MessageFormat.format("{0} is not a valid application archive", archive));
return false;
}
final String projectFieldContents = getProjectNameFieldValue();
if (projectFieldContents.equals("")) { //$NON-NLS-1$
setErrorMessage(null);
setMessage(IDEWorkbenchMessages.WizardNewProjectCreationPage_projectNameEmpty);
return false;
}
final IStatus nameStatus = workspace.validateName(projectFieldContents, IResource.PROJECT);
if (!nameStatus.isOK()) {
setErrorMessage(nameStatus.getMessage());
return false;
}
final IProject handle = getProjectHandle();
if (handle.exists()) {
setErrorMessage(IDEWorkbenchMessages.WizardNewProjectCreationPage_projectExistsMessage);
return false;
}
final IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(getProjectNameFieldValue());
locationArea.setExistingProject(project);
final String validLocationMessage = locationArea.checkValidLocation();
if (validLocationMessage != null) { // there is no destination location given
setErrorMessage(validLocationMessage);
return false;
}
if (runtimes.getSelection().isEmpty()) {
setErrorMessage("Select target runtime");
return false;
}
setErrorMessage(null);
setMessage(null);
return true;
} finally {
validating = false;
}
}
private boolean isValidArchive(File f) {
if (f.isFile()) {
final Map<String, IApplicationImporter> importers = new TreeMap<String, IApplicationImporter>();
final IApplicationImporter[] applicationImporters = TMWCoreUI.getApplicationImporters();
for (IApplicationImporter importer : applicationImporters) {
final IMobileWebRuntime runtime = importer.getApplicationRuntime(f);
if (runtime != null) {
importers.put(runtime.getName(), importer);
}
}
final ISelection selection = runtimes.getSelection();
Object sel = null;
if (!selection.isEmpty()) {
@SuppressWarnings("unchecked")
Map.Entry<String, IApplicationImporter> entry = (Entry<String, IApplicationImporter>) ((IStructuredSelection) selection)
.getFirstElement();
for (Entry<String, IApplicationImporter> ent : importers.entrySet()) {
if (ent.getKey().equals(entry.getKey())) {
sel = ent;
}
}
}
runtimes.setInput(importers);
if (sel != null) {
runtimes.setSelection(new StructuredSelection(sel));
} else if (importers.size() == 1) {
runtimes.setSelection(new StructuredSelection(importers.entrySet().iterator().next()));
}
runtimes.getControl().setEnabled(importers.size() > 1);
return !runtimes.getSelection().isEmpty();
}
return false;
}
public IApplicationImporter getImporter() {
if (runtimes == null || runtimes.getControl().isDisposed()) {
return null;
}
@SuppressWarnings("unchecked")
final Map.Entry<String, IApplicationImporter> element = (Entry<String, IApplicationImporter>) ((IStructuredSelection) runtimes
.getSelection()).getFirstElement();
return element.getValue();
}
}