diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/CompositeProperties.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/CompositeProperties.java new file mode 100644 index 0000000000..e2532dfa5e --- /dev/null +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/CompositeProperties.java @@ -0,0 +1,242 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ +package org.eclipse.buildship.core; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Properties; + +import org.eclipse.buildship.core.internal.CorePlugin; +import org.eclipse.buildship.core.internal.configuration.CompositeConfiguration; + +public class CompositeProperties { + + private final List projectList; + private final Boolean overwriteWorkspaceSettings; + private final GradleDistribution distribution; + private final File gradleUserHome; + private final File javaHome; + private final Boolean buildScansEnabled; + private final Boolean offlineMode; + private final Boolean autoSync; + private final List arguments; + private final List jvmArguments; + private final Boolean showConsoleView; + private final Boolean showExecutionsView; + private final Boolean useProjectAsRoot; + private final File rootProject; + + private static final String KEY_COMPOSITE_PROJECTS = "composite.projects"; + private static final String KEY_OVERWRITE_WORKSPACE_SETTINGS = "override.workspace.settings"; + private static final String KEY_DISTRIBUTION = "connection.gradle.distribution"; + private static final String KEY_GRADLE_USER_HOME = "gradle.user.home"; + private static final String KEY_JAVA_HOME = "java.home"; + private static final String KEY_BUILD_SCANS_ENABLED = "build.scans.enabled"; + private static final String KEY_OFFLINE_MODE = "offline.mode"; + private static final String KEY_AUTO_SYNC = "auto.sync"; + private static final String KEY_ARGUMENTS = "arguments"; + private static final String KEY_JVM_ARGUMENTS = "jvm.arguments"; + private static final String KEY_SHOW_CONSOLE_VIEW = "show.console.view"; + private static final String KEY_SHOW_EXECUTION_VIEW = "show.executions.view"; + private static final String KEY_USE_PROJECT_AS_ROOT = "project.as.root"; + private static final String KEY_ROOT_PROJECT = "root.project"; + + private CompositeProperties(CompositePropertiesBuilder builder) { + this.projectList = builder.projectList; + this.overwriteWorkspaceSettings = builder.overrideWorkspaceConfiguration; + this.distribution = builder.gradleDistribution == null ? GradleDistribution.fromBuild() : builder.gradleDistribution; + this.gradleUserHome = builder.gradleUserHome == null ? null: builder.gradleUserHome; + this.javaHome = builder.javaHome == null ? null : builder.javaHome; + this.buildScansEnabled = builder.buildScansEnabled; + this.offlineMode = builder.offlineMode; + this.autoSync = builder.autoSync; + this.arguments = builder.arguments == null ? Collections.emptyList() : builder.arguments; + this.jvmArguments = builder.jvmArguments == null ? Collections.emptyList() : builder.jvmArguments; + this.showConsoleView = builder.showConsoleView; + this.showExecutionsView = builder.showExecutionsView; + this.useProjectAsRoot = builder.projectAsCompositeRoot; + this.rootProject = builder.rootProject == null ? null: builder.rootProject; + } + + public static CompositePropertiesReader getCompositeReaderForFile(String compositeName) { + return new CompositePropertiesReader(compositeName); + } + + public static CompositePropertiesBuilder create() { + return new CompositePropertiesBuilder(); + } + + public static CompositePropertiesBuilder forCompositeConfiguration(CompositeConfiguration compositeConf) { + return new CompositePropertiesBuilder(compositeConf); + } + + public Properties toProperties() { + Properties prop = new Properties(); + + prop.put(KEY_COMPOSITE_PROJECTS, this.projectList.toString()); + prop.put(KEY_OVERWRITE_WORKSPACE_SETTINGS, this.overwriteWorkspaceSettings.toString()); + prop.put(KEY_DISTRIBUTION, this.distribution == null ? GradleDistribution.fromBuild() : this.distribution.toString()); + prop.put(KEY_GRADLE_USER_HOME, this.gradleUserHome == null ? "" : this.gradleUserHome.getAbsolutePath()); + prop.put(KEY_JAVA_HOME, this.javaHome == null ? "" : this.javaHome.getAbsolutePath()); + prop.put(KEY_BUILD_SCANS_ENABLED, this.buildScansEnabled.toString()); + prop.put(KEY_OFFLINE_MODE, this.offlineMode.toString()); + prop.put(KEY_AUTO_SYNC, this.autoSync.toString()); + prop.put(KEY_ARGUMENTS, removeBrackets(this.arguments.toString())); + prop.put(KEY_JVM_ARGUMENTS, removeBrackets(this.jvmArguments.toString())); + prop.put(KEY_SHOW_CONSOLE_VIEW, this.showConsoleView.toString()); + prop.put(KEY_SHOW_EXECUTION_VIEW, this.showExecutionsView.toString()); + prop.put(KEY_USE_PROJECT_AS_ROOT, this.useProjectAsRoot.toString()); + prop.put(KEY_ROOT_PROJECT, this.rootProject == null ? "" : this.rootProject.toString()); + return prop; + } + + private String removeBrackets(String arguments) { + return arguments.replace("[", "").replace("]", "").replace(",", ""); + } + + public static final class CompositePropertiesBuilder { + + public List projectList; + private boolean overrideWorkspaceConfiguration = false; + private GradleDistribution gradleDistribution; + private File gradleUserHome = null; + private File javaHome = null; + private boolean buildScansEnabled = false; + private boolean offlineMode = false; + private boolean autoSync = false; + private List arguments = new ArrayList<>(); + private List jvmArguments = new ArrayList<>(); + private boolean showConsoleView = true; + private boolean showExecutionsView = true; + private boolean projectAsCompositeRoot = false; + private File rootProject = null; + + private CompositePropertiesBuilder() { + } + + public CompositePropertiesBuilder(CompositeConfiguration compositeConf) { + this.projectList = compositeConf.getIncludedBuilds(); + this.overrideWorkspaceConfiguration = compositeConf.getBuildConfiguration().isOverrideWorkspaceSettings(); + this.gradleDistribution = compositeConf.getBuildConfiguration().getGradleDistribution(); + this.gradleUserHome = compositeConf.getBuildConfiguration().getGradleUserHome(); + this.javaHome = compositeConf.getBuildConfiguration().getJavaHome(); + this.buildScansEnabled = compositeConf.getBuildConfiguration().isBuildScansEnabled(); + this.offlineMode = compositeConf.getBuildConfiguration().isOfflineMode(); + this.autoSync = compositeConf.getBuildConfiguration().isAutoSync(); + this.arguments = compositeConf.getBuildConfiguration().getArguments(); + this.jvmArguments = compositeConf.getBuildConfiguration().getJvmArguments(); + this.showConsoleView = compositeConf.getBuildConfiguration().isShowConsoleView(); + this.showExecutionsView = compositeConf.getBuildConfiguration().isShowExecutionsView(); + this.projectAsCompositeRoot = compositeConf.projectAsCompositeRoot(); + this.rootProject = compositeConf.getBuildConfiguration().getRootProjectDirectory(); + + } + + public CompositePropertiesBuilder projectList(List projectList) { + this.projectList = projectList; + return this; + } + + public CompositePropertiesBuilder overrideWorkspaceConfiguration(boolean overrideWorkspaceConfiguration) { + this.overrideWorkspaceConfiguration = overrideWorkspaceConfiguration; + return this; + } + + public CompositePropertiesBuilder gradleDistribution(GradleDistribution gradleDistribution) { + this.gradleDistribution = gradleDistribution; + return this; + } + + public CompositePropertiesBuilder gradleUserHome(File gradleUserHome) { + this.gradleUserHome = gradleUserHome; + return this; + } + + public CompositePropertiesBuilder javaHome(File javaHome) { + this.javaHome = javaHome; + return this; + } + + public CompositePropertiesBuilder buildScansEnabled(boolean buildScansEnabled) { + this.buildScansEnabled = buildScansEnabled; + return this; + } + + public CompositePropertiesBuilder offlineMode(boolean offlineMode) { + this.offlineMode = offlineMode; + return this; + } + + public CompositePropertiesBuilder autoSync(boolean autoSync) { + this.autoSync = autoSync; + return this; + } + + public CompositePropertiesBuilder arguments(List arguments) { + this.arguments = arguments; + return this; + } + + public CompositePropertiesBuilder jvmArguments(List jvmArguments) { + this.jvmArguments = jvmArguments; + return this; + } + + public CompositePropertiesBuilder showConsoleView(boolean showConsoleView) { + this.showConsoleView = showConsoleView; + return this; + } + + public CompositePropertiesBuilder showExecutionsView(boolean showExecutionsView) { + this.showExecutionsView = showExecutionsView; + return this; + } + + public CompositePropertiesBuilder projectAsCompositeRoot(boolean projectAsCompositeRoot) { + this.projectAsCompositeRoot = projectAsCompositeRoot; + return this; + } + + public CompositePropertiesBuilder rootProject(File rootProject) { + this.rootProject = rootProject; + return this; + } + + public CompositeProperties build() { + return new CompositeProperties(this); + } + } + + public static final class CompositePropertiesReader { + private Properties compositeProperties = new Properties(); + + private CompositePropertiesReader(String compositeName) { + File compositeDirectory = CorePlugin.getInstance().getStateLocation().append("workspace-composites").append(compositeName).toFile(); + try { + FileInputStream input= new FileInputStream(compositeDirectory); + this.compositeProperties = new Properties(); + this.compositeProperties.load(input); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public boolean getProjectAsCompositeRoot() { + return Boolean.valueOf(this.compositeProperties.get(KEY_USE_PROJECT_AS_ROOT).toString()); + } + + //If needed implement reader for other properties + + } +} diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/BuildConfigurationPersistence.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/BuildConfigurationPersistence.java index 5bbdcc6d22..ac3a75b3ec 100644 --- a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/BuildConfigurationPersistence.java +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/BuildConfigurationPersistence.java @@ -45,6 +45,8 @@ final class BuildConfigurationPersistence { private static final String PREF_KEY_JVM_ARGUMENTS = "jvm.arguments"; private static final String PREF_KEY_SHOW_CONSOLE_VIEW = "show.console.view"; private static final String PREF_KEY_SHOW_EXECUTIONS_VIEW = "show.executions.view"; + private static final String PREF_KEY_USE_PROJECT_AS_ROOT = "project.as.root"; + private static final String PREF_KEY_ROOT_PROJECT = "root.project"; public BuildConfigurationProperties readBuildConfiguratonProperties(IProject project) { Preconditions.checkNotNull(project); @@ -58,7 +60,13 @@ public BuildConfigurationProperties readBuildConfiguratonProperties(File project return readPreferences(preferences, projectDir); } - public void saveBuildConfiguration(IProject project, BuildConfigurationProperties properties) { + public DefaultBuildConfigurationProperties readCompositeBuildProperties(File compositeDir) { + Preconditions.checkNotNull(compositeDir); + PreferenceStore preferences = PreferenceStore.forPreferenceFile(compositeDir); + return readCompositePreferences(preferences, compositeDir); + } + + public void saveBuildConfiguration(IProject project, DefaultBuildConfigurationProperties properties) { Preconditions.checkNotNull(project); Preconditions.checkNotNull(properties); PreferenceStore preferences = PreferenceStore.forProjectScope(project, PREF_NODE); @@ -147,25 +155,73 @@ private static BuildConfigurationProperties readPreferences(PreferenceStore pref boolean showConsoleView = preferences.readBoolean(PREF_KEY_SHOW_CONSOLE_VIEW, false); boolean showExecutionsView = preferences.readBoolean(PREF_KEY_SHOW_EXECUTIONS_VIEW, false); - return new BuildConfigurationProperties(rootDir, distribution, gradleUserHome, javaHome, overrideWorkspaceSettings, buildScansEnabled, offlineMode, autoSync, arguments, jvmArguments, showConsoleView, showExecutionsView); - } - - private static void savePreferences(BuildConfigurationProperties properties, PreferenceStore preferences) { - GradleDistribution gradleDistribution = properties.getGradleDistribution(); - String gradleDistributionString = gradleDistribution == null ? GradleDistribution.fromBuild().toString() : gradleDistribution.toString(); - preferences.write(PREF_KEY_CONNECTION_GRADLE_DISTRIBUTION, gradleDistributionString); - preferences.write(PREF_KEY_GRADLE_USER_HOME, toPortableString(properties.getGradleUserHome())); - preferences.write(PREF_KEY_JAVA_HOME, toPortableString(properties.getJavaHome())); - preferences.writeBoolean(PREF_KEY_OVERRIDE_WORKSPACE_SETTINGS, properties.isOverrideWorkspaceSettings()); - preferences.writeBoolean(PREF_KEY_BUILD_SCANS_ENABLED, properties.isBuildScansEnabled()); - preferences.writeBoolean(PREF_KEY_OFFLINE_MODE, properties.isOfflineMode()); - preferences.writeBoolean(PREF_KEY_AUTO_SYNC, properties.isAutoSync()); - List arguments = properties.getArguments(); - preferences.write(PREF_KEY_ARGUMENTS, arguments == null ? "" : Joiner.on(' ').join(arguments)); - List jvmArguments = properties.getJvmArguments(); - preferences.write(PREF_KEY_JVM_ARGUMENTS, jvmArguments == null ? "" : Joiner.on(' ').join(jvmArguments)); - preferences.writeBoolean(PREF_KEY_SHOW_CONSOLE_VIEW, properties.isShowConsoleView()); - preferences.writeBoolean(PREF_KEY_SHOW_EXECUTIONS_VIEW, properties.isShowExecutionsView()); + return new DefaultBuildConfigurationProperties(rootDir, distribution, gradleUserHome, javaHome, overrideWorkspaceSettings, buildScansEnabled, offlineMode, autoSync, arguments, jvmArguments, showConsoleView, showExecutionsView); + } + + private DefaultBuildConfigurationProperties readCompositePreferences(PreferenceStore preferences, + File compositePreferencesDir) { + boolean overrideWorkspaceSettings = preferences.readBoolean(PREF_KEY_OVERRIDE_WORKSPACE_SETTINGS, false); + + String distributionString = preferences.readString(PREF_KEY_CONNECTION_GRADLE_DISTRIBUTION, null); + GradleDistribution distribution; + try { + distribution = GradleDistribution.fromString(distributionString); + } catch (RuntimeException ignore) { + distribution = GradleDistribution.fromBuild(); + } + + String gradleUserHomeString = preferences.readString(PREF_KEY_GRADLE_USER_HOME, ""); + File gradleUserHome = gradleUserHomeString.isEmpty() + ? null + : new File(gradleUserHomeString); + String javaHomeString = preferences.readString(PREF_KEY_JAVA_HOME, ""); + File javaHome = javaHomeString.isEmpty() + ? null + : new File(javaHomeString); + + boolean buildScansEnabled = preferences.readBoolean(PREF_KEY_BUILD_SCANS_ENABLED, false); + boolean offlineMode = preferences.readBoolean(PREF_KEY_OFFLINE_MODE, false); + boolean autoSync = preferences.readBoolean(PREF_KEY_AUTO_SYNC, false); + List arguments = Lists.newArrayList(Splitter.on(' ').omitEmptyStrings().split(preferences.readString(PREF_KEY_ARGUMENTS, ""))); + List jvmArguments = Lists.newArrayList(Splitter.on(' ').omitEmptyStrings().split(preferences.readString(PREF_KEY_JVM_ARGUMENTS, ""))); + boolean showConsoleView = preferences.readBoolean(PREF_KEY_SHOW_CONSOLE_VIEW, false); + boolean showExecutionsView = preferences.readBoolean(PREF_KEY_SHOW_EXECUTIONS_VIEW, false); + + File rootDir = new File(preferences.readString(PREF_KEY_ROOT_PROJECT, compositePreferencesDir.getAbsolutePath())); + + return new DefaultBuildConfigurationProperties(rootDir, distribution, gradleUserHome, javaHome, overrideWorkspaceSettings, buildScansEnabled, offlineMode, autoSync, arguments, jvmArguments, showConsoleView, showExecutionsView); + } + + private static void savePreferences(DefaultBuildConfigurationProperties properties, PreferenceStore preferences) { + if (properties.isOverrideWorkspaceSettings()) { + GradleDistribution gradleDistribution = properties.getGradleDistribution(); + String gradleDistributionString = gradleDistribution == null ? GradleDistribution.fromBuild().toString() : gradleDistribution.toString(); + preferences.write(PREF_KEY_CONNECTION_GRADLE_DISTRIBUTION, gradleDistributionString); + preferences.write(PREF_KEY_GRADLE_USER_HOME, toPortableString(properties.getGradleUserHome())); + preferences.write(PREF_KEY_JAVA_HOME, toPortableString(properties.getJavaHome())); + preferences.writeBoolean(PREF_KEY_OVERRIDE_WORKSPACE_SETTINGS, properties.isOverrideWorkspaceSettings()); + preferences.writeBoolean(PREF_KEY_BUILD_SCANS_ENABLED, properties.isBuildScansEnabled()); + preferences.writeBoolean(PREF_KEY_OFFLINE_MODE, properties.isOfflineMode()); + preferences.writeBoolean(PREF_KEY_AUTO_SYNC, properties.isAutoSync()); + List arguments = properties.getArguments(); + preferences.write(PREF_KEY_ARGUMENTS, arguments == null ? "" : Joiner.on(' ').join(arguments)); + List jvmArguments = properties.getJvmArguments(); + preferences.write(PREF_KEY_JVM_ARGUMENTS, jvmArguments == null ? "" : Joiner.on(' ').join(jvmArguments)); + preferences.writeBoolean(PREF_KEY_SHOW_CONSOLE_VIEW, properties.isShowConsoleView()); + preferences.writeBoolean(PREF_KEY_SHOW_EXECUTIONS_VIEW, properties.isShowExecutionsView()); + } else { + preferences.delete(PREF_KEY_CONNECTION_GRADLE_DISTRIBUTION); + preferences.delete(PREF_KEY_GRADLE_USER_HOME); + preferences.delete(PREF_KEY_JAVA_HOME); + preferences.delete(PREF_KEY_OVERRIDE_WORKSPACE_SETTINGS); + preferences.delete(PREF_KEY_BUILD_SCANS_ENABLED); + preferences.delete(PREF_KEY_OFFLINE_MODE); + preferences.delete(PREF_KEY_AUTO_SYNC); + preferences.delete(PREF_KEY_ARGUMENTS); + preferences.delete(PREF_KEY_JVM_ARGUMENTS); + preferences.delete(PREF_KEY_SHOW_CONSOLE_VIEW); + preferences.delete(PREF_KEY_SHOW_EXECUTIONS_VIEW); + } preferences.flush(); } diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/CompositeConfiguration.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/CompositeConfiguration.java new file mode 100644 index 0000000000..d89b1e1139 --- /dev/null +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/CompositeConfiguration.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.core.internal.configuration; + +import java.io.File; +import java.util.List; + +/** + * Configuration for a workspace composite in a Gradle build. + * + * @author Sebastian Kuzniarz + */ +public interface CompositeConfiguration { + + String getCompositeName(); + + List getIncludedBuilds(); + + BuildConfiguration getBuildConfiguration(); + + Boolean projectAsCompositeRoot(); +} diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/ConfigurationManager.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/ConfigurationManager.java index 436eece597..de6824404a 100644 --- a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/ConfigurationManager.java +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/ConfigurationManager.java @@ -49,7 +49,11 @@ BuildConfiguration createBuildConfiguration(File rootProjectDirectory, boolean o void deleteProjectConfiguration(IProject project); - RunConfiguration loadRunConfiguration(ILaunchConfiguration configuration); + CompositeConfiguration loadCompositeConfiguration(String workingSetName); + + void saveCompositeConfiguration(CompositeConfiguration compConf); + + RunConfiguration loadRunConfiguration(ILaunchConfiguration launchConfiguration); TestRunConfiguration loadTestRunConfiguration(ILaunchConfiguration configuration); diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultCompositeConfiguration.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultCompositeConfiguration.java new file mode 100644 index 0000000000..661d054c52 --- /dev/null +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultCompositeConfiguration.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.core.internal.configuration; + +import java.io.File; +import java.util.List; + +import com.google.common.base.Objects; +import com.google.common.base.Preconditions; + +public class DefaultCompositeConfiguration implements CompositeConfiguration { + + private final String compositeName; + private final List projectList; + private final BuildConfiguration buildConfiguration; + private final Boolean projectAsCompositeRoot; + + public DefaultCompositeConfiguration(String compositeName, List projectList, BuildConfiguration buildConfiguration, Boolean projectAsCompositeRoot) { + this.compositeName = Preconditions.checkNotNull(compositeName); + this.projectList = Preconditions.checkNotNull(projectList); + this.buildConfiguration = Preconditions.checkNotNull(buildConfiguration); + this.projectAsCompositeRoot = Preconditions.checkNotNull(projectAsCompositeRoot); + } + + @Override + public String getCompositeName() { + return this.compositeName; + } + + @Override + public List getIncludedBuilds() { + return this.projectList; + } + + @Override + public BuildConfiguration getBuildConfiguration() { + return this.buildConfiguration; + } + + @Override + public Boolean projectAsCompositeRoot() { + return this.projectAsCompositeRoot; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof DefaultCompositeConfiguration) { + DefaultCompositeConfiguration other = (DefaultCompositeConfiguration) obj; + return Objects.equal(this.compositeName, other.compositeName) + && Objects.equal(this.projectList, other.projectList) + && Objects.equal(this.buildConfiguration, other.buildConfiguration) + && Objects.equal(this.projectAsCompositeRoot, other.projectAsCompositeRoot); + } + return false; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.compositeName, + this.buildConfiguration); + } + +} diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultConfigurationManager.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultConfigurationManager.java index 3f963745b2..bfd88018c4 100644 --- a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultConfigurationManager.java +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/configuration/DefaultConfigurationManager.java @@ -10,18 +10,16 @@ package org.eclipse.buildship.core.internal.configuration; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Properties; -import com.google.common.base.Optional; -import com.google.common.base.Preconditions; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IPath; -import org.eclipse.core.runtime.Path; -import org.eclipse.debug.core.ILaunchConfiguration; - +import org.eclipse.buildship.core.CompositeProperties; +import org.eclipse.buildship.core.CompositeProperties.CompositePropertiesReader; import org.eclipse.buildship.core.GradleDistribution; import org.eclipse.buildship.core.internal.CorePlugin; import org.eclipse.buildship.core.internal.CoreTraceScopes; @@ -30,6 +28,13 @@ import org.eclipse.buildship.core.internal.launch.GradleRunConfigurationAttributes; import org.eclipse.buildship.core.internal.launch.GradleTestRunConfigurationAttributes; import org.eclipse.buildship.core.internal.util.file.RelativePathUtils; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; +import org.eclipse.debug.core.ILaunchConfiguration; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; /** * Default implementation for {@link ConfigurationManager}. @@ -91,6 +96,11 @@ public BuildConfiguration loadBuildConfiguration(File rootDir) { return new DefaultBuildConfiguration(buildConfigProperties, loadWorkspaceConfiguration()); } + public BuildConfiguration loadBuildConfigurationForComposite(File fileDir) { + DefaultBuildConfigurationProperties buildConfigProperties = this.buildConfigurationPersistence.readCompositeBuildProperties(fileDir); + return new DefaultBuildConfiguration(buildConfigProperties, loadWorkspaceConfiguration()); + } + @Override public void saveBuildConfiguration(BuildConfiguration configuration) { Preconditions.checkArgument(configuration instanceof DefaultBuildConfiguration, "Unknow configuration type: ", configuration.getClass()); @@ -181,6 +191,42 @@ public void deleteProjectConfiguration(IProject project) { this.buildConfigurationPersistence.deletePathToRoot(project.getLocation().toFile()); } } + + private File getCompositePropertiesFile(String compositeName) { + return CorePlugin.getInstance().getStateLocation().append("workspace-composites").append(compositeName).toFile(); + } + + @Override + public CompositeConfiguration loadCompositeConfiguration(String workingSetName) { + File compositePropertiesFile = getCompositePropertiesFile(workingSetName); + BuildConfiguration buildConfig = loadBuildConfigurationForComposite(compositePropertiesFile); + List projectList = loadCompositeProjects(compositePropertiesFile); + CompositePropertiesReader compositeReader = CompositeProperties.getCompositeReaderForFile(workingSetName); + boolean projectAsCompositeRoot = compositeReader.getProjectAsCompositeRoot(); + return new DefaultCompositeConfiguration(workingSetName, projectList, buildConfig, projectAsCompositeRoot); + } + + private List loadCompositeProjects(File compositePropertiesFile) { + List projects = new ArrayList(); + //TODO (kuzniarz) add File read loop for project list creation + //TODO (kuzniarz) implement load mechanism that reads external gradle projects from properties file. Needs a save mechanism first... + return projects; + } + + @Override + public void saveCompositeConfiguration(CompositeConfiguration compConf) { + try { + FileOutputStream out = new FileOutputStream(getCompositePropertiesFile(compConf.getCompositeName())); + Properties prop = CompositeProperties.forCompositeConfiguration(compConf).build().toProperties(); + prop.store(out, ""); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } @Override public RunConfiguration loadRunConfiguration(ILaunchConfiguration launchConfiguration) { @@ -305,4 +351,5 @@ private static String projectRootToRelativePath(File projectDir, File rootDir) { IPath projectPath = new Path(projectDir.getPath()); return RelativePathUtils.getRelativePath(projectPath, rootProjectPath).toPortableString(); } + } diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/i18n/CoreMessages.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/i18n/CoreMessages.java index f063447196..d55ce584ed 100644 --- a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/i18n/CoreMessages.java +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/i18n/CoreMessages.java @@ -74,6 +74,7 @@ public final class CoreMessages extends NLS { public static String Preference_Label_AutoSyncHover; public static String Preference_Label_ShowConsoleViewHover; public static String Preference_Label_ShowExecutionsViewHover; + public static String Preference_Label_Root_Project; public static String Preference_Label_ModulePath; public static String Preference_Label_ModulePathHover; diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/util/binding/Validators.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/util/binding/Validators.java index ec3ab157d5..3082c19185 100644 --- a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/util/binding/Validators.java +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/util/binding/Validators.java @@ -21,6 +21,7 @@ import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.osgi.util.NLS; +import org.eclipse.buildship.core.internal.CorePlugin; import org.eclipse.buildship.core.internal.i18n.CoreMessages; /** @@ -139,6 +140,39 @@ public boolean apply(IProject project) { }; } + public static Validator uniqueWorkspaceCompositeNameValidator(final String prefix) { + return new Validator() { + + @Override + public Optional validate(String compositeName) { + if (Strings.isNullOrEmpty(compositeName)) { + return Optional.of(NLS.bind(CoreMessages.ErrorMessage_0_MustBeSpecified, prefix)); + } else if (compositeName.equals(compositeName.trim()) == false) { + return Optional.of(NLS.bind(CoreMessages.ErrorMessage_0_IsNotValid, prefix)); + } else if (compositePropertiesFileDoesNotExist(compositeName) && compositeNameAlreadyExistsinWorkspace(compositeName)){ + return Optional.of(NLS.bind(CoreMessages.ErrorMessage_0_AlreadyExists, prefix)); + } else { + return Optional.absent(); + } + } + + private boolean compositePropertiesFileDoesNotExist(String compositeName) { + return CorePlugin.getInstance().getStateLocation() + .append("workspace-composites").append(compositeName).toFile().exists(); + } + + private boolean compositeNameAlreadyExistsinWorkspace(String compositeName) { + File compositePreferencesFolder = CorePlugin.getInstance().getStateLocation().append("workspace-composites").toFile(); + for (File workingSetPreferences : compositePreferencesFolder.listFiles()) { + if (workingSetPreferences.getName().equals(compositeName)) { + return true; + } + } + return false; + } + }; + } + public static Validator validateIfConditionFalse(final Validator validator, final Property condition) { return new Validator() { @Override diff --git a/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/workspace/BuildComposite.java b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/workspace/BuildComposite.java new file mode 100644 index 0000000000..a6a5b59099 --- /dev/null +++ b/org.eclipse.buildship.core/src/main/java/org/eclipse/buildship/core/internal/workspace/BuildComposite.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.core.internal.workspace; + +import java.io.File; + +import org.eclipse.buildship.core.internal.CorePlugin; + +public class BuildComposite { + + public static File preferencesFile(String projectName) { + File preferencesFile = CorePlugin.getInstance().getStateLocation().append("workspace-composites").append(projectName).toFile(); + if (preferencesFile.canWrite()) { + return preferencesFile; + } else { + preferencesFile.getParentFile().mkdir(); + return preferencesFile; + } + } +} diff --git a/org.eclipse.buildship.core/src/main/resources/org/eclipse/buildship/core/internal/i18n/CoreMessages.properties b/org.eclipse.buildship.core/src/main/resources/org/eclipse/buildship/core/internal/i18n/CoreMessages.properties index 3cbdeb0c0a..0f44ca9283 100644 --- a/org.eclipse.buildship.core/src/main/resources/org/eclipse/buildship/core/internal/i18n/CoreMessages.properties +++ b/org.eclipse.buildship.core/src/main/resources/org/eclipse/buildship/core/internal/i18n/CoreMessages.properties @@ -63,5 +63,4 @@ Preference_Label_AutoSync=Automatic Project Synchronization Preference_Label_AutoSyncHover=Automatically start project synchronization in the background when the build script changes. Preference_Label_ShowConsoleViewHover=Makes the Console view visible during task execution Preference_Label_ShowExecutionsViewHover=Makes the Executions view visible during task execution -Preference_Label_ModulePath=Enable module support -Preference_Label_ModulePathHover=Add module dependencies to the modulepath \ No newline at end of file +Preference_Label_Root_Project=Select specific project as composite root diff --git a/org.eclipse.buildship.ui/META-INF/MANIFEST.MF b/org.eclipse.buildship.ui/META-INF/MANIFEST.MF index f7d748703f..3bc45a6f2c 100644 --- a/org.eclipse.buildship.ui/META-INF/MANIFEST.MF +++ b/org.eclipse.buildship.ui/META-INF/MANIFEST.MF @@ -20,9 +20,10 @@ Require-Bundle: org.eclipse.buildship.core, org.eclipse.jdt.ui, org.eclipse.jface.databinding, org.eclipse.jface.text, + org.eclipse.jface, com.ibm.icu, com.google.guava;bundle-version="[32.1.2,33.0.0)", org.gradle.toolingapi;bundle-version="[8.1.1,8.2.0)", org.eclipse.ui.workbench.texteditor Bundle-ActivationPolicy: lazy -Bundle-ClassPath: . +Bundle-ClassPath: . \ No newline at end of file diff --git a/org.eclipse.buildship.ui/css/dark-theme.css b/org.eclipse.buildship.ui/css/dark-theme.css index 3d38c86297..132cb94418 100644 --- a/org.eclipse.buildship.ui/css/dark-theme.css +++ b/org.eclipse.buildship.ui/css/dark-theme.css @@ -1,4 +1,4 @@ -GradleProjectSettingsComposite, GradleDistributionGroup, AdvancedOptionsGroup { +GradleProjectSettingsComposite, GradleDistributionGroup, GradleUserHomeGroup { background-color:#515658; color:#eeeeee; } diff --git a/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj.png b/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj.png new file mode 100644 index 0000000000..1b99f8deac Binary files /dev/null and b/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj.png differ diff --git a/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj@2x.png b/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj@2x.png new file mode 100644 index 0000000000..2f8d2fedca Binary files /dev/null and b/org.eclipse.buildship.ui/icons/full/etool16/new_gradlecomposite_obj@2x.png differ diff --git a/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj.png b/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj.png new file mode 100644 index 0000000000..23bd3f8917 Binary files /dev/null and b/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj.png differ diff --git a/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj@2x.png b/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj@2x.png new file mode 100644 index 0000000000..2fc15e6361 Binary files /dev/null and b/org.eclipse.buildship.ui/icons/full/obj16/gradlecomposite_obj@2x.png differ diff --git a/org.eclipse.buildship.ui/plugin.xml b/org.eclipse.buildship.ui/plugin.xml index 277c850514..efee3c23a7 100644 --- a/org.eclipse.buildship.ui/plugin.xml +++ b/org.eclipse.buildship.ui/plugin.xml @@ -26,6 +26,22 @@ + + + Create a new Gradle workspace composite. + + + + @@ -51,14 +67,27 @@ name="Gradle"> - - - - - + + + + + + Create a new Gradle workspace composite. + + + + + @@ -105,6 +134,12 @@ id="org.eclipse.buildship.ui.views" name="Gradle"> + + @@ -152,6 +187,12 @@ name="Add Gradle Nature" description="Adds the Gradle nature and synchronizes this project as if the Gradle Import wizard had been run on its location."> + + + + @@ -284,6 +329,11 @@ icon="icons/full/elcl16/refresh.png" disabledIcon="icons/full/dlcl16/refresh.png"> + + @@ -406,6 +456,10 @@ type="org.eclipse.ui.views.properties.IPropertySource"> + + @@ -429,75 +483,88 @@ + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + point="org.eclipse.ui.menus"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + ifEmpty="false" + operator="or"> + + + + + + - - - + + + @@ -570,6 +637,31 @@ + + + + + + + + + + + + + + + + + + @@ -620,6 +712,39 @@ + + + + + + + + + + + + + + + + + + @@ -632,6 +757,17 @@ + + + + + @@ -643,26 +779,22 @@ - - - - - - - - - - - - - - - + point="org.eclipse.help.contentExtension"> + + + + + + + + diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/composite/WorkingSetProperyTester.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/composite/WorkingSetProperyTester.java new file mode 100644 index 0000000000..f05b3b6d40 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/composite/WorkingSetProperyTester.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2020 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.composite; + +import org.eclipse.ui.IWorkingSet; +import org.eclipse.buildship.core.internal.GradlePluginsRuntimeException; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.IGradleCompositeIDs; + +/** + * Property tester to determine if the test launch shortcut should be visible in the context menus. + */ +public final class WorkingSetProperyTester extends org.eclipse.core.expressions.PropertyTester { + + private static final String PROPERTY_NAME_IS_GRADLE_COMPOSITE_ID = "gradlecomposite"; + private static final String GRADLE_COMPOSITE_ID = IGradleCompositeIDs.NATURE; + + @Override + public boolean test(Object receiver, String propertyString, Object[] args, Object expectedValue) { + if (propertyString.equals(PROPERTY_NAME_IS_GRADLE_COMPOSITE_ID)) { + return receiver instanceof IWorkingSet && isGradleComposite((IWorkingSet)receiver); + } else { + throw new GradlePluginsRuntimeException("Unrecognized property to test: " + propertyString); + } + } + + private boolean isGradleComposite(IWorkingSet workingSet) { + try { + return workingSet.getId().equals(GRADLE_COMPOSITE_ID); + } catch (Exception e) { + return false; + } + } + +} + diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/AbstractPropertiesPage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/AbstractPropertiesPage.java new file mode 100644 index 0000000000..ec8b3227a9 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/AbstractPropertiesPage.java @@ -0,0 +1,125 @@ +/******************************************************************************* + * Copyright (c) 2020 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.preferences; + +import java.util.List; + +import org.eclipse.buildship.core.internal.util.binding.Property; +import org.eclipse.buildship.ui.internal.wizard.HelpContextIdProvider; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.CompositeConfiguration; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.GradleCreateWorkspaceCompositeWizardPage; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeCreationWizard; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.wizard.WizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.ScrolledComposite; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.PlatformUI; + +/** + * Common base class for all pages in the {@link WorkspaceCompositeCreationWizard}. + */ +public abstract class AbstractPropertiesPage extends WizardPage { + + private final CompositeConfiguration configuration; + + /** + * Constructor setting up the main messages and the validation facility for this wizard page. + * + * @param name the name of the page + * @param title the page title + * @param defaultMessage the default message to show when there is no validation error + * @param configuration the data model of the wizard + * @param observedProperties the subset of the properties from the data model that are managed + * on this page + */ + protected AbstractPropertiesPage(String name, String title, String defaultMessage, CompositeConfiguration configuration, final List> observedProperties) { + super(name); + + this.configuration = configuration; + + // set the basic message and the attached image + setTitle(title); + setDescription(defaultMessage); + setImageDescriptor(ImageDescriptor.createFromFile(GradleCreateWorkspaceCompositeWizardPage.class, "/icons/full/wizban/wizard.png")); //$NON-NLS-1$ + } + + protected CompositeConfiguration getConfiguration() { + return this.configuration; + } + + @Override + public void createControl(Composite parent) { + // align dialog units to the current resolution + initializeDialogUnits(parent); + + // create the container control + Composite pageControl = createWizardPageContent(parent); + + // assign the created control to the wizard page + setControl(pageControl); + } + + private Composite createWizardPageContent(Composite parent) { + // create a scrollable root to handle resizing + ScrolledComposite externalRoot = new ScrolledComposite(parent, SWT.H_SCROLL | SWT.V_SCROLL); + externalRoot.setExpandHorizontal(true); + externalRoot.setExpandVertical(true); + externalRoot.setMinSize(new Point(230, 380)); + + // add the controls inside the root composite + Composite container = new Composite(externalRoot, SWT.NONE); + createWidgets(container); + + // also compute the size of the container, otherwise the ScrolledComposite's content is not + // rendered properly + Point containerSize = container.computeSize(SWT.DEFAULT, SWT.DEFAULT); + container.setSize(containerSize); + + // set the root's content and return it + externalRoot.setContent(container); + return externalRoot; + } + + /** + * Populates the widgets in the wizard page. + */ + protected abstract void createWidgets(Composite root); + + /** + * Returns text to display under the widgets. If {@code null} or empty then nothing is displayed. + * + * @return explanation text for for the wizard page + */ + protected abstract String getPageContextInformation(); + + @Override + public void setVisible(boolean visible) { + super.setVisible(visible); + + // every time the page becomes visible, set the proper help context, this is required since + // the user could navigate back to the initial Eclipse import page which sets another help + // context + if (visible) { + if (getWizard() instanceof HelpContextIdProvider) { + String helpContextId = ((HelpContextIdProvider) getWizard()).getHelpContextId(); + PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), helpContextId); + } + } + } + + @Override + public void dispose() { + super.dispose(); + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeImportOptionsPreferencePage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeImportOptionsPreferencePage.java new file mode 100644 index 0000000000..f26b9e8f19 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeImportOptionsPreferencePage.java @@ -0,0 +1,174 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.preferences; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.buildship.core.internal.CorePlugin; +import org.eclipse.buildship.core.internal.configuration.BuildConfiguration; +import org.eclipse.buildship.core.internal.configuration.CompositeConfiguration; +import org.eclipse.buildship.core.internal.configuration.ConfigurationManager; +import org.eclipse.buildship.core.internal.configuration.DefaultCompositeConfiguration; +import org.eclipse.buildship.core.internal.util.binding.Validator; +import org.eclipse.buildship.core.internal.util.binding.Validators; +import org.eclipse.buildship.core.internal.workspace.InternalGradleBuild; +import org.eclipse.buildship.ui.internal.util.gradle.GradleDistributionViewModel; +import org.eclipse.buildship.ui.internal.util.widget.AdvancedOptionsGroup; +import org.eclipse.buildship.ui.internal.util.widget.GradleProjectSettingsComposite; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.ui.IWorkbenchPropertyPage; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.dialogs.PreferencesUtil; +import org.eclipse.ui.dialogs.PropertyPage; + +/** + * Preference page for composite import options. + * + * @author Sebastian Kuzniarz + */ + +public final class GradleCompositeImportOptionsPreferencePage extends PropertyPage implements IWorkbenchPropertyPage{ + + public static final String PAGE_ID = "org.eclipse.buildship.ui.compositeImportOptionsProperties"; + + private GradleProjectSettingsComposite gradleProjectSettingsComposite; + + private final Validator distributionValidator; + private final Validator javaHomeValidator; + private final Validator gradleUserHomeValidator; + + public GradleCompositeImportOptionsPreferencePage() { + this.gradleUserHomeValidator = Validators.optionalDirectoryValidator("Gradle user home"); + this.javaHomeValidator = Validators.optionalDirectoryValidator("Java home"); + this.distributionValidator = GradleDistributionViewModel.validator(); + } + + @Override + protected Control createContents(Composite parent) { + this.gradleProjectSettingsComposite = GradleProjectSettingsComposite.builder(parent) + .withAutoSyncCheckbox() + .withOverrideCheckbox("Override workspace settings", "Configure Workspace Settings") + .build(); + this.gradleProjectSettingsComposite.setVisible(true); + + initValues(); + addListeners(); + return this.gradleProjectSettingsComposite; + } + + @Override + public void applyData(Object data) { + // TODO Auto-generated method stub + super.applyData(data); + + } + + private void initValues() { + IWorkingSet composite = getTargetComposite(); + + BuildConfiguration buildConfig = CorePlugin.configurationManager().loadCompositeConfiguration(composite.getName()).getBuildConfiguration(); + + boolean overrideWorkspaceSettings = buildConfig.isOverrideWorkspaceSettings(); + this.gradleProjectSettingsComposite.getGradleDistributionGroup().setDistribution(GradleDistributionViewModel.from(buildConfig.getGradleDistribution())); + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().setGradleUserHome(buildConfig.getGradleUserHome()); + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().setJavaHome(buildConfig.getJavaHome()); + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().setArguments(buildConfig.getArguments()); + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().setJvmArguments(buildConfig.getJvmArguments()); + this.gradleProjectSettingsComposite.getOverrideBuildSettingsCheckbox().setSelection(overrideWorkspaceSettings); + this.gradleProjectSettingsComposite.getBuildScansCheckbox().setSelection(buildConfig.isBuildScansEnabled()); + this.gradleProjectSettingsComposite.getOfflineModeCheckbox().setSelection(buildConfig.isOfflineMode()); + this.gradleProjectSettingsComposite.getAutoSyncCheckbox().setSelection(buildConfig.isAutoSync()); + this.gradleProjectSettingsComposite.getShowConsoleViewCheckbox().setSelection(buildConfig.isShowConsoleView()); + this.gradleProjectSettingsComposite.getShowExecutionsViewCheckbox().setSelection(buildConfig.isShowExecutionsView()); + this.gradleProjectSettingsComposite.updateEnablement(); + } + + private void addListeners() { + this.gradleProjectSettingsComposite.getParentPreferenceLink().addSelectionListener(new WorkbenchPreferenceOpeningSelectionListener()); + AdvancedOptionsGroup advancedOptionsGroup = this.gradleProjectSettingsComposite.getAdvancedOptionsGroup(); + advancedOptionsGroup.getGradleUserHomeText().addModifyListener(new ValidatingListener<>(this, () -> advancedOptionsGroup.getGradleUserHome(), this.gradleUserHomeValidator)); + advancedOptionsGroup.getJavaHomeText().addModifyListener(new ValidatingListener<>(this, () -> advancedOptionsGroup.getJavaHome(), this.javaHomeValidator)); + this.gradleProjectSettingsComposite.getGradleDistributionGroup().addDistributionChangedListener(new GradleDistributionValidatingListener(this, this.distributionValidator)); + } + + @Override + public boolean performOk() { + IWorkingSet composite = getTargetComposite(); + List compositeBuilds = getIncludedBuildsList(composite); + ConfigurationManager manager = CorePlugin.configurationManager(); + CompositeConfiguration currentConfig = manager.loadCompositeConfiguration(composite.getName()); + + BuildConfiguration updatedConfig = manager.createBuildConfiguration(currentConfig.getBuildConfiguration().getRootProjectDirectory(), + this.gradleProjectSettingsComposite.getOverrideBuildSettingsCheckbox().getSelection(), + this.gradleProjectSettingsComposite.getGradleDistributionGroup().getDistribution().toGradleDistribution(), + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().getGradleUserHome(), + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().getJavaHome(), + this.gradleProjectSettingsComposite.getBuildScansCheckbox().getSelection(), + this.gradleProjectSettingsComposite.getOfflineModeCheckbox().getSelection(), + this.gradleProjectSettingsComposite.getAutoSyncCheckbox().getSelection(), + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().getArguments(), + this.gradleProjectSettingsComposite.getAdvancedOptionsGroup().getJvmArguments(), + this.gradleProjectSettingsComposite.getShowConsoleViewCheckbox().getSelection(), + this.gradleProjectSettingsComposite.getShowExecutionsViewCheckbox().getSelection()); + CompositeConfiguration compConf = new DefaultCompositeConfiguration(composite.getName(), compositeBuilds, updatedConfig, currentConfig.projectAsCompositeRoot()); + manager.saveCompositeConfiguration(compConf); + return true; + } + + private List getIncludedBuildsList(IWorkingSet composite) { + List includedBuildsList = new ArrayList(); + InternalGradleBuild gradleBuild = null; + for (IAdaptable element : composite.getElements()) { + if (CorePlugin.internalGradleWorkspace().getBuild(((IProject) element)).isPresent()) { + gradleBuild = (InternalGradleBuild) CorePlugin.internalGradleWorkspace().getBuild(((IProject) element)).get(); + includedBuildsList.add(gradleBuild.getBuildConfig().getRootProjectDirectory()); + } + } + return includedBuildsList; + } + + @SuppressWarnings("cast") + private IWorkingSet getTargetComposite() { + return (IWorkingSet) Platform.getAdapterManager().getAdapter(getElement(), IWorkingSet.class); + } + + /** + * Opens the workspace preferences dialog. + */ + private class WorkbenchPreferenceOpeningSelectionListener implements SelectionListener { + + @Override + public void widgetSelected(SelectionEvent e) { + openWorkspacePreferences(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + openWorkspacePreferences(); + } + + private void openWorkspacePreferences() { + PreferencesUtil.createPreferenceDialogOn(getShell(), GradleWorkbenchPreferencePage.PAGE_ID, null, null).open(); + } + } +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeRootProjectPreferencePage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeRootProjectPreferencePage.java new file mode 100644 index 0000000000..ef4381ea93 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCompositeRootProjectPreferencePage.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.preferences; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.buildship.core.internal.CorePlugin; +import org.eclipse.buildship.core.internal.configuration.BuildConfiguration; +import org.eclipse.buildship.core.internal.configuration.CompositeConfiguration; +import org.eclipse.buildship.core.internal.configuration.ConfigurationManager; +import org.eclipse.buildship.core.internal.configuration.DefaultCompositeConfiguration; +import org.eclipse.buildship.core.internal.util.binding.Validator; +import org.eclipse.buildship.core.internal.util.binding.Validators; +import org.eclipse.buildship.core.internal.workspace.InternalGradleBuild; +import org.eclipse.buildship.ui.internal.util.file.DirectoryDialogSelectionListener; +import org.eclipse.buildship.ui.internal.util.layout.LayoutUtils; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeWizardMessages; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; +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.Label; +import org.eclipse.swt.widgets.Layout; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.IWorkbenchPropertyPage; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.dialogs.PropertyPage; + +/** + * Preference page for composite root project. + * + * @author Sebastian Kuzniarz + */ + +public final class GradleCompositeRootProjectPreferencePage extends PropertyPage implements IWorkbenchPropertyPage{ + + public static final String PAGE_ID = "org.eclipse.buildship.ui.compositeRootProjectProperties"; + + private Text workspaceCompositeRootProjectLabel; + private Button projectAsCompositeRootCheckbox; + private Button selectRootProject; + private Composite rootProjectSettingsComposite; + private Label rootProjectLabel; + + private final Validator rootProjectValidator; + CompositeConfiguration compositeConfig; + + private Layout createLayout() { + GridLayout layout = LayoutUtils.newGridLayout(2); + layout.horizontalSpacing = 4; + layout.verticalSpacing = 4; + return layout; + } + + public GradleCompositeRootProjectPreferencePage() { + this.rootProjectValidator = Validators.optionalDirectoryValidator("Root project"); + } + + @Override + protected Control createContents(Composite parent) { + this.rootProjectSettingsComposite = buildRootProjectSettingsComposite(parent); + addListeners(); + initValues(); + return this.rootProjectSettingsComposite; + } + + private Composite buildRootProjectSettingsComposite(Composite parent) { + Composite rootProjectComposite = new Composite(parent, SWT.WRAP); + rootProjectComposite.setLayout(createLayout()); + + this.projectAsCompositeRootCheckbox = new Button(rootProjectComposite, SWT.CHECK); + this.projectAsCompositeRootCheckbox.setText("Use project as composite root"); + GridDataFactory.swtDefaults().applyTo(rootProjectComposite); + + Label line = new Label(rootProjectComposite, SWT.SEPARATOR | SWT.HORIZONTAL); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).span(2, 1).applyTo(line); + + // composite root container + Composite workspaceCompositeNameComposite = new Composite(rootProjectComposite, SWT.NONE); + GridLayoutFactory.swtDefaults().extendedMargins(0, 0, 0, 10).numColumns(3).applyTo(workspaceCompositeNameComposite); + GridDataFactory.swtDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).span(3, SWT.DEFAULT).applyTo(workspaceCompositeNameComposite); + + // root project label + this.rootProjectLabel = new Label(workspaceCompositeNameComposite, SWT.NONE); + this.rootProjectLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); + this.rootProjectLabel.setText(WorkspaceCompositeWizardMessages.Label_RootProject); + this.rootProjectLabel.setEnabled(false); + + // root project text field + this.workspaceCompositeRootProjectLabel = new Text(workspaceCompositeNameComposite, SWT.BORDER); + this.workspaceCompositeRootProjectLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + this.workspaceCompositeRootProjectLabel.setEnabled(false); + + // root project select button + this.selectRootProject = new Button(workspaceCompositeNameComposite, SWT.PUSH); + this.selectRootProject.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1)); + this.selectRootProject.setText(WorkspaceCompositeWizardMessages.Button_Select_RootProject); + this.selectRootProject.setEnabled(false); + return rootProjectComposite; + } + + private void initValues() { + IWorkingSet composite = getTargetComposite(); + + this.compositeConfig = CorePlugin.configurationManager().loadCompositeConfiguration(composite.getName()); + boolean useProjectAsCompositeRoot = this.compositeConfig.projectAsCompositeRoot(); + + this.projectAsCompositeRootCheckbox.setSelection(useProjectAsCompositeRoot); + this.workspaceCompositeRootProjectLabel.setText(this.compositeConfig.getBuildConfiguration().getRootProjectDirectory().toString()); + updateEnablement(); + } + + private void addListeners() { + if (this.projectAsCompositeRootCheckbox != null) { + this.projectAsCompositeRootCheckbox.addSelectionListener(new SelectionListener() { + + @Override + public void widgetSelected(SelectionEvent e) { + updateEnablement(); + } + + @Override + public void widgetDefaultSelected(SelectionEvent e) { + updateEnablement(); + } + }); + + File rootProjectDir = this.workspaceCompositeRootProjectLabel.getText().isEmpty() ? null: new File(this.workspaceCompositeRootProjectLabel.getText()); + this.workspaceCompositeRootProjectLabel.addModifyListener(new ValidatingListener<>(this, () -> rootProjectDir, this.rootProjectValidator)); + + this.selectRootProject.addSelectionListener(new DirectoryDialogSelectionListener(this.getShell(), this.workspaceCompositeRootProjectLabel, "Root project")); + } + } + + public void updateEnablement() { + if (this.projectAsCompositeRootCheckbox != null) { + boolean enabled = this.projectAsCompositeRootCheckbox.getSelection(); + this.rootProjectLabel.setEnabled(enabled); + this.selectRootProject.setEnabled(enabled); + this.workspaceCompositeRootProjectLabel.setEnabled(enabled); + } + } + + @SuppressWarnings("cast") + private IWorkingSet getTargetComposite() { + return (IWorkingSet) Platform.getAdapterManager().getAdapter(getElement(), IWorkingSet.class); + } + + @Override + public void dispose() { + super.dispose(); + } + + @Override + public boolean performOk() { + IWorkingSet composite = getTargetComposite(); + ConfigurationManager manager = CorePlugin.configurationManager(); + CompositeConfiguration currentConfig = manager.loadCompositeConfiguration(composite.getName()); + BuildConfiguration updatedConfig = manager.createBuildConfiguration(new File(this.workspaceCompositeRootProjectLabel.getText()), + currentConfig.getBuildConfiguration().isOverrideWorkspaceSettings(), + currentConfig.getBuildConfiguration().getGradleDistribution(), + currentConfig.getBuildConfiguration().getGradleUserHome(), + currentConfig.getBuildConfiguration().getJavaHome(), + currentConfig.getBuildConfiguration().isBuildScansEnabled(), + currentConfig.getBuildConfiguration().isOfflineMode(), + currentConfig.getBuildConfiguration().isAutoSync(), + currentConfig.getBuildConfiguration().getArguments(), + currentConfig.getBuildConfiguration().getJvmArguments(), + currentConfig.getBuildConfiguration().isShowConsoleView(), + currentConfig.getBuildConfiguration().isShowExecutionsView()); + CompositeConfiguration compConf = new DefaultCompositeConfiguration(currentConfig.getCompositeName(), + getIncludedBuildsList(composite), + updatedConfig, + this.projectAsCompositeRootCheckbox.getSelection()); + manager.saveCompositeConfiguration(compConf); + return true; + } + + private List getIncludedBuildsList(IWorkingSet composite) { + List includedBuildsList = new ArrayList(); + for (IAdaptable element : composite.getElements()) { + InternalGradleBuild gradleBuild = (InternalGradleBuild) CorePlugin.internalGradleWorkspace().getBuild(((IProject) element)).get(); + includedBuildsList.add(gradleBuild.getBuildConfig().getRootProjectDirectory()); + } + return includedBuildsList; + } +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCreateWorkspaceCompositePreferencePage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCreateWorkspaceCompositePreferencePage.java new file mode 100644 index 0000000000..aa4b7c0ff1 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleCreateWorkspaceCompositePreferencePage.java @@ -0,0 +1,335 @@ +/******************************************************************************* + * Copyright (c) 2020 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.preferences; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.eclipse.buildship.core.BuildConfiguration; +import org.eclipse.buildship.core.GradleBuild; +import org.eclipse.buildship.core.internal.CorePlugin; +import org.eclipse.buildship.core.internal.configuration.GradleProjectNature; +import org.eclipse.buildship.core.internal.configuration.ProjectConfiguration; +import org.eclipse.buildship.core.internal.workspace.InternalGradleBuild; +import org.eclipse.buildship.ui.internal.util.layout.LayoutUtils; +import org.eclipse.buildship.ui.internal.util.widget.GradleProjectGroup; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.CompositeConfiguration; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.CompositeCreationConfiguration; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.CompositeCreationWizardController; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.CompositeImportWizardController; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.GradleImportOptionsWizardPage; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.IGradleCompositeIDs; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeCreationWizard; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeWizardMessages; +import org.eclipse.core.resources.IProject; +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.Plugin; +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.wizard.IWizardPage; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Text; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.IWorkingSetManager; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.dialogs.IWorkingSetPage; + +import com.google.common.collect.ImmutableList; + +/** + * Page on the {@link WorkspaceCompositeCreationWizard} declaring the workspace + * composite name and included projects. + */ +public final class GradleCreateWorkspaceCompositePreferencePage extends AbstractPropertiesPage + implements IWorkingSetPage { + + private final CompositeCreationConfiguration creationConfiguration; + + @SuppressWarnings("unused") + private Text workspaceCompositeNameText; + private Label compositeName; + private GradleProjectGroup gradleProjectCheckboxtreeComposite; + + private static IWorkingSet gradleComposite; + private boolean firstCheck; + private static CompositeImportWizardController importController; + + public GradleCreateWorkspaceCompositePreferencePage(CompositeConfiguration importConfiguration, + CompositeCreationConfiguration creationConfiguration) { + super("NewGradleWorkspaceComposite", //$NON-NLS-1$ + WorkspaceCompositeWizardMessages.Title_NewGradleWorkspaceCompositeWizardPage, + WorkspaceCompositeWizardMessages.InfoMessage_NewGradleWorkspaceCompositeWizardPageDefault, importConfiguration, ImmutableList.of(creationConfiguration.getCompositeName(), + creationConfiguration.getCompositeProjects())); + gradleComposite = null; + this.creationConfiguration = creationConfiguration; + this.firstCheck = true; + } + + public GradleCreateWorkspaceCompositePreferencePage() { + this(getCompositeImportConfiguration(), getCompositeCreationConfiguration()); + } + + private IWizardPage buildImportOptionsWizardPage() { + IWizardPage page = new GradleImportOptionsWizardPage(getConfiguration()); + page.setWizard(getWizard()); + return page; + } + + protected String getPageId() { + return "org.eclipse.buildship.ui.GradleCompositePage"; //$NON-NLS-1$ + } + + //TODO (kuzniarz) This will definitely need rework IAdaptable -> File + private static CompositeCreationConfiguration getCompositeCreationConfiguration() { + List compositeElements = new ArrayList<>(); + String compositeName = gradleComposite != null ? gradleComposite.getName() : ""; + CompositeCreationWizardController creationController = new CompositeCreationWizardController(compositeName, compositeElements); + return creationController.getConfiguration(); + } + + private static CompositeConfiguration getCompositeImportConfiguration() { + importController = new CompositeImportWizardController(null); + return importController.getConfiguration(); + } + + @Override + public void createControl(Composite parent) { + super.createControl(parent); + } + + @Override + protected void createWidgets(Composite root) { + root.setLayout(LayoutUtils.newGridLayout(3)); + createContent(root); + } + + private void createContent(Composite root) { + + // composite name container + Composite workspaceCompositeNameComposite = new Composite(root, SWT.FILL); + GridLayoutFactory.fillDefaults().extendedMargins(0, 0, 0, 5).numColumns(2) + .applyTo(workspaceCompositeNameComposite); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).span(3, SWT.DEFAULT) + .applyTo(workspaceCompositeNameComposite); + + // composite name label + this.compositeName = new Label(workspaceCompositeNameComposite, SWT.NONE); + this.compositeName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); + this.compositeName.setText(WorkspaceCompositeWizardMessages.Label_CompositeName); + + // composite name text field + this.workspaceCompositeNameText = new Text(workspaceCompositeNameComposite, SWT.BORDER); + this.workspaceCompositeNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + + this.gradleProjectCheckboxtreeComposite = new GradleProjectGroup(root, (gradleComposite != null)); + GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(3, SWT.DEFAULT) + .applyTo(this.gradleProjectCheckboxtreeComposite); + + if (gradleComposite != null) { + this.workspaceCompositeNameText.setText(gradleComposite.getName()); + this.gradleProjectCheckboxtreeComposite.setCheckboxTreeSelection(gradleComposite.getElements()); + } + + addListeners(); + } + + private void addListeners() { + this.workspaceCompositeNameText.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + updateLocation(); + validateInput(); + } + }); + this.gradleProjectCheckboxtreeComposite.getCheckboxTree().addListener(SWT.Selection, new Listener() { + + @Override + public void handleEvent(Event event) { + updateCompositeProjects(); + validateInput(); + } + }); + } + + protected void updateCompositeProjects() { + List projectList = new ArrayList<>(); + + for (TreeItem treeElement : this.gradleProjectCheckboxtreeComposite.getCheckboxTree().getItems()) { + if (treeElement.getChecked() == true) { + if (treeElement.getText().contains(" (External): ")) { + String[] treeValues = treeElement.getText().replace(" (External): ", "$").split("\\$"); + // treeValues[0] contains the project name + // treeValues[1] contains the file path + File externalFolder = new File(treeValues[1]); + projectList.add(externalFolder); + } else { + projectList.add(getGradleRootFor(ResourcesPlugin.getWorkspace().getRoot().getProject(treeElement.getText()))); + } + } + } + getConfiguration().getIncludedBuildsList().setValue(projectList); + this.creationConfiguration.setCompositeProjects(projectList); + } + + protected File getGradleRootFor(IProject project) { + InternalGradleBuild gradleBuild = (InternalGradleBuild) CorePlugin.internalGradleWorkspace().getBuild(project).get(); + return gradleBuild.getBuildConfig().getRootProjectDirectory(); + } + + private void updateLocation() { + // always update project name last to ensure project name validation errors have + // precedence in the UI + getConfiguration().getCompositeName().setValue(this.workspaceCompositeNameText.getText()); + this.creationConfiguration.setCompositeName(this.workspaceCompositeNameText.getText()); + } + + @Override + protected String getPageContextInformation() { + return WorkspaceCompositeWizardMessages.InfoMessage_NewGradleWorkspaceCompositeWizardPageContext; + } + + @Override + public void finish() { + try { + updateCompositeProjects(); + String workspaceCompositeName = this.workspaceCompositeNameText.getText(); + String oldWorkspaceCompositeName = ""; + IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager(); + File compositePreferenceFile = getWorkspaceCompositesPropertiesFile(workspaceCompositeName); + IAdaptable[] compositeElements = getCompositeElements(getConfiguration().getIncludedBuildsList().getValue()); + if (gradleComposite == null) { + gradleComposite = workingSetManager.createWorkingSet(workspaceCompositeName, compositeElements); + gradleComposite.setId(IGradleCompositeIDs.NATURE); + } else { + IAdaptable[] oldElements = gradleComposite.getElements(); + oldWorkspaceCompositeName = gradleComposite.getName(); + if (!gradleComposite.getName().equals(this.workspaceCompositeNameText.getText())) { + gradleComposite.setName(this.workspaceCompositeNameText.getText()); + } + + if (!oldElements.equals(compositeElements)) { + gradleComposite.setElements(compositeElements); + } + } + FileOutputStream out = new FileOutputStream(compositePreferenceFile.getAbsoluteFile()); + Properties prop = getConfiguration().toCompositeProperties().toProperties(); + prop.store(out, " "); + out.close(); + if (!workspaceCompositeName.equals(oldWorkspaceCompositeName)) { + File oldCompositeProperties = getWorkspaceCompositesPropertiesFile(oldWorkspaceCompositeName); + oldCompositeProperties.delete(); + } + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + private File getWorkspaceCompositesPropertiesFile(String compositeName) { + return CorePlugin.getInstance().getStateLocation() + .append("workspace-composites").append(compositeName).toFile(); + } + + private IAdaptable[] getCompositeElements(List includedBuildsList) { + List compositeElements = new ArrayList<>(); + for (File includedBuild : includedBuildsList) { + //TODO (kuzniarz) Files need to be added to composite to be viewed in ProjectExplorer + if (isExternalProject(includedBuild)) { + //compositeElements.add(ResourcesPlugin.getWorkspace().getRoot().getFile(Path.fromOSString(includedBuild.getAbsolutePath()))); + } else { + compositeElements.add(ResourcesPlugin.getWorkspace().getRoot().getProject(includedBuild.getName())); + } + } + return compositeElements.toArray(new IAdaptable[includedBuildsList.size()]); + } + + private boolean isExternalProject(File includedBuild) { + return !ResourcesPlugin.getWorkspace().getRoot().getProject(includedBuild.getName()).exists(); + } + + @Override + public IWorkingSet getSelection() { + return gradleComposite; + } + + @Override + public void setSelection(IWorkingSet workingSet) { + Assert.isNotNull(workingSet, "Composite must not be null"); //$NON-NLS-1$ + gradleComposite = workingSet; + if (getContainer() == null && getShell() != null && this.workspaceCompositeNameText != null) { + this.workspaceCompositeNameText.setText(gradleComposite.getName()); + } + } + + @Override + public IWizardPage getNextPage() { + return buildImportOptionsWizardPage(); + } + + protected void validateInput() { + String errorMessage = null; + String infoMessage = null; + String newText= this.workspaceCompositeNameText.getText(); + + if (newText.equals(newText.trim()) == false) { + errorMessage = WorkspaceCompositeWizardMessages.WarningMessage_GradleWorkspaceComposite_NameWhitespaces; + } + if (newText.isEmpty()) { + if (this.firstCheck) { + setPageComplete(false); + this.firstCheck= false; + return; + } else { + errorMessage = WorkspaceCompositeWizardMessages.WarningMessage_GradleWorkspaceComposite_NameEmpty; + } + } + + this.firstCheck= false; + + if (errorMessage == null && (gradleComposite == null || newText.equals(gradleComposite.getName()) == false)) { + IWorkingSet[] workingSets= PlatformUI.getWorkbench().getWorkingSetManager().getWorkingSets(); + for (int i= 0; i < workingSets.length; i++) { + if (newText.equals(workingSets[i].getName())) { + errorMessage= WorkspaceCompositeWizardMessages.WarningMessage_GradleWorkspaceComposite_CompositeNameExists; + } + } + } + + if (!hasSelectedElement()) { + infoMessage = WorkspaceCompositeWizardMessages.WarningMessage_GradleWorkspaceComposite_CompositeEmpty; + } + + setMessage(infoMessage, INFORMATION); + setErrorMessage(errorMessage); + setPageComplete(errorMessage == null); + } + + private boolean hasSelectedElement() { + return this.creationConfiguration.getCompositeProjects().getValue().size() > 0; + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleDistributionValidatingListener.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleDistributionValidatingListener.java index 5ca331192d..b1ce49d8a6 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleDistributionValidatingListener.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleDistributionValidatingListener.java @@ -22,7 +22,7 @@ * * @author Donat Csikos */ -final class GradleDistributionValidatingListener implements DistributionChangedListener { +public final class GradleDistributionValidatingListener implements DistributionChangedListener { private final PreferencePage preferencePage; private final Validator distributionValidator; diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleProjectPreferencePage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleProjectPreferencePage.java index 53517a5534..7536005a30 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleProjectPreferencePage.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleProjectPreferencePage.java @@ -110,7 +110,7 @@ public boolean performOk() { return true; } - @SuppressWarnings({"cast", "RedundantCast"}) + @SuppressWarnings({"cast"}) private IProject getTargetProject() { return (IProject) Platform.getAdapterManager().getAdapter(getElement(), IProject.class); } diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleWorkspaceCompositePreferencePage.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleWorkspaceCompositePreferencePage.java new file mode 100644 index 0000000000..70495b84a2 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/GradleWorkspaceCompositePreferencePage.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.preferences; + +import org.eclipse.jface.layout.GridDataFactory; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.dialogs.PropertyPage; + +import org.eclipse.buildship.ui.internal.util.layout.LayoutUtils; +import org.eclipse.buildship.ui.internal.util.widget.GradleProjectGroup; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeWizardMessages; + +/** + * Preference page for workspace composite configuration. + * + * @author Sebastian Kuzniarz + */ +@SuppressWarnings("unused") +public final class GradleWorkspaceCompositePreferencePage extends PropertyPage { + + public static final String PAGE_ID = "org.eclipse.buildship.ui.compositeproperties"; + + private Text workspaceCompositeNameText; + private Label compositeName; + private GradleProjectGroup gradleProjectCheckboxtreeComposite; + private Composite gradleWorkspaceCompositeSettingsComposite; + + @Override + protected Control createContents(Composite parent) { + this.gradleWorkspaceCompositeSettingsComposite = new Composite(parent, SWT.FILL); + this.gradleWorkspaceCompositeSettingsComposite.setLayout(LayoutUtils.newGridLayout(2)); + + // composite name container + Composite workspaceCompositeNameComposite = new Composite(this.gradleWorkspaceCompositeSettingsComposite, SWT.FILL); + GridLayoutFactory.fillDefaults().extendedMargins(0, 0, 0, 5).numColumns(2).applyTo(workspaceCompositeNameComposite); + GridDataFactory.fillDefaults().align(SWT.FILL, SWT.TOP).grab(true, false).span(3, SWT.DEFAULT).applyTo(workspaceCompositeNameComposite); + + // composite name label + this.compositeName = new Label(workspaceCompositeNameComposite, SWT.NONE); + this.compositeName.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1)); + this.compositeName.setText(WorkspaceCompositeWizardMessages.Label_CompositeName); + + // composite name text field + this.workspaceCompositeNameText = new Text(workspaceCompositeNameComposite, SWT.BORDER); + this.workspaceCompositeNameText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + + this.gradleProjectCheckboxtreeComposite = new GradleProjectGroup(this.gradleWorkspaceCompositeSettingsComposite, true); + GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(3, SWT.DEFAULT).applyTo(this.gradleProjectCheckboxtreeComposite); + + return this.gradleWorkspaceCompositeSettingsComposite; + } + + @Override + public boolean performOk() { + return true; + } +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/ValidatingListener.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/ValidatingListener.java index 34dded78f7..27a53d0b55 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/ValidatingListener.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/preferences/ValidatingListener.java @@ -23,7 +23,7 @@ * * @author Donat Csikos */ -final class ValidatingListener implements ModifyListener { +public final class ValidatingListener implements ModifyListener { private final PreferencePage preferencePage; private final Supplier target; diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/file/ExternalProjectDialogSelectionListener.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/file/ExternalProjectDialogSelectionListener.java new file mode 100644 index 0000000000..862fd0e777 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/file/ExternalProjectDialogSelectionListener.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2020 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.util.file; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.google.common.base.Preconditions; + +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.jface.viewers.ColumnViewerToolTipSupport; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.widgets.DirectoryDialog; +import org.eclipse.swt.widgets.MessageBox; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.TreeItem; + +import org.eclipse.buildship.ui.internal.i18n.UiMessages; + +public class ExternalProjectDialogSelectionListener extends SelectionAdapter { + + private final Shell shell; + private final TreeViewer projectTreeViewer; + private final String title; + private final Map externalProjectPaths; + + public ExternalProjectDialogSelectionListener(Shell shell, TreeViewer treeViewer, String entity) { + + this.shell = Preconditions.checkNotNull(shell); + this.projectTreeViewer = treeViewer; + this.title = NLS.bind(UiMessages.Title_Select_0, entity); + ColumnViewerToolTipSupport.enableFor(this.projectTreeViewer); + this.externalProjectPaths = new HashMap<>(); + } + + @Override + public void widgetSelected(SelectionEvent e) { + DirectoryDialog directoryDialog = new DirectoryDialog(this.shell, SWT.SHEET); + directoryDialog.setText(this.title); + + String userHomeDir = System.getProperty("user.home"); + directoryDialog.setFilterPath(userHomeDir); + + String selectedDirectory = directoryDialog.open(); + if (selectedDirectory != null) { + addExternalProjectToProjectTree(selectedDirectory); + } + } + + private void addExternalProjectToProjectTree(String selectedDirectory) { + String projectDir = selectedDirectory; + File gradleSettingsFile = getGradleSettings(projectDir); + if (gradleSettingsFile.isFile()) { + try { + FileInputStream inputStream = new FileInputStream(gradleSettingsFile); + Properties gradleSettings = new Properties(); + gradleSettings.load(inputStream); + String projectName = getProjectName(gradleSettings); + TreeItem jItem = new TreeItem(this.projectTreeViewer.getTree(), 0); + jItem.setFont(JFaceResources.getFontRegistry().getItalic(JFaceResources.DEFAULT_FONT)); + jItem.setChecked(true); + jItem.setText(projectName + " (External): " + gradleSettingsFile.getParentFile().getPath()); + if (!this.externalProjectPaths.containsKey(gradleSettingsFile.getParentFile().getPath())) { + this.externalProjectPaths.put(gradleSettingsFile.getParentFile().getPath(), projectName); + } + } catch (IOException e) { + e.printStackTrace(); + } + } else { + MessageBox dialog = new MessageBox(this.shell, SWT.ICON_ERROR | SWT.OK); + dialog.setText("Error"); + dialog.setMessage("The selected directory is not a gradle project dir!"); + dialog.open(); + } + } + + private String getProjectName(Properties gradleSettings) { + //Refactored method to include String cleaning + return gradleSettings.get("rootProject.name").toString().replaceAll("'", "").replaceAll("\"", ""); + } + + private File getGradleSettings(String projectDir) { + File groovyFile = new File(projectDir + "/settings.gradle"); + File kotlinFile = new File(projectDir + "/settings.gradle.kts"); + if (groovyFile.exists()) { + return groovyFile; + } else if (kotlinFile.exists()) { + return kotlinFile; + } else { + return new File(""); + } + } + + public Map getExternalProjectPaths() { + return this.externalProjectPaths; + } + +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/GradleProjectGroup.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/GradleProjectGroup.java new file mode 100644 index 0000000000..0c0e7fa365 --- /dev/null +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/GradleProjectGroup.java @@ -0,0 +1,223 @@ +/******************************************************************************* + * Copyright (c) 2019 Gradle Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + ******************************************************************************/ + +package org.eclipse.buildship.ui.internal.util.widget; + +import java.util.ArrayList; +import java.util.Map; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspaceRoot; +import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.layout.GridLayoutFactory; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.ISelectionProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.jface.wizard.WizardDialog; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.BusyIndicator; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Group; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeItem; +import org.eclipse.ui.IWorkbenchPage; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.IWorkingSet; +import org.eclipse.ui.PlatformUI; + +import org.eclipse.buildship.core.internal.configuration.GradleProjectNature; +import org.eclipse.buildship.ui.internal.util.file.ExternalProjectDialogSelectionListener; +import org.eclipse.buildship.ui.internal.wizard.project.ProjectCreationWizard; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.IGradleCompositeIDs; +import org.eclipse.buildship.ui.internal.wizard.workspacecomposite.WorkspaceCompositeWizardMessages; + +@SuppressWarnings("unused") +public class GradleProjectGroup extends Group { + + private Font font; + private Button newGradleProject; + private Button addExternalGradleProject; + private ExternalProjectDialogSelectionListener externalProjectListener; + private Composite buttonComposite; + private TreeViewer gradleProjectTree; + private boolean editMode; + + public GradleProjectGroup(Composite parent, boolean editMode) { + super(parent, SWT.NONE); + setText(WorkspaceCompositeWizardMessages.Group_Label_GradleProjects); + this.editMode = editMode; + createWidgets(); + } + + public void createWidgets() { + setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + GridLayoutFactory.swtDefaults().numColumns(4).applyTo(this); + + this.gradleProjectTree = new TreeViewer(this, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.CHECK); + this.gradleProjectTree.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1)); + fillCheckboxTreeWithProjects(); + if (this.editMode) { + configureTree(); + } + + this.gradleProjectTree.setUseHashlookup(true); + + this.buttonComposite = new Composite(this, SWT.NONE); + this.buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, true, 1, 1)); + GridLayoutFactory.fillDefaults().numColumns(1).applyTo(this.buttonComposite); + + this.newGradleProject = new Button(this.buttonComposite, SWT.PUSH); + this.newGradleProject.setText(WorkspaceCompositeWizardMessages.Button_New_GradleProject); + this.newGradleProject.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + + this.addExternalGradleProject = new Button(this.buttonComposite, SWT.PUSH); + this.addExternalGradleProject.setText(WorkspaceCompositeWizardMessages.Button_Add_ExternalGradleProject); + this.addExternalGradleProject.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1)); + this.addExternalGradleProject.setEnabled(false); + + addListener(); + } + + private void addListener() { + this.newGradleProject.addSelectionListener(new SelectionAdapter() { + + @Override + public void widgetSelected(SelectionEvent e) { + WizardDialog wizard = new WizardDialog(getShell(), new ProjectCreationWizard()); + if (wizard.open() == WizardDialog.OK) { + fillCheckboxTreeWithProjects(); + configureTree(); + } + } + }); + this.externalProjectListener = new ExternalProjectDialogSelectionListener(getShell(), this.gradleProjectTree, ""); + this.addExternalGradleProject.addSelectionListener(this.externalProjectListener); + } + + private void configureTree() { + ArrayList selection = getInitialTreeSelection(); + selectTreeElements(selection); + } + + private void selectTreeElements(ArrayList selection) { + try { + this.gradleProjectTree.getTree().setRedraw(false); + for (TreeItem item : this.gradleProjectTree.getTree().getItems()) { + if (selection.contains(item.getText())) { + item.setChecked(true); + } + } + } finally { + this.gradleProjectTree.getTree().setRedraw(true); + } + } + + public boolean hasSelectedItems() { + return this.gradleProjectTree.getTree().getSelectionCount() > 0; + } + + private ArrayList getInitialTreeSelection() { + ArrayList projectNames = new ArrayList<>(); + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + + @Override + public void run() { + IStructuredSelection projectSelection = null; + IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); + if (page == null) { + return; + } + + IWorkbenchPart part = page.getActivePart(); + if (part == null) { + return; + } + + try { + ISelectionProvider provider = part.getSite().getSelectionProvider(); + if (provider != null) { + ISelection selection = provider.getSelection(); + projectSelection = selection instanceof IStructuredSelection ? (IStructuredSelection) selection : StructuredSelection.EMPTY; + } + } catch (Exception e) { + return; + } + + Object[] elements = projectSelection.toArray(); + + for (int i = 0; i < elements.length; i++) { + if (elements[i] instanceof IWorkingSet) { + IWorkingSet ge = ((IWorkingSet) elements[i]); + if (ge != null && ge.getId().equals(IGradleCompositeIDs.NATURE)) { + for (int j = 0; j < ge.getElements().length; j++) { + IAdaptable[] element = ge.getElements(); + projectNames.add(((IAdaptable) element[j]).getAdapter(IProject.class).getName()); + } + elements[i] = projectNames; + } + } + } + } + }); + + return projectNames; + } + + public void setCheckboxTreeSelection(IAdaptable[] projects) { + ArrayList compositeProjects = new ArrayList(); + for (IAdaptable project : projects) { + compositeProjects.add(((IProject) project).getName()); + } + selectTreeElements(compositeProjects); + } + + private void fillCheckboxTreeWithProjects() { + this.gradleProjectTree.getTree().removeAll(); + try { + IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); + IProject[] projects = workspaceRoot.getProjects(); + for (int i = 0; i < projects.length; i++) { + IProject project = projects[i]; + if (project.hasNature(GradleProjectNature.ID)) { + TreeItem jItem = new TreeItem(this.gradleProjectTree.getTree(), 0); + jItem.setText(project.getName()); + } + } + } catch (CoreException ce) { + ce.printStackTrace(); + } + } + + public Tree getCheckboxTree() { + return this.gradleProjectTree.getTree(); + } + + public TreeViewer getCheckboxTreeViewer() { + return this.gradleProjectTree; + } + + public Map getExternalProjectPathList() { + return this.externalProjectListener.getExternalProjectPaths(); + } + + @Override + protected void checkSubclass() { + // Disable the check that prevents subclassing of SWT components + } +} diff --git a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/UiBuilder.java b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/UiBuilder.java index e4bc15aaa7..5cb2a45d94 100644 --- a/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/UiBuilder.java +++ b/org.eclipse.buildship.ui/src/main/java/org/eclipse/buildship/ui/internal/util/widget/UiBuilder.java @@ -85,6 +85,16 @@ public UiBuilder alignFillHorizontal() { return this; } + /** + * Aligns the created widget to fill the cell vertically aligned at top. + * + * @return the builder + */ + public UiBuilder alignFillVerticalTop() { + this.control.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, true, 1, 1)); + return this; + } + /** * Aligns the created widget to fill both horizontal and vertical. * @@ -177,6 +187,17 @@ public UiBuilder