Index: plugin.xml =================================================================== --- plugin.xml (revision 543) +++ plugin.xml (working copy) @@ -14,7 +14,7 @@ name="%wizard.newJ2MEProject.label" icon="icons/newjprj_wiz_m_sm.gif" category="mtj.category" - class="org.eclipse.mtj.ui.internal.wizards.project.NewMIDLetProjectWizard" + class="org.eclipse.mtj.ui.internal.wizards.projects.NewMidletProjectWizard" project="true" finalPerspective="org.eclipse.mtj.ui.MtjPerspective" id="org.eclipse.mtj.ui.wizards.NewJ2MEProjectWizard"> Index: META-INF/MANIFEST.MF =================================================================== --- META-INF/MANIFEST.MF (revision 543) +++ META-INF/MANIFEST.MF (working copy) @@ -43,3 +43,4 @@ org.eclipse.mtj.ui.editors.jad, org.eclipse.mtj.ui.viewers Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Import-Package: org.eclipse.core.filesystem Index: src/org/eclipse/mtj/ui/devices/DeviceSelector.java =================================================================== --- src/org/eclipse/mtj/ui/devices/DeviceSelector.java (revision 543) +++ src/org/eclipse/mtj/ui/devices/DeviceSelector.java (working copy) @@ -57,12 +57,10 @@ /** * The content providers for the device viewer. */ - private class DeviceContentProvider implements - IStructuredContentProvider { + private class DeviceContentProvider implements IStructuredContentProvider { /* * (non-Javadoc) - * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { @@ -70,8 +68,9 @@ /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + * @see + * org.eclipse.jface.viewers.IStructuredContentProvider#getElements( + * java.lang.Object) */ public Object[] getElements(Object inputElement) { Object[] elements = NO_ELEMENTS; @@ -96,9 +95,9 @@ /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, - * java.lang.Object, java.lang.Object) + * @see + * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse + * .jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @@ -107,11 +106,11 @@ /** * A label provider implementation for the Device Group */ - private class DeviceGroupNameLabelProvider extends LabelProvider { + private class DeviceGroupNameLabelProvider extends LabelProvider { /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + * @see + * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object element) { @@ -124,11 +123,10 @@ * * @author Craig Setera */ - private class DeviceGroupsContentProvider implements + private class DeviceGroupsContentProvider implements IStructuredContentProvider { /* * (non-Javadoc) - * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { @@ -136,8 +134,9 @@ /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + * @see + * org.eclipse.jface.viewers.IStructuredContentProvider#getElements( + * java.lang.Object) */ public Object[] getElements(Object inputElement) { Object[] elements = NO_ELEMENTS; @@ -156,9 +155,9 @@ /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, - * java.lang.Object, java.lang.Object) + * @see + * org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse + * .jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { } @@ -170,8 +169,8 @@ private class DeviceLabelProvider extends LabelProvider { /* * (non-Javadoc) - * - * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) + * @see + * org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object) */ @Override public String getText(Object element) { @@ -180,20 +179,32 @@ } } - private final Object[] NO_ELEMENTS = new Object[0]; + /** + * The Device Group Label + */ + private String deviceGroupComentLabel = null; + + /** + * The Device Group Label + */ + private String deviceGroupLabel = "SDK"; - // Listener for changes in the registry - private IDeviceRegistryListener registryListener; + private ComboViewer deviceNamesViewer; - private Button manageDevicesButton; - private ComboViewer groupViewer; private ComboViewer deviceViewer; - private ISelectionChangedListener selectionChangedListener; + private boolean fireSelectionChangedListener = true; - private ComboViewer viewer; + private ComboViewer groupViewer; - private ComboViewer deviceNamesViewer; + private Button manageDevicesButton; + + private final Object[] NO_ELEMENTS = new Object[0]; + + // Listener for changes in the registry + private IDeviceRegistryListener registryListener; + private ISelectionChangedListener selectionChangedListener; + private ComboViewer viewer; /** * Fill in the user interface components into the parent. Specify whether to @@ -206,9 +217,10 @@ public void createContents(Composite parent, boolean includeGroup, boolean includeManageButton) { Composite composite = null; + if (includeGroup) { Group group = new Group(parent, SWT.NONE); - group.setText("Device"); + group.setText(deviceGroupLabel); composite = group; } else { @@ -216,6 +228,11 @@ } setCompositeLayout(parent, composite); + if (deviceGroupComentLabel != null) { + (new Label(composite, SWT.NONE)).setText(deviceGroupComentLabel); + new Label(composite, SWT.NONE); + } + createSelectionControls(composite); if (includeManageButton) { createDeviceManagementControls(composite); @@ -235,6 +252,28 @@ } /** + * @param fireSelectionChangedListener the fireSelectionChangedListener to + * set + */ + public void enableFireSelectionChanged(boolean fireSelectionChangedListener) { + this.fireSelectionChangedListener = fireSelectionChangedListener; + } + + /** + * @return the deviceGroupComentLabel + */ + public String getDeviceGroupComentLabel() { + return deviceGroupComentLabel; + } + + /** + * @return the deviceGroupLabel + */ + public String getDeviceGroupLabel() { + return deviceGroupLabel; + } + + /** * Return the device selected by the user or null if the user * has not yet selected a device. * @@ -247,6 +286,27 @@ } /** + * @return the fireSelectionChangedListener + */ + public boolean isFireSelectionChangedEnabled() { + return fireSelectionChangedListener; + } + + /** + * @param deviceGroupComentLabel the deviceGroupComentLabel to set + */ + public void setDeviceGroupComentLabel(String deviceGroupComentLabel) { + this.deviceGroupComentLabel = deviceGroupComentLabel; + } + + /** + * @param deviceGroupLabel the deviceGroupLabel to set + */ + public void setDeviceGroupLabel(String deviceGroupLabel) { + this.deviceGroupLabel = deviceGroupLabel; + } + + /** * Set the controls to the specified state of enablement. * * @param enabled @@ -295,9 +355,9 @@ /* * (non-Javadoc) - * * @see org.eclipse.mtj.core.mod - * bel.device.IDeviceRegistryListener#deviceAdded(org.eclipse.mtj.core.model.device.IDevice) + * bel.device.IDeviceRegistryListener#deviceAdded + * (org.eclipse.mtj.core.model.device.IDevice) */ public void deviceAdded(IDevice device) { @@ -316,8 +376,8 @@ /* * (non-Javadoc) - * - * @see org.eclipse.mtj.core.model.device.IDeviceRegistryListener#deviceRemoved(org.eclipse.mtj.core.model.device.IDevice) + * @seeorg.eclipse.mtj.core.model.device.IDeviceRegistryListener# + * deviceRemoved(org.eclipse.mtj.core.model.device.IDevice) */ public void deviceRemoved(IDevice device) { IDevice current = getSelectedDevice(); @@ -568,19 +628,4 @@ StructuredSelection selection = new StructuredSelection(selectedObject); viewer.setSelection(selection, true); } - - /** - * @return the fireSelectionChangedListener - */ - public boolean isFireSelectionChangedEnabled() { - return fireSelectionChangedListener; - } - - /** - * @param fireSelectionChangedListener the fireSelectionChangedListener to - * set - */ - public void enableFireSelectionChanged(boolean fireSelectionChangedListener) { - this.fireSelectionChangedListener = fireSelectionChangedListener; - } } Index: src/org/eclipse/mtj/ui/internal/MTJUIPlugin.java =================================================================== --- src/org/eclipse/mtj/ui/internal/MTJUIPlugin.java (revision 543) +++ src/org/eclipse/mtj/ui/internal/MTJUIPlugin.java (working copy) @@ -21,7 +21,9 @@ import java.util.Map; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ProjectScope; +import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.ErrorDialog; @@ -41,6 +43,7 @@ import org.eclipse.swt.graphics.Resource; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.eclipse.ui.preferences.ScopedPreferenceStore; @@ -80,9 +83,9 @@ /* * (non-Javadoc) - * * @see java.lang.Object#equals(java.lang.Object) */ + @Override public boolean equals(Object obj) { boolean equals = false; @@ -97,9 +100,9 @@ /* * (non-Javadoc) - * * @see java.lang.Object#hashCode() */ + @Override public int hashCode() { return display.hashCode() ^ (red << 24) ^ (green << 16) ^ blue; } @@ -132,9 +135,9 @@ /* * (non-Javadoc) - * * @see java.lang.Object#equals(java.lang.Object) */ + @Override public boolean equals(Object obj) { boolean equals = false; @@ -150,9 +153,9 @@ /* * (non-Javadoc) - * * @see java.lang.Object#hashCode() */ + @Override public int hashCode() { return display.hashCode() ^ name.hashCode() ^ (height << 16) ^ style; @@ -166,15 +169,15 @@ * Display an error to the user given the specified information. * * @param shell the parent shell of the dialog, or null if none - * @param severity the severity; one of OK, - * ERROR, INFO, - * WARNING, or CANCEL + * @param severity the severity; one of OK, ERROR, + * INFO, WARNING, or + * CANCEL * @param code the plug-in-specific status code, or OK * @param title the title to use for this dialog, or null to - * indicate that the default title should be used + * indicate that the default title should be used * @param message the message to show in the error dialog * @param exception a low-level exception, or null if not - * applicable + * applicable */ public static void displayError(Shell shell, int severity, int code, String title, String message, Throwable exception) { @@ -187,6 +190,22 @@ ErrorDialog.openError(shell, title, message, status); } + public static IWorkbenchPage getActivePage() { + return getDefault().internalGetActivePage(); + } + + public static IWorkbenchWindow getActiveWorkbenchWindow() { + return getDefault().getWorkbench().getActiveWorkbenchWindow(); + } + + public static Shell getActiveWorkbenchShell() { + IWorkbenchWindow window = getActiveWorkbenchWindow(); + if (window != null) { + return window.getShell(); + } + return null; + } + /** * Return the active window's shell. * @@ -243,6 +262,10 @@ return plugin; } + public static IWorkspace getWorkspace() { + return ResourcesPlugin.getWorkspace(); + } + /** * Return the dialog settings section within the specified parent settings * object. This method will create the new section if necessary. @@ -385,6 +408,7 @@ * @param context the bundle context for this plug-in * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) */ + @Override public void start(BundleContext context) throws Exception { super.start(context); @@ -416,6 +440,7 @@ * @param context the bundle context for this plug-in * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) */ + @Override public void stop(BundleContext context) throws Exception { super.stop(context); } @@ -420,6 +445,14 @@ super.stop(context); } + private IWorkbenchPage internalGetActivePage() { + IWorkbenchWindow window = getWorkbench().getActiveWorkbenchWindow(); + if (window == null) { + return null; + } + return window.getActivePage(); + } + /** * Start up the OTA server if the user requested it be started up * immediately. Index: src/org/eclipse/mtj/ui/internal/editors/jad/form/JADFormEditor.java =================================================================== --- src/org/eclipse/mtj/ui/internal/editors/jad/form/JADFormEditor.java (revision 543) +++ src/org/eclipse/mtj/ui/internal/editors/jad/form/JADFormEditor.java (working copy) @@ -87,7 +87,6 @@ * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor) */ @Override - @SuppressWarnings("unchecked") public void doSave(IProgressMonitor monitor) { monitor.beginTask("Saving Application descriptor", getPageCount() + 1); @@ -296,7 +295,15 @@ * @return */ private File getLocalFile() { - return jadFile.getLocation().toFile(); + + File localfile = null; + + try { + localfile = jadFile.getLocation().toFile(); + } catch (Exception e) { + MTJCorePlugin.log(IStatus.ERROR, e); + } + return localfile; } private JADEditorPageConfigElement[] readAllVendorSpecJADAttributes() { Index: src/org/eclipse/mtj/ui/internal/wizards/NewElementWizard.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/NewElementWizard.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/NewElementWizard.java (revision 0) @@ -0,0 +1,158 @@ +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.wizards; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.mtj.core.internal.MTJCorePlugin; +import org.eclipse.mtj.ui.internal.MTJUIPlugin; +import org.eclipse.mtj.ui.internal.actions.WorkbenchRunnableAdapter; +import org.eclipse.mtj.ui.internal.utils.ExceptionHandler; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.INewWizard; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.ide.IDE; +import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; + +public abstract class NewElementWizard extends Wizard implements INewWizard { + + private IWorkbench workbench; + private IStructuredSelection selection; + + public NewElementWizard() { + setNeedsProgressMonitor(true); + } + + protected void openResource(final IFile resource) { + final IWorkbenchPage activePage = MTJUIPlugin.getActivePage(); + if (activePage != null) { + final Display display = getShell().getDisplay(); + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + try { + IDE.openEditor(activePage, resource, true); + } catch (PartInitException e) { + MTJCorePlugin.log(Status.ERROR, e); + } + } + }); + } + } + } + + /** + * Subclasses should override to perform the actions of the wizard. This + * method is run in the wizard container's context as a workspace runnable. + * + * @param monitor + * @throws InterruptedException + * @throws CoreException + */ + protected abstract void finishPage(IProgressMonitor monitor) + throws InterruptedException, CoreException; + + /** + * Returns the scheduling rule for creating the element. + * + * @return returns the scheduling rule + */ + protected ISchedulingRule getSchedulingRule() { + return ResourcesPlugin.getWorkspace().getRoot(); // look all by default + } + + protected boolean canRunForked() { + return true; + } + + public abstract IJavaElement getCreatedElement(); + + protected void handleFinishException(Shell shell, + InvocationTargetException e) { + String title = "New"; + String message = "Creation of element failed."; + ExceptionHandler.handle(e, shell, title, message); + } + + /* (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#performFinish() + */ + public boolean performFinish() { + IWorkspaceRunnable op = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException, + OperationCanceledException { + try { + finishPage(monitor); + } catch (InterruptedException e) { + throw new OperationCanceledException(e.getMessage()); + } + } + }; + try { + ISchedulingRule rule = null; + Job job = Job.getJobManager().currentJob(); + if (job != null) + rule = job.getRule(); + IRunnableWithProgress runnable = null; + if (rule != null) + runnable = new WorkbenchRunnableAdapter(op, rule, true); + else + runnable = new WorkbenchRunnableAdapter(op, getSchedulingRule()); + getContainer().run(canRunForked(), true, runnable); + } catch (InvocationTargetException e) { + handleFinishException(getShell(), e); + return false; + } catch (InterruptedException e) { + return false; + } + return true; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.IWorkbenchWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + public void init(IWorkbench workbench, IStructuredSelection currentSelection) { + this.workbench = workbench; + selection = currentSelection; + } + + public IStructuredSelection getSelection() { + return selection; + } + + public IWorkbench getWorkbench() { + return workbench; + } + + protected void selectAndReveal(IResource newResource) { + BasicNewResourceWizard.selectAndReveal(newResource, workbench + .getActiveWorkbenchWindow()); + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/projects/Messages.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/projects/Messages.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/projects/Messages.java (revision 0) @@ -0,0 +1,107 @@ +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.wizards.projects; + +import org.eclipse.osgi.util.NLS; + +/** + * Provides convenience methods for manipulating messages. + * + * @author Diego Madruga Sandin + */ +public class Messages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.mtj.ui.internal.wizards.projects.messages"; //$NON-NLS-1$ + + public static String NewMidletProjectWizard_wizard_title; + public static String NewMidletProjectWizard_image_descriptor; + + public static String NewMidletProjectWizard_error_create_project_window_message; + public static String NewMidletProjectWizard_error_create_project_window_title; + public static String NewMidletProjectWizard_error_open_jad_file; + + public static String NewMidletProjectWizardPageOne_description; + + public static String NewMidletProjectWizardPageOne_deviceGroup; + + public static String NewMidletProjectWizardPageOne_deviceGroup_coment; + + public static String NewMidletProjectWizardPageOne_validate_devicecount_error; + public static String NewMidletProjectWizardPageOne_validate_jadname_error_emptyname; + public static String NewMidletProjectWizardPageOne_validate_jadname_error_extension; + + public static String NewMidletProjectWizardPageOne_preprocessor; + + public static String NewMidletProjectWizardPageOne_preprocessorGroup; + + public static String NewMidletProjectWizardPageOne_projectNameGroup; + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_alreadyExists; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_emptyName; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_failedCreateContents; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_invalidDirectory; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_missingLocation; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace1; + + public static String NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace2; + + public static String NewMidletProjectWizardPageOne_jad_groupname; + public static String NewMidletProjectWizardPageOne_jad_label; + + public static String NewMidletProjectWizardPageOne_jadFileNameField; + + public static String NewMidletProjectWizardPageOne_jadNameGroup_projectBasedRadio; + + public static String NewMidletProjectWizardPageOne_jadNameGroup_userDefinedRadio; + + public static String NewMidletProjectWizardPageOne_locationGroup_browse_button; + + public static String NewMidletProjectWizardPageOne_locationGroup_changeControlPressed_dialogMessage; + + public static String NewMidletProjectWizardPageOne_locationGroup_contents; + + public static String NewMidletProjectWizardPageOne_locationGroup_externalLocationRadio; + + public static String NewMidletProjectWizardPageOne_locationGroup_projectLocation; + + public static String NewMidletProjectWizardPageOne_locationGroup_workspaceLocationRadio; + + public static String NewMidletProjectWizardPageOne_title; + + public static String NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_message; + public static String NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_title; + public static String NewMidletProjectWizardPageTwo_createBackup_error_1; + public static String NewMidletProjectWizardPageTwo_createBackup_error_2; + public static String NewMidletProjectWizardPageTwo_doRemoveProject_taskname; + public static String NewMidletProjectWizardPageTwo_performFinish_monitor_taskname; + public static String NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_message; + public static String NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_title; + public static String NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotclasspath; + public static String NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotproject; + public static String NewMidletProjectWizardPageTwo_updateProject_errordialog_message; + public static String NewMidletProjectWizardPageTwo_updateProject_errordialog_title; + public static String NewMidletProjectWizardPageTwo_updateProject_fail_read_metadata; + public static String NewMidletProjectWizardPageTwo_updateProject_monitor_buildpath_name; + public static String NewMidletProjectWizardPageTwo_updateProject_taskname; + + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} Index: src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizard.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizard.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizard.java (revision 0) @@ -0,0 +1,213 @@ +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.wizards.projects; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IConfigurationElement; +import org.eclipse.core.runtime.IExecutableExtension; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.mtj.core.internal.MTJCorePlugin; +import org.eclipse.mtj.core.model.project.IMidletSuiteProject; +import org.eclipse.mtj.core.model.project.MidletSuiteFactory; +import org.eclipse.mtj.ui.internal.MTJUIPlugin; +import org.eclipse.mtj.ui.internal.utils.ExceptionHandler; +import org.eclipse.mtj.ui.internal.wizards.NewElementWizard; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IWorkbench; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.wizards.newresource.BasicNewProjectResourceWizard; +import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard; + +/** + * Wizard for creation of a new Java ME MIDlet Project. + * + * @author Diego Madruga Sandin + * @since 0.9 + */ +public class NewMidletProjectWizard extends NewElementWizard implements + IExecutableExtension { + + private IConfigurationElement configElement; + + private NewMidletProjectWizardPageOne firstPage; + private NewMidletProjectWizardPageTwo secondPage; + + private IWorkbench workbench; + + /** + * Construct a new MIDLet project wizard. + */ + public NewMidletProjectWizard() { + this(null, null); + } + + /** + * Construct a new MIDLet project wizard. + * + * @param pageOne the first wizard page + * @param pageTwo the second wizard page + */ + public NewMidletProjectWizard(NewMidletProjectWizardPageOne pageOne, + NewMidletProjectWizardPageTwo pageTwo) { + + ImageDescriptor descriptor = MTJUIPlugin + .getIconImageDescriptor(Messages.NewMidletProjectWizard_image_descriptor); + setDefaultPageImageDescriptor(descriptor); + setWindowTitle(Messages.NewMidletProjectWizard_wizard_title); + + firstPage = pageOne; + secondPage = pageTwo; + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.Wizard#addPages() + */ + @Override + public void addPages() { + if (firstPage == null) { + firstPage = new NewMidletProjectWizardPageOne(); + } + addPage(firstPage); + + if (secondPage == null) { + secondPage = new NewMidletProjectWizardPageTwo(firstPage); + } + addPage(secondPage); + + firstPage.init(getSelection(), getActivePart()); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets + * .Composite) + */ + public void createControl(Composite parent) { + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.NewElementWizard#getCreatedElement() + */ + @Override + public IJavaElement getCreatedElement() { + return secondPage.getJavaProject(); + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.NewElementWizard#init(org.eclipse.ui.IWorkbench, org.eclipse.jface.viewers.IStructuredSelection) + */ + @Override + public void init(IWorkbench workbench, IStructuredSelection currentSelection) { + super.init(workbench, currentSelection); + this.workbench = workbench; + } + + /* + * (non-Javadoc) + * @see IWizard#performCancel() + */ + @Override + public boolean performCancel() { + secondPage.performCancel(); + return super.performCancel(); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.wizard.IWizard#performFinish() + */ + @Override + public boolean performFinish() { + boolean res = super.performFinish(); + if (res) { + + BasicNewProjectResourceWizard.updatePerspective(configElement); + + /* Open the Application Descriptor file */ + try { + IMidletSuiteProject midletSuiteProject = MidletSuiteFactory + .getMidletSuiteProject(secondPage.getJavaProject()); + + IFile jadfile = midletSuiteProject + .getApplicationDescriptorFile(); + + if (jadfile != null) { + BasicNewResourceWizard.selectAndReveal(jadfile, workbench + .getActiveWorkbenchWindow()); + openResource(jadfile); + } + + } catch (Throwable e) { + MTJCorePlugin.log(IStatus.ERROR, + Messages.NewMidletProjectWizard_error_open_jad_file, e + .getCause()); + } + } + return res; + } + + /* + * Stores the configuration element for the wizard. The config element will + * be used in performFinish to set the result perspective. + */ + public void setInitializationData(IConfigurationElement cfig, + String propertyName, Object data) { + configElement = cfig; + } + + private IWorkbenchPart getActivePart() { + IWorkbenchWindow activeWindow = getWorkbench() + .getActiveWorkbenchWindow(); + if (activeWindow != null) { + IWorkbenchPage activePage = activeWindow.getActivePage(); + if (activePage != null) { + return activePage.getActivePart(); + } + } + return null; + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.NewElementWizard#finishPage(org.eclipse + * .core.runtime.IProgressMonitor) + */ + @Override + protected void finishPage(IProgressMonitor monitor) + throws InterruptedException, CoreException { + secondPage.performFinish(monitor); // use the full progress monitor + } + + @Override + protected void handleFinishException(Shell shell, + InvocationTargetException e) { + String title = Messages.NewMidletProjectWizard_error_create_project_window_title; + String message = Messages.NewMidletProjectWizard_error_create_project_window_message; + ExceptionHandler.handle(e, getShell(), title, message); + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageOne.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageOne.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageOne.java (revision 0) @@ -0,0 +1,1074 @@ +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.wizards.projects; + +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.Observable; +import java.util.Observer; + +import org.eclipse.core.filesystem.URIUtil; +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.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.launching.JavaRuntime; +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.viewers.ISelectionChangedListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.SelectionChangedEvent; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.mtj.core.internal.JavaMEClasspathContainer; +import org.eclipse.mtj.core.internal.MTJCorePlugin; +import org.eclipse.mtj.core.model.device.DeviceRegistry; +import org.eclipse.mtj.core.model.device.IDevice; +import org.eclipse.mtj.core.persistence.PersistenceException; +import org.eclipse.mtj.ui.IMTJUIConstants; +import org.eclipse.mtj.ui.devices.DeviceSelector; +import org.eclipse.mtj.ui.internal.MTJUIPlugin; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.DialogField; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.IDialogFieldListener; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.IStringButtonAdapter; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.LayoutUtil; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.SelectionButtonDialogField; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.StringButtonDialogField; +import org.eclipse.mtj.ui.internal.wizards.dialogfields.StringDialogField; +import org.eclipse.swt.SWT; +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.Control; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.IWorkbenchPart; + +/** + * Main page for the wizard that creates the new MIDlet project. + * + * @author Diego Madruga Sandin + * @since 0.9 + */ +public class NewMidletProjectWizardPageOne extends WizardPage { + + private final class DeviceGroup extends Observable { + + private DeviceSelector deviceSelector; + + /** + * @param composite + * @return + */ + public Control createControl(Composite parent) { + + Composite deviceComposite = new Composite(parent, SWT.NONE); + deviceComposite.setFont(parent.getFont()); + deviceComposite.setLayout(initGridLayout(new GridLayout(1, false), + false)); + + deviceSelector = new DeviceSelector(); + deviceSelector + .setDeviceGroupLabel(Messages.NewMidletProjectWizardPageOne_deviceGroup); + deviceSelector + .setDeviceGroupComentLabel(Messages.NewMidletProjectWizardPageOne_deviceGroup_coment); + deviceSelector.createContents(deviceComposite, true, true); + deviceSelector + .setSelectionChangedListener(new ISelectionChangedListener() { + public void selectionChanged(SelectionChangedEvent event) { + fireEvent(); + } + }); + + selectedDevice = getSelectedDevice(); + return deviceComposite; + } + + /** + * Return the number of devices available. + * + * @return the number of devices available. + */ + public int getDeviceCount() { + int count = 0; + + /* Check the number of devices already registered */ + DeviceRegistry registry = DeviceRegistry.singleton; + + try { + count = registry.getDeviceCount(); + } catch (PersistenceException e) { + MTJCorePlugin.log(IStatus.WARNING, + "Error retrieving device count", //$NON-NLS-1$ + e); + } + return count; + } + + /** + * Return the device selected by the user. + * + * @return + */ + public IDevice getSelectedDevice() { + return deviceSelector.getSelectedDevice(); + } + + protected void fireEvent() { + selectedDevice = getSelectedDevice(); + setChanged(); + notifyObservers(); + } + + } + + private final class JadNameGroup extends Observable implements Observer, + IDialogFieldListener { + + private String previousJadName; + protected final StringDialogField jadFileNameField; + protected final SelectionButtonDialogField projectBasedRadio; + protected final SelectionButtonDialogField userDefinedRadio; + + /** + * + */ + public JadNameGroup() { + + projectBasedRadio = new SelectionButtonDialogField(SWT.RADIO); + projectBasedRadio.setDialogFieldListener(this); + projectBasedRadio + .setLabelText(Messages.NewMidletProjectWizardPageOne_jadNameGroup_projectBasedRadio); + + userDefinedRadio = new SelectionButtonDialogField(SWT.RADIO); + userDefinedRadio + .setLabelText(Messages.NewMidletProjectWizardPageOne_jadNameGroup_userDefinedRadio); + + // text field for project name + jadFileNameField = new StringDialogField(); + jadFileNameField + .setLabelText(Messages.NewMidletProjectWizardPageOne_jadFileNameField); + jadFileNameField.setDialogFieldListener(this); + + userDefinedRadio.attachDialogField(jadFileNameField); + + projectBasedRadio.setSelection(true); + userDefinedRadio.setSelection(false); + + } + + /** + * @param composite + * @return + */ + public Control createControl(Composite parent) { + + final int numColumns = 2; + + final Group group = new Group(parent, SWT.NONE); + group.setLayout(initGridLayout(new GridLayout(numColumns, false), + true)); + group.setText(Messages.NewMidletProjectWizardPageOne_jad_groupname); + + (new Label(group, SWT.NULL)) + .setText(Messages.NewMidletProjectWizardPageOne_jad_label); + + projectBasedRadio.doFillIntoGrid(group, numColumns); + userDefinedRadio.doFillIntoGrid(group, numColumns); + jadFileNameField.doFillIntoGrid(group, 3); + + LayoutUtil.setHorizontalGrabbing(jadFileNameField + .getTextControl(null)); + + return group; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.IDialogFieldListener#dialogFieldChanged(org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField) + */ + public void dialogFieldChanged(DialogField field) { + + if (field == projectBasedRadio) { + final boolean checked = projectBasedRadio.isSelected(); + if (checked) { + previousJadName = jadFileNameField.getText(); + jadFileNameField.setText(projectNameGroup.getName() + + ".jad"); //$NON-NLS-1$ + } else { + jadFileNameField.setText(previousJadName); + } + } + + fireEvent(); + } + + /** + * Return the JAD file name specified by the user. + * + * @return + */ + public String getJadFileName() { + return jadFileNameField.getText(); + } + + /** + * @return + */ + public boolean isProjectBasedRadioSelected() { + return projectBasedRadio.isSelected(); + } + + public void postSetFocus() { + jadFileNameField.postSetFocusOnDialogField(getShell().getDisplay()); + } + + /** + * Return the JAD file name specified by the user. + * + * @return + */ + public void setJadFileName(String name) { + jadFileNameField.setText(name); + } + + /* (non-Javadoc) + * @see java.util.Observer#update(java.util.Observable, java.lang.Object) + */ + public void update(Observable o, Object arg) { + if (isProjectBasedRadioSelected()) { + setJadFileName(projectNameGroup.getName() + ".jad"); //$NON-NLS-1$ + } + fireEvent(); + } + + protected void fireEvent() { + setChanged(); + notifyObservers(); + } + + } + + /** + * Request a location. Fires an event whenever the checkbox or the location + * field is changed, regardless of whether the change originates from the + * user or has been invoked programmatically. + */ + private final class LocationGroup extends Observable implements Observer, + IStringButtonAdapter, IDialogFieldListener { + + private static final String DIALOGSTORE_LAST_EXTERNAL_LOC = IMTJUIConstants.PLUGIN_ID + + ".last.external.project"; //$NON-NLS-1$ + + private String fPreviousExternalLocation; + protected final SelectionButtonDialogField externalLocationRadio; + + protected final StringButtonDialogField projectLocation; + + protected final SelectionButtonDialogField workspaceLocationRadio; + + public LocationGroup() { + + workspaceLocationRadio = new SelectionButtonDialogField(SWT.RADIO); + workspaceLocationRadio.setDialogFieldListener(this); + workspaceLocationRadio + .setLabelText(Messages.NewMidletProjectWizardPageOne_locationGroup_workspaceLocationRadio); + + externalLocationRadio = new SelectionButtonDialogField(SWT.RADIO); + externalLocationRadio + .setLabelText(Messages.NewMidletProjectWizardPageOne_locationGroup_externalLocationRadio); + + projectLocation = new StringButtonDialogField(this); + projectLocation.setDialogFieldListener(this); + projectLocation + .setLabelText(Messages.NewMidletProjectWizardPageOne_locationGroup_projectLocation); + projectLocation + .setButtonLabel(Messages.NewMidletProjectWizardPageOne_locationGroup_browse_button); + + externalLocationRadio.attachDialogField(projectLocation); + + workspaceLocationRadio.setSelection(true); + externalLocationRadio.setSelection(false); + + fPreviousExternalLocation = ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.dialogfields.IStringButtonAdapter#changeControlPressed(org.eclipse.mtj.ui.internal.wizards.dialogfields.DialogField) + */ + public void changeControlPressed(DialogField field) { + + final DirectoryDialog dialog = new DirectoryDialog(getShell()); + + dialog + .setMessage(Messages.NewMidletProjectWizardPageOne_locationGroup_changeControlPressed_dialogMessage); + String directoryName = projectLocation.getText().trim(); + if (directoryName.length() == 0) { + String prevLocation = MTJUIPlugin.getDefault() + .getDialogSettings().get(DIALOGSTORE_LAST_EXTERNAL_LOC); + if (prevLocation != null) { + directoryName = prevLocation; + } + } + + if (directoryName.length() > 0) { + final File path = new File(directoryName); + if (path.exists()) { + dialog.setFilterPath(directoryName); + } + } + final String selectedDirectory = dialog.open(); + if (selectedDirectory != null) { + projectLocation.setText(selectedDirectory); + MTJUIPlugin.getDefault().getDialogSettings().put( + DIALOGSTORE_LAST_EXTERNAL_LOC, selectedDirectory); + } + } + + /** + * @param composite + * @return + */ + public Control createControl(Composite composite) { + final int numColumns = 3; + + final Group group = new Group(composite, SWT.NONE); + group.setLayout(initGridLayout(new GridLayout(numColumns, false), + true)); + group + .setText(Messages.NewMidletProjectWizardPageOne_locationGroup_contents); + + workspaceLocationRadio.doFillIntoGrid(group, numColumns); + externalLocationRadio.doFillIntoGrid(group, numColumns); + projectLocation.doFillIntoGrid(group, numColumns); + LayoutUtil.setHorizontalGrabbing(projectLocation + .getTextControl(null)); + + return group; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.IDialogFieldListener#dialogFieldChanged(org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField) + */ + public void dialogFieldChanged(DialogField field) { + + if (field == workspaceLocationRadio) { + final boolean checked = workspaceLocationRadio.isSelected(); + if (checked) { + fPreviousExternalLocation = projectLocation.getText(); + projectLocation.setText(getDefaultPath(projectNameGroup + .getName())); + } else { + projectLocation.setText(fPreviousExternalLocation); + } + } + fireEvent(); + } + + public IPath getLocation() { + + if (isWorkspaceRadioSelected()) { + return Platform.getLocation(); + } + return Path.fromOSString(projectLocation.getText().trim()); + } + + /** + * @return true if the location is in the workspace + */ + public boolean isLocationInWorkspace() { + + final String location = projectLocationGroup.getLocation() + .toOSString(); + IPath projectPath = Path.fromOSString(location); + return Platform.getLocation().isPrefixOf(projectPath); + } + + public boolean isWorkspaceRadioSelected() { + return workspaceLocationRadio.isSelected(); + } + + public void setLocation(IPath path) { + workspaceLocationRadio.setSelection(path == null); + if (path != null) { + projectLocation.setText(path.toOSString()); + } else { + projectLocation.setText(getDefaultPath(projectNameGroup + .getName())); + } + fireEvent(); + } + + /* + * (non-Javadoc) + * @see java.util.Observer#update(java.util.Observable, + * java.lang.Object) + */ + public void update(Observable o, Object arg) { + if (isWorkspaceRadioSelected()) { + projectLocation.setText(getDefaultPath(projectNameGroup + .getName())); + } + fireEvent(); + } + + protected void fireEvent() { + setChanged(); + notifyObservers(); + } + + protected String getDefaultPath(String name) { + final IPath path = Platform.getLocation().append(name); + return path.toOSString(); + } + } + + /** + * Request a project name. Fires an event whenever the text field is + * changed, regardless of its content. + */ + private final class ProjectNameGroup extends Observable implements + IDialogFieldListener { + + protected final StringDialogField projNameField; + + public ProjectNameGroup() { + projNameField = new StringDialogField(); + projNameField + .setLabelText(Messages.NewMidletProjectWizardPageOne_projectNameGroup); + projNameField.setDialogFieldListener(this); + + } + + public Control createControl(Composite composite) { + Composite nameComposite = new Composite(composite, SWT.NONE); + nameComposite.setFont(composite.getFont()); + nameComposite.setLayout(initGridLayout(new GridLayout(2, false), + false)); + + projNameField.doFillIntoGrid(nameComposite, 2); + LayoutUtil + .setHorizontalGrabbing(projNameField.getTextControl(null)); + + return nameComposite; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.dialogfields.IDialogFieldListener#dialogFieldChanged(org.eclipse.mtj.ui.internal.wizards.dialogfields.DialogField) + */ + public void dialogFieldChanged(DialogField field) { + fireEvent(); + } + + public String getName() { + return projNameField.getText().trim(); + } + + public void postSetFocus() { + projNameField.postSetFocusOnDialogField(getShell().getDisplay()); + } + + public void setName(String name) { + projNameField.setText(name); + } + + protected void fireEvent() { + setChanged(); + notifyObservers(); + } + } + + /** + * Validate this page and show appropriate warnings and error + * NewWizardMessages. + */ + private final class Validator implements Observer { + + public void update(Observable o, Object arg) { + + final IWorkspace workspace = MTJUIPlugin.getWorkspace(); + + final String name = projectNameGroup.getName(); + + // check whether the project name field is empty + if (name.length() == 0) { + setErrorMessage(null); + setMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_emptyName); + setPageComplete(false); + return; + } + + // check whether the project name is valid + final IStatus nameStatus = workspace.validateName(name, + IResource.PROJECT); + if (!nameStatus.isOK()) { + setErrorMessage(nameStatus.getMessage()); + setPageComplete(false); + return; + } + + // check whether project already exists + final IProject handle = workspace.getRoot().getProject(name); + if (handle.exists()) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_alreadyExists); + setPageComplete(false); + return; + } + + IPath projectLocation = ResourcesPlugin.getWorkspace().getRoot() + .getLocation().append(name); + if (projectLocation.toFile().exists()) { + try { + // correct casing + String canonicalPath = projectLocation.toFile() + .getCanonicalPath(); + projectLocation = new Path(canonicalPath); + } catch (IOException e) { + MTJCorePlugin.log(IStatus.ERROR, e); + } + + String existingName = projectLocation.lastSegment(); + if (!existingName.equals(projectNameGroup.getName())) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_alreadyExists); + setPageComplete(false); + return; + } + + } + + final String location = projectLocationGroup.getLocation() + .toOSString(); + + // check whether location is empty + if (location.length() == 0) { + setErrorMessage(null); + setMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_missingLocation); + setPageComplete(false); + return; + } + + // check whether the location is a syntactically correct path + if (!Path.EMPTY.isValidPath(location)) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_invalidDirectory); + setPageComplete(false); + return; + } + + IPath projectPath = Path.fromOSString(location); + + if (projectLocationGroup.isWorkspaceRadioSelected()) { + projectPath = projectPath.append(projectNameGroup.getName()); + } + + if (projectPath.toFile().exists()) {// create from existing source + if (Platform.getLocation().isPrefixOf(projectPath)) { // create + // from existing source in workspace + if (!Platform.getLocation().equals( + projectPath.removeLastSegments(1))) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace1); + setPageComplete(false); + return; + } + + if (!projectPath.toFile().exists()) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace2); + setPageComplete(false); + return; + } + } + } else if (!projectLocationGroup.isWorkspaceRadioSelected()) {// create + // at + // non existing external location + if (!canCreate(projectPath.toFile())) { + setErrorMessage(Messages.NewMidletProjectWizardPageOne_projectNameGroup_update_error_failedCreateContents); + setPageComplete(false); + return; + } + + // If we do not place the contents in the workspace validate the + // location. + final IStatus locationStatus = workspace + .validateProjectLocation(handle, projectPath); + if (!locationStatus.isOK()) { + setErrorMessage(locationStatus.getMessage()); + setPageComplete(false); + return; + } + } + + IStatus status; + + status = isValidJadName(jadNameGroup.getJadFileName()); + if (!status.isOK()) { + setErrorMessage(status.getMessage()); + setPageComplete(false); + return; + } + + /* Update the device count */ + int deviceCount = deviceGroup.getDeviceCount(); + status = isValidDeviceCount(deviceCount); + if (!status.isOK()) { + setErrorMessage(status.getMessage()); + setPageComplete(false); + return; + } + + status = isValidDeviceSelection(); + if (!status.isOK()) { + setErrorMessage(status.getMessage()); + setPageComplete(false); + return; + } + + setPageComplete(true); + setErrorMessage(null); + setMessage(null); + } + + private boolean canCreate(File file) { + while (!file.exists()) { + file = file.getParentFile(); + if (file == null) { + return false; + } + } + + return file.canWrite(); + } + + /** + * Check if at least one device was previously imported by user. + * + * @return a status object with code IStatus.OK if at least one device + * is available, otherwise a status object indicating that no + * device is was previously imported. + */ + private IStatus isValidDeviceCount(final int deviceCount) { + IStatus status = null; + + if (deviceCount <= 0) { + status = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageOne_validate_devicecount_error); + + } else { + status = new Status(IStatus.OK, IMTJUIConstants.PLUGIN_ID, ""); //$NON-NLS-1$ + } + + return status; + } + + /** + * Check if the user selected a device. + * + * @return a status object with code IStatus.OK if one device is + * selected , otherwise a status object indicating that no + * device is selected. + */ + private IStatus isValidDeviceSelection() { + IStatus status = null; + + if (deviceGroup.getSelectedDevice() == null) { + status = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageOne_validate_devicecount_error); + } else { + status = new Status(IStatus.OK, IMTJUIConstants.PLUGIN_ID, ""); //$NON-NLS-1$ + } + + return status; + } + + /** + * Validates the JAD file name. + * + * @return a status object with code IStatus.OK if the JAD file name is + * valid , otherwise a status object indicating what is wrong + * with the file name + * @see IWorkspace#validateName(String, int) + */ + private IStatus isValidJadName(final String jadName) { + + final String jadFileName = jadName; + + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + + IStatus result = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageOne_validate_jadname_error_emptyname); + + if ((jadFileName != null) && (jadFileName != "")) { //$NON-NLS-1$ + result = workspace.validateName(jadFileName, IResource.FILE); + + if (result.isOK()) { + /* File name must end with the .jad file extension */ + if (!jadFileName.endsWith(".jad")) { //$NON-NLS-1$ + result = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageOne_validate_jadname_error_extension); + /* File name must not be only the .jad file extension */ + } else if (jadFileName.equals(".jad")) { //$NON-NLS-1$ + result = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageOne_validate_jadname_error_emptyname); + } + } + } + return result; + } + } + + private static final String PAGE_NAME = "NewJavaProjectWizardPageOne"; //$NON-NLS-1$ + + private final DeviceGroup deviceGroup; + + private final JadNameGroup jadNameGroup; + + private Button preprocessedButton; + + private boolean preprocessingEnabled; + private final LocationGroup projectLocationGroup; + + private final ProjectNameGroup projectNameGroup; + private IDevice selectedDevice = null; + private final Validator wizardPageValidator; + + /** + * Creates a new NewMidletProjectWizardPageOne + */ + public NewMidletProjectWizardPageOne() { + super(PAGE_NAME); + setPageComplete(false); + setTitle(Messages.NewMidletProjectWizardPageOne_title); + setDescription(Messages.NewMidletProjectWizardPageOne_description); + + projectNameGroup = new ProjectNameGroup(); + jadNameGroup = new JadNameGroup(); + projectLocationGroup = new LocationGroup(); + deviceGroup = new DeviceGroup(); + + // establish connections + projectNameGroup.addObserver(projectLocationGroup); + projectNameGroup.addObserver(jadNameGroup); + + // initialize all elements + projectNameGroup.notifyObservers(); + + // create and connect validator + wizardPageValidator = new Validator(); + projectNameGroup.addObserver(wizardPageValidator); + deviceGroup.addObserver(wizardPageValidator); + projectLocationGroup.addObserver(wizardPageValidator); + jadNameGroup.addObserver(wizardPageValidator); + + // initialize defaults + setProjectName(""); //$NON-NLS-1$ + setProjectLocationURI(null); + + JavaRuntime.getDefaultVMInstall(); + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets + * .Composite) + */ + public void createControl(Composite parent) { + initializeDialogUnits(parent); + + final Composite composite = new Composite(parent, SWT.NULL); + composite.setFont(parent.getFont()); + composite.setLayout(initGridLayout(new GridLayout(1, false), true)); + composite.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL)); + + // create UI elements + Control nameControl = createNameControl(composite); + nameControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Control jadControl = createJadNameControl(composite); + jadControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Control locationControl = createLocationControl(composite); + locationControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Control deviceControl = createDeviceGroupSelectionControl(composite); + deviceControl.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + Control preprocessorControl = createPreprocessorGroupSelectionControl(composite); + preprocessorControl + .setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + + setControl(composite); + } + + /** + * Returns the default class path entries to be added on new projects. By + * default this is the JRE container as selected by the user. + * + * @return returns the default class path entries + */ + public IClasspathEntry[] getDefaultClasspathEntries() { + IPath entryPath = new Path(JavaMEClasspathContainer.JAVAME_CONTAINER + + "/" + getSelectedDevice()); //$NON-NLS-1$ + + return new IClasspathEntry[] { JavaCore.newContainerEntry(entryPath) }; + } + + /** + * @return + */ + public String getJadFileName() { + return jadNameGroup.getJadFileName(); + } + + /** + * Returns the source class path entries to be added on new projects. The + * underlying resource may not exist. + * + * @return returns the default class path entries + */ + public IPath getOutputLocation() { + IPath outputLocationPath = new Path(getProjectName()).makeAbsolute(); + + IPath binPath = new Path(PreferenceConstants.getPreferenceStore() + .getString(PreferenceConstants.SRCBIN_BINNAME)); + if (binPath.segmentCount() > 0) { + outputLocationPath = outputLocationPath.append(binPath); + } + + return outputLocationPath; + } + + /** + * Returns the current project location path as entered by the user, or + * null if the project should be created in the workspace. + * + * @return the project location path or its anticipated initial value. + */ + public URI getProjectLocationURI() { + if (projectLocationGroup.isLocationInWorkspace()) { + return null; + } + return URIUtil.toURI(projectLocationGroup.getLocation()); + } + + /** + * Gets a project name for the new project. + * + * @return the new project resource handle + */ + public String getProjectName() { + return projectNameGroup.getName(); + } + + /** + * Returns the compiler compliance to be used for the project, or + * null to use the workspace compiler compliance. + * + * @return compiler compliance to be used for the project or + * null + */ + public IDevice getSelectedDevice() { + return selectedDevice; + } + + /** + * Returns the source class path entries to be added on new projects. The + * underlying resources may not exist. All entries that are returned must be + * of kind {@link IClasspathEntry#CPE_SOURCE}. + * + * @return returns the source class path entries for the new project + */ + public IClasspathEntry[] getSourceClasspathEntries() { + IPath sourceFolderPath = new Path(getProjectName()).makeAbsolute(); + + IPath srcPath = new Path(PreferenceConstants.getPreferenceStore() + .getString(PreferenceConstants.SRCBIN_SRCNAME)); + if (srcPath.segmentCount() > 0) { + sourceFolderPath = sourceFolderPath.append(srcPath); + } + + return new IClasspathEntry[] { JavaCore + .newSourceEntry(sourceFolderPath) }; + } + + /** + * The wizard owning this page can call this method to initialize the fields + * from the current selection and active part. + * + * @param selection used to initialize the fields + * @param activePart the (typically active) part to initialize the fields or + * null + */ + public void init(IStructuredSelection selection, IWorkbenchPart activePart) { + + } + + /** + * Return a boolean concerning whether preprocessing is enabled for the + * newly created project. + * + * @return the preprocessingEnabled + */ + public boolean isPreprocessingEnabled() { + return preprocessingEnabled; + } + + /** + * Sets the project location of the new project or null if the + * project should be created in the workspace + * + * @param uri the new project location + */ + public void setProjectLocationURI(URI uri) { + IPath path = uri != null ? URIUtil.toPath(uri) : null; + projectLocationGroup.setLocation(path); + } + + /** + * Sets the name of the new project + * + * @param name the new name + */ + public void setProjectName(String name) { + if (name == null) { + throw new IllegalArgumentException(); + } + + projectNameGroup.setName(name); + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean) + */ + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + if (visible) { + projectNameGroup.postSetFocus(); + } + } + + private GridLayout initGridLayout(GridLayout layout, boolean margins) { + layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + if (margins) { + layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN); + layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN); + } else { + layout.marginWidth = 0; + layout.marginHeight = 0; + } + return layout; + } + + /** + * Creates the controls for the JRE selection + * + * @param composite the parent composite + * @return the created control + */ + protected Control createDeviceGroupSelectionControl(Composite composite) { + return deviceGroup.createControl(composite); + } + + /** + * @param composite + * @return + */ + protected Control createJadNameControl(Composite composite) { + return jadNameGroup.createControl(composite); + } + + /** + * Creates the controls for the location field. + * + * @param composite the parent composite + * @return the created control + */ + protected Control createLocationControl(Composite composite) { + return projectLocationGroup.createControl(composite); + } + + /** + * Creates the controls for the name field. + * + * @param composite the parent composite + * @return the created control + */ + protected Control createNameControl(Composite composite) { + return projectNameGroup.createControl(composite); + } + + /** + * @param composite + * @return + */ + protected Control createPreprocessorGroupSelectionControl( + Composite composite) { + + // Add an extra composite to get the layout to match up the + // components vertically + Group preprocessorGroup = new Group(composite, SWT.NONE); + preprocessorGroup.setLayout(new GridLayout(1, true)); + preprocessorGroup.setLayoutData(new GridData(GridData.FILL_BOTH)); + preprocessorGroup + .setText(Messages.NewMidletProjectWizardPageOne_preprocessorGroup); + + preprocessedButton = new Button(preprocessorGroup, SWT.CHECK); + preprocessedButton + .setText(Messages.NewMidletProjectWizardPageOne_preprocessor); + preprocessedButton + .setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + preprocessedButton.addSelectionListener(new SelectionAdapter() { + + /* + * (non-Javadoc) + * + * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) + */ + @Override + public void widgetSelected(SelectionEvent e) { + preprocessingEnabled = preprocessedButton.getSelection(); + } + }); + return preprocessorGroup; + } + + /* (non-Javadoc) + * @see org.eclipse.jface.dialogs.DialogPage#setControl(org.eclipse.swt.widgets.Control) + */ + @Override + protected void setControl(Control newControl) { + Dialog.applyDialogFont(newControl); + super.setControl(newControl); + } +} Index: src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageTwo.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageTwo.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/projects/NewMidletProjectWizardPageTwo.java (revision 0) @@ -0,0 +1,851 @@ +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.wizards.projects; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.InvocationTargetException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.filesystem.EFS; +import org.eclipse.core.filesystem.IFileInfo; +import org.eclipse.core.filesystem.IFileStore; +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.resources.IResourceStatus; +import org.eclipse.core.resources.IWorkspaceDescription; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Preferences; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.ui.PreferenceConstants; +import org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.mtj.core.IMTJCoreConstants; +import org.eclipse.mtj.core.internal.JavaMEClasspathContainer; +import org.eclipse.mtj.core.internal.MTJCorePlugin; +import org.eclipse.mtj.core.internal.preprocessor.PreprocessorBuilder; +import org.eclipse.mtj.core.model.device.IDevice; +import org.eclipse.mtj.core.model.project.MetaData; +import org.eclipse.mtj.core.model.project.MidletSuiteFactory; +import org.eclipse.mtj.ui.IMTJUIConstants; +import org.eclipse.mtj.ui.internal.utils.ExceptionHandler; +import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation; + +/** + * The New MIDlet Project Java Capability Wizard Page allows the user to + * configure the build path and output location of the MIDlet Project. As + * addition to the {@link JavaCapabilityConfigurationPage}, the wizard page does + * an early project creation (so that linked folders can be defined). + * + * @author Diego Madruga Sandin + * @since 0.9 + */ +public class NewMidletProjectWizardPageTwo extends + JavaCapabilityConfigurationPage { + + private static final String FILENAME_CLASSPATH = ".classpath"; //$NON-NLS-1$ + + private static final String FILENAME_PROJECT = ".project"; //$NON-NLS-1$ + + /** + * @param projectName + * @param location + * @return + */ + private static URI getRealLocation(String projectName, URI location) { + if (location == null) { // inside workspace + try { + URI rootLocation = ResourcesPlugin.getWorkspace().getRoot() + .getLocationURI(); + + location = new URI(rootLocation.getScheme(), null, Path + .fromPortableString(rootLocation.getPath()).append( + projectName).toString(), null); + } catch (URISyntaxException e) { + Assert.isTrue(false, "Can't happen"); //$NON-NLS-1$ + } + } + return location; + } + + public Boolean isAutobuild; + private IProject currProject; + private URI currProjectLocation; + private File fDotClasspathBackup; + private File fDotProjectBackup; + private NewMidletProjectWizardPageOne firstPage; + private HashSet fOrginalFolders; + + private boolean keepContent; + + /** + * Creates a new New MIDlet Project Java Capability Wizard Page. + * + * @param workbench + */ + public NewMidletProjectWizardPageTwo(NewMidletProjectWizardPageOne page) { + this.currProjectLocation = null; + this.currProject = null; + this.firstPage = page; + isAutobuild = null; + } + + /** + * Called from the wizard on cancel. + */ + public void performCancel() { + if (currProject != null) { + removeProvisonalProject(); + } + } + + /** + * Called from the wizard on finish. + * + * @param monitor the progress monitor + * @throws CoreException thrown when the project creation or configuration + * failed + * @throws InterruptedException thrown when the user canceled the project + * creation + */ + @SuppressWarnings("unchecked") + public void performFinish(IProgressMonitor monitor) throws CoreException, + InterruptedException { + try { + + monitor + .beginTask( + Messages.NewMidletProjectWizardPageTwo_performFinish_monitor_taskname, + 3); + if (currProject == null) { + updateProject(new SubProgressMonitor(monitor, 1)); + } + + configureJavaProject(new SubProgressMonitor(monitor, 2)); + + if (!keepContent) { + IJavaProject project = JavaCore.create(currProject); + Map options = project.getOptions(false); + + // complete compliance options + project.setOptions(options); + } + + } finally { + monitor.done(); + currProject = null; + if (isAutobuild != null) { + IWorkspaceDescription description = ResourcesPlugin + .getWorkspace().getDescription(); + description.setAutoBuilding(isAutobuild.booleanValue()); + ResourcesPlugin.getWorkspace().setDescription(description); + isAutobuild = null; + } + } + } + + /* + * (non-Javadoc) + * @see org.eclipse.jface.dialogs.IDialogPage#setVisible(boolean) + */ + @Override + public void setVisible(boolean visible) { + boolean isShownFirstTime = visible && (currProject == null); + if (visible) { + if (isShownFirstTime) { + // entering from the first page + createProvisonalProject(); + } + } else { + if (getContainer().getCurrentPage() == firstPage) { + // leaving back to the first page + removeProvisonalProject(); + } + } + super.setVisible(visible); + if (isShownFirstTime) { + setFocus(); + } + } + + /** + * Update the java configuration before making the page visible. + */ + public void updateConfiguration() { + String projectName = firstPage.getProjectName(); + + currProject = ResourcesPlugin.getWorkspace().getRoot().getProject( + projectName); + + IJavaProject javaProject = JavaCore.create(currProject); + IPath projectPath = currProject.getFullPath(); + + // Initialize the classpath entries using the source directories + // and classpath container + ArrayList entryList = new ArrayList(); + entryList.add(getSrcPathEntry(projectPath)); + addResourcesDirectoryIfRequested(entryList, currProject); + IPath entryPath = new Path(JavaMEClasspathContainer.JAVAME_CONTAINER + + "/" + firstPage.getSelectedDevice()); //$NON-NLS-1$ + + entryList.add(JavaCore.newContainerEntry(entryPath)); + IClasspathEntry[] entries = entryList + .toArray(new IClasspathEntry[entryList.size()]); + + init(javaProject, null, entries, false); + } + + /** + * Add a resources directory as a source path entry if the user preferences + * requested. + * + * @param entryList + * @param project + */ + private void addResourcesDirectoryIfRequested( + List entryList, IProject project) { + Preferences prefs = MTJCorePlugin.getDefault().getPluginPreferences(); + + if (useSourceAndBinaryFolders() + && prefs.getBoolean(IMTJCoreConstants.PREF_USE_RESOURCES_DIR)) { + // Create the resources directory if it doesn't already exist + String resDirName = prefs + .getString(IMTJCoreConstants.PREF_RESOURCES_DIR); + IFolder resFolder = project.getFolder(resDirName); + + if (!resFolder.exists()) { + try { + resFolder.create(true, true, new NullProgressMonitor()); + } catch (CoreException e) { + e.printStackTrace(); + } + } + + // Add it as a source folder to the java project + entryList.add(JavaCore.newSourceEntry(resFolder.getFullPath())); + } + } + + private IStatus changeToNewProject() { + class UpdateRunnable implements IRunnableWithProgress { + public IStatus infoStatus = Status.OK_STATUS; + + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + try { + if (isAutobuild == null) { + IWorkspaceDescription description = ResourcesPlugin + .getWorkspace().getDescription(); + isAutobuild = Boolean.valueOf(description + .isAutoBuilding()); + description.setAutoBuilding(false); + ResourcesPlugin.getWorkspace().setDescription( + description); + } + infoStatus = updateProject(monitor); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } catch (OperationCanceledException e) { + throw new InterruptedException(); + } finally { + monitor.done(); + } + } + } + + UpdateRunnable op = new UpdateRunnable(); + try { + getContainer().run(true, false, + new WorkspaceModifyDelegatingOperation(op)); + + return op.infoStatus; + } catch (InvocationTargetException e) { + + final String title = Messages.NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_title; + final String message = Messages.NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_message; + ExceptionHandler.handle(e, getShell(), title, message); + + } catch (InterruptedException e) { + // cancel pressed + } + return null; + } + + /** + * @param source + * @param target + * @param monitor + * @throws IOException + * @throws CoreException + */ + private void copyFile(File source, IFileStore target, + IProgressMonitor monitor) throws IOException, CoreException { + FileInputStream is = new FileInputStream(source); + OutputStream os = target.openOutputStream(EFS.NONE, monitor); + copyFile(is, os); + } + + /** + * @param source + * @param target + * @throws IOException + * @throws CoreException + */ + private void copyFile(IFileStore source, File target) throws IOException, + CoreException { + InputStream is = source.openInputStream(EFS.NONE, null); + FileOutputStream os = new FileOutputStream(target); + copyFile(is, os); + } + + /** + * @param is + * @param os + * @throws IOException + */ + private void copyFile(InputStream is, OutputStream os) throws IOException { + try { + byte[] buffer = new byte[8192]; + while (true) { + int bytesRead = is.read(buffer); + if (bytesRead == -1) { + break; + } + + os.write(buffer, 0, bytesRead); + } + } finally { + try { + is.close(); + } finally { + os.close(); + } + } + } + + /** + * @param source + * @param name + * @return + * @throws CoreException + */ + private File createBackup(IFileStore source, String name) + throws CoreException { + try { + File bak = File.createTempFile("eclipse-" + name, ".bak"); //$NON-NLS-1$//$NON-NLS-2$ + copyFile(source, bak); + return bak; + } catch (IOException e) { + IStatus status = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + IStatus.ERROR, + Messages.NewMidletProjectWizardPageTwo_createBackup_error_1 + + name + + Messages.NewMidletProjectWizardPageTwo_createBackup_error_2, + e); + throw new CoreException(status); + } + } + + private void deleteProjectFile(URI projectLocation) throws CoreException { + IFileStore file = EFS.getStore(projectLocation); + if (file.fetchInfo().exists()) { + IFileStore projectFile = file.getChild(FILENAME_PROJECT); + if (projectFile.fetchInfo().exists()) { + projectFile.delete(EFS.NONE, null); + } + } + } + + private final void doRemoveProject(IProgressMonitor monitor) + throws InvocationTargetException { + final boolean noProgressMonitor = (currProjectLocation == null); // inside + // workspace + if ((monitor == null) || noProgressMonitor) { + monitor = new NullProgressMonitor(); + } + monitor + .beginTask( + Messages.NewMidletProjectWizardPageTwo_doRemoveProject_taskname, + 3); + try { + try { + URI projLoc = currProject.getLocationURI(); + + boolean removeContent = !keepContent + && currProject.isSynchronized(IResource.DEPTH_INFINITE); + if ((!removeContent) + && (currProject.getProject().getFullPath().toFile() + .exists())) { + restoreExistingFolders(projLoc); + } + currProject.delete(removeContent, false, + new SubProgressMonitor(monitor, 2)); + + MidletSuiteFactory.removeMidletSuiteProject(getJavaProject()); + + restoreExistingFiles(projLoc, + new SubProgressMonitor(monitor, 1)); + } finally { + IWorkspaceDescription description = ResourcesPlugin + .getWorkspace().getDescription(); + description.setAutoBuilding(isAutobuild.booleanValue()); + ResourcesPlugin.getWorkspace().setDescription(description); + // isAutobuild must be set + isAutobuild = null; + } + } catch (CoreException e) { + throw new InvocationTargetException(e); + } finally { + monitor.done(); + currProject = null; + keepContent = false; + } + } + + /** + * Get the source path for the project taking into account the new project + * preferences that the user has specified. + * + * @param projectPath + * @return + */ + private IPath getSrcPath(IPath projectPath) { + IPath srcPath = projectPath; + + if (useSourceAndBinaryFolders()) { + IPreferenceStore store = PreferenceConstants.getPreferenceStore(); + String srcPathName = store + .getString(PreferenceConstants.SRCBIN_SRCNAME); + srcPath = projectPath.append(srcPathName); + } + + return srcPath; + } + + /** + * Return an IClasspathEntry for the source path. + * + * @param projectPath + * @return + */ + private IClasspathEntry getSrcPathEntry(IPath projectPath) { + IPath srcPath = getSrcPath(projectPath); + + // Set up exclusions for the verified and deployed directories + // if the source and project directories are the same + IPath[] exclusions = null; + if (srcPath.equals(projectPath)) { + exclusions = new IPath[3]; + exclusions[0] = new Path(MTJCorePlugin.getDeploymentDirectoryName() + + "/"); //$NON-NLS-1$ + exclusions[1] = new Path(IMTJCoreConstants.TEMP_FOLDER_NAME + "/"); //$NON-NLS-1$ + exclusions[2] = new Path(PreprocessorBuilder.PROCESSED_DIRECTORY + + "/"); //$NON-NLS-1$ + } else { + exclusions = new IPath[0]; + } + + return JavaCore.newSourceEntry(srcPath, exclusions); + } + + /** + * @param realLocation + * @return + * @throws CoreException + */ + private boolean hasExistingContent(URI realLocation) throws CoreException { + IFileStore file = EFS.getStore(realLocation); + return file.fetchInfo().exists(); + } + + private void rememberExisitingFolders(URI projectLocation) { + fOrginalFolders = new HashSet(); + + try { + IFileStore[] children = EFS.getStore(projectLocation).childStores( + EFS.NONE, null); + for (IFileStore child : children) { + IFileInfo info = child.fetchInfo(); + if (info.isDirectory() && info.exists() + && !fOrginalFolders.contains(child.getName())) { + fOrginalFolders.add(child); + } + } + } catch (CoreException e) { + final String title = Messages.NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_title; + final String message = Messages.NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_message; + ExceptionHandler.handle(e, getShell(), title, message); + } + } + + private void rememberExistingFiles(URI projectLocation) + throws CoreException { + fDotProjectBackup = null; + fDotClasspathBackup = null; + + IFileStore file = EFS.getStore(projectLocation); + if (file.fetchInfo().exists()) { + IFileStore projectFile = file.getChild(FILENAME_PROJECT); + if (projectFile.fetchInfo().exists()) { + fDotProjectBackup = createBackup(projectFile, "project-desc"); //$NON-NLS-1$ + } + IFileStore classpathFile = file.getChild(FILENAME_CLASSPATH); + if (classpathFile.fetchInfo().exists()) { + fDotClasspathBackup = createBackup(classpathFile, + "classpath-desc"); //$NON-NLS-1$ + } + } + } + + private void restoreExistingFiles(URI projectLocation, + IProgressMonitor monitor) throws CoreException { + int ticks = ((fDotProjectBackup != null ? 1 : 0) + (fDotClasspathBackup != null ? 1 + : 0)) * 2; + monitor.beginTask("", ticks); //$NON-NLS-1$ + try { + IFileStore projectFile = EFS.getStore(projectLocation).getChild( + FILENAME_PROJECT); + projectFile.delete(EFS.NONE, new SubProgressMonitor(monitor, 1)); + if (fDotProjectBackup != null) { + copyFile(fDotProjectBackup, projectFile, + new SubProgressMonitor(monitor, 1)); + } + } catch (IOException e) { + IStatus status = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + IStatus.ERROR, + Messages.NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotproject, + e); + throw new CoreException(status); + } + try { + IFileStore classpathFile = EFS.getStore(projectLocation).getChild( + FILENAME_CLASSPATH); + classpathFile.delete(EFS.NONE, new SubProgressMonitor(monitor, 1)); + if (fDotClasspathBackup != null) { + copyFile(fDotClasspathBackup, classpathFile, + new SubProgressMonitor(monitor, 1)); + } + } catch (IOException e) { + IStatus status = new Status( + IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, + IStatus.ERROR, + Messages.NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotclasspath, + e); + throw new CoreException(status); + } + } + + private void restoreExistingFolders(URI projectLocation) { + try { + IFileStore[] children = EFS.getStore(projectLocation).childStores( + EFS.NONE, null); + for (IFileStore child : children) { + IFileInfo info = child.fetchInfo(); + if (info.isDirectory() && info.exists() + && !fOrginalFolders.contains(child)) { + child.delete(EFS.NONE, null); + fOrginalFolders.remove(child); + } + } + + for (IFileStore fileStore : fOrginalFolders) { + IFileStore deleted = fileStore; + deleted.mkdir(EFS.NONE, null); + } + } catch (CoreException e) { + final String title = Messages.NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_title; + final String message = Messages.NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_message; + ExceptionHandler.handle(e, getShell(), title, message); + } + } + + /** + * @param monitor + * @return + * @throws CoreException + * @throws InterruptedException + */ + private final IStatus updateProject(IProgressMonitor monitor) + throws CoreException, InterruptedException { + IStatus result = Status.OK_STATUS; + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + try { + monitor + .beginTask( + Messages.NewMidletProjectWizardPageTwo_updateProject_taskname, + 7); + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + String projectName = firstPage.getProjectName(); + + currProject = ResourcesPlugin.getWorkspace().getRoot().getProject( + projectName); + currProjectLocation = firstPage.getProjectLocationURI(); + + URI realLocation = getRealLocation(projectName, currProjectLocation); + keepContent = hasExistingContent(realLocation); + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + if (keepContent) { + rememberExistingFiles(realLocation); + rememberExisitingFolders(realLocation); + } + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + try { + + JavaCapabilityConfigurationPage.createProject(currProject, + firstPage.getProjectLocationURI(), + new SubProgressMonitor(monitor, 1)); + + // Set the device into the project metadata to make + // the java project creation happy. + IDevice device = firstPage.getSelectedDevice(); + + MetaData metadata = new MetaData(currProject); + metadata.setDevice(device); + try { + metadata.saveMetaData(); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } + + updateConfiguration(); + + // Get the java nature + try { + IRunnableWithProgress progress = super.getRunnable(); + progress.run(monitor); + } catch (Throwable e) { + throw new CoreException(new Status( + IResourceStatus.FAILED_READ_METADATA, "", e //$NON-NLS-1$ + .getMessage())); + } + + // Get the J2ME nature and metadata set up + String jadFileName = firstPage.getJadFileName(); + + IJavaProject javaProject = super.getJavaProject(); + + MidletSuiteFactory.MidletSuiteCreationRunnable runnable = MidletSuiteFactory + .getMidletSuiteCreationRunnable(currProject, + javaProject, device, jadFileName); + + runnable.setPreprocessingEnable(firstPage + .isPreprocessingEnabled()); + + runnable.run(monitor); + + } catch (CoreException e) { + if (e.getStatus().getCode() == IResourceStatus.FAILED_READ_METADATA) { + result = new Status( + IStatus.INFO, + IMTJUIConstants.PLUGIN_ID, + Messages.NewMidletProjectWizardPageTwo_updateProject_fail_read_metadata); + + deleteProjectFile(realLocation); + if (currProject.exists()) { + currProject.delete(true, null); + } + + createProject(currProject, currProjectLocation, null); + } else { + throw e; + } + } catch (Throwable e) { + throw new CoreException(Status.CANCEL_STATUS); + } + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + initializeBuildPath(JavaCore.create(currProject), + new SubProgressMonitor(monitor, 2)); + + configureJavaProject(new SubProgressMonitor(monitor, 3)); + // create the Java project to allow the use of the new source folder + // page + } catch (Exception e) { + throw new CoreException(Status.CANCEL_STATUS); + } finally { + monitor.done(); + } + + return result; + } + + /** + * Return a boolean indicating whether there will be separate source and + * binary folders in the project. + * + * @return + */ + private boolean useSourceAndBinaryFolders() { + IPreferenceStore store = PreferenceConstants.getPreferenceStore(); + return store.getBoolean(PreferenceConstants.SRCBIN_FOLDERS_IN_NEWPROJ); + } + + /** + * Creates the provisional project on which the wizard is working on. The + * provisional project is typically created when the page is entered the + * first time. The early project creation is required to configure linked + * folders. + * + * @return the provisional project + */ + protected IProject createProvisonalProject() { + IStatus status = changeToNewProject(); + if ((status != null) && !status.isOK()) { + ErrorDialog.openError(getShell(), "createProvisonalProject", null, //$NON-NLS-1$ + status); + } + return currProject; + } + + /** + * Evaluates the new build path and output folder according to the settings + * on the first page. The resulting build path is set by calling + * {@link #init(IJavaProject, IPath, IClasspathEntry[], boolean)}. Clients + * can override this method. + * + * @param javaProject the new project which is already created when this + * method is called. + * @param monitor the progress monitor + * @throws CoreException thrown when initializing the build path failed + */ + protected void initializeBuildPath(IJavaProject javaProject, + IProgressMonitor monitor) throws CoreException { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor + .beginTask( + Messages.NewMidletProjectWizardPageTwo_updateProject_monitor_buildpath_name, + 2); + + try { + IClasspathEntry[] entries = null; + IProject project = javaProject.getProject(); + + List cpEntries = new ArrayList(); + IWorkspaceRoot root = project.getWorkspace().getRoot(); + + IClasspathEntry sourceClasspathEntrie = getSrcPathEntry(project + .getFullPath()); + IFolder folder = root.getFolder(sourceClasspathEntrie.getPath()); + + if (!folder.exists()) { + folder.create(true, true, new SubProgressMonitor(monitor, 1)); + } + cpEntries.add(sourceClasspathEntrie); + addResourcesDirectoryIfRequested(cpEntries, project); + + IPath entryPath = new Path( + JavaMEClasspathContainer.JAVAME_CONTAINER + "/" //$NON-NLS-1$ + + firstPage.getSelectedDevice()); + cpEntries.add(JavaCore.newContainerEntry(entryPath)); + + entries = cpEntries.toArray(new IClasspathEntry[cpEntries.size()]); + + if (monitor.isCanceled()) { + throw new OperationCanceledException(); + } + + init(javaProject, getOutputLocation(), entries, false); + } finally { + monitor.done(); + } + } + + /** + * Removes the provisional project. The provisional project is typically + * removed when the user cancels the wizard or goes back to the first page. + */ + protected void removeProvisonalProject() { + if (!currProject.exists()) { + currProject = null; + return; + } + + IRunnableWithProgress op = new IRunnableWithProgress() { + public void run(IProgressMonitor monitor) + throws InvocationTargetException, InterruptedException { + doRemoveProject(monitor); + } + }; + + try { + getContainer().run(true, true, + new WorkspaceModifyDelegatingOperation(op)); + } catch (InvocationTargetException e) { + + final String title = Messages.NewMidletProjectWizardPageTwo_updateProject_errordialog_title; + final String message = Messages.NewMidletProjectWizardPageTwo_updateProject_errordialog_message; + ExceptionHandler.handle(e, getShell(), title, message); + + } catch (InterruptedException e) { + // cancel pressed + } + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.ui.wizards.JavaCapabilityConfigurationPage#useNewSourcePage + * () + */ + @Override + protected final boolean useNewSourcePage() { + return true; + } +} Index: src/org/eclipse/mtj/ui/internal/wizards/projects/messages.properties =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/projects/messages.properties (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/projects/messages.properties (revision 0) @@ -0,0 +1,50 @@ +NewMidletProjectWizard_error_create_project_window_message=An error occurred while creating the MIDlet project +NewMidletProjectWizard_error_create_project_window_title=Error Creating MIDlet Project +NewMidletProjectWizard_error_open_jad_file=Error opening the Application Descriptor file +NewMidletProjectWizard_image_descriptor=newjprj_wiz_M.gif +NewMidletProjectWizard_wizard_title=New MIDlet Project + +NewMidletProjectWizardPageOne_description=Create a MIDlet project in the workspace or in an external location. +NewMidletProjectWizardPageOne_deviceGroup=Target Device +NewMidletProjectWizardPageOne_deviceGroup_coment=This project is target to run with: +NewMidletProjectWizardPageOne_jad_groupname=Application Descriptor +NewMidletProjectWizardPageOne_jad_label=Name to be used for the jad file, generated during the \"Create Package\" process: +NewMidletProjectWizardPageOne_jadFileNameField=Jad filename: +NewMidletProjectWizardPageOne_jadNameGroup_projectBasedRadio=Use project name as filename +NewMidletProjectWizardPageOne_jadNameGroup_userDefinedRadio=Use custom jad file name +NewMidletProjectWizardPageOne_locationGroup_browse_button=Browse... +NewMidletProjectWizardPageOne_locationGroup_changeControlPressed_dialogMessage=Choose a directory for the project contents: +NewMidletProjectWizardPageOne_locationGroup_contents=Contents +NewMidletProjectWizardPageOne_locationGroup_externalLocationRadio=Create project from existing source +NewMidletProjectWizardPageOne_locationGroup_projectLocation=Directory: +NewMidletProjectWizardPageOne_locationGroup_workspaceLocationRadio=Create new project in workspace +NewMidletProjectWizardPageOne_validate_devicecount_error=There is no device available. Please, use the Manage Device button to import at least one. +NewMidletProjectWizardPageOne_validate_jadname_error_extension=Invalid jad name, missing the \".jad\" file extension. +NewMidletProjectWizardPageOne_validate_jadname_error_emptyname=Invalid jad name, missing the file name. +NewMidletProjectWizardPageOne_preprocessor=Enable Preprocessing Support +NewMidletProjectWizardPageOne_preprocessorGroup=Preprocessor +NewMidletProjectWizardPageOne_projectNameGroup=Project name: +NewMidletProjectWizardPageOne_projectNameGroup_update_error_alreadyExists=A project with this name already exists +NewMidletProjectWizardPageOne_projectNameGroup_update_error_emptyName=Enter a project name. +NewMidletProjectWizardPageOne_projectNameGroup_update_error_failedCreateContents=Cannot create project content at the given external location. +NewMidletProjectWizardPageOne_projectNameGroup_update_error_invalidDirectory=Invalid project contents directory +NewMidletProjectWizardPageOne_projectNameGroup_update_error_missingLocation=Enter a location for the project. +NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace1=Projects located in the workspace folder must be direct sub folders of the workspace folder +NewMidletProjectWizardPageOne_projectNameGroup_update_error_workspace2=The selected existing source location in the workspace root does not exist +NewMidletProjectWizardPageOne_title=Create a MIDlet Project + +NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_message=An error occurred while creating project. Check log for details. +NewMidletProjectWizardPageTwo_changeToNewProject_errordialog_title=New MIDlet Project +NewMidletProjectWizardPageTwo_createBackup_error_1=Problem while creating backup for '' +NewMidletProjectWizardPageTwo_createBackup_error_2='' +NewMidletProjectWizardPageTwo_doRemoveProject_taskname=Removing project... +NewMidletProjectWizardPageTwo_performFinish_monitor_taskname=Creating project... +NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_message=An error occurred while creating project. Check log for details. +NewMidletProjectWizardPageTwo_rememberExisitingFolders_errordialog_title=New MIDlet Project +NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotclasspath=Problem while restoring backup for .classpath +NewMidletProjectWizardPageTwo_restoreExistingFiles_problem_restoring_dotproject=Problem while restoring backup for .project +NewMidletProjectWizardPageTwo_updateProject_errordialog_message=An error occurred while creating project. Check log for details. +NewMidletProjectWizardPageTwo_updateProject_errordialog_title=New MIDlet Project +NewMidletProjectWizardPageTwo_updateProject_fail_read_metadata=Could not read project metadata +NewMidletProjectWizardPageTwo_updateProject_monitor_buildpath_name=Initializing build path +NewMidletProjectWizardPageTwo_updateProject_taskname=Initializing project... Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/ComboDialogField.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/ComboDialogField.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/ComboDialogField.java (revision 0) @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Combo; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; + +/** + * Dialog field containing a label and a combo control. + */ +public class ComboDialogField extends DialogField { + + protected static GridData gridDataForCombo(int span) { + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = false; + gd.horizontalSpan = span; + return gd; + } + + private Combo fComboControl; + private int fFlags; + private String[] fItems; + private ModifyListener fModifyListener; + private int fSelectionIndex; + + private String fText; + + /** + * @param flags + */ + public ComboDialogField(int flags) { + super(); + fText = ""; //$NON-NLS-1$ + fItems = new String[0]; + fFlags = flags; + fSelectionIndex = -1; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#doFillIntoGrid(org.eclipse.swt.widgets.Composite, int) + */ + @Override + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label = getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Combo combo = getComboControl(parent); + combo.setLayoutData(gridDataForCombo(nColumns - 1)); + + return new Control[] { label, combo }; + } + + /** + * Creates or returns the created combo control. + * + * @param parent The parent composite or null when the widget + * has already been created. + */ + public Combo getComboControl(Composite parent) { + if (fComboControl == null) { + assertCompositeNotNull(parent); + fModifyListener = new ModifyListener() { + public void modifyText(ModifyEvent e) { + doModifyText(e); + } + }; + SelectionListener selectionListener = new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + } + + public void widgetSelected(SelectionEvent e) { + doSelectionChanged(e); + } + }; + + fComboControl = new Combo(parent, fFlags); + fComboControl.setItems(fItems); + if (fSelectionIndex != -1) { + fComboControl.select(fSelectionIndex); + } else { + fComboControl.setText(fText); + } + fComboControl.setFont(parent.getFont()); + fComboControl.addModifyListener(fModifyListener); + fComboControl.addSelectionListener(selectionListener); + fComboControl.setEnabled(isEnabled()); + } + return fComboControl; + } + + // ------- focus methods + + /** + * Gets the combo items. + */ + public String[] getItems() { + return fItems; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#getNumberOfControls() + */ + @Override + public int getNumberOfControls() { + return 2; + } + + /** + * @return + */ + public int getSelectionIndex() { + return fSelectionIndex; + } + + /** + * Gets the text. + */ + public String getText() { + return fText; + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField#refresh() + */ + @Override + public void refresh() { + super.refresh(); + setTextWithoutUpdate(fText); + } + + /** + * Selects an item. + */ + public boolean selectItem(int index) { + boolean success = false; + if (isOkToUse(fComboControl)) { + fComboControl.select(index); + success = fComboControl.getSelectionIndex() == index; + } else { + if ((index >= 0) && (index < fItems.length)) { + fText = fItems[index]; + fSelectionIndex = index; + success = true; + } + } + if (success) { + dialogFieldChanged(); + } + return success; + } + + /** + * Selects an item. + */ + public boolean selectItem(String name) { + for (int i = 0; i < fItems.length; i++) { + if (fItems[i].equals(name)) { + return selectItem(i); + } + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#setFocus() + */ + @Override + public boolean setFocus() { + if (isOkToUse(fComboControl)) { + fComboControl.setFocus(); + } + return true; + } + + /** + * Sets the combo items. Triggers a dialog-changed event. + */ + public void setItems(String[] items) { + fItems = items; + if (isOkToUse(fComboControl)) { + fComboControl.setItems(items); + } + dialogFieldChanged(); + } + + /** + * Sets the text. Triggers a dialog-changed event. + */ + public void setText(String text) { + fText = text; + if (isOkToUse(fComboControl)) { + fComboControl.setText(text); + } else { + dialogFieldChanged(); + } + } + + /** + * Sets the text without triggering a dialog-changed event. + */ + public void setTextWithoutUpdate(String text) { + fText = text; + if (isOkToUse(fComboControl)) { + fComboControl.removeModifyListener(fModifyListener); + fComboControl.setText(text); + fComboControl.addModifyListener(fModifyListener); + } + } + + private void doModifyText(ModifyEvent e) { + if (isOkToUse(fComboControl)) { + fText = fComboControl.getText(); + fSelectionIndex = fComboControl.getSelectionIndex(); + } + dialogFieldChanged(); + } + + private void doSelectionChanged(SelectionEvent e) { + if (isOkToUse(fComboControl)) { + fItems = fComboControl.getItems(); + fText = fComboControl.getText(); + fSelectionIndex = fComboControl.getSelectionIndex(); + } + dialogFieldChanged(); + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#updateEnableState() + */ + @Override + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fComboControl)) { + fComboControl.setEnabled(isEnabled()); + } + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/DialogField.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/DialogField.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/DialogField.java (revision 0) @@ -0,0 +1,236 @@ +/******************************************************************************* + * Copyright (c) 2000, 2006 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.core.runtime.Assert; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; + +/** + * Base class of all dialog fields. Dialog fields manage controls together with + * the model, independed from the creation time of the widgets. - support for + * automated layouting. - enable / disable, set focus a concept of the base + * class. DialogField have a label. + */ +public class DialogField { + + /** + * Creates a spacer control. + * + * @param parent The parent composite + */ + public static Control createEmptySpace(Composite parent) { + return createEmptySpace(parent, 1); + } + + /** + * Creates a spacer control with the given span. The composite is assumed to + * have MGridLayout as layout. + * + * @param parent The parent composite + */ + public static Control createEmptySpace(Composite parent, int span) { + Label label = new Label(parent, SWT.LEFT); + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.BEGINNING; + gd.grabExcessHorizontalSpace = false; + gd.horizontalSpan = span; + gd.horizontalIndent = 0; + gd.widthHint = 0; + gd.heightHint = 0; + label.setLayoutData(gd); + return label; + } + + protected static GridData gridDataForLabel(int span) { + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + gd.horizontalSpan = span; + return gd; + } + + private IDialogFieldListener fDialogFieldListener; + + private boolean fEnabled; + + private Label fLabel; + + protected String fLabelText; + + public DialogField() { + fEnabled = true; + fLabel = null; + fLabelText = ""; //$NON-NLS-1$ + } + + /** + * Programatically invocation of a dialog field change. + */ + public void dialogFieldChanged() { + if (fDialogFieldListener != null) { + fDialogFieldListener.dialogFieldChanged(this); + } + } + + /** + * Creates all controls of the dialog field and fills it to a composite. The + * composite is assumed to have MGridLayout as layout. The + * dialog field will adjust its controls' spans to the number of columns + * given. To be re-implemented by dialog field implementors. + */ + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label = getLabelControl(parent); + label.setLayoutData(gridDataForLabel(nColumns)); + + return new Control[] { label }; + } + + /** + * Creates or returns the created label widget. + * + * @param parent The parent composite or null if the widget has + * already been created. + */ + public Label getLabelControl(Composite parent) { + if (fLabel == null) { + assertCompositeNotNull(parent); + + fLabel = new Label(parent, SWT.LEFT | SWT.WRAP); + fLabel.setFont(parent.getFont()); + fLabel.setEnabled(fEnabled); + if ((fLabelText != null) && !"".equals(fLabelText)) { //$NON-NLS-1$ + fLabel.setText(fLabelText); + } else { + fLabel.setText("."); //$NON-NLS-1$ + fLabel.setVisible(false); + } + } + return fLabel; + } + + /** + * Returns the number of columns of the dialog field. To be reimplemented by + * dialog field implementors. + */ + public int getNumberOfControls() { + return 1; + } + + /** + * Gets the enable state of the dialog field. + */ + public final boolean isEnabled() { + return fEnabled; + } + + /** + * Posts setFocus to the display event queue. + */ + public void postSetFocusOnDialogField(Display display) { + if (display != null) { + display.asyncExec(new Runnable() { + public void run() { + setFocus(); + } + }); + } + } + + /** + * Brings the UI in sync with the model. Only needed when model was changed + * in different thread while UI was already created. + */ + public void refresh() { + updateEnableState(); + } + + /** + * Defines the listener for this dialog field. + */ + public final void setDialogFieldListener(IDialogFieldListener listener) { + fDialogFieldListener = listener; + } + + /** + * Sets the enable state of the dialog field. + */ + public final void setEnabled(boolean enabled) { + if (enabled != fEnabled) { + fEnabled = enabled; + updateEnableState(); + } + } + + /** + * Tries to set the focus to the dialog field. Returns true if + * the dialog field can take focus. To be re-implemented by dialog field + * implementors. + */ + public boolean setFocus() { + return false; + } + + /** + * Sets the label of the dialog field. + */ + public void setLabelText(String labeltext) { + fLabelText = labeltext; + if (isOkToUse(fLabel)) { + fLabel.setText(labeltext); + } + } + + protected final void assertCompositeNotNull(Composite comp) { + Assert.isNotNull(comp, + "uncreated control requested with composite null"); //$NON-NLS-1$ + } + + protected final void assertEnoughColumns(int nColumns) { + Assert.isTrue(nColumns >= getNumberOfControls(), + "given number of columns is too small"); //$NON-NLS-1$ + } + + /** + * Tests is the control is not null and not disposed. + */ + protected final boolean isOkToUse(Control control) { + return (control != null) && (Display.getCurrent() != null) + && !control.isDisposed(); + } + + /** + * Called when the enable state changed. To be extended by dialog field + * implementors. + */ + protected void updateEnableState() { + if (fLabel != null) { + fLabel.setEnabled(fEnabled); + } + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IDialogFieldListener.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IDialogFieldListener.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IDialogFieldListener.java (revision 0) @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +/** + * Change listener used by DialogField + */ +public interface IDialogFieldListener { + + /** + * The dialog field has changed. + * + * @param field the dialog field that changed + */ + void dialogFieldChanged(DialogField field); + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IStringButtonAdapter.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IStringButtonAdapter.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/IStringButtonAdapter.java (revision 0) @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +/** + * Change listener used by StringButtonDialogField + */ +public interface IStringButtonAdapter { + + void changeControlPressed(DialogField field); + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/LayoutUtil.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/LayoutUtil.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/LayoutUtil.java (revision 0) @@ -0,0 +1,155 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +public class LayoutUtil { + + /** + * Creates a composite and fills in the given editors. + * + * @param labelOnTop Defines if the label of all fields should be on top of + * the fields + */ + public static void doDefaultLayout(Composite parent, DialogField[] editors, + boolean labelOnTop) { + doDefaultLayout(parent, editors, labelOnTop, 0, 0); + } + + /** + * Creates a composite and fills in the given editors. + * + * @param labelOnTop Defines if the label of all fields should be on top of + * the fields + * @param marginWidth The margin width to be used by the composite + * @param marginHeight The margin height to be used by the composite + */ + public static void doDefaultLayout(Composite parent, DialogField[] editors, + boolean labelOnTop, int marginWidth, int marginHeight) { + int nCulumns = getNumberOfColumns(editors); + Control[][] controls = new Control[editors.length][]; + for (int i = 0; i < editors.length; i++) { + controls[i] = editors[i].doFillIntoGrid(parent, nCulumns); + } + if (labelOnTop) { + nCulumns--; + modifyLabelSpans(controls, nCulumns); + } + GridLayout layout = null; + if (parent.getLayout() instanceof GridLayout) { + layout = (GridLayout) parent.getLayout(); + } else { + layout = new GridLayout(); + } + if (marginWidth != SWT.DEFAULT) { + layout.marginWidth = marginWidth; + } + if (marginHeight != SWT.DEFAULT) { + layout.marginHeight = marginHeight; + } + layout.numColumns = nCulumns; + parent.setLayout(layout); + } + + /** + * Calculates the number of columns needed by field editors + */ + public static int getNumberOfColumns(DialogField[] editors) { + int nCulumns = 0; + for (DialogField editor : editors) { + nCulumns = Math.max(editor.getNumberOfControls(), nCulumns); + } + return nCulumns; + } + + /** + * Sets the heightHint hint of a control. Assumes that GridData is used. + */ + public static void setHeightHint(Control control, int heightHint) { + Object ld = control.getLayoutData(); + if (ld instanceof GridData) { + ((GridData) ld).heightHint = heightHint; + } + } + + /** + * Sets the horizontal grabbing of a control to true. Assumes that GridData + * is used. + */ + public static void setHorizontalGrabbing(Control control) { + Object ld = control.getLayoutData(); + if (ld instanceof GridData) { + ((GridData) ld).grabExcessHorizontalSpace = true; + } + } + + /** + * Sets the horizontal indent of a control. Assumes that GridData is used. + */ + public static void setHorizontalIndent(Control control, int horizontalIndent) { + Object ld = control.getLayoutData(); + if (ld instanceof GridData) { + ((GridData) ld).horizontalIndent = horizontalIndent; + } + } + + /** + * Sets the span of a control. Assumes that GridData is used. + */ + public static void setHorizontalSpan(Control control, int span) { + Object ld = control.getLayoutData(); + if (ld instanceof GridData) { + ((GridData) ld).horizontalSpan = span; + } else if (span != 1) { + GridData gd = new GridData(); + gd.horizontalSpan = span; + control.setLayoutData(gd); + } + } + + /** + * Sets the width hint of a control. Assumes that GridData is used. + */ + public static void setWidthHint(Control control, int widthHint) { + Object ld = control.getLayoutData(); + if (ld instanceof GridData) { + ((GridData) ld).widthHint = widthHint; + } + } + + /** + * @param controls + * @param nCulumns + */ + private static void modifyLabelSpans(Control[][] controls, int nCulumns) { + for (Control[] control : controls) { + setHorizontalSpan(control[0], nCulumns); + } + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/SelectionButtonDialogField.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/SelectionButtonDialogField.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/SelectionButtonDialogField.java (revision 0) @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** + * Dialog Field containing a single button such as a radio or checkbox button. + */ +public class SelectionButtonDialogField extends DialogField { + + private DialogField[] fAttachedDialogFields; + private Button fButton; + private int fButtonStyle; + private boolean fIsSelected; + + /** + * Creates a selection button. Allowed button styles: SWT.RADIO, SWT.CHECK, + * SWT.TOGGLE, SWT.PUSH + */ + public SelectionButtonDialogField(int buttonStyle) { + super(); + fIsSelected = false; + fAttachedDialogFields = null; + fButtonStyle = buttonStyle; + } + + /** + * Attaches a field to the selection state of the selection button. The + * attached field will be disabled if the selection button is not selected. + */ + public void attachDialogField(DialogField dialogField) { + attachDialogFields(new DialogField[] { dialogField }); + } + + /** + * Attaches fields to the selection state of the selection button. The + * attached fields will be disabled if the selection button is not selected. + */ + public void attachDialogFields(DialogField[] dialogFields) { + fAttachedDialogFields = dialogFields; + for (DialogField dialogField : dialogFields) { + dialogField.setEnabled(fIsSelected); + } + } + + /* + * @see DialogField#doFillIntoGrid + */ + @Override + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Button button = getSelectionButton(parent); + GridData gd = new GridData(); + gd.horizontalSpan = nColumns; + gd.horizontalAlignment = GridData.FILL; + + button.setLayoutData(gd); + + return new Control[] { button }; + } + + // ------- layout helpers + + /* + * @see DialogField#getNumberOfControls + */ + @Override + public int getNumberOfControls() { + return 1; + } + + /** + * Returns the selection button widget. When called the first time, the + * widget will be created. + * + * @param group The parent composite when called the first time, or + * null after. + */ + public Button getSelectionButton(Composite group) { + if (fButton == null) { + assertCompositeNotNull(group); + + fButton = new Button(group, fButtonStyle); + fButton.setFont(group.getFont()); + fButton.setText(fLabelText); + fButton.setEnabled(isEnabled()); + fButton.setSelection(fIsSelected); + fButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + doWidgetSelected(e); + } + + public void widgetSelected(SelectionEvent e) { + doWidgetSelected(e); + } + }); + } + return fButton; + } + + // ------- ui creation + + /** + * Returns true is teh gived field is attached to the selection + * button. + */ + public boolean isAttached(DialogField editor) { + if (fAttachedDialogFields != null) { + for (DialogField attachedDialogField : fAttachedDialogFields) { + if (attachedDialogField == editor) { + return true; + } + } + } + return false; + } + + /** + * Returns the selection state of the button. + */ + public boolean isSelected() { + return fIsSelected; + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField#refresh() + */ + @Override + public void refresh() { + super.refresh(); + if (isOkToUse(fButton)) { + fButton.setSelection(fIsSelected); + } + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField#setLabelText + * (java.lang.String) + */ + @Override + public void setLabelText(String labeltext) { + fLabelText = labeltext; + if (isOkToUse(fButton)) { + fButton.setText(labeltext); + } + } + + // ------ model access + + /** + * Sets the selection state of the button. + */ + public void setSelection(boolean selected) { + changeValue(selected); + if (isOkToUse(fButton)) { + fButton.setSelection(selected); + } + } + + private void changeValue(boolean newState) { + if (fIsSelected != newState) { + fIsSelected = newState; + if (fAttachedDialogFields != null) { + boolean focusSet = false; + for (DialogField attachedDialogField : fAttachedDialogFields) { + attachedDialogField.setEnabled(fIsSelected); + if (fIsSelected && !focusSet) { + focusSet = attachedDialogField.setFocus(); + } + } + } + dialogFieldChanged(); + } else if (fButtonStyle == SWT.PUSH) { + dialogFieldChanged(); + } + } + + // ------ enable / disable management + + private void doWidgetSelected(SelectionEvent e) { + if (isOkToUse(fButton)) { + changeValue(fButton.getSelection()); + } + } + + /* + * @see DialogField#updateEnableState + */ + @Override + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fButton)) { + fButton.setEnabled(isEnabled()); + } + } + +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringButtonDialogField.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringButtonDialogField.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringButtonDialogField.java (revision 0) @@ -0,0 +1,157 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Dialog field containing a label, text control and a button control. + */ +public class StringButtonDialogField extends StringDialogField { + + protected static GridData gridDataForButton(Button button, int span) { + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = false; + gd.horizontalSpan = span; + return gd; + } + + private Button fBrowseButton; + private String fBrowseButtonLabel; + + private boolean fButtonEnabled; + + private IStringButtonAdapter fStringButtonAdapter; + + public StringButtonDialogField(IStringButtonAdapter adapter) { + super(); + fStringButtonAdapter = adapter; + fBrowseButtonLabel = "!Browse...!"; //$NON-NLS-1$ + fButtonEnabled = true; + } + + // ------ adapter communication + + /** + * Programmatical pressing of the button + */ + public void changeControlPressed() { + fStringButtonAdapter.changeControlPressed(this); + } + + // ------- layout helpers + + /* + * @see DialogField#doFillIntoGrid + */ + @Override + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label = getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Text text = getTextControl(parent); + text.setLayoutData(gridDataForText(nColumns - 2)); + Button button = getChangeControl(parent); + button.setLayoutData(gridDataForButton(button, 1)); + + return new Control[] { label, text, button }; + } + + /** + * Sets the enable state of the button. + */ + public void enableButton(boolean enable) { + if (isOkToUse(fBrowseButton)) { + fBrowseButton.setEnabled(isEnabled() && enable); + } + fButtonEnabled = enable; + } + + /** + * Creates or returns the created buttom widget. + * + * @param parent The parent composite or null if the widget has + * already been created. + */ + public Button getChangeControl(Composite parent) { + if (fBrowseButton == null) { + assertCompositeNotNull(parent); + + fBrowseButton = new Button(parent, SWT.PUSH); + fBrowseButton.setFont(parent.getFont()); + fBrowseButton.setText(fBrowseButtonLabel); + fBrowseButton.setEnabled(isEnabled() && fButtonEnabled); + fBrowseButton.addSelectionListener(new SelectionListener() { + public void widgetDefaultSelected(SelectionEvent e) { + changeControlPressed(); + } + + public void widgetSelected(SelectionEvent e) { + changeControlPressed(); + } + }); + + } + return fBrowseButton; + } + + // ------- ui creation + + /* + * @see DialogField#getNumberOfControls + */ + @Override + public int getNumberOfControls() { + return 3; + } + + // ------ enable / disable management + + /** + * Sets the label of the button. + */ + public void setButtonLabel(String label) { + fBrowseButtonLabel = label; + } + + /* + * @see DialogField#updateEnableState + */ + @Override + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fBrowseButton)) { + fBrowseButton.setEnabled(isEnabled() && fButtonEnabled); + } + } +} Index: src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringDialogField.java =================================================================== --- src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringDialogField.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/wizards/dialogfields/StringDialogField.java (revision 0) @@ -0,0 +1,189 @@ +/******************************************************************************* + * Copyright (c) 2000, 2005 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.wizards.dialogfields; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; + +/** + * Dialog field containing a label and a text control. + */ +public class StringDialogField extends DialogField { + + /** + * @param span + * @return + */ + protected static GridData gridDataForText(int span) { + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = false; + gd.horizontalSpan = span; + return gd; + } + + private ModifyListener fModifyListener; + private String fText; + + private Text fTextControl; + + /** + * + */ + public StringDialogField() { + super(); + fText = ""; //$NON-NLS-1$ + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#doFillIntoGrid(org.eclipse.swt.widgets.Composite, int) + */ + @Override + public Control[] doFillIntoGrid(Composite parent, int nColumns) { + assertEnoughColumns(nColumns); + + Label label = getLabelControl(parent); + label.setLayoutData(gridDataForLabel(1)); + Text text = getTextControl(parent); + text.setLayoutData(gridDataForText(nColumns - 1)); + + return new Control[] { label, text }; + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#getNumberOfControls() + */ + @Override + public int getNumberOfControls() { + return 2; + } + + /** + * Gets the text. Can not be null + */ + public String getText() { + return fText; + } + + /** + * Creates or returns the created text control. + * + * @param parent The parent composite or null when the widget + * has already been created. + */ + public Text getTextControl(Composite parent) { + if (fTextControl == null) { + assertCompositeNotNull(parent); + fModifyListener = new ModifyListener() { + public void modifyText(ModifyEvent e) { + doModifyText(e); + } + }; + + fTextControl = new Text(parent, SWT.SINGLE | SWT.BORDER); + fTextControl.setText(fText); + fTextControl.setFont(parent.getFont()); + fTextControl.addModifyListener(fModifyListener); + + fTextControl.setEnabled(isEnabled()); + } + return fTextControl; + } + + /* + * (non-Javadoc) + * @see + * org.eclipse.jdt.internal.ui.wizards.dialogfields.DialogField#refresh() + */ + @Override + public void refresh() { + super.refresh(); + if (isOkToUse(fTextControl)) { + setTextWithoutUpdate(fText); + } + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#setFocus() + */ + @Override + public boolean setFocus() { + if (isOkToUse(fTextControl)) { + fTextControl.setFocus(); + fTextControl.setSelection(0, fTextControl.getText().length()); + } + return true; + } + + /** + * Sets the text. Triggers a dialog-changed event. + */ + public void setText(String text) { + fText = text; + if (isOkToUse(fTextControl)) { + fTextControl.setText(text); + } else { + dialogFieldChanged(); + } + } + + /** + * Sets the text without triggering a dialog-changed event. + */ + public void setTextWithoutUpdate(String text) { + fText = text; + if (isOkToUse(fTextControl)) { + fTextControl.removeModifyListener(fModifyListener); + fTextControl.setText(text); + fTextControl.addModifyListener(fModifyListener); + } + } + + /** + * @param e + */ + private void doModifyText(ModifyEvent e) { + if (isOkToUse(fTextControl)) { + fText = fTextControl.getText(); + } + dialogFieldChanged(); + } + + /* (non-Javadoc) + * @see org.eclipse.mtj.ui.internal.wizards.testing.dialogfields.DialogField#updateEnableState() + */ + @Override + protected void updateEnableState() { + super.updateEnableState(); + if (isOkToUse(fTextControl)) { + fTextControl.setEnabled(isEnabled()); + } + } + +} Index: src/org/eclipse/mtj/ui/internal/actions/WorkbenchRunnableAdapter.java =================================================================== --- src/org/eclipse/mtj/ui/internal/actions/WorkbenchRunnableAdapter.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/actions/WorkbenchRunnableAdapter.java (revision 0) @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Initial version + */ +package org.eclipse.mtj.ui.internal.actions; + +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.OperationCanceledException; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.ISchedulingRule; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jface.operation.IRunnableWithProgress; +import org.eclipse.jface.operation.IThreadListener; +import org.eclipse.mtj.ui.IMTJUIConstants; + +/** + * An IRunnableWithProgress that adapts and + * IWorkspaceRunnable so that is can be executed inside + * IRunnableContext. OperationCanceledException thrown + * by the adapted runnable are caught and re-thrown as a + * InterruptedException. + */ +public class WorkbenchRunnableAdapter implements IRunnableWithProgress, + IThreadListener { + + private boolean fTransfer = false; + private IWorkspaceRunnable fWorkspaceRunnable; + private ISchedulingRule fRule; + + /** + * Runs a workspace runnable with the workspace lock. + * + * @param runnable the runnable + */ + public WorkbenchRunnableAdapter(IWorkspaceRunnable runnable) { + this(runnable, ResourcesPlugin.getWorkspace().getRoot()); + } + + /** + * Runs a workspace runnable with the given lock or null to run + * with no lock at all. + * + * @param runnable the runnable + * @param rule the scheduling rule + */ + public WorkbenchRunnableAdapter(IWorkspaceRunnable runnable, + ISchedulingRule rule) { + fWorkspaceRunnable = runnable; + fRule = rule; + } + + /** + * Runs a workspace runnable with the given lock or null to run + * with no lock at all. + * + * @param runnable the runnable + * @param rule the scheduling rule + * @param transfer true if the rule is to be transfered to the + * model context thread. Otherwise false + */ + public WorkbenchRunnableAdapter(IWorkspaceRunnable runnable, + ISchedulingRule rule, boolean transfer) { + fWorkspaceRunnable = runnable; + fRule = rule; + fTransfer = transfer; + } + + public ISchedulingRule getSchedulingRule() { + return fRule; + } + + /** + * {@inheritDoc} + */ + public void threadChange(Thread thread) { + if (fTransfer) + Job.getJobManager().transferRule(fRule, thread); + } + + /* + * @see IRunnableWithProgress#run(IProgressMonitor) + */ + public void run(IProgressMonitor monitor) throws InvocationTargetException, + InterruptedException { + try { + JavaCore.run(fWorkspaceRunnable, fRule, monitor); + } catch (OperationCanceledException e) { + throw new InterruptedException(e.getMessage()); + } catch (CoreException e) { + throw new InvocationTargetException(e); + } + } + + public void runAsUserJob(String name, final Object jobFamiliy) { + Job job = new Job(name) { + /* + * (non-Javadoc) + * @see + * org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime + * .IProgressMonitor) + */ + protected IStatus run(IProgressMonitor monitor) { + try { + WorkbenchRunnableAdapter.this.run(monitor); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof CoreException) { + return ((CoreException) cause).getStatus(); + } else { + return new Status(IStatus.ERROR, + IMTJUIConstants.PLUGIN_ID, cause.getMessage(), + cause); + } + } catch (InterruptedException e) { + return Status.CANCEL_STATUS; + } finally { + monitor.done(); + } + return Status.OK_STATUS; + } + + public boolean belongsTo(Object family) { + return jobFamiliy == family; + } + }; + job.setRule(fRule); + job.setUser(true); + job.schedule(); + + } +} Index: src/org/eclipse/mtj/ui/internal/utils/ExceptionHandler.java =================================================================== --- src/org/eclipse/mtj/ui/internal/utils/ExceptionHandler.java (revision 0) +++ src/org/eclipse/mtj/ui/internal/utils/ExceptionHandler.java (revision 0) @@ -0,0 +1,169 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 IBM Corporation and others. + * 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: + * IBM Corporation - initial API and implementation + *******************************************************************************/ + +/** + * Copyright (c) 2008 Motorola. + * + * 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: + * Diego Sandin (Motorola) - Adapted code available in JDT + */ +package org.eclipse.mtj.ui.internal.utils; + +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.dialogs.ErrorDialog; +import org.eclipse.jface.dialogs.MessageDialog; +import org.eclipse.mtj.core.internal.MTJCorePlugin; +import org.eclipse.mtj.ui.internal.MTJUIPlugin; +import org.eclipse.swt.widgets.Shell; + +/** + * The default exception handler shows an error dialog when one of its handle + * methods is called. If the passed exception is a CoreException an + * error dialog pops up showing the exception's status information. For a + * InvocationTargetException a normal message dialog pops up + * showing the exception's message. Additionally the exception is written to the + * platform log. + */ +public class ExceptionHandler { + + private static ExceptionHandler fgInstance = new ExceptionHandler(); + + /** + * Handles the given CoreException. + * + * @param e the CoreException to be handled + * @param parent the dialog window's parent shell + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + public static void handle(CoreException e, Shell parent, String title, + String message) { + fgInstance.perform(e, parent, title, message); + } + + /** + * Handles the given CoreException. The workbench shell is used + * as a parent for the dialog window. + * + * @param e the CoreException to be handled + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + public static void handle(CoreException e, String title, String message) { + handle(e, MTJUIPlugin.getActiveWorkbenchShell(), title, message); + } + + /** + * Handles the given InvocationTargetException. + * + * @param e the InvocationTargetException to be handled + * @param parent the dialog window's parent shell + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + public static void handle(InvocationTargetException e, Shell parent, + String title, String message) { + fgInstance.perform(e, parent, title, message); + } + + /** + * Handles the given InvocationTargetException. The workbench + * shell is used as a parent for the dialog window. + * + * @param e the InvocationTargetException to be handled + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + public static void handle(InvocationTargetException e, String title, + String message) { + handle(e, MTJUIPlugin.getActiveWorkbenchShell(), title, message); + } + + /** + * Logs the given exception using the platform's logging mechanism. The + * exception is logged as an error with the error code + * JavaStatusConstants.INTERNAL_ERROR. + * + * @param t the throwable to log + * @param message the message + */ + public static void log(Throwable t, String message) { + MTJCorePlugin.log(IStatus.ERROR, message, t); + } + + /** + * @param exceptionMessage + * @param shell + * @param title + * @param message + */ + private void displayMessageDialog(String exceptionMessage, Shell shell, + String title, String message) { + StringWriter msg = new StringWriter(); + if (message != null) { + msg.write(message); + msg.write("\n\n"); //$NON-NLS-1$ + } + if ((exceptionMessage == null) || (exceptionMessage.length() == 0)) { + msg.write("See error log for more details."); + } else { + msg.write(exceptionMessage); + } + MessageDialog.openError(shell, title, msg.toString()); + } + + /** + * @param e the CoreException to be handled + * @param shell the dialog window's parent shell + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + protected void perform(CoreException e, Shell shell, String title, + String message) { + MTJCorePlugin.log(IStatus.ERROR, e); + IStatus status = e.getStatus(); + if (status != null) { + ErrorDialog.openError(shell, title, message, status); + } else { + displayMessageDialog(e.getMessage(), shell, title, message); + } + } + + /** + * @param e the CoreException to be handled + * @param shell the dialog window's parent shell + * @param title the dialog window's window title + * @param message message to be displayed by the dialog window + */ + protected void perform(InvocationTargetException e, Shell shell, + String title, String message) { + Throwable target = e.getTargetException(); + if (target instanceof CoreException) { + perform((CoreException) target, shell, title, message); + } else { + MTJCorePlugin.log(IStatus.ERROR, e); + if ((e.getMessage() != null) && (e.getMessage().length() > 0)) { + displayMessageDialog(e.getMessage(), shell, title, message); + } else { + displayMessageDialog(target.getMessage(), shell, title, message); + } + } + } +}