diff --git a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
index c3048f7f216..872462a02ef 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
+++ b/build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF
@@ -6,7 +6,8 @@ Bundle-Version: 5.0.100.qualifier
Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
-Export-Package: org.eclipse.cdt.managedbuilder.ui.actions,
+Export-Package: org.eclipse.cdt.managedbuilder.internal.ui.workingsets,
+ org.eclipse.cdt.managedbuilder.ui.actions,
org.eclipse.cdt.managedbuilder.ui.properties,
org.eclipse.cdt.managedbuilder.ui.wizards
Require-Bundle: org.eclipse.ui.ide;bundle-version="[3.2.0,4.0.0)",
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
index 5c80786ecf6..62d64f9d9cc 100644
--- a/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
+++ b/build/org.eclipse.cdt.managedbuilder.ui/plugin.xml
@@ -675,7 +675,17 @@
class="org.eclipse.cdt.make.ui.dialogs.GCCPerProjectSCDProfilePage"
name="%MBSPerProjectProfile.name"
profileId="org.eclipse.cdt.managedbuilder.core.GCCWinManagedMakePerProjectProfileCPP"/>
-
+
+
+
+
+
+
+
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfiguration.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfiguration.java
new file mode 100644
index 00000000000..6bb40408b37
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfiguration.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.managedbuilder.internal.ui.workingsets;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
+import org.eclipse.cdt.internal.ui.workingsets.WorkingSetProjectConfiguration;
+import org.eclipse.cdt.managedbuilder.core.IConfiguration;
+import org.eclipse.cdt.managedbuilder.core.ManagedBuildManager;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A managed-build implementation of the working set project configuration. It
+ * knows how to build the selected configuration without activating it.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+class MBSProjectConfiguration extends WorkingSetProjectConfiguration {
+
+ /**
+ * Initializes me.
+ *
+ * @param parent
+ * my parent working set configuration
+ */
+ public MBSProjectConfiguration(IWorkingSetConfiguration parent) {
+ super(parent);
+ }
+
+ @Override
+ public IStatus build(IProgressMonitor monitor) {
+ return MBSProjectConfiguration.build(resolveProject(),
+ resolveSelectedConfiguration(), monitor);
+ }
+
+ /**
+ * Builds the MBS configuration selected by the specified working set
+ * project configuration.
+ *
+ * @param projectConfig
+ * a project configuration to build
+ * @param monitor
+ * for reporting build progress
+ *
+ * @return the result of the MBS build
+ */
+ static IStatus build(IProject project, ICConfigurationDescription config,
+ IProgressMonitor monitor) {
+
+ IStatus result = Status.OK_STATUS;
+
+ IConfiguration mbsConfig = (config == null) ? null
+ : ManagedBuildManager.getConfigurationForDescription(config);
+
+ if (mbsConfig == null) {
+ result = new Status(IStatus.WARNING, CUIPlugin.PLUGIN_ID, NLS.bind(
+ "No configuration selected for project \"{0}\".", project
+ .getName()));
+ } else {
+ monitor = SubMonitor.convert(monitor);
+
+ try {
+ ManagedBuildManager.buildConfigurations(
+ new IConfiguration[] { mbsConfig }, monitor);
+ } catch (CoreException e) {
+ result = e.getStatus();
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfigurationFactory.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfigurationFactory.java
new file mode 100644
index 00000000000..356069c4af1
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectConfigurationFactory.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.managedbuilder.internal.ui.workingsets;
+
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration;
+import org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory;
+import org.eclipse.cdt.internal.ui.workingsets.WorkingSetProjectConfiguration;
+import org.eclipse.cdt.internal.ui.workingsets.WorkspaceSnapshot.ProjectState;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Working set project configuration factory for MBS projects.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ */
+public class MBSProjectConfigurationFactory extends
+ IWorkingSetProjectConfigurationFactory.Registry.Default {
+
+ /**
+ * Initializes me.
+ */
+ public MBSProjectConfigurationFactory() {
+ super();
+ }
+
+ @Override
+ protected WorkingSetProjectConfiguration createProjectConfiguration(
+ IWorkingSetConfiguration parent) {
+
+ return new MBSProjectConfiguration(parent);
+ }
+
+ @Override
+ public ProjectState createProjectState(IProject project,
+ ICProjectDescription desc) {
+
+ return new MBSProjectState(project, desc);
+ }
+}
diff --git a/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectState.java b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectState.java
new file mode 100644
index 00000000000..4322d2b74ad
--- /dev/null
+++ b/build/org.eclipse.cdt.managedbuilder.ui/src/org/eclipse/cdt/managedbuilder/internal/ui/workingsets/MBSProjectState.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.managedbuilder.internal.ui.workingsets;
+
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.internal.ui.workingsets.WorkspaceSnapshot.ProjectState;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+/**
+ * A managed-build implementation of the workspace snapshot project state. It
+ * knows how to build the selected configuration without activating it.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+class MBSProjectState extends ProjectState {
+
+ /**
+ * Initializes me with my project and its description.
+ *
+ * @param project
+ * my project
+ * @param desc
+ * its description
+ */
+ public MBSProjectState(IProject project, ICProjectDescription desc) {
+ super(project, desc);
+ }
+
+ @Override
+ protected IStatus build(String configID, IProgressMonitor monitor) {
+ IStatus result = MBSProjectConfiguration.build(getProject(),
+ getConfiguration(configID), monitor);
+
+ if (result.isOK()) {
+ built(configID);
+ }
+
+ return result;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/.settings/.api_filters b/core/org.eclipse.cdt.ui/.settings/.api_filters
new file mode 100644
index 00000000000..580a529ff83
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/.settings/.api_filters
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index 8e28be462a7..29491a0125c 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2003, 2008 IBM Corporation and others.
+# Copyright (c) 2003, 2009 IBM Corporation, QNX Software Systems, and others.
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v1.0
# which accompanies this distribution, and is available at
@@ -10,6 +10,7 @@
# Markus Schorn (Wind River Systems)
# Anton Leherbauer (Wind River Systems)
# Sergey Prigogin (Google)
+# QNX Software Systems - [272416] Rework the working set configurations
###############################################################################
pluginName=C/C++ Development Tools UI
providerName=Eclipse.org
@@ -508,7 +509,14 @@ cEditorHyperlinkTarget= C/C++ Editor
cElementHyperlinkDetector= C/C++ Elements
keybinding.MSVS= Microsoft Visual Studio
-wsselection= Configs for Working set
+wsselection= Manage &Working Sets...
+workingSetConfigsPage=C/C++ Build
+activateWorkingSetConfig.label=Set &Active by Working Set
+activateWorkingSetConfig.context.label=Set &Active
+buildWorkingSetConfig.label=&Build by Working Set
+buildWorkingSetConfig.context.label=&Build
+workingSetConfigs.context.label=&Build Configurations
+workingSetConfigurationsExtensionPoint=Working Set Configurations
# Keywords for Preferences
preferenceKeywords.common=c cpp cplusplus cdt
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index b646e19f45d..26d04529dc9 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -24,6 +24,7 @@
+
@@ -1115,6 +1116,77 @@
contentTypeId="org.eclipse.cdt.core.asmSource"
contentMergeViewerId="org.eclipse.cdt.ui.compare.AsmContentViewerCreator"/>
+
+
+
+
+
+
+
+
+
-
@@ -2859,6 +2911,12 @@
namespace="org.eclipse.cdt.ui"
properties="isSource"
type="org.eclipse.core.resources.IFile"/>
+
@@ -3018,5 +3076,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/org.eclipse.cdt.ui/schema/workingSetConfigurations.exsd b/core/org.eclipse.cdt.ui/schema/workingSetConfigurations.exsd
new file mode 100644
index 00000000000..a1d6645638f
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/schema/workingSetConfigurations.exsd
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+ <p>
+<b>This extension point is internal to the CDT plug-in family.</b>
+</p><p>
+Extension point for registration of project configuration factories for handling extended configuration options for custom project natures, in working set configurations. These factories are responsible for creating the project configuration elements and the UI controllers for the Manage Working Set Configurations dialog.
+</p>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Registration of a factory for project configuration elements in working set configurations. Factories are registered against project natures via nested <tt><nature></tt> elements.
+
+
+
+
+
+
+
+
+
+ A unique identifier for the project configuration factory.
+
+
+
+
+
+
+ Fully qualified name of the factory class. It must implement the <tt>IWorkingSetProjectConfigurationFactory</tt> interface.
+
+
+
+
+
+
+
+
+
+
+
+
+ A reference to a project nature.
+
+
+
+
+
+
+ The referenced project nature ID.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 6.0
+
+
+
+
+
+
+
+
+ <pre>
+<extension point="org.eclipse.cdt.ui.workingSetConfigurations">
+ <projectConfigurationFactory
+ id="org.example.myProject"
+ class="org.example.MyProjectConfigurationFactory">
+ <nature id="org.example.myProjectNature"/>
+ </projectConfigurationFactory>
+</extension>
+</pre>
+
+
+
+
+
+
+
+
+ Registered project configuration factories are required to implement the <tt>org.eclipse.cdt.internal.ui.workingsets.IWorkingSetProjectConfigurationFactory</tt> interface.
+
+
+
+
+
+
+
+
+
+ Copyright (c) 2009 QNX Software Systems and others. All rights reserved.
+
+
+
+
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetConfigsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetConfigsContribution.java
new file mode 100644
index 00000000000..bb4a174d41f
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetConfigsContribution.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.actions.CompoundContributionItem;
+
+import com.ibm.icu.text.Collator;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+
+/**
+ * Common API of dynamic contribution of items to manipulate configurations of a working set.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+abstract class AbstractWorkingSetConfigsContribution extends CompoundContributionItem {
+
+ private IWorkingSetProxy workingSet;
+
+ private Comparator configOrdering = new Comparator() {
+ private Collator collator = Collator.getInstance();
+
+ public int compare(IWorkingSetConfiguration o1, IWorkingSetConfiguration o2) {
+ return collator.compare(o1.getName(), o2.getName());
+ }
+ };
+
+ /**
+ * Initializes me without a working set. I figure it out, later. This is only appropriate usage for
+ * context-menu contribution, where the workbench selection is obvious.
+ */
+ public AbstractWorkingSetConfigsContribution() {
+ super();
+ }
+
+ /**
+ * Initializes me with my working set.
+ *
+ * @param workingSet
+ * my working set
+ */
+ AbstractWorkingSetConfigsContribution(IWorkingSetProxy workingSet) {
+ super();
+
+ this.workingSet = workingSet;
+ }
+
+ @Override
+ protected IContributionItem[] getContributionItems() {
+ if (getWorkingSet() == null) {
+ return new IContributionItem[0];
+ }
+
+ // sort the configurations by name
+ List configs = new java.util.ArrayList(
+ getWorkingSet().getConfigurations());
+ Collections.sort(configs, configOrdering);
+
+ IContributionItem[] result = new IContributionItem[configs.size()];
+ int i = 0;
+ for (IWorkingSetConfiguration next : configs) {
+ result[i] = createContribution(next, i);
+ i++;
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a contribution item for a specific configuration of my working set.
+ *
+ * @param config
+ * a configuration of my working set
+ * @param index
+ * the index of the contribution in the composite
+ *
+ * @return the contribution
+ */
+ protected abstract IContributionItem createContribution(IWorkingSetConfiguration config, int index);
+
+ /**
+ * Obtains my working set. It may be lazily determined from the current workbench selection.
+ *
+ * @return my working set
+ */
+ protected IWorkingSetProxy getWorkingSet() {
+ if (workingSet == null) {
+ ISelection sel = CUIPlugin.getActivePage().getSelection();
+ if (sel instanceof IStructuredSelection) {
+ IStructuredSelection ssel = (IStructuredSelection) sel;
+
+ if (!ssel.isEmpty()) {
+ Object first = ssel.getFirstElement();
+ if (first instanceof IWorkingSet) {
+ workingSet = WorkingSetConfigurationManager.getDefault().getWorkingSet(
+ ((IWorkingSet) first).getName());
+ }
+ }
+ }
+ }
+
+ return workingSet;
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetsContribution.java
new file mode 100644
index 00000000000..5c091cdd365
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/AbstractWorkingSetsContribution.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.IWorkingSetManager;
+import org.eclipse.ui.actions.CompoundContributionItem;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+
+/**
+ * A dynamic contribution of sub-menus for working set configuration actions, with further sub-menus showing
+ * the configurations to choose from.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+abstract class AbstractWorkingSetsContribution extends CompoundContributionItem {
+
+ private IWorkingSetManager workingSetManager;
+
+ /**
+ * Initializes me without an identifier.
+ */
+ public AbstractWorkingSetsContribution() {
+ super();
+ }
+
+ /**
+ * Initializes me with my identifier.
+ *
+ * @param id
+ * my identifier
+ */
+ public AbstractWorkingSetsContribution(String id) {
+ super(id);
+ }
+
+ @Override
+ protected IContributionItem[] getContributionItems() {
+ // at most 5 recent working sets
+ List result = new java.util.ArrayList(5);
+
+ int i = 0;
+ for (IWorkingSet recent : getWorkingsetManager().getRecentWorkingSets()) {
+ IWorkingSetProxy proxy = WorkingSetConfigurationManager.getDefault().getWorkingSet(
+ recent.getName());
+
+ if (proxy != null) {
+ IContributionItem item = createMenu(proxy, i++);
+ if (item != null) {
+ result.add(item);
+ }
+ }
+ }
+
+ return result.toArray(new IContributionItem[result.size()]);
+ }
+
+ private IWorkingSetManager getWorkingsetManager() {
+ if (workingSetManager == null) {
+ workingSetManager = CUIPlugin.getDefault().getWorkbench().getWorkingSetManager();
+ }
+
+ return workingSetManager;
+ }
+
+ private IContributionItem createMenu(IWorkingSetProxy workingSet, int index) {
+ IContributionItem result = null;
+ IWorkingSet ws = workingSet.resolve();
+ String label = NLS.bind(WorkingSetMessages.WorkingSetMenus_enumPattern, index + 1, ws.getLabel());
+ Collection configs = workingSet.getConfigurations();
+
+ if (!configs.isEmpty()) {
+ MenuManager submenu = new MenuManager(label, ws.getName());
+ result = submenu;
+
+ submenu.add(createContribution(workingSet));
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a contribution item for a working set.
+ *
+ * @param workingSet
+ * a working set
+ * @return the contribution
+ */
+ protected abstract IContributionItem createContribution(IWorkingSetProxy workingSet);
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetConfigsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetConfigsContribution.java
new file mode 100644
index 00000000000..66843754812
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetConfigsContribution.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A dynamic contribution of items to activate configurations of a working set.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public class ActivateWorkingSetConfigsContribution extends AbstractWorkingSetConfigsContribution {
+
+ /**
+ * Initializes me without a working set. I figure it out, later. This is only appropriate usage for
+ * context-menu contribution, where the workbench selection is obvious.
+ */
+ public ActivateWorkingSetConfigsContribution() {
+ super();
+ }
+
+ /**
+ * Initializes me with my working set.
+ *
+ * @param workingSet
+ * my working set
+ */
+ ActivateWorkingSetConfigsContribution(IWorkingSetProxy workingSet) {
+ super(workingSet);
+ }
+
+ @Override
+ protected IContributionItem createContribution(IWorkingSetConfiguration config, int index) {
+ return new ActionContributionItem(new ActivateConfigAction(config, index + 1));
+ }
+
+ //
+ // Nested classes
+ //
+
+ private static class ActivateConfigAction extends Action {
+ private IWorkingSetConfiguration workingSetConfig;
+
+ ActivateConfigAction(IWorkingSetConfiguration workingSetConfig, int ordinal) {
+ super(NLS.bind(WorkingSetMessages.WorkingSetMenus_enumPattern, ordinal, workingSetConfig
+ .getName()));
+
+ this.workingSetConfig = workingSetConfig;
+ }
+
+ @Override
+ public void run() {
+ workingSetConfig.activate();
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetsContribution.java
new file mode 100644
index 00000000000..542404d1a5b
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ActivateWorkingSetsContribution.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.jface.action.IContributionItem;
+
+/**
+ * A dynamic contribution of sub-menus to activate working sets, with further sub-menus showing the
+ * configurations to choose from.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public class ActivateWorkingSetsContribution extends AbstractWorkingSetsContribution {
+
+ /**
+ * Initializes me.
+ */
+ public ActivateWorkingSetsContribution() {
+ super();
+ }
+
+ @Override
+ protected IContributionItem createContribution(IWorkingSetProxy workingSet) {
+ return new ActivateWorkingSetConfigsContribution(workingSet);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildJob.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildJob.java
new file mode 100644
index 00000000000..be10196b11d
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildJob.java
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2009 Intel Corporation, QNX Software Systems, and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Intel Corporation - initial API and implementation
+ * QNX Software Systems - [272416] Rework the working set configurations
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.newui.UIMessages;
+
+/**
+ * A job that builds a bunch of workspace projects or a working set configuration.
+ */
+public final class BuildJob extends Job {
+ private Collection projects;
+ private IWorkingSetConfiguration workingSetConfig;
+
+ /**
+ * Initializes me with a bunch projects to build in their active configurations.
+ *
+ * @param projects
+ * the projects to build
+ */
+ public BuildJob(Collection projects) {
+ super(UIMessages.getString("WorkingSetConfigAction.21")); //$NON-NLS-1$
+ this.projects = new java.util.ArrayList(projects);
+ }
+
+ /**
+ * Initializes me with a working set configuration to build.
+ *
+ * @param workingSetConfig
+ * the working set configuration to build
+ */
+ public BuildJob(IWorkingSetConfiguration workingSetConfig) {
+ super(UIMessages.getString("WorkingSetConfigAction.21")); //$NON-NLS-1$
+ this.workingSetConfig = workingSetConfig;
+ }
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ if (projects != null) {
+ return buildProjects(monitor);
+ } else {
+ return buildWorkingSetConfig(monitor);
+ }
+ }
+
+ private IStatus buildProjects(IProgressMonitor monitor) {
+ try {
+ for (IProject p : projects) {
+ try {
+ setName(UIMessages.getString("WorkingSetConfigAction.21") + p.getName()); //$NON-NLS-1$
+ p.build(IncrementalProjectBuilder.INCREMENTAL_BUILD, monitor);
+ } catch (CoreException e) {
+ return new MultiStatus(CUIPlugin.PLUGIN_ID, 0, new IStatus[] { e.getStatus() },
+ UIMessages.getString("WorkingSetConfigAction.22"), //$NON-NLS-1$
+ null);
+ }
+ if (monitor.isCanceled()) {
+ return Status.CANCEL_STATUS;
+ }
+ }
+ } finally {
+ monitor.done();
+ }
+ return Status.OK_STATUS;
+ }
+
+ private IStatus buildWorkingSetConfig(IProgressMonitor monitor) {
+ try {
+ return workingSetConfig.build(monitor);
+ } finally {
+ monitor.done();
+ }
+ }
+
+ @Override
+ public boolean belongsTo(Object family) {
+ return ResourcesPlugin.FAMILY_MANUAL_BUILD == family;
+ }
+
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetConfigsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetConfigsContribution.java
new file mode 100644
index 00000000000..b6b52507185
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetConfigsContribution.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A dynamic contribution of items to build configurations of a working set.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public class BuildWorkingSetConfigsContribution extends AbstractWorkingSetConfigsContribution {
+
+ /**
+ * Initializes me without a working set. I figure it out, later. This is only appropriate usage for
+ * context-menu contribution, where the workbench selection is obvious.
+ */
+ public BuildWorkingSetConfigsContribution() {
+ super();
+ }
+
+ /**
+ * Initializes me with my working set.
+ *
+ * @param workingSet
+ * my working set
+ */
+ BuildWorkingSetConfigsContribution(IWorkingSetProxy workingSet) {
+ super(workingSet);
+ }
+
+ @Override
+ protected IContributionItem createContribution(IWorkingSetConfiguration config, int index) {
+ return new ActionContributionItem(new BuildConfigAction(config, index + 1));
+ }
+
+ //
+ // Nested classes
+ //
+
+ private static class BuildConfigAction extends Action {
+ private IWorkingSetConfiguration workingSetConfig;
+
+ BuildConfigAction(IWorkingSetConfiguration workingSetConfig, int ordinal) {
+ super(NLS.bind(WorkingSetMessages.WorkingSetMenus_enumPattern, ordinal, workingSetConfig
+ .getName()));
+
+ this.workingSetConfig = workingSetConfig;
+ }
+
+ @Override
+ public void run() {
+ new BuildJob(workingSetConfig).schedule();
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetsContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetsContribution.java
new file mode 100644
index 00000000000..c0707a70082
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/BuildWorkingSetsContribution.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.jface.action.IContributionItem;
+
+/**
+ * A dynamic contribution of sub-menus to build working sets, with further sub-menus showing the
+ * configurations to choose from.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public class BuildWorkingSetsContribution extends AbstractWorkingSetsContribution {
+
+ /**
+ * Initializes me.
+ */
+ public BuildWorkingSetsContribution() {
+ super();
+ }
+
+ @Override
+ protected IContributionItem createContribution(IWorkingSetProxy workingSet) {
+ return new BuildWorkingSetConfigsContribution(workingSet);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfiguration.java
new file mode 100644
index 00000000000..a57d734e4d2
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfiguration.java
@@ -0,0 +1,181 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+
+/**
+ *
+ * The protocol for working set configurations. A working set configuration specifies, at a minimum, a
+ * {@linkplain ICConfigurationDescription build configuration} for each C/C++ project in the working set.
+ * {@linkplain #activate() activating} the configuration applies these build configurations to the respective
+ * projects as their active build configurations.
+ *
+ *
+ * Implementations of this interface may choose to manage more configuration settings than are captured by the
+ * active build configuration. They are, then, responsible for persistence, editing, and application of these
+ * settings.
+ *
+ *
+ * A working set configuration is considered to be {@linkplain #isActive() active} if all of the projects in
+ * the working set are configured to build according to the configuration specified by the working set
+ * configuration. It is an implementation detail (i.e., unspecified) what it means for a working set that has
+ * recorded settings for projects that are not currently {@linkplain IResource#isAccessible() accessible} in
+ * the workspace. However, for projects that are accessible and are included in the working set, but for which
+ * the working set configuration has no settings, such projects are implicitly in the working set
+ * configuration and it specifies their current configuration settings. Thus, in the extreme case, a
+ * working-set configuration that includes none of the projects that currently are members of the working set,
+ * is active.
+ *
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public interface IWorkingSetConfiguration extends IWorkingSetConfigurationElement {
+ /**
+ * Obtains the working set element that contains me.
+ *
+ * @return my working set
+ */
+ IWorkingSetProxy getWorkingSet();
+
+ /**
+ * Queries my name.
+ *
+ * @return my name
+ */
+ String getName();
+
+ /**
+ * Obtains the project configuration element for the specified project.
+ *
+ * @param projectName
+ * a project name
+ *
+ * @return that project's configuration element
+ *
+ * @throws IllegalArgumentException
+ * if the specified project is not a member of my working set
+ *
+ * @see #getProjectConfigurations()
+ */
+ IWorkingSetProjectConfiguration getProjectConfiguration(String projectName);
+
+ /**
+ * Obtains the configuration elements for all of the projects in my working set. These include any
+ * projects that were not in my working set when I was last updated, and does not include any projects
+ * that were in my working set when I was last updated but that no longer are.
+ *
+ * @return my project configuration elements
+ */
+ Collection getProjectConfigurations();
+
+ /**
+ * Queries whether I am currently active in the workspace. I am active if and only if for every the
+ * projects in my working set, its active configuration is the one that I specify for it. As a special
+ * case, the configurations of an empty working set can never be active.
+ *
+ * @return whether I am currently active in the workspace
+ *
+ * @see #activate()
+ */
+ boolean isActive();
+
+ /**
+ * Updates the workspace to set, for each project in my working set, the active configuration that I
+ * specify for it. This method has no effect if I am already active.
+ *
+ * @see #isActive()
+ */
+ void activate();
+
+ /**
+ * Builds my project configurations in the workspace.
+ *
+ * @param monitor
+ * for reporting progress of the working-set build
+ * @return the aggregate status of the individual
+ * {@linkplain IWorkingSetProjectConfiguration#build(IProgressMonitor) project builds}
+ */
+ IStatus build(IProgressMonitor monitor);
+
+ /**
+ * Creates a snapshot (also known as a "working copy") of myself, providing a mutable view suitable
+ * for editing.
+ *
+ * @param workingSet
+ * my parent working set snapshot
+ * @param workspace
+ * a workspace snapshot that captures the baseline state of the workspace and the working set
+ * configurations that are to be edited
+ *
+ * @return a working-copy snapshot of myself
+ */
+ ISnapshot createSnapshot(IWorkingSetProxy.ISnapshot workingSet, WorkspaceSnapshot workspace);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * The snapshot ("working copy") view of a working set configuration. It defines additional API for the
+ * manipulation of working set configurations.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+ interface ISnapshot extends IWorkingSetConfiguration, IWorkingSetConfigurationElement.ISnapshot {
+ IWorkingSetProxy.ISnapshot getWorkingSet();
+
+ /**
+ *
+ * Queries whether I am read-only. Read-only working set configurations are used for the special case
+ * of showing what is the active configuration of the projects in a working set when none of the named
+ * working set configurations is active. Thus, a working set that has no user-defined named
+ * configurations does, at least, have its read-only active configuration.
+ *
+ *
+ * A working set only ever has at most one read-only configuration, though it may have multiple active
+ * configurations if some of its configurations are equivalent.
+ *
+ *
+ * @return whether I am the read-only active configuration of my working set
+ */
+ boolean isReadOnly();
+
+ /**
+ * Sets my name, which must be unique amongst the configurations in my working set.
+ *
+ * @param name
+ * my new, unique name
+ *
+ * @throws IllegalArgumentException
+ * if the new name is null or empty, or if it is already used by another
+ * configuration of the same working set
+ */
+ void setName(String name);
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfigurationElement.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfigurationElement.java
new file mode 100644
index 00000000000..b060014c9fb
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetConfigurationElement.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.ui.IMemento;
+import org.eclipse.ui.IPersistable;
+
+/**
+ * The protocol for elements of the working-set configuration model, which can be persisted via
+ * {@linkplain IMemento mementos}.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ */
+public interface IWorkingSetConfigurationElement extends IPersistable {
+ /**
+ * Loads me from the specified memento.
+ *
+ * @param memento
+ * a memento in which I am persisted
+ */
+ void loadState(IMemento memento);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * The protocol for mutable working-copies ("snapshots") of working set configuration model elements.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ * @see WorkspaceSnapshot
+ */
+ interface ISnapshot {
+ /**
+ * Obtains the workspace snapshot that describes the baseline state of the working-set configuration
+ * editing session of which I am a part.
+ *
+ * @return my base workspace snapshot
+ */
+ WorkspaceSnapshot getWorkspaceSnapshot();
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfiguration.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfiguration.java
new file mode 100644
index 00000000000..e3f1b53d2dc
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfiguration.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+
+/**
+ *
+ * The protocol for project configurations in a working set configuration. At a minimum, the project
+ * configuration specifies which build configuration is {@linkplain #getSelectedConfigurationID() selected} to
+ * be set as the project's active configuration. Implementations are free to add more configuration
+ * information than the selected build configuration.
+ *
+ *
+ * Note that project configurations are owned by working set configurations. Thus, different configurations of
+ * the same (or different) working set may specify different settings for the same project.
+ *
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public interface IWorkingSetProjectConfiguration extends IWorkingSetConfigurationElement {
+ /**
+ * Obtains the working set configuration element that owns me.
+ *
+ * @return my working set configuration
+ */
+ IWorkingSetConfiguration getWorkingSetConfiguration();
+
+ /**
+ * Queries the name of the project that I configure.
+ *
+ * @return my project name
+ */
+ String getProjectName();
+
+ /**
+ * Resolves my project name to the actual project resource in the workspace.
+ *
+ * @return my referenced project, or null if the project is not
+ * {@linkplain IResource#isAccessible() accessible} in the workspace
+ */
+ IProject resolveProject();
+
+ /**
+ * Queries the ID of the build configuration that is currently selected for my project.
+ *
+ * @return my selected build configuration ID
+ */
+ String getSelectedConfigurationID();
+
+ /**
+ * Sets the ID of the build configuration that is currently selected for my project.
+ *
+ * @param id
+ * my selected build configuration ID
+ */
+ void setSelectedConfigurationID(String id);
+
+ /**
+ *
+ * Resolves my selected configuration reference to the C model's description handle for it.
+ *
+ *
+ * Note that, in the general case, it is possible for the configuration to resolve to a different
+ * object from one call to the next, but always representing the same configuration. However, in the case
+ * of a working-copy {@linkplain IWorkingSetProjectConfiguration.ISnapshot snapshot} of me, the result
+ * will always be the same object.
+ *
+ *
+ * @return the C model representation of my selected build configuration
+ *
+ * @see #resolveConfigurations()
+ */
+ ICConfigurationDescription resolveSelectedConfiguration();
+
+ /**
+ *
+ * Resolves the set of available configurations of my project.
+ *
+ *
+ * Note that, in the general case, it is possible for these configurations to resolve to different
+ * objects from one call to the next, but always representing the same configurations. However, in the
+ * case of a working-copy {@linkplain IWorkingSetProjectConfiguration.ISnapshot snapshot} of me, the
+ * results will always be the same objects.
+ *
+ *
+ * @return the C model representation of my selected available build configurations
+ *
+ * @see #resolveSelectedConfiguration()
+ */
+ Collection resolveConfigurations();
+
+ /**
+ * Queries whether my project currently has my selected configuration active in the workspace.
+ *
+ * @return whether I am my project's active configuration
+ *
+ * @see #getSelectedConfigurationID()
+ * @see #activate()
+ */
+ boolean isActive();
+
+ /**
+ * Activates my selected configuration in the workspace, for my project.
+ *
+ * @see #getSelectedConfigurationID()
+ * @see #setSelectedConfigurationID(String)
+ * @see #isActive()
+ */
+ void activate();
+
+ /**
+ * Builds my selected configuration in the workspace, for my project. If building the configuration
+ * actually requires activating it, and it was not already active, then it would be a good idea to return
+ * a warning status indicating that the active configuration had to be changed in order to effect the
+ * build.
+ *
+ * @param monitor
+ * a progress monitor to report build progress
+ * @return a status indicating any error or warning conditions in the invocation of the build
+ */
+ IStatus build(IProgressMonitor monitor);
+
+ /**
+ * Creates a snapshot (also known as a "working copy") of myself, providing a mutable view suitable
+ * for editing.
+ *
+ * @param workingSetConfig
+ * my parent working set configuration snapshot
+ * @param workspace
+ * a workspace snapshot that captures the baseline state of the workspace and the working set
+ * configurations that are to be edited
+ *
+ * @return a working-copy snapshot of myself
+ */
+ ISnapshot createSnapshot(IWorkingSetConfiguration.ISnapshot workingSetConfig, WorkspaceSnapshot workspace);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * The snapshot ("working copy") view of a working set project configuration.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+ interface ISnapshot extends IWorkingSetProjectConfiguration, IWorkingSetConfigurationElement.ISnapshot {
+ IWorkingSetConfiguration.ISnapshot getWorkingSetConfiguration();
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationController.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationController.java
new file mode 100644
index 00000000000..bfb1c82dc9f
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationController.java
@@ -0,0 +1,176 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Protocol for the view controller for the project configurations pane of the working set configurations
+ * dialog. It takes care of coordinating the user gestures in that pane with the working-set configuration
+ * model and vice-versa.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ */
+public interface IWorkingSetProjectConfigurationController {
+ /**
+ * Queries the project configuration in the Working Set Configurations pane that I control.
+ *
+ * @return the new working set configuration selection. May be null if there is no selection
+ */
+ IWorkingSetProjectConfiguration.ISnapshot getProjectConfiguration();
+
+ /**
+ * Notifies me that the check state of some element that I control in the sub-tree of my
+ * {@linkplain #getProjectConfiguration() project configuration} has changed its check-state. The
+ * controller context can be used to pass back reactions such as to veto the check-state change or to
+ * signal that some level of UI refresh is required.
+ *
+ * @param element
+ * an element that has been checked or unchecked
+ * @param checked
+ * whether the element is now checked
+ * @param context
+ * the controller context, used to communicate vetos, refreshes, etc.
+ */
+ void checkStateChanged(Object element, boolean checked, IControllerContext context);
+
+ /**
+ * Computes the initial check-box settings for my tree according to the current state of my
+ * {@linkplain #getProjectConfiguration() project configuration}.
+ *
+ * @param context
+ * context in which I can set initial check-states of my elements
+ */
+ void updateCheckState(IControllerContext context);
+
+ /**
+ * Obtains a content provider for the structure rooted at my {@linkplain #getProjectConfiguration()
+ * project configuration}. Note that this method will only be called once, and that the caller takes
+ * responsibility for {@linkplain IContentProvider#dispose() disposing} the content provider.
+ *
+ * @return my content provider
+ */
+ ITreeContentProvider getContentProvider();
+
+ /**
+ *
+ * Obtains a label provider for the structure rooted at my {@linkplain #getProjectConfiguration() project
+ * configuration}. Note that this method will only be called once, and that the caller takes
+ * responsibility for {@linkplain IBaseLabelProvider#dispose() disposing} the label provider.
+ *
+ *
+ * The viewer argument is useful to obtain information about default font and colors, for label providers
+ * that implement the optional {@link IFontProvider} and/or {@link IColorProvider} interfaces.
+ *
+ *
+ * @param viewer
+ * the viewer for which I will provide labels
+ *
+ * @return my label provider
+ */
+ ILabelProvider getLabelProvider(Viewer viewer);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * An interface provided by the Manage Working Set Configurations dialog infrastructure to
+ * {@link IWorkingSetProjectConfigurationController}s for communication of state changes back to the UI.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @author Christian W. Damus (damus)
+ *
+ * @since 6.0
+ */
+ interface IControllerContext {
+ /**
+ * Queries whether the current working set configuration context is a read-only one. In such cases, I
+ * should probably disallow check-state changes and other editing.
+ *
+ * @return whether the current working set configuration is read-only
+ *
+ * @see IWorkingSetConfiguration.ISnapshot#isReadOnly()
+ */
+ boolean isReadOnly();
+
+ /**
+ * Sets the check state of an element in the Project Configurations pane under the authority of the
+ * controller. This is particularly useful for setting the
+ * {@linkplain IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext) initial
+ * check state} of a controller and for
+ * {@linkplain IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean, IControllerContext)
+ * vetoing check state changes}.
+ *
+ * @param element
+ * the element to update checked
+ * @param checked
+ * whether the element should be checked
+ *
+ * @see IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean,
+ * IControllerContext)
+ * @see IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext)
+ * @see #setGrayed(Object, boolean)
+ */
+ void setChecked(Object element, boolean checked);
+
+ /**
+ * Sets the gray state of an element in the Project Configurations pane under the authority of the
+ * controller. This is particularly useful for setting the
+ * {@linkplain IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext) initial
+ * check state} of a controller and for
+ * {@linkplain IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean, IControllerContext)
+ * responding to check state changes}.
+ *
+ * @param element
+ * the element to update checked
+ * @param checked
+ * whether the element should be checked
+ *
+ * @see IWorkingSetProjectConfigurationController#checkStateChanged(Object, boolean,
+ * IControllerContext)
+ * @see IWorkingSetProjectConfigurationController#updateCheckState(IControllerContext)
+ * @see #setChecked(Object, boolean)
+ */
+ void setGrayed(Object element, boolean grayed);
+
+ /**
+ * Requests an update of the visual appearance of the specified element. The element may be any
+ * element under my control, or even the {@link IWorkingSetConfiguration} or {@link IWorkingSetProxy}
+ * that owns my project configuration.
+ *
+ * @param element
+ * an element to update
+ */
+ void update(Object element);
+
+ /**
+ * Notifies that the specified project configuration's activation state has changed. That is, that it
+ * is now activated when previously it was not, or vice-versa.
+ *
+ * @param project
+ * configuration the project configuration that changed
+ */
+ void activationStateChanged(IWorkingSetProjectConfiguration projectConfiguration);
+ }
+}
\ No newline at end of file
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationFactory.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationFactory.java
new file mode 100644
index 00000000000..87358cbaf34
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProjectConfigurationFactory.java
@@ -0,0 +1,394 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectNatureDescriptor;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.ui.CUIPlugin;
+
+import org.eclipse.cdt.internal.ui.workingsets.WorkspaceSnapshot.ProjectState;
+
+/**
+ * Protocol for a factory of {@link IWorkingSetProjectConfiguration}s. Factories are {@linkplain Registry
+ * registered} against project natures.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+public interface IWorkingSetProjectConfigurationFactory {
+ /**
+ * Queries my factory ID. The ID is persisted in the working set configuration data so that the same
+ * factory can be used to reconstruct project configurations when loading the working set configurations.
+ *
+ * @return my unique identifier
+ */
+ String getID();
+
+ /**
+ * Creates a new project configuration element.
+ *
+ * @param parent
+ * the working set configuration that owns the new project configuration
+ * @param project
+ * the workspace project for which to create the configuration
+ *
+ * @return the new project configuration
+ */
+ IWorkingSetProjectConfiguration createProjectConfiguration(IWorkingSetConfiguration parent,
+ IProject project);
+
+ /**
+ * Creates a UI controller to support editing the specified project configuration snapshot, which should
+ * have been obtained from a configuration that I previously
+ * {@linkplain #createProjectConfiguration(org.eclipse.cdt.internal.ui.workingsets.IWorkingSetConfiguration, IProject)
+ * created}, myself.
+ *
+ * @param config
+ * a project configuration snapshot that I created
+ *
+ * @return a suitable controller for it. Must not be null
+ */
+ IWorkingSetProjectConfigurationController createProjectConfigurationController(
+ IWorkingSetProjectConfiguration.ISnapshot config);
+
+ /**
+ * Creates a snapshot of the configuration state of a project in the workspace. This may capture
+ * additional build meta-data beyond just the "active configuration."
+ *
+ * @param project
+ * a project to capture in a {@link WorkspaceSnapshot}
+ * @param desc
+ * the project description, from which to capture the initial configuration data
+ *
+ * @return the project state capture. Must not be null
+ */
+ WorkspaceSnapshot.ProjectState createProjectState(IProject project, ICProjectDescription desc);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * A registry of {@linkplain IWorkingSetProjectConfigurationFactory project configuration factories}
+ * contributed on the org.eclipse.cdt.ui.workingSetConfigurations extension point.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+ class Registry {
+ private static final String EXT_PT_ID = "workingSetConfigurations"; //$NON-NLS-1$
+ private static final String E_FACTORY = "projectConfigurationFactory"; //$NON-NLS-1$
+ private static final String E_NATURE = "projectNature"; //$NON-NLS-1$
+ private static final String A_ID = "id"; //$NON-NLS-1$
+ private static final String A_CLASS = "class"; //$NON-NLS-1$
+
+ /**
+ * The shared project configuration factory registry.
+ */
+ public static Registry INSTANCE = new Registry();
+
+ private final IWorkingSetProjectConfigurationFactory defaultFactory = new Default();
+ private final Map factoriesByID = new java.util.HashMap();
+ private final Map factoriesByNature = new java.util.HashMap();
+
+ private Map> projectNaturePartOrdering;
+
+ private Registry() {
+ super();
+
+ projectNaturePartOrdering = computeProjectNaturePartOrdering();
+
+ loadExtensions();
+ }
+
+ public IWorkingSetProjectConfigurationFactory getFactory(String id) {
+ IWorkingSetProjectConfigurationFactory result = get(factoriesByID, id);
+
+ if (result == null) {
+ result = defaultFactory;
+ }
+
+ return result;
+ }
+
+ public IWorkingSetProjectConfigurationFactory getFactory(IProject project) {
+ IWorkingSetProjectConfigurationFactory result = null;
+
+ for (String nature : getPartOrderedNatureIDs(project)) {
+ result = get(factoriesByNature, nature);
+
+ if (result != null) {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ private IWorkingSetProjectConfigurationFactory get(
+ Map, IWorkingSetProjectConfigurationFactory> map, Object key) {
+ return map.get(key);
+ }
+
+ private String[] getPartOrderedNatureIDs(IProject project) {
+ String[] result;
+
+ try {
+ result = project.getDescription().getNatureIds();
+ } catch (CoreException e) {
+ CUIPlugin.log(e.getStatus());
+ result = new String[0];
+ }
+
+ if (result.length > 0) {
+ Arrays.sort(result, new Comparator() {
+ public int compare(String nature1, String nature2) {
+ Set required1 = projectNaturePartOrdering.get(nature1);
+ Set required2 = projectNaturePartOrdering.get(nature2);
+
+ if (required1.contains(nature2)) {
+ return -1; // required1 precedes required2
+ } else if (required2.contains(nature1)) {
+ return +1; // required2 precedes required1
+ } else if (nature1.startsWith("org.eclipse.cdt.") //$NON-NLS-1$
+ && !nature2.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
+ return +1; // lower priority to CDT natures
+ } else if (nature2.startsWith("org.eclipse.cdt.") //$NON-NLS-1$
+ && !nature1.startsWith("org.eclipse.cdt.")) { //$NON-NLS-1$
+ return -1; // lower priority to CDT natures
+ }
+
+ return 0; // not partially comparable
+ }
+ });
+ }
+
+ return result;
+ }
+
+ private Map> computeProjectNaturePartOrdering() {
+ Map> result = new java.util.HashMap>();
+
+ // first pass to populate the map with immediate requireds
+ IWorkspace ws = ResourcesPlugin.getWorkspace();
+ for (IProjectNatureDescriptor next : ws.getNatureDescriptors()) {
+ result.put(next.getNatureId(), new java.util.HashSet(Arrays.asList(next
+ .getRequiredNatureIds())));
+ }
+
+ // now, iterate to add transitive requireds
+ boolean loopAgain;
+ do {
+ loopAgain = false;
+
+ for (Map.Entry> next : result.entrySet()) {
+ Set requireds = next.getValue();
+ Set newRequireds = new java.util.HashSet(requireds);
+
+ boolean changed = false;
+
+ for (String required : requireds) {
+ changed |= newRequireds.addAll(result.get(required));
+ }
+
+ if (changed) {
+ loopAgain = true;
+ next.setValue(newRequireds);
+ }
+ }
+ } while (loopAgain);
+
+ return result;
+ }
+
+ private void loadExtensions() {
+ IExtensionRegistry registry = Platform.getExtensionRegistry();
+ for (IExtension ext : registry.getExtensionPoint(CUIPlugin.PLUGIN_ID, EXT_PT_ID).getExtensions()) {
+ for (IConfigurationElement element : ext.getConfigurationElements()) {
+ if (E_FACTORY.equals(element.getName())) {
+ try {
+ Descriptor desc = new Descriptor(element);
+
+ synchronized (factoriesByID) {
+ factoriesByID.put(desc.getID(), desc);
+ }
+
+ synchronized (factoriesByNature) {
+ for (IConfigurationElement nature : element.getChildren(E_NATURE)) {
+ String natureID = nature.getAttribute(A_ID);
+
+ if (natureID != null) {
+ factoriesByNature.put(natureID, desc);
+ } else {
+ CUIPlugin.log(NLS.bind(
+ WorkingSetMessages.WSProjConfigFactory_noNatureID, ext
+ .getContributor().getName()), null);
+ }
+ }
+ }
+ } catch (CoreException e) {
+ CUIPlugin.log(e.getStatus());
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Nested classes
+ //
+
+ /**
+ * A self-resolving descriptor for lazy instantiation of a factory.
+ */
+ private class Descriptor implements IWorkingSetProjectConfigurationFactory {
+ private final IConfigurationElement extension;
+ private final String id;
+
+ Descriptor(IConfigurationElement extension) throws CoreException {
+ this.extension = extension;
+ id = extension.getAttribute(A_ID);
+
+ if (id == null) {
+ throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, NLS.bind(
+ WorkingSetMessages.WSProjConfigFactory_noFactoryID, extension.getContributor()
+ .getName())));
+ }
+ }
+
+ public String getID() {
+ return id;
+ }
+
+ public IWorkingSetProjectConfiguration createProjectConfiguration(
+ IWorkingSetConfiguration parent, IProject project) {
+ return resolve().createProjectConfiguration(parent, project);
+ }
+
+ public IWorkingSetProjectConfigurationController createProjectConfigurationController(
+ IWorkingSetProjectConfiguration.ISnapshot config) {
+
+ return resolve().createProjectConfigurationController(config);
+ }
+
+ public ProjectState createProjectState(IProject project, ICProjectDescription desc) {
+ return resolve().createProjectState(project, desc);
+ }
+
+ private IWorkingSetProjectConfigurationFactory resolve() {
+ IWorkingSetProjectConfigurationFactory result = null;
+
+ try {
+ result = (IWorkingSetProjectConfigurationFactory) extension
+ .createExecutableExtension(A_CLASS);
+ } catch (ClassCastException e) {
+ CUIPlugin.log(NLS.bind(WorkingSetMessages.WSProjConfigFactory_badFactory, extension
+ .getContributor().getName()), e);
+ } catch (CoreException e) {
+ CUIPlugin.log(new MultiStatus(CUIPlugin.PLUGIN_ID, 0, new IStatus[] { e.getStatus() },
+ WorkingSetMessages.WSProjConfigFactory_factoryFailed, null));
+ }
+
+ if (result == null) {
+ result = defaultFactory;
+ }
+
+ // replace the descriptor in the maps
+ synchronized (factoriesByID) {
+ factoriesByID.put(getID(), result);
+ }
+ synchronized (factoriesByNature) {
+ for (Map.Entry next : factoriesByNature
+ .entrySet()) {
+ if (next.getValue().getID().equals(getID())) {
+ next.setValue(result);
+ }
+ }
+ }
+
+ return result;
+ }
+ }
+
+ /**
+ * The default project configuration factory. Clients may extend this class to implement custom
+ * factories for their project natures.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+ public static class Default implements IWorkingSetProjectConfigurationFactory, IExecutableExtension {
+
+ private String id;
+
+ public Default() {
+ super();
+ }
+
+ public IWorkingSetProjectConfiguration createProjectConfiguration(
+ IWorkingSetConfiguration parent, IProject project) {
+
+ WorkingSetProjectConfiguration result = createProjectConfiguration(parent);
+ result.setProjectName(project.getName());
+ return result;
+ }
+
+ protected WorkingSetProjectConfiguration createProjectConfiguration(
+ IWorkingSetConfiguration parent) {
+ return new WorkingSetProjectConfiguration(parent);
+ }
+
+ public IWorkingSetProjectConfigurationController createProjectConfigurationController(
+ IWorkingSetProjectConfiguration.ISnapshot config) {
+
+ return new ProjectConfigurationController(config);
+ }
+
+ public ProjectState createProjectState(IProject project, ICProjectDescription desc) {
+ return new WorkspaceSnapshot.ProjectState(project, desc);
+ }
+
+ public String getID() {
+ return id;
+ }
+
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data)
+ throws CoreException {
+
+ this.id = config.getAttribute(A_ID);
+ }
+
+ }
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProxy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProxy.java
new file mode 100644
index 00000000000..30c84ded942
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/IWorkingSetProxy.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.ui.IWorkingSet;
+
+/**
+ * The protocol for elements representing working sets, providing proxies for the workbench's actual
+ * {@link IWorkingSet}s. A working set may have zero or more {@linkplain IWorkingSetConfiguration
+ * configurations} that aggregate configuration settings for the C/C++ projects in the working set.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ */
+public interface IWorkingSetProxy extends IWorkingSetConfigurationElement {
+ /**
+ * Queries my name. This is the {@link IWorkingSet#getName() name} of my referenced working set, not its
+ * {@link IWorkingSet#getLabel() label}. As my referenced working set's name changes, so does my name.
+ *
+ * @return my working set's name
+ */
+ String getName();
+
+ /**
+ * Resolves me to the actual working set as maintained by the workbench.
+ *
+ * @return my referenced working set, or null if it no longer exists
+ */
+ IWorkingSet resolve();
+
+ /**
+ * Resolves the actual existing projects in my working set, that are currently
+ * {@linkplain IResource#isAccessible() accessible} in the workspace.
+ *
+ * @return my projects
+ */
+ Collection resolveProjects();
+
+ /**
+ * Queries whether I am a valid working set proxy, to be displayed to and manipulated by the user. This
+ * should at least check that the proxy {@linkplain #resolve() resolves} to an existing working set and
+ * that it includes at least one {@linkplain #resolveProjects() project}.
+ *
+ * @return whether I am a valid working set proxy
+ */
+ boolean isValid();
+
+ /**
+ * Obtains the named configuration of my working set.
+ *
+ * @param name
+ * a configuration name
+ *
+ * @return the matching configuration, or null if there is none such
+ */
+ IWorkingSetConfiguration getConfiguration(String name);
+
+ /**
+ * Obtains all of the configurations currently defined for my working set. If I am a working-copy
+ * {@linkplain IWorkingSetProxy.ISnapshot snapshot}, then these may include a special
+ * {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only} configuration indicating the
+ * active configurations of my projects, if none of my named configurations is
+ * {@linkplain IWorkingSetConfiguration#isActive() active}.
+ *
+ * @return my configurations
+ */
+ Collection getConfigurations();
+
+ /**
+ * Creates a snapshot (also known as a "working copy") of myself, providing a mutable view suitable
+ * for editing.
+ *
+ * @param workspace
+ * a workspace snapshot that captures the baseline state of the workspace and the working set
+ * configurations that are to be edited
+ *
+ * @return a working-copy snapshot of myself
+ */
+ ISnapshot createSnapshot(WorkspaceSnapshot workspace);
+
+ //
+ // Nested types
+ //
+
+ /**
+ * The snapshot ("working copy") view of a working set proxy. It has additional API for modifying
+ * configurations, which can then be {@linkplain WorkspaceSnapshot#save() saved} for posterity.
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @noextend This interface is not intended to be extended by clients.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ */
+ interface ISnapshot extends IWorkingSetProxy, IWorkingSetConfigurationElement.ISnapshot {
+ /**
+ * Creates a new configuration with the specified name.
+ *
+ * @param name
+ * a new configuration name
+ *
+ * @return the new configuration
+ *
+ * @throws IllegalArgumentException
+ * if the new name is null or empty, or if it is already used by another
+ * configuration of the same working set
+ */
+ IWorkingSetConfiguration.ISnapshot createConfiguration(String name);
+
+ /**
+ * Removes the specified configuration from me.
+ *
+ * @param config
+ * a configuration to remove
+ *
+ * @throws IllegalArgumentException
+ * if the configuration to be removed is
+ * {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only}
+ */
+ void removeConfiguration(IWorkingSetConfiguration config);
+
+ /**
+ *
+ * Updates me according to the (assumed to have changed) activation state of my configurations. If any
+ * named configurations are active and I currently have a "fake"
+ * {@linkplain IWorkingSetConfiguration.ISnapshot#isReadOnly() read-only} configuration, then it is
+ * removed and I signal a "major change."
+ *
+ *
+ * If I have no named configurations that are active, and currently have not got a read-only
+ * configuration to show the active configuration, then I create it and signal a "major change."
+ *
+ *
+ * It is assumed that the UI will refresh the tree structure rooted in me when I signal a major
+ * change.
+ *
+ *
+ * @return whether this update results in a "major change" to my child configuration structure
+ */
+ boolean updateActiveConfigurations();
+ }
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ProjectConfigsController.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ProjectConfigsController.java
new file mode 100644
index 00000000000..2623a9549f3
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ProjectConfigsController.java
@@ -0,0 +1,386 @@
+/*******************************************************************************
+ * Copyright (c) 2009 QNX Software Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * QNX Software Systems - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Map;
+
+import org.eclipse.jface.viewers.CheckStateChangedEvent;
+import org.eclipse.jface.viewers.CheckboxTreeViewer;
+import org.eclipse.jface.viewers.ICheckStateListener;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * View controller for the project configurations pane of the working set configurations dialog. It takes care
+ * of coordinating the user gestures in that pane with the working-set configuration model and vice-versa.
+ *
+ * @author Christian W. Damus (cdamus)
+ *
+ * @since 6.0
+ *
+ */
+class ProjectConfigsController implements ICheckStateListener, DisposeListener {
+ private CheckboxTreeViewer tree;
+
+ private IWorkingSetConfiguration.ISnapshot workingSet;
+ private WorkingSetConfigsController workingSetController;
+
+ private ControllerContext controllerContext;
+
+ private ILabelProvider labelProvider = new DelegatingLabelProvider();
+ private ITreeContentProvider contentProvider = new DelegatingContentProvider();
+
+ /**
+ * Initializes me.
+ */
+ ProjectConfigsController() {
+ super();
+ }
+
+ /**
+ * Assigns the tree viewer that I control.
+ *
+ * @param tree
+ * my tree viewer
+ */
+ void setTreeViewer(CheckboxTreeViewer tree) {
+ if (this.tree != null) {
+ this.tree.getTree().removeDisposeListener(this);
+ this.tree.removeCheckStateListener(this);
+ this.tree.setLabelProvider(null);
+ this.tree.setContentProvider(null);
+ }
+
+ this.tree = tree;
+
+ if (this.tree != null) {
+ this.tree.setUseHashlookup(true);
+ this.tree.setContentProvider(contentProvider);
+ this.tree.setLabelProvider(labelProvider);
+ this.tree.addCheckStateListener(this);
+ this.tree.getTree().addDisposeListener(this);
+ }
+ }
+
+ /**
+ * Injects the current selection of a working set from the Working Set Configurations pane. This changes
+ * the project configurations that I show in my own tree.
+ *
+ * @param config
+ * the new working set configuration selection. May be null if there is no
+ * selection
+ */
+ void setWorkingSetConfiguration(IWorkingSetConfiguration.ISnapshot config) {
+ if ((tree != null) && (config != workingSet)) {
+ this.workingSet = config;
+
+ tree.setSelection(new StructuredSelection());
+
+ if (config != null) {
+ controllerContext = new ControllerContext(tree);
+ tree.setInput(config);
+ tree.getTree().setEnabled(true);
+ updateCheckState(config);
+ tree.expandToLevel(2);
+ } else {
+ tree.getTree().setEnabled(false);
+ tree.setInput(config);
+ controllerContext.dispose();
+ controllerContext = null;
+ }
+ }
+ }
+
+ /**
+ * Queries the current working set configuration that I show in my tree.
+ *
+ * @return the working set configuration, or null if none
+ */
+ IWorkingSetConfiguration.ISnapshot getWorkingSetConfiguration() {
+ return workingSet;
+ }
+
+ public void checkStateChanged(CheckStateChangedEvent event) {
+ Object element = event.getElement();
+ IWorkingSetProjectConfigurationController controller = controllerContext
+ .controllerForElement(element);
+
+ if (controller != null) {
+ controller.checkStateChanged(element, event.getChecked(), controllerContext);
+
+ } else {
+ // controller unknown? Cannot change the check-state
+ tree.setChecked(element, !event.getChecked());
+ }
+ }
+
+ public void widgetDisposed(DisposeEvent e) {
+ dispose();
+ }
+
+ /**
+ * Computes the initial check-box settings for my tree according to the current state of the specified
+ * working set configuration.
+ *
+ * @param config
+ * a working set configuration that I am now showing
+ */
+ private void updateCheckState(IWorkingSetConfiguration.ISnapshot config) {
+ for (IWorkingSetProjectConfiguration project : config.getProjectConfigurations()) {
+ IWorkingSetProjectConfigurationController controller = controllerContext
+ .controllerForElement(project);
+
+ if (controller != null) {
+ controller.updateCheckState(controllerContext);
+ }
+ }
+ }
+
+ void update() {
+ if (tree != null) {
+ tree.refresh(true);
+ }
+ }
+
+ /**
+ * Connects me to the controller of the working set configurations pane.
+ *
+ * @param controller
+ * the working-set configs controller
+ */
+ void setWorkingSetConfigurationsController(WorkingSetConfigsController controller) {
+ workingSetController = controller;
+ }
+
+ void dispose() {
+ if (controllerContext != null) {
+ controllerContext.dispose();
+ controllerContext = null;
+ }
+ }
+
+ //
+ // Nested classes
+ //
+
+ private class ControllerContext implements IWorkingSetProjectConfigurationController.IControllerContext {
+
+ private Map