Java tutorial
/******************************************************************************* * Copyright (c) 2012 Synflow SAS. * 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: * Matthieu Wipliez - initial API and implementation and/or initial documentation *******************************************************************************/ package com.synflow.cx.ui.wizards; import static com.synflow.core.ISynflowConstants.FILE_EXT_CX; import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.regex.Pattern; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.operation.IRunnableWithProgress; 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.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.ide.undo.CreateFileOperation; import org.eclipse.ui.ide.undo.WorkspaceUndoUtil; import com.synflow.core.SynflowCore; import com.synflow.core.layout.ITreeElement; import com.synflow.core.layout.Package; /** * This class provides a page to create a new text file. * * @author Matthieu Wipliez */ public class NewFilePage extends WizardPage implements ModifyListener { private static Pattern id = Pattern.compile("[A-Z][a-zA-Z0-9_]*"); private static final int SIZING_TEXT_FIELD_WIDTH = 250; private static String getTypeUpper(String type) { return type.substring(0, 1).toUpperCase() + type.substring(1); } private Package containingPackage; private Label labelPackage; private Text resourceNameField; private IStructuredSelection selection; private final String type; public NewFilePage(String type, IStructuredSelection selection) { super("New" + getTypeUpper(type)); this.selection = selection; setTitle("New Cx " + type); setDescription("Creates a new Cx " + type + "."); this.type = type; } @Override public void createControl(Composite parent) { initializeDialogUnits(parent); Composite composite = new Composite(parent, SWT.NONE); composite.setFont(parent.getFont()); GridLayout layout = new GridLayout(); layout.numColumns = 2; composite.setLayout(layout); Label label1 = new Label(composite, SWT.NONE); label1.setText("Package:"); label1.setFont(this.getFont()); labelPackage = new Label(composite, SWT.NONE); labelPackage.setFont(this.getFont()); Label label2 = new Label(composite, SWT.WRAP); label2.setText(getTypeUpper(type) + " name:"); label2.setFont(this.getFont()); // resource name entry field resourceNameField = new Text(composite, SWT.BORDER); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); data.widthHint = SIZING_TEXT_FIELD_WIDTH; resourceNameField.setLayoutData(data); resourceNameField.setFont(this.getFont()); initializePage(); // add modify listener *after* page is initialized // so page is not complete, but no error message is shown initially resourceNameField.addModifyListener(this); // Show description on opening setControl(composite); } /** * 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. * * @param initialContents * initial contents of the file * * @return the created file resource, or <code>null</code> if the file was not created */ public IFile createNewFile(final InputStream initialContents) { final IFile newFileHandle = getFile(); IRunnableWithProgress op = new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) { CreateFileOperation op = new CreateFileOperation(newFileHandle, null, initialContents, getTitle()); try { // see bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=219901 // directly execute the operation so that the undo state is // not preserved. Making this undoable resulted in too many // accidental file deletions. op.execute(monitor, WorkspaceUndoUtil.getUIInfoAdapter(getShell())); } catch (final ExecutionException e) { getContainer().getShell().getDisplay().syncExec(new Runnable() { @Override public void run() { if (e.getCause() instanceof CoreException) { ErrorDialog.openError(getContainer().getShell(), "Could not create " + type, null, ((CoreException) e.getCause()).getStatus()); } else { SynflowCore.log(e.getCause()); MessageDialog.openError(getContainer().getShell(), "Could not create " + type, NLS.bind("Internal error: {0}", 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. SynflowCore.log(e.getTargetException()); MessageDialog.open(MessageDialog.ERROR, getContainer().getShell(), "Could not create " + type, NLS.bind("Internal error: {0}", e.getTargetException().getMessage()), SWT.SHEET); return null; } return newFileHandle; } protected final String getEntityName() { return resourceNameField.getText(); } private IFile getFile() { String fileName = resourceNameField.getText() + "." + FILE_EXT_CX; IFolder folder = (IFolder) containingPackage.getResource(); return folder.getFile(fileName); } protected final String getPackage() { return containingPackage.getName(); } protected CharSequence getStringContents(String author, int year) { return null; } /** * Initializes this page's controls. */ protected void initializePage() { Iterator<?> it = selection.iterator(); if (it.hasNext()) { Object next = it.next(); if (next instanceof ITreeElement) { ITreeElement element = (ITreeElement) next; if (element.isPackage()) { containingPackage = (Package) element; labelPackage.setText(containingPackage.getName()); } } } // cannot complete until a name is entered setPageComplete(false); } @Override public void modifyText(ModifyEvent e) { setPageComplete(validatePage()); } /** * 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() { String text = resourceNameField.getText(); if (text.isEmpty()) { setErrorMessage("Enter a " + type + " name."); return false; } // check first letter is uppercase char first = text.charAt(0); if (!Character.isUpperCase(first)) { setErrorMessage("A " + type + " name must begin with a uppercase letter"); return false; } if (!id.matcher(text).matches()) { setErrorMessage("Invalid " + type + " name: '" + text + "' is not a valid identifier. Must match \"" + id.toString() + "\"."); return false; } IFile file = getFile(); if (file.exists()) { setErrorMessage("An entity with the same name already exists."); return false; } setErrorMessage(null); return true; } }