/* * Copyright (c) 2015 the original author or authors. * 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: * Etienne Studer & Donát Csikós (Gradle Inc.) - initial API and implementation and initial documentation */ package org.eclipse.buildship.ui.launch; import java.io.File; import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Strings; import com.google.common.collect.FluentIterable; import com.gradleware.tooling.toolingutils.binding.Validator; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; import org.eclipse.debug.ui.StringVariableSelectionDialog; import org.eclipse.jface.viewers.ArrayContentProvider; 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.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; 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.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ListDialog; import org.eclipse.ui.model.WorkbenchLabelProvider; import org.eclipse.buildship.core.CorePlugin; import org.eclipse.buildship.core.configuration.GradleProjectNature; import org.eclipse.buildship.core.i18n.CoreMessages; import org.eclipse.buildship.core.launch.GradleRunConfigurationAttributes; import org.eclipse.buildship.core.util.binding.Validators; import org.eclipse.buildship.core.util.collections.CollectionsUtils; import org.eclipse.buildship.core.util.file.FileUtils; import org.eclipse.buildship.core.util.variable.ExpressionUtils; import org.eclipse.buildship.ui.PluginImage.ImageState; import org.eclipse.buildship.ui.PluginImages; import org.eclipse.buildship.ui.util.file.DirectoryDialogSelectionListener; /** * Specifies a root project and a list of tasks to execute via the run configurations. */ public final class ProjectTab extends AbstractLaunchConfigurationTab { private final Validator<File> workingDirValidator; private Text tasksText; private Text workingDirectoryText; private Button showExecutionViewCheckbox; private Button showConsoleViewCheckbox; public ProjectTab() { this.workingDirValidator = Validators.requiredDirectoryValidator(CoreMessages.RunConfiguration_Label_WorkingDirectory); } @Override public String getName() { return LaunchMessages.Tab_Name_GradleTasks; } @Override public Image getImage() { return PluginImages.RUN_CONFIG_TASKS.withState(ImageState.ENABLED).getImage(); } @Override public void createControl(Composite root) { Composite parent = new Composite(root, SWT.NONE); GridLayout layout = new GridLayout(1, false); parent.setLayout(layout); setControl(parent); Group tasksGroup = createGroup(parent, CoreMessages.RunConfiguration_Label_GradleTasks + ":"); //$NON-NLS-1$ createTasksSelectionControl(tasksGroup); Group workingDirectoryGroup = createGroup(parent, CoreMessages.RunConfiguration_Label_WorkingDirectory + ":"); //$NON-NLS-1$ createWorkingDirectorySelectionControl(workingDirectoryGroup); Group buildExecutionGroup = createGroup(parent, CoreMessages.RunConfiguration_Label_BuildExecution + ":"); //$NON-NLS-1$ createBuildExecutionControl(buildExecutionGroup); } private Group createGroup(Composite parent, String groupName) { Group group = new Group(parent, SWT.NONE); group.setText(groupName); group.setLayout(new GridLayout()); group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); return group; } private void createTasksSelectionControl(Composite container) { this.tasksText = new Text(container, SWT.MULTI | SWT.BORDER | SWT.WRAP | SWT.V_SCROLL); GridData tasksTextLayoutData = new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1); tasksTextLayoutData.heightHint = 50; this.tasksText.setLayoutData(tasksTextLayoutData); this.tasksText.addModifyListener(new DialogUpdater()); } private void createWorkingDirectorySelectionControl(Composite container) { this.workingDirectoryText = new Text(container, SWT.SINGLE | SWT.BORDER); this.workingDirectoryText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); this.workingDirectoryText.addModifyListener(new DialogUpdater()); Composite buttonContainer = new Composite(container, SWT.NONE); GridLayout buttonContainerLayout = new GridLayout(3, false); buttonContainerLayout.marginHeight = 1; buttonContainerLayout.marginWidth = 0; buttonContainer.setLayout(buttonContainerLayout); buttonContainer.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END)); Button browseWorkspaceButton = new Button(buttonContainer, SWT.NONE); browseWorkspaceButton.setText(LaunchMessages.Button_Label_BrowseWorkspace); browseWorkspaceButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { ListDialog projectDialog = new ListDialog(getShell()); projectDialog.setTitle(LaunchMessages.Title_BrowseWorkspaceDialog); projectDialog.setContentProvider(new ArrayContentProvider() { @Override public Object[] getElements(Object input) { return findAllGradleProjects(); } }); projectDialog.setLabelProvider(new WorkbenchLabelProvider()); projectDialog.setInput(ResourcesPlugin.getWorkspace().getRoot()); // open the dialog and put the path of the selected project into the working directory text field projectDialog.open(); Object[] result = projectDialog.getResult(); if (result != null) { if (result.length > 0) { String locationInExpression = ExpressionUtils.encodeWorkspaceLocation((IProject) result[0]); ProjectTab.this.workingDirectoryText.setText(locationInExpression); } else { ProjectTab.this.workingDirectoryText.setText(""); //$NON-NLS-1$ } } } }); Button browseFilesystemButton = new Button(buttonContainer, SWT.NONE); browseFilesystemButton.setText(LaunchMessages.Button_Label_BrowseFilesystem); browseFilesystemButton.addSelectionListener(new DirectoryDialogSelectionListener(getShell(), this.workingDirectoryText, LaunchMessages.Title_BrowseFileSystemDialog)); Button selectVariableButton = new Button(buttonContainer, SWT.NONE); selectVariableButton.setText(LaunchMessages.Button_Label_SelectVariables); selectVariableButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { StringVariableSelectionDialog dialog = new StringVariableSelectionDialog(getShell()); dialog.open(); String variable = dialog.getVariableExpression(); if (variable != null) { ProjectTab.this.workingDirectoryText.insert(variable); } } }); } private IProject[] findAllGradleProjects() { return FluentIterable.from(CorePlugin.workspaceOperations().getAllProjects()).filter(new Predicate<IProject>() { @Override public boolean apply(IProject project) { return GradleProjectNature.isPresentOn(project); } }).toArray(IProject.class); } private void createBuildExecutionControl(Composite container) { this.showExecutionViewCheckbox = new Button(container, SWT.CHECK); this.showExecutionViewCheckbox.setText(CoreMessages.BuildExecution_Label_ShowExecutionView); this.showExecutionViewCheckbox.addSelectionListener( new DialogUpdater()); this.showConsoleViewCheckbox = new Button(container, SWT.CHECK); this.showConsoleViewCheckbox.setText(CoreMessages.BuildExecution_Label_ShowConsoleView); this.showConsoleViewCheckbox.addSelectionListener(new DialogUpdater()); } @Override public void initializeFrom(ILaunchConfiguration configuration) { GradleRunConfigurationAttributes configurationAttributes = GradleRunConfigurationAttributes.from(configuration); this.tasksText.setText(CollectionsUtils.joinWithSpace(configurationAttributes.getTasks())); this.workingDirectoryText.setText(Strings.nullToEmpty(configurationAttributes.getWorkingDirExpression())); this.showExecutionViewCheckbox.setSelection(configurationAttributes.isShowExecutionView()); this.showConsoleViewCheckbox.setSelection(configurationAttributes.isShowConsoleView()); } @Override public void performApply(ILaunchConfigurationWorkingCopy configuration) { GradleRunConfigurationAttributes.applyTasks(CollectionsUtils.splitBySpace(this.tasksText.getText()), configuration); GradleRunConfigurationAttributes.applyWorkingDirExpression(this.workingDirectoryText.getText(), configuration); GradleRunConfigurationAttributes.applyShowExecutionView(this.showExecutionViewCheckbox.getSelection(), configuration); GradleRunConfigurationAttributes.applyShowConsoleView(this.showConsoleViewCheckbox.getSelection(), configuration); } @SuppressWarnings("Contract") @Override public boolean isValid(ILaunchConfiguration configuration) { String workingDirectoryExpression = this.workingDirectoryText.getText(); String workingDirectoryResolved; try { workingDirectoryResolved = ExpressionUtils.decode(workingDirectoryExpression); } catch (CoreException e) { setErrorMessage(NLS.bind(LaunchMessages.ErrorMessage_CannotResolveExpression_0, workingDirectoryExpression)); return false; } File workingDir = FileUtils.getAbsoluteFile(workingDirectoryResolved).orNull(); Optional<String> error = this.workingDirValidator.validate(workingDir); setErrorMessage(error.orNull()); return !error.isPresent(); } @Override public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { // leave the controls empty } /** * Listener implementation to update the dialog buttons and messages. */ private class DialogUpdater extends SelectionAdapter implements ModifyListener { @Override public void widgetSelected(SelectionEvent e) { updateLaunchConfigurationDialog(); } @Override public void modifyText(ModifyEvent e) { updateLaunchConfigurationDialog(); } } }