Bug 353628 - No binding table for org.eclipse.ui.contexts.dialog

Properly install close-dialog keybinding for Cmd-W and comment out
warning in BindingServiceImpl
diff --git a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java
index cabb7a4..9bd7a71 100644
--- a/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java
+++ b/bundles/org.eclipse.e4.ui.bindings/src/org/eclipse/e4/ui/bindings/internal/BindingServiceImpl.java
@@ -109,7 +109,7 @@
 		String contextId = binding.getContextId();
 		BindingTable table = manager.getTable(contextId);
 		if (table == null) {
-			System.err.println("No binding table for " + contextId); //$NON-NLS-1$
+			//System.err.println("No binding table for " + contextId); //$NON-NLS-1$
 			return;
 		}
 		table.removeBinding(binding);
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIHandler.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIHandler.java
index c68c45f..598bcfa 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIHandler.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIHandler.java
@@ -36,8 +36,6 @@
 import org.eclipse.e4.ui.bindings.EBindingService;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.commands.MCommand;
-import org.eclipse.e4.ui.model.application.commands.MHandler;
-import org.eclipse.e4.ui.model.application.commands.impl.CommandsFactoryImpl;
 import org.eclipse.e4.ui.model.application.ui.MContext;
 import org.eclipse.e4.ui.model.application.ui.MUIElement;
 import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
@@ -54,8 +52,6 @@
 import org.eclipse.e4.ui.workbench.UIEvents;
 import org.eclipse.e4.ui.workbench.modeling.EModelService;
 import org.eclipse.e4.ui.workbench.renderers.swt.HandledMenuItemRenderer;
-import org.eclipse.jface.bindings.Binding;
-import org.eclipse.jface.bindings.TriggerSequence;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
@@ -97,9 +93,6 @@
 	// toggle coolbar isn't actually defined anywhere
 	private static final String COMMAND_ID_TOGGLE_COOLBAR = "org.eclipse.ui.ToggleCoolbarAction"; //$NON-NLS-1$
 
-	private static final String COMMAND_ID_CLOSE_DIALOG = "org.eclipse.ui.cocoa.closeDialog"; //$NON-NLS-1$
-	private static final String CLOSE_DIALOG_KEYSEQUENCE = "M1+W"; //$NON-NLS-1$
-
 	static long sel_toolbarButtonClicked_;
 	private static final long NSWindowToolbarButton = 3;
 
@@ -220,11 +213,6 @@
 				hookWorkbenchListeners();
 				processModelMenus();
 
-				// Now add the special Cmd-W dialog helper
-				addCloseDialogCommand();
-				addCloseDialogHandler();
-				addCloseDialogBinding();
-
 				// modify all shells opened on startup
 				for (MWindow window : app.getChildren()) {
 					modifyWindowShell(window);
@@ -336,42 +324,6 @@
 		}
 	}
 
-	private void addCloseDialogCommand() {
-		closeDialogCommand = findCommand(COMMAND_ID_CLOSE_DIALOG);
-		if (closeDialogCommand != null) {
-			return;
-		}
-		closeDialogCommand = CommandsFactoryImpl.eINSTANCE.createCommand();
-		closeDialogCommand.setElementId(COMMAND_ID_CLOSE_DIALOG);
-		closeDialogCommand.setCommandName("%command.closeDialog.name"); //$NON-NLS-1$
-		closeDialogCommand.setDescription("%command.closeDialog.desc"); //$NON-NLS-1$
-		closeDialogCommand.setContributorURI(CocoaUIProcessor.CONTRIBUTOR_URI);
-		app.getCommands().add(closeDialogCommand);
-	}
-
-	private void addCloseDialogHandler() {
-		MHandler handler = findHandler(closeDialogCommand);
-		if (handler != null) {
-			return;
-		}
-		handler = CommandsFactoryImpl.eINSTANCE.createHandler();
-		handler.setCommand(closeDialogCommand);
-		handler.setContributionURI(CocoaUIProcessor.CONTRIBUTION_URI_PREFIX
-				+ "/" + CloseDialogHandler.class.getName());//$NON-NLS-1$
-		app.getHandlers().add(handler);
-	}
-
-	private void addCloseDialogBinding() {
-		TriggerSequence sequence = bindingService
-				.createSequence(CLOSE_DIALOG_KEYSEQUENCE);
-		ParameterizedCommand cmd = commandService.createCommand(
-				COMMAND_ID_CLOSE_DIALOG, null);
-		Binding binding = bindingService.createBinding(sequence, cmd,
-				EBindingService.DIALOG_CONTEXT_ID, null);
-		bindingService.deactivateBinding(binding);
-		bindingService.activateBinding(binding);
-	}
-
 	void log(Exception e) {
 		// StatusUtil.handleStatus(e, StatusManager.LOG);
 		statusReporter
@@ -640,40 +592,6 @@
 	}
 
 	/**
-	 * Find the command definition
-	 * 
-	 * @param commandId
-	 * @return the command definition or null if not found
-	 */
-	private MCommand findCommand(String commandId) {
-		for (MCommand cmd : app.getCommands()) {
-			if (commandId.equals(cmd.getElementId())) {
-				return cmd;
-			}
-		}
-		return null;
-	}
-
-	/**
-	 * Find a handler defined for the provided command. This command returns on
-	 * the first command found.
-	 * 
-	 * @param cmd
-	 * @return the first handler found, or <code>null</code> if none
-	 */
-	private MHandler findHandler(MCommand cmd) {
-		if (cmd == null) {
-			return null;
-		}
-		for (MHandler handler : app.getHandlers()) {
-			if (handler.getCommand() == cmd) {
-				return handler;
-			}
-		}
-		return null;
-	}
-
-	/**
 	 * Locate an action (a menu item, actually) with the given id in the current
 	 * menu bar and run it.
 	 * 
diff --git a/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIProcessor.java b/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIProcessor.java
index a59fc1e..a60f09b 100644
--- a/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIProcessor.java
+++ b/bundles/org.eclipse.e4.ui.workbench.renderers.swt.cocoa/src/org/eclipse/e4/ui/workbench/renderers/swt/cocoa/CocoaUIProcessor.java
@@ -10,11 +10,18 @@
  *******************************************************************************/
 package org.eclipse.e4.ui.workbench.renderers.swt.cocoa;
 
+import java.util.List;
 import javax.inject.Inject;
+import javax.inject.Provider;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
 import org.eclipse.e4.core.di.annotations.Execute;
+import org.eclipse.e4.core.services.statusreporter.StatusReporter;
+import org.eclipse.e4.ui.bindings.EBindingService;
 import org.eclipse.e4.ui.model.application.MAddon;
 import org.eclipse.e4.ui.model.application.MApplication;
 import org.eclipse.e4.ui.model.application.MApplicationFactory;
+import org.eclipse.e4.ui.model.application.commands.MBindingContext;
 import org.eclipse.e4.ui.model.application.commands.MBindingTable;
 import org.eclipse.e4.ui.model.application.commands.MCategory;
 import org.eclipse.e4.ui.model.application.commands.MCommand;
@@ -41,19 +48,29 @@
 	static final String HOST_ID = "org.eclipse.e4.ui.workbench.renderers.swt"; //$NON-NLS-1$
 	protected static final String CONTRIBUTION_URI_PREFIX = "bundleclass://" + HOST_ID; //$NON-NLS-1$
 
+	// constants for close dialog
+	private static final String COMMAND_ID_CLOSE_DIALOG = "org.eclipse.ui.cocoa.closeDialog"; //$NON-NLS-1$
+	private static final String CLOSE_DIALOG_KEYSEQUENCE = "M1+W"; //$NON-NLS-1$
+
 	@Inject
 	protected MApplication app;
 
+	@Inject
+	protected Provider<StatusReporter> statusReporter;
+
 	/**
 	 * Execute!
 	 */
 	@Execute
 	public void execute() {
+		// hook About, Preferences, etc.
 		installAddon();
 
-		// these handlers are installed directly on the app and are thus
-		// independent of the context.
-		installHandlers();
+		// Window > Zoom, etc.
+		installWindowHandlers();
+
+		// install close dialog handlers
+		installCloseDialogHandlers();
 	}
 
 	/**
@@ -78,7 +95,7 @@
 	 * than in a <tt>fragments.e4xmi</tt> as the project
 	 * <tt>Application.e4xmi</tt> may (and likely will) use different IDs.
 	 */
-	public void installHandlers() {
+	public void installWindowHandlers() {
 		installHandler(
 				defineCommand(
 						"org.eclipse.ui.category.window", "org.eclipse.ui.cocoa.arrangeWindowsInFront", //$NON-NLS-1$ //$NON-NLS-2$
@@ -107,6 +124,18 @@
 				ZoomWindowHandler.class, CONTRIBUTOR_URI);
 	}
 
+	/** Add the special Cmd-W dialog helper */
+	private void installCloseDialogHandlers() {
+		MCommand closeDialogCommand = defineCommand(
+				"org.eclipse.ui.category.window", COMMAND_ID_CLOSE_DIALOG, //$NON-NLS-1$
+				"%command.closeDialog.name", //$NON-NLS-1$
+				"%command.closeDialog.desc", CONTRIBUTOR_URI);//$NON-NLS-1$
+		installHandler(closeDialogCommand, CloseDialogHandler.class,
+				CONTRIBUTOR_URI);
+		installKeybinding(EBindingService.DIALOG_CONTEXT_ID,
+				CLOSE_DIALOG_KEYSEQUENCE, closeDialogCommand);
+	}
+
 	/**
 	 * Install a keybinding to the provided command, providing the command is
 	 * not already bound to another keybinding.
@@ -139,10 +168,22 @@
 		}
 
 		if (bindingTable == null) {
-			// perhaps we should create it
-			System.err.println("Cannot find table for binding context: " //$NON-NLS-1$
-					+ bindingContextId);
-			return;
+			MBindingContext bindingContext = findBindingContext(
+					app.getBindingContexts(), bindingContextId);
+			if (bindingContext == null) {
+				statusReporter
+						.get()
+						.report(new Status(
+								IStatus.WARNING,
+								CocoaUIProcessor.FRAGMENT_ID,
+								"No binding context exists for " + bindingContextId), //$NON-NLS-1$
+						StatusReporter.LOG);
+				return;
+			}
+			bindingTable = MCommandsFactory.INSTANCE.createBindingTable();
+			bindingTable.setBindingContext(bindingContext);
+			bindingTable.setContributorURI(CONTRIBUTOR_URI);
+			app.getBindingTables().add(bindingTable);
 		}
 
 		MKeyBinding binding = MCommandsFactory.INSTANCE.createKeyBinding();
@@ -152,6 +193,26 @@
 	}
 
 	/**
+	 * @param bindingContexts
+	 * @param bindingContextId
+	 * @return
+	 */
+	private MBindingContext findBindingContext(
+			List<MBindingContext> bindingContexts, String bindingContextId) {
+		for (MBindingContext bc : bindingContexts) {
+			if (bindingContextId.equals(bc.getElementId())) {
+				return bc;
+			}
+			MBindingContext result = findBindingContext(bc.getChildren(),
+					bindingContextId);
+			if (result != null) {
+				return result;
+			}
+		}
+		return null;
+	}
+
+	/**
 	 * Configure and install a command handler for the provided command and
 	 * handler
 	 *