| /******************************************************************************* |
| * Copyright (c) 2011, 2017 BestSolution.at 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: |
| * Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.e4.tools.services.impl; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.annotation.PreDestroy; |
| import javax.inject.Inject; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.e4.tools.services.IResourcePool; |
| import org.eclipse.e4.tools.services.IResourceProviderService; |
| import org.eclipse.e4.tools.services.IResourceService; |
| import org.eclipse.e4.tools.services.ToolsServicesActivator; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Resource; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Display; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.FrameworkUtil; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| |
| public class ResourceService implements IResourceService { |
| private enum Type { |
| IMAGE, FONT, COLOR |
| } |
| |
| static class PooledResource<T extends Resource> implements |
| IPooledResource<T> { |
| private final Display display; |
| private int count; |
| private T resource; |
| private String id; |
| private ResourceService resourceService; |
| |
| PooledResource(Display display, ResourceService resourceService, |
| String id, T resource) { |
| this.display = display; |
| this.id = id; |
| this.count = 1; |
| this.resourceService = resourceService; |
| this.resource = resource; |
| } |
| |
| @Override |
| public String getId() { |
| return id; |
| } |
| |
| @Override |
| public T getResource() { |
| return resource; |
| } |
| |
| @Override |
| public void dispose() { |
| this.count--; |
| if (this.count == 0) { |
| resourceService.removePooledResource(this); |
| if (resource != null) { |
| resource.dispose(); |
| } |
| resource = null; |
| id = null; |
| resourceService = null; |
| } |
| } |
| } |
| |
| public static class ResourcePool implements IDiposeableResourcePool { |
| private IResourceService resourceService; |
| |
| private List<IPooledResource<Image>> pooledImages = new ArrayList<>(); |
| private List<IPooledResource<Font>> pooledFonts = new ArrayList<>(); |
| private List<IPooledResource<Color>> pooledColors = new ArrayList<>(); |
| private final Display display; |
| |
| @Inject |
| public ResourcePool(IResourceService resourceService, Display display) { |
| this.display = display; |
| this.resourceService = resourceService; |
| } |
| |
| @Override |
| public Image getImage(String key) throws CoreException { |
| if (resourceService == null) { |
| throw new CoreException( |
| new Status(IStatus.ERROR, |
| ToolsServicesActivator.PLUGIN_ID, |
| Messages.ResourceService_PoolDisposed)); |
| } |
| IPooledResource<Image> image = null; |
| |
| for (final IPooledResource<Image> img : pooledImages) { |
| if (img.getId().equals(key)) { |
| image = img; |
| } |
| } |
| if (image == null) { |
| image = resourceService.getImage(display, key); |
| pooledImages.add(image); |
| } |
| |
| return image.getResource(); |
| } |
| |
| @Override |
| public Font getFont(String key) throws CoreException { |
| if (resourceService == null) { |
| throw new CoreException( |
| new Status(IStatus.ERROR, |
| ToolsServicesActivator.PLUGIN_ID, |
| Messages.ResourceService_PoolDisposed)); |
| } |
| |
| IPooledResource<Font> font = null; |
| for (final IPooledResource<Font> fon : pooledFonts) { |
| if (fon.getId().equals(key)) { |
| font = fon; |
| } |
| } |
| if (font == null) { |
| font = resourceService.getFont(display, key); |
| pooledFonts.add(font); |
| } |
| return font.getResource(); |
| } |
| |
| @Override |
| public Color getColor(String key) throws CoreException { |
| if (resourceService == null) { |
| throw new CoreException( |
| new Status(IStatus.ERROR, |
| ToolsServicesActivator.PLUGIN_ID, |
| Messages.ResourceService_PoolDisposed)); |
| } |
| IPooledResource<Color> color = null; |
| |
| for (final IPooledResource<Color> col : pooledColors) { |
| if (col.getId().equals(key)) { |
| color = col; |
| } |
| } |
| |
| if (color == null) { |
| color = resourceService.getColor(display, |
| key); |
| pooledColors.add(color); |
| } |
| return color.getResource(); |
| } |
| |
| @Override |
| public Image getImageUnchecked(String key) { |
| try { |
| return getImage(key); |
| } catch (final CoreException e) { |
| return null; |
| } |
| } |
| |
| @Override |
| public Font getFontUnchecked(String key) { |
| try { |
| return getFont(key); |
| } catch (final CoreException e) { |
| return null; |
| } |
| } |
| |
| @Override |
| public Color getColorUnchecked(String key) { |
| try { |
| return getColor(key); |
| } catch (final CoreException e) { |
| return null; |
| } |
| } |
| |
| @Override |
| @PreDestroy |
| public void dispose() { |
| for (final IPooledResource<Image> img : pooledImages) { |
| img.dispose(); |
| } |
| for (final IPooledResource<Font> font : pooledFonts) { |
| font.dispose(); |
| } |
| for (final IPooledResource<Color> col : pooledColors) { |
| col.dispose(); |
| } |
| resourceService = null; |
| pooledImages = null; |
| pooledFonts = null; |
| pooledColors = null; |
| } |
| } |
| |
| static class DisplayPool { |
| private Map<String, PooledResource<Image>> imagePool; |
| private Map<String, PooledResource<Color>> colorPool; |
| private Map<String, PooledResource<Font>> fontPool; |
| |
| public Map<String, PooledResource<Color>> getColorPool() { |
| if (colorPool == null) { |
| colorPool = new HashMap<>(); |
| } |
| return colorPool; |
| } |
| |
| public Map<String, PooledResource<Image>> getImagePool() { |
| if (imagePool == null) { |
| imagePool = new HashMap<>(); |
| } |
| return imagePool; |
| } |
| |
| public Map<String, PooledResource<Font>> getFontPool() { |
| if (fontPool == null) { |
| fontPool = new HashMap<>(); |
| } |
| return fontPool; |
| } |
| } |
| |
| private final Map<Display, DisplayPool> displayPool = new HashMap<>(); |
| // private Map<String, IResourceProviderService> imagekey2providers = new |
| // HashMap<String, IResourceProviderService>(); |
| // private Map<String, IResourceProviderService> fontkey2providers = new |
| // HashMap<String, IResourceProviderService>(); |
| // private Map<String, IResourceProviderService> colorkey2providers = new |
| // HashMap<String, IResourceProviderService>(); |
| private final BundleContext context; |
| |
| public ResourceService() { |
| final Bundle b = FrameworkUtil.getBundle(ResourceService.class); |
| context = b.getBundleContext(); |
| } |
| |
| protected void removePooledResource(PooledResource<?> resource) { |
| if (resource.getResource() instanceof Image) { |
| displayPool.get(resource.display).getImagePool().remove(resource.getId()); |
| } else if (resource.getResource() instanceof Color) { |
| displayPool.get(resource.display).getColorPool().remove(resource.getId()); |
| } else if (resource.getResource() instanceof Font) { |
| displayPool.get(resource.display).getFontPool().remove(resource.getId()); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <R extends Resource> PooledResource<R> loadResource( |
| Display display, String key, Type type) { |
| DisplayPool p = displayPool.get(display); |
| PooledResource<R> resource = null; |
| |
| if (p != null) { |
| if (type == Type.IMAGE) { |
| resource = (PooledResource<R>) p.getImagePool().get(key); |
| } else if (type == Type.COLOR) { |
| resource = (PooledResource<R>) p.getColorPool().get(key); |
| } else { |
| resource = (PooledResource<R>) p.getFontPool().get(key); |
| } |
| } |
| |
| if (resource != null && resource.getResource() != null) { |
| resource.count++; |
| } else { |
| resource = new PooledResource<>(display, this, key, |
| (R) lookupResource(display, key, type)); |
| |
| if (p == null) { |
| p = new DisplayPool(); |
| displayPool.put(display, p); |
| } |
| |
| if (type == Type.IMAGE) { |
| p.getImagePool().put(key, (PooledResource<Image>) resource); |
| } else if (type == Type.COLOR) { |
| p.getColorPool().put(key, (PooledResource<Color>) resource); |
| } else { |
| p.getFontPool().put(key, (PooledResource<Font>) resource); |
| } |
| |
| } |
| |
| return resource; |
| } |
| |
| @SuppressWarnings("unchecked") |
| private <R> R lookupResource(Display display, String key, Type type) { |
| |
| if (type == Type.IMAGE) { |
| final IResourceProviderService provider = lookupOSGI(key); |
| if (provider != null) { |
| return (R) provider.getImage(display, key); |
| } |
| } else if (type == Type.COLOR) { |
| final IResourceProviderService provider = lookupOSGI(key); |
| if (provider != null) { |
| return (R) provider.getColor(display, key); |
| } |
| |
| } else { |
| final IResourceProviderService provider = lookupOSGI(key); |
| if (provider != null) { |
| return (R) provider.getFont(display, key); |
| } |
| } |
| throw new IllegalArgumentException(Messages.ResourceService_NoProvider + key |
| + "'."); //$NON-NLS-1$ |
| } |
| |
| private IResourceProviderService lookupOSGI(String key) { |
| try { |
| final Collection<ServiceReference<IResourceProviderService>> refs = context |
| .getServiceReferences(IResourceProviderService.class, "(" //$NON-NLS-1$ |
| + key + "=*)"); //$NON-NLS-1$ |
| if (!refs.isEmpty()) { |
| final ServiceReference<IResourceProviderService> ref = refs |
| .iterator().next(); |
| return context.getService(ref); |
| } |
| } catch (final InvalidSyntaxException e) { |
| // TODO Auto-generated catch block |
| e.printStackTrace(); |
| } |
| return null; |
| } |
| |
| // public void addProvider(IResourceProviderService provider, |
| // Map<String, String> map) { |
| // for (Entry<String, String> e : map.entrySet()) { |
| // if( e.getKey().startsWith("IMAGE") ) { |
| // imagekey2providers.put(e.getKey(), provider); |
| // } else if( e.getKey().startsWith("FONT") ) { |
| // fontkey2providers.put(e.getKey(), provider); |
| // } else if( e.getKey().startsWith("COLOR") ) { |
| // colorkey2providers.put(e.getKey(), provider); |
| // } |
| // } |
| // } |
| // |
| // public void removeProvider(IResourceProviderService provider, |
| // Map<String, String> map) { |
| // for (Entry<String, String> e : map.entrySet()) { |
| // if( e.getKey().startsWith("IMAGE") ) { |
| // imagekey2providers.remove(e.getKey()); |
| // } else if( e.getKey().startsWith("FONT") ) { |
| // fontkey2providers.remove(e.getKey()); |
| // } else if( e.getKey().startsWith("COLOR") ) { |
| // colorkey2providers.remove(e.getKey()); |
| // } |
| // } |
| // } |
| |
| @Override |
| public PooledResource<Image> getImage(Display display, String key) { |
| return loadResource(display, key, Type.IMAGE); |
| } |
| |
| @Override |
| public PooledResource<Color> getColor(Display display, String key) { |
| return loadResource(display, key, Type.COLOR); |
| } |
| |
| @Override |
| public PooledResource<Font> getFont(Display display, String key) { |
| return loadResource(display, key, Type.FONT); |
| } |
| |
| @Override |
| public IDiposeableResourcePool getResourcePool(Display display) { |
| return new ResourcePool(this, display); |
| } |
| |
| @Override |
| public IResourcePool getControlPool(Control control) { |
| final ResourcePool pool = new ResourcePool(this, control.getDisplay()); |
| control.addDisposeListener(e -> pool.dispose()); |
| return pool; |
| } |
| |
| } |