/******************************************************************************* * Copyright (c) 2015 Pivotal, Inc. * 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: * Pivotal, Inc. - initial API and implementation *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash.views; import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.ImageLoader; import org.eclipse.swt.widgets.Display; import org.springframework.ide.eclipse.boot.dash.model.RunState; /** * @author Kris De Volder */ public class RunStateImages { private Map<Object, Image[]> animations = new HashMap<Object, Image[]>(); public synchronized Image[] getAnimation(RunState state) throws Exception { Image[] anim = animations.get(state); if (anim==null) { String url = state.getImageUrl(); animations.put(state, anim = createAnimation(url)); } return anim; } private Image[] createAnimation(String urlString) throws Exception { ImageLoader loader = new ImageLoader(); InputStream input = null; ClassLoader cl = this.getClass().getClassLoader(); // For a png there might be animation frames to load (ImageLoader cannot // pull out frames for an animated png) // Given an input url of the form "foo.png" this will search // for "foo_1.png", "foo_2.png" etc, until it can find no more frames int dot = urlString.lastIndexOf('.'); String prefix = urlString.substring(0, dot); String suffix = urlString.substring(dot+1); List<Image> images = new ArrayList<Image>(); int count = 1; while ((input = cl.getResourceAsStream(prefix+"_"+Integer.toString(count++)+"."+suffix))!=null) { ImageData[] data = loader.load(input); for (ImageData idata: data) { images.add(new Image(Display.getDefault(),idata)); } } if (images.size()!=0) { // Animation frames were found, return them return images.toArray(new Image[images.size()]); } // Just load it in the regular way, this route does cope // with animated gifs input = cl.getResourceAsStream(urlString); try { ImageData[] data = loader.load(input); Image[] imgs = new Image[data.length]; for (int i = 0; i < imgs.length; i++) { imgs[i] = new Image(Display.getDefault(), data[i]); } return imgs; } finally { input.close(); } } public synchronized Image[] getDecoratedImages(final RunState state, final ImageDescriptor descriptor, final int position) throws Exception { Image[] images = getAnimation(state); if (descriptor == null) { return images; } else { Object key = Arrays.<Object>asList(state, descriptor, position); Image[] decoratedImages = animations.get(key); if (decoratedImages == null) { decoratedImages = Arrays.copyOf(images, images.length); for (int i = 0; i < decoratedImages.length; i++) { decoratedImages[i] = new DecorationOverlayIcon(decoratedImages[i], descriptor, IDecoration.BOTTOM_RIGHT).createImage(decoratedImages[i].getDevice()); } animations.put(key, decoratedImages); } return decoratedImages; } } void dispose() { if (animations!=null) { for (Image[] anim : animations.values()) { if (anim!=null) { for (Image image : anim) { image.dispose(); } } } animations = null; } } }