Java tutorial
/* * 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 & Dont Csiks (Gradle Inc.) - initial API and implementation and initial documentation */ package org.eclipse.buildship.ui.launch; import java.util.List; import org.gradle.util.GradleVersion; import com.google.common.base.Function; import com.google.common.base.Optional; import com.google.common.base.Strings; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; import com.gradleware.tooling.toolingutils.binding.Validator; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.ui.AbstractLaunchConfigurationTab; 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.events.SelectionListener; import org.eclipse.swt.graphics.Font; 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.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Text; import org.eclipse.buildship.core.CorePlugin; import org.eclipse.buildship.core.GradlePluginsRuntimeException; import org.eclipse.buildship.core.i18n.CoreMessages; import org.eclipse.buildship.core.launch.GradleRunConfigurationAttributes; import org.eclipse.buildship.core.util.gradle.GradleDistributionValidator; import org.eclipse.buildship.core.util.gradle.GradleDistributionWrapper; import org.eclipse.buildship.core.util.gradle.GradleDistributionWrapper.DistributionType; import org.eclipse.buildship.core.util.gradle.PublishedGradleVersionsWrapper; import org.eclipse.buildship.ui.PluginImage.ImageState; import org.eclipse.buildship.ui.PluginImages; import org.eclipse.buildship.ui.i18n.UiMessages; import org.eclipse.buildship.ui.util.file.DirectoryDialogSelectionListener; import org.eclipse.buildship.ui.util.font.FontUtils; import org.eclipse.buildship.ui.util.selection.Enabler; import org.eclipse.buildship.ui.util.widget.ButtonUtils; import org.eclipse.buildship.ui.util.widget.UiBuilder; /** * Specifies the Gradle distribution to apply when executing tasks via the run configurations. */ public final class GradleDistributionTab extends AbstractLaunchConfigurationTab { private final Font defaultFont; private final UiBuilder.UiBuilderFactory builderFactory; private final Validator<GradleDistributionWrapper> gradleDistributionValidator; private final PublishedGradleVersionsWrapper publishedGradleVersions; private Text localInstallationDirText; private Text remoteDistributionUriText; private Combo gradleVersionCombo; private Button useAutomaticOption; private Button useGradleWrapperOption; private Button useLocalInstallationDirOption; private Button useRemoteDistributionUriOption; private Button useGradleVersionOption; private List<Button> allRadioButtons; private final SelectionListener optionSelectionChangedListener; private final ModifyListener textChangedListener; // if different configurations are loaded we change radio buttons and text fields. this // generates several change events which trigger the launch config to update and leads to // an inconsistent state. to resolve that, we disable the launch config update in when the // initializeFrom() method is called private boolean disableUpdateDialog = false; public GradleDistributionTab() { this.defaultFont = FontUtils.getDefaultDialogFont(); this.builderFactory = new UiBuilder.UiBuilderFactory(this.defaultFont); this.gradleDistributionValidator = GradleDistributionValidator.gradleDistributionValidator(); this.publishedGradleVersions = CorePlugin.publishedGradleVersions(); this.optionSelectionChangedListener = new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (!GradleDistributionTab.this.disableUpdateDialog) { updateLaunchConfigurationDialog(); } } }; this.textChangedListener = new ModifyListener() { @Override public void modifyText(ModifyEvent e) { if (!GradleDistributionTab.this.disableUpdateDialog) { updateLaunchConfigurationDialog(); } } }; } @Override public String getName() { return LaunchMessages.Tab_Name_GradleDistribution; } @Override public Image getImage() { return PluginImages.RUN_CONFIG_GRADLE_DISTRIBUTION.withState(ImageState.ENABLED).getImage(); } @Override public void createControl(Composite parent) { Composite page = new Composite(parent, SWT.NONE); GridLayout layout = new GridLayout(1, false); page.setLayout(layout); setControl(page); Group gradleDistributionGroup = createGroup(page, CoreMessages.RunConfiguration_Label_GradleDistribution + ":"); createGradleDistributionSelectionControl(gradleDistributionGroup); } private Group createGroup(Composite parent, String groupName) { Group group = new Group(parent, SWT.NONE); group.setText(groupName); group.setLayout(new GridLayout(3, false)); group.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); return group; } private void createGradleDistributionSelectionControl(Group container) { // first option: use the same distribution that was used for project import this.useAutomaticOption = this.builderFactory.newRadio(container).alignLeft() .text(CoreMessages.GradleDistribution_Label_FromImportSettings).control(); this.useAutomaticOption.setToolTipText(CoreMessages.GradleDistribution_Label_FromImportSettings_Tooltip); this.useAutomaticOption.setSelection(true); this.builderFactory.span(container); this.builderFactory.span(container); // second option: gradle wrapper this.useGradleWrapperOption = this.builderFactory.newRadio(container).alignLeft() .text(CoreMessages.GradleDistribution_Label_GradleWrapper).control(); this.builderFactory.span(container); this.builderFactory.span(container); // third option: local installation directory this.useLocalInstallationDirOption = this.builderFactory.newRadio(container).alignLeft() .text(CoreMessages.GradleDistribution_Label_LocalInstallationDirectory).control(); this.localInstallationDirText = this.builderFactory.newText(container).alignFillHorizontal().disabled() .control(); Button localInstallationDirBrowseButton = this.builderFactory.newButton(container).alignLeft().disabled() .text(UiMessages.Button_Label_Browse).control(); localInstallationDirBrowseButton.addSelectionListener( new DirectoryDialogSelectionListener(container.getShell(), this.localInstallationDirText, CoreMessages.GradleDistribution_Label_LocalInstallationDirectory)); // fourth option: remote distribution installation this.useRemoteDistributionUriOption = this.builderFactory.newRadio(container).alignLeft() .text(CoreMessages.GradleDistribution_Label_RemoteDistributionUri).control(); this.remoteDistributionUriText = this.builderFactory.newText(container).alignFillHorizontal().disabled() .control(); this.builderFactory.span(container); // fifth option: gradle version this.useGradleVersionOption = this.builderFactory.newRadio(container).alignLeft() .text(CoreMessages.GradleDistribution_Label_SpecificGradleVersion).control(); this.gradleVersionCombo = this.builderFactory.newCombo(container).alignLeft().disabled().control(); this.gradleVersionCombo.setSize(150, this.gradleVersionCombo.getSize().y); this.gradleVersionCombo.setItems(getGradleVersions()); this.builderFactory.span(container); // update launch configuration when the content of the widgets are changing this.localInstallationDirText.addModifyListener(this.textChangedListener); this.remoteDistributionUriText.addModifyListener(this.textChangedListener); this.gradleVersionCombo.addModifyListener(this.textChangedListener); // update the enabled/disabled state when the currently selected radio is changing this.useAutomaticOption.addSelectionListener(this.optionSelectionChangedListener); this.useGradleWrapperOption.addSelectionListener(this.optionSelectionChangedListener); this.useLocalInstallationDirOption.addSelectionListener(this.optionSelectionChangedListener); this.useRemoteDistributionUriOption.addSelectionListener(this.optionSelectionChangedListener); this.useGradleVersionOption.addSelectionListener(this.optionSelectionChangedListener); // update the enabled/disabled state when the currently selected radio is changing new Enabler(this.useAutomaticOption).enables(); new Enabler(this.useGradleWrapperOption).enables(); new Enabler(this.useLocalInstallationDirOption).enables(this.localInstallationDirText, localInstallationDirBrowseButton); new Enabler(this.useRemoteDistributionUriOption).enables(this.remoteDistributionUriText); new Enabler(this.useGradleVersionOption).enables(this.gradleVersionCombo); // save all created radio buttons in a list this.allRadioButtons = ImmutableList.of(this.useAutomaticOption, this.useGradleWrapperOption, this.useLocalInstallationDirOption, this.useRemoteDistributionUriOption, this.useGradleVersionOption); } private String[] getGradleVersions() { return FluentIterable.from(this.publishedGradleVersions.getVersions()) .transform(new Function<GradleVersion, String>() { @Override public String apply(GradleVersion gradleVersion) { return gradleVersion.getVersion(); } }).toArray(String.class); } @Override public void initializeFrom(ILaunchConfiguration configuration) { // do not trigger save configuration (through events) when initializing the values this.disableUpdateDialog = true; try { GradleRunConfigurationAttributes configurationAttributes = GradleRunConfigurationAttributes .from(configuration); if (configurationAttributes.isUseGradleDistributionFromImport()) { setSelectionToAutomatic(); } else { setSelection(GradleDistributionWrapper.from(configurationAttributes.getGradleDistribution())); } } finally { this.disableUpdateDialog = false; } } private void setSelectionToAutomatic() { resetValues(); updateSelectedState(this.useAutomaticOption, this.allRadioButtons); } private void resetValues() { this.localInstallationDirText.setText(""); this.remoteDistributionUriText.setText(""); if (this.gradleVersionCombo.getItemCount() > 0) { this.gradleVersionCombo.select(0); } else { this.gradleVersionCombo.setText(""); } } private void setSelection(GradleDistributionWrapper wrapper) { resetValues(); // set correct enabled state and specific configuration values DistributionType type = wrapper.getType(); String configuration = Strings.nullToEmpty(wrapper.getConfiguration()); switch (type) { case WRAPPER: updateSelectedState(this.useGradleWrapperOption, this.allRadioButtons); break; case LOCAL_INSTALLATION: updateSelectedState(this.useLocalInstallationDirOption, this.allRadioButtons); this.localInstallationDirText.setText(configuration); break; case REMOTE_DISTRIBUTION: updateSelectedState(this.useRemoteDistributionUriOption, this.allRadioButtons); this.remoteDistributionUriText.setText(configuration); break; case VERSION: updateSelectedState(this.useGradleVersionOption, this.allRadioButtons); updateVersionSelection(configuration); break; default: throw new GradlePluginsRuntimeException("Unrecognized Gradle distribution type: " + type); //$NON-NLS-1$ } } private void updateSelectedState(Button selectedRadioButton, List<Button> allRadioButtons) { for (Button radioButton : allRadioButtons) { boolean selected = radioButton.equals(selectedRadioButton); ButtonUtils.setSelectionAndFireEvent(radioButton, selected); if (selected) { radioButton.setFocus(); } } } private void updateVersionSelection(String version) { // select the version in the combo box if the exist for (int i = 0; i < this.gradleVersionCombo.getItemCount(); ++i) { if (this.gradleVersionCombo.getItem(i).equals(version)) { this.gradleVersionCombo.select(i); return; } } // otherwise, create a new entry in the combo and select it int index = this.gradleVersionCombo.getItemCount(); this.gradleVersionCombo.add(version, index); this.gradleVersionCombo.select(index); } @Override public void performApply(ILaunchConfigurationWorkingCopy configuration) { if (this.useAutomaticOption.getSelection()) { GradleRunConfigurationAttributes.applyUseGradleDistributionFromImport(true, configuration); } else { GradleRunConfigurationAttributes.applyUseGradleDistributionFromImport(false, configuration); GradleRunConfigurationAttributes.applyGradleDistribution(getSelection().toGradleDistribution(), configuration); } } @Override public boolean isValid(ILaunchConfiguration launchConfig) { if (!this.useAutomaticOption.getSelection()) { GradleDistributionWrapper gradleDistribution = getSelection(); Optional<String> error = this.gradleDistributionValidator.validate(gradleDistribution); setErrorMessage(error.orNull()); return !error.isPresent(); } else { return true; } } private GradleDistributionWrapper getSelection() { if (this.useGradleWrapperOption.getSelection()) { return GradleDistributionWrapper.from(DistributionType.WRAPPER, null); } else if (this.useLocalInstallationDirOption.getSelection()) { return GradleDistributionWrapper.from(DistributionType.LOCAL_INSTALLATION, this.localInstallationDirText.getText()); } else if (this.useRemoteDistributionUriOption.getSelection()) { return GradleDistributionWrapper.from(DistributionType.REMOTE_DISTRIBUTION, this.remoteDistributionUriText.getText()); } else if (this.useGradleVersionOption.getSelection()) { return getGradleDistributionWrapper(); } else { throw new IllegalStateException("No Gradle distribution selected."); } } private GradleDistributionWrapper getGradleDistributionWrapper() { int selectionIndex = this.gradleVersionCombo.getSelectionIndex(); return GradleDistributionWrapper.from(DistributionType.VERSION, Strings.emptyToNull( selectionIndex == -1 || !Strings.isNullOrEmpty(this.gradleVersionCombo.getText()) ? this.gradleVersionCombo.getText() : this.gradleVersionCombo.getItem(selectionIndex))); } @Override public void setDefaults(ILaunchConfigurationWorkingCopy configuration) { // leave the controls empty } @Override public void dispose() { this.defaultFont.dispose(); super.dispose(); } }