package net.sourceforge.pmd.eclipse.ui;
import java.util.HashMap;
import java.util.Map;
import net.sourceforge.pmd.eclipse.plugin.PMDPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
/**
*
* @author br
*
*/
public class ShapePainter {
/** Provides a simple cache for the images. */
private static Map<String, Image> shapes = new HashMap<String, Image>();
private ShapePainter() {}
/**
* Creates an image initialized with the transparent colour with the shape drawn within.
* It will return cached images to avoid creating new images (and using the limited GDI handles
* under Windows).
*/
public static Image newDrawnImage(Display display, int width, int height, Shape shape, RGB transparentColour, RGB fillColour) {
String key = width + "x" + height + " " + shape + " " + transparentColour + " " + fillColour;
if (shapes.containsKey(key)) {
return shapes.get(key);
}
Image image = new Image(display, width, height);
GC gc = new GC(image);
gc.setBackground(PMDPlugin.getDefault().colorFor(transparentColour));
gc.fillRectangle(0, 0, width, height);
gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
gc.setBackground(PMDPlugin.getDefault().colorFor(fillColour));
drawShape(width-1, height-1, shape, gc, 0, 0, null);
ImageData data = image.getImageData();
int clrIndex = data.palette.getPixel(transparentColour);
data.transparentPixel = clrIndex;
Image newImage = new Image(display, data);
image.dispose();
gc.dispose();
shapes.put(key, newImage);
return newImage;
}
public static void disposeAll() {
for (Image i : shapes.values()) {
i.dispose();
}
shapes.clear();
}
public static void drawShape(int width, int height, Shape shapeId, GC gc, int x, int y, String optionalText) {
// TODO implement the following shapes: star, pentagon, hexagon, octagon, doughnut
switch (shapeId) {
case square: {
gc.fillRectangle(x, y, width, height); // fill it
gc.drawRectangle(x, y, width, height); // then the border on top
break;
}
case circle: {
gc.fillArc(x, y, width, height, 0, 360*64);
gc.drawArc(x, y, width, height, 0, 360*64);
break;
}
case domeLeft: {
gc.fillArc(x+width/4, y, width, height, 90, 180);
gc.drawArc(x+width/4, y, width, height, 90, 180);
int threeQuarters = width/2 + width/4;
gc.drawLine(x + threeQuarters, y, x+threeQuarters, y+height);
break;
}
case domeRight: {
gc.fillArc(x-width/4, y, width, height, 270, 180);
gc.drawArc(x-width/4, y, width, height, 270, 180);
gc.drawLine(x + width/4, y, x+width/4, y+height);
break;
}
case pipe: {
gc.fillRectangle(x + (width/4), y, width - (width/2), height);
gc.drawRectangle(x + (width/4), y, width - (width/2), height);
break;
}
// case plus: {
// int xA = x + width/3;
// int xB = x + ((width/3) * 2);
// int yA = y + height/3;
// int yB = y+ ((height/3) * 2);
// int[] points = new int[] { xA,y, xB,y, xB,yA, x+width,yA, x+width,yB, xB,yB, xB,y+height, xA,y+height, xA,yB, x,yB, x,yA, xA,yA };
// gc.fillPolygon(points);
// gc.drawPolygon(points);
// break;
// }
case minus: {
gc.fillRectangle(x, y + (height/4), width, height - (height/2));
gc.drawRectangle(x, y + (height/4), width, height - (height/2));
break;
}
case triangleDown: {
gc.fillPolygon(new int[] {x, y, x+width, y, x+(width/2), y+height});
gc.drawPolygon(new int[] {x, y, x+width, y, x+(width/2), y+height});
break;
}
case triangleUp: {
gc.fillPolygon(new int[] {x, y+height, x+width, y+height, x+(width/2), y});
gc.drawPolygon(new int[] {x, y+height, x+width, y+height, x+(width/2), y});
break;
}
case triangleRight: {
gc.fillPolygon(new int[] {x, y+height, x+width, y+(height/2), x, y});
gc.drawPolygon(new int[] {x, y+height, x+width, y+(height/2), x, y});
break;
}
case triangleLeft: {
gc.fillPolygon(new int[] {x, y+(height/2), x+width, y, x+width, y+height});
gc.drawPolygon(new int[] {x, y+(height/2), x+width, y, x+width, y+height});
break;
}
case triangleNorthEast: {
gc.fillPolygon(new int[] {x, y, x+width, y, x+width, y+height});
gc.drawPolygon(new int[] {x, y, x+width, y, x+width, y+height});
break;
}
case triangleNorthWest: {
gc.fillPolygon(new int[] {x, y, x+width, y, x, y+height});
gc.drawPolygon(new int[] {x, y, x+width, y, x, y+height});
break;
}
case triangleSouthEast: {
gc.fillPolygon(new int[] {x, y, x+width, y+height, x, y+height});
gc.drawPolygon(new int[] {x, y, x+width, y+height, x, y+height});
break;
}
case triangleSouthWest: {
gc.fillPolygon(new int[] {x, y+height, x+width, y+height, x+width, y});
gc.drawPolygon(new int[] {x, y+height, x+width, y+height, x+width, y});
break;
}
case roundedRect: {
gc.fillRoundRectangle(x, y, width, height, width / 2, height / 2);
gc.drawRoundRectangle(x, y, width, height, width / 2, height / 2);
break;
}
case diamond: {
gc.fillPolygon(new int[] {x+(width/2), y, x+width, y+(height/2), x+(width/2), y+height, x, y+(height/2)});
gc.drawPolygon(new int[] {x+(width/2), y, x+width, y+(height/2), x+(width/2), y+height, x, y+(height/2)});
break;
}
default: {
int[] points = shapeId.scaledPointsTo(width, height, x, y, false, true);
if (points.length > 1) {
gc.fillPolygon(points);
gc.drawPolygon(points);
}
}
}
if (optionalText != null) gc.drawString(optionalText, x, y);
}
}