/******************************************************************************* * Copyright (c) 2006-2007 Nicolas Richeton. * 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 : * Nicolas Richeton (nicolas.richeton@gmail.com) - initial API and implementation *******************************************************************************/ package org.eclipse.nebula.widgets.gallery; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Point; /** * <p> * Base class used to implement a custom gallery item renderer. * </p> * <p> * NOTE: THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT. * </p> * * @author Nicolas Richeton (nicolas.richeton@gmail.com) */ public abstract class AbstractGalleryItemRenderer { /** * Id for decorators located at the bottom right of the item image * * Example : item.setData( AbstractGalleryItemRenderer.OVERLAY_BOTTOM_RIGHT * , <Image or Image[]> ); */ public final static String OVERLAY_BOTTOM_RIGHT = "org.eclipse.nebula.widget.gallery.bottomRightOverlay"; //$NON-NLS-1$ /** * Id for decorators located at the bottom left of the item image * * Example : item.setData( AbstractGalleryItemRenderer.OVERLAY_BOTTOM_RIGHT * , <Image or Image[]> ); */ public final static String OVERLAY_BOTTOM_LEFT = "org.eclipse.nebula.widget.gallery.bottomLeftOverlay"; //$NON-NLS-1$ /** * Id for decorators located at the top right of the item image * * Example : item.setData( AbstractGalleryItemRenderer.OVERLAY_BOTTOM_RIGHT * , <Image or Image[]> ); */ public final static String OVERLAY_TOP_RIGHT = "org.eclipse.nebula.widget.gallery.topRightOverlay"; //$NON-NLS-1$ /** * Id for decorators located at the top left of the item image * * Example : item.setData( AbstractGalleryItemRenderer.OVERLAY_BOTTOM_RIGHT * , <Image or Image[]> ); */ public final static String OVERLAY_TOP_LEFT = "org.eclipse.nebula.widget.gallery.topLeftOverlay"; //$NON-NLS-1$ protected static final String EMPTY_STRING = ""; //$NON-NLS-1$ protected Gallery gallery; Color galleryBackgroundColor, galleryForegroundColor; protected boolean selected; /** * true is the current item is selected * * @return */ public boolean isSelected() { return selected; } public void setSelected(boolean selected) { this.selected = selected; } /** * Draws an item. * * @param gc * @param item * @param index * @param x * @param y * @param width * @param height */ public abstract void draw(GC gc, GalleryItem item, int index, int x, int y, int width, int height); public abstract void dispose(); /** * This method is called before drawing the first item. It may be used to * calculate some values (like font metrics) that will be used for each * item. * * @param gc */ public void preDraw(GC gc) { // Cache gallery color since this method is resource intensive. galleryForegroundColor = gallery.getForeground(); galleryBackgroundColor = gallery.getBackground(); } /** * This method is called after drawing the last item. It may be used to * cleanup and release resources created in preDraw(). * * @param gc */ public void postDraw(GC gc) { galleryForegroundColor = null; galleryBackgroundColor = null; } /** * Get current gallery. * * @return */ public Gallery getGallery() { return gallery; } /** * Set the current gallery. This method is automatically called by * {@link Gallery#setItemRenderer(AbstractGalleryItemRenderer)}. There is * not need to call it from user code. * * @param gallery */ public void setGallery(Gallery gallery) { this.gallery = gallery; } /** * Returns the best size ratio for overlay images. This ensure that all * images can fit without being drawn on top of others. * * @param imageSize * @param overlaySizeTopLeft * @param overlaySizeTopRight * @param overlaySizeBottomLeft * @param overlaySizeBottomRight * @return */ protected double getOverlayRatio(Point imageSize, Point overlaySizeTopLeft, Point overlaySizeTopRight, Point overlaySizeBottomLeft, Point overlaySizeBottomRight) { double ratio = 1; if (overlaySizeTopLeft.x + overlaySizeTopRight.x > imageSize.x) { ratio = Math.min(ratio, (double) imageSize.x / (overlaySizeTopLeft.x + overlaySizeTopRight.x)); } if (overlaySizeBottomLeft.x + overlaySizeBottomRight.x > imageSize.x) { ratio = Math.min(ratio, (double) imageSize.x / (overlaySizeBottomLeft.x + overlaySizeBottomRight.x)); } if (overlaySizeTopLeft.y + overlaySizeBottomLeft.y > imageSize.y) { ratio = Math.min(ratio, (double) imageSize.y / (overlaySizeTopLeft.y + overlaySizeBottomLeft.y)); } if (overlaySizeTopRight.y + overlaySizeBottomRight.y > imageSize.y) { ratio = Math.min(ratio, (double) imageSize.y / (overlaySizeTopRight.y + overlaySizeBottomRight.y)); } return ratio; } /** * Draw image overlays. Overlays are defined with image.setData using the * following keys : * <ul> * <li>org.eclipse.nebula.widget.gallery.bottomLeftOverlay</li> * <li>org.eclipse.nebula.widget.gallery.bottomRightOverlay</li> * <li>org.eclipse.nebula.widget.gallery.topLeftOverlay</li> * <li>org.eclipse.nebula.widget.gallery.topRightOverlay</li> *</ul> * */ protected void drawAllOverlays(GC gc, GalleryItem item, int x, int y, Point imageSize, int xShift, int yShift) { Image[] imagesBottomLeft = getImageOverlay(item, OVERLAY_BOTTOM_LEFT); Image[] imagesBottomRight = getImageOverlay(item, OVERLAY_BOTTOM_RIGHT); Image[] imagesTopLeft = getImageOverlay(item, OVERLAY_TOP_LEFT); Image[] imagesTopRight = getImageOverlay(item, OVERLAY_TOP_RIGHT); Point overlaySizeBottomLeft = getOverlaySize(imagesBottomLeft); Point overlaySizeBottomRight = getOverlaySize(imagesBottomRight); Point overlaySizeTopLeft = getOverlaySize(imagesTopLeft); Point overlaySizeTopRight = getOverlaySize(imagesTopRight); double ratio = getOverlayRatio(imageSize, overlaySizeTopLeft, overlaySizeTopRight, overlaySizeBottomLeft, overlaySizeBottomRight); drawOverlayImages(gc, x + xShift, y + yShift, ratio, imagesTopLeft); drawOverlayImages( gc, (int) (x + xShift + imageSize.x - overlaySizeTopRight.x * ratio), y + yShift, ratio, imagesTopRight); drawOverlayImages(gc, x + xShift, (int) (y + yShift + imageSize.y - overlaySizeBottomLeft.y * ratio), ratio, imagesBottomLeft); drawOverlayImages(gc, (int) (x + xShift + imageSize.x - overlaySizeBottomRight.x * ratio), (int) (y + yShift + imageSize.y - overlaySizeBottomRight.y * ratio), ratio, imagesBottomRight); } /** * Draw overlay images for one corner. * * @param gc * @param x * @param y * @param ratio * @param images */ protected void drawOverlayImages(GC gc, int x, int y, double ratio, Image[] images) { if (images == null) return; int position = 0; for (int i = 0; i < images.length; i++) { Image img = images[i]; gc.drawImage(img, 0, 0, img.getBounds().width, img.getBounds().height, x + position, y, (int) (img .getBounds().width * ratio), (int) (img.getBounds().height * ratio)); position += img.getBounds().width * ratio; } } /** * Return overlay size, summing all images sizes * * @param images * @return */ protected Point getOverlaySize(Image[] images) { if (images == null) return new Point(0, 0); Point result = new Point(0, 0); for (int i = 0; i < images.length; i++) { result.x += images[i].getBounds().width; result.y = Math.max(result.y, images[i].getBounds().height); } return result; } /** * Returns an array of images or null of no overlay was defined for this * image. * * @param item * @param id * @return Image[] or null */ protected Image[] getImageOverlay(GalleryItem item, String id) { Object data = item.getData(id); if (data == null) { return null; } Image[] result = null; if (data instanceof Image) { result = new Image[1]; result[0] = (Image) data; } if (data instanceof Image[]) { result = (Image[]) data; } return result; } /** * Check the GalleryItem, Gallery, and Display in order for the active * background color for the given GalleryItem. * * @param item * @return the background Color to use for this item */ protected Color getBackground(GalleryItem item) { Color backgroundColor = item.background; if (backgroundColor == null) { backgroundColor = item.getParent().getBackground(); } return backgroundColor; } /** * Check the GalleryItem, Gallery, and Display in order for the active * foreground color for the given GalleryItem. * * @param item * @return the foreground Color to use for this item */ protected Color getForeground(GalleryItem item) { Color foregroundColor = item.getForeground(true); if (foregroundColor == null) { foregroundColor = item.getParent().getForeground(); } return foregroundColor; } /** * Check the GalleryItem, Gallery, and Display in order for the active font * for the given GalleryItem. * * @param item * @return the Font to use for this item */ protected Font getFont(GalleryItem item) { Font font = item.getFont(true); if (font == null) { font = item.getParent().getFont(); } return font; } }