/******************************************************************************* * Copyright (c) 2010, 2013 Itema AS and others. * 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: * Itema AS - initial API and implementation *******************************************************************************/ package org.eclipse.mylyn.internal.builds.ui.notifications; import java.util.HashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.mylyn.builds.core.IBuildServer; import org.eclipse.mylyn.builds.ui.BuildsUi; import org.eclipse.mylyn.builds.ui.spi.BuildServerWizard; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.notifications.core.AbstractNotification; import org.eclipse.mylyn.commons.notifications.core.NotificationSinkEvent; import org.eclipse.mylyn.commons.notifications.ui.AbstractUiNotification; import org.eclipse.mylyn.commons.notifications.ui.NotificationControl; import org.eclipse.mylyn.commons.repositories.core.RepositoryLocation; import org.eclipse.mylyn.internal.builds.ui.BuildsUiPlugin; import org.eclipse.mylyn.internal.builds.ui.view.NewBuildServerAction; import org.eclipse.mylyn.internal.commons.repositories.ui.wizards.NewRepositoryWizardRegistry; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.wizards.IWizardDescriptor; /** * GUI control designed to display build service messages. These messages can contain links that may be clicked by the * user and handled here. The following link formats are allowed: * <ul> * <li><code>create</code> - Calls the create wizard selection dialog.</li> * <li><code>discover:<id>?<arguments></code> - Calls the wizard with the specified id and passes along the * given arguments.</li> * </ul> * <p> * An exact list of which properties are supported can be found in {@link RepositoryLocation}. * </p> * <p> * A stack of messages is maintained. When a new message arrives it is placed on top of the stack and displayed. * </p> * <p> * The code was lifted from org.eclipse.mylyn.internal.tasks.ui.notifications and modified to be suitable for this use. * It also has been simplified a bit. * </p> * * @author Torkild U. Resheim */ public class BuildsServiceMessageControl extends NotificationControl { private final CopyOnWriteArrayList<AbstractNotification> messages; //private final Stack<AbstractNotification> messages; public BuildsServiceMessageControl(Composite parent) { super(parent); messages = new CopyOnWriteArrayList<AbstractNotification>(); } protected void closeMessage() { if (messages.isEmpty()) { close(); } else { nextMessage(); } } private void nextMessage() { if (!messages.isEmpty()) { AbstractNotification message = messages.remove(0); if (ensureControl()) { setTitle(message.getLabel()); setDescription(message.getDescription()); if (message instanceof AbstractUiNotification) { setTitleImage(((AbstractUiNotification) message).getNotificationKindImage()); } setEventId(message.getEventId()); } } } /** * Opens a new repository wizard using the given data. * * @param data */ private void openRepositoryWizard(String data) { String connectorKind = data; if (data.indexOf('?') > -1) { connectorKind = data.substring(0, data.indexOf('?')); } // Get the Mylyn repository wizard IWizardDescriptor descriptor = NewRepositoryWizardRegistry.getInstance().findWizard(connectorKind); try { // Then if we have a wizard, open it. if (descriptor != null) { // This will use the default constructor so we need to convey some data. IWizard wizard = descriptor.createWizard(); if (wizard instanceof BuildServerWizard) { try { // Set data we got from the discovery mechanism. This // comes as a list of properties with keys and values. HashMap<String, String> properties = new HashMap<String, String>(); int i = data.indexOf('?'); if (i > -1) { String[] props = data.substring(i + 1).split("&"); //$NON-NLS-1$ for (String set : props) { String[] kv = set.split("="); //$NON-NLS-1$ properties.put(kv[0], kv[1]); } } IBuildServer bs = BuildsUi.createServer(connectorKind); RepositoryLocation rl = new RepositoryLocation(properties); bs.getLocation().apply(rl); ((BuildServerWizard) wizard).setBuildServer(bs); } catch (Exception e) { StatusHandler.log(new Status(IStatus.ERROR, BuildsUiPlugin.ID_PLUGIN, Messages.BuildsServiceMessageControl_ErrorStartingWizard, e)); } } WizardDialog wd = new WizardDialog(getShell(), wizard); wd.setTitle(wizard.getWindowTitle()); wd.open(); } } catch (CoreException e) { StatusHandler.log(new Status(IStatus.ERROR, BuildsUiPlugin.ID_PLUGIN, Messages.BuildsServiceMessageControl_ErrorStartingWizard, e)); } } @Override protected SelectionListener getLinkListener() { return new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { if (e.text != null) { String cmd = null; String args = null; if (e.text.contains(":")) { //$NON-NLS-1$ cmd = e.text.substring(0, e.text.indexOf(':')).toLowerCase(); args = e.text.substring(e.text.indexOf(':') + 1); } else { cmd = e.text.toLowerCase(); } if (cmd.equals("create")) { //$NON-NLS-1$ closeMessage(); new NewBuildServerAction().run(); } else if (cmd.equals("discover")) { //$NON-NLS-1$ closeMessage(); if (args != null) { openRepositoryWizard(args); } } } } }; } public void notify(final NotificationSinkEvent event) { for (final AbstractNotification message : event.getNotifications()) { messages.add(message); } // Show the next message but only if we're currently not // showing any messages. Display.getDefault().asyncExec(new Runnable() { public void run() { if (isClosed()) { nextMessage(); } } }); } }