/******************************************************************************* * Copyright (c) 2008 g-Eclipse Consortium * 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 * * Initial development of the original code was made for the g-Eclipse project * funded by European Union project number: FP6-IST-034327 * http://www.geclipse.eu/ * * Contributors: * RUR (http://acet.rdg.ac.uk/) * - Ashish Thandavan - initial API and implementation * - David Johnson - added some enhancements ******************************************************************************/ package eu.geclipse.workflow.ui.wizards; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.net.URL; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; 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.Path; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.osgi.util.NLS; 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.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.undo.CreateFolderOperation; import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; import org.eclipse.ui.internal.ide.IDEWorkbenchMessages; import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin; import org.eclipse.ui.internal.ide.misc.ResourceAndContainerGroup; import eu.geclipse.core.model.IGridContainer; import eu.geclipse.core.model.IGridElement; import eu.geclipse.core.model.IGridProject; import eu.geclipse.workflow.IGridWorkflowDescription; import eu.geclipse.workflow.ui.internal.WorkflowDiagramEditorPlugin; import eu.geclipse.workflow.ui.part.Messages; /** * Main page for a wizard that creates a workflow resource. * * @author athandava Many bits of code in this class have been reused from * org.eclipse.ui.dialogs.WizardNewFileCreationPage and * org.eclipse.ui.dialogs.WizardNewFolderMainPage */ public class NewWorkflowCreationWizardPage extends WizardPage implements Listener { private static final int SIZING_CONTAINER_GROUP_HEIGHT = 250; private String extension = "workflow"; private String initialName = "new"; // link target location private URI linkTargetPath; private IStructuredSelection currentSelection; private IPath initialContainerFullPath; private ResourceAndContainerGroup resourceGroup; private IFolder newFolder; /** * Constructor which takes the pagename and current selection as arguments. * * @param pageName * @param selection */ protected NewWorkflowCreationWizardPage( String pageName, IStructuredSelection selection ) { super( pageName ); URL imgUrl = WorkflowDiagramEditorPlugin.getDefault() .getBundle() .getEntry( "icons/wizban/NewWorkflowWizard.gif" ); //$NON-NLS-1$ setImageDescriptor( ImageDescriptor.createFromURL( imgUrl ) ); this.currentSelection = selection; setPageComplete( false ); } /** * The method that creates the controls on the page. */ public void createControl( Composite parent ) { initializeDialogUnits( parent ); // top level group Composite topLevel = new Composite( parent, SWT.NONE ); topLevel.setFont( parent.getFont() ); topLevel.setLayout( new GridLayout() ); topLevel.setLayoutData( new GridData( GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL ) ); PlatformUI.getWorkbench() .getHelpSystem() .setHelp( topLevel, WorkflowDiagramEditorPlugin.ID + "new_workflow_wizard_page_context" ); this.resourceGroup = new ResourceAndContainerGroup( topLevel, this, Messages.getString( "NewWorkflowCreationWizardPage_WorkflowName" ), Messages.getString( "NewWorkflowCreationWizardPage_WorkflowNameLabel" ), false, SIZING_CONTAINER_GROUP_HEIGHT ); this.resourceGroup.setAllowExistingResources( false ); initializePage(); validatePage(); // Show description on opening setErrorMessage( null ); setMessage( null ); setControl( topLevel ); setFileName( getUniqueFileName() ); this.resourceGroup.setFocus(); } /** * @return */ private String getUniqueFileName() { IPath containerFullPath = getContainerFullPath(); String fileName = this.initialName; if( containerFullPath == null ) { containerFullPath = new Path( "" ); //$NON-NLS-1$ } if( fileName == null || fileName.trim().length() == 0 ) { fileName = "default"; //$NON-NLS-1$ } IPath filePath = containerFullPath.append( fileName ); if( this.extension != null && !this.extension.equals( filePath.getFileExtension() ) ) { filePath = filePath.addFileExtension( this.extension ); } this.extension = filePath.getFileExtension(); fileName = filePath.removeFileExtension().lastSegment(); int i = 0; while( ResourcesPlugin.getWorkspace().getRoot().exists( filePath ) ) { i++; filePath = containerFullPath.append( fileName + i ); if( this.extension != null ) { filePath = filePath.addFileExtension( this.extension ); } } return filePath.lastSegment(); } /** * Creates a folder resource handle for the folder with the given workspace * path. This method does not create the folder resource; this is the * responsibility of <code>createNewFolder</code>. * * @param folderPath the path of the folder resource to create a handle for * @return the new folder resource handle * @see #createNewFolder */ protected IFolder createFolderHandle( IPath folderPath ) { return IDEWorkbenchPlugin.getPluginWorkspace() .getRoot() .getFolder( folderPath ); } /** * Creates a new folder resource in the selected container and with the * selected name. Creates any missing resource containers along the path; does * nothing if the container resources already exist. * <p> * In normal usage, this method is invoked after the user has pressed Finish * on the wizard; the enablement of the Finish button implies that all * controls on this page currently contain valid values. * </p> * <p> * Note that this page caches the new folder once it has been successfully * created; subsequent invocations of this method will answer the same folder * resource without attempting to create it again. * </p> * <p> * This method should be called within a workspace modify operation since it * creates resources. * </p> * * @return the created folder resource, or <code>null</code> if the folder was * not created */ public IFolder createNewFolder() { if( this.newFolder != null ) { return this.newFolder; } // create the new folder and cache it if successful final IPath containerPath = this.resourceGroup.getContainerFullPath(); IPath newFolderPath = containerPath.append( this.resourceGroup.getResource() ); final IFolder newFolderHandle = createFolderHandle( newFolderPath ); IRunnableWithProgress op = new IRunnableWithProgress() { public void run( IProgressMonitor monitor ) { CreateFolderOperation op = new CreateFolderOperation( newFolderHandle, NewWorkflowCreationWizardPage.this.linkTargetPath, IDEWorkbenchMessages.WizardNewFolderCreationPage_title ); try { PlatformUI.getWorkbench() .getOperationSupport() .getOperationHistory() .execute( op, monitor, WorkspaceUndoUtil.getUIInfoAdapter( getShell() ) ); } catch( final ExecutionException e ) { getContainer().getShell().getDisplay().syncExec( new Runnable() { public void run() { if( e.getCause() instanceof CoreException ) { ErrorDialog.openError( getContainer().getShell(), // Was // Utilities. // getFocusShell // () IDEWorkbenchMessages.WizardNewFolderCreationPage_errorTitle, null, // no special message ( ( CoreException )e.getCause() ).getStatus() ); } else { IDEWorkbenchPlugin.log( getClass(), "createNewFolder()", e.getCause() ); //$NON-NLS-1$ MessageDialog.openError( getContainer().getShell(), IDEWorkbenchMessages.WizardNewFolderCreationPage_internalErrorTitle, NLS.bind( IDEWorkbenchMessages.WizardNewFolder_internalError, e.getCause().getMessage() ) ); } } } ); } } }; try { getContainer().run( true, true, op ); } catch( InterruptedException e ) { return null; } catch( InvocationTargetException e ) { // ExecutionExceptions are handled above, but unexpected runtime // exceptions and errors may still occur. IDEWorkbenchPlugin.log( getClass(), "createNewFolder()", e.getTargetException() ); //$NON-NLS-1$ MessageDialog.openError( getContainer().getShell(), IDEWorkbenchMessages.WizardNewFolderCreationPage_internalErrorTitle, NLS.bind( IDEWorkbenchMessages.WizardNewFolder_internalError, e.getTargetException().getMessage() ) ); return null; } this.newFolder = newFolderHandle; return this.newFolder; } /** * Returns the current full path of the containing resource as entered or * selected by the user, or its anticipated initial value. * * @return the container's full path, anticipated initial value, or * <code>null</code> if no path is known */ public IPath getContainerFullPath() { return this.resourceGroup.getContainerFullPath(); } /** * @return foldername */ public String getFolderName() { if( this.resourceGroup == null ) { return this.initialName; } return this.resourceGroup.getResource(); } /** * @return */ protected IPath getFolderPath() { IPath path = getContainerFullPath(); if( path == null ) { path = new Path( "" ); //$NON-NLS-1$ } String fileName = getFolderName(); if( fileName != null ) { path = path.append( fileName ); } return path; } /** * The <code>NewWorkflowCreationWizardPage</code> implementation of this * <code>Listener</code> method handles all events and enablements for * controls on this page. */ public void handleEvent( Event event ) { setPageComplete( validatePage() ); } /** * Initializes this page's controls. */ protected void initializePage() { Object o = this.currentSelection.getFirstElement(); if (o instanceof IGridContainer) { IGridElement e = (IGridElement)o; IGridProject project = e.getProject(); IPath path = null; if (project != null) { IGridElement workflows = project.getProjectFolder( IGridWorkflowDescription.class ); if( workflows != null ) { path = workflows.getPath(); } else { path = project.getPath(); } } this.resourceGroup.setContainerFullPath( path ); } setPageComplete( false ); } /** * Sets the value of this page's container name field, or stores it for future * use if this page's controls do not exist yet. * * @param path the full path to the container */ public void setContainerFullPath( IPath path ) { if( this.resourceGroup == null ) { this.initialContainerFullPath = path; } else { this.resourceGroup.setContainerFullPath( path ); } } /** * Set the only file extension allowed for this page's file name field. If * this page's controls do not exist yet, store it for future use. <br> * <br> * If a file extension is specified, then it will always be appended with a * '.' to the text from the file name field for validation when the following * conditions are met: <br> * <br> * (1) File extension length is greater than 0 <br> * (2) File name field text length is greater than 0 <br> * (3) File name field text does not already end with a '.' and the file * extension specified (case sensitive) <br> * <br> * The file extension will not be reflected in the actual file name field * until the file name field loses focus. * * @param value The file extension without the '.' prefix (e.g. 'java', 'xml') * @since 3.3 */ public void setFileExtension( String value ) { if( this.resourceGroup == null ) { this.extension = value; } else { this.resourceGroup.setResourceExtension( value ); } } /** * Sets the value of this page's file name field, or stores it for future use * if this page's controls do not exist yet. * * @param value new file name */ public void setFileName( String value ) { if( this.resourceGroup == null ) { this.initialName = value; } else { this.resourceGroup.setResource( value ); } } /** * Checks and returns whether this page's controls currently all contain valid * values. * * @return <code>true</code> if all controls are valid, and <code>false</code> * if at least one is invalid */ protected boolean validatePage() { boolean valid = true; if( !this.resourceGroup.areAllValuesValid() ) { // if blank name then fail silently if( this.resourceGroup.getProblemType() == ResourceAndContainerGroup.PROBLEM_RESOURCE_EMPTY || this.resourceGroup.getProblemType() == ResourceAndContainerGroup.PROBLEM_CONTAINER_EMPTY ) { setMessage( this.resourceGroup.getProblemMessage() ); setErrorMessage( null ); } else { setErrorMessage( this.resourceGroup.getProblemMessage() ); } valid = false; } String resourceName = this.resourceGroup.getResource(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); IStatus result = workspace.validateName( resourceName, IResource.FILE ); if( !result.isOK() ) { setErrorMessage( result.getMessage() ); return false; } IStatus linkedResourceStatus = null; // validateLinkedResource sets messages itself if( valid && ( linkedResourceStatus == null || linkedResourceStatus.isOK() ) ) { setMessage( null ); setErrorMessage( null ); // perform "resource exists" check if it was skipped in // ResourceAndContainerGroup if( this.resourceGroup.getAllowExistingResources() ) { String problemMessage = NLS.bind( IDEWorkbenchMessages.ResourceGroup_nameExists, getFolderName() ); IPath resourcePath = getContainerFullPath().append( getFolderName() ); if( workspace.getRoot().getFolder( resourcePath ).exists() ) { setErrorMessage( problemMessage ); valid = false; } if( workspace.getRoot().getFile( resourcePath ).exists() ) { setMessage( problemMessage, IMessageProvider.WARNING ); } } } if( this.extension != null && !getFolderPath().toString().endsWith( "." + this.extension ) ) //$NON-NLS-1$ { setErrorMessage( NLS.bind( "Folder name should have ''{0}'' extension.", //$NON-NLS-1$ this.extension ) ); valid = false; } return valid; } }