### Eclipse Workspace Patch 1.0 #P org.eclipse.mylyn.bugzilla.ui Index: plugin.xml =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.bugzilla.ui/plugin.xml,v retrieving revision 1.109 diff -u -r1.109 plugin.xml --- plugin.xml 24 Jan 2010 14:30:07 -0000 1.109 +++ plugin.xml 24 May 2010 22:06:27 -0000 @@ -30,6 +30,9 @@ + + Index: src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaRepositoryMigrator.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaRepositoryMigrator.java diff -N src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaRepositoryMigrator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/bugzilla/ui/tasklist/BugzillaRepositoryMigrator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.bugzilla.ui.tasklist; + +import org.eclipse.mylyn.internal.bugzilla.core.BugzillaCorePlugin; +import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryMigrator; +import org.eclipse.mylyn.tasks.core.TaskRepository; + +/** + * @author Robert Elves + * @since 3.4 + */ +public class BugzillaRepositoryMigrator extends AbstractRepositoryMigrator { + + @Override + public String getConnectorKind() { + return BugzillaCorePlugin.CONNECTOR_KIND; + } + + @Override + public boolean migrateRepository(TaskRepository repository) { + if (repository.getProperty(IRepositoryConstants.PROPERTY_CATEGORY) == null) { + repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_BUGS); + return true; + } + return false; + +// repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_BUGS); +// +// if (repository.getConnectorKind().equals("bugzilla") || repository.getConnectorKind().equals("local")) { +// if (repository.getRepositoryUrl().contains("bugs.eclipse.org")) { +// repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_BUGS); +// } else { +// repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_TASKS); +// } +// } else { +// String category = repository.getProperty(IRepositoryConstants.PROPERTY_CATEGORY); +// if (category == null) { +// repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_OTHER); +// } +// } + } + +} #P org.eclipse.mylyn.tasks.core Index: META-INF/MANIFEST.MF =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.core/META-INF/MANIFEST.MF,v retrieving revision 1.365 diff -u -r1.365 MANIFEST.MF --- META-INF/MANIFEST.MF 11 Apr 2010 19:49:55 -0000 1.365 +++ META-INF/MANIFEST.MF 24 May 2010 22:06:29 -0000 @@ -14,6 +14,7 @@ org.eclipse.mylyn.internal.tasks.core;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs", org.eclipse.mylyn.internal.tasks.core.data;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs", org.eclipse.mylyn.internal.tasks.core.externalization;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs", + org.eclipse.mylyn.internal.tasks.core.notifications;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs", org.eclipse.mylyn.internal.tasks.core.sync;x-friends:="org.eclipse.mylyn.tasks.ui,org.eclipse.mylyn.tasks.bugs", org.eclipse.mylyn.tasks.core, org.eclipse.mylyn.tasks.core.data, Index: src/org/eclipse/mylyn/internal/tasks/core/TaskRepositoryManager.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/TaskRepositoryManager.java,v retrieving revision 1.32 diff -u -r1.32 TaskRepositoryManager.java --- src/org/eclipse/mylyn/internal/tasks/core/TaskRepositoryManager.java 10 Jan 2010 05:02:07 -0000 1.32 +++ src/org/eclipse/mylyn/internal/tasks/core/TaskRepositoryManager.java 24 May 2010 22:06:29 -0000 @@ -33,6 +33,7 @@ import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryDelta.Type; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryMigrator; import org.eclipse.mylyn.tasks.core.IRepositoryListener; import org.eclipse.mylyn.tasks.core.IRepositoryManager; import org.eclipse.mylyn.tasks.core.ITask; @@ -57,6 +58,7 @@ private final Map repositoryConnectors = new HashMap(); + // connector kinds to corresponding repositories private final Map> repositoryMap = new HashMap>(); private final Set listeners = new CopyOnWriteArraySet(); @@ -67,6 +69,8 @@ public static final String PREFIX_LOCAL = "local-"; //$NON-NLS-1$ + private static final Map repositoryCategories = new HashMap(); + private final PropertyChangeListener PROPERTY_CHANGE_LISTENER = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { TaskRepositoryManager.this.notifyRepositorySettingsChanged((TaskRepository) evt.getSource(), @@ -76,7 +80,16 @@ private final TaskRepositoriesExternalizer externalizer = new TaskRepositoriesExternalizer(); + private List migrators; + public TaskRepositoryManager() { + this.migrators = Collections.emptyList(); + Category catTasks = new Category(IRepositoryConstants.CATEGORY_TASKS, "Tasks", 0); //$NON-NLS-1$ + repositoryCategories.put(catTasks.getId(), catTasks); + Category catBugs = new Category(IRepositoryConstants.CATEGORY_BUGS, "Bugs", 100); //$NON-NLS-1$ + repositoryCategories.put(catBugs.getId(), catBugs); + Category catOther = new Category(IRepositoryConstants.CATEGORY_OTHER, "Other", 200); //$NON-NLS-1$ + repositoryCategories.put(catOther.getId(), catOther); } public synchronized Collection getRepositoryConnectors() { @@ -118,6 +131,7 @@ // TODO 4.0 return false to indicate that remove was unsuccessful return; } + repository.addChangeListener(PROPERTY_CHANGE_LISTENER); } @@ -182,6 +196,15 @@ return sb.toString(); } + public Category getCategory(String id) { + Category category = repositoryCategories.get(IRepositoryConstants.CATEGORY_OTHER); + Category cat = repositoryCategories.get(id); + if (cat != null) { + category = cat; + } + return category; + } + public TaskRepository getRepository(String kind, String urlString) { Assert.isNotNull(kind); Assert.isNotNull(urlString); @@ -233,11 +256,11 @@ return null; } - public Set getRepositories(String kind) { - Assert.isNotNull(kind); + public Set getRepositories(String connectorKind) { + Assert.isNotNull(connectorKind); Set result; synchronized (this) { - result = repositoryMap.get(kind); + result = repositoryMap.get(connectorKind); } if (result == null) { return Collections.emptySet(); @@ -309,9 +332,14 @@ if (removeHttpAuthMigration(repository)) { migration = true; } + if (applyMigrators(repository)) { + migration = true; + } if (repositoryMap.containsKey(repository.getConnectorKind())) { repositoryMap.get(repository.getConnectorKind()).add(repository); + repository.addChangeListener(PROPERTY_CHANGE_LISTENER); + } else { orphanedRepositories.add(repository); } @@ -323,6 +351,33 @@ } } + private boolean applyMigrators(final TaskRepository repository) { + final boolean[] result = new boolean[1]; + for (AbstractRepositoryMigrator migrator : migrators) { + if (migrator.getConnectorKind().equals(repository.getConnectorKind())) { + + final AbstractRepositoryMigrator finalRepositoryMigrator = migrator; + result[0] = false; + SafeRunner.run(new ISafeRunnable() { + + public void handleException(Throwable e) { + StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, + "Repository migration failed for repository \"" + repository.getUrl() + "\"", e)); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public void run() throws Exception { + if (finalRepositoryMigrator.migrateRepository(repository)) { + result[0] = true; + } + } + + }); + break; + } + } + return result[0]; + } + @SuppressWarnings("deprecation") private boolean removeHttpAuthMigration(TaskRepository repository) { String httpusername = repository.getProperty(TaskRepository.AUTH_HTTP_USERNAME); @@ -447,4 +502,13 @@ } } + public Category getCategory(TaskRepository repository) { + String categoryId = repository.getProperty(IRepositoryConstants.PROPERTY_CATEGORY); + return getCategory(categoryId); + } + + public void initialize(List repositoryMigrators) { + this.migrators = repositoryMigrators; + + } } Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/IServiceMessageListener.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/IServiceMessageListener.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/IServiceMessageListener.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/IServiceMessageListener.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.notifications; + +/** + * @author Robert Elves + */ +public interface IServiceMessageListener { + + public void handleEvent(ServiceMessageEvent event); + +} Index: src/org/eclipse/mylyn/tasks/core/AbstractRepositoryMigrator.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/core/AbstractRepositoryMigrator.java diff -N src/org/eclipse/mylyn/tasks/core/AbstractRepositoryMigrator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/core/AbstractRepositoryMigrator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.core; + +/** + * @author Robert Elves + * @since 3.4 + */ +public abstract class AbstractRepositoryMigrator { + + public abstract String getConnectorKind(); + + public boolean migrateRepository(TaskRepository repository) { + return false; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageXmlHandler.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.notifications; + +import java.util.ArrayList; +import java.util.List; + +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +/** + * @author Robert Elves + * @author Steffen Pingel + */ +public class ServiceMessageXmlHandler extends DefaultHandler { + + private static final String TAG_MESSAGE = "ServiceMessage"; //$NON-NLS-1$ + + private StringBuilder characters; + + private final List messages = new ArrayList(); + + private ServiceMessage message; + + @Override + public void characters(char[] ch, int start, int length) throws SAXException { + characters.append(ch, start, length); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (TAG_MESSAGE.equals(qName.trim())) { + message = new ServiceMessage(); + } + characters = new StringBuilder(); + } + + @Override + public void endElement(String uri, String localName, String qName) throws SAXException { + if (message == null) { + return; + } + if (TAG_MESSAGE.equals(qName.trim())) { + if (message.isValid()) { + messages.add(message); + } + } else { + String parsedText = characters.toString(); + ServiceMessage.Element element; + try { + element = ServiceMessage.Element.valueOf(qName.trim().toUpperCase()); + switch (element) { + case ID: + message.setId(parsedText); + break; + case DESCRIPTION: + message.setDescription(parsedText); + break; + case TITLE: + message.setTitle(parsedText); + break; + case URL: + message.setUrl(parsedText); + break; + case IMAGE: + message.setImage(parsedText); + break; + case VERSION: + message.setVersion(parsedText); + break; + } + } catch (IllegalArgumentException e) { + // ignore unrecognized elements + } + } + } + + public List getMessages() { + return new ArrayList(messages); + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,225 @@ +/******************************************************************************* + * Copyright (c) 2004, 2008 Tasktop Technologies. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Tasktop EULA + * which accompanies this distribution, and is available at + * http://tasktop.com/legal + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.notifications; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HostConfiguration; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.methods.GetMethod; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.SafeRunner; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.SubProgressMonitor; +import org.eclipse.core.runtime.jobs.IJobChangeEvent; +import org.eclipse.core.runtime.jobs.Job; +import org.eclipse.core.runtime.jobs.JobChangeAdapter; +import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.commons.net.WebLocation; +import org.eclipse.mylyn.commons.net.WebUtil; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; + +/** + * @author Robert Elves + * @author Steffen Pingel + */ +public class ServiceMessageManager { + + protected static final long START_DELAY = 30 * 1000; + + protected static final long RECHECK_DELAY = 2 * 60 * 60 * 1000; + + private String serviceMessageUrl; + + private volatile List messages = Collections.emptyList(); + + private Job messageCheckJob; + + private final List listeners = new CopyOnWriteArrayList(); + + private String lastModified; + + private String eTag; + + private boolean statusLogged; + + public ServiceMessageManager(String serviceMessageUrl, String lastModified, String eTag) { + this.serviceMessageUrl = serviceMessageUrl; + this.lastModified = lastModified; + this.eTag = eTag; + } + + public void start() { + if (messageCheckJob == null) { + messageCheckJob = new Job("Checking for new service message") { //$NON-NLS-1$ + @Override + protected IStatus run(IProgressMonitor monitor) { + updateServiceMessage(monitor); + return Status.OK_STATUS; + } + + }; + messageCheckJob.setSystem(true); + messageCheckJob.setPriority(Job.DECORATE); + messageCheckJob.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + if (messageCheckJob != null) { + messageCheckJob.schedule(RECHECK_DELAY); + } + } + }); + } + messageCheckJob.schedule(START_DELAY); + } + + public void stop() { + if (messageCheckJob != null) { + messageCheckJob.cancel(); + messageCheckJob = null; + } + + final ServiceMessageEvent event = new ServiceMessageEvent(this, ServiceMessageEvent.EVENT_KIND.STOP); + + for (final IServiceMessageListener listener : listeners) { + SafeRunner.run(new ISafeRunnable() { + public void run() throws Exception { + listener.handleEvent(event); + } + + public void handleException(Throwable e) { + StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, "Listener failed: " //$NON-NLS-1$ + + listener.getClass(), e)); + } + }); + } + } + + public void setServiceMessageUrl(String url) { + this.serviceMessageUrl = url; + } + + public void addServiceMessageListener(IServiceMessageListener listener) { + listeners.add(listener); + } + + public void removeServiceMessageListener(IServiceMessageListener listener) { + listeners.remove(listener); + } + + private void notifyListeners(List messages) { + this.messages = messages; + for (final ServiceMessage message : messages) { + message.setETag(eTag); + message.setLastModified(lastModified); + } + + final ServiceMessageEvent event = new ServiceMessageEvent(this, ServiceMessageEvent.EVENT_KIND.MESSAGE_UPDATE, + messages); + + for (final IServiceMessageListener listener : listeners) { + SafeRunner.run(new ISafeRunnable() { + public void run() throws Exception { + listener.handleEvent(event); + } + + public void handleException(Throwable e) { + StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, "Listener failed: " //$NON-NLS-1$ + + listener.getClass(), e)); + } + }); + } + } + + public List getServiceMessages() { + return new ArrayList(this.messages); + } + + /** + * Public for testing + */ + public int updateServiceMessage(IProgressMonitor monitor) { + int status = -1; + List messages = null; + try { + HttpClient httpClient = new HttpClient(WebUtil.getConnectionManager()); + WebUtil.configureHttpClient(httpClient, null); + + WebLocation location = new WebLocation(serviceMessageUrl); + HostConfiguration hostConfiguration = WebUtil.createHostConfiguration(httpClient, location, + new SubProgressMonitor(monitor, 1)); + + GetMethod method = new GetMethod(serviceMessageUrl); + method.setRequestHeader("If-Modified-Since", lastModified); //$NON-NLS-1$ + method.setRequestHeader("If-None-Match", eTag); //$NON-NLS-1$ + + try { + status = WebUtil.execute(httpClient, hostConfiguration, method, monitor); + if (status == HttpStatus.SC_OK && messageCheckJob != null) { + Header lastModifiedHeader = method.getResponseHeader("Last-Modified"); //$NON-NLS-1$ + if (lastModifiedHeader != null) { + lastModified = lastModifiedHeader.getValue(); + } + Header eTagHeader = method.getResponseHeader("ETag"); //$NON-NLS-1$ + if (eTagHeader != null) { + eTag = eTagHeader.getValue(); + } + + InputStream in = WebUtil.getResponseBodyAsStream(method, monitor); + try { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + SAXParser parser = factory.newSAXParser(); + + ServiceMessageXmlHandler handler = new ServiceMessageXmlHandler(); + parser.parse(in, handler); + messages = handler.getMessages(); + } finally { + in.close(); + } + } else if (status == HttpStatus.SC_NOT_FOUND) { + // no messages + } else if (status == HttpStatus.SC_NOT_MODIFIED) { + // no new messages + } else { + if (!statusLogged) { + statusLogged = true; + StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, + "Http error retrieving service message: " + HttpStatus.getStatusText(status))); //$NON-NLS-1$ + } + } + } finally { + WebUtil.releaseConnection(method, monitor); + } + } catch (Exception e) { + if (!statusLogged) { + statusLogged = true; + StatusHandler.log(new Status(IStatus.WARNING, ITasksCoreConstants.ID_PLUGIN, + "Http error retrieving service message.", e)); //$NON-NLS-1$ + } + } + + if (messages != null && messages.size() > 0) { + notifyListeners(messages); + } + return status; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessage.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.notifications; + +/** + * @author Robert Elves + */ +public class ServiceMessage { + + public enum Element { + ID, TITLE, DESCRIPTION, URL, IMAGE, VERSION + }; + + private String id; + + private String title; + + private String description; + + private String url; + + private String image; + + private String version; + + private String eTag; + + private String lastModified; + + public String getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getDescription() { + return description; + } + + public String getUrl() { + return url; + } + + public String getImage() { + return image; + } + + public void setETag(String eTag) { + this.eTag = eTag; + } + + public void setLastModified(String lastModified) { + this.lastModified = lastModified; + } + + public String getETag() { + return eTag; + } + + public String getLastModified() { + return lastModified; + } + + public String getVersion() { + return version; + } + + public void setId(String id) { + this.id = id; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setUrl(String url) { + this.url = url; + } + + public void setImage(String image) { + this.image = image; + } + + public void setVersion(String version) { + this.version = version; + } + + public boolean isValid() { + return id != null && title != null && description != null && image != null; + } + +} Index: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageEvent.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageEvent.java diff -N src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageEvent.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/core/notifications/ServiceMessageEvent.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.core.notifications; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.EventObject; +import java.util.List; + +/** + * @author Steffen Pingel + */ +public class ServiceMessageEvent extends EventObject { + + public enum EVENT_KIND { + MESSAGE_UPDATE, STOP + }; + + private static final long serialVersionUID = 1L; + + private final List messages; + + private final EVENT_KIND eventKind; + + public ServiceMessageEvent(ServiceMessageManager manager, EVENT_KIND kind) { + this(manager, kind, new ArrayList()); + } + + public ServiceMessageEvent(ServiceMessageManager manager, EVENT_KIND eventKind, List messages) { + super(manager); + this.eventKind = eventKind; + this.messages = Collections.unmodifiableList(new ArrayList(messages)); + } + + public List getMessages() { + return messages; + } + + public EVENT_KIND getEventKind() { + return eventKind; + } + +} #P org.eclipse.mylyn.tasks.tests Index: src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java,v retrieving revision 1.87 diff -u -r1.87 AllTasksTests.java --- src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java 4 Mar 2010 18:41:15 -0000 1.87 +++ src/org/eclipse/mylyn/tasks/tests/AllTasksTests.java 24 May 2010 22:06:30 -0000 @@ -30,6 +30,7 @@ import org.eclipse.mylyn.tasks.tests.ui.editor.RepositoryCompletionProcessorTest; import org.eclipse.mylyn.tasks.tests.ui.editor.TaskEditorPartDescriptorTest; import org.eclipse.mylyn.tasks.tests.ui.editor.TaskUrlHyperlinkDetectorTest; +import org.eclipse.mylyn.tasks.tests.util.ServiceMessageManagerTest; /** * @author Mik Kersten @@ -102,6 +103,7 @@ suite.addTestSuite(PlanningPartTest.class); suite.addTestSuite(RepositoryCompletionProcessorTest.class); suite.addTestSuite(TaskAttributeDiffTest.class); + suite.addTestSuite(ServiceMessageManagerTest.class); // XXX long running tests, put back? //suite.addTestSuite(QueryExportImportTest.class); //suite.addTestSuite(BackgroundSaveTest.class); Index: src/org/eclipse/mylyn/tasks/tests/util/ServiceMessageManagerTest.java =================================================================== RCS file: src/org/eclipse/mylyn/tasks/tests/util/ServiceMessageManagerTest.java diff -N src/org/eclipse/mylyn/tasks/tests/util/ServiceMessageManagerTest.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/tasks/tests/util/ServiceMessageManagerTest.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.tasks.tests.util; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import junit.framework.TestCase; + +import org.apache.commons.httpclient.HttpStatus; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessage; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageManager; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageXmlHandler; + +/** + * @author Robert Elves + */ +public class ServiceMessageManagerTest extends TestCase { + + private static final String MESSAGE_XML_URL = "http://eclipse.org/mylyn/messageTest.xml"; + + public void testRetrievingMessage() throws Exception { + ServiceMessageManager manager = new ServiceMessageManager(MESSAGE_XML_URL, "", ""); + int status = manager.updateServiceMessage(new NullProgressMonitor()); + assertEquals(HttpStatus.SC_OK, status); + ServiceMessage message = manager.getServiceMessages().get(0); + + assertEquals("1", message.getId()); + assertEquals("140 character description here....", message.getDescription()); + assertEquals("Mylyn 3.4 now available!", message.getTitle()); + assertEquals("http://eclipse.org/mylyn/downloads", message.getUrl()); + assertEquals("Mylyn 3.4 now available!", message.getTitle()); + assertEquals("dialog_messasge_info_image", message.getImage()); + } + + public void testETag() throws Exception { + + ServiceMessageManager manager = new ServiceMessageManager(MESSAGE_XML_URL, "", ""); + int status = manager.updateServiceMessage(new NullProgressMonitor()); + assertEquals(HttpStatus.SC_OK, status); + ServiceMessage message = manager.getServiceMessages().get(0); + + assertNotNull(message.getLastModified()); + assertNotNull(message.getETag()); + + status = manager.updateServiceMessage(new NullProgressMonitor()); + assertEquals(HttpStatus.SC_NOT_MODIFIED, status); + } + + public void testParsingMessageXml() throws Exception { + String messageXml = " 1140 character description here....Mylyn 3.4 now available!http://eclipse.org/mylyn/downloadsdialog_messasge_info_image"; + InputStream is = new ByteArrayInputStream(messageXml.getBytes("UTF-8")); + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + SAXParser parser = factory.newSAXParser(); + ServiceMessageXmlHandler handler = new ServiceMessageXmlHandler(); + parser.parse(is, handler); + ServiceMessage message = handler.getMessages().get(0); + + assertEquals("1", message.getId()); + assertEquals("140 character description here....", message.getDescription()); + assertEquals("Mylyn 3.4 now available!", message.getTitle()); + assertEquals("http://eclipse.org/mylyn/downloads", message.getUrl()); + assertEquals("Mylyn 3.4 now available!", message.getTitle()); + assertEquals("dialog_messasge_info_image", message.getImage()); + } + +} #P org.eclipse.mylyn.tasks.ui Index: src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoriesView.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoriesView.java,v retrieving revision 1.44 diff -u -r1.44 TaskRepositoriesView.java --- src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoriesView.java 13 Oct 2009 01:11:06 -0000 1.44 +++ src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoriesView.java 24 May 2010 22:06:31 -0000 @@ -22,10 +22,9 @@ import org.eclipse.jface.viewers.DecoratingLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.TableViewer; -import org.eclipse.jface.viewers.Viewer; +import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.mylyn.commons.core.StatusHandler; +import org.eclipse.mylyn.internal.tasks.core.Category; import org.eclipse.mylyn.internal.tasks.core.IRepositoryModelListener; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryAdapter; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; @@ -50,6 +49,7 @@ import org.eclipse.ui.handlers.IHandlerService; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds; +import org.eclipse.ui.themes.IThemeManager; /** * @author Mik Kersten @@ -62,7 +62,7 @@ @Deprecated public static final String ID = ITasksUiConstants.ID_VIEW_REPOSITORIES; - private TableViewer viewer; + private TreeViewer viewer; private final Action addRepositoryAction = new AddRepositoryAction(); @@ -121,18 +121,6 @@ } }; - static class ViewContentProvider implements IStructuredContentProvider { - public void inputChanged(Viewer v, Object oldInput, Object newInput) { - } - - public void dispose() { - } - - public Object[] getElements(Object parent) { - return TasksUi.getRepositoryManager().getAllRepositories().toArray(); - } - } - public TaskRepositoriesView() { TasksUi.getRepositoryManager().addListener(REPOSITORY_LISTENER); TasksUiPlugin.getDefault().addModelListener(MODEL_LISTENER); @@ -172,27 +160,14 @@ @Override public void createPartControl(Composite parent) { - viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); - viewer.setContentProvider(new ViewContentProvider()); + viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); + viewer.setContentProvider(new TeamRepositoriesContentProvider()); viewer.setUseHashlookup(true); viewer.setLabelProvider(new DecoratingLabelProvider(new TaskRepositoryLabelProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator())); - viewer.setSorter(new TaskRepositoriesSorter()); + viewer.setSorter(new TaskRepositoriesViewSorter()); -// new ViewerSorter() { -// -// @Override -// public int compare(Viewer viewer, Object e1, Object e2) { -// if (e1 instanceof TaskRepository && e2 instanceof TaskRepository) { -// TaskRepository t1 = (TaskRepository) e1; -// TaskRepository t2 = (TaskRepository) e2; -// return (t1.getKind() + t1.getUrl()).compareTo(t2.getKind() + t2.getUrl()); -// } else { -// return super.compare(viewer, e1, e2); -// } -// } -// }); viewer.setInput(getViewSite()); viewer.addDoubleClickListener(new IDoubleClickListener() { public void doubleClick(DoubleClickEvent event) { @@ -208,13 +183,19 @@ } }); - // FIXME remove listener when view is disposed - TasksUi.getRepositoryManager().addListener(new TaskRepositoryListener()); + final IThemeManager themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager(); + new GradientDrawer(themeManager, getViewer()) { + @Override + protected boolean shouldApplyGradient(org.eclipse.swt.widgets.Event event) { + return event.item.getData() instanceof Category; + } + }; makeActions(); hookContextMenu(); hookGlobalActions(); contributeToActionBars(); + getViewer().expandAll(); getSite().setSelectionProvider(getViewer()); } @@ -288,28 +269,12 @@ public void refresh() { if (viewer != null && !viewer.getControl().isDisposed()) { viewer.refresh(); + viewer.expandAll(); } } - public TableViewer getViewer() { + public TreeViewer getViewer() { return viewer; } - public class TaskRepositoryListener extends TaskRepositoryAdapter { - - @Override - public void repositorySettingsChanged(TaskRepository repository) { - if (PlatformUI.isWorkbenchRunning() && !PlatformUI.getWorkbench().getDisplay().isDisposed()) { - PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() { - public void run() { - if (!getViewer().getControl().isDisposed()) { - getViewer().refresh(true); - } - } - }); - } - } - - } - } Index: src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java,v retrieving revision 1.338 diff -u -r1.338 TaskListView.java --- src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java 26 Apr 2010 17:37:32 -0000 1.338 +++ src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListView.java 24 May 2010 22:06:31 -0000 @@ -64,6 +64,9 @@ import org.eclipse.mylyn.internal.tasks.core.ITaskListChangeListener; import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.internal.tasks.core.TaskContainerDelta; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageEvent; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageManager; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageEvent.EVENT_KIND; import org.eclipse.mylyn.internal.tasks.ui.AbstractTaskListFilter; import org.eclipse.mylyn.internal.tasks.ui.CategorizedPresentation; import org.eclipse.mylyn.internal.tasks.ui.ITasksUiPreferenceConstants; @@ -86,6 +89,7 @@ import org.eclipse.mylyn.internal.tasks.ui.actions.TaskListSortAction; import org.eclipse.mylyn.internal.tasks.ui.actions.TaskListViewActionGroup; import org.eclipse.mylyn.internal.tasks.ui.editors.TaskListChangeAdapter; +import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListServiceMessageControl; import org.eclipse.mylyn.internal.tasks.ui.util.PlatformUtil; import org.eclipse.mylyn.internal.tasks.ui.util.SortCriterion; import org.eclipse.mylyn.internal.tasks.ui.util.TaskDragSourceListener; @@ -131,6 +135,7 @@ import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Text; @@ -390,6 +395,8 @@ private CustomTaskListDecorationDrawer customDrawer; + private TaskListServiceMessageControl serviceMessageControl; + private final IPageListener PAGE_LISTENER = new IPageListener() { public void pageActivated(IWorkbenchPage page) { filteredTree.indicateActiveTaskWorkingSet(); @@ -554,6 +561,7 @@ @Override public void dispose() { super.dispose(); + TasksUiPlugin.getDefault().getServiceMessageManager().removeServiceMessageListener(serviceMessageControl); TasksUiPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(tasksUiPreferenceListener); TasksUiInternal.getTaskList().removeChangeListener(TASKLIST_CHANGE_LISTENER); TasksUiPlugin.getTaskActivityManager().removeActivityListener(TASK_ACTIVITY_LISTENER); @@ -730,6 +738,15 @@ @Override public void createPartControl(Composite parent) { + Composite body = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.horizontalSpacing = 0; + layout.verticalSpacing = 0; + layout.numColumns = 1; + body.setLayout(layout); + IWorkbenchSiteProgressService progress = (IWorkbenchSiteProgressService) getSite().getAdapter( IWorkbenchSiteProgressService.class); if (progress != null) { @@ -743,7 +760,7 @@ themeManager = getSite().getWorkbenchWindow().getWorkbench().getThemeManager(); themeManager.addPropertyChangeListener(THEME_CHANGE_LISTENER); - filteredTree = new TaskListFilteredTree(parent, SWT.MULTI | SWT.VERTICAL | /* SWT.H_SCROLL | */SWT.V_SCROLL + filteredTree = new TaskListFilteredTree(body, SWT.MULTI | SWT.VERTICAL | /* SWT.H_SCROLL | */SWT.V_SCROLL | SWT.NO_SCROLL | SWT.FULL_SELECTION, new SubstringPatternFilter(), getViewSite().getWorkbenchWindow()); // need to do initialize tooltip early for native tooltip disablement to take effect @@ -923,6 +940,12 @@ TasksUiPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(tasksUiPreferenceListener); + serviceMessageControl = new TaskListServiceMessageControl(body); + ServiceMessageManager manager = TasksUiPlugin.getDefault().getServiceMessageManager(); + serviceMessageControl.handleEvent(new ServiceMessageEvent(manager, EVENT_KIND.MESSAGE_UPDATE, + manager.getServiceMessages())); + TasksUiPlugin.getDefault().getServiceMessageManager().addServiceMessageListener(serviceMessageControl); + // Need to do this because the page, which holds the active working set is not around on creation, see bug 203179 PlatformUI.getWorkbench().getActiveWorkbenchWindow().addPageListener(PAGE_LISTENER); } Index: src/org/eclipse/mylyn/internal/tasks/ui/preferences/Messages.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/Messages.java,v retrieving revision 1.6 diff -u -r1.6 Messages.java --- src/org/eclipse/mylyn/internal/tasks/ui/preferences/Messages.java 3 Apr 2010 06:10:03 -0000 1.6 +++ src/org/eclipse/mylyn/internal/tasks/ui/preferences/Messages.java 24 May 2010 22:06:31 -0000 @@ -63,6 +63,8 @@ public static String TasksUiPreferencePage_See_X_for_configuring_Task_List_colors; + public static String TasksUiPreferencePage_show_service_messages; + public static String TasksUiPreferencePage_Show_tooltip_on_hover_Label; public static String TasksUiPreferencePage_Specify_the_folder_for_tasks; Index: src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java,v retrieving revision 1.41 diff -u -r1.41 TasksUiPreferencePage.java --- src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java 26 Feb 2010 04:07:20 -0000 1.41 +++ src/org/eclipse/mylyn/internal/tasks/ui/preferences/TasksUiPreferencePage.java 24 May 2010 22:06:31 -0000 @@ -109,6 +109,8 @@ private Button taskListTooltipEnabledButton; + private Button taskListServiceMessageEnabledButton; + public TasksUiPreferencePage() { super(); setPreferenceStore(TasksUiPlugin.getDefault().getPreferenceStore()); @@ -208,16 +210,22 @@ getPreferenceStore().setValue(ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED, taskListTooltipEnabledButton.getSelection()); + getPreferenceStore().setValue(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, + taskListServiceMessageEnabledButton.getSelection()); + getPreferenceStore().setValue(ITasksUiPreferenceConstants.WEEK_START_DAY, getWeekStartValue()); //getPreferenceStore().setValue(TasksUiPreferenceConstants.PLANNING_STARTHOUR, hourDayStart.getSelection()); // getPreferenceStore().setValue(TasksUiPreferenceConstants.PLANNING_ENDHOUR, hourDayEnd.getSelection()); - MonitorUiPlugin.getDefault().getPreferenceStore().setValue(ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED, - timeoutEnabledButton.getSelection()); - MonitorUiPlugin.getDefault().getPreferenceStore().setValue(ActivityContextManager.ACTIVITY_TIMEOUT, - timeoutMinutes.getSelection() * (60 * 1000)); - - MonitorUiPlugin.getDefault().getPreferenceStore().setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED, - activityTrackingEnabledButton.getSelection()); + MonitorUiPlugin.getDefault() + .getPreferenceStore() + .setValue(ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED, timeoutEnabledButton.getSelection()); + MonitorUiPlugin.getDefault() + .getPreferenceStore() + .setValue(ActivityContextManager.ACTIVITY_TIMEOUT, timeoutMinutes.getSelection() * (60 * 1000)); + + MonitorUiPlugin.getDefault() + .getPreferenceStore() + .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED, activityTrackingEnabledButton.getSelection()); String taskDirectory = taskDirectoryText.getText(); taskDirectory = taskDirectory.replaceAll(BACKSLASH_MULTI, FORWARDSLASH); @@ -276,6 +284,9 @@ taskListTooltipEnabledButton.setSelection(getPreferenceStore().getBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + weekStartCombo.select(getPreferenceStore().getInt(ITasksUiPreferenceConstants.WEEK_START_DAY) - 1); //hourDayStart.setSelection(getPreferenceStore().getInt(TasksUiPreferenceConstants.PLANNING_STARTHOUR)); // hourDayEnd.setSelection(getPreferenceStore().getInt(TasksUiPreferenceConstants.PLANNING_ENDHOUR)); @@ -283,11 +294,13 @@ int minutes = MonitorUiPlugin.getDefault().getPreferenceStore().getInt(ActivityContextManager.ACTIVITY_TIMEOUT) / MS_MINUTES; timeoutMinutes.setSelection(minutes); - timeoutEnabledButton.setSelection(MonitorUiPlugin.getDefault().getPreferenceStore().getBoolean( - ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED)); - - activityTrackingEnabledButton.setSelection(MonitorUiPlugin.getDefault().getPreferenceStore().getBoolean( - MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED)); + timeoutEnabledButton.setSelection(MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED)); + + activityTrackingEnabledButton.setSelection(MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED)); return true; } @@ -310,6 +323,9 @@ taskListTooltipEnabledButton.setSelection(getPreferenceStore().getDefaultBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getDefaultBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); + // synchQueries.setSelection(getPreferenceStore().getDefaultBoolean( // TaskListPreferenceConstants.REPOSITORY_SYNCH_ON_STARTUP)); enableBackgroundSynch.setSelection(getPreferenceStore().getDefaultBoolean( @@ -322,15 +338,18 @@ weekStartCombo.select(getPreferenceStore().getDefaultInt(ITasksUiPreferenceConstants.WEEK_START_DAY) - 1); // hourDayStart.setSelection(getPreferenceStore().getDefaultInt(TasksUiPreferenceConstants.PLANNING_STARTHOUR)); // hourDayEnd.setSelection(getPreferenceStore().getDefaultInt(TasksUiPreferenceConstants.PLANNING_ENDHOUR)); - int activityTimeoutMinutes = MonitorUiPlugin.getDefault().getPreferenceStore().getDefaultInt( - ActivityContextManager.ACTIVITY_TIMEOUT) + int activityTimeoutMinutes = MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getDefaultInt(ActivityContextManager.ACTIVITY_TIMEOUT) / MS_MINUTES; timeoutMinutes.setSelection(activityTimeoutMinutes); - timeoutEnabledButton.setSelection(MonitorUiPlugin.getDefault().getPreferenceStore().getDefaultBoolean( - ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED)); - - activityTrackingEnabledButton.setSelection(MonitorUiPlugin.getDefault().getPreferenceStore().getDefaultBoolean( - MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED)); + timeoutEnabledButton.setSelection(MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getDefaultBoolean(ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED)); + + activityTrackingEnabledButton.setSelection(MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getDefaultBoolean(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED)); updateRefreshGroupEnablements(); } @@ -480,6 +499,11 @@ taskListTooltipEnabledButton.setText(Messages.TasksUiPreferencePage_Show_tooltip_on_hover_Label); taskListTooltipEnabledButton.setSelection(getPreferenceStore().getBoolean( ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED)); + + taskListServiceMessageEnabledButton = new Button(group, SWT.CHECK); + taskListServiceMessageEnabledButton.setText(Messages.TasksUiPreferencePage_show_service_messages); + taskListServiceMessageEnabledButton.setSelection(getPreferenceStore().getBoolean( + ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)); } private void createTaskActivityGroup(Composite container) { @@ -488,11 +512,13 @@ group.setLayout(new GridLayout(3, false)); group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); - boolean activityTrackingEnabled = MonitorUiPlugin.getDefault().getPreferenceStore().getBoolean( - MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED); - - boolean timeoutEnabled = MonitorUiPlugin.getDefault().getPreferenceStore().getBoolean( - ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED); + boolean activityTrackingEnabled = MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED); + + boolean timeoutEnabled = MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getBoolean(ActivityContextManager.ACTIVITY_TIMEOUT_ENABLED); activityTrackingEnabledButton = new Button(group, SWT.CHECK); activityTrackingEnabledButton.setText(Messages.TasksUiPreferencePage_Enable_Time_Tracking); @@ -525,8 +551,9 @@ timeoutMinutes.setIncrement(5); timeoutMinutes.setMaximum(60); timeoutMinutes.setMinimum(1); - long minutes = MonitorUiPlugin.getDefault().getPreferenceStore().getLong( - ActivityContextManager.ACTIVITY_TIMEOUT) + long minutes = MonitorUiPlugin.getDefault() + .getPreferenceStore() + .getLong(ActivityContextManager.ACTIVITY_TIMEOUT) / MS_MINUTES; timeoutMinutes.setSelection((int) minutes); timeoutMinutes.addSelectionListener(new SelectionAdapter() { Index: src/org/eclipse/mylyn/internal/tasks/ui/preferences/messages.properties =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/preferences/messages.properties,v retrieving revision 1.10 diff -u -r1.10 messages.properties --- src/org/eclipse/mylyn/internal/tasks/ui/preferences/messages.properties 3 Apr 2010 06:10:03 -0000 1.10 +++ src/org/eclipse/mylyn/internal/tasks/ui/preferences/messages.properties 24 May 2010 22:06:31 -0000 @@ -27,6 +27,7 @@ TasksUiPreferencePage_Rich_Editor__Recommended_=Rich Editor (Recommended) TasksUiPreferencePage_Scheduling=Scheduling TasksUiPreferencePage_See_X_for_configuring_Task_List_colors=See ''{0}'' for configuring Task List colors. +TasksUiPreferencePage_show_service_messages=Show service messages TasksUiPreferencePage_Show_tooltip_on_hover_Label=Show task overview popups on hover TasksUiPreferencePage_Specify_the_folder_for_tasks=Specify the folder for tasks TasksUiPreferencePage_Stop_time_accumulation_after=Stop time accumulation after Index: src/org/eclipse/mylyn/internal/tasks/ui/ITasksUiPreferenceConstants.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ITasksUiPreferenceConstants.java,v retrieving revision 1.12 diff -u -r1.12 ITasksUiPreferenceConstants.java --- src/org/eclipse/mylyn/internal/tasks/ui/ITasksUiPreferenceConstants.java 15 Jan 2010 02:02:58 -0000 1.12 +++ src/org/eclipse/mylyn/internal/tasks/ui/ITasksUiPreferenceConstants.java 24 May 2010 22:06:31 -0000 @@ -52,6 +52,8 @@ public static final String NOTIFICATIONS_ENABLED = "org.eclipse.mylyn.tasks.ui.notifications.enabled"; //$NON-NLS-1$ + public static final String SERVICE_MESSAGES_ENABLED = "org.eclipse.mylyn.tasks.ui.messages.enabled"; //$NON-NLS-1$ + public static final String WEEK_START_DAY = "org.eclipse.mylyn.tasks.ui.planning.week.start.day"; //$NON-NLS-1$ public static final String PLANNING_ENDHOUR = "org.eclipse.mylyn.tasks.ui.planning.end.hour"; //$NON-NLS-1$ @@ -87,4 +89,12 @@ public static final String PREF_DATA_DIR = "org.eclipse.mylyn.data.dir"; //$NON-NLS-1$ public static final String DEFAULT_ATTACHMENTS_DIRECTORY = "org.eclipse.mylyn.tasks.ui.attachments.defaultDirectory"; //$NON-NLS-1$ + + public static final String SERVICE_MESSAGE_URL = "org.eclipse.mylyn.tasks.ui.servicemessage.url"; //$NON-NLS-1$; + + public static final String LAST_SERVICE_MESSAGE_ID = "org.eclipse.mylyn.tasks.ui.servicemessage.id"; //$NON-NLS-1$ + + public static final String LAST_SERVICE_MESSAGE_ETAG = "org.eclipse.mylyn.tasks.ui.servicemessage.etag"; //$NON-NLS-1$ + + public static final String LAST_SERVICE_MESSAGE_LAST_MODIFIED = "org.eclipse.mylyn.tasks.ui.servicemessage.lastmodified"; //$NON-NLS-1$ } Index: src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java,v retrieving revision 1.131 diff -u -r1.131 TasksUiPlugin.java --- src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java 5 Feb 2010 01:12:35 -0000 1.131 +++ src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java 24 May 2010 22:06:31 -0000 @@ -77,6 +77,7 @@ import org.eclipse.mylyn.internal.tasks.core.externalization.IExternalizationParticipant; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizationParticipant; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizer; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageManager; import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotificationReminder; import org.eclipse.mylyn.internal.tasks.ui.notifications.TaskListNotifier; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiExtensionReader; @@ -149,6 +150,8 @@ private RepositoryTemplateManager repositoryTemplateManager; + private ServiceMessageManager serviceMessageManager; + private final Set taskEditorPageFactories = new HashSet(); private final TreeSet repositoryLinkProviders = new TreeSet( @@ -343,6 +346,14 @@ || event.getProperty().equals(ITasksUiPreferenceConstants.REPOSITORY_SYNCH_SCHEDULE_MILISECONDS)) { updateSynchronizationScheduler(false); } + + if (event.getProperty().equals(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { + if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { + serviceMessageManager.start(); + } else { + serviceMessageManager.stop(); + } + } } }; @@ -552,7 +563,7 @@ // NOTE: initializing extensions in start(..) has caused race // conditions previously - TasksUiExtensionReader.initStartupExtensions(taskListExternalizer); + TasksUiExtensionReader.initStartupExtensions(taskListExternalizer, repositoryManager); // instantiate taskDataManager TaskDataStore taskDataStore = new TaskDataStore(repositoryManager); @@ -605,6 +616,17 @@ // make this available early for clients that are not initialized through tasks ui but need access taskListNotificationManager = new TaskListNotificationManager(); + String lastMod = getPreferenceStore().getString( + ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_LAST_MODIFIED); + String etag = getPreferenceStore().getString(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_ETAG); + + serviceMessageManager = new ServiceMessageManager(getPreferenceStore().getString( + ITasksUiPreferenceConstants.SERVICE_MESSAGE_URL), lastMod, etag); + + if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { + serviceMessageManager.start(); + } + // trigger lazy initialization new TasksUiInitializationJob().schedule(); } catch (Exception e) { @@ -727,6 +749,7 @@ // ContextCorePlugin.getDefault().getPluginPreferences().removePropertyChangeListener( // PREFERENCE_LISTENER); // } + serviceMessageManager.stop(); taskEditorBloatManager.dispose(PlatformUI.getWorkbench()); INSTANCE = null; } @@ -868,6 +891,7 @@ store.setDefault(ITasksUiPreferenceConstants.PREF_DATA_DIR, getDefaultDataDirectory()); store.setDefault(ITasksUiPreferenceConstants.GROUP_SUBTASKS, true); store.setDefault(ITasksUiPreferenceConstants.NOTIFICATIONS_ENABLED, true); + store.setDefault(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED, true); store.setDefault(ITasksUiPreferenceConstants.FILTER_PRIORITY, PriorityLevel.P5.toString()); store.setDefault(ITasksUiPreferenceConstants.EDITOR_TASKS_RICH, true); store.setDefault(ITasksUiPreferenceConstants.EDITOR_CURRENT_LINE_HIGHLIGHT, false); @@ -894,6 +918,8 @@ store.setDefault(ITasksUiPreferenceConstants.AUTO_EXPAND_TASK_LIST, true); store.setDefault(ITasksUiPreferenceConstants.TASK_LIST_TOOL_TIPS_ENABLED, true); + + store.setDefault(ITasksUiPreferenceConstants.SERVICE_MESSAGE_URL, "http://eclipse.org/mylyn/message.xml"); //$NON-NLS-1$ } public static TaskActivityManager getTaskActivityManager() { @@ -1306,4 +1332,8 @@ } } + public ServiceMessageManager getServiceMessageManager() { + return serviceMessageManager; + } + } Index: schema/repositories.exsd =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/schema/repositories.exsd,v retrieving revision 1.24 diff -u -r1.24 repositories.exsd --- schema/repositories.exsd 9 Nov 2009 13:58:07 -0000 1.24 +++ schema/repositories.exsd 24 May 2010 22:06:31 -0000 @@ -24,6 +24,7 @@ + @@ -169,6 +170,26 @@ + + + + (no description available) + + + + + + + + + + + + + + + + Index: src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiExtensionReader.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiExtensionReader.java,v retrieving revision 1.75 diff -u -r1.75 TasksUiExtensionReader.java --- src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiExtensionReader.java 24 Feb 2010 01:34:02 -0000 1.75 +++ src/org/eclipse/mylyn/internal/tasks/ui/util/TasksUiExtensionReader.java 24 May 2010 22:06:31 -0000 @@ -30,6 +30,7 @@ import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; import org.eclipse.mylyn.internal.tasks.core.externalization.TaskListExternalizer; import org.eclipse.mylyn.internal.tasks.ui.IDynamicSubMenuContributor; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; @@ -37,6 +38,7 @@ import org.eclipse.mylyn.internal.tasks.ui.views.TaskListView; import org.eclipse.mylyn.tasks.core.AbstractDuplicateDetector; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryMigrator; import org.eclipse.mylyn.tasks.core.AbstractTaskListMigrator; import org.eclipse.mylyn.tasks.core.RepositoryTemplate; import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; @@ -57,11 +59,15 @@ IConfigurationElement element; - IConfigurationElement migratorElement; + IConfigurationElement taskListMigratorElement; + + IConfigurationElement repositoryMigratorElement; AbstractRepositoryConnector repositoryConnector; - AbstractTaskListMigrator migrator; + AbstractTaskListMigrator taskListMigrator; + + AbstractRepositoryMigrator repositoryMigrator; private final String id; @@ -94,18 +100,16 @@ } } - public IStatus createMigrator() { - Assert.isTrue(migrator == null); + public IStatus createTaskListMigrator() { + Assert.isTrue(taskListMigrator == null); try { - Object migratorObject = migratorElement.createExecutableExtension(ATTR_CLASS); + Object migratorObject = taskListMigratorElement.createExecutableExtension(ATTR_CLASS); if (migratorObject instanceof AbstractTaskListMigrator) { - migrator = (AbstractTaskListMigrator) migratorObject; + taskListMigrator = (AbstractTaskListMigrator) migratorObject; return Status.OK_STATUS; } else { - return new Status( - IStatus.ERROR, - TasksUiPlugin.ID_PLUGIN, - "Could not load task list migrator migrator: " + migratorObject.getClass().getCanonicalName() //$NON-NLS-1$ + return new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, + "Could not load task list migrator: " + migratorObject.getClass().getCanonicalName() //$NON-NLS-1$ + " must implement " + AbstractTaskListMigrator.class.getCanonicalName()); //$NON-NLS-1$ } } catch (Throwable e) { @@ -114,6 +118,24 @@ } } + public IStatus createRepositoryMigrator() { + Assert.isTrue(repositoryMigrator == null); + try { + Object migratorObject = repositoryMigratorElement.createExecutableExtension(ATTR_CLASS); + if (migratorObject instanceof AbstractRepositoryMigrator) { + repositoryMigrator = (AbstractRepositoryMigrator) migratorObject; + return Status.OK_STATUS; + } else { + return new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, + "Could not load repository migrator: " + migratorObject.getClass().getCanonicalName() //$NON-NLS-1$ + + " must implement " + AbstractRepositoryMigrator.class.getCanonicalName()); //$NON-NLS-1$ + } + } catch (Throwable e) { + return new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, + "Could not load repository migrator extension", e); //$NON-NLS-1$ + } + } + public String getPluginId() { return element.getContributor().getName(); } @@ -158,6 +180,8 @@ public static final String ELMNT_MIGRATOR = "taskListMigrator"; //$NON-NLS-1$ + public static final String ELMNT_REPOSITORY_MIGRATOR = "repositoryMigrator"; //$NON-NLS-1$ + public static final String ATTR_BRANDING_ICON = "brandingIcon"; //$NON-NLS-1$ public static final String ATTR_OVERLAY_ICON = "overlayIcon"; //$NON-NLS-1$ @@ -207,12 +231,13 @@ */ private static Set disabledContributors = new HashSet(); - public static void initStartupExtensions(TaskListExternalizer taskListExternalizer) { + public static void initStartupExtensions(TaskListExternalizer taskListExternalizer, + TaskRepositoryManager repositoryManager) { if (!coreExtensionsRead) { IExtensionRegistry registry = Platform.getExtensionRegistry(); // NOTE: has to be read first, consider improving - initConnectorCores(taskListExternalizer, registry); + initConnectorCores(taskListExternalizer, repositoryManager, registry); IExtensionPoint templatesExtensionPoint = registry.getExtensionPoint(EXTENSION_TEMPLATES); IExtension[] templateExtensions = templatesExtensionPoint.getExtensions(); @@ -256,7 +281,8 @@ } } - private static void initConnectorCores(TaskListExternalizer taskListExternalizer, IExtensionRegistry registry) { + private static void initConnectorCores(TaskListExternalizer taskListExternalizer, + TaskRepositoryManager repositoryManager, IExtensionRegistry registry) { List descriptors = new ArrayList(); MultiStatus result = new MultiStatus(TasksUiPlugin.ID_PLUGIN, 0, "Repository connectors failed to load.", null); //$NON-NLS-1$ @@ -267,16 +293,20 @@ for (IExtension repositoryExtension : repositoryExtensions) { IConfigurationElement[] elements = repositoryExtension.getConfigurationElements(); ConnectorDescriptor descriptor = null; - IConfigurationElement migratorElement = null; + IConfigurationElement tasklistMigratorElement = null; + IConfigurationElement repositoryMigratorElement = null; for (IConfigurationElement element : elements) { if (element.getName().equals(ELMNT_REPOSITORY_CONNECTOR)) { descriptor = new ConnectorDescriptor(element); } else if (element.getName().equals(ELMNT_MIGRATOR)) { - migratorElement = element; + tasklistMigratorElement = element; + } else if (element.getName().equals(ELMNT_REPOSITORY_MIGRATOR)) { + repositoryMigratorElement = element; } } if (descriptor != null) { - descriptor.migratorElement = migratorElement; + descriptor.taskListMigratorElement = tasklistMigratorElement; + descriptor.repositoryMigratorElement = repositoryMigratorElement; descriptors.add(descriptor); if (descriptor.getId() != null) { add(descriptorById, descriptor.getId(), descriptor); @@ -300,14 +330,23 @@ checkForConflicts(descriptors, result, descriptorByConnectorKind); // register connectors - List migrators = new ArrayList(); + List taskListmigrators = new ArrayList(); + List repositoryMigrators = new ArrayList(); for (ConnectorDescriptor descriptor : descriptors) { if (descriptor.repositoryConnector != null) { - TasksUiPlugin.getRepositoryManager().addRepositoryConnector(descriptor.repositoryConnector); - if (descriptor.migratorElement != null) { - IStatus status = descriptor.createMigrator(); - if (status.isOK() && descriptor.migrator != null) { - migrators.add(descriptor.migrator); + repositoryManager.addRepositoryConnector(descriptor.repositoryConnector); + if (descriptor.taskListMigratorElement != null) { + IStatus status = descriptor.createTaskListMigrator(); + if (status.isOK() && descriptor.taskListMigrator != null) { + taskListmigrators.add(descriptor.taskListMigrator); + } else { + result.add(status); + } + } + if (descriptor.repositoryMigratorElement != null) { + IStatus status = descriptor.createRepositoryMigrator(); + if (status.isOK() && descriptor.repositoryMigrator != null) { + repositoryMigrators.add(descriptor.repositoryMigrator); } else { result.add(status); } @@ -319,7 +358,8 @@ StatusHandler.log(result); } - taskListExternalizer.initialize(migrators); + repositoryManager.initialize(repositoryMigrators); + taskListExternalizer.initialize(taskListmigrators); } private static boolean isDisabled(IConfigurationElement element) { Index: plugin.xml =================================================================== RCS file: /cvsroot/tools/org.eclipse.mylyn/org.eclipse.mylyn.tasks.ui/plugin.xml,v retrieving revision 1.377 diff -u -r1.377 plugin.xml --- plugin.xml 3 Apr 2010 01:33:20 -0000 1.377 +++ plugin.xml 24 May 2010 22:06:31 -0000 @@ -1115,6 +1115,9 @@ class="org.eclipse.mylyn.internal.tasks.ui.LocalRepositoryConnectorUi" name="%LocalRepositoryConnectorUi.name" overlayIcon="icons/ovr16/overlay-local.gif"/> + + Index: src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/notifications/TaskListServiceMessageControl.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,270 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.notifications; + +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.mylyn.internal.provisional.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.provisional.commons.ui.CommonThemes; +import org.eclipse.mylyn.internal.provisional.commons.ui.GradientCanvas; +import org.eclipse.mylyn.internal.tasks.core.notifications.IServiceMessageListener; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessage; +import org.eclipse.mylyn.internal.tasks.core.notifications.ServiceMessageEvent; +import org.eclipse.mylyn.internal.tasks.ui.ITasksUiPreferenceConstants; +import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; +import org.eclipse.mylyn.tasks.ui.TasksUiUtil; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Font; +import org.eclipse.swt.graphics.FontData; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Label; +import org.eclipse.ui.PlatformUI; +import org.eclipse.ui.forms.FormColors; +import org.eclipse.ui.forms.IFormColors; +import org.eclipse.ui.forms.events.HyperlinkAdapter; +import org.eclipse.ui.forms.events.HyperlinkEvent; +import org.eclipse.ui.forms.events.IHyperlinkListener; +import org.eclipse.ui.forms.widgets.Hyperlink; +import org.eclipse.ui.forms.widgets.ImageHyperlink; +import org.eclipse.ui.forms.widgets.TableWrapData; +import org.eclipse.ui.forms.widgets.TableWrapLayout; +import org.osgi.framework.Version; + +/** + * @author Robert Elves + * @author Steffen Pingel + */ +public class TaskListServiceMessageControl implements IServiceMessageListener { + + private ImageHyperlink imageHyperlink; + + private Hyperlink titleHyperlink; + + private Label descriptionLabel; + + private GridData headData; + + private final Composite parent; + + private GradientCanvas head; + + private ImageHyperlink closeLink; + + private ServiceMessage currentMessage; + + private String messageUrl; + + public TaskListServiceMessageControl(Composite parent) { + this.parent = parent; + } + + private void setTitleImage(Image image) { + imageHyperlink.setImage(image); + } + + private void setTitle(String title) { + titleHyperlink.setText(title); + } + + private void setDescription(String description) { + descriptionLabel.setText(description); + } + + private void addHyperlinkListener(IHyperlinkListener listener) { + titleHyperlink.addHyperlinkListener(listener); + imageHyperlink.addHyperlinkListener(listener); + } + + protected void setMessageUrl(String url) { + messageUrl = url; + } + + public Control createControl(Composite parent) { + FormColors colors = TasksUiPlugin.getDefault().getFormColors(parent.getDisplay()); + head = new GradientCanvas(parent, SWT.NONE); + GridLayout headLayout = new GridLayout(); + headLayout.marginHeight = 0; + headLayout.marginWidth = 0; + headLayout.horizontalSpacing = 0; + headLayout.verticalSpacing = 0; + headLayout.numColumns = 1; + head.setLayout(headLayout); + headData = new GridData(SWT.FILL, SWT.TOP, true, false); + head.setLayoutData(headData); + + Color top = colors.getColor(IFormColors.H_GRADIENT_END); + Color bot = colors.getColor(IFormColors.H_GRADIENT_START); + head.setBackgroundGradient(new Color[] { bot, top }, new int[] { 100 }, true); + head.setSeparatorVisible(true); + head.setSeparatorAlignment(SWT.TOP); + + head.putColor(IFormColors.H_BOTTOM_KEYLINE1, colors.getColor(IFormColors.H_BOTTOM_KEYLINE1)); + head.putColor(IFormColors.H_BOTTOM_KEYLINE2, colors.getColor(IFormColors.H_BOTTOM_KEYLINE2)); + head.putColor(IFormColors.H_HOVER_LIGHT, colors.getColor(IFormColors.H_HOVER_LIGHT)); + head.putColor(IFormColors.H_HOVER_FULL, colors.getColor(IFormColors.H_HOVER_FULL)); + head.putColor(IFormColors.TB_TOGGLE, colors.getColor(IFormColors.TB_TOGGLE)); + head.putColor(IFormColors.TB_TOGGLE_HOVER, colors.getColor(IFormColors.TB_TOGGLE_HOVER)); + + TableWrapLayout layout = new TableWrapLayout(); + layout.numColumns = 3; + head.setLayout(layout); + + imageHyperlink = new ImageHyperlink(head, SWT.NONE); + + titleHyperlink = new Hyperlink(head, SWT.NONE); + + setHeaderFontSizeAndStyle(titleHyperlink); + + addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(HyperlinkEvent e) { + if (messageUrl != null) { + TasksUiUtil.openUrl(messageUrl); + } + + } + }); + + closeLink = new ImageHyperlink(head, SWT.NONE); + closeLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CLOSE)); + TableWrapData data = new TableWrapData(); + data.align = TableWrapData.RIGHT; + closeLink.setLayoutData(data); + closeLink.addHyperlinkListener(new HyperlinkAdapter() { + @Override + public void linkActivated(HyperlinkEvent e) { + closeMessage(); + } + + @Override + public void linkEntered(HyperlinkEvent e) { + closeLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CLOSE_HOVER)); + } + + @Override + public void linkExited(HyperlinkEvent e) { + closeLink.setImage(CommonImages.getImage(CommonImages.NOTIFICATION_CLOSE)); + } + }); + + // spacer + new Label(head, SWT.NONE).setText(" "); //$NON-NLS-1$ + + descriptionLabel = new Label(head, SWT.WRAP); + data = new TableWrapData(); + data.colspan = 2; + descriptionLabel.setLayoutData(data); + return head; + } + + private void closeMessage() { + if (currentMessage != null) { + TasksUiPlugin.getDefault().getPreferenceStore().setValue( + ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_ID, currentMessage.getId()); + } + head.dispose(); + parent.layout(true); + } + + // From EditorUtil + private static Font setHeaderFontSizeAndStyle(Control text) { + float sizeFactor = 1.2f; + Font initialFont = text.getFont(); + FontData[] fontData = initialFont.getFontData(); + for (FontData element : fontData) { + element.setHeight((int) (element.getHeight() * sizeFactor)); + element.setStyle(element.getStyle() | SWT.BOLD); + } + final Font textFont = new Font(text.getDisplay(), fontData); + text.setFont(textFont); + text.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + textFont.dispose(); + } + }); + Color color = PlatformUI.getWorkbench().getThemeManager().getCurrentTheme().getColorRegistry().get( + CommonThemes.COLOR_COMPLETED); + text.setForeground(color); + return textFont; + } + + public void handleEvent(final ServiceMessageEvent event) { + switch (event.getEventKind()) { + case MESSAGE_UPDATE: + IPreferenceStore preferenceStore = TasksUiPlugin.getDefault().getPreferenceStore(); + String lastMessageId = preferenceStore.getString(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_ID); + for (final ServiceMessage message : event.getMessages()) { + if (!message.isValid() || message.getId().equals("-1")) { //$NON-NLS-1$ + continue; + } + + if (!lastMessageId.equals(message.getId()) && isForCurrentVersion(message)) { + Display.getDefault().asyncExec(new Runnable() { + public void run() { + setMessage(message); + } + }); + } + } + break; + case STOP: + head.dispose(); + parent.layout(true); + break; + } + } + + private boolean isForCurrentVersion(ServiceMessage message) { + if (message.getVersion() == null) { + return true; + } + + try { + VersionRange version = new VersionRange(message.getVersion()); + String versionString = (String) TasksUiPlugin.getDefault().getBundle().getHeaders().get("Bundle-Version"); //$NON-NLS-1$ + return version.isIncluded(new Version(versionString)); + } catch (IllegalArgumentException e) { + // invalid version range + return false; + } + } + + protected void setMessage(ServiceMessage message) { + if (message != null) { + createControl(parent); + IPreferenceStore preferenceStore = TasksUiPlugin.getDefault().getPreferenceStore(); + preferenceStore.setValue(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_ETAG, message.getETag()); + preferenceStore.setValue(ITasksUiPreferenceConstants.LAST_SERVICE_MESSAGE_LAST_MODIFIED, + message.getLastModified()); + + this.currentMessage = message; + + setTitle(message.getTitle()); + setDescription(message.getDescription()); + setTitleImage(Dialog.getImage(message.getImage())); + if (message.getUrl() != null) { + setMessageUrl(message.getUrl()); + } + parent.layout(true); + } + } + +} Index: src/org/eclipse/mylyn/internal/tasks/ui/views/TeamRepositoriesContentProvider.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/views/TeamRepositoriesContentProvider.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/views/TeamRepositoriesContentProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/views/TeamRepositoriesContentProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui.views; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; +import org.eclipse.mylyn.internal.tasks.core.Category; +import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.TasksUi; + +/** + * @author Robert Elves + */ +public class TeamRepositoriesContentProvider implements ITreeContentProvider { + + private final TaskRepositoryManager manager; + + public TeamRepositoriesContentProvider() { + manager = ((TaskRepositoryManager) TasksUi.getRepositoryManager()); + } + + public void inputChanged(Viewer v, Object oldInput, Object newInput) { + } + + public void dispose() { + } + + public Object[] getElements(Object parent) { + + Set objects = new HashSet(); + //objects.addAll(TasksUi.getRepositoryManager().getAllRepositories()); + + objects.add(manager.getCategory(IRepositoryConstants.CATEGORY_TASKS)); + objects.add(manager.getCategory(IRepositoryConstants.CATEGORY_BUGS)); + objects.add(manager.getCategory(IRepositoryConstants.CATEGORY_OTHER)); + + return objects.toArray(); + } + + public Object[] getChildren(Object parentElement) { + if (parentElement instanceof Category) { + Set objects = new HashSet(); + for (TaskRepository repository : TasksUi.getRepositoryManager().getAllRepositories()) { + Category cat = manager.getCategory(repository); + if (cat.equals(parentElement)) { + objects.add(repository); + } +// String categoryId = repository.getProperty(IRepositoryConstants.PROPERTY_CATEGORY); +// if (categoryId != null && ((Category) parentElement).getId().equals(categoryId)) { +// objects.add(repository); +// } + } + return objects.toArray(); + } + return new Object[0]; + } + + public Object getParent(Object element) { + return null; + } + + public boolean hasChildren(Object element) { + return element instanceof Category; + } +} \ No newline at end of file Index: src/org/eclipse/mylyn/internal/tasks/ui/LocalRepositoryMigrator.java =================================================================== RCS file: src/org/eclipse/mylyn/internal/tasks/ui/LocalRepositoryMigrator.java diff -N src/org/eclipse/mylyn/internal/tasks/ui/LocalRepositoryMigrator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/mylyn/internal/tasks/ui/LocalRepositoryMigrator.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2010 Tasktop Technologies 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: + * Tasktop Technologies - initial API and implementation + *******************************************************************************/ + +package org.eclipse.mylyn.internal.tasks.ui; + +import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; +import org.eclipse.mylyn.internal.tasks.core.LocalRepositoryConnector; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryMigrator; +import org.eclipse.mylyn.tasks.core.TaskRepository; + +/** + * @author Robert Elves + * @since 3.4 + */ +public class LocalRepositoryMigrator extends AbstractRepositoryMigrator { + + @Override + public String getConnectorKind() { + return LocalRepositoryConnector.CONNECTOR_KIND; + } + + @Override + public boolean migrateRepository(TaskRepository repository) { + if (repository.getProperty(IRepositoryConstants.PROPERTY_CATEGORY) == null) { + repository.setProperty(IRepositoryConstants.PROPERTY_CATEGORY, IRepositoryConstants.CATEGORY_TASKS); + return true; + } + return false; + } + +}