/*******************************************************************************
* 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;
}
}