/**
* Copyright (c) 2002-2007 IBM Corporation 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:
* IBM - Initial API and implementation
*/
package org.eclipse.emf.edit.ui.provider;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.eclipse.jface.resource.CompositeImageDescriptor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.emf.common.EMFPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.edit.EMFEditPlugin;
import org.eclipse.emf.edit.provider.ComposedImage;
/**
*
*/
public class ExtendedImageRegistry
{
public static final ExtendedImageRegistry INSTANCE = new ExtendedImageRegistry();
public static ExtendedImageRegistry getInstance()
{
return INSTANCE;
}
protected HashMap<Object, Image> table = new HashMap<Object, Image>(10);
public ExtendedImageRegistry()
{
Display display = Display.getCurrent();
hookDisplayDispose(display);
}
public ExtendedImageRegistry(Display display)
{
hookDisplayDispose(display);
}
protected static Object resourceURL =
EMFEditPlugin.INSTANCE.getImage("full/obj16/Resource");
protected static String resourceURLPrefix = resourceURL.toString() + "#";
protected static String itemURLPrefix =
EMFEditPlugin.INSTANCE.getImage("full/obj16/Item").toString() + "#";
protected static String createChildURLPrefix =
EMFEditPlugin.INSTANCE.getImage("full/ctool16/CreateChild").toString() + "#";
public Image getImage(Object object)
{
if (object instanceof Image)
{
return (Image)object;
}
else
{
Image result = table.get(object);
if (result == null)
{
if (object instanceof ImageDescriptor)
{
ImageDescriptor imageDescriptor = (ImageDescriptor)object;
result = imageDescriptor.createImage();
}
else if (object instanceof URL || object instanceof URI)
{
String urlString = object.toString();
ImageDescriptor imageDescriptor = null;
if (urlString.startsWith(resourceURLPrefix))
{
if (EMFPlugin.IS_RESOURCES_BUNDLE_AVAILABLE)
{
imageDescriptor =
PlatformUI.getWorkbench().getEditorRegistry().getImageDescriptor
("dummy." + urlString.substring(resourceURLPrefix.length()));
}
else
{
result = getImage(resourceURL);
}
}
else if (urlString.startsWith(itemURLPrefix))
{
try
{
URL url = new URL(urlString.substring(0, itemURLPrefix.length()));
String key1 = urlString.substring(itemURLPrefix.length());
imageDescriptor = new URLImageDescriptor(url, key1, null);
}
catch (IOException exception)
{
// Ignore
}
}
else if (urlString.startsWith(createChildURLPrefix))
{
try
{
URL url = new URL(urlString.substring(0, createChildURLPrefix.length()));
String key1 = urlString.substring(createChildURLPrefix.length() + 1);
String key2 = null;
int index = key1.indexOf("/");
if (index != -1)
{
key2 = key1.substring(index + 1);
key1 = key1.substring(0, index);
}
imageDescriptor = new URLImageDescriptor(url, key1, key2);
}
catch (IOException exception)
{
// Ignore
}
}
else
{
try
{
imageDescriptor = ImageDescriptor.createFromURL(new URL(urlString));
}
catch (IOException exception)
{
// Ignore
}
}
if (imageDescriptor != null)
{
result = imageDescriptor.createImage();
}
}
else if (object instanceof ComposedImage)
{
ImageDescriptor composedImageDescriptor = new ComposedImageDescriptor((ComposedImage)object);
result = composedImageDescriptor.createImage();
}
if (result != null)
{
table.put(object, result);
}
}
return result;
}
}
public ImageDescriptor getImageDescriptor(Object object)
{
if (object instanceof ImageDescriptor)
{
return (ImageDescriptor)object;
}
else
{
final Image image = getImage(object);
if (image != null)
{
return new ImageWrapperImageDescriptor(image);
}
else
{
return null;
}
}
}
protected void handleDisplayDispose()
{
for (Image image : table.values())
{
image.dispose();
}
table = null;
}
protected void hookDisplayDispose(Display display)
{
display.disposeExec
(new Runnable()
{
public void run()
{
handleDisplayDispose();
}
});
}
}
class ImageWrapperImageDescriptor extends ImageDescriptor
{
protected Image image;
public ImageWrapperImageDescriptor(Image image)
{
this.image = image;
}
@Override
public boolean equals(Object that)
{
return
that instanceof ImageWrapperImageDescriptor &&
((ImageWrapperImageDescriptor)that).image.equals(image);
}
@Override
public int hashCode()
{
return image.hashCode();
}
@Override
public ImageData getImageData()
{
return image.getImageData();
}
}
class ComposedImageDescriptor extends CompositeImageDescriptor
{
protected ComposedImage composedImage;
protected List<ImageData> imageDatas;
public ComposedImageDescriptor(ComposedImage composedImage)
{
this.composedImage = composedImage;
}
@Override
public void drawCompositeImage(int width, int height)
{
ComposedImage.Size size = new ComposedImage.Size();
size.width = width;
size.height = height;
Iterator<ImageData> images = imageDatas.iterator();
for (Iterator<ComposedImage.Point> points = composedImage.getDrawPoints(size).iterator(); points.hasNext(); )
{
ComposedImage.Point point = points.next();
drawImage(images.next(), point.x, point.y);
}
}
@Override
public Point getSize()
{
List<Object> images = composedImage.getImages();
imageDatas = new ArrayList<ImageData>(images.size());
List<ComposedImage.Size> sizes = new ArrayList<ComposedImage.Size>(images.size());
for (Object object : images)
{
Image image = ExtendedImageRegistry.getInstance().getImage(object);
ImageData imageData = image.getImageData();
imageDatas.add(imageData);
ComposedImage.Size size = new ComposedImage.Size();
size.width = imageData.width;
size.height = imageData.height;
sizes.add(size);
}
ComposedImage.Size result = composedImage.getSize(sizes);
return new Point(result.width, result.height);
}
}
class URLImageDescriptor extends ImageDescriptor
{
protected URL url;
protected String key1;
protected String key2;
URLImageDescriptor(URL url, String key1, String key2)
{
this.url = url;
this.key1 = key1;
this.key2 = key2;
}
@Override
public ImageData getImageData()
{
InputStream in = null;
try
{
if (key1 != null)
{
ImageDataSynthesizer imageDataSynthesizer = new ImageDataSynthesizer(url);
in = imageDataSynthesizer.generateGIF(key1, key2);
return new ImageData(in);
}
else
{
in = url.openStream();
}
return new ImageData(in);
}
catch (IOException e)
{
return null;
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
return null;
}
}
}
}
protected InputStream getStream() throws IOException
{
return url.openStream();
}
@Override
public int hashCode()
{
return url.hashCode() | (key1 == null ? 0 : key1.hashCode()) | (key2 == null ? 0 : key2.hashCode());
}
@Override
public boolean equals(Object that)
{
if (that instanceof URLImageDescriptor)
{
URLImageDescriptor otherURLImageDescriptor = (URLImageDescriptor)that;
return
url.equals(otherURLImageDescriptor.url) &&
(key1 == null ? otherURLImageDescriptor.key1 == null : key1.equals(otherURLImageDescriptor.key1)) &&
(key2 == null ? otherURLImageDescriptor.key2 == null : key2.equals(otherURLImageDescriptor.key2));
}
else
{
return false;
}
}
@Override
public String toString()
{
return getClass().getName() + "(" + url + "#" + key1 + "/" + key2 + ")";
}
}
class ImageDataSynthesizer
{
protected URL url;
protected static final int tableOffset1 = 49;
protected static final int tableOffset2 = 25;
public ImageDataSynthesizer(URL url)
{
this.url = url;
}
protected int code(String code)
{
int result = 0;
for (int i = 0; i < code.length(); ++ i)
{
result += code.charAt(i) - 32;
}
return result;
}
public InputStream generateGIF(String key1, String key2)
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try
{
byte [] content = new byte [5000];
int result = getContents(content, url);
// generateColor();
ColorInformation info1 = ColorInformation.getColor(code(key1));
ColorInformation info2 = key2 == null ? null : ColorInformation.getColor(code(key2));
for (int j = 0; j < result; ++j)
{
if (j == tableOffset1 || j == tableOffset1 + 3 || j == tableOffset1 + 6 || j == tableOffset1 + 9)
{
int index = (j - tableOffset1) / 3;
if (!info1.rainbow || info1.which == index - 1)
{
content[j] = info1.scale(info1.red, info1.factor[index]);
}
}
else if (j == tableOffset1 + 1 || j == tableOffset1 + 4 || j == tableOffset1 + 7 || j == tableOffset1 + 10)
{
int index = (j - tableOffset1 - 1) / 3;
if (!info1.rainbow || info1.which == index - 1)
{
content[j] = info1.scale(info1.green, info1.factor[index]);
}
}
else if (j == tableOffset1 + 2 || j == tableOffset1 + 5 || j == tableOffset1 + 8 || j == tableOffset1 + 11)
{
int index = (j - tableOffset1 - 2) / 3;
if (!info1.rainbow || info1.which == index - 1)
{
content[j] = info1.scale(info1.blue, info1.factor[index]);
}
}
if (info2 != null)
{
if (j == tableOffset2 || j == tableOffset2 + 3 || j == tableOffset2 + 6 || j == tableOffset2 + 9)
{
int index = (j - tableOffset2) / 3;
if (!info2.rainbow || info2.which == index - 1)
{
content[j] = info2.scale(info2.red, info2.factor[index]);
}
}
else if (j == tableOffset2 + 1 || j == tableOffset2 + 4 || j == tableOffset2 + 7 || j == tableOffset2 + 10)
{
int index = (j - tableOffset2 - 1) / 3;
if (!info2.rainbow || info2.which == index - 1)
{
content[j] = info2.scale(info2.green, info2.factor[index]);
}
}
else if (j == tableOffset2 + 2 || j == tableOffset2 + 5 || j == tableOffset2 + 8 || j == tableOffset2 + 11)
{
int index = (j - tableOffset2 - 2) / 3;
if (!info2.rainbow || info2.which == index - 1)
{
content[j] = info2.scale(info2.blue, info2.factor[index]);
}
}
}
}
DataOutputStream writer = new DataOutputStream(outputStream);
writer.write(content, 0, result);
writer.close();
}
catch (Exception exception)
{
exception.printStackTrace();
}
return new ByteArrayInputStream(outputStream.toByteArray());
}
protected int getContents(byte [] content, URL gifURL) throws IOException
{
BufferedInputStream bufferedInputStream = new BufferedInputStream(gifURL.openStream());
DataInputStream reader = new DataInputStream(bufferedInputStream);
int result = reader.read(content, 0, content.length);
reader.close();
return result;
}
protected static class ColorInformation
{
public static ColorInformation getColor(int index)
{
index = Math.abs(index) % 61;
while (entries.size() <= index)
{
instance.generateColor();
ColorInformation entry = new ColorInformation();
entry.red = instance.red;
entry.green = instance.green;
entry.blue = instance.blue;
entry.which = instance.which;
entry.factor = new double [] { instance.factor[0], instance.factor[1], instance.factor[2], instance.factor[3] };
entry.rainbow = instance.rainbow;
entries.add(entry);
instance.fixFactor();
}
return entries.get(index);
}
protected static ColorInformation instance = new ColorInformation();
protected static List<ColorInformation> entries = new ArrayList<ColorInformation>(1000);
public int red = 192;
public int green = 64;
public int blue = 64;
public int which = 2;
public int change = 64;
public double [] factor = { 0.35, 0.1, -0.1, -0.3 };
public boolean rainbow;
public byte scale(int value, double factor)
{
if (factor > 0.0)
{
return (byte)(value + (255 - value) * factor);
}
else
{
return (byte)(value + value * factor);
}
}
protected void generateColor()
{
switch (which)
{
case 0:
{
red += change;
if (red <= 64)
{
which = 1;
change = -change;
}
else if (red >= 192)
{
which = 1;
change = -change;
}
break;
}
case 1:
{
green += change;
if (green >= 192)
{
which = 2;
change = -change;
}
else if (green <= 64)
{
which = 2;
change = -change;
}
break;
}
case 2:
{
blue += change;
if (blue >= 192)
{
which = 0;
change = -change;
}
else if (blue <=64)
{
which = 0;
change = -change;
}
break;
}
}
}
protected void fixFactor()
{
if (red == 192 && green == 64 && blue == 64)
{
for (int j = 0; j < factor.length; ++j)
{
factor[j] += 0.3;
}
if (factor[0] >= 1.0)
{
rainbow = true;
for (int j = 0; j < factor.length; ++j)
{
factor[j] -= 0.8;
}
}
}
}
}
}