Provide more helpful item providers for key binding tasks
diff --git a/features/org.eclipse.oomph.setup.workbench-feature/feature.xml b/features/org.eclipse.oomph.setup.workbench-feature/feature.xml
index 9a2e6cd..99af98f 100644
--- a/features/org.eclipse.oomph.setup.workbench-feature/feature.xml
+++ b/features/org.eclipse.oomph.setup.workbench-feature/feature.xml
@@ -12,7 +12,7 @@
 <feature
       id="org.eclipse.oomph.setup.workbench"
       label="%featureName"
-      version="1.16.0.qualifier"
+      version="1.17.0.qualifier"
       provider-name="%providerName"
       license-feature="org.eclipse.oomph.license"
       license-feature-version="0.0.0">
diff --git a/features/org.eclipse.oomph.setup.workbench-feature/pom.xml b/features/org.eclipse.oomph.setup.workbench-feature/pom.xml
index 4098fc3..2c0bfda 100644
--- a/features/org.eclipse.oomph.setup.workbench-feature/pom.xml
+++ b/features/org.eclipse.oomph.setup.workbench-feature/pom.xml
@@ -20,6 +20,6 @@
   </parent>
   <groupId>org.eclipse.oomph.features</groupId>
   <artifactId>org.eclipse.oomph.setup.workbench</artifactId>
-  <version>1.16.0-SNAPSHOT</version>
+  <version>1.17.0-SNAPSHOT</version>
   <packaging>eclipse-feature</packaging>
 </project>
diff --git a/plugins/org.eclipse.oomph.setup.workbench.edit/META-INF/MANIFEST.MF b/plugins/org.eclipse.oomph.setup.workbench.edit/META-INF/MANIFEST.MF
index cd6b867..ca7b7f5 100644
--- a/plugins/org.eclipse.oomph.setup.workbench.edit/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.oomph.setup.workbench.edit/META-INF/MANIFEST.MF
@@ -2,17 +2,20 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.oomph.setup.workbench.edit;singleton:=true
-Bundle-Version: 1.13.0.qualifier
+Bundle-Version: 1.14.0.qualifier
 Bundle-ClassPath: .
 Bundle-Activator: org.eclipse.oomph.setup.workbench.provider.WorkbenchEditPlugin$Implementation
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-11
-Export-Package: org.eclipse.oomph.setup.workbench.provider;version="1.13.0";x-internal:=true
+Export-Package: org.eclipse.oomph.setup.workbench.provider;version="1.14.0";x-internal:=true
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.24.0,4.0.0)",
- org.eclipse.oomph.setup.workbench;bundle-version="[1.13.0,2.0.0)";visibility:=reexport,
+ org.eclipse.core.commands;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.oomph.setup.workbench;bundle-version="[1.14.0,2.0.0)";visibility:=reexport,
  org.eclipse.emf.edit;bundle-version="[2.10.0,3.0.0)";visibility:=reexport,
  org.eclipse.oomph.base.edit;bundle-version="[1.16.0,2.0.0)";visibility:=reexport,
- org.eclipse.oomph.setup.edit;bundle-version="[1.16.0,2.0.0)";visibility:=reexport
+ org.eclipse.oomph.setup.edit;bundle-version="[1.16.0,2.0.0)";visibility:=reexport,
+ org.eclipse.ui.workbench;bundle-version="[3.0.0,4.0.0)",
+ org.eclipse.jface;bundle-version="[3.0.0,4.0.0)"
 Bundle-ActivationPolicy: lazy
 Automatic-Module-Name: org.eclipse.oomph.setup.workbench.edit
diff --git a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/FileAssociationsTaskItemProvider.java b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/FileAssociationsTaskItemProvider.java
index 1ea5ca0..76ae9a5 100644
--- a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/FileAssociationsTaskItemProvider.java
+++ b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/FileAssociationsTaskItemProvider.java
@@ -10,8 +10,6 @@
  */
 package org.eclipse.oomph.setup.workbench.provider;
 
-import org.eclipse.oomph.base.BaseFactory;
-import org.eclipse.oomph.base.BasePackage;
 import org.eclipse.oomph.setup.provider.SetupTaskItemProvider;
 import org.eclipse.oomph.setup.workbench.FileAssociationsTask;
 import org.eclipse.oomph.setup.workbench.WorkbenchFactory;
@@ -164,8 +162,6 @@
   {
     super.collectNewChildDescriptors(newChildDescriptors, object);
 
-    newChildDescriptors.add(createChildParameter(BasePackage.Literals.MODEL_ELEMENT__ANNOTATIONS, BaseFactory.eINSTANCE.createAnnotation()));
-
     newChildDescriptors.add(createChildParameter(WorkbenchPackage.Literals.FILE_ASSOCIATIONS_TASK__MAPPINGS, WorkbenchFactory.eINSTANCE.createFileMapping()));
   }
 
diff --git a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingContextItemProvider.java b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingContextItemProvider.java
index 3f24207..5f1e341 100644
--- a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingContextItemProvider.java
+++ b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingContextItemProvider.java
@@ -17,6 +17,7 @@
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.util.ResourceLocator;
+import org.eclipse.emf.ecore.EStructuralFeature;
 import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
 import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
 import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
@@ -24,6 +25,7 @@
 
 import java.util.Collection;
 import java.util.List;
+import java.util.Map;
 
 /**
  * This is the item provider adapter for a {@link org.eclipse.oomph.setup.workbench.KeyBindingContext} object.
@@ -33,6 +35,8 @@
  */
 public class KeyBindingContextItemProvider extends ModelElementItemProvider
 {
+  private Map<String, String> contexts;
+
   /**
    * This constructs an instance from a factory and a notifier.
    * <!-- begin-user-doc -->
@@ -44,6 +48,15 @@
     super(adapterFactory);
   }
 
+  public Map<String, String> getContexts()
+  {
+    if (contexts == null)
+    {
+      contexts = WorkbenchEditPlugin.getContexts();
+    }
+    return contexts;
+  }
+
   /**
    * This returns the property descriptors for the adapted class.
    * <!-- begin-user-doc -->
@@ -76,6 +89,23 @@
         WorkbenchPackage.Literals.KEY_BINDING_CONTEXT__ID, true, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
   }
 
+  @Override
+  protected Collection<?> filterChoices(Collection<?> choices, EStructuralFeature feature, Object object)
+  {
+    if (feature == WorkbenchPackage.Literals.KEY_BINDING_CONTEXT__ID)
+    {
+      return getContexts().keySet();
+    }
+
+    return super.filterChoices(choices, feature, object);
+  }
+
+  @Override
+  protected boolean isChoiceArbitrary(EStructuralFeature feature, Object object)
+  {
+    return feature == WorkbenchPackage.Literals.KEY_BINDING_CONTEXT__ID || super.isChoiceArbitrary(feature, object);
+  }
+
   /**
    * This returns KeyBindingContext.gif.
    * <!-- begin-user-doc -->
@@ -108,8 +138,14 @@
   @Override
   public String getText(Object object)
   {
-    String label = ((KeyBindingContext)object).getID();
-    return label == null || label.length() == 0 ? getString("_UI_KeyBindingContext_type") : label; //$NON-NLS-1$
+    String id = ((KeyBindingContext)object).getID();
+    String name = id == null ? null : getContexts().get(id);
+    if (name != null)
+    {
+      id += " \u279d " + name; //$NON-NLS-1$
+    }
+
+    return id == null || id.length() == 0 ? getString("_UI_KeyBindingContext_type") : id; //$NON-NLS-1$
   }
 
   /**
diff --git a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingTaskItemProvider.java b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingTaskItemProvider.java
index f7e2518..2cc6b58 100644
--- a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingTaskItemProvider.java
+++ b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/KeyBindingTaskItemProvider.java
@@ -10,24 +10,31 @@
  */
 package org.eclipse.oomph.setup.workbench.provider;
 
-import org.eclipse.oomph.base.BaseFactory;
-import org.eclipse.oomph.base.BasePackage;
 import org.eclipse.oomph.setup.provider.SetupTaskItemProvider;
+import org.eclipse.oomph.setup.workbench.CommandParameter;
 import org.eclipse.oomph.setup.workbench.KeyBindingTask;
 import org.eclipse.oomph.setup.workbench.WorkbenchFactory;
 import org.eclipse.oomph.setup.workbench.WorkbenchPackage;
 
+import org.eclipse.emf.common.command.Command;
+import org.eclipse.emf.common.command.CompoundCommand;
 import org.eclipse.emf.common.notify.AdapterFactory;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.util.ResourceLocator;
+import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.edit.command.SetCommand;
+import org.eclipse.emf.edit.domain.EditingDomain;
 import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
 import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
 import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
 import org.eclipse.emf.edit.provider.ViewerNotification;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Set;
 
 /**
  * This is the item provider adapter for a {@link org.eclipse.oomph.setup.workbench.KeyBindingTask} object.
@@ -140,6 +147,84 @@
         WorkbenchPackage.Literals.KEY_BINDING_TASK__COMMAND, true, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
   }
 
+  @Override
+  protected Collection<?> filterChoices(Collection<?> choices, EStructuralFeature feature, Object object)
+  {
+    if (feature == WorkbenchPackage.Literals.KEY_BINDING_TASK__COMMAND)
+    {
+      Set<String> result = new LinkedHashSet<>();
+      KeyBindingTask keyBindingTask = (KeyBindingTask)object;
+      String command = keyBindingTask.getCommand();
+      if (command != null)
+      {
+        result.add(command);
+      }
+
+      result.addAll(WorkbenchEditPlugin.getCommands().keySet());
+      return result;
+    }
+    else if (feature == WorkbenchPackage.Literals.KEY_BINDING_TASK__SCHEME)
+    {
+      Set<String> result = new LinkedHashSet<>();
+      KeyBindingTask keyBindingTask = (KeyBindingTask)object;
+      String scheme = keyBindingTask.getScheme();
+      if (scheme != null)
+      {
+        result.add(scheme);
+      }
+
+      result.addAll(WorkbenchEditPlugin.getSchemes());
+      return result;
+    }
+
+    return super.filterChoices(choices, feature, object);
+  }
+
+  @Override
+  protected boolean isChoiceArbitrary(EStructuralFeature feature, Object object)
+  {
+    if (feature == WorkbenchPackage.Literals.KEY_BINDING_TASK__COMMAND || feature == WorkbenchPackage.Literals.KEY_BINDING_TASK__SCHEME)
+    {
+      return true;
+    }
+
+    return super.isChoiceArbitrary(feature, object);
+  }
+
+  @Override
+  protected Command createSetCommand(EditingDomain domain, EObject owner, EStructuralFeature feature, Object value)
+  {
+    if (feature == WorkbenchPackage.Literals.KEY_BINDING_TASK__COMMAND)
+    {
+      Command command = super.createSetCommand(domain, owner, feature, value);
+
+      Set<String> availableCommandParameters = WorkbenchEditPlugin.getCommandParameters((String)value).keySet();
+      List<CommandParameter> commandParameters = new ArrayList<>();
+      KeyBindingTask keyBindingTask = (KeyBindingTask)owner;
+      LOOP: for (String id : availableCommandParameters)
+      {
+        for (CommandParameter commandParameter : keyBindingTask.getCommandParameters())
+        {
+          if (id.equals(commandParameter.getID()))
+          {
+            commandParameters.add(commandParameter);
+            continue LOOP;
+          }
+        }
+        CommandParameter commandParameter = WorkbenchFactory.eINSTANCE.createCommandParameter();
+        commandParameter.setID(id);
+        commandParameters.add(commandParameter);
+      }
+
+      CompoundCommand result = new CompoundCommand();
+      result.append(command);
+      result.append(SetCommand.create(domain, owner, WorkbenchPackage.Literals.KEY_BINDING_TASK__COMMAND_PARAMETERS, commandParameters));
+      return result.unwrap();
+    }
+
+    return super.createSetCommand(domain, owner, feature, value);
+  }
+
   /**
    * This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
    * {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
@@ -207,7 +292,9 @@
   public String getText(Object object)
   {
     KeyBindingTask keyBindingTask = (KeyBindingTask)object;
-    return "" + keyBindingTask.getKeys() + " = " + keyBindingTask.getCommand(); //$NON-NLS-1$ //$NON-NLS-2$
+    String command = keyBindingTask.getCommand();
+    String name = command == null ? null : WorkbenchEditPlugin.getCommands().get(command);
+    return "" + keyBindingTask.getKeys() + " = " + command + (name == null ? "" : " \u279d " + name); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
   }
 
   /**
@@ -251,8 +338,6 @@
   {
     super.collectNewChildDescriptors(newChildDescriptors, object);
 
-    newChildDescriptors.add(createChildParameter(BasePackage.Literals.MODEL_ELEMENT__ANNOTATIONS, BaseFactory.eINSTANCE.createAnnotation()));
-
     newChildDescriptors.add(createChildParameter(WorkbenchPackage.Literals.KEY_BINDING_TASK__CONTEXTS, WorkbenchFactory.eINSTANCE.createKeyBindingContext()));
 
     newChildDescriptors
diff --git a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/WorkbenchEditPlugin.java b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/WorkbenchEditPlugin.java
index 5ab98a9..b4a9faa 100644
--- a/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/WorkbenchEditPlugin.java
+++ b/plugins/org.eclipse.oomph.setup.workbench.edit/src/org/eclipse/oomph/setup/workbench/provider/WorkbenchEditPlugin.java
@@ -12,10 +12,27 @@
 
 import org.eclipse.oomph.base.provider.BaseEditPlugin;
 import org.eclipse.oomph.setup.provider.SetupEditPlugin;
+import org.eclipse.oomph.util.StringUtil;
 
 import org.eclipse.emf.common.EMFPlugin;
 import org.eclipse.emf.common.util.ResourceLocator;
 
+import org.eclipse.core.commands.Command;
+import org.eclipse.core.commands.IParameter;
+import org.eclipse.core.commands.common.NotDefinedException;
+import org.eclipse.core.commands.contexts.Context;
+import org.eclipse.jface.bindings.Scheme;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.commands.ICommandService;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.keys.IBindingService;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
 /**
  * This is the central singleton for the Workbench edit plugin.
  * <!-- begin-user-doc -->
@@ -100,4 +117,87 @@
     }
   }
 
+  public static Set<String> getSchemes()
+  {
+    Set<String> result = new TreeSet<>();
+    IBindingService service = PlatformUI.getWorkbench().getService(IBindingService.class);
+    for (Scheme schemeId : service.getDefinedSchemes())
+    {
+      result.add(schemeId.getId());
+    }
+
+    return result;
+  }
+
+  public static Map<String, String> getContexts()
+  {
+    Map<String, String> result = new TreeMap<>();
+    for (Context context : PlatformUI.getWorkbench().getService(IContextService.class).getDefinedContexts())
+    {
+      String id = context.getId();
+      try
+      {
+        String name = context.getName();
+        result.put(id, name);
+      }
+      catch (NotDefinedException ex)
+      {
+        result.put(id, null);
+      }
+    }
+
+    return result;
+  }
+
+  public static Map<String, String> getCommands()
+  {
+    Map<String, String> result = new TreeMap<>();
+    ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
+    for (Command command : commandService.getDefinedCommands())
+    {
+      try
+      {
+        result.put(command.getId(), command.getName());
+      }
+      catch (NotDefinedException ex)
+      {
+        result.put(command.getId(), command.getId());
+      }
+    }
+
+    return result;
+  }
+
+  public static Map<String, String> getCommandParameters(String commandId)
+  {
+    Map<String, String> result = new LinkedHashMap<>();
+    if (!StringUtil.isEmpty(commandId))
+    {
+      ICommandService commandService = PlatformUI.getWorkbench().getService(ICommandService.class);
+      Command command = commandService.getCommand(commandId);
+      if (command != null)
+      {
+        try
+        {
+          IParameter[] parameters = command.getParameters();
+          if (parameters != null)
+          {
+            for (IParameter parameter : parameters)
+            {
+              String id = parameter.getId();
+              String name = parameter.getName();
+              result.put(id, name);
+            }
+          }
+        }
+        catch (NotDefinedException ex)
+        {
+          //$FALL-THROUGH$
+        }
+      }
+    }
+
+    return result;
+  }
+
 }
diff --git a/plugins/org.eclipse.oomph.setup.workbench/META-INF/MANIFEST.MF b/plugins/org.eclipse.oomph.setup.workbench/META-INF/MANIFEST.MF
index f6b97d4..410a8fd 100644
--- a/plugins/org.eclipse.oomph.setup.workbench/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.oomph.setup.workbench/META-INF/MANIFEST.MF
@@ -2,20 +2,20 @@
 Bundle-ManifestVersion: 2
 Bundle-Name: %pluginName
 Bundle-SymbolicName: org.eclipse.oomph.setup.workbench;singleton:=true
-Bundle-Version: 1.13.0.qualifier
+Bundle-Version: 1.14.0.qualifier
 Bundle-ClassPath: .
 Bundle-Vendor: %providerName
 Bundle-Localization: plugin
 Bundle-RequiredExecutionEnvironment: JavaSE-11
-Export-Package: org.eclipse.oomph.setup.workbench;version="1.13.0";x-internal:=true,
- org.eclipse.oomph.setup.workbench.impl;version="1.13.0";x-internal:=true,
- org.eclipse.oomph.setup.workbench.util;version="1.13.0";x-internal:=true
+Export-Package: org.eclipse.oomph.setup.workbench;version="1.14.0";x-internal:=true,
+ org.eclipse.oomph.setup.workbench.impl;version="1.14.0";x-internal:=true,
+ org.eclipse.oomph.setup.workbench.util;version="1.14.0";x-internal:=true
 Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.24.0,4.0.0)",
  org.eclipse.emf.ecore;bundle-version="[2.10.0,3.0.0)";visibility:=reexport,
- org.eclipse.oomph.setup;bundle-version="[1.23.0,2.0.0)";visibility:=reexport,
+ org.eclipse.oomph.setup;bundle-version="[1.26.0,2.0.0)";visibility:=reexport,
  org.eclipse.ui.workbench;bundle-version="[3.0.0,4.0.0)",
  org.eclipse.core.commands;bundle-version="[3.0.0,4.0.0)",
  org.eclipse.jface;bundle-version="[3.0.0,4.0.0)",
- org.eclipse.oomph.ui;bundle-version="[1.16.0,2.0.0)"
+ org.eclipse.oomph.ui;bundle-version="[1.19.0,2.0.0)"
 Bundle-ActivationPolicy: lazy
 Automatic-Module-Name: org.eclipse.oomph.setup.workbench
diff --git a/plugins/org.eclipse.oomph.setup.workbench/pom.xml b/plugins/org.eclipse.oomph.setup.workbench/pom.xml
index 0e48017..97f1068 100644
--- a/plugins/org.eclipse.oomph.setup.workbench/pom.xml
+++ b/plugins/org.eclipse.oomph.setup.workbench/pom.xml
@@ -20,7 +20,7 @@
   </parent>
   <groupId>org.eclipse.oomph</groupId>
   <artifactId>org.eclipse.oomph.setup.workbench</artifactId>
-  <version>1.13.0-SNAPSHOT</version>
+  <version>1.14.0-SNAPSHOT</version>
   <packaging>eclipse-plugin</packaging>
 
   <build>