001: /*******************************************************************************
002: * Copyright (c) 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.forms.widgets;
011:
012: import java.util.Arrays;
013: import java.util.HashMap;
014:
015: import org.eclipse.swt.graphics.Color;
016: import org.eclipse.swt.graphics.GC;
017: import org.eclipse.swt.graphics.Image;
018: import org.eclipse.swt.widgets.Display;
019:
020: public class FormImages {
021: private static FormImages instance;
022:
023: public static FormImages getInstance() {
024: if (instance == null)
025: instance = new FormImages();
026: return instance;
027: }
028:
029: private HashMap images;
030: private HashMap ids;
031:
032: private FormImages() {
033: }
034:
035: private abstract class ImageIdentifier {
036: Display fDisplay;
037: Color[] fColors;
038: int fLength;
039:
040: ImageIdentifier(Display display, Color[] colors, int length) {
041: fDisplay = display;
042: fColors = colors;
043: fLength = length;
044: }
045:
046: public boolean equals(Object obj) {
047: if (obj instanceof ImageIdentifier) {
048: ImageIdentifier id = (ImageIdentifier) obj;
049: if (id.fColors.length == fColors.length) {
050: boolean result = id.fDisplay.equals(fDisplay)
051: && id.fLength == fLength;
052: for (int i = 0; i < fColors.length && result; i++) {
053: result = result
054: && id.fColors[i].equals(fColors[i]);
055: }
056: return result;
057: }
058: }
059: return false;
060: }
061:
062: public int hashCode() {
063: int hash = fDisplay.hashCode();
064: for (int i = 0; i < fColors.length; i++)
065: hash = hash * 7 + fColors[i].hashCode();
066: hash = hash * 7 + fLength;
067: return hash;
068: }
069: }
070:
071: private class SimpleImageIdentifier extends ImageIdentifier {
072: private int fTheight;
073: private int fMarginHeight;
074:
075: SimpleImageIdentifier(Display display, Color color1,
076: Color color2, int realtheight, int theight,
077: int marginHeight) {
078: super (display, new Color[] { color1, color2 }, realtheight);
079: fTheight = theight;
080: fMarginHeight = marginHeight;
081: }
082:
083: public boolean equals(Object obj) {
084: if (obj instanceof SimpleImageIdentifier) {
085: SimpleImageIdentifier id = (SimpleImageIdentifier) obj;
086: if (super .equals(obj) && id.fTheight == fTheight
087: && id.fMarginHeight == fMarginHeight)
088: return true;
089: }
090: return false;
091: }
092:
093: public int hashCode() {
094: int hash = super .hashCode();
095: hash = hash * 7 + new Integer(fTheight).hashCode();
096: hash = hash * 7 + new Integer(fMarginHeight).hashCode();
097: return hash;
098: }
099: }
100:
101: private class ComplexImageIdentifier extends ImageIdentifier {
102: Color fBg;
103: boolean fVertical;
104: int[] fPercents;
105:
106: public ComplexImageIdentifier(Display display, Color[] colors,
107: int length, int[] percents, boolean vertical, Color bg) {
108: super (display, colors, length);
109: fBg = bg;
110: fVertical = vertical;
111: fPercents = percents;
112: }
113:
114: public boolean equals(Object obj) {
115: if (obj instanceof ComplexImageIdentifier) {
116: ComplexImageIdentifier id = (ComplexImageIdentifier) obj;
117: if (super .equals(obj) && id.fVertical == fVertical
118: && Arrays.equals(id.fPercents, fPercents)) {
119: if ((id.fBg == null && fBg == null)
120: || (id.fBg != null && id.fBg.equals(fBg)))
121: return true;
122: // if the only thing that isn't the same is the background color
123: // still return true if it does not matter (percents add up to 100)
124: int sum = 0;
125: for (int i = 0; i < fPercents.length; i++)
126: sum += fPercents[i];
127: if (sum >= 100)
128: return true;
129: }
130: }
131: return false;
132: }
133:
134: public int hashCode() {
135: int hash = super .hashCode();
136: hash = hash * 7 + new Boolean(fVertical).hashCode();
137: for (int i = 0; i < fPercents.length; i++)
138: hash = hash * 7 + new Integer(fPercents[i]).hashCode();
139: return hash;
140: }
141: }
142:
143: private class ImageReference {
144: private Image fImage;
145: private int fCount;
146:
147: public ImageReference(Image image) {
148: fImage = image;
149: fCount = 1;
150: }
151:
152: public Image getImage() {
153: return fImage;
154: }
155:
156: // returns a boolean indicating if all clients of this image are finished
157: // a true result indicates the underlying image should be disposed
158: public boolean decCount() {
159: return --fCount == 0;
160: }
161:
162: public void incCount() {
163: fCount++;
164: }
165: }
166:
167: public Image getGradient(Display display, Color color1,
168: Color color2, int realtheight, int theight, int marginHeight) {
169: checkHashMaps();
170: ImageIdentifier id = new SimpleImageIdentifier(display, color1,
171: color2, realtheight, theight, marginHeight);
172: ImageReference result = (ImageReference) images.get(id);
173: if (result != null && !result.getImage().isDisposed()) {
174: result.incCount();
175: return result.getImage();
176: }
177: Image image = createGradient(display, color1, color2,
178: realtheight, theight, marginHeight);
179: images.put(id, new ImageReference(image));
180: ids.put(image, id);
181: return image;
182: }
183:
184: public Image getGradient(Display display, Color[] colors,
185: int[] percents, int length, boolean vertical, Color bg) {
186: checkHashMaps();
187: ImageIdentifier id = new ComplexImageIdentifier(display,
188: colors, length, percents, vertical, bg);
189: ImageReference result = (ImageReference) images.get(id);
190: if (result != null && !result.getImage().isDisposed()) {
191: result.incCount();
192: return result.getImage();
193: }
194: Image image = createGradient(display, colors, percents, length,
195: vertical, bg);
196: images.put(id, new ImageReference(image));
197: ids.put(image, id);
198: return image;
199: }
200:
201: public boolean markFinished(Image image) {
202: checkHashMaps();
203: ImageIdentifier id = (ImageIdentifier) ids.get(image);
204: if (id != null) {
205: ImageReference ref = (ImageReference) images.get(id);
206: if (ref != null) {
207: if (ref.decCount()) {
208: images.remove(id);
209: ids.remove(ref.getImage());
210: ref.getImage().dispose();
211: validateHashMaps();
212: }
213: return true;
214: }
215: }
216: // if the image was not found, dispose of it for the caller
217: image.dispose();
218: return false;
219: }
220:
221: private void checkHashMaps() {
222: if (images == null)
223: images = new HashMap();
224: if (ids == null)
225: ids = new HashMap();
226: }
227:
228: private void validateHashMaps() {
229: if (images.size() == 0)
230: images = null;
231: if (ids.size() == 0)
232: ids = null;
233: }
234:
235: private Image createGradient(Display display, Color color1,
236: Color color2, int realtheight, int theight, int marginHeight) {
237: Image image = new Image(display, 1, realtheight);
238: image.setBackground(color1);
239: GC gc = new GC(image);
240: gc.setBackground(color1);
241: gc.fillRectangle(0, 0, 1, realtheight);
242: gc.setForeground(color2);
243: gc.setBackground(color1);
244: gc.fillGradientRectangle(0, marginHeight + 2, 1, theight - 2,
245: true);
246: gc.dispose();
247: return image;
248: }
249:
250: private Image createGradient(Display display, Color[] colors,
251: int[] percents, int length, boolean vertical, Color bg) {
252: int width = vertical ? 1 : length;
253: int height = vertical ? length : 1;
254: Image gradient = new Image(display, Math.max(width, 1), Math
255: .max(height, 1));
256: GC gc = new GC(gradient);
257: drawTextGradient(gc, width, height, colors, percents, vertical,
258: bg);
259: gc.dispose();
260: return gradient;
261: }
262:
263: private void drawTextGradient(GC gc, int width, int height,
264: Color[] colors, int[] percents, boolean vertical, Color bg) {
265: final Color oldBackground = gc.getBackground();
266: if (colors.length == 1) {
267: if (colors[0] != null)
268: gc.setBackground(colors[0]);
269: gc.fillRectangle(0, 0, width, height);
270: } else {
271: final Color oldForeground = gc.getForeground();
272: Color lastColor = colors[0];
273: if (lastColor == null)
274: lastColor = oldBackground;
275: int pos = 0;
276: for (int i = 0; i < percents.length; ++i) {
277: gc.setForeground(lastColor);
278: lastColor = colors[i + 1];
279: if (lastColor == null)
280: lastColor = oldBackground;
281: gc.setBackground(lastColor);
282: if (vertical) {
283: final int gradientHeight = (percents[i] * height / 100)
284: - pos;
285: gc.fillGradientRectangle(0, pos, width,
286: gradientHeight, true);
287: pos += gradientHeight;
288: } else {
289: final int gradientWidth = (percents[i] * width / 100)
290: - pos;
291: gc.fillGradientRectangle(pos, 0, gradientWidth,
292: height, false);
293: pos += gradientWidth;
294: }
295: }
296: if (vertical && pos < height) {
297: gc.setBackground(bg);
298: gc.fillRectangle(0, pos, width, height - pos);
299: }
300: if (!vertical && pos < width) {
301: gc.setBackground(bg);
302: gc.fillRectangle(pos, 0, width - pos, height);
303: }
304: gc.setForeground(oldForeground);
305: }
306: }
307: }
|