blob: e8dda26015b518fa8c2eb775daa21e4209942a7b [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
*******************************************************************************/
package org.eclipse.ui.internal.forms.widgets;
import java.util.Arrays;
import java.util.HashMap;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
public class FormImages {
private static FormImages instance;
public static FormImages getInstance() {
if (instance == null)
instance = new FormImages();
return instance;
}
private HashMap images;
private HashMap ids;
private FormImages() {
}
private abstract class ImageIdentifier {
Display fDisplay;
RGB[] fRGBs;
int fLength;
ImageIdentifier(Display display, Color[] colors, int length) {
fDisplay = display;
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 ImageIdentifier) {
ImageIdentifier id = (ImageIdentifier)obj;
if (id.fRGBs.length == fRGBs.length) {
boolean result = id.fDisplay.equals(fDisplay) && 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 = fDisplay.hashCode();
for (int i = 0; i < fRGBs.length; i++)
hash = hash * 7 + fRGBs[i].hashCode();
hash = hash * 7 + fLength;
return hash;
}
}
private class SimpleImageIdentifier extends ImageIdentifier{
private int fTheight;
private int fMarginHeight;
SimpleImageIdentifier (Display display, Color color1, Color color2,
int realtheight, int theight, int marginHeight) {
super(display, new Color[] {color1, color2}, realtheight);
fTheight = theight;
fMarginHeight = marginHeight;
}
public boolean equals(Object obj) {
if (obj instanceof SimpleImageIdentifier) {
SimpleImageIdentifier id = (SimpleImageIdentifier) 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;
}
}
private class ComplexImageIdentifier extends ImageIdentifier {
RGB fBgRGB;
boolean fVertical;
int[] fPercents;
public ComplexImageIdentifier(Display display, Color[] colors, int length,
int[] percents, boolean vertical, Color bg) {
super(display, colors, length);
fBgRGB = bg == null ? null : bg.getRGB();
fVertical = vertical;
fPercents = percents;
}
public boolean equals(Object obj) {
if (obj instanceof ComplexImageIdentifier) {
ComplexImageIdentifier id = (ComplexImageIdentifier) 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;
}
}
private class ImageReference {
private Image fImage;
private int fCount;
public ImageReference(Image image) {
fImage = image;
fCount = 1;
}
public Image getImage() {
return fImage;
}
// returns a boolean indicating if all clients of this image are finished
// a true result indicates the underlying image should be disposed
public boolean decCount() {
return --fCount == 0;
}
public void incCount() {
fCount++;
}
}
public Image getGradient(Display display, Color color1, Color color2,
int realtheight, int theight, int marginHeight) {
checkHashMaps();
ImageIdentifier id = new SimpleImageIdentifier(display, color1, color2, realtheight, theight, marginHeight);
ImageReference result = (ImageReference) images.get(id);
if (result != null && !result.getImage().isDisposed()) {
result.incCount();
return result.getImage();
}
Image image = createGradient(display, color1, color2, realtheight, theight, marginHeight);
images.put(id, new ImageReference(image));
ids.put(image, id);
return image;
}
public Image getGradient(Display display, Color[] colors, int[] percents,
int length, boolean vertical, Color bg) {
checkHashMaps();
ImageIdentifier id = new ComplexImageIdentifier(display, colors, length, percents, vertical, bg);
ImageReference result = (ImageReference) images.get(id);
if (result != null && !result.getImage().isDisposed()) {
result.incCount();
return result.getImage();
}
Image image = createGradient(display, colors, percents, length, vertical, bg);
images.put(id, new ImageReference(image));
ids.put(image, id);
return image;
}
public boolean markFinished(Image image) {
checkHashMaps();
ImageIdentifier id = (ImageIdentifier)ids.get(image);
if (id != null) {
ImageReference ref = (ImageReference) images.get(id);
if (ref != null) {
if (ref.decCount()) {
images.remove(id);
ids.remove(ref.getImage());
ref.getImage().dispose();
validateHashMaps();
}
return true;
}
}
// if the image was not found, dispose of it for the caller
image.dispose();
return false;
}
private void checkHashMaps() {
if (images == null)
images = new HashMap();
if (ids == null)
ids = new HashMap();
}
private void validateHashMaps() {
if (images.size() == 0)
images = null;
if (ids.size() == 0)
ids = null;
}
private Image createGradient(Display display, Color color1, Color color2,
int realtheight, int theight, int marginHeight) {
Image image = new Image(display, 1, realtheight);
image.setBackground(color1);
GC gc = new GC(image);
gc.setBackground(color1);
gc.fillRectangle(0, 0, 1, realtheight);
gc.setForeground(color2);
gc.setBackground(color1);
gc.fillGradientRectangle(0, marginHeight + 2, 1, theight - 2, true);
gc.dispose();
return image;
}
private Image createGradient(Display display, Color[] colors, int[] percents,
int length, boolean vertical, Color bg) {
int width = vertical ? 1 : length;
int height = vertical ? length : 1;
Image gradient = new Image(display, Math.max(width, 1), Math
.max(height, 1));
GC gc = new GC(gradient);
drawTextGradient(gc, width, height, colors, percents, vertical, bg);
gc.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] * height / 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);
}
}
}