/***************************************************************************** * Copyright (c) 2010 ATOS ORIGIN. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Tristan Faure (ATOS ORIGIN INTEGRATION) tristan.faure@atosorigin.com - Initial API and implementation *****************************************************************************/ package org.eclipse.papyrus.infra.widgets.toolbox.notification.builders; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.Map; import java.util.Set; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.Platform; import org.eclipse.papyrus.infra.widgets.toolbox.notification.IBuilder; import org.eclipse.papyrus.infra.widgets.toolbox.notification.ICompositeCreator; import org.eclipse.papyrus.infra.widgets.toolbox.notification.INotification; import org.eclipse.papyrus.infra.widgets.toolbox.notification.NotificationRunnable; import org.eclipse.papyrus.infra.widgets.toolbox.notification.PapyrusToolkit; import org.eclipse.papyrus.infra.widgets.toolbox.notification.Type; import org.eclipse.papyrus.infra.widgets.toolbox.notification.popups.PopupNotification; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.forms.widgets.FormToolkit; /** * A class creating a notification, * the run method launch the message according to the value of the attributes * * @author tristan faure * */ public class NotificationBuilder { private FormToolkit toolkit = PapyrusToolkit.INSTANCE; /** The parameters of the notification with the corresponding values */ protected Map<String, Object> parameters = new HashMap<String, Object>(); /** The builders creating the notification */ protected static Map<Class<? extends IBuilder>, IBuilder> builders = getBuilders(); /** asynchronous, determines if the message needs or not to be synchronous with the notification */ static String ASYNCHRONOUS = "asynchronous"; /** a message displayed in the notification */ static String MESSAGE = "message"; /** a composite creator for the element */ static String COMPOSITE = "composite"; /** a default action in the notification */ static String ACTION = "default_action"; /** a delay to display if it is a temporary notification */ static String DELAY = "delay"; /** determines if the notification is temporary */ static String TEMPORARY = "temporary"; /** a title displayed in the notification */ static String TITLE = "title"; /** determines if there is html content in the notification */ static String HTML = "html"; /** determines the type according to {@link Type} */ static String TYPE = "type"; /** an image displayed generally at the left of the notification */ static String IMAGE = "image"; /** * Determine a specific builder class, if it is filled, it is forced to it */ protected Class<? extends IBuilder> builderClass; /** * Returns the ibuilders able to create notifications * * @return the list of {@link IBuilder} */ private static Map<Class<? extends IBuilder>, IBuilder> getBuilders() { Map<Class<? extends IBuilder>, IBuilder> result = new HashMap<Class<? extends IBuilder>, IBuilder>(); IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.papyrus.infra.widgets.toolbox.papyrusNotificationBuilder"); for(IConfigurationElement e : elements) { IBuilder instance; try { instance = (IBuilder)e.createExecutableExtension("builder"); result.put(instance.getClass(), instance); } catch (CoreException e1) { } } return result; } /** * Set a message for the notification * * @param message * , the message to display * @return this */ public NotificationBuilder setMessage(String message) { parameters.put(MESSAGE, message); return this; } /** * Determines if the notification is asynchronous (don't force the user to read the notification immediately) * * @param asynchronous * , true if it asynchronous * @return this */ public NotificationBuilder setAsynchronous(boolean asynchronous) { parameters.put(ASYNCHRONOUS, asynchronous); return this; } /** * Set a default action for the notification * * @param runnable * , a runnable triggered when default action of the notification is selected * The first action added is the default One * @return this */ @SuppressWarnings("unchecked") public NotificationBuilder addAction(NotificationRunnable runnable) { Collection<NotificationRunnable> runnables = (Collection<NotificationRunnable>)parameters.get(ACTION); if(runnables == null) { runnables = new LinkedList<NotificationRunnable>(); parameters.put(ACTION, runnables); } runnables.add(runnable); return this; } /** * Set a composite creator, able to fill a notification * * @param creator * , the composite creator * @return this */ public NotificationBuilder setComposite(ICompositeCreator creator) { parameters.put(COMPOSITE, creator); return this; } /** * Set a delay if the notification is temporary * * @param delayMs * , the delay in ms for visibility * @return this */ public NotificationBuilder setDelay(long delayMs) { parameters.put(DELAY, delayMs); return this; } /** * Set true if the notification is temporary * * @param temporary * @return this */ public NotificationBuilder setTemporary(boolean temporary) { parameters.put(TEMPORARY, temporary); return this; } /** * Set a title for the notification * * @param title * , the title * @return this */ public NotificationBuilder setTitle(String title) { parameters.put(TITLE, title); return this; } /** * Set if the notification has to understand HTML * * @param useHTML * @return this */ public NotificationBuilder setHTML(boolean useHTML) { parameters.put(HTML, useHTML); return this; } /** * Set the type of the notification according to {@link Type} * * @param type * , the desired type * @return this */ public NotificationBuilder setType(Type type) { parameters.put(TYPE, type); return this; } /** * Set an image for the notification * * @param image * , the desired image * @return this */ public NotificationBuilder setImage(Image image) { parameters.put(IMAGE, image); return this; } /** * Force a builder class * * @param builderClass * , a class which inherits from {@link IBuilder} * @return this */ public NotificationBuilder setBuilderClass(Class<? extends IBuilder> builderClass) { this.builderClass = builderClass; return this; } /** * Allows the developer to use a specific parameter * * @param name * , the key of the parameter * @param value * , the value * @return this */ public NotificationBuilder setParameter(String name, Object value) { parameters.put(name, value); return this; } /** * Creates a notification according to different parameters */ public INotification run() { Set<IBuilder> copy = null; if(builderClass != null) { copy = new HashSet<IBuilder>(); try { copy.add(builderClass.newInstance()); } catch (InstantiationException e) { } catch (IllegalAccessException e) { } } else { copy = new HashSet<IBuilder>(builders.values()); } for(Iterator<IBuilder> i = copy.iterator(); i.hasNext();) { IBuilder b = i.next(); for(String string : parameters.keySet()) { if(!b.accept(string, parameters.get(string))) { i.remove(); break; } } } INotification result = null; PropertyWrapper wrapper = new PropertyWrapper(parameters); if(copy.size() >= 1) { result = copy.iterator().next().build(wrapper, toolkit); // default case : the popup } else if(copy.isEmpty()) { result = builders.get(PopupBuilder.class).build(wrapper, toolkit); } return result; } /** * Creates a notification builder already configured to display an information builder * * @return a notification builder */ public static NotificationBuilder createInformationBuilder() { NotificationBuilder builder = new NotificationBuilder(); return builder; } /** * Creates a notification builder already configured to display an asynchronous popup * * @param text * , the text to display * @return a notification builder */ public static NotificationBuilder createAsyncPopup(String text) { return new NotificationBuilder().setAsynchronous(true).setTemporary(true).setMessage(text).setDelay(2000); } /** * Creates a notification builder already configured to display an asynchronous popup with a specified title * * @param text * , the text to display * @param title * , the title of the popup * @return a notification builder */ public static NotificationBuilder createAsyncPopup(String title, String text) { return new NotificationBuilder().setAsynchronous(true).setTemporary(true).setMessage(text).setTitle(title).setDelay(2000); } /** * Creates a notification builder already configured to display an information popup * * @param text * , the text to display * @return a notification builder */ public static NotificationBuilder createInfoPopup(String text) { return new NotificationBuilder().setAsynchronous(false).setTemporary(false).setMessage(text).setType(Type.INFO); } /** * Creates a notification builder already configured to display an warning popup * * @param text * , the text to display * @return a notification builder */ public static NotificationBuilder createWarningPopup(String text) { return new NotificationBuilder().setAsynchronous(false).setTemporary(false).setMessage(text).setType(Type.WARNING); } /** * Creates a notification builder already configured to display a popup with question icon * * @param text * , the text to display * @return a notification builder */ public static NotificationBuilder createQuestionPopup(String text) { return new NotificationBuilder().setAsynchronous(false).setTemporary(false).setMessage(text).setType(Type.QUESTION); } /** * Creates a notification builder already configured to display a popup with error icon * * @param text * , the text to display * @return a notification builder */ public static NotificationBuilder createErrorPopup(String text) { return new NotificationBuilder().setAsynchronous(false).setTemporary(false).setMessage(text).setType(Type.ERROR); } /** * Creates a notification builder already configured to display a yes no question * * @param yes * , the action to launch if yes is selected * @param no * , the action to launch if no is selected * @return a notification builder */ public static NotificationBuilder createYesNo(String message, final Runnable yes, final Runnable no) { return new NotificationBuilder().setType(Type.QUESTION).setAsynchronous(false).setTemporary(false).setMessage(message).addAction(new NotificationRunnable() { public void run(IContext context) { if(yes != null) { context.put(IContext.ACTION_ID, SWT.YES); yes.run(); } } public String getLabel() { return "Yes"; } }).addAction(new NotificationRunnable() { public void run(IContext context) { if(no != null) { context.put(IContext.ACTION_ID, SWT.NO); no.run(); } } public String getLabel() { return "No"; } }); } /** * Creates a notification builder already configured to display a yes no question, no runnables are necesary as the user just want the * PopupNotification result * This NotificationRunnable is not intended to be changed to an asynchronous notification for example * When the run method is called use getRsult method in {@link PopupNotification} and test if the value is SWT.YES or SWT.NO * @param message * , the message to display * * @return a notification builder */ public static NotificationBuilder createYesNo(String message) { return new NotificationBuilder().setType(Type.QUESTION).setAsynchronous(false).setTemporary(false).setMessage(message).addAction(new NotificationRunnable() { public void run(IContext context) { context.put(IContext.ACTION_ID, SWT.YES); } public String getLabel() { return "Yes"; } }).addAction(new NotificationRunnable() { public void run(IContext context) { context.put(IContext.ACTION_ID, SWT.NO); } public String getLabel() { return "No"; } }); } /** * Creates a notification builder already configured to display a yes no question * * @param yes * , the action to launch if yes is selected * @param no * , the action to launch if no is selected * @return a notification builder */ public static NotificationBuilder createYesNo(String message, final NotificationRunnable yes, final NotificationRunnable no) { return new NotificationBuilder().setType(Type.QUESTION).setAsynchronous(false).setTemporary(false).setMessage(message).addAction(new NotificationRunnable() { public void run(IContext context) { if(yes != null) { context.put(IContext.ACTION_ID, SWT.YES); yes.run(context); } } public String getLabel() { return "Yes"; } }).addAction(new NotificationRunnable() { public void run(IContext context) { if(no != null) { context.put(IContext.ACTION_ID, SWT.NO); no.run(context); } } public String getLabel() { return "No"; } }); } /** * Return the system image according to the imageID * * @param imageID * @param shell * @return */ public static Image getSWTImage(final int imageID, Shell shell) { final Display display; if(shell == null || shell.isDisposed()) { display = Display.getCurrent(); // The dialog should be always instantiated in UI thread. // However it was possible to instantiate it in other threads // (the code worked in most cases) so the assertion covers // only the failing scenario. See bug 107082 for details. Assert.isNotNull(display, "The dialog should be created in UI thread"); //$NON-NLS-1$ } else { display = shell.getDisplay(); } final Image[] image = new Image[1]; display.syncExec(new Runnable() { public void run() { image[0] = display.getSystemImage(imageID); } }); return image[0]; } }