Bug 508787 - Various UI improvements

 * Added Mnemonics
 * Buttons use default minimum size
 * Added image to Launches tab
 * "Launch mode" label fixed
 * Launch mode entries are capitalized
 * Launch mode entries are sorted
 * Launch modes without available history are filtered

Change-Id: I6f02fac9d9169e125ea923d57d6f57f4ec5dc751
Signed-off-by: Markus Duft <markus.duft@ssi-schaefer.com>
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
index 5c3b700..4e1528f 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugPluginImages.java
@@ -205,6 +205,7 @@
 		declareRegistryImage(IInternalDebugUIConstants.IMG_OBJECT_MEMORY_CHANGED, OBJECT + "memorychanged_obj.png");  //$NON-NLS-1$
 		declareRegistryImage(IInternalDebugUIConstants.IMG_OBJECT_MEMORY, OBJECT + "memory_obj.png");  //$NON-NLS-1$
 		declareRegistryImage(IInternalDebugUIConstants.IMG_OBJS_BREAKPOINT_TYPE, OBJECT + "brkp_type.png");  //$NON-NLS-1$
+		declareRegistryImage(IInternalDebugUIConstants.IMG_OBJS_LAUNCH_GROUP, OBJECT + "lgroup_obj.png"); //$NON-NLS-1$
 		
 		// tabs
 		declareRegistryImage(IInternalDebugUIConstants.IMG_OBJS_COMMON_TAB, OBJECT + "common_tab.png"); //$NON-NLS-1$
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
index b8fe2e5..9dd3c85 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/DebugUIMessages.properties
@@ -117,7 +117,7 @@
 GroupLaunch_Cycle=Infinite loop detected for ''{0}'' group
 GroupLaunch_Error=Error
 GroupLaunchConfigurationSelectionDialog_0=The selected launch contains a direct or indirect reference to this group
-GroupLaunchConfigurationSelectionDialog_4=Launch Mode:
+GroupLaunchConfigurationSelectionDialog_4=Launch mode:
 GroupLaunchConfigurationSelectionDialog_5=Use default mode when launching
 GroupLaunchConfigurationSelectionDialog_7=Select a launch configuration
 GroupLaunchConfigurationSelectionDialog_8=Post launch action:
@@ -128,14 +128,14 @@
 GroupLaunchConfigurationSelectionDialog_13=Edit Launch Configuration
 GroupLaunchConfigurationSelectionDialog_14=Add one or more launch configurations to the launch group
 GroupLaunchConfigurationSelectionDialog_15=Edit an existing entry in the launch group
-GroupLaunchConfigurationTabGroup_1=Up
-GroupLaunchConfigurationTabGroup_2=Down
-GroupLaunchConfigurationTabGroup_3=Edit...
-GroupLaunchConfigurationTabGroup_4=Add...
-GroupLaunchConfigurationTabGroup_5=Remove
+GroupLaunchConfigurationTabGroup_1=&Up
+GroupLaunchConfigurationTabGroup_2=&Down
+GroupLaunchConfigurationTabGroup_3=&Edit...
+GroupLaunchConfigurationTabGroup_4=&Add...
+GroupLaunchConfigurationTabGroup_5=&Remove
 GroupLaunchConfigurationTabGroup_6=Name
 GroupLaunchConfigurationTabGroup_7=Mode
-GroupLaunchConfigurationTabGroup_10=Launches
+GroupLaunchConfigurationTabGroup_10=&Launches
 GroupLaunchConfigurationTabGroup_12=Action
 GroupLaunchConfigurationTabGroup_13=Delay {0} seconds
 GroupLaunchConfigurationTabGroup_14=Launch {0} does not exist.
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
index 9ae1f2a..2a7dcc5 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/IInternalDebugUIConstants.java
@@ -137,6 +137,7 @@
     public static final String IMG_OBJECT_MEMORY_CHANGED="IMG_OBJECT_MEMORY_CHANGED";  //$NON-NLS-1$
     public static final String IMG_OBJECT_MEMORY="IMG_OBJECT_MEMORY";  //$NON-NLS-1$
     public static final String IMG_OBJS_BREAKPOINT_TYPE="IMG_OBJ_BREAKPOINT_TYPE"; //$NON-NLS-1$
+	public static final String IMG_OBJS_LAUNCH_GROUP = "IMG_OBJ_LAUNCH_GROUP"; //$NON-NLS-1$
     
     // wizard images
     public static final String IMG_WIZBAN_IMPORT_BREAKPOINTS = "IMG_WIZBAN_IMPORT_BREAKPOINTS"; //$NON-NLS-1$
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java
index fed29d2..4187db0 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/ComboControlledStackComposite.java
@@ -13,6 +13,7 @@
 
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.TreeMap;
 
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.custom.StackLayout;
@@ -33,7 +34,8 @@
 class ComboControlledStackComposite extends Composite {
 	private Composite fArea;
 	private Combo fCombo;
-	private Map<String, Composite> tabMap; // label ==> tab 
+	private Map<String, Composite> tabMap; // label ==> tab
+	private Map<String, String> capMap = new TreeMap<>();
 	private StackLayout layout;
 	private Label fLabel;
 
@@ -47,28 +49,36 @@
 	public void setLabelText(String label) {
 		fLabel.setText(label);
 	}
+
+	private static String capitalize(String l) {
+		return l.substring(0, 1).toUpperCase() + l.substring(1);
+	}
+
 	public void addItem(String label, Composite tab) {
 		tabMap.put(label, tab);
-		fCombo.add(label);
+		String cap = capitalize(label);
+		fCombo.add(cap);
+		capMap.put(cap, label);
 		if (layout.topControl==null) {
 			layout.topControl = tab;
-			fCombo.setText(label);
+			fCombo.setText(cap);
 		}
 	}
 
 	public void deleteItem(String label) {
-		if (fCombo.getText().equals(label)) {
+		if (capMap.get(fCombo.getText()).equals(label)) {
 			setSelection(fCombo.getItem(0));
 		}
 		Composite tab = tabMap.get(label);
 		if (tab != null) {
 			tab.dispose();
 			tabMap.remove(label);
+			capMap.remove(capitalize(label));
 		}
 	}
 
 	public void setSelection(String label) {
-		fCombo.setText(label);
+		fCombo.setText(capitalize(label));
 		setPage(label);
 	}
 
@@ -93,10 +103,18 @@
 		return fLabel;
 	}
 
+	/**
+	 * @return the underlying combo, should NOT be used to get the actual text,
+	 *         use {@link #getSelection()} instead.
+	 */
 	public Combo getCombo() {
 		return fCombo;
 	}
 
+	public String getSelection() {
+		return capMap.get(fCombo.getText());
+	}
+
 	protected Composite createTabArea(Composite parent) {
 		Composite comp = new Composite(parent, SWT.NONE);
 		layout = new StackLayout();
@@ -124,7 +142,7 @@
 	}
 
 	protected void comboSelected(String label) {
-		setPage(label);
+		setPage(capMap.get(label));
 	}
 
 	protected void setPage(String label) {
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java
index c6f4c58..6db551d 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationSelectionDialog.java
@@ -13,10 +13,13 @@
 package org.eclipse.debug.internal.ui.groups;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
+import java.util.Set;
+import java.util.TreeSet;
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.debug.core.DebugPlugin;
@@ -31,6 +34,7 @@
 import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationFilteredTree;
 import org.eclipse.debug.internal.ui.launchConfigurations.LaunchConfigurationManager;
 import org.eclipse.debug.internal.ui.launchConfigurations.LaunchGroupFilter;
+import org.eclipse.debug.internal.ui.launchConfigurations.LaunchHistory;
 import org.eclipse.debug.ui.IDebugUIConstants;
 import org.eclipse.debug.ui.ILaunchGroup;
 import org.eclipse.jface.dialogs.IDialogConstants;
@@ -70,7 +74,6 @@
 	private static final String GROUP_TYPE_ID = "org.eclipse.debug.core.groups.GroupLaunchConfigurationType"; //$NON-NLS-1$
 	
 	private ISelection fSelection;
-	private ILaunchGroup[] launchGroups;
 	private String mode;
 	private GroupElementPostLaunchAction action = GroupElementPostLaunchAction.NONE;
 	private Object actionParam;
@@ -86,8 +89,6 @@
 
 	public GroupLaunchConfigurationSelectionDialog(Shell shell, String initMode, boolean forEditing, ILaunchConfiguration self) {
 		super(shell);
-		LaunchConfigurationManager manager = DebugUIPlugin.getDefault().getLaunchConfigurationManager();
-		launchGroups = manager.getLaunchGroups();
 		mode = initMode;
 		fForEditing = forEditing;
 		selfRef = self;
@@ -151,13 +152,24 @@
 
 		fStackComposite = new ComboControlledStackComposite(comp, SWT.NONE);
 
-		Map<String, ILaunchGroup> modes = new TreeMap<>();
-		for (ILaunchGroup launchGroup : launchGroups) {
+		Map<String, ILaunchGroup> modes = new LinkedHashMap<>();
+		modes.put(GroupLaunchElement.MODE_INHERIT, new InheritModeGroup());
+		Set<ILaunchGroup> sortedGroups = new TreeSet<>((a, b) -> {
+			return a.getLabel().compareTo(b.getLabel());
+		});
+		LaunchConfigurationManager mgr = DebugUIPlugin.getDefault().getLaunchConfigurationManager();
+		sortedGroups.addAll(Arrays.asList(mgr.getLaunchGroups()));
+		for (ILaunchGroup launchGroup : sortedGroups) {
+			LaunchHistory history = mgr.getLaunchHistory(launchGroup.getIdentifier());
+			if (history == null) {
+				// mode currently not supported.
+				continue;
+			}
+
 			if (!modes.containsKey(launchGroup.getMode())) {
 				modes.put(launchGroup.getMode(), launchGroup);
 			}
 		}
-		modes.put(GroupLaunchElement.MODE_INHERIT, new InheritModeGroup());
 
 		for (Map.Entry<String, ILaunchGroup> entry : modes.entrySet()) {
 			ILaunchGroup launchGroup = entry.getValue();
@@ -194,7 +206,7 @@
 		fStackComposite.getCombo().addSelectionListener(new SelectionAdapter() {
 			@Override
 			public void widgetSelected(SelectionEvent e) {
-				mode = ((Combo) e.widget).getText();
+				mode = fStackComposite.getSelection();
 			}
 		});
 
diff --git a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java
index 86e2395..183ce1e 100644
--- a/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java
+++ b/org.eclipse.debug.ui/ui/org/eclipse/debug/internal/ui/groups/GroupLaunchConfigurationTabGroup.java
@@ -27,8 +27,11 @@
 import org.eclipse.debug.internal.ui.DebugPluginImages;
 import org.eclipse.debug.internal.ui.DebugUIMessages;
 import org.eclipse.debug.internal.ui.DebugUIPlugin;
+import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
+import org.eclipse.debug.internal.ui.SWTFactory;
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTab;
 import org.eclipse.debug.ui.AbstractLaunchConfigurationTabGroup;
+import org.eclipse.debug.ui.DebugUITools;
 import org.eclipse.debug.ui.ILaunchConfigurationDialog;
 import org.eclipse.debug.ui.ILaunchConfigurationTab;
 import org.eclipse.jface.viewers.BaseLabelProvider;
@@ -219,11 +222,7 @@
 		 * @return Button
 		 */
 		protected Button createPushButton(Composite parent, String key) {
-			Button button = new Button(parent, SWT.PUSH);
-			button.setText(key);
-			button.setFont(parent.getFont());
-			GridData data = new GridData(GridData.FILL_HORIZONTAL);
-			button.setLayoutData(data);
+			Button button = SWTFactory.createPushButton(parent, key, null);
 			button.addSelectionListener(this);
 			return button;
 		}
@@ -488,6 +487,11 @@
 		}
 
 		@Override
+		public Image getImage() {
+			return DebugUITools.getImage(IInternalDebugUIConstants.IMG_OBJS_LAUNCH_GROUP);
+		}
+
+		@Override
 		public void initializeFrom(ILaunchConfiguration configuration) {
 			try {
 				self = configuration.copy(configuration.getName());