/******************************************************************************* * Copyright Technophobia Ltd 2012 * * This file is part of the Substeps Eclipse Plugin. * * The Substeps Eclipse Plugin is free software: you can redistribute it and/or modify * it under the terms of the Eclipse Public License v1.0. * * The Substeps Eclipse Plugin is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Eclipse Public License for more details. * * You should have received a copy of the Eclipse Public License * along with the Substeps Eclipse Plugin. If not, see <http://www.eclipse.org/legal/epl-v10.html>. ******************************************************************************/ package com.technophobia.substeps.junit.launcher.tab.component; import java.util.Collection; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.window.Window; 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.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementTreeSelectionDialog; import org.eclipse.ui.dialogs.ISelectionStatusValidator; import org.eclipse.ui.model.BaseWorkbenchContentProvider; import org.eclipse.ui.model.WorkbenchLabelProvider; import com.technophobia.eclipse.transformer.Callback; import com.technophobia.substeps.FeatureRunnerPlugin; import com.technophobia.substeps.junit.launcher.model.SubstepsLaunchModel; import com.technophobia.substeps.junit.ui.SubstepsFeatureMessages; import com.technophobia.substeps.supplier.Predicate; import com.technophobia.substeps.supplier.Supplier; public class FeatureFileComponent extends AbstractTabComponent { private Text featureFileLocationText; private Button featureFileLocationButton; private final Predicate<IFolder> isFeatureFolderPredicate; public FeatureFileComponent(final Callback onChangeCallback, final Supplier<IProject> projectSupplier, final Predicate<IFolder> featureFolderPredicate) { super(onChangeCallback, projectSupplier); isFeatureFolderPredicate = featureFolderPredicate; } @Override public void initializeFrom(final SubstepsLaunchModel model) { featureFileLocationText.setText(model.getFeatureFile()); } @Override public void saveTo(final SubstepsLaunchModel model) { if (featureFileLocationText != null) { model.setFeatureFile(featureFileLocationText.getText().trim()); } } @Override public void setDefaultOn(final SubstepsLaunchModel model, final IResource currentResource) { if (currentResource instanceof IFile) { final IFile file = (IFile) currentResource; if (file.getFileExtension().equalsIgnoreCase("feature")) { model.setFeatureFile(projectLocalisedPathFor(file)); } } } @Override public void validate(final Collection<String> errorMessageList) { final String featureFileName = featureFileLocationText.getText().trim(); if (featureFileName.length() == 0) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_featurefilenotdefined); return; } if (!validFeatureFile(project(), featureFileName, errorMessageList)) { return; } } @Override public void create(final Composite comp) { final Label featureFileLocationLabel = new Label(comp, SWT.NONE); featureFileLocationLabel.setText(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_label_feature_location); GridData gd = new GridData(); gd.horizontalIndent = 25; gd.verticalIndent = 5; featureFileLocationLabel.setLayoutData(gd); featureFileLocationText = new Text(comp, SWT.SINGLE | SWT.BORDER); gd = new GridData(GridData.FILL_HORIZONTAL); gd.verticalIndent = 5; featureFileLocationText.setLayoutData(gd); featureFileLocationText.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent evt) { onChange(); } }); featureFileLocationButton = new Button(comp, SWT.PUSH); featureFileLocationButton .setText(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_browse_feature_location); featureFileLocationButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent evt) { final String newLocation = handleFeatureFileLocationButtonSelected(); if (newLocation != null && !newLocation.isEmpty()) { featureFileLocationText.setText(newLocation); } } }); } @Override protected boolean isValid() { return !featureFileLocationText.getText().trim().isEmpty(); } @Override public void enableControls() { featureFileLocationText.setEnabled(true); featureFileLocationButton.setEnabled(true); } @Override public void disableControls() { featureFileLocationText.setEnabled(false); featureFileLocationButton.setEnabled(false); } /* * Show a dialog that lets the user select a folder or substeps file. */ private String handleFeatureFileLocationButtonSelected() { final IResource resource = chooseFeatureFileResource(); if (resource == null) { return ""; } return projectLocalisedPathFor(resource); } private IResource chooseFeatureFileResource() { final ILabelProvider labelProvider = new WorkbenchLabelProvider(); final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(featureFileLocationText.getShell(), labelProvider, new BaseWorkbenchContentProvider()); dialog.setTitle(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_featurefiledialog_title); dialog.setMessage(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_featurefiledialog_message); dialog.setInput(project()); dialog.setAllowMultiple(false); dialog.setValidator(new ISelectionStatusValidator() { @Override public IStatus validate(final Object[] selection) { if (selection.length > 0) { final Object item = selection[0]; if (item instanceof IFile) { final IFile file = (IFile) item; if ("feature".equalsIgnoreCase(file.getFileExtension())) { return new Status(IStatus.OK, FeatureRunnerPlugin.PLUGIN_ID, ""); } } else if (item instanceof IFolder) { if (isFeatureFolderPredicate.forModel((IFolder) item)) { return new Status(IStatus.OK, FeatureRunnerPlugin.PLUGIN_ID, ""); } } } return new Status(IStatus.ERROR, FeatureRunnerPlugin.PLUGIN_ID, SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_notFeatureFile); } }); if (dialog.open() == Window.OK) { return (IResource) dialog.getFirstResult(); } return null; } /** * Determine if a feature file exists under project with name * * @param project * The project where substeps lives * @param featureFileName * file name, relative to project * @return true if feature file exists, otherwise false */ private boolean validFeatureFile(final IProject project, final String featureFileName, final Collection<String> errorMessageList) { if (isFileName(featureFileName)) { if (featureFileName.endsWith(".feature")) { if (!project.getFile(featureFileName).exists()) { errorMessageList .add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_featurefilenotexists); return false; } } else { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_notFeatureFile); return false; } } else { final IFolder folder = project.getFolder(featureFileName); if (!folder.exists()) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_featurefilenotexists); return false; } else if (!isFeatureFolderPredicate.forModel(folder)) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_featurefilenotexists); return false; } } return true; } private boolean isFileName(final String featureFileName) { return featureFileName.indexOf('.') > -1; } }