blob: 830f7de18b9c9e121cc518006f363dd033984151 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2008 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 Corporation - initial API and implementation
* Wang Yizhuo (wangyizhuo@gmail.com) - patch (see Bugzilla #239178)
*******************************************************************************/
package org.eclipse.ui.internal.forms.widgets;
import java.util.Arrays;
import java.util.HashMap;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
public class FormImages {
private static FormImages instance;
public static FormImages getInstance() {
if (instance == null)
instance = new FormImages();
return instance;
}
private LocalResourceManager resources;
private HashMap descriptors;
private FormImages() {
}
private abstract class AbstractImageDescriptor extends ImageDescriptor {
RGB[] fRGBs;
int fLength;
AbstractImageDescriptor(Color[] colors, int length) {
fRGBs = new RGB[colors.length];
for (int i = 0; i < colors.length; i++) {
Color color = colors[i];
fRGBs[i] = color == null ? null : color.getRGB();
}
fLength = length;
}
public boolean equals(Object obj) {
if (obj instanceof AbstractImageDescriptor) {
AbstractImageDescriptor id = (AbstractImageDescriptor)obj;
if (id.fRGBs.length == fRGBs.length) {
boolean result = id.fLength == fLength;
for (int i = 0; i < fRGBs.length && result; i++) {
result = result && id.fRGBs[i].equals(fRGBs[i]);
}
return result;
}
}
return false;
}
public int hashCode() {
int hash = 0;
for (int i = 0; i < fRGBs.length; i++)
hash = hash * 7 + fRGBs[i].hashCode();
hash = hash * 7 + fLength;
return hash;
}
}
private class SimpleImageDescriptor extends AbstractImageDescriptor{
private int fTheight;
private int fMarginHeight;
SimpleImageDescriptor (Color color1, Color color2,
int realtheight, int theight, int marginHeight) {
super(new Color[] {color1, color2}, realtheight);
fTheight = theight;
fMarginHeight = marginHeight;
}
public boolean equals(Object obj) {
if (obj instanceof SimpleImageDescriptor) {
SimpleImageDescriptor id = (SimpleImageDescriptor) obj;
if (super.equals(obj) &&
id.fTheight == fTheight && id.fMarginHeight == fMarginHeight)
return true;
}
return false;
}
public int hashCode() {
int hash = super.hashCode();
hash = hash * 7 + new Integer(fTheight).hashCode();
hash = hash * 7 + new Integer(fMarginHeight).hashCode();
return hash;
}
public ImageData getImageData() {
return null;
}
public Image createImage(boolean returnMissingImageOnError, Device device) {
Image image = new Image(device, 1, fLength);
Color color1 = new Color(device, fRGBs[0]);
Color color2 = new Color(device, fRGBs[1]);
image.setBackground(color1);
GC gc = new GC(image);
gc.setBackground(color1);
gc.fillRectangle(0, 0, 1, fLength);
gc.setForeground(color2);
gc.setBackground(color1);
gc.fillGradientRectangle(0, fMarginHeight + 2, 1, fTheight - 2, true);
gc.dispose();
color1.dispose();
color2.dispose();
return image;
}
}
private class ComplexImageDescriptor extends AbstractImageDescriptor {
RGB fBgRGB;
boolean fVertical;
int[] fPercents;
public ComplexImageDescriptor(Color[] colors, int length,
int[] percents, boolean vertical, Color bg) {
super(colors, length);
fBgRGB = bg == null ? null : bg.getRGB();
fVertical = vertical;
fPercents = percents;
}
public boolean equals(Object obj) {
if (obj instanceof ComplexImageDescriptor) {
ComplexImageDescriptor id = (ComplexImageDescriptor) obj;
if (super.equals(obj) &&
id.fVertical == fVertical && Arrays.equals(id.fPercents, fPercents)) {
if ((id.fBgRGB == null && fBgRGB == null) ||
(id.fBgRGB != null && id.fBgRGB.equals(fBgRGB)))
return true;
// if the only thing that isn't the same is the background color
// still return true if it does not matter (percents add up to 100)
int sum = 0;
for (int i = 0; i < fPercents.length; i++)
sum += fPercents[i];
if (sum >= 100)
return true;
}
}
return false;
}
public int hashCode() {
int hash = super.hashCode();
hash = hash * 7 + new Boolean(fVertical).hashCode();
for (int i = 0; i < fPercents.length; i++)
hash = hash * 7 + new Integer(fPercents[i]).hashCode();
return hash;
}
public ImageData getImageData() {
return null;
}
public Image createImage(boolean returnMissingImageOnError, Device device) {
int width = fVertical ? 1 : fLength;
int height = fVertical ? fLength : 1;
Image gradient = new Image(device, Math.max(width, 1), Math
.max(height, 1));
GC gc = new GC(gradient);
Color[] colors = new Color[fRGBs.length];
for (int i = 0; i < colors.length; i++)
colors[i] = new Color(device, fRGBs[i]);
Color bg = fBgRGB == null ? null : new Color(device, fBgRGB);
drawTextGradient(gc, width, height, colors, fPercents, fVertical, bg);
gc.dispose();
for (int i = 0; i < colors.length; i++)
colors[i].dispose();
if (bg != null)
bg.dispose();
return gradient;
}
private void drawTextGradient(GC gc, int width, int height, Color[] colors,
int[] percents, boolean vertical, Color bg) {
final Color oldBackground = gc.getBackground();
if (colors.length == 1) {
if (colors[0] != null)
gc.setBackground(colors[0]);
gc.fillRectangle(0, 0, width, height);
} else {
final Color oldForeground = gc.getForeground();
Color lastColor = colors[0];
if (lastColor == null)
lastColor = oldBackground;
int pos = 0;
for (int i = 0; i < percents.length; ++i) {
gc.setForeground(lastColor);
lastColor = colors[i + 1];
if (lastColor == null)
lastColor = oldBackground;
gc.setBackground(lastColor);
if (vertical) {
int gradientHeight = percents[i] * height / 100;
gc.fillGradientRectangle(0, pos, width, gradientHeight,
true);
pos += gradientHeight;
} else {
int gradientWidth = percents[i] * width / 100;
gc.fillGradientRectangle(pos, 0, gradientWidth, height,
false);
pos += gradientWidth;
}
}
if (vertical && pos < height) {
if (bg != null)
gc.setBackground(bg);
gc.fillRectangle(0, pos, width, height - pos);
}
if (!vertical && pos < width) {
if (bg != null)
gc.setBackground(bg);
gc.fillRectangle(pos, 0, width - pos, height);
}
gc.setForeground(oldForeground);
}
}
}
public Image getGradient(Color color1, Color color2,
int realtheight, int theight, int marginHeight) {
if (color1 == null || color1.isDisposed() || color2 == null || color2.isDisposed())
return null;
AbstractImageDescriptor desc = new SimpleImageDescriptor(color1, color2, realtheight, theight, marginHeight);
return getGradient(desc);
}
public Image getGradient(Color[] colors, int[] percents,
int length, boolean vertical, Color bg) {
if (colors.length == 0)
return null;
for (int i = 0; i < colors.length; i++)
if (colors[i] == null || colors[i].isDisposed())
return null;
if (bg != null && bg.isDisposed())
return null;
AbstractImageDescriptor desc = new ComplexImageDescriptor(colors, length, percents, vertical, bg);
return getGradient(desc);
}
private synchronized Image getGradient(AbstractImageDescriptor desc) {
checkHashMaps();
Image result = getResourceManager().createImage(desc);
descriptors.put(result, desc);
return result;
}
public synchronized boolean markFinished(Image image) {
checkHashMaps();
AbstractImageDescriptor desc = (AbstractImageDescriptor)descriptors.get(image);
if (desc != null) {
getResourceManager().destroyImage(desc);
if (getResourceManager().find(desc) == null) {
descriptors.remove(image);
validateHashMaps();
}
return true;
}
// if the image was not found, dispose of it for the caller
image.dispose();
return false;
}
private LocalResourceManager getResourceManager() {
if (resources == null)
resources = new LocalResourceManager(JFaceResources.getResources());
return resources;
}
private void checkHashMaps() {
if (descriptors == null)
descriptors = new HashMap();
}
private void validateHashMaps() {
if (descriptors.size() == 0)
descriptors = null;
}
}