blob: e8eec3534ecb2a388c9922a987b430aa14eb9878 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 Original authors and others.
* 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:
* Original authors and others - initial API and implementation
******************************************************************************/
package org.eclipse.nebula.widgets.nattable.renderer.swt;
import org.eclipse.swt.SWT;
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.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
/**
* This class contains utility methods for drawing graphics
*
* @see <a href="http://java-gui.info/Apress-The.Definitive.Guide.to.SWT.and.JFace/8886final/LiB0095.html">GC snippets</a>
*/
public class GraphicsUtils {
/**
* Draws text vertically (rotates plus or minus 90 degrees). Uses the current
* font, color, and background.
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param string the text to draw
* @param x the x coordinate of the top left corner of the drawing rectangle
* @param y the y coordinate of the top left corner of the drawing rectangle
* @param gc the GC on which to draw the text
* @param style the style (SWT.UP or SWT.DOWN)
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
public static void drawVerticalText(String string, int x, int y, GC gc, int style) {
drawVerticalText(string, x, y, false, false, true, gc, style);
}
/**
* Draws text vertically (rotates plus or minus 90 degrees). Uses the current
* font, color, and background.
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param string the text to draw
* @param x the x coordinate of the top left corner of the drawing rectangle
* @param y the y coordinate of the top left corner of the drawing rectangle
* @param underline set to <code>true</code> to render the text underlined
* @param strikethrough set to <code>true</code> to render the text strikethrough
* @param paintBackground set to <code>false</code> to render the background transparent.
* Needed for example to render the background with an image or gradient with another painter
* so the text drawn here should have no background.
* @param gc the GC on which to draw the text
* @param style the style (SWT.UP or SWT.DOWN)
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
//TODO get style information for underline, strikethrough and paintbackground
//this should be somehow encapsulated in a more clean way so it is hidden from the interface call in IGraphicsContext
public static void drawVerticalText(String string, int x, int y,
boolean underline, boolean strikethrough, boolean paintBackground,
GC gc, int style) {
// Get the current display
Display display = Display.getCurrent();
if (display == null) SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
// Determine string's dimensions
// FontMetrics fm = gc.getFontMetrics();
Point pt = gc.textExtent(string.trim());
// Create an image the same size as the string
Image stringImage = new Image(display, pt.x, pt.y);
// Create a GC so we can draw the image
GC stringGc = new GC(stringImage);
// Set attributes from the original GC to the new GC
stringGc.setAntialias(gc.getAntialias());
stringGc.setTextAntialias(gc.getTextAntialias());
stringGc.setForeground(gc.getForeground());
stringGc.setBackground(gc.getBackground());
stringGc.setFont(gc.getFont());
// Fill the image with the specified background color
// to avoid white spaces if the text does not fill the
// whole image (e.g. on new lines)
stringGc.fillRectangle(0, 0, pt.x, pt.y);
// Draw the text onto the image
stringGc.drawText(string, 0, 0);
//draw underline and/or strikethrough
if (underline || strikethrough) {
//check and draw underline and strikethrough separately so it is possible to combine both
if (underline) {
//y = start y of text + font height
// - half of the font descent so the underline is between the baseline and the bottom
int underlineY = pt.y - (stringGc.getFontMetrics().getDescent() / 2);
stringGc.drawLine(
0,
underlineY,
pt.x,
underlineY);
}
if (strikethrough) {
//y = start y of text + half of font height + ascent so lower case characters are
//also strikethrough
int strikeY = (pt.y / 2) + (stringGc.getFontMetrics().getLeading() / 2);
stringGc.drawLine(
0,
strikeY,
pt.x,
strikeY);
}
}
// Draw the image vertically onto the original GC
drawVerticalImage(stringImage, x, y, paintBackground, gc, style);
// Dispose the new GC
stringGc.dispose();
// Dispose the image
stringImage.dispose();
}
/**
* Draws an image vertically (rotates plus or minus 90 degrees)
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param image the image to draw
* @param x the x coordinate of the top left corner of the drawing rectangle
* @param y the y coordinate of the top left corner of the drawing rectangle
* @param gc the GC on which to draw the image
* @param style the style (SWT.UP or SWT.DOWN)
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
public static void drawVerticalImage(Image image, int x, int y, GC gc, int style) {
drawVerticalImage(image, x, y, true, gc, style);
}
/**
* Draws an image vertically (rotates plus or minus 90 degrees)
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param image the image to draw
* @param x the x coordinate of the top left corner of the drawing rectangle
* @param y the y coordinate of the top left corner of the drawing rectangle
* @param paintBackground set to <code>false</code> to render the background transparent.
* Needed for example to render the background with an image or gradient with another painter
* so the text drawn here should have no background.
* @param gc the GC on which to draw the image
* @param style the style (SWT.UP or SWT.DOWN)
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
public static void drawVerticalImage(Image image, int x, int y, boolean paintBackground, GC gc, int style) {
// Get the current display
Display display = Display.getCurrent();
if (display == null) SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
// Use the image's data to create a rotated image's data
ImageData sd = image.getImageData();
ImageData dd = new ImageData(sd.height, sd.width, sd.depth, sd.palette);
dd.transparentPixel = sd.transparentPixel;
//set the defined backgroundcolor to be transparent
if (!paintBackground) {
dd.transparentPixel = sd.palette.getPixel(gc.getBackground().getRGB());
}
// Determine which way to rotate, depending on up or down
boolean up = (style & SWT.UP) == SWT.UP;
// Run through the horizontal pixels
for (int sx = 0; sx < sd.width; sx++) {
// Run through the vertical pixels
for (int sy = 0; sy < sd.height; sy++) {
// Determine where to move pixel to in destination image data
int dx = up ? sy : sd.height - sy - 1;
int dy = up ? sd.width - sx - 1 : sx;
// Swap the x, y source data to y, x in the destination
dd.setPixel(dx, dy, sd.getPixel(sx, sy));
}
}
// Create the vertical image
Image vertical = new Image(display, dd);
// Draw the vertical image onto the original GC
gc.drawImage(vertical, x, y);
// Dispose the vertical image
vertical.dispose();
}
/**
* Creates an image containing the specified text, rotated either plus or minus
* 90 degrees.
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param text the text to rotate
* @param font the font to use
* @param foreground the color for the text
* @param background the background color
* @param style direction to rotate (up or down)
* @return Image
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
public static Image createRotatedText(String text, Font font, Color foreground,
Color background, int style) {
// Get the current display
Display display = Display.getCurrent();
if (display == null) SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
// Create a GC to calculate font's dimensions
GC gc = new GC(display);
gc.setFont(font);
// Determine string's dimensions
// FontMetrics fm = gc.getFontMetrics();
Point pt = gc.textExtent(text);
// Dispose that gc
gc.dispose();
// Create an image the same size as the string
Image stringImage = new Image(display, pt.x, pt.y);
// Create a gc for the image
gc = new GC(stringImage);
gc.setFont(font);
gc.setForeground(foreground);
gc.setBackground(background);
// Draw the text onto the image
gc.drawText(text, 0, 0);
// Draw the image vertically onto the original GC
Image image = createRotatedImage(stringImage, style);
// Dispose the new GC
gc.dispose();
// Dispose the horizontal image
stringImage.dispose();
// Return the rotated image
return image;
}
/**
* Creates a rotated image (plus or minus 90 degrees)
* <dl>
* <dt><b>Styles: </b></dt>
* <dd>UP, DOWN</dd>
* </dl>
*
* @param image the image to rotate
* @param style direction to rotate (up or down)
* @return Image
* <p>
* Note: Only one of the style UP or DOWN may be specified.
* </p>
*/
public static Image createRotatedImage(Image image, int style) {
// Get the current display
Display display = Display.getCurrent();
if (display == null) SWT.error(SWT.ERROR_THREAD_INVALID_ACCESS);
// Use the image's data to create a rotated image's data
ImageData sd = image.getImageData();
ImageData dd = new ImageData(sd.height, sd.width, sd.depth, sd.palette);
// Determine which way to rotate, depending on up or down
boolean up = (style & SWT.UP) == SWT.UP;
// Run through the horizontal pixels
for (int sx = 0; sx < sd.width; sx++) {
// Run through the vertical pixels
for (int sy = 0; sy < sd.height; sy++) {
// Determine where to move pixel to in destination image data
int dx = up ? sy : sd.height - sy - 1;
int dy = up ? sd.width - sx - 1 : sx;
// Swap the x, y source data to y, x in the destination
dd.setPixel(dx, dy, sd.getPixel(sx, sy));
}
}
// Create the vertical image
return new Image(display, dd);
}
}