Add support for status notification popups RCL_2_4
authordadubrow
Fri, 26 Feb 2010 11:30:21 -0600
branchRCL_2_4
changeset 1034 42eaaa076776
parent 1032 083e0a53ef29
child 1035 a50c0b5d243e
Add support for status notification popups
connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/api/IStatusDisplay.java
connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ui/StatusDisplay.java
--- a/connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF	Thu Feb 25 23:47:43 2010 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/META-INF/MANIFEST.MF	Fri Feb 26 11:30:21 2010 -0600
@@ -7,12 +7,13 @@
 Bundle-Vendor: Nokia
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.core.runtime,
- org.eclipse.ui,
+ org.eclipse.ui;visibility:=reexport,
  com.nokia.cpp.utils.core,
  org.eclipse.emf.ecore.xmi;bundle-version="2.4.0",
  org.eclipse.core.net;bundle-version="1.1.0",
  org.eclipse.help;bundle-version="3.4.0",
- com.nokia.cpp.utils.ui
+ com.nokia.cpp.utils.ui,
+ org.eclipse.mylyn.commons.ui;bundle-version="3.2.0"
 Bundle-RequiredExecutionEnvironment: J2SE-1.5
 Bundle-ActivationPolicy: lazy
 Export-Package: com.nokia.carbide.installpackages,
--- a/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java	Thu Feb 25 23:47:43 2010 -0600
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/RemoteConnectionsActivator.java	Fri Feb 26 11:30:21 2010 -0600
@@ -30,6 +30,8 @@
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.viewers.IFilter;
 import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.plugin.AbstractUIPlugin;
 import org.osgi.framework.BundleContext;
@@ -38,11 +40,12 @@
 import com.nokia.carbide.remoteconnections.interfaces.IConnectionTypeProvider;
 import com.nokia.carbide.remoteconnections.interfaces.IConnectionsManager;
 import com.nokia.carbide.remoteconnections.internal.api.IDeviceDiscoveryAgent;
+import com.nokia.carbide.remoteconnections.internal.api.IStatusDisplay;
 import com.nokia.carbide.remoteconnections.internal.api.IDeviceDiscoveryAgent.IPrerequisiteStatus;
 import com.nokia.carbide.remoteconnections.internal.registry.Registry;
 import com.nokia.carbide.remoteconnections.internal.ui.DeviceDiscoveryPrequisiteErrorDialog;
+import com.nokia.carbide.remoteconnections.internal.ui.StatusDisplay;
 import com.nokia.cpp.internal.api.utils.core.Logging;
-import com.nokia.cpp.internal.api.utils.ui.RunRunnableWhenWorkbenchVisibleJob;
 import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
 
 /**
@@ -50,6 +53,39 @@
  */
 public class RemoteConnectionsActivator extends AbstractUIPlugin {
 
+	private final class WhenWorkbenchIsVisibleThread extends Thread {
+		private Shell shell;
+		private boolean visible;
+		private final Runnable runnable;
+		
+		public WhenWorkbenchIsVisibleThread(Runnable runnable) {
+			this.runnable = runnable;
+			shell = WorkbenchUtils.getActiveShell();
+		}
+		
+		public void run() {
+			while (true) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						if (shell != null && shell.isVisible()) {
+							visible = true;
+						}
+					}
+				});
+				if (visible)
+					break;
+				
+				try {
+					Thread.sleep(500);
+				} catch (InterruptedException e) {
+					break;
+				}
+			}
+			if (visible)
+				runnable.run();
+		}
+	}
+
 	// The plug-in ID
 	public static final String PLUGIN_ID = "com.nokia.carbide.remoteConnections"; //$NON-NLS-1$
 
@@ -59,6 +95,7 @@
 	private static RemoteConnectionsActivator plugin;
 
 	private Collection<IDeviceDiscoveryAgent> discoveryAgents;
+
 	private static final String IGNORE_AGENT_LOAD_ERRORS_KEY = "ignoreAgentLoadErrors"; //$NON-NLS-1$
 
 	/**
@@ -74,14 +111,14 @@
 		instance.loadExtensions();
 		instance.loadConnections();
 
-		RunRunnableWhenWorkbenchVisibleJob.start(new Runnable() {
+		new WhenWorkbenchIsVisibleThread(new Runnable() {
 			public void run() {
 				if (!ignoreAgentLoadErrors())
 					checkPrerequisites();
-
+				
 				loadAndStartDeviceDiscoveryAgents();
 			}
-		});
+		}).start();
 	}
 
 	private boolean ignoreAgentLoadErrors() {
@@ -242,4 +279,8 @@
 			}
 		}
 	}
+	
+	public static IStatusDisplay getStatusDisplay() {
+		return new StatusDisplay();
+	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/api/IStatusDisplay.java	Fri Feb 26 11:30:21 2010 -0600
@@ -0,0 +1,42 @@
+/**
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.carbide.remoteconnections.internal.api;
+
+import org.eclipse.core.runtime.IStatus;
+
+public interface IStatusDisplay {
+
+	/**
+	 * Asynchronously displays status with notification UI
+	 * @param status IStatus
+	 */
+	void displayStatus(IStatus status);
+	
+	/**
+	 * Synchronously displays status with notification UI
+	 * Displays a prompt and runs action if user accepts.
+	 * Calling thread will block until notification is closed (either by timer or by user)
+	 * and if action will be called on the calling thread.
+	 * NOTE: This cannot be called on display thread!<br>
+	 * <code>assert Display.getCurrent() == null;</code>
+	 * @param status IStatus
+	 * @param prompt String
+	 * @param action Runnable
+	 */
+	void displayStatusWithAction(IStatus status, String prompt, Runnable action);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivity/com.nokia.carbide.remoteConnections/src/com/nokia/carbide/remoteconnections/internal/ui/StatusDisplay.java	Fri Feb 26 11:30:21 2010 -0600
@@ -0,0 +1,147 @@
+/**
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+package com.nokia.carbide.remoteconnections.internal.ui;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.dialogs.Dialog;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.mylyn.internal.provisional.commons.ui.AbstractNotificationPopup;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+
+import com.nokia.carbide.remoteconnections.internal.api.IStatusDisplay;
+import com.nokia.cpp.internal.api.utils.core.Check;
+
+@SuppressWarnings("restriction")
+public class StatusDisplay implements IStatusDisplay {
+		
+	private final class NotificationPopup extends AbstractNotificationPopup {
+		private final IStatus status;
+		private final String prompt;
+
+		private NotificationPopup(Display display, IStatus status, String prompt) {
+			super(display);
+			this.status = status;
+			this.prompt = prompt;
+			setDelayClose(30 * 1000);
+		}
+		
+		protected void createContentArea(Composite composite) {
+			GridLayoutFactory.fillDefaults().margins(5, 5).applyTo(composite);
+			Label label = new Label(composite, SWT.WRAP);
+			label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+			label.setText(status.getMessage());
+			label.setBackground(composite.getBackground());
+			if (prompt != null) {
+				Link link = new Link(composite, SWT.WRAP);
+				link.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+				link.setText(MessageFormat.format("<a href=\"{0}\">{0}</a>", prompt));
+				link.setBackground(composite.getBackground());
+				link.addSelectionListener(new SelectionAdapter() {
+					public void widgetSelected(SelectionEvent e) {
+						clicked = true;
+						NotificationPopup.this.close();
+					}
+				});
+			}
+		}
+		
+		@Override
+		protected String getPopupShellTitle() {
+			switch (status.getSeverity()) {
+			case IStatus.INFO:
+				return "Information";
+			case IStatus.WARNING:
+				return "Warning";
+			case IStatus.ERROR:
+				return "Error";
+			};
+			Check.checkState(false);
+			return null;
+		}
+	 
+		@Override
+		protected Image getPopupShellImage(int maximumHeight) {
+			switch (status.getSeverity()) {
+			case IStatus.INFO:
+				return JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_INFO);
+			case IStatus.WARNING:
+				return JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING);
+			case IStatus.ERROR:
+				return JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_ERROR);
+			};
+			Check.checkState(false);
+			return null;
+		}
+	}
+
+	private boolean clicked;
+	private boolean closed;
+
+	public StatusDisplay() {
+	}
+
+	public void displayStatus(final IStatus status) {
+		final Display display = Display.getDefault();
+		display.syncExec(new Runnable() {
+			public void run() {
+				doDisplayStatus(display, null, status);
+			}
+		});
+	}
+
+	public void displayStatusWithAction(final IStatus status, final String prompt, Runnable action) {
+		final Display display = Display.getDefault();
+		display.asyncExec(new Runnable() {
+			public void run() {
+				doDisplayStatus(display, prompt, status);
+			}
+		});
+		while (!closed) {
+			try {
+				Thread.sleep(200);
+			} catch (InterruptedException e1) {
+			}
+		}
+		if (clicked)
+			action.run();
+	}
+
+	protected void doDisplayStatus(Display display, String prompt, IStatus status) {
+		NotificationPopup popup = new NotificationPopup(display, status, prompt);
+		popup.open();
+		popup.getShell().addDisposeListener(new DisposeListener() {
+			public void widgetDisposed(DisposeEvent e) {
+				StatusDisplay.this.closed = true;
+			}
+		});
+	}
+
+}