/******************************************************************************* * Copyright (c) 2009, 2010 Sven Kiera * 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 *******************************************************************************/ package org.phpsrc.eclipse.pti.tools.phpunit.ui.wizards; import java.io.File; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.dltk.core.ISourceModule; import org.eclipse.dltk.core.search.IDLTKSearchScope; import org.eclipse.dltk.core.search.SearchMatch; import org.eclipse.dltk.internal.core.SourceType; import org.eclipse.jface.dialogs.IDialogPage; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.window.Window; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; 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.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ContainerSelectionDialog; import org.phpsrc.eclipse.pti.core.IPHPCoreConstants; import org.phpsrc.eclipse.pti.core.PHPToolkitUtil; import org.phpsrc.eclipse.pti.core.search.PHPSearchEngine; import org.phpsrc.eclipse.pti.core.search.PHPSearchMatch; import org.phpsrc.eclipse.pti.core.search.ui.dialogs.FilteredPHPClassSelectionDialog; import org.phpsrc.eclipse.pti.tools.phpunit.core.PHPUnit; import org.phpsrc.eclipse.pti.tools.phpunit.core.PHPUnitUtil; import org.phpsrc.eclipse.pti.tools.phpunit.core.preferences.PHPUnitPreferences; import org.phpsrc.eclipse.pti.tools.phpunit.core.preferences.PHPUnitPreferencesFactory; @SuppressWarnings("restriction") public class PHPClassCreationWizardPage extends WizardPage { protected Text fClassPath; protected Text fClassName; protected IFile fClassFile; protected Text fPhpClassName; protected Text fContainer; protected Text fFile; protected Text fSuperClass; private IStructuredSelection selection; protected IProject project; protected static final String UTF_8 = "UTF 8"; //$NON-NLS-1$ protected static final String NO_TEMPLATE = "-- none -- "; //$NON-NLS-1$ protected Label targetResourceLabel; protected PHPUnitPreferences preferences; protected boolean testFileExists = false; private interface IClassSearchListener { public void handleSearchMatch(PHPSearchMatch match); }; public PHPClassCreationWizardPage(final IStructuredSelection selection) { super("wizardPage"); //$NON-NLS-1$ setTitle("New PHP Class"); this.selection = selection; } /** * @see IDialogPage#createControl(Composite) */ public void createControl(final Composite parent) { Composite container = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.verticalSpacing = 10; container.setLayout(layout); // ###### Source ###### Group classGroup = new Group(container, SWT.RESIZE); classGroup.setText("Source"); GridLayout classLayout = new GridLayout(); classLayout.numColumns = 3; classLayout.verticalSpacing = 10; classGroup.setLayout(classLayout); classGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // ### Source File ### Label classFolderLabel = new Label(classGroup, SWT.NULL); classFolderLabel.setText("Source File:"); fClassPath = new Text(classGroup, SWT.BORDER | SWT.SINGLE); fClassPath.setEditable(false); GridData gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; fClassPath.setLayoutData(gd); // ### Class to test ### Label classLabel = new Label(classGroup, SWT.NULL); classLabel.setText("Test Class:"); fClassName = new Text(classGroup, SWT.BORDER | SWT.SINGLE); fClassName.setEditable(false); gd = new GridData(GridData.FILL_HORIZONTAL); fClassName.setLayoutData(gd); fClassName.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); Button sourceButton = new Button(classGroup, SWT.PUSH); sourceButton.setText("Search..."); sourceButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { handleClassSearch(new IClassSearchListener() { public void handleSearchMatch(PHPSearchMatch match) { setTestCaseClass(match); } }); } }); // ###### Test ###### Group fileGroup = new Group(container, SWT.RESIZE); fileGroup.setText("PHP Class"); GridLayout fileLayout = new GridLayout(); fileLayout.numColumns = 3; fileLayout.verticalSpacing = 10; fileGroup.setLayout(fileLayout); fileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); // ### Test Class ### Label testClassNameLabel = new Label(fileGroup, SWT.NULL); testClassNameLabel.setText("Class Name:"); fPhpClassName = new Text(fileGroup, SWT.BORDER | SWT.SINGLE); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; fPhpClassName.setLayoutData(gd); // ### SuperClass ### Label superClassLabel = new Label(fileGroup, SWT.NULL); superClassLabel.setText("SuperClass:"); fSuperClass = new Text(fileGroup, SWT.BORDER | SWT.SINGLE); gd = new GridData(GridData.FILL_HORIZONTAL); fSuperClass.setLayoutData(gd); Button superClassButton = new Button(fileGroup, SWT.PUSH); superClassButton.setText("Search..."); superClassButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { handleClassSearch(new IClassSearchListener() { public void handleSearchMatch(PHPSearchMatch match) { fSuperClass .setText(match.getElement().getElementName()); } }); } }); // ### Target Folder ### Label fileLabel = new Label(fileGroup, SWT.NULL); fileLabel.setText("Target Folder:"); gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING); gd.verticalIndent = 4; fileLabel.setLayoutData(gd); Composite folderLabelGroup = new Composite(fileGroup, SWT.NULL); layout = new GridLayout(); layout.numColumns = 1; layout.verticalSpacing = 0; layout.marginHeight = 0; layout.marginWidth = 0; folderLabelGroup.setLayout(layout); gd = new GridData(GridData.FILL_HORIZONTAL); gd.verticalIndent = 2; folderLabelGroup.setLayoutData(gd); fContainer = new Text(folderLabelGroup, SWT.BORDER | SWT.SINGLE); fContainer.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); fContainer.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); Label folderInfoLabel = new Label(folderLabelGroup, SWT.NULL); folderInfoLabel.setText("Path must start with a project like " + File.separatorChar + "<project>" + File.separatorChar + "<folder 1>" + File.separatorChar + "<folder 2>"); folderInfoLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); makeFontItalic(folderInfoLabel); Button containerButton = new Button(fileGroup, SWT.PUSH); containerButton.setText("Browse..."); containerButton.setLayoutData(new GridData( GridData.VERTICAL_ALIGN_BEGINNING)); containerButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(final SelectionEvent e) { handleContainerBrowse(); } }); // ### File Name ### targetResourceLabel = new Label(fileGroup, SWT.NULL); targetResourceLabel.setText("File Name:"); fFile = new Text(fileGroup, SWT.BORDER | SWT.SINGLE); gd = new GridData(GridData.FILL_HORIZONTAL); gd.horizontalSpan = 2; fFile.setLayoutData(gd); fFile.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); initialize(); dialogChanged(); setControl(container); } private void setTestCaseClass(SearchMatch match) { setTestCaseClass((SourceType) match.getElement(), match.getResource()); } private void setTestCaseClass(PHPSearchMatch match) { setTestCaseClass(match.getElement(), match.getResource()); } private void setTestCaseClass(SourceType type, IResource resource) { Assert.isNotNull(type); Assert.isNotNull(resource); if (resource instanceof IFile && PHPUnit.isTestCase((IFile) resource)) { String className = PHPToolkitUtil.getClassNameWithNamespace(type .getSourceModule()); fClassName.setText(className); fClassPath.setText(resource.getFullPath().toOSString()); fClassFile = (IFile) resource; fPhpClassName.setText(PHPUnitUtil.generatePHPClassName(className)); File phpClassFile = PHPUnitUtil .generateProjectRelativePHPClassFile(type, resource); fContainer.setText(phpClassFile.getParent()); fFile.setText(phpClassFile.getName()); } } /** * Tests if the current workbench selection is a suitable container to use. */ private void initialize() { if (selection != null && !selection.isEmpty() && selection instanceof IStructuredSelection) { final IStructuredSelection ssel = (IStructuredSelection) selection; if (ssel.size() > 1) { return; } Object obj = ssel.getFirstElement(); if (obj instanceof IAdaptable) { obj = ((IAdaptable) obj).getAdapter(IResource.class); } IContainer container = null; if (obj instanceof IResource) { if (obj instanceof IContainer) { container = (IContainer) obj; } else { container = ((IResource) obj).getParent(); } } if (container != null) { fContainer.setText(container.getFullPath().toOSString()); this.project = container.getProject(); preferences = PHPUnitPreferencesFactory.factory(this.project); } } if (preferences == null) { preferences = PHPUnitPreferencesFactory.factoryGlobal(); } if (selection != null) { ISourceModule module = PHPToolkitUtil.getSourceModule(selection .getFirstElement()); if (module != null) { this.setTestCaseClassName(PHPToolkitUtil.getClassName(module), (IResource) selection.getFirstElement()); } } } /** * Uses the standard container selection dialog to choose the new value for * the container field. */ private void handleContainerBrowse() { final ContainerSelectionDialog dialog = new ContainerSelectionDialog( getShell(), ResourcesPlugin.getWorkspace().getRoot(), false, "Select Test File Folder"); dialog.showClosedProjects(false); if (dialog.open() == Window.OK) { final Object[] result = dialog.getResult(); if (result.length == 1) fContainer.setText(((Path) result[0]).toOSString()); } } private void handleClassSearch(IClassSearchListener listener) { FilteredPHPClassSelectionDialog dialog = new FilteredPHPClassSelectionDialog( getShell(), false); if (dialog.open() == Window.OK) { PHPSearchMatch result = (PHPSearchMatch) dialog.getFirstResult(); if (result != null && result.getElement() != null) listener.handleSearchMatch(result); } } /** * Ensures that both text fields are set. */ protected void dialogChanged() { testFileExists = false; if (preferences == null || preferences.getPhpExecutable() == null || "".equals(preferences.getPhpExecutable())) { updateStatus("No preferences found. Please check your PHPUnit configuration."); return; } if (fClassFile == null) { updateStatus("No class to test selected"); return; } final String container = getContainerName(); final String fileName = getFileName(); if (container.length() == 0) { updateStatus("Folder must be specified"); return; } final IContainer containerFolder = getContainer(container); if (containerFolder == null || !containerFolder.exists()) { setMessage("Selected folder does not exist and will be created", WizardPage.INFORMATION); } else { if (containerFolder.getProject() == null) { updateStatus("Project must be specified within Target Folder"); return; } if (!containerFolder.getProject().isOpen()) { updateStatus("Selected folder is in a closed project"); return; } if (fileName != null && !fileName.equals("") && containerFolder.getFile(new Path(fileName)).exists()) { //$NON-NLS-1$ setMessage("File exists so new methods will be supplemented", WizardPage.INFORMATION); testFileExists = true; } } this.project = null; String projectName = null; if (container != null && container.length() > 0) { if (container.indexOf(java.io.File.separatorChar, 1) > 0) projectName = container.substring(1, container.indexOf(java.io.File.separatorChar, 1)); else projectName = container.substring(1); IContainer projectContainer = getContainer(java.io.File.separatorChar + projectName); if (projectContainer != null) this.project = projectContainer.getProject(); } if (this.project == null) { if (projectName != null) updateStatus("Project \"" + projectName + "\" does not exist"); else updateStatus("Project must be specified within Target Folder"); return; } int dotIndex = fileName.lastIndexOf('.'); if (fileName.length() == 0 || dotIndex == 0) { updateStatus("File name must be specified"); return; } if (dotIndex != -1) { String fileNameWithoutExtention = fileName.substring(0, dotIndex); for (int i = 0; i < fileNameWithoutExtention.length(); i++) { char ch = fileNameWithoutExtention.charAt(i); if (!(Character.isJavaIdentifierPart(ch) || ch == '.' || ch == '-')) { updateStatus("File name contains illegal characters"); return; } } } final IContentType contentType = Platform.getContentTypeManager() .getContentType(IPHPCoreConstants.ContentTypeID_PHP); if (!contentType.isAssociatedWith(fileName)) { // fixed bug 195274 // get the extensions from content type final String[] fileExtensions = contentType .getFileSpecs(IContentType.FILE_EXTENSION_SPEC); StringBuffer buffer = new StringBuffer( "The file name must end in one of the following extensions ["); buffer.append(fileExtensions[0]); for (String extension : fileExtensions) { buffer.append(", ").append(extension); //$NON-NLS-1$ } buffer.append("]"); //$NON-NLS-1$ updateStatus(buffer.toString()); return; } updateStatus(null); } protected IContainer getContainer(final String text) { final Path path = new Path(text); final IResource resource = ResourcesPlugin.getWorkspace().getRoot() .findMember(path); return resource instanceof IContainer ? (IContainer) resource : null; } protected void updateStatus(final String message) { setErrorMessage(message); setPageComplete(message == null); } public boolean setTestCaseClassName(String className) { return setTestCaseClassName(className, PHPSearchEngine.createWorkspaceScope(), null); } public boolean setTestCaseClassName(String className, IResource classFile) { return setTestCaseClassName(className, PHPSearchEngine.createProjectScope(classFile.getProject()), classFile); } public boolean setTestCaseClassName(String className, IDLTKSearchScope scope) { return setTestCaseClassName(className, scope, null); } protected boolean setTestCaseClassName(String className, IDLTKSearchScope scope, IResource classFile) { SearchMatch[] matches = PHPSearchEngine.findClass(className, scope); if (matches.length > 0) { for (SearchMatch match : matches) { if (classFile == null || match.getResource().equals(classFile)) { setTestCaseClass(match); return true; } } // no file found, so use first match setTestCaseClass(matches[0]); return true; } return false; } public String getSourceClassName() { return fClassName.getText(); } public IFile getSourceClassFile() { return fClassFile; } public String getContainerName() { return fContainer.getText(); } public String getFileName() { return fFile.getText(); } public String getPHPClassFilePath() { return getContainerName() + File.separatorChar + getFileName(); } public String getPHPClassSuperClass() { return fSuperClass.getText(); } public String getPHPClassName() { return fPhpClassName.getText(); } public IProject getProject() { return project; } public boolean finish() { return true; } protected void makeFontItalic(Control label) { Font font = label.getFont(); FontData[] data = font.getFontData(); if (data.length > 0) { data[0].setStyle(data[0].getStyle() | SWT.ITALIC); } label.setFont(new Font(font.getDevice(), data)); } }