/******************************************************************************* * 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.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.ProjectManagerSuppliedSubstepsLocationFinder; import com.technophobia.substeps.junit.launcher.model.SubstepsLaunchModel; import com.technophobia.substeps.junit.ui.SubstepsFeatureMessages; import com.technophobia.substeps.supplier.Supplier; import com.technophobia.substeps.supplier.Transformer; public class SubstepsFileComponent extends AbstractTabComponent { private Text substepsLocationText; private Button substepsLocationButton; private final Transformer<IProject, String> defaultSubstepsLocationFinder; public SubstepsFileComponent(final Callback onChangeCallback, final Supplier<IProject> projectSupplier) { this(onChangeCallback, projectSupplier, new ProjectManagerSuppliedSubstepsLocationFinder()); } public SubstepsFileComponent(final Callback onChangeCallback, final Supplier<IProject> projectSupplier, final Transformer<IProject, String> defaultSubstepsLocationFinder) { super(onChangeCallback, projectSupplier); this.defaultSubstepsLocationFinder = defaultSubstepsLocationFinder; } @Override public void initializeFrom(final SubstepsLaunchModel model) { substepsLocationText.setText(model.getSubstepsFile()); } @Override public void saveTo(final SubstepsLaunchModel model) { if (substepsLocationText != null) { model.setSubstepsFile(substepsLocationText.getText().trim()); } } @Override public void setDefaultOn(final SubstepsLaunchModel model, final IResource currentResource) { final String substepsFolder = defaultSubstepsLocationFinder.from(currentResource.getProject()); if (substepsFolder != null) { model.setSubstepsFile(substepsFolder); } else { model.setSubstepsFile(""); } } @Override public void create(final Composite comp) { final Label substepsLocationLabel = new Label(comp, SWT.NONE); substepsLocationLabel.setText(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_label_substeps_location); GridData gd = new GridData(); gd.horizontalIndent = 25; gd.verticalIndent = 5; substepsLocationLabel.setLayoutData(gd); substepsLocationText = new Text(comp, SWT.SINGLE | SWT.BORDER); gd = new GridData(GridData.FILL_HORIZONTAL); gd.verticalIndent = 5; substepsLocationText.setLayoutData(gd); substepsLocationText.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent evt) { onChange(); } }); substepsLocationButton = new Button(comp, SWT.PUSH); substepsLocationButton.setText(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_browse_substeps_location); substepsLocationButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent evt) { final String newLocation = handleSubstepsLocationButtonSelected(); if (newLocation != null && !newLocation.isEmpty()) { substepsLocationText.setText(newLocation); } } }); } @Override public void validate(final Collection<String> errorMessageList) { final String substepsFileName = substepsLocationText.getText().trim(); if (substepsFileName.length() == 0) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_substepsnotdefined); return; } if (!validSubstepsFile(project(), substepsFileName, errorMessageList)) { return; } } @Override protected boolean isValid() { return !substepsLocationText.getText().trim().isEmpty(); } @Override public void enableControls() { substepsLocationText.setEnabled(true); substepsLocationButton.setEnabled(true); } @Override public void disableControls() { substepsLocationText.setEnabled(false); substepsLocationButton.setEnabled(false); } /* * Show a dialog that lets the user select a folder or substeps file. */ private String handleSubstepsLocationButtonSelected() { final IResource resource = chooseSubstepsResource(); if (resource == null) { return ""; } return projectLocalisedPathFor(resource); } private IResource chooseSubstepsResource() { final ILabelProvider labelProvider = new WorkbenchLabelProvider(); final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(substepsLocationText.getShell(), labelProvider, new BaseWorkbenchContentProvider()); dialog.setTitle(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_substepsdialog_title); dialog.setMessage(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_substepsdialog_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 (!"substeps".equalsIgnoreCase(file.getFileExtension())) { return new Status(IStatus.ERROR, FeatureRunnerPlugin.PLUGIN_ID, SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_notSubstepsFile); } } } return new Status(IStatus.OK, FeatureRunnerPlugin.PLUGIN_ID, ""); } }); if (dialog.open() == Window.OK) { return (IResource) dialog.getFirstResult(); } return null; } /** * Determine if a substeps file folder exists under project with name * * @param project * The project where substeps lives * @param substepsFileName * file/folder name, relative to project * @return true if substeps file/folder exists, otherwise false */ private boolean validSubstepsFile(final IProject project, final String substepsFileName, final Collection<String> errorMessageList) { if (substepsFileName.endsWith(".substeps")) { if (!project.getFile(substepsFileName).exists()) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_substepsnotexists); return false; } } else if (substepsFileName.indexOf('.') > -1) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_notSubstepsFile); return false; } else { if (!project.getFolder(substepsFileName).exists()) { errorMessageList.add(SubstepsFeatureMessages.SubstepsLaunchConfigurationTab_error_substepsnotexists); return false; } } return true; } }