diff options
29 files changed, 1154 insertions, 143 deletions
diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/ITasksCoreConstants.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/ITasksCoreConstants.java index 284a3c351..e38d2d24e 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/ITasksCoreConstants.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/internal/tasks/core/ITasksCoreConstants.java @@ -71,6 +71,8 @@ public interface ITasksCoreConstants { @Deprecated public static final String PROPERTY_USE_SECURE_STORAGE = "org.eclipse.mylyn.tasklist.repositories.configuration.securestorage"; //$NON-NLS-1$ + public static final String PROPERTY_BRAND_ID = "org.eclipse.mylyn.brand.id"; //$NON-NLS-1$ + /** * Jobs that have the same instances of this rule set are mutually exclusive. */ diff --git a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/spi/RepositoryConnectorBranding.java b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/spi/RepositoryConnectorBranding.java index 64f659a8a..f18f44158 100644 --- a/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/spi/RepositoryConnectorBranding.java +++ b/org.eclipse.mylyn.tasks.core/src/org/eclipse/mylyn/tasks/core/spi/RepositoryConnectorBranding.java @@ -13,15 +13,18 @@ package org.eclipse.mylyn.tasks.core.spi; import java.io.IOException; import java.io.InputStream; +import java.util.List; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import com.google.common.collect.ImmutableList; + /** - * Specifies branding for a connector that is registered as runtime using {@link RepositoryConnectorContributor}. The - * branding extension is obtained by adapting an {@link AbstractRepositoryConnector} instance to - * {@link RepositoryConnectorBranding}. + * Specifies branding for a connector. The branding extension is obtained by adapting an + * {@link AbstractRepositoryConnector} instance to {@link RepositoryConnectorBranding}. * <p> * To contribute branding clients need to register an {@link IAdapterFactory} for the type * {@link AbstractRepositoryConnector}. @@ -81,8 +84,12 @@ import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; public abstract class RepositoryConnectorBranding { /** - * Returns an input stream with the image data for a 16x16 branding icon. This is typically shown in the UI when - * selecting connectors. Supported file formats are GIF and PNG. + * Returns an input stream with the image data for a 16x16 branding icon, for a connector that is registered at + * runtime using {@link RepositoryConnectorContributor}. This is typically shown in the UI when selecting + * connectors. Supported file formats are GIF and PNG. + * <p> + * Note: for connectors contributed through the <code>org.eclipse.mylyn.tasks.ui.repositories</code> extension + * point, the branding image specified in the extension takes precedence; this method is never called. * * @return input stream for image data * @throws IOException @@ -92,9 +99,12 @@ public abstract class RepositoryConnectorBranding { public abstract InputStream getBrandingImageData() throws IOException; /** - * Returns an input stream with the image data for a 7x8 overlay branding icon. This is typically a very small - * version of the branding icon that is used for overlays over repository icons. Supported file formats are GIF and - * PNG. + * Returns an input stream with the image data for a 7x8 overlay branding icon, for a connector that is registered + * at runtime using {@link RepositoryConnectorContributor}. This is typically a very small version of the branding + * icon that is used for overlays over repository icons. Supported file formats are GIF and PNG. + * <p> + * Note: for connectors contributed through the <code>org.eclipse.mylyn.tasks.ui.repositories</code> extension + * point, the overlay image specified in the extension takes precedence; this method is never called. * * @return input stream for image data * @throws IOException @@ -103,4 +113,69 @@ public abstract class RepositoryConnectorBranding { @NonNull public abstract InputStream getOverlayImageData() throws IOException; + /** + * Returns a list of identifiers of the brands supported by this connector. This is useful for connectors that can + * connect to different brands of the same system. Typically, different brands are functionally identical but use + * different labels and icons. + * <p> + * Each brand may be presented in the UI as though it were a separate connector. + * + * @since 3.16 + */ + @NonNull + public List<String> getBrands() { + return ImmutableList.of(); + } + + /** + * Returns branding image data for a specific brand of the target system. Returns <code>null</code> if the given + * brand is unknown to the connector or uses the {@link #getBrandingImageData() default branding image}. The default + * implementation always returns <code>null</code>. + * + * @return input stream for image data, or <code>null</code> + * @throws IOException + * thrown if opening of the stream fails + * @see #getBrandingImageData() + * @see #getBrands() + * @since 3.16 + */ + @Nullable + public InputStream getBrandingImageData(@NonNull String brand) throws IOException { + return null; + } + + /** + * Returns overlay image data for a specific brand of the target system. Returns <code>null</code> if the given + * brand is unknown to the connector or uses the {@link #getOverlayImageData() default overlay image}. The default + * implementation always returns <code>null</code>. + * + * @param brand + * @throws IOException + * thrown if opening of the stream fails + * @return + * @see #getOverlayImageData() + * @see #getBrands() + * @since 3.16 + */ + @Nullable + public InputStream getOverlayImageData(@NonNull String brand) throws IOException { + return null; + } + + /** + * Returns the connector label to use for a specific brand of the target system. Returns <code>null</code> if the + * given brand is unknown to the connector or uses the {@link AbstractRepositoryConnector#getLabel() default + * connector label}. The default implementation always returns <code>null</code>. + * + * @param brand + * @return + * @see AbstractRepositoryConnector#getLabel() + * @see #getBrands() + * @since 3.16 + */ + @Nullable + public String getConnectorLabel(@NonNull String brand) { + return null; + } + } diff --git a/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF b/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF index 2c194a032..237045a3f 100644 --- a/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF +++ b/org.eclipse.mylyn.tasks.tests/META-INF/MANIFEST.MF @@ -31,7 +31,8 @@ Require-Bundle: org.junit;bundle-version="4.8.2", org.eclipse.mylyn.tasks.ui, org.eclipse.mylyn.tests.util, org.eclipse.mylyn.commons.repositories.core, - org.eclipse.core.runtime.compatibility.auth;resolution:=optional + org.eclipse.core.runtime.compatibility.auth;resolution:=optional, + com.google.guava;bundle-version="15.0.0" Export-Package: org.eclipse.mylyn.tasks.tests;x-internal:=true, org.eclipse.mylyn.tasks.tests.bugs;x-internal:=true, org.eclipse.mylyn.tasks.tests.connector;x-friends:="org.eclipse.mylyn.tasks.ui.tests", diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/RepositoryConnectorContributorTest.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/RepositoryConnectorContributorTest.java index 4c6e19b89..609147457 100644 --- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/RepositoryConnectorContributorTest.java +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/core/RepositoryConnectorContributorTest.java @@ -11,20 +11,80 @@ package org.eclipse.mylyn.tasks.tests.core; +import java.util.HashMap; +import java.util.Map; + import junit.framework.TestCase; import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; +import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; +import org.eclipse.mylyn.internal.tasks.core.TaskTask; +import org.eclipse.mylyn.internal.tasks.ui.IBrandManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.tests.support.MockRepositoryConnectorAdapter.DynamicMockRepositoryConnectorUi; import org.eclipse.mylyn.tasks.tests.support.MockRepositoryConnectorDescriptor.DynamicMockRepositoryConnector; import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; import org.eclipse.mylyn.tasks.ui.TasksUi; import org.eclipse.swt.graphics.Image; +import org.junit.After; +import org.junit.Before; import org.junit.Test; +import com.google.common.collect.ImmutableSet; + public class RepositoryConnectorContributorTest extends TestCase { + private final IBrandManager manager = TasksUiPlugin.getDefault().getBrandManager(); + + private final DynamicMockRepositoryConnector connector = new DynamicMockRepositoryConnector(); + + private final Map<String, TaskRepository> repositories = new HashMap<>(); + + private final Map<String, ITask> tasks = new HashMap<>(); + + private TaskRepository repositoryForConnectorWithNoBrands; + + private TaskTask taskForConnectorWithNoBrands; + + @Before + @Override + protected void setUp() throws Exception { + setUpBrand("org.mylyn"); + setUpBrand("org.eclipse"); + setUpBrand("unknown"); + setUpBrand("exceptional"); + setUpBrand(null); + + String repositoryUrl = "http://mock-connector-with-no-brands"; + repositoryForConnectorWithNoBrands = new TaskRepository("mock-connector-with-no-brands", repositoryUrl); + repositoryForConnectorWithNoBrands.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, "org.mylyn"); + TasksUi.getRepositoryManager().addRepository(repositoryForConnectorWithNoBrands); + taskForConnectorWithNoBrands = new TaskTask("mock-connector-with-no-brands", repositoryUrl, "1"); + } + + private void setUpBrand(String brand) { + String repositoryUrl = "http://mock-" + brand; + TaskRepository repository = new TaskRepository(connector.getConnectorKind(), repositoryUrl); + repository.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, brand); + TasksUi.getRepositoryManager().addRepository(repository); + repositories.put(brand, repository); + tasks.put(brand, new TaskTask(connector.getConnectorKind(), repositoryUrl, "1")); + } + + @Override + @After + protected void tearDown() throws Exception { + for (TaskRepository repository : repositories.values()) { + ((TaskRepositoryManager) TasksUi.getRepositoryManager()).removeRepository(repository); + } + ((TaskRepositoryManager) TasksUi.getRepositoryManager()).removeRepository(repositoryForConnectorWithNoBrands); + } + @Test public void testConnectorContributed() { AbstractRepositoryConnector connector = TasksUi.getRepositoryConnector(DynamicMockRepositoryConnector.CONNECTOR_KIND); @@ -42,17 +102,85 @@ public class RepositoryConnectorContributorTest extends TestCase { } @Test - public void testMockBrandingIcon() { - Image brandingImage = TasksUiPlugin.getDefault().getBrandingIcon(DynamicMockRepositoryConnector.CONNECTOR_KIND); + public void testDefaultBrandingIcon() { + Image brandingImage = TasksUiPlugin.getDefault() + .getBrandManager() + .getDefaultBrandingIcon(DynamicMockRepositoryConnector.CONNECTOR_KIND); assertNotNull("Expected branding image contributed by MockRepositoryConnectorAdapter", brandingImage); + assertEquals(16, brandingImage.getImageData().height); } @Test - public void testMockOverlayIcon() { - ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon( - DynamicMockRepositoryConnector.CONNECTOR_KIND); + public void testDefaultOverlayIcon() { + ImageDescriptor overlay = TasksUiPlugin.getDefault() + .getBrandManager() + .getDefaultOverlayIcon(DynamicMockRepositoryConnector.CONNECTOR_KIND); assertNotNull("Expected overlay image contributed by MockRepositoryConnectorAdapter", overlay); assertEquals(8, overlay.getImageData().height); } + @Test + public void testGetBrands() throws Exception { + assertEquals(ImmutableSet.of("org.mylyn", "org.eclipse"), manager.getBrands(connector.getConnectorKind())); + } + + @Test + public void testGetConnectorLabel() { + assertEquals("Label for org.mylyn", manager.getConnectorLabel(connector, "org.mylyn")); + assertEquals("Label for org.eclipse", manager.getConnectorLabel(connector, "org.eclipse")); + assertEquals(connector.getLabel(), manager.getConnectorLabel(connector, "unknown")); + assertEquals(connector.getLabel(), manager.getConnectorLabel(connector, "exceptional")); + assertEquals(connector.getLabel(), manager.getConnectorLabel(connector, null)); + AbstractRepositoryConnector mockConnector = new DynamicMockRepositoryConnector() { + @Override + public String getConnectorKind() { + return "mock-connector-with-no-brands"; + }; + }; + assertEquals(connector.getLabel(), manager.getConnectorLabel(mockConnector, "org.mylyn")); + } + + @Test + public void testGetBrandingIcon() { + assertBrandingIconHeight(3, "org.mylyn"); + assertBrandingIconHeight(2, "org.eclipse"); + assertBrandingIconHeight(16, "unknown"); + assertBrandingIconHeight(16, "exceptional"); + assertBrandingIconHeight(16, null); + + assertNull(manager.getBrandingIcon(repositoryForConnectorWithNoBrands.getConnectorKind(), "org.mylyn")); + assertNull(manager.getBrandingIcon(repositoryForConnectorWithNoBrands)); + } + + private void assertBrandingIconHeight(int expectedHeight, String brand) { + assertIconHeight(expectedHeight, manager.getBrandingIcon(connector.getConnectorKind(), brand)); + assertIconHeight(expectedHeight, manager.getBrandingIcon(repositories.get(brand))); + } + + @Test + public void testGetOverlayIcon() { + assertOverlayIconHeight(5, "org.mylyn"); + assertOverlayIconHeight(4, "org.eclipse"); + assertOverlayIconHeight(8, "unknown"); + assertOverlayIconHeight(8, "exceptional"); + assertOverlayIconHeight(8, null); + + assertNull(manager.getOverlayIcon(repositoryForConnectorWithNoBrands.getConnectorKind(), "org.mylyn")); + assertNull(manager.getOverlayIcon(repositoryForConnectorWithNoBrands)); + assertNull(manager.getOverlayIcon(taskForConnectorWithNoBrands)); + } + + private void assertOverlayIconHeight(int expectedHeight, String brand) { + assertIconHeight(expectedHeight, manager.getOverlayIcon(connector.getConnectorKind(), brand)); + assertIconHeight(expectedHeight, manager.getOverlayIcon(repositories.get(brand))); + assertIconHeight(expectedHeight, manager.getOverlayIcon(tasks.get(brand))); + } + + private void assertIconHeight(int expectedHeight, Image image) { + assertEquals(expectedHeight, image.getImageData().height); + } + + private void assertIconHeight(int expectedHeight, ImageDescriptor descriptor) { + assertEquals(expectedHeight, CommonImages.getImage(descriptor).getImageData().height); + } } diff --git a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/support/MockRepositoryConnectorAdapter.java b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/support/MockRepositoryConnectorAdapter.java index e4a26c25a..994438985 100644 --- a/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/support/MockRepositoryConnectorAdapter.java +++ b/org.eclipse.mylyn.tasks.tests/src/org/eclipse/mylyn/tasks/tests/support/MockRepositoryConnectorAdapter.java @@ -13,6 +13,8 @@ package org.eclipse.mylyn.tasks.tests.support; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.mylyn.commons.sdk.util.CommonTestUtil; @@ -22,6 +24,8 @@ import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnectorUi; import org.eclipse.mylyn.tasks.ui.AbstractRepositoryConnectorUi; +import com.google.common.collect.ImmutableList; + public class MockRepositoryConnectorAdapter implements IAdapterFactory { public final static class DynamicMockRepositoryConnectorUi extends MockRepositoryConnectorUi { @@ -58,6 +62,48 @@ public class MockRepositoryConnectorAdapter implements IAdapterFactory { public InputStream getBrandingImageData() throws IOException { return CommonTestUtil.getResource(this, "testdata/icons/mock-repository.gif"); } + + @Override + public List<String> getBrands() { + ArrayList<String> brands = new ArrayList<String>(ImmutableList.of("org.mylyn", "org.eclipse", + "exceptional")); + brands.add(1, null); + return brands; + } + + @Override + public String getConnectorLabel(String brand) { + if ("exceptional".equals(brand)) { + throw new NullPointerException(); + } else if (getBrands().contains(brand)) { + return "Label for " + brand; + } + return super.getConnectorLabel(brand); + } + + @Override + public InputStream getOverlayImageData(final String brand) throws IOException { + if ("org.mylyn".equals(brand)) { + return CommonTestUtil.getResource(this, "testdata/icons/mock-5x5.gif"); + } else if ("org.eclipse".equals(brand)) { + return CommonTestUtil.getResource(this, "testdata/icons/mock-4x4.gif"); + } else if ("exceptional".equals(brand)) { + throw new NullPointerException(); + } + return super.getOverlayImageData(brand); + } + + @Override + public InputStream getBrandingImageData(final String brand) throws IOException { + if ("org.mylyn".equals(brand)) { + return CommonTestUtil.getResource(this, "testdata/icons/mock-3x3.gif"); + } else if ("org.eclipse".equals(brand)) { + return CommonTestUtil.getResource(this, "testdata/icons/mock-2x2.gif"); + } else if ("exceptional".equals(brand)) { + throw new NullPointerException(); + } + return super.getBrandingImageData(brand); + } }; } } diff --git a/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-2x2.gif b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-2x2.gif Binary files differnew file mode 100644 index 000000000..b73642636 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-2x2.gif diff --git a/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-3x3.gif b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-3x3.gif Binary files differnew file mode 100644 index 000000000..294ad2a7a --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-3x3.gif diff --git a/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-4x4.gif b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-4x4.gif Binary files differnew file mode 100644 index 000000000..2985fd086 --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-4x4.gif diff --git a/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-5x5.gif b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-5x5.gif Binary files differnew file mode 100644 index 000000000..69ddf257a --- /dev/null +++ b/org.eclipse.mylyn.tasks.tests/testdata/icons/mock-5x5.gif diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/BrandManagerTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/BrandManagerTest.java new file mode 100644 index 000000000..3aee07402 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/BrandManagerTest.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2015 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 static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.graphics.ImageData; +import org.eclipse.swt.graphics.PaletteData; +import org.eclipse.swt.widgets.Display; +import org.junit.Test; + +import com.google.common.collect.ImmutableSet; + +@SuppressWarnings("restriction") +public class BrandManagerTest { + private final BrandManager brandManager = new BrandManager(); + + @Test + public void testGetConnectorLabel() { + MockRepositoryConnector mock1 = connector("mock1"); + MockRepositoryConnector mock2 = connector("mock2"); + brandManager.addConnectorLabel("mock1", "org.mylyn", "Mylyn"); + brandManager.addConnectorLabel("mock1", "org.eclipse", "Eclipse"); + brandManager.addConnectorLabel("mock2", "org.mylyn", "Mylyn"); + brandManager.addConnectorLabel("mock2", "com.acme", "ACME"); + + assertBrands(); + assertEquals("Mylyn", brandManager.getConnectorLabel(mock1, "org.mylyn")); + assertEquals("Eclipse", brandManager.getConnectorLabel(mock1, "org.eclipse")); + assertEquals("Mylyn", brandManager.getConnectorLabel(mock2, "org.mylyn")); + assertEquals("ACME", brandManager.getConnectorLabel(mock2, "com.acme")); + assertEquals(mock2.getLabel(), brandManager.getConnectorLabel(mock2, "org.eclipse")); + assertEquals(mock2.getLabel(), brandManager.getConnectorLabel(mock2, null)); + } + + @Test + public void testGetBrandingIcon() { + brandManager.addBrandingIcon("mock1", "org.mylyn", image(1)); + brandManager.addBrandingIcon("mock1", "org.eclipse", new Image(Display.getCurrent(), 2, 2)); + brandManager.addBrandingIcon("mock2", "org.mylyn", new Image(Display.getCurrent(), 3, 3)); + brandManager.addBrandingIcon("mock2", "com.acme", new Image(Display.getCurrent(), 4, 4)); + + assertBrands(); + assertBrandingIconHeight(1, "mock1", "org.mylyn"); + assertBrandingIconHeight(2, "mock1", "org.eclipse"); + assertBrandingIconHeight(3, "mock2", "org.mylyn"); + assertBrandingIconHeight(4, "mock2", "com.acme"); + + assertEquals(null, brandManager.getBrandingIcon("mock2", "org.eclipse")); + assertEquals(null, brandManager.getBrandingIcon(repository("mock2", "org.eclipse"))); + assertEquals(null, brandManager.getBrandingIcon("mock2", null)); + assertEquals(null, brandManager.getBrandingIcon(repository("mock2", null))); + + brandManager.addDefaultBrandingIcon("mock2", new Image(Display.getCurrent(), 5, 5)); + assertEquals(5, brandManager.getBrandingIcon("mock2", "org.eclipse").getImageData().height); + assertEquals(5, brandManager.getBrandingIcon(repository("mock2", "org.eclipse")).getImageData().height); + assertEquals(5, brandManager.getBrandingIcon("mock2", null).getImageData().height); + assertEquals(5, brandManager.getBrandingIcon(repository("mock2", null)).getImageData().height); + } + + private void assertBrandingIconHeight(int expectedHeight, String connectorKind, String brand) { + assertEquals(expectedHeight, brandManager.getBrandingIcon(connectorKind, brand).getImageData().height); + assertEquals(expectedHeight, + brandManager.getBrandingIcon(repository(connectorKind, brand)).getImageData().height); + } + + private TaskRepository repository(String connectorKind, String brand) { + TaskRepository repository = new TaskRepository(connectorKind, "http://mock"); + repository.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, brand); + return repository; + } + + @Test + public void testGetOverlayIcon() { + brandManager.addOverlayIcon("mock1", "org.mylyn", imageDescriptor(1)); + brandManager.addOverlayIcon("mock1", "org.eclipse", imageDescriptor(2)); + brandManager.addOverlayIcon("mock2", "org.mylyn", imageDescriptor(3)); + brandManager.addOverlayIcon("mock2", "com.acme", imageDescriptor(4)); + + assertBrands(); + assertOverlayIconHeight(1, "mock1", "org.mylyn"); + assertOverlayIconHeight(2, "mock1", "org.eclipse"); + assertOverlayIconHeight(3, "mock2", "org.mylyn"); + assertOverlayIconHeight(4, "mock2", "com.acme"); + + assertEquals(null, brandManager.getOverlayIcon("mock2", "org.eclipse")); + assertEquals(null, brandManager.getOverlayIcon(repository("mock2", "org.eclipse"))); + assertEquals(null, brandManager.getOverlayIcon("mock2", null)); + assertEquals(null, brandManager.getOverlayIcon(repository("mock2", null))); + + brandManager.addDefaultOverlayIcon("mock2", imageDescriptor(5)); + assertEquals(5, brandManager.getOverlayIcon("mock2", "org.eclipse").getImageData().height); + assertEquals(5, brandManager.getOverlayIcon(repository("mock2", "org.eclipse")).getImageData().height); + assertEquals(5, brandManager.getOverlayIcon("mock2", null).getImageData().height); + assertEquals(5, brandManager.getOverlayIcon(repository("mock2", null)).getImageData().height); + } + + private void assertOverlayIconHeight(int expectedHeight, String connectorKind, String brand) { + assertEquals(expectedHeight, brandManager.getOverlayIcon(connectorKind, brand).getImageData().height); + assertEquals(expectedHeight, + brandManager.getOverlayIcon(repository(connectorKind, brand)).getImageData().height); + } + + private void assertBrands() { + assertEquals(ImmutableSet.of("org.mylyn", "org.eclipse"), brandManager.getBrands("mock1")); + assertEquals(ImmutableSet.of("org.mylyn", "com.acme"), brandManager.getBrands("mock2")); + assertEquals(ImmutableSet.of(), brandManager.getBrands("unknown")); + } + + private Image image(int size) { + return new Image(Display.getCurrent(), size, size); + } + + private ImageDescriptor imageDescriptor(int size) { + ImageDescriptor mock = mock(ImageDescriptor.class); + ImageData data = new ImageData(size, size, 1, new PaletteData(1, 1, 1)); + when(mock.getImageData()).thenReturn(data); + return mock; + } + + private MockRepositoryConnector connector(final String kind) { + return new MockRepositoryConnector() { + @Override + public String getConnectorKind() { + return kind; + } + }; + } +} diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProviderTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProviderTest.java new file mode 100644 index 000000000..1a4b4d659 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProviderTest.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 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 static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.tasks.ui.ConnectorBrand; +import org.eclipse.mylyn.internal.tasks.ui.IBrandManager; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; +import org.eclipse.mylyn.tasks.ui.TasksUiImages; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.widgets.Display; +import org.junit.Test; +import org.mockito.Matchers; + +public class TaskRepositoryLabelProviderTest { + private final IBrandManager manager = mock(IBrandManager.class);; + + private final TaskRepositoryLabelProvider labelProvider = new TaskRepositoryLabelProvider() { + @Override + protected org.eclipse.mylyn.internal.tasks.ui.IBrandManager getBrandManager() { + return manager; + }; + }; + + @Test + public void testGetImage() { + Image brandingImage = new Image(Display.getCurrent(), 1, 1); + when(manager.getBrandingIcon("mock", "a")).thenReturn(brandingImage); + assertEquals(brandingImage, labelProvider.getImage(new ConnectorBrand(new MockRepositoryConnector(), "a"))); + assertEquals(CommonImages.getImage(TasksUiImages.REPOSITORY), + labelProvider.getImage(new ConnectorBrand(new MockRepositoryConnector(), "b"))); + } + + @Test + public void testGetText() { + when(manager.getConnectorLabel(any(AbstractRepositoryConnector.class), Matchers.eq("a"))).thenReturn( + "Mock Brand"); + when(manager.getConnectorLabel(any(AbstractRepositoryConnector.class), Matchers.eq("b"))).thenReturn( + "Mock Brand B"); + assertEquals("Mock Brand", labelProvider.getText(new ConnectorBrand(new MockRepositoryConnector(), "a"))); + assertEquals("Mock Brand B", labelProvider.getText(new ConnectorBrand(new MockRepositoryConnector(), "b"))); + } +} diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/ConnectorBrandContentProviderTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/ConnectorBrandContentProviderTest.java new file mode 100644 index 000000000..bf68245aa --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/ConnectorBrandContentProviderTest.java @@ -0,0 +1,74 @@ +/******************************************************************************* + * Copyright (c) 2015 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.wizards; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.Collection; + +import org.eclipse.mylyn.internal.tasks.ui.BrandManager; +import org.eclipse.mylyn.internal.tasks.ui.ConnectorBrand; +import org.eclipse.mylyn.internal.tasks.ui.wizards.SelectRepositoryConnectorPage.ConnectorBrandContentProvider; +import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; + +public class ConnectorBrandContentProviderTest { + + @Test + public void testGetElementsNoConnectors() { + Collection<MockRepositoryConnector> connectors = ImmutableList.of(); + BrandManager brandManager = mock(BrandManager.class); + ConnectorBrandContentProvider provider = new ConnectorBrandContentProvider(brandManager, connectors); + + assertEquals(0, provider.getElements(null).length); + } + + @Test + public void testGetElementsMultipleConnectors() { + MockRepositoryConnector cantCreateRepository = mockConnector("cantCreateRepository"); + when(cantCreateRepository.canCreateRepository()).thenReturn(false); + MockRepositoryConnector notUserManaged = mockConnector("notUserManaged"); + when(notUserManaged.isUserManaged()).thenReturn(false); + MockRepositoryConnector c1 = mockConnector("c1"); + MockRepositoryConnector c2 = mockConnector("c2"); + MockRepositoryConnector c3 = mockConnector("c3"); + Collection<MockRepositoryConnector> connectors = ImmutableList.of(c1, c2, notUserManaged, cantCreateRepository, + c3); + BrandManager brandManager = mock(BrandManager.class); + ConnectorBrandContentProvider provider = new ConnectorBrandContentProvider(brandManager, connectors); + + assertBrands(provider, new ConnectorBrand(c1, null), new ConnectorBrand(c2, null), new ConnectorBrand(c3, null)); + + when(brandManager.getBrands(c1.getConnectorKind())).thenReturn(ImmutableList.of("a", "b", "c")); + when(brandManager.getBrands(c2.getConnectorKind())).thenReturn(ImmutableList.<String> of()); + when(brandManager.getBrands(c3.getConnectorKind())).thenReturn(ImmutableList.of("d")); + assertBrands(provider, new ConnectorBrand(c1, null), new ConnectorBrand(c1, "a"), new ConnectorBrand(c1, "b"), + new ConnectorBrand(c1, "c"), new ConnectorBrand(c2, null), new ConnectorBrand(c3, null), + new ConnectorBrand(c3, "d")); + } + + protected MockRepositoryConnector mockConnector(String kind) { + MockRepositoryConnector spy = spy(new MockRepositoryConnector()); + when(spy.getConnectorKind()).thenReturn(kind); + return spy; + } + + protected void assertBrands(ConnectorBrandContentProvider provider, ConnectorBrand... brands) { + assertEquals(Arrays.asList(brands), Arrays.asList(provider.getElements(null))); + } +} diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizardTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizardTest.java new file mode 100644 index 000000000..23ea56b83 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizardTest.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2015 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.wizards; + +import static org.eclipse.mylyn.internal.tasks.ui.wizards.Messages.SelectRepositoryConnectorPage_Select_a_task_repository_type; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import org.eclipse.mylyn.internal.tasks.ui.ConnectorBrand; +import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; +import org.junit.Test; + +public class NewRepositoryWizardTest { + + @Test + public void testGetNextPageIWizardPage() { + NewRepositoryWizard wizard = new NewRepositoryWizard(null); + wizard.addPages(); + SelectRepositoryConnectorPage page = (SelectRepositoryConnectorPage) wizard.getPage(SelectRepositoryConnectorPage_Select_a_task_repository_type); + page.setConnectorBrand(new ConnectorBrand(new MockRepositoryConnector(), "org.mylyn")); + + wizard.getNextPage(null); + assertNull(wizard.getBrand()); + try { + wizard.getNextPage(page); + } catch (RuntimeException e) { + assertTrue(e.getMessage().startsWith("The connector implementation is incomplete")); + } + assertEquals("org.mylyn", wizard.getBrand()); + } +} diff --git a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/tasks/ui/wizards/RepositorySettingsPageTest.java b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/tasks/ui/wizards/RepositorySettingsPageTest.java index cad3e5a8e..6b416ceea 100644 --- a/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/tasks/ui/wizards/RepositorySettingsPageTest.java +++ b/org.eclipse.mylyn.tasks.ui.tests/src/org/eclipse/mylyn/tasks/ui/wizards/RepositorySettingsPageTest.java @@ -12,7 +12,10 @@ package org.eclipse.mylyn.tasks.ui.wizards; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -22,12 +25,17 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.jface.wizard.IWizard; import org.eclipse.jface.wizard.IWizardContainer; +import org.eclipse.jface.wizard.Wizard; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; +import org.eclipse.mylyn.internal.tasks.ui.wizards.EditRepositoryWizard; +import org.eclipse.mylyn.internal.tasks.ui.wizards.NewRepositoryWizard; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.tests.connector.MockRepositoryConnector; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.PlatformUI; import org.junit.Test; +@SuppressWarnings("restriction") public class RepositorySettingsPageTest { public static class TestRepositorySettingsPage extends AbstractRepositorySettingsPage { @@ -106,6 +114,39 @@ public class RepositorySettingsPageTest { assertEquals("", page.getRepositoryLabel()); } + @Test + public void applyToNewRepository() { + NewRepositoryWizard wizard = mock(NewRepositoryWizard.class); + when(wizard.getBrand()).thenReturn("org.mylyn"); + AbstractRepositorySettingsPage page = createPage(wizard); + TaskRepository repository = createTaskRepository(); + + page.applyTo(repository); + assertEquals("org.mylyn", repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)); + } + + @Test + public void applyToExistingRepository() { + EditRepositoryWizard wizard = mock(EditRepositoryWizard.class); + AbstractRepositorySettingsPage page = createPage(wizard); + TaskRepository repository = createTaskRepository(); + + page.applyTo(repository); + assertNull(repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)); + + repository.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, "org.mylyn"); + page.applyTo(repository); + assertEquals("org.mylyn", repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)); + } + + protected AbstractRepositorySettingsPage createPage(Wizard wizard) { + AbstractRepositorySettingsPage page = spy(new RepositorySettingsPageWithNoCredentials(null)); + doReturn("label").when(page).getRepositoryLabel(); + when(page.needsProxy()).thenReturn(false); + when(page.getWizard()).thenReturn(wizard); + return page; + } + private IWizardContainer applyWizardContainer(TestRepositorySettingsPage page) { IWizard wizard = mock(IWizard.class); IWizardContainer container = mock(IWizardContainer.class); diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/BrandManager.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/BrandManager.java new file mode 100644 index 000000000..e23ea4352 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/BrandManager.java @@ -0,0 +1,137 @@ +/******************************************************************************* + * Copyright (c) 2015 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 java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.IRepositoryManager; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.mylyn.tasks.ui.TasksUi; +import org.eclipse.swt.graphics.Image; + +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.LinkedHashMultimap; +import com.google.common.collect.Multimap; +import com.google.common.collect.Table; + +public class BrandManager implements IBrandManager { + + private final Multimap<String, String> brands = LinkedHashMultimap.create(); + + private final Table<String, String, Image> brandingIcons = HashBasedTable.create(); + + private final Table<String, String, ImageDescriptor> overlayIcons = HashBasedTable.create(); + + private final Table<String, String, String> connectorLabels = HashBasedTable.create(); + + private final Map<String, Image> defaultBrandingIcons = new HashMap<>(); + + private final Map<String, ImageDescriptor> defaultOverlayIcons = new HashMap<>(); + + public void addBrandingIcon(String repositoryType, String brand, Image icon) { + brands.put(repositoryType, brand); + brandingIcons.put(repositoryType, brand, icon); + } + + public void addOverlayIcon(String repositoryType, String brand, ImageDescriptor icon) { + brands.put(repositoryType, brand); + overlayIcons.put(repositoryType, brand, icon); + } + + public void addConnectorLabel(String repositoryType, String brand, String label) { + brands.put(repositoryType, brand); + connectorLabels.put(repositoryType, brand, label); + } + + public void addDefaultBrandingIcon(String repositoryType, Image icon) { + defaultBrandingIcons.put(repositoryType, icon); + } + + public void addDefaultOverlayIcon(String repositoryType, ImageDescriptor icon) { + defaultOverlayIcons.put(repositoryType, icon); + } + + @Override + public Image getBrandingIcon(TaskRepository repository) { + return getBrandingIcon(repository.getConnectorKind(), + repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)); + } + + @Override + public ImageDescriptor getOverlayIcon(TaskRepository repository) { + return getOverlayIcon(repository.getConnectorKind(), + repository.getProperty(ITasksCoreConstants.PROPERTY_BRAND_ID)); + } + + @Override + public ImageDescriptor getOverlayIcon(ITask task) { + TaskRepository repository = getRepositoryManager().getRepository(task.getConnectorKind(), + task.getRepositoryUrl()); + if (repository != null) { + return getOverlayIcon(repository); + } + return getDefaultOverlayIcon(task.getConnectorKind()); + } + + @Override + public Image getBrandingIcon(String repositoryType, @Nullable String brand) { + Image icon = brandingIcons.get(repositoryType, brand); + if (icon != null) { + return icon; + } + return getDefaultBrandingIcon(repositoryType); + } + + @Override + public ImageDescriptor getOverlayIcon(String repositoryType, @Nullable String brand) { + ImageDescriptor icon = overlayIcons.get(repositoryType, brand); + if (icon != null) { + return icon; + } + return getDefaultOverlayIcon(repositoryType); + } + + @Override + public String getConnectorLabel(AbstractRepositoryConnector connector, @Nullable String brand) { + String brandLabel = connectorLabels.get(connector.getConnectorKind(), brand); + if (brandLabel != null) { + return brandLabel; + } + return connector.getLabel(); + } + + @Override + public Collection<String> getBrands(String connectorKind) { + return brands.get(connectorKind); + } + + @Override + public Image getDefaultBrandingIcon(String repositoryType) { + return defaultBrandingIcons.get(repositoryType); + } + + @Override + public ImageDescriptor getDefaultOverlayIcon(String repositoryType) { + return defaultOverlayIcons.get(repositoryType); + } + + protected IRepositoryManager getRepositoryManager() { + return TasksUi.getRepositoryManager(); + } +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ConnectorBrand.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ConnectorBrand.java new file mode 100644 index 000000000..c05b53431 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/ConnectorBrand.java @@ -0,0 +1,77 @@ +/******************************************************************************* + * Copyright (c) 2015 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.tasks.core.AbstractRepositoryConnector; +import org.eclipse.osgi.util.NLS; + +public class ConnectorBrand { + private final AbstractRepositoryConnector connector; + + private final String brandId; + + public ConnectorBrand(AbstractRepositoryConnector connector, String brandId) { + this.connector = connector; + this.brandId = brandId; + } + + public AbstractRepositoryConnector getConnector() { + return connector; + } + + public String getBrandId() { + return brandId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((brandId == null) ? 0 : brandId.hashCode()); + result = prime * result + ((connector == null) ? 0 : connector.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (!(obj instanceof ConnectorBrand)) { + return false; + } + ConnectorBrand other = (ConnectorBrand) obj; + if (brandId == null) { + if (other.brandId != null) { + return false; + } + } else if (!brandId.equals(other.brandId)) { + return false; + } + if (connector == null) { + if (other.connector != null) { + return false; + } + } else if (!connector.equals(other.connector)) { + return false; + } + return true; + } + + @Override + public String toString() { + return NLS.bind("<{0},{1}>", connector.getConnectorKind(), brandId); //$NON-NLS-1$ + } +} diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/IBrandManager.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/IBrandManager.java new file mode 100644 index 000000000..08d6a5388 --- /dev/null +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/IBrandManager.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2015 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 java.util.Collection; + +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; +import org.eclipse.mylyn.tasks.core.ITask; +import org.eclipse.mylyn.tasks.core.TaskRepository; +import org.eclipse.swt.graphics.Image; + +public interface IBrandManager { + + public Image getBrandingIcon(TaskRepository repository); + + public ImageDescriptor getOverlayIcon(TaskRepository repository); + + public ImageDescriptor getOverlayIcon(ITask task); + + /** + * Returns the branding icon for the given connector kind and brand. Returns the default icon for the repository + * type if the brand is <code>null</code> or is unknown to the connector. + */ + public Image getBrandingIcon(String connectorKind, @Nullable String brand); + + /** + * Returns the overlay icon for the given connector kind and brand. Returns the default icon for the repository type + * if the brand is <code>null</code> or is unknown to the connector. + */ + public ImageDescriptor getOverlayIcon(String connectorKind, @Nullable String brand); + + /** + * Returns the connector label for the given connector and brand. Returns the default label for the connector if the + * brand is <code>null</code> or is unknown to the connector. + */ + public String getConnectorLabel(AbstractRepositoryConnector connector, @Nullable String brand); + + /** + * Returns the brands known to the given connector. + */ + public Collection<String> getBrands(String connectorKind); + + public Image getDefaultBrandingIcon(String connectorKind); + + public ImageDescriptor getDefaultOverlayIcon(String connectorKind); + +}
\ No newline at end of file diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskLabelDecorator.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskLabelDecorator.java index c9c0c6ed0..fbe710cf1 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskLabelDecorator.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TaskLabelDecorator.java @@ -58,8 +58,7 @@ public class TaskLabelDecorator implements ILightweightLabelDecorator { decoration.addSuffix(" [" + taskRepository.getRepositoryLabel() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ } } else if (element instanceof TaskRepository) { - ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon( - ((TaskRepository) element).getConnectorKind()); + ImageDescriptor overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon((TaskRepository) element); if (overlay != null) { decoration.addOverlay(overlay, IDecoration.BOTTOM_RIGHT); } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java index 46c295982..4c0c1cd58 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/TasksUiPlugin.java @@ -128,7 +128,7 @@ import org.osgi.util.tracker.ServiceTracker; /** * Main entry point for the Tasks UI. - * + * * @author Mik Kersten * @since 3.0 */ @@ -183,9 +183,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { private TaskListExternalizer taskListExternalizer; - private final Map<String, Image> brandingIcons = new HashMap<String, Image>(); - - private final Map<String, ImageDescriptor> overlayIcons = new HashMap<String, ImageDescriptor>(); + private final BrandManager brandManager = new BrandManager(); private final Set<AbstractDuplicateDetector> duplicateDetectors = new HashSet<AbstractDuplicateDetector>(); @@ -636,16 +634,16 @@ public class TasksUiPlugin extends AbstractUIPlugin { serviceMessageManager = new ServiceMessageManager(serviceMessageUrl, lastMod, etag, checktime, new NotificationEnvironment() { - private Set<String> installedFeatures; + private Set<String> installedFeatures; - @Override - public Set<String> getInstalledFeatures(IProgressMonitor monitor) { - if (installedFeatures == null) { - installedFeatures = DiscoveryUi.createInstallJob().getInstalledFeatures(monitor); - } - return installedFeatures; - } - }); + @Override + public Set<String> getInstalledFeatures(IProgressMonitor monitor) { + if (installedFeatures == null) { + installedFeatures = DiscoveryUi.createInstallJob().getInstalledFeatures(monitor); + } + return installedFeatures; + } + }); // Disabled for initial 3.4 release as per bug#263528 if (getPreferenceStore().getBoolean(ITasksUiPreferenceConstants.SERVICE_MESSAGES_ENABLED)) { @@ -777,7 +775,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { /** * Returns the local task repository. If the repository does not exist it is created and added to the task * repository manager. - * + * * @return the local task repository; never <code>null</code> * @since 3.0 */ @@ -867,7 +865,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { * Persist <code>path</code> as data directory and loads data from <code>path</code>. This method may block if other * jobs are running that modify tasks data. This method will only execute after all conflicting jobs have been * completed. - * + * * @throws CoreException * in case setting of the data directory did not complete normally * @throws OperationCanceledException @@ -954,12 +952,12 @@ public class TasksUiPlugin extends AbstractUIPlugin { if (!taskActivityMonitor.getActivationHistory().isEmpty()) { // tasks have been active before so fore preference enabled MonitorUiPlugin.getDefault() - .getPreferenceStore() - .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED, true); + .getPreferenceStore() + .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED, true); } MonitorUiPlugin.getDefault() - .getPreferenceStore() - .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED + ".checked", true); //$NON-NLS-1$ + .getPreferenceStore() + .setValue(MonitorUiPlugin.ACTIVITY_TRACKING_ENABLED + ".checked", true); //$NON-NLS-1$ MonitorUiPlugin.getDefault().savePluginPreferences(); } @@ -1119,20 +1117,44 @@ public class TasksUiPlugin extends AbstractUIPlugin { return INSTANCE.repositoryTemplateManager; } + /** + * @deprecated Use {@link BrandManager#addDefaultBrandingIcon(String, Image)} instead + * @see #getBrandManager() + */ + @Deprecated public void addBrandingIcon(String repositoryType, Image icon) { - brandingIcons.put(repositoryType, icon); + brandManager.addDefaultBrandingIcon(repositoryType, icon); } + /** + * @deprecated Use {@link BrandManager#getDefaultBrandingIcon(String)} instead + * @see #getBrandManager() + */ + @Deprecated public Image getBrandingIcon(String repositoryType) { - return brandingIcons.get(repositoryType); + return brandManager.getDefaultBrandingIcon(repositoryType); } + /** + * @deprecated Use {@link BrandManager#addDefaultOverlayIcon(String, ImageDescriptor)} instead + * @see #getBrandManager() + */ + @Deprecated public void addOverlayIcon(String repositoryType, ImageDescriptor icon) { - overlayIcons.put(repositoryType, icon); + brandManager.addDefaultOverlayIcon(repositoryType, icon); } + /** + * @deprecated Use {@link BrandManager#getDefaultOverlayIcon(String)} instead + * @see #getBrandManager() + */ + @Deprecated public ImageDescriptor getOverlayIcon(String repositoryType) { - return overlayIcons.get(repositoryType); + return brandManager.getDefaultOverlayIcon(repositoryType); + } + + public IBrandManager getBrandManager() { + return brandManager; } public void addRepositoryLinkProvider(AbstractTaskRepositoryLinkProvider repositoryLinkProvider) { @@ -1257,7 +1279,7 @@ public class TasksUiPlugin extends AbstractUIPlugin { /** * Associate a Task Repository with a workbench project - * + * * @param resource * project or resource belonging to a project * @param repository diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/NewTaskAction.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/NewTaskAction.java index bdd77b8dc..a3e36cc4f 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/NewTaskAction.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/actions/NewTaskAction.java @@ -223,7 +223,7 @@ public class NewTaskAction extends BaseSelectionListenerAction implements IMenuC RepositorySelectionAction action = new RepositorySelectionAction(repository); ActionContributionItem item = new ActionContributionItem(action); action.setText(repository.getRepositoryLabel()); - ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon(repository.getConnectorKind()); + ImageDescriptor overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon(repository); ImageDescriptor compositeDescriptor = new TaskListImageDescriptor(TasksUiImages.TASK_NEW, overlay, false, false); action.setImageDescriptor(compositeDescriptor); item.fill(dropDownMenu, -1); diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskRepositoryCredentialsDialog.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskRepositoryCredentialsDialog.java index edfe35cfd..6e0fae129 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskRepositoryCredentialsDialog.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/dialogs/TaskRepositoryCredentialsDialog.java @@ -135,7 +135,7 @@ public class TaskRepositoryCredentialsDialog extends TitleAreaDialog { .applyTo(labelComposite); Label label = new Label(labelComposite, SWT.NONE); - label.setImage(TasksUiPlugin.getDefault().getBrandingIcon(taskRepository.getConnectorKind())); + label.setImage(TasksUiPlugin.getDefault().getBrandManager().getBrandingIcon(taskRepository)); label = new Label(labelComposite, SWT.NONE); label.setText(Messages.TaskRepositoryCredentialsDialog_Task_Repository); @@ -285,6 +285,7 @@ public class TaskRepositoryCredentialsDialog extends TitleAreaDialog { .applyTo(label); } + @Override public String getMessage() { return message; } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/RepositoryConnectorUiExtensionReader.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/RepositoryConnectorUiExtensionReader.java index fddc012d4..58bc60bbc 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/RepositoryConnectorUiExtensionReader.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/util/RepositoryConnectorUiExtensionReader.java @@ -30,6 +30,7 @@ import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.mylyn.commons.core.StatusHandler; import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.internal.tasks.core.util.ContributorBlackList; +import org.eclipse.mylyn.internal.tasks.ui.BrandManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.spi.RepositoryConnectorBranding; @@ -100,53 +101,31 @@ public class RepositoryConnectorUiExtensionReader { RepositoryConnectorBranding branding = loadAdapter(connector, RepositoryConnectorBranding.class); if (branding != null) { - InputStream brandingImageData = branding.getBrandingImageData(); - if (brandingImageData != null) { - try { - TasksUiPlugin.getDefault().addBrandingIcon(connector.getConnectorKind(), - getImage(brandingImageData)); - } finally { - closeQuietly(brandingImageData); - } - } - InputStream overlayImageData = branding.getOverlayImageData(); - if (overlayImageData != null) { - try { - TasksUiPlugin.getDefault().addOverlayIcon(connector.getConnectorKind(), - getImageDescriptor(overlayImageData)); - } finally { - closeQuietly(brandingImageData); - } - } - } - } - - private void closeQuietly(InputStream in) { - try { - in.close(); - } catch (IOException e) { - // ignore + addDefaultImageData(connector, branding); + addBranding(connector.getConnectorKind(), branding); } } - @SuppressWarnings("unchecked") - public <T> T loadAdapter(final AbstractRepositoryConnector connector, Class<T> klass) { - T adapter = null; - if (connector instanceof IAdaptable) { - adapter = (T) ((IAdaptable) connector).getAdapter(klass); + protected void addDefaultImageData(final AbstractRepositoryConnector connector, + RepositoryConnectorBranding branding) throws IOException { + InputStream brandingImageData = branding.getBrandingImageData(); + if (brandingImageData != null) { + try { + ((BrandManager) TasksUiPlugin.getDefault().getBrandManager()).addDefaultBrandingIcon( + connector.getConnectorKind(), getImage(brandingImageData)); + } finally { + closeQuietly(brandingImageData); + } } - if (adapter == null) { - adapter = (T) Platform.getAdapterManager().loadAdapter(connector, klass.getName()); + InputStream overlayImageData = branding.getOverlayImageData(); + if (overlayImageData != null) { + try { + ((BrandManager) TasksUiPlugin.getDefault().getBrandManager()).addDefaultOverlayIcon( + connector.getConnectorKind(), getImageDescriptor(overlayImageData)); + } finally { + closeQuietly(brandingImageData); + } } - return adapter; - } - - private ImageDescriptor getImageDescriptor(InputStream in) { - return ImageDescriptor.createFromImageData(new ImageData(in)); - } - - private Image getImage(InputStream in) { - return CommonImages.getImage(getImageDescriptor(in)); } @Override @@ -157,6 +136,70 @@ public class RepositoryConnectorUiExtensionReader { }); } + protected void addBranding(final String connectorKind, RepositoryConnectorBranding branding) throws IOException { + BrandManager brandManager = (BrandManager) TasksUiPlugin.getDefault().getBrandManager(); + for (String brand : branding.getBrands()) { + if (brand == null) { + continue; + } + try { + String connectorLabel = branding.getConnectorLabel(brand); + if (connectorLabel != null) { + brandManager.addConnectorLabel(connectorKind, brand, connectorLabel); + } + + InputStream brandingImageData = branding.getBrandingImageData(brand); + if (brandingImageData != null) { + try { + brandManager.addBrandingIcon(connectorKind, brand, getImage(brandingImageData)); + } finally { + closeQuietly(brandingImageData); + } + } + + InputStream overlayImageData = branding.getOverlayImageData(brand); + if (overlayImageData != null) { + try { + brandManager.addOverlayIcon(connectorKind, brand, getImageDescriptor(overlayImageData)); + } finally { + closeQuietly(brandingImageData); + } + } + } catch (Exception e) { + StatusHandler.log(new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, NLS.bind( + "Loading of brand '{0}' for kind '{1}' failed.", brand, connectorKind), e)); //$NON-NLS-1$ + } + } + } + + private void closeQuietly(InputStream in) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + + @SuppressWarnings("unchecked") + public <T> T loadAdapter(final AbstractRepositoryConnector connector, Class<T> klass) { + T adapter = null; + if (connector instanceof IAdaptable) { + adapter = (T) ((IAdaptable) connector).getAdapter(klass); + } + if (adapter == null) { + adapter = (T) Platform.getAdapterManager().loadAdapter(connector, klass.getName()); + } + return adapter; + } + + private ImageDescriptor getImageDescriptor(InputStream in) { + return ImageDescriptor.createFromImageData(new ImageData(in)); + } + + private Image getImage(InputStream in) { + return CommonImages.getImage(getImageDescriptor(in)); + } + private void registerFromExtensionPoint() { IExtensionPoint repositoriesExtensionPoint = registry.getExtensionPoint(EXTENSION_REPOSITORIES); IExtension[] repositoryExtensions = repositoriesExtensionPoint.getExtensions(); @@ -177,7 +220,8 @@ public class RepositoryConnectorUiExtensionReader { Object connectorUiObject = element.createExecutableExtension(ATTR_CLASS); if (connectorUiObject instanceof AbstractRepositoryConnectorUi) { AbstractRepositoryConnectorUi connectorUi = (AbstractRepositoryConnectorUi) connectorUiObject; - if (TasksUiPlugin.getConnector(connectorUi.getConnectorKind()) != null) { + AbstractRepositoryConnector connector = TasksUiPlugin.getConnector(connectorUi.getConnectorKind()); + if (connector != null) { TasksUiPlugin.getDefault().addRepositoryConnectorUi(connectorUi); String iconPath = element.getAttribute(ATTR_BRANDING_ICON); @@ -185,8 +229,8 @@ public class RepositoryConnectorUiExtensionReader { ImageDescriptor descriptor = AbstractUIPlugin.imageDescriptorFromPlugin( element.getContributor().getName(), iconPath); if (descriptor != null) { - TasksUiPlugin.getDefault().addBrandingIcon(connectorUi.getConnectorKind(), - CommonImages.getImage(descriptor)); + ((BrandManager) TasksUiPlugin.getDefault().getBrandManager()).addDefaultBrandingIcon( + connectorUi.getConnectorKind(), CommonImages.getImage(descriptor)); } } String overlayIconPath = element.getAttribute(ATTR_OVERLAY_ICON); @@ -194,9 +238,15 @@ public class RepositoryConnectorUiExtensionReader { ImageDescriptor descriptor = AbstractUIPlugin.imageDescriptorFromPlugin( element.getContributor().getName(), overlayIconPath); if (descriptor != null) { - TasksUiPlugin.getDefault().addOverlayIcon(connectorUi.getConnectorKind(), descriptor); + ((BrandManager) TasksUiPlugin.getDefault().getBrandManager()).addDefaultOverlayIcon( + connectorUi.getConnectorKind(), descriptor); } } + + RepositoryConnectorBranding branding = loadAdapter(connector, RepositoryConnectorBranding.class); + if (branding != null) { + addBranding(connector.getConnectorKind(), branding); + } } else { StatusHandler.log(new Status( IStatus.ERROR, diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskDetailLabelProvider.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskDetailLabelProvider.java index 5ee00d133..394ab7b37 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskDetailLabelProvider.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskDetailLabelProvider.java @@ -17,7 +17,6 @@ import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.internal.tasks.core.AbstractTask; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; -import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.ITask; import org.eclipse.mylyn.tasks.core.TaskRepository; import org.eclipse.mylyn.tasks.ui.TasksUi; @@ -37,9 +36,7 @@ public class TaskDetailLabelProvider extends LabelProvider implements ILabelProv return super.getImage(element); } - AbstractRepositoryConnector connector = TasksUi.getRepositoryManager().getRepositoryConnector( - ((ITask) element).getConnectorKind()); - ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon(connector.getConnectorKind()); + ImageDescriptor overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon((ITask) element); if (overlay != null) { return CommonImages.getImageWithOverlay(TasksUiImages.REPOSITORY, overlay, false, false); } else { diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListToolTip.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListToolTip.java index a1415f57f..f8ca4beff 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListToolTip.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskListToolTip.java @@ -418,18 +418,18 @@ public class TaskListToolTip extends GradientToolTip { private Image getImage(IRepositoryElement element) { if (element instanceof IRepositoryQuery) { IRepositoryQuery query = (IRepositoryQuery) element; - AbstractRepositoryConnector connector = TasksUi.getRepositoryManager().getRepositoryConnector( - query.getConnectorKind()); - if (connector != null) { - return TasksUiPlugin.getDefault().getBrandingIcon(connector.getConnectorKind()); + TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(query.getRepositoryUrl()); + if (repository != null) { + return TasksUiPlugin.getDefault().getBrandManager().getBrandingIcon(repository); } + return TasksUiPlugin.getDefault().getBrandManager().getDefaultBrandingIcon(query.getConnectorKind()); } else if (element instanceof ITask) { - ITask repositoryTask = (ITask) element; - AbstractRepositoryConnector connector = TasksUi.getRepositoryManager().getRepositoryConnector( - repositoryTask.getConnectorKind()); - if (connector != null) { - return TasksUiPlugin.getDefault().getBrandingIcon(connector.getConnectorKind()); + ITask task = (ITask) element; + TaskRepository repository = TasksUiPlugin.getRepositoryManager().getRepository(task.getRepositoryUrl()); + if (repository != null) { + return TasksUiPlugin.getDefault().getBrandManager().getBrandingIcon(repository); } + return TasksUiPlugin.getDefault().getBrandManager().getDefaultBrandingIcon(task.getConnectorKind()); } else if (element instanceof ScheduledTaskContainer) { return CommonImages.getImage(CommonImages.CALENDAR); } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProvider.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProvider.java index 5e29e566b..456165c2b 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProvider.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/views/TaskRepositoryLabelProvider.java @@ -15,6 +15,8 @@ import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.mylyn.commons.ui.CommonImages; import org.eclipse.mylyn.internal.tasks.core.Category; +import org.eclipse.mylyn.internal.tasks.ui.ConnectorBrand; +import org.eclipse.mylyn.internal.tasks.ui.IBrandManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.actions.DisconnectRepositoryAction; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; @@ -42,7 +44,16 @@ public class TaskRepositoryLabelProvider implements ILabelProvider { return CommonImages.getImage(TasksUiImages.CATEGORY); } else if (object instanceof AbstractRepositoryConnector) { AbstractRepositoryConnector repositoryConnector = (AbstractRepositoryConnector) object; - Image image = TasksUiPlugin.getDefault().getBrandingIcon(repositoryConnector.getConnectorKind()); + Image image = getBrandManager().getDefaultBrandingIcon(repositoryConnector.getConnectorKind()); + if (image != null) { + return image; + } else { + return CommonImages.getImage(TasksUiImages.REPOSITORY); + } + } else if (object instanceof ConnectorBrand) { + ConnectorBrand connectorBrand = (ConnectorBrand) object; + Image image = getBrandManager().getBrandingIcon(connectorBrand.getConnector().getConnectorKind(), + connectorBrand.getBrandId()); if (image != null) { return image; } else { @@ -59,7 +70,6 @@ public class TaskRepositoryLabelProvider implements ILabelProvider { } public String getText(Object object) { - if (object instanceof TaskRepository) { TaskRepository repository = (TaskRepository) object; StringBuilder label = new StringBuilder(); @@ -70,6 +80,9 @@ public class TaskRepositoryLabelProvider implements ILabelProvider { return label.toString(); } else if (object instanceof AbstractRepositoryConnector) { return ((AbstractRepositoryConnector) object).getLabel(); + } else if (object instanceof ConnectorBrand) { + ConnectorBrand connectorBrand = (ConnectorBrand) object; + return getBrandManager().getConnectorLabel(connectorBrand.getConnector(), connectorBrand.getBrandId()); } else if (object instanceof Category) { return ((Category) object).getLabel(); } else { @@ -77,6 +90,10 @@ public class TaskRepositoryLabelProvider implements ILabelProvider { } } + protected IBrandManager getBrandManager() { + return TasksUiPlugin.getDefault().getBrandManager(); + } + public void addListener(ILabelProviderListener listener) { // ignore diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizard.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizard.java index af70ec3b9..720818c66 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizard.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/NewRepositoryWizard.java @@ -60,6 +60,8 @@ public class NewRepositoryWizard extends Wizard implements INewWizard { private boolean showNewQueryPromptOnFinish; + private String brand; + public NewRepositoryWizard() { this(null); } @@ -99,6 +101,7 @@ public class NewRepositoryWizard extends Wizard implements INewWizard { public IWizardPage getNextPage(IWizardPage page) { if (page == selectConnectorPage) { connector = selectConnectorPage.getConnector(); + brand = selectConnectorPage.getBrand(); updateSettingsPage(); return settingsPage; } @@ -132,7 +135,7 @@ public class NewRepositoryWizard extends Wizard implements INewWizard { return taskRepository; } - private void updateSettingsPage() { + void updateSettingsPage() { assert connector != null; if (!connector.getConnectorKind().equals(lastConnectorKind)) { AbstractRepositoryConnectorUi connectorUi = TasksUiPlugin.getConnectorUi(connector.getConnectorKind()); @@ -182,4 +185,8 @@ public class NewRepositoryWizard extends Wizard implements INewWizard { this.showNewQueryPromptOnFinish = showNewQueryPromptOnFinish; } + public String getBrand() { + return brand; + } + } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/SelectRepositoryConnectorPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/SelectRepositoryConnectorPage.java index 5d144c8d7..dc7a2e8e5 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/SelectRepositoryConnectorPage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/internal/tasks/ui/wizards/SelectRepositoryConnectorPage.java @@ -12,6 +12,7 @@ package org.eclipse.mylyn.internal.tasks.ui.wizards; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import org.eclipse.core.commands.Command; @@ -31,6 +32,8 @@ import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.mylyn.commons.ui.CommonImages; +import org.eclipse.mylyn.internal.tasks.ui.ConnectorBrand; +import org.eclipse.mylyn.internal.tasks.ui.IBrandManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.util.TasksUiInternal; import org.eclipse.mylyn.internal.tasks.ui.views.TaskRepositoriesSorter; @@ -54,9 +57,19 @@ public class SelectRepositoryConnectorPage extends WizardPage { private TableViewer viewer; - private AbstractRepositoryConnector connector; + private ConnectorBrand connectorBrand; - static class RepositoryContentProvider implements IStructuredContentProvider { + static class ConnectorBrandContentProvider implements IStructuredContentProvider { + + private final Collection<? extends AbstractRepositoryConnector> connectors; + + private final IBrandManager brandManager; + + public ConnectorBrandContentProvider(IBrandManager brandManager, + Collection<? extends AbstractRepositoryConnector> connectors) { + this.brandManager = brandManager; + this.connectors = connectors; + } public void inputChanged(Viewer v, Object oldInput, Object newInput) { } @@ -65,14 +78,16 @@ public class SelectRepositoryConnectorPage extends WizardPage { } public Object[] getElements(Object parent) { - List<AbstractRepositoryConnector> userManagedRepositories = new ArrayList<AbstractRepositoryConnector>(); - for (AbstractRepositoryConnector connector : TasksUi.getRepositoryManager().getRepositoryConnectors()) { + List<ConnectorBrand> connectorBrands = new ArrayList<ConnectorBrand>(); + for (AbstractRepositoryConnector connector : connectors) { if (connector.isUserManaged() && connector.canCreateRepository()) { - userManagedRepositories.add(connector); + connectorBrands.add(new ConnectorBrand(connector, null)); + for (String brand : brandManager.getBrands(connector.getConnectorKind())) { + connectorBrands.add(new ConnectorBrand(connector, brand)); + } } } - - return userManagedRepositories.toArray(); + return connectorBrands.toArray(); } } @@ -84,7 +99,7 @@ public class SelectRepositoryConnectorPage extends WizardPage { @Override public boolean canFlipToNextPage() { - return connector != null; + return connectorBrand != null; } public void createControl(Composite parent) { @@ -92,7 +107,8 @@ public class SelectRepositoryConnectorPage extends WizardPage { GridLayoutFactory.fillDefaults().numColumns(1).spacing(0, 3).applyTo(container); viewer = new TableViewer(container, SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); - viewer.setContentProvider(new RepositoryContentProvider()); + viewer.setContentProvider(new ConnectorBrandContentProvider(TasksUiPlugin.getDefault().getBrandManager(), + TasksUi.getRepositoryManager().getRepositoryConnectors())); viewer.setSorter(new TaskRepositoriesSorter()); viewer.setLabelProvider(new DecoratingLabelProvider(new TaskRepositoryLabelProvider(), PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator())); @@ -100,8 +116,8 @@ public class SelectRepositoryConnectorPage extends WizardPage { viewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); - if (selection.getFirstElement() instanceof AbstractRepositoryConnector) { - connector = (AbstractRepositoryConnector) selection.getFirstElement(); + if (selection.getFirstElement() instanceof ConnectorBrand) { + setConnectorBrand((ConnectorBrand) selection.getFirstElement()); setPageComplete(true); } } @@ -146,8 +162,16 @@ public class SelectRepositoryConnectorPage extends WizardPage { setControl(container); } + void setConnectorBrand(ConnectorBrand connectorBrand) { + this.connectorBrand = connectorBrand; + } + public AbstractRepositoryConnector getConnector() { - return connector; + return connectorBrand == null ? null : connectorBrand.getConnector(); + } + + public String getBrand() { + return connectorBrand == null ? null : connectorBrand.getBrandId(); } } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/TaskEditor.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/TaskEditor.java index 8b9717320..190600024 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/TaskEditor.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/editors/TaskEditor.java @@ -1144,7 +1144,12 @@ public class TaskEditor extends SharedHeaderFormEditor { if (LocalRepositoryConnector.CONNECTOR_KIND.equals(connectorKind)) { return CommonImages.getImage(TasksUiImages.TASK); } else { - ImageDescriptor overlay = TasksUiPlugin.getDefault().getOverlayIcon(connectorKind); + ImageDescriptor overlay; + if (outgoingNewRepository != null) { + overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon(outgoingNewRepository); + } else { + overlay = TasksUiPlugin.getDefault().getBrandManager().getOverlayIcon(task); + } Image image = CommonImages.getImageWithOverlay(TasksUiImages.REPOSITORY, overlay, false, false); return image; } diff --git a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/wizards/AbstractRepositorySettingsPage.java b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/wizards/AbstractRepositorySettingsPage.java index f039ce6cc..1b80f2072 100644 --- a/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/wizards/AbstractRepositorySettingsPage.java +++ b/org.eclipse.mylyn.tasks.ui/src/org/eclipse/mylyn/tasks/ui/wizards/AbstractRepositorySettingsPage.java @@ -49,10 +49,12 @@ import org.eclipse.mylyn.commons.workbench.browser.BrowserUtil; import org.eclipse.mylyn.commons.workbench.forms.SectionComposite; import org.eclipse.mylyn.internal.commons.repositories.ui.RepositoryUiUtil; import org.eclipse.mylyn.internal.tasks.core.IRepositoryConstants; +import org.eclipse.mylyn.internal.tasks.core.ITasksCoreConstants; import org.eclipse.mylyn.internal.tasks.core.RepositoryTemplateManager; import org.eclipse.mylyn.internal.tasks.core.TaskRepositoryManager; import org.eclipse.mylyn.internal.tasks.ui.TasksUiPlugin; import org.eclipse.mylyn.internal.tasks.ui.wizards.Messages; +import org.eclipse.mylyn.internal.tasks.ui.wizards.NewRepositoryWizard; import org.eclipse.mylyn.tasks.core.AbstractRepositoryConnector; import org.eclipse.mylyn.tasks.core.RepositoryInfo; import org.eclipse.mylyn.tasks.core.RepositoryTemplate; @@ -92,7 +94,7 @@ import org.eclipse.ui.statushandlers.StatusManager; /** * Extend to provide custom repository settings. This page is typically invoked by the user requesting properties via * the Task Repositories view. - * + * * @author Mik Kersten * @author Rob Elves * @author Steffen Pingel @@ -103,7 +105,7 @@ import org.eclipse.ui.statushandlers.StatusManager; * @since 2.0 */ public abstract class AbstractRepositorySettingsPage extends AbstractTaskRepositoryPage implements ITaskRepositoryPage, -IAdaptable { + IAdaptable { protected static final String PREFS_PAGE_ID_NET_PROXY = "org.eclipse.ui.net.NetPreferences"; //$NON-NLS-1$ @@ -437,10 +439,10 @@ IAdaptable { }); GridDataFactory.fillDefaults() - .hint(300, SWT.DEFAULT) - .grab(true, false) - .span(2, SWT.DEFAULT) - .applyTo(serverUrlCombo); + .hint(300, SWT.DEFAULT) + .grab(true, false) + .span(2, SWT.DEFAULT) + .applyTo(serverUrlCombo); repositoryLabelEditor = new StringFieldEditor("", LABEL_REPOSITORY_LABEL, StringFieldEditor.UNLIMITED, //$NON-NLS-1$ compositeContainer) { @@ -786,10 +788,10 @@ IAdaptable { certAuthButton = new Button(certAuthComp, SWT.CHECK); GridDataFactory.fillDefaults() - .indent(0, 5) - .align(SWT.LEFT, SWT.TOP) - .span(3, SWT.DEFAULT) - .applyTo(certAuthButton); + .indent(0, 5) + .align(SWT.LEFT, SWT.TOP) + .span(3, SWT.DEFAULT) + .applyTo(certAuthButton); certAuthButton.setText(Messages.AbstractRepositorySettingsPage_Enable_certificate_authentification); @@ -881,10 +883,10 @@ IAdaptable { httpAuthButton = new Button(httpAuthComp, SWT.CHECK); GridDataFactory.fillDefaults() - .indent(0, 5) - .align(SWT.LEFT, SWT.TOP) - .span(3, SWT.DEFAULT) - .applyTo(httpAuthButton); + .indent(0, 5) + .align(SWT.LEFT, SWT.TOP) + .span(3, SWT.DEFAULT) + .applyTo(httpAuthButton); httpAuthButton.setText(Messages.AbstractRepositorySettingsPage_Enable_http_authentication); @@ -1641,7 +1643,7 @@ IAdaptable { /** * Returns true, if credentials are incomplete. Clients may override this method. - * + * * @since 3.4 */ protected boolean isMissingCredentials() { @@ -1727,7 +1729,7 @@ IAdaptable { * Note: The credentials of the created repository are not persisted in the platform keystore. When overriding, * subclasses must either call super or call {@link TaskRepository#setShouldPersistCredentials(boolean) * setShouldPersistCredentials(false)} before calling {@link #applyTo(TaskRepository)}. - * + * * @since 2.0 */ public TaskRepository createTaskRepository() { @@ -1748,6 +1750,10 @@ IAdaptable { connector.applyDefaultCategory(repository); } repository.setVersion(getVersion()); + if (getWizard() instanceof NewRepositoryWizard) { + String brand = ((NewRepositoryWizard) getWizard()).getBrand(); + repository.setProperty(ITasksCoreConstants.PROPERTY_BRAND_ID, brand); + } if (needsEncoding()) { repository.setCharacterEncoding(getCharacterEncoding()); } @@ -1930,7 +1936,7 @@ IAdaptable { * <p> * This information is typically used by the wizard to set the enablement of the validation UI affordance. * </p> - * + * * @return <code>true</code> if this page can be validated, and <code>false</code> otherwise * @see #needsValidation() * @see IWizardContainer#updateButtons() @@ -1949,7 +1955,7 @@ IAdaptable { /** * Public for testing. - * + * * @since 2.0 */ public void setUrl(String url) { @@ -1958,7 +1964,7 @@ IAdaptable { /** * Public for testing. - * + * * @since 2.0 */ public void setUserId(String id) { @@ -1967,7 +1973,7 @@ IAdaptable { /** * Public for testing. - * + * * @since 2.0 */ public void setPassword(String pass) { @@ -2016,7 +2022,7 @@ IAdaptable { /** * Validate settings provided by the {@link #getValidator(TaskRepository) validator}, typically the server settings. - * + * * @since 2.0 */ protected void validateSettings() { @@ -2052,7 +2058,7 @@ IAdaptable { StatusManager.getManager().handle( new Status(IStatus.ERROR, TasksUiPlugin.ID_PLUGIN, Messages.AbstractRepositorySettingsPage_Internal_error_validating_repository, e), - StatusManager.SHOW | StatusManager.LOG); + StatusManager.SHOW | StatusManager.LOG); return; } catch (InterruptedException e) { // canceled @@ -2113,7 +2119,7 @@ IAdaptable { * For version 3.11 we change the abstract implementation to a default implementation. The default implementation * creates an {@link Validator} and deligate the work to * {@link AbstractRepositoryConnector#validateRepository(TaskRepository, IProgressMonitor)} - * + * * @since 2.0 */ @@ -2132,7 +2138,7 @@ IAdaptable { /** * Public for testing. - * + * * @since 2.0 */ public abstract class Validator { @@ -2153,7 +2159,7 @@ IAdaptable { /** * Provides an adapter for the {@link IValidatable} interface. - * + * * @since 3.7 * @see IAdaptable#getAdapter(Class) */ @@ -2215,7 +2221,7 @@ IAdaptable { /** * Returns the toolkit used to construct sections and hyperlinks. - * + * * @return the toolkit * @throws IllegalStateException * if the toolkit has not been initialized |