001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2006 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: Message.java 3512 2006-12-08 05:52:03Z yling $
023: */
024: package com.bostechcorp.cbesb.ui.util.resource;
025:
026: import java.io.BufferedInputStream;
027: import java.io.FileInputStream;
028: import java.io.InputStream;
029: import java.util.HashMap;
030: import java.util.Iterator;
031:
032: import org.eclipse.swt.SWT;
033: import org.eclipse.swt.graphics.Color;
034: import org.eclipse.swt.graphics.Cursor;
035: import org.eclipse.swt.graphics.Font;
036: import org.eclipse.swt.graphics.FontData;
037: import org.eclipse.swt.graphics.GC;
038: import org.eclipse.swt.graphics.Image;
039: import org.eclipse.swt.graphics.ImageData;
040: import org.eclipse.swt.graphics.Point;
041: import org.eclipse.swt.graphics.RGB;
042: import org.eclipse.swt.graphics.Rectangle;
043: import org.eclipse.swt.widgets.Canvas;
044: import org.eclipse.swt.widgets.Control;
045: import org.eclipse.swt.widgets.CoolBar;
046: import org.eclipse.swt.widgets.CoolItem;
047: import org.eclipse.swt.widgets.Display;
048:
049: public class SWTResourceManager {
050:
051: /**
052: * Dispose of cached objects and their underlying OS resources. This should
053: * only be called when the cached objects are no longer needed (e.g. on
054: * application shutdown)
055: */
056: public static void dispose() {
057: disposeColors();
058: disposeFonts();
059: disposeImages();
060: disposeCursors();
061: }
062:
063: // ////////////////////////////
064: // Color support
065: // ////////////////////////////
066:
067: /**
068: * Maps RGB values to colors
069: */
070: private static HashMap<RGB, Color> m_ColorMap = new HashMap<RGB, Color>();
071:
072: /**
073: * Returns the system color matching the specific ID
074: *
075: * @param systemColorID
076: * int The ID value for the color
077: * @return Color The system color matching the specific ID
078: */
079: public static Color getColor(int systemColorID) {
080: Display display = Display.getCurrent();
081: return display.getSystemColor(systemColorID);
082: }
083:
084: /**
085: * Returns a color given its red, green and blue component values
086: *
087: * @param r
088: * int The red component of the color
089: * @param g
090: * int The green component of the color
091: * @param b
092: * int The blue component of the color
093: * @return Color The color matching the given red, green and blue componet
094: * values
095: */
096: public static Color getColor(int r, int g, int b) {
097: return getColor(new RGB(r, g, b));
098: }
099:
100: /**
101: * Returns a color given its RGB value
102: *
103: * @param rgb
104: * RGB The RGB value of the color
105: * @return Color The color matching the RGB value
106: */
107: public static Color getColor(RGB rgb) {
108: Color color = m_ColorMap.get(rgb);
109: if (color == null) {
110: Display display = Display.getCurrent();
111: color = new Color(display, rgb);
112: m_ColorMap.put(rgb, color);
113: }
114: return color;
115: }
116:
117: /**
118: * Dispose of all the cached colors
119: */
120: public static void disposeColors() {
121: for (Iterator iter = m_ColorMap.values().iterator(); iter
122: .hasNext();)
123: ((Color) iter.next()).dispose();
124: m_ColorMap.clear();
125: }
126:
127: // ////////////////////////////
128: // Image support
129: // ////////////////////////////
130:
131: /**
132: * Maps image names to images
133: */
134: private static HashMap<String, Image> m_ClassImageMap = new HashMap<String, Image>();
135:
136: /**
137: * Maps images to image decorators
138: */
139: private static HashMap<Image, HashMap<Image, Image>> m_ImageToDecoratorMap = new HashMap<Image, HashMap<Image, Image>>();
140:
141: /**
142: * Returns an image encoded by the specified input stream
143: *
144: * @param is
145: * InputStream The input stream encoding the image data
146: * @return Image The image encoded by the specified input stream
147: */
148: protected static Image getImage(InputStream is) {
149: Display display = Display.getCurrent();
150: ImageData data = new ImageData(is);
151: if (data.transparentPixel > 0)
152: return new Image(display, data, data.getTransparencyMask());
153: return new Image(display, data);
154: }
155:
156: /**
157: * Returns an image stored in the file at the specified path
158: *
159: * @param path
160: * String The path to the image file
161: * @return Image The image stored in the file at the specified path
162: */
163: public static Image getImage(String path) {
164: return getImage("default", path); //$NON-NLS-1$
165: }
166:
167: /**
168: * Returns an image stored in the file at the specified path
169: *
170: * @param section
171: * The section to which belongs specified image
172: * @param path
173: * String The path to the image file
174: * @return Image The image stored in the file at the specified path
175: */
176: public static Image getImage(String section, String path) {
177: String key = section + '|' + SWTResourceManager.class.getName()
178: + '|' + path;
179: Image image = m_ClassImageMap.get(key);
180: if (image == null) {
181: try {
182: FileInputStream fis = new FileInputStream(path);
183: image = getImage(fis);
184: m_ClassImageMap.put(key, image);
185: fis.close();
186: } catch (Exception e) {
187: image = getMissingImage();
188: m_ClassImageMap.put(key, image);
189: }
190: }
191: return image;
192: }
193:
194: /**
195: * Returns an image stored in the file at the specified path relative to the
196: * specified class
197: *
198: * @param clazz
199: * Class The class relative to which to find the image
200: * @param path
201: * String The path to the image file
202: * @return Image The image stored in the file at the specified path
203: */
204: public static Image getImage(Class clazz, String path) {
205: String key = clazz.getName() + '|' + path;
206: Image image = m_ClassImageMap.get(key);
207: if (image == null) {
208: try {
209: if (path.length() > 0 && path.charAt(0) == '/') {
210: String newPath = path.substring(1, path.length());
211: image = getImage(new BufferedInputStream(clazz
212: .getClassLoader().getResourceAsStream(
213: newPath)));
214: } else {
215: image = getImage(clazz.getResourceAsStream(path));
216: }
217: m_ClassImageMap.put(key, image);
218: } catch (Exception e) {
219: image = getMissingImage();
220: m_ClassImageMap.put(key, image);
221: }
222: }
223: return image;
224: }
225:
226: private static final int MISSING_IMAGE_SIZE = 10;
227:
228: private static Image getMissingImage() {
229: Image image = new Image(Display.getCurrent(),
230: MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
231: //
232: GC gc = new GC(image);
233: gc.setBackground(getColor(SWT.COLOR_RED));
234: gc.fillRectangle(0, 0, MISSING_IMAGE_SIZE, MISSING_IMAGE_SIZE);
235: gc.dispose();
236: //
237: return image;
238: }
239:
240: /**
241: * Style constant for placing decorator image in top left corner of base
242: * image.
243: */
244: public static final int TOP_LEFT = 1;
245:
246: /**
247: * Style constant for placing decorator image in top right corner of base
248: * image.
249: */
250: public static final int TOP_RIGHT = 2;
251:
252: /**
253: * Style constant for placing decorator image in bottom left corner of base
254: * image.
255: */
256: public static final int BOTTOM_LEFT = 3;
257:
258: /**
259: * Style constant for placing decorator image in bottom right corner of base
260: * image.
261: */
262: public static final int BOTTOM_RIGHT = 4;
263:
264: /**
265: * Returns an image composed of a base image decorated by another image
266: *
267: * @param baseImage
268: * Image The base image that should be decorated
269: * @param decorator
270: * Image The image to decorate the base image
271: * @return Image The resulting decorated image
272: */
273: public static Image decorateImage(Image baseImage, Image decorator) {
274: return decorateImage(baseImage, decorator, BOTTOM_RIGHT);
275: }
276:
277: /**
278: * Returns an image composed of a base image decorated by another image
279: *
280: * @param baseImage
281: * Image The base image that should be decorated
282: * @param decorator
283: * Image The image to decorate the base image
284: * @param corner
285: * The corner to place decorator image
286: * @return Image The resulting decorated image
287: */
288: public static Image decorateImage(Image baseImage, Image decorator,
289: int corner) {
290: HashMap<Image, Image> decoratedMap = m_ImageToDecoratorMap
291: .get(baseImage);
292: if (decoratedMap == null) {
293: decoratedMap = new HashMap<Image, Image>();
294: m_ImageToDecoratorMap.put(baseImage, decoratedMap);
295: }
296: Image result = decoratedMap.get(decorator);
297: if (result == null) {
298: Rectangle bid = baseImage.getBounds();
299: Rectangle did = decorator.getBounds();
300: result = new Image(Display.getCurrent(), bid.width,
301: bid.height);
302: GC gc = new GC(result);
303: gc.drawImage(baseImage, 0, 0);
304: //
305: if (corner == TOP_LEFT) {
306: gc.drawImage(decorator, 0, 0);
307: } else if (corner == TOP_RIGHT) {
308: gc.drawImage(decorator, bid.width - did.width - 1, 0);
309: } else if (corner == BOTTOM_LEFT) {
310: gc.drawImage(decorator, 0, bid.height - did.height - 1);
311: } else if (corner == BOTTOM_RIGHT) {
312: gc.drawImage(decorator, bid.width - did.width - 1,
313: bid.height - did.height - 1);
314: }
315: //
316: gc.dispose();
317: decoratedMap.put(decorator, result);
318: }
319: return result;
320: }
321:
322: /**
323: * Dispose all of the cached images
324: */
325: public static void disposeImages() {
326: for (Iterator I = m_ClassImageMap.values().iterator(); I
327: .hasNext();)
328: ((Image) I.next()).dispose();
329: m_ClassImageMap.clear();
330: //
331: for (Iterator I = m_ImageToDecoratorMap.values().iterator(); I
332: .hasNext();) {
333: HashMap decoratedMap = (HashMap) I.next();
334: for (Iterator J = decoratedMap.values().iterator(); J
335: .hasNext();) {
336: Image image = (Image) J.next();
337: image.dispose();
338: }
339: }
340: }
341:
342: /**
343: * Dispose cached images in specified section
344: *
345: * @param section
346: * the section do dispose
347: */
348: public static void disposeImages(String section) {
349: for (Iterator I = m_ClassImageMap.keySet().iterator(); I
350: .hasNext();) {
351: String key = (String) I.next();
352: if (!key.startsWith(section + '|'))
353: continue;
354: Image image = m_ClassImageMap.get(key);
355: image.dispose();
356: I.remove();
357: }
358: }
359:
360: // ////////////////////////////
361: // Font support
362: // ////////////////////////////
363:
364: /**
365: * Maps font names to fonts
366: */
367: private static HashMap<String, Font> m_FontMap = new HashMap<String, Font>();
368:
369: /**
370: * Maps fonts to their bold versions
371: */
372: private static HashMap<Font, Font> m_FontToBoldFontMap = new HashMap<Font, Font>();
373:
374: /**
375: * Returns a font based on its name, height and style
376: *
377: * @param name
378: * String The name of the font
379: * @param height
380: * int The height of the font
381: * @param style
382: * int The style of the font
383: * @return Font The font matching the name, height and style
384: */
385: public static Font getFont(String name, int height, int style) {
386: return getFont(name, height, style, false, false);
387: }
388:
389: /**
390: * Returns a font based on its name, height and style. Windows-specific
391: * strikeout and underline flags are also supported.
392: *
393: * @param name
394: * String The name of the font
395: * @param size
396: * int The size of the font
397: * @param style
398: * int The style of the font
399: * @param strikeout
400: * boolean The strikeout flag (warning: Windows only)
401: * @param underline
402: * boolean The underline flag (warning: Windows only)
403: * @return Font The font matching the name, height, style, strikeout and
404: * underline
405: */
406: public static Font getFont(String name, int size, int style,
407: boolean strikeout, boolean underline) {
408: String fontName = name + '|' + size + '|' + style + '|'
409: + strikeout + '|' + underline;
410: Font font = m_FontMap.get(fontName);
411: if (font == null) {
412: FontData fontData = new FontData(name, size, style);
413: if (strikeout || underline) {
414: try {
415: Class logFontClass = Class
416: .forName("org.eclipse.swt.internal.win32.LOGFONT"); //$NON-NLS-1$
417: Object logFont = FontData.class
418: .getField("data").get(fontData); //$NON-NLS-1$
419: if (logFont != null && logFontClass != null) {
420: if (strikeout) {
421: logFontClass
422: .getField("lfStrikeOut").set(logFont, new Byte((byte) 1)); //$NON-NLS-1$
423: }
424: if (underline) {
425: logFontClass
426: .getField("lfUnderline").set(logFont, new Byte((byte) 1)); //$NON-NLS-1$
427: }
428: }
429: } catch (Throwable e) {
430: //TODO remove syserr
431: System.err
432: .println("Unable to set underline or strikeout" + " (probably on a non-Windows platform). " + e); //$NON-NLS-1$ //$NON-NLS-2$
433: }
434: }
435: font = new Font(Display.getCurrent(), fontData);
436: m_FontMap.put(fontName, font);
437: }
438: return font;
439: }
440:
441: /**
442: * Return a bold version of the give font
443: *
444: * @param baseFont
445: * Font The font for whoch a bold version is desired
446: * @return Font The bold version of the give font
447: */
448: public static Font getBoldFont(Font baseFont) {
449: Font font = m_FontToBoldFontMap.get(baseFont);
450: if (font == null) {
451: FontData fontDatas[] = baseFont.getFontData();
452: FontData data = fontDatas[0];
453: font = new Font(Display.getCurrent(), data.getName(), data
454: .getHeight(), SWT.BOLD);
455: m_FontToBoldFontMap.put(baseFont, font);
456: }
457: return font;
458: }
459:
460: /**
461: * Dispose all of the cached fonts
462: */
463: public static void disposeFonts() {
464: for (Iterator iter = m_FontMap.values().iterator(); iter
465: .hasNext();)
466: ((Font) iter.next()).dispose();
467: m_FontMap.clear();
468: }
469:
470: // ////////////////////////////
471: // CoolBar support
472: // ////////////////////////////
473:
474: /**
475: * Fix the layout of the specified CoolBar
476: *
477: * @param bar
478: * CoolBar The CoolBar that shgoud be fixed
479: */
480: public static void fixCoolBarSize(CoolBar bar) {
481: CoolItem[] items = bar.getItems();
482: // ensure that each item has control (at least empty one)
483: for (int i = 0; i < items.length; i++) {
484: CoolItem item = items[i];
485: if (item.getControl() == null)
486: item.setControl(new Canvas(bar, SWT.NONE) {
487: @Override
488: public Point computeSize(int wHint, int hHint,
489: boolean changed) {
490: return new Point(20, 20);
491: }
492: });
493: }
494: // compute size for each item
495: for (int i = 0; i < items.length; i++) {
496: CoolItem item = items[i];
497: Control control = item.getControl();
498: control.pack();
499: Point size = control.getSize();
500: item.setSize(item.computeSize(size.x, size.y));
501: }
502: }
503:
504: // ////////////////////////////
505: // Cursor support
506: // ////////////////////////////
507:
508: /**
509: * Maps IDs to cursors
510: */
511: private static HashMap<Integer, Cursor> m_IdToCursorMap = new HashMap<Integer, Cursor>();
512:
513: /**
514: * Returns the system cursor matching the specific ID
515: *
516: * @param id
517: * int The ID value for the cursor
518: * @return Cursor The system cursor matching the specific ID
519: */
520: public static Cursor getCursor(int id) {
521: Integer key = new Integer(id);
522: Cursor cursor = m_IdToCursorMap.get(key);
523: if (cursor == null) {
524: cursor = new Cursor(Display.getDefault(), id);
525: m_IdToCursorMap.put(key, cursor);
526: }
527: return cursor;
528: }
529:
530: /**
531: * Dispose all of the cached cursors
532: */
533: public static void disposeCursors() {
534: for (Iterator iter = m_IdToCursorMap.values().iterator(); iter
535: .hasNext();)
536: ((Cursor) iter.next()).dispose();
537: m_IdToCursorMap.clear();
538: }
539: }
|