Bug 383348 - Replace actions with invalid menu paths in CDT UI

This change adjusts replaces the following actions (part of action set
org.eclipse.cdt.ui.buildConfigActionSet) with commands and menus:

* org.eclipse.cdt.ui.manageConfigsAction2
* org.eclipse.cdt.ui.buildConfigMenuAction
* org.eclipse.cdt.ui.wsselection

This is done to avoid menu extension errors on perspective
customization, due to problematic code in CustomizePerspectiveDialog. In
particular the customize perspective dialog will populate main menu
submenus only after going over actions; this causes the menu paths of
the actions above to be detected as invalid, despite actually being
valid and functional.

The original action classes are deprecated and marked for removal. The
respective classes are defined in non-internal packages; removal would
be considered API breakage and so must be done in a major version bump.

Change-Id: I31517697689772395b7e1868ef4cab07ad946085
Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
diff --git a/core/org.eclipse.cdt.ui/plugin.properties b/core/org.eclipse.cdt.ui/plugin.properties
index 9aac275..178d926 100644
--- a/core/org.eclipse.cdt.ui/plugin.properties
+++ b/core/org.eclipse.cdt.ui/plugin.properties
@@ -496,6 +496,8 @@
 SearchUnresolvedIncludes.label=Search for Unresolved &Includes
 CreateParserLog.name=Create Parser Log File
 CreateParserLog.label=Create Parser &Log File
+wsselection.command.name=Manage Working Sets
+ManageConfigs.command.name=Manage Build Configurations
 
 indexerPage.name = Indexer Page
 proposalFilter.name = Code Completion Proposal Filter
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index ee0a587..103e3a9 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -1751,6 +1751,47 @@
          </menu>
       </menuContribution>
       <menuContribution
+            locationURI="menu:org.eclipse.cdt.ui.prjmenu?before=manage">
+         <menu
+               id="org.eclipse.cdt.ui.workingSets.changeBuildConfigMenu"
+               label="%BuildConfigMenuAction.label"
+               tooltip="%BuildConfigAction.tooltip">
+            <visibleWhen>
+               <with
+                     variable="activeContexts">
+                  <iterate
+                        ifEmpty="false"
+                        operator="or">
+                     <equals
+                           value="org.eclipse.cdt.ui.buildConfigActionSet">
+                     </equals>
+                  </iterate>
+               </with>
+            </visibleWhen>
+            <dynamic
+                  class="org.eclipse.cdt.internal.ui.workingsets.ChangeBuildConfigContribution"
+                  id="org.eclipse.cdt.ui.changeBuildConfig">
+            </dynamic>
+         </menu>
+         <command
+               commandId="org.eclipse.cdt.ui.menu.manage.configs.command"
+               label="%ManageConfigAction.label"
+               style="push">
+            <visibleWhen>
+               <with
+                     variable="activeContexts">
+                  <iterate
+                        ifEmpty="false"
+                        operator="or">
+                     <equals
+                           value="org.eclipse.cdt.ui.buildConfigActionSet">
+                     </equals>
+                  </iterate>
+               </with>
+            </visibleWhen>
+         </command>
+      </menuContribution>
+      <menuContribution
             locationURI="menu:org.eclipse.cdt.ui.prjmenu?before=wrksets">
          <menu
                id="org.eclipse.cdt.ui.workingSets.buildMenu"
@@ -1792,6 +1833,23 @@
                   id="org.eclipse.cdt.ui.activateWorkingSetConfigs">
             </dynamic>
          </menu>
+         <command
+               commandId="org.eclipse.cdt.ui.menu.wsselection.command"
+               label="%wsselection"
+               style="push">
+            <visibleWhen>
+               <with
+                     variable="activeContexts">
+                  <iterate
+                        ifEmpty="false"
+                        operator="or">
+                     <equals
+                           value="org.eclipse.cdt.ui.buildConfigActionSet">
+                     </equals>
+                  </iterate>
+               </with>
+            </visibleWhen>
+         </command>
       </menuContribution>
    </extension>
    <extension
@@ -2163,28 +2221,6 @@
               style="pulldown"
               toolbarPath="org.eclipse.ui.workbench.file/build.group"
               tooltip="%BuildConfigAction.tooltip2"/>
-        <action
-              class="org.eclipse.cdt.ui.actions.ManageConfigsAction"
-              enablesFor="+"
-              id="org.eclipse.cdt.ui.manageConfigsAction2"
-              label="%ManageConfigAction.label"
-              menubarPath="project/org.eclipse.cdt.ui.prjmenu/manage"
-              />
-        <action
-              class="org.eclipse.cdt.ui.actions.ChangeBuildConfigMenuAction"
-              enablesFor="+"
-              id="org.eclipse.cdt.ui.buildConfigMenuAction"
-              label="%BuildConfigMenuAction.label"
-              menubarPath="project/org.eclipse.cdt.ui.prjmenu/manage"
-              style="pulldown"
-              tooltip="%BuildConfigAction.tooltip"/>
-        <action
-              class="org.eclipse.cdt.ui.actions.WorkingSetConfigAction"
-              id="org.eclipse.cdt.ui.wsselection"
-              label="%wsselection"
-              menubarPath="project/org.eclipse.cdt.ui.prjmenu/wrksets"
-              style="push"
-              />
      </actionSet>
      <actionSet
             label="%CElementCreationActionSet.label"
@@ -4221,6 +4257,18 @@
             namespace="org.eclipse.cdt.ui"
             properties="hasCProjects"
             type="org.eclipse.ui.IWorkingSet"/>
+      <propertyTester
+            class="org.eclipse.cdt.internal.ui.workingsets.NonEmptyWorkingSetPropertyTester"
+            id="org.eclipse.cdt.ui.nonEmptyWorkingSetPropertyTester"
+            namespace="org.eclipse.cdt.ui"
+            properties="hasNonEmptyWorkingSet"
+            type="java.lang.Object"/>
+      <propertyTester
+            class="org.eclipse.cdt.internal.ui.workingsets.HasManagedCdtProjectSelection"
+            id="org.eclipse.cdt.ui.hasManagedCdtProjectSelection"
+            namespace="org.eclipse.cdt.ui"
+            properties="hasManagedCdtProjectSelection"
+            type="java.util.Collection"/>
   </extension>
    
   <extension
@@ -4693,6 +4741,16 @@
 		categoryId="org.eclipse.ui.category.project"
 		id="org.eclipse.cdt.ui.menu.createParserLog">
 	</command>
+    <command
+        name="%wsselection.command.name"
+        categoryId="org.eclipse.ui.category.project"
+        id="org.eclipse.cdt.ui.menu.wsselection.command">
+    </command>
+    <command
+        name="%ManageConfigs.command.name"
+        categoryId="org.eclipse.ui.category.project"
+        id="org.eclipse.cdt.ui.menu.manage.configs.command">
+    </command>
  </extension>
  <extension
        point="org.eclipse.ui.handlers">
@@ -4720,6 +4778,24 @@
 		class="org.eclipse.cdt.internal.ui.actions.CreateParserLogHandler"
 		commandId="org.eclipse.cdt.ui.menu.createParserLog">
     </handler>
+	<handler
+		class="org.eclipse.cdt.internal.ui.actions.WorkingSetConfigHandler"
+		commandId="org.eclipse.cdt.ui.menu.wsselection.command">
+        <enabledWhen>
+            <test
+                 property="org.eclipse.cdt.ui.hasNonEmptyWorkingSet">
+            </test>
+        </enabledWhen>
+    </handler>
+	<handler
+		class="org.eclipse.cdt.internal.ui.actions.ManageConfigsHandler"
+		commandId="org.eclipse.cdt.ui.menu.manage.configs.command">
+        <enabledWhen>
+            <test
+                 property="org.eclipse.cdt.ui.hasManagedCdtProjectSelection">
+            </test>
+        </enabledWhen>
+    </handler>
  </extension>
  <extension
 	point="org.eclipse.ui.menus">
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ManageConfigsHandler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ManageConfigsHandler.java
new file mode 100644
index 0000000..0e6598f
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/ManageConfigsHandler.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.actions;
+
+import org.eclipse.cdt.ui.newui.IConfigManager;
+import org.eclipse.cdt.ui.newui.ManageConfigSelector;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+/**
+ * Handler for command which lets to manage (add/remove etc.) build configurations of the project.
+ */
+public class ManageConfigsHandler extends AbstractHandler {
+
+	public static final String COMMAND_ID = "org.eclipse.cdt.ui.menu.wsselection.command"; //$NON-NLS-1$
+
+	@Override
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		IStructuredSelection selection = HandlerUtil.getCurrentStructuredSelection(event);
+		if (!selection.isEmpty()) {
+			IProject[] obs = ManageConfigSelector.getProjects(selection.toArray());
+			IConfigManager cm = ManageConfigSelector.getManager(obs);
+			if (cm != null && obs != null) {
+				cm.manage(obs, true);
+			}
+		}
+		return null;
+	}
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkingSetConfigHandler.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkingSetConfigHandler.java
new file mode 100644
index 0000000..18ad18a
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/actions/WorkingSetConfigHandler.java
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.actions;
+
+import org.eclipse.cdt.internal.ui.workingsets.WorkingSetConfigurationDialog;
+import org.eclipse.core.commands.AbstractHandler;
+import org.eclipse.core.commands.ExecutionEvent;
+import org.eclipse.core.commands.ExecutionException;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.IWorkingSetManager;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.handlers.HandlerUtil;
+
+public class WorkingSetConfigHandler extends AbstractHandler {
+
+	public static final String COMMAND_ID = "org.eclipse.cdt.ui.menu.manage.configs.command"; //$NON-NLS-1$
+
+	@Override
+	public Object execute(ExecutionEvent event) throws ExecutionException {
+		boolean enabled = hasNonEmptyWorksets();
+		if (enabled) {
+			IWorkbenchWindow window = HandlerUtil.getActiveWorkbenchWindow(event);
+			new WorkingSetConfigurationDialog(window.getShell()).open();
+		}
+		return null;
+	}
+
+	private boolean hasNonEmptyWorksets() {
+		IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+		IWorkingSet[] workingSets = workingSetManager.getWorkingSets();
+		if (workingSets != null) {
+			for (IWorkingSet workingSet : workingSets) {
+				if (!workingSet.isEmpty()) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ChangeBuildConfigContribution.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ChangeBuildConfigContribution.java
new file mode 100644
index 0000000..0f6a572
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/ChangeBuildConfigContribution.java
@@ -0,0 +1,298 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.eclipse.cdt.core.model.CoreModel;
+import org.eclipse.cdt.core.model.ICElement;
+import org.eclipse.cdt.core.model.ICProject;
+import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
+import org.eclipse.cdt.core.settings.model.ICProjectDescription;
+import org.eclipse.cdt.internal.ui.cview.IncludeRefContainer;
+import org.eclipse.cdt.internal.ui.cview.IncludeReferenceProxy;
+import org.eclipse.cdt.ui.CUIPlugin;
+import org.eclipse.cdt.ui.actions.ChangeConfigAction;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.ActionContributionItem;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.action.IContributionItem;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IViewPart;
+import org.eclipse.ui.IViewReference;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.CompoundContributionItem;
+
+/**
+ * A dynamic contribution of items to change the build configuration of selected projects.
+ *
+ */
+public class ChangeBuildConfigContribution extends CompoundContributionItem {
+
+	@Override
+	protected IContributionItem[] getContributionItems() {
+		HashSet<IProject> projects = findProjects();
+
+		SortedSet<String> configNames = new TreeSet<>();
+		String sCurrentConfig = null;
+		boolean bCurrentConfig = true;
+		for (IProject prj : projects) {
+			ICConfigurationDescription[] cfgDescs = getCfgs(prj);
+
+			String sActiveConfig = null;
+			// Store names and detect active configuration
+			for (ICConfigurationDescription cfgDesc : cfgDescs) {
+				String s = cfgDesc.getName();
+				if (!configNames.contains(s))
+					configNames.add(s);
+				if (cfgDesc.isActive())
+					sActiveConfig = s;
+			}
+
+			// Check whether all projects have the same active configuration
+			if (bCurrentConfig) {
+				if (sCurrentConfig == null)
+					sCurrentConfig = sActiveConfig;
+				else {
+					if (!sCurrentConfig.equals(sActiveConfig))
+						bCurrentConfig = false;
+				}
+			}
+		}
+
+		List<ActionContributionItem> actions = new ArrayList<>();
+		int accel = 0;
+		for (String sName : configNames) {
+			String sDesc = null;
+			boolean commonName = true;
+			boolean commonDesc = true;
+			boolean firstProj = true;
+			for (IProject prj : projects) {
+				ICConfigurationDescription[] cfgDescs = getCfgs(prj);
+				int i = 0;
+				for (; i < cfgDescs.length; i++) {
+					if (cfgDescs[i].getName().equals(sName)) {
+						String sNewDesc = cfgDescs[i].getDescription();
+						if (sNewDesc != null && sNewDesc.length() == 0) {
+							sNewDesc = null;
+						}
+						if (commonDesc) {
+							if (firstProj) {
+								sDesc = sNewDesc;
+								firstProj = false;
+							} else if (sNewDesc == null && sDesc != null
+									|| sNewDesc != null && !sNewDesc.equals(sDesc)) {
+								commonDesc = false;
+							}
+						}
+						break;
+					}
+				}
+				if (i == cfgDescs.length) {
+					commonName = false;
+					break;
+				}
+			}
+			if (commonName) {
+				StringBuffer builder = new StringBuffer(sName);
+				if (commonDesc) {
+					if (sDesc != null) {
+						builder.append(" ("); //$NON-NLS-1$
+						builder.append(sDesc);
+						builder.append(")"); //$NON-NLS-1$
+					}
+				} else {
+					builder.append(" (...)"); //$NON-NLS-1$
+				}
+
+				IAction action = new ChangeConfigAction(projects, sName, builder.toString(), accel + 1);
+				if (bCurrentConfig && sCurrentConfig != null && sCurrentConfig.equals(sName)) {
+					action.setChecked(true);
+				}
+				ActionContributionItem item = new ActionContributionItem(action);
+				actions.add(item);
+				accel++;
+			}
+		}
+		return actions.toArray(new IContributionItem[0]);
+	}
+
+	private static HashSet<IProject> findProjects() {
+		HashSet<IProject> fProjects = new LinkedHashSet<>();
+		ISelection selection = CUIPlugin.getActivePage().getSelection();
+		boolean badObject = addProjectsFromSelection(selection, fProjects);
+
+		if (badObject || fProjects.isEmpty()) {
+			// Check for lone CDT project in workspace
+			IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+			if (projects != null && projects.length == 1) {
+				IProject project = projects[0];
+				if (CoreModel.getDefault().isNewStyleProject(project) && (getCfgs(project).length > 0)) {
+					fProjects.add(project);
+				}
+			}
+
+			// Check the three supported views
+			IWorkbenchPage page = CUIPlugin.getActivePage();
+			int viewCount = 0;
+			if (page != null) {
+				IViewReference theViewRef = null;
+				IViewReference viewRef = null;
+
+				theViewRef = page.findViewReference("org.eclipse.cdt.ui.CView"); //$NON-NLS-1$
+				viewCount += (theViewRef != null) ? 1 : 0;
+
+				viewRef = page.findViewReference("org.eclipse.ui.navigator.ProjectExplorer"); //$NON-NLS-1$
+				viewCount += (viewRef != null) ? 1 : 0;
+				theViewRef = (theViewRef == null) ? viewRef : theViewRef;
+
+				viewRef = page.findViewReference("org.eclipse.ui.views.ResourceNavigator"); //$NON-NLS-1$
+				viewCount += (viewRef != null) ? 1 : 0;
+				theViewRef = (theViewRef == null) ? viewRef : theViewRef;
+
+				if (theViewRef != null && viewCount == 1) {
+					IViewPart view = theViewRef.getView(false);
+					if (view != null) {
+						ISelection cdtSelection = view.getSite().getSelectionProvider().getSelection();
+						if (cdtSelection != null) {
+							if (!cdtSelection.isEmpty()) {
+								if (!cdtSelection.equals(selection)) {
+									addProjectsFromSelection(cdtSelection, fProjects);
+								}
+							}
+						}
+					}
+				}
+			}
+		}
+		return fProjects;
+	}
+
+	private static boolean addProjectsFromSelection(ISelection selection, HashSet<IProject> fProjects) {
+		boolean badObject = false;
+		if (selection != null) {
+			if (selection instanceof IStructuredSelection) {
+				if (selection.isEmpty()) {
+					// could be a form editor or something.  try to get the project from the active part
+					IWorkbenchPage page = CUIPlugin.getActivePage();
+					if (page != null) {
+						IWorkbenchPart part = page.getActivePart();
+						if (part != null) {
+							Object o = part.getAdapter(IResource.class);
+							if (o != null && o instanceof IResource) {
+								fProjects.add(((IResource) o).getProject());
+							}
+						}
+					}
+				}
+				Iterator<?> iter = ((IStructuredSelection) selection).iterator();
+				while (iter.hasNext()) {
+					Object selItem = iter.next();
+					IProject project = null;
+					if (selItem instanceof ICElement) {
+						ICProject cproject = ((ICElement) selItem).getCProject();
+						if (cproject != null)
+							project = cproject.getProject();
+					} else if (selItem instanceof IResource) {
+						project = ((IResource) selItem).getProject();
+					} else if (selItem instanceof IncludeRefContainer) {
+						ICProject fCProject = ((IncludeRefContainer) selItem).getCProject();
+						if (fCProject != null)
+							project = fCProject.getProject();
+					} else if (selItem instanceof IncludeReferenceProxy) {
+						IncludeRefContainer irc = ((IncludeReferenceProxy) selItem).getIncludeRefContainer();
+						if (irc != null) {
+							ICProject fCProject = irc.getCProject();
+							if (fCProject != null)
+								project = fCProject.getProject();
+						}
+					} else if (selItem instanceof IAdaptable) {
+						Object adapter = ((IAdaptable) selItem).getAdapter(IProject.class);
+						if (adapter != null && adapter instanceof IProject) {
+							project = (IProject) adapter;
+						}
+					}
+					// Check whether the project is CDT project
+					if (project != null) {
+						if (!CoreModel.getDefault().isNewStyleProject(project))
+							project = null;
+						else {
+							ICConfigurationDescription[] tmp = getCfgs(project);
+							if (tmp.length == 0)
+								project = null;
+						}
+					}
+					if (project != null) {
+						fProjects.add(project);
+					} else {
+						badObject = true;
+						break;
+					}
+				}
+			} else if (selection instanceof ITextSelection) {
+				// If a text selection check the selected part to see if we can find
+				// an editor part that we can adapt to a resource and then
+				// back to a project.
+				IWorkbenchWindow window = CUIPlugin.getActiveWorkbenchWindow();
+				if (window != null) {
+					IWorkbenchPage page = window.getActivePage();
+					if (page != null) {
+						IWorkbenchPart part = page.getActivePart();
+						if (part instanceof IEditorPart) {
+							IEditorPart epart = (IEditorPart) part;
+							IResource resource = epart.getEditorInput().getAdapter(IResource.class);
+							if (resource != null) {
+								IProject project = resource.getProject();
+								badObject = !(project != null && CoreModel.getDefault().isNewStyleProject(project));
+
+								if (!badObject) {
+									fProjects.add(project);
+								}
+							}
+						}
+					}
+				}
+
+			}
+		}
+		return badObject;
+	}
+
+	private static ICConfigurationDescription[] getCfgs(IProject prj) {
+		ICProjectDescription prjd = CoreModel.getDefault().getProjectDescription(prj, false);
+		if (prjd != null) {
+			ICConfigurationDescription[] cfgs = prjd.getConfigurations();
+			if (cfgs != null) {
+				return cfgs;
+			}
+		}
+
+		return new ICConfigurationDescription[0];
+	}
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/HasManagedCdtProjectSelection.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/HasManagedCdtProjectSelection.java
new file mode 100644
index 0000000..cc1f480
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/HasManagedCdtProjectSelection.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import java.util.Collection;
+
+import org.eclipse.cdt.ui.newui.ManageConfigSelector;
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Property tester for the enablement of the command handled by {@link org.eclipse.cdt.internal.ui.actions.ManageConfigsHandler}.
+ * Will evaluate {@code true} if the current selection is a managed CDT project, contains a managed CDT project, or belongs to a managed CDT project.
+ */
+public class HasManagedCdtProjectSelection extends PropertyTester {
+
+	private static final String PROPERTY_HAS_MANAGED_CDT_PROJECT_SELECTION = "hasManagedCdtProjectSelection"; //$NON-NLS-1$
+
+	@Override
+	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+		if (PROPERTY_HAS_MANAGED_CDT_PROJECT_SELECTION.equals(property)) {
+			boolean hasNonEmptyWorksets = hasManagedCdtProjectSelection(receiver);
+			return hasNonEmptyWorksets;
+		}
+		return false;
+	}
+
+	private static boolean hasManagedCdtProjectSelection(Object receiver) {
+		if (receiver instanceof Collection) {
+			Collection<?> selection = (Collection<?>) receiver;
+			if (!selection.isEmpty()) {
+				IProject[] obs = ManageConfigSelector.getProjects(selection.toArray());
+				return ManageConfigSelector.getManager(obs) != null;
+			}
+		}
+		return false;
+	}
+
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/NonEmptyWorkingSetPropertyTester.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/NonEmptyWorkingSetPropertyTester.java
new file mode 100644
index 0000000..2944480
--- /dev/null
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/workingsets/NonEmptyWorkingSetPropertyTester.java
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Simeon Andreev and others.
+ *
+ * This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ *     Simeon Andreev - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.internal.ui.workingsets;
+
+import org.eclipse.core.expressions.PropertyTester;
+import org.eclipse.ui.IWorkingSet;
+import org.eclipse.ui.IWorkingSetManager;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Property tester for the enablement of the command handled by {@link org.eclipse.cdt.internal.ui.actions.WorkingSetConfigHandler}.
+ * Will evaluate {@code true} if there is a non-empty working set in the workspace.
+ */
+public class NonEmptyWorkingSetPropertyTester extends PropertyTester {
+
+	private static final String PROPERTY_HAS_NON_EMPTY_WORKING_SET = "hasNonEmptyWorkingSet"; //$NON-NLS-1$
+
+	@Override
+	public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
+		if (PROPERTY_HAS_NON_EMPTY_WORKING_SET.equals(property)) {
+			boolean hasNonEmptyWorksets = hasNonEmptyWorksets();
+			return hasNonEmptyWorksets;
+		}
+		return false;
+	}
+
+	private static boolean hasNonEmptyWorksets() {
+		IWorkingSetManager workingSetManager = PlatformUI.getWorkbench().getWorkingSetManager();
+		IWorkingSet[] workingSets = workingSetManager.getWorkingSets();
+		if (workingSets != null) {
+			for (IWorkingSet workingSet : workingSets) {
+				if (!workingSet.isEmpty()) {
+					return true;
+				}
+			}
+		}
+		return false;
+	}
+}
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ChangeBuildConfigMenuAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ChangeBuildConfigMenuAction.java
index 06b6fea..aae3610 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ChangeBuildConfigMenuAction.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ChangeBuildConfigMenuAction.java
@@ -30,7 +30,10 @@
 
 /**
  * Action which changes active build configuration of the current project
+ *
+ * @deprecated Replaced with menu contribution {@link org.eclipse.cdt.internal.ui.workingsets.ChangeBuildConfigContribution}.
  */
+@Deprecated(forRemoval = true)
 public class ChangeBuildConfigMenuAction extends ChangeBuildConfigActionBase
 		implements IWorkbenchWindowPulldownDelegate2 {
 
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ManageConfigsAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ManageConfigsAction.java
index 2027fd3..0a09b29 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ManageConfigsAction.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/ManageConfigsAction.java
@@ -28,7 +28,10 @@
 
 /**
  * Action which lets to manage (add/remove etc.) build configurations of the project.
+ *
+ * @deprecated Replaced with a command and handler {@link org.eclipse.cdt.internal.ui.actions.ManageConfigsHandler}.
  */
+@Deprecated(forRemoval = true)
 public class ManageConfigsAction implements IWorkbenchWindowPulldownDelegate2, IObjectActionDelegate {
 	IProject[] obs = null;
 
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/WorkingSetConfigAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/WorkingSetConfigAction.java
index d238c84..df54907 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/WorkingSetConfigAction.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/actions/WorkingSetConfigAction.java
@@ -27,7 +27,9 @@
 import org.eclipse.ui.PlatformUI;
 
 /**
+ * @deprecated Replaced with a command and handler {@link org.eclipse.cdt.internal.ui.actions.WorkingSetConfigHandler}.
  */
+@Deprecated(forRemoval = true)
 public class WorkingSetConfigAction implements IWorkbenchWindowActionDelegate, IPropertyChangeListener {
 
 	private static final IWorkingSetManager wsm = PlatformUI.getWorkbench().getWorkingSetManager();