/* * Copyright (c) 2006 Stiftung Deutsches Elektronen-Synchroton, * Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY. * * THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS. * WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE * IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR * CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. * NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. * DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, * OR MODIFICATIONS. * THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION, * USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS * PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY * AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM */ package org.csstudio.ui.util.wizards; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.util.Iterator; import org.csstudio.ui.util.composites.ResourceAndContainerGroup; import org.csstudio.ui.util.internal.localization.Messages; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IPath; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.wizard.WizardPage; 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; /** * Standard main page for a wizard that creates a file resource. * <p> * This page may be used by clients as-is; it may be also be subclassed to suit. * </p> * <p> * Subclasses may override * <ul> * <li><code>getInitialContents</code></li> * <li><code>getNewFileLabel</code></li> * </ul> * </p> * <p> * Subclasses may extend * <ul> * <li><code>handleEvent</code></li> * </ul> * </p> * <p> * <b>Code is based upon * <code>org.eclipse.ui.dialogs.WizardNewFileCreationPage</code> in plugin * <code>org.eclipse.ui.ide</code>.</b> * </p> * * @author Alexander Will * @version $Revision$ * */ //TODO: Copied from org.csstudio.platform.ui. Review is needed. public class WizardNewFileCreationPage extends WizardPage implements Listener { /** * The current resource selection. */ private IStructuredSelection _currentSelection; /** * Cache of newly-created file. */ private IFile _newFile; /** * Target container selection group. */ private ResourceAndContainerGroup _resourceGroup; /** * Initial value store for the file name. */ private String _initialFileName; /** * Initial value store for the target container. */ private IPath _initialContainerFullPath; /** * Flag that signals whether the target project can be chosen or not. */ private boolean _canChooseProject; /** * Creates a new file creation wizard page. If the initial resource * selection contains exactly one container resource then it will be used as * the default container resource. * * @param pageName * the name of the page * @param selection * the current resource selection */ public WizardNewFileCreationPage(final String pageName, final IStructuredSelection selection) { this(pageName, selection, true); } /** * Creates a new file creation wizard page. If the initial resource * selection contains exactly one container resource then it will be used as * the default container resource. * * @param pageName * the name of the page * @param selection * the current resource selection * @param canChooseProject * flag to allow the selection of the target project */ public WizardNewFileCreationPage(final String pageName, final IStructuredSelection selection, final boolean canChooseProject) { super(pageName); setPageComplete(false); _currentSelection = selection; _canChooseProject = canChooseProject; } /** * {@inheritDoc} */ @Override public final void createControl(final Composite parent) { initializeDialogUnits(parent); // top level group Composite topLevel = new Composite(parent, SWT.NONE); topLevel.setLayout(new GridLayout()); topLevel.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL)); topLevel.setFont(parent.getFont()); // PlatformUI.getWorkbench().getHelpSystem().setHelp(topLevel, // IIDEHelpContextIds.NEW_FILE_WIZARD_PAGE); // resource and container group _resourceGroup = new ResourceAndContainerGroup(topLevel, this, getNewFileLabel(), Messages.WizardNewFileCreationPage_LABEL_FILE, false, 250); if (getFileExtension() != null) { _resourceGroup.setFileExtension(getFileExtension()); } _resourceGroup.setAllowExistingResources(false); initialPopulateContainerNameField(); if (_initialFileName != null) { _resourceGroup.setResource(_initialFileName); } _resourceGroup.setContainerSelectionGroupEnabled(_canChooseProject); validatePage(); // Show description on opening setErrorMessage(null); setMessage(null); setControl(topLevel); } /** * Creates a file resource given the file handle and contents. * * @param fileHandle * the file handle to create a file resource with * @param contents * the initial contents of the new file resource, or * <code>null</code> if none (equivalent to an empty stream) * @exception CoreException * if the operation fails */ protected final void createFile(final IFile fileHandle, final InputStream contents) throws CoreException { InputStream inputStream = contents; if (inputStream == null) { inputStream = new ByteArrayInputStream(new byte[0]); } try { IPath path = fileHandle.getFullPath(); IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); int numSegments = path.segmentCount(); if (numSegments > 2 && !root.getFolder(path.removeLastSegments(1)).exists()) { // If the direct parent of the path doesn't exist, try to // create the // necessary directories. for (int i = numSegments - 2; i > 0; i--) { IFolder folder = root.getFolder(path.removeLastSegments(i)); if (!folder.exists()) { folder.create(false, true, null); } } } fileHandle.create(inputStream, false, null); } catch (CoreException e) { // If the file already existed locally, just refresh to get contents if (e.getStatus().getCode() == IResourceStatus.PATH_OCCUPIED) { fileHandle.refreshLocal(IResource.DEPTH_ZERO, null); } else { throw e; } } } /** * Creates a file resource handle for the file with the given workspace * path. This method does not create the file resource; this is the * responsibility of <code>createFile</code>. * * @param filePath * the path of the file resource to create a handle for * @return the new file resource handle * @see #createFile */ protected final IFile createFileHandle(final IPath filePath) { return ResourcesPlugin.getWorkspace().getRoot().getFile(filePath); } /** * Creates a new file 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 on this page currently contain valid values. * </p> * <p> * Note that this page caches the new file once it has been successfully * created; subsequent invocations of this method will answer the same file * 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 file resource, or <code>null</code> if the file was * not created */ public final IFile createNewFile() { if (_newFile != null) { return _newFile; } // create the new file and cache it if successful final IPath containerPath = _resourceGroup.getContainerFullPath(); IPath newFilePath = containerPath.append(_resourceGroup.getResource()); IFile newFileHandle = createFileHandle(newFilePath); final InputStream initialContents = getInitialContents(); try { createFile(newFileHandle, initialContents); } catch (CoreException e) { ErrorDialog.openError(getContainer().getShell(), Messages.WizardNewFileCreationPage_ERROR_TITLE, null, e .getStatus()); newFileHandle = null; } _newFile = newFileHandle; return _newFile; } /** * 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 final IPath getContainerFullPath() { return _resourceGroup.getContainerFullPath(); } /** * Returns the current file name as entered by the user, or its anticipated * initial value. * * @return the file name, its anticipated initial value, or * <code>null</code> if no file name is known */ public String getFileName() { if (_resourceGroup == null) { return _initialFileName; } return _resourceGroup.getResource(); } /** * Returns a stream containing the initial contents to be given to new file * resource instances. <b>Subclasses</b> may wish to override. This default * implementation provides no initial contents. * * @return initial contents to be given to new file resource instances */ protected InputStream getInitialContents() { return null; } /** * Returns the label to display in the file name specification visual * component group. * <p> * Subclasses may reimplement. * </p> * * @return the label to display in the file name specification visual * component group */ protected String getNewFileLabel() { return Messages.WizardNewFileCreationPage_LABEL_FILE_NAME; } /** * The <code>WizardNewFileCreationPage</code> implementation of this * <code>Listener</code> method handles all events and enablements for * controls on this page. Subclasses may extend. * * @param event * The event to handle. */ @Override public void handleEvent(final Event event) { setPageComplete(validatePage()); } /** * Sets the initial contents of the container name entry field, based upon * either a previously-specified initial value or the ability to determine * such a value. */ protected final void initialPopulateContainerNameField() { if (_initialContainerFullPath != null) { _resourceGroup.setContainerFullPath(_initialContainerFullPath); } else { Iterator<?> it = _currentSelection.iterator(); if (it.hasNext()) { Object object = it.next(); IResource selectedResource = null; if (object instanceof IResource) { selectedResource = (IResource) object; } else if (object instanceof IAdaptable) { selectedResource = (IResource) ((IAdaptable) object) .getAdapter(IResource.class); } if (selectedResource != null) { if (selectedResource.getType() == IResource.FILE) { selectedResource = selectedResource.getParent(); } if (selectedResource.isAccessible()) { _resourceGroup.setContainerFullPath(selectedResource .getFullPath()); } } } } } /** * 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 final void setContainerFullPath(final IPath path) { if (_resourceGroup == null) { _initialContainerFullPath = path; } else { _resourceGroup.setContainerFullPath(path); } } /** * 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 final void setFileName(final String value) { if (_resourceGroup == null) { _initialFileName = value; } else { _resourceGroup.setResource(value); } } /** * 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 final boolean validatePage() { boolean valid = true; if (!_resourceGroup.areAllValuesValid()) { // if blank name then fail silently if (_resourceGroup.getProblemType() == ResourceAndContainerGroup.PROBLEM_RESOURCE_EMPTY || _resourceGroup.getProblemType() == ResourceAndContainerGroup.PROBLEM_CONTAINER_EMPTY) { setMessage(_resourceGroup.getProblemMessage()); setErrorMessage(null); } else { setErrorMessage(_resourceGroup.getProblemMessage()); } valid = false; } if (valid) { setMessage(null); setErrorMessage(null); } return valid; } /** * {@inheritDoc} */ @Override public final void setVisible(final boolean visible) { super.setVisible(visible); if (visible) { _resourceGroup.setFocus(); } } /** * Return the file extension. * * @return The file extension. */ public String getFileExtension() { return null; } }