summaryrefslogtreecommitdiff
path: root/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java')
-rw-r--r--propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java337
1 files changed, 337 insertions, 0 deletions
diff --git a/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java b/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java
new file mode 100644
index 0000000..f7cc09d
--- /dev/null
+++ b/propertysheet/src/org/eclipse/wb/internal/core/utils/ui/DrawUtils.java
@@ -0,0 +1,337 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Google, Inc.
+ * 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:
+ * Google, Inc. - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.wb.internal.core.utils.ui;
+
+import com.google.common.io.Closeables;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+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.graphics.Rectangle;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.wb.draw2d.IColorConstants;
+
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Utilities for drawing on {@link GC}.
+ *
+ * @author scheglov_ke
+ * @coverage core.ui
+ */
+public class DrawUtils {
+ private static final String DOTS = "...";
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Drawing
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /**
+ * Draws given text clipped horizontally and centered vertically.
+ */
+ public static final void drawStringCV(GC gc, String text, int x, int y, int width, int height) {
+ Rectangle oldClipping = gc.getClipping();
+ try {
+ gc.setClipping(new Rectangle(x, y, width, height));
+ //
+ int textStartY = y + (height - gc.getFontMetrics().getHeight()) / 2;
+ gc.drawString(clipString(gc, text, width), x, textStartY, true);
+ } finally {
+ gc.setClipping(oldClipping);
+ }
+ }
+
+ /**
+ * Draws given text clipped or centered horizontally and centered vertically.
+ */
+ public static final void drawStringCHCV(GC gc, String text, int x, int y, int width, int height) {
+ int textStartY = y + (height - gc.getFontMetrics().getHeight()) / 2;
+ Point textSize = gc.stringExtent(text);
+ //
+ if (textSize.x > width) {
+ gc.drawString(clipString(gc, text, width), x, textStartY);
+ } else {
+ gc.drawString(text, x + (width - textSize.x) / 2, textStartY);
+ }
+ }
+
+ /**
+ * Draws image at given <code>x</code> and centered vertically.
+ */
+ public static final void drawImageCV(GC gc, Image image, int x, int y, int height) {
+ if (image != null) {
+ Rectangle imageBounds = image.getBounds();
+ gc.drawImage(image, x, y + (height - imageBounds.height) / 2);
+ }
+ }
+
+ /**
+ * Draws image at given <code>x</code> and centered vertically.
+ */
+ public static final void drawImageCHCV(GC gc, Image image, int x, int y, int width, int height) {
+ if (image != null) {
+ Rectangle imageBounds = image.getBounds();
+ int centerX = (width - imageBounds.width) / 2;
+ int centerY = y + (height - imageBounds.height) / 2;
+ gc.drawImage(image, x + centerX, centerY);
+ }
+ }
+
+ /**
+ * Draws {@link Image} on {@link GC} centered in given {@link Rectangle}. If {@link Image} is
+ * bigger that {@link Rectangle}, {@link Image} will be scaled down as needed with keeping
+ * proportions.
+ */
+ public static void drawScaledImage(GC gc, Image image, Rectangle targetRectangle) {
+ int imageWidth = image.getBounds().width;
+ int imageHeight = image.getBounds().height;
+ // prepare scaled image size
+ int newImageWidth;
+ int newImageHeight;
+ if (imageWidth <= targetRectangle.width && imageHeight <= targetRectangle.height) {
+ newImageWidth = imageWidth;
+ newImageHeight = imageHeight;
+ } else {
+ // prepare minimal scale
+ double k;
+ {
+ double k_w = targetRectangle.width / (double) imageWidth;
+ double k_h = targetRectangle.height / (double) imageHeight;
+ k = Math.min(k_w, k_h);
+ }
+ // calculate scaled image size
+ newImageWidth = (int) (imageWidth * k);
+ newImageHeight = (int) (imageHeight * k);
+ }
+ // draw image centered in target rectangle
+ int destX = targetRectangle.x + (targetRectangle.width - newImageWidth) / 2;
+ int destY = targetRectangle.y + (targetRectangle.height - newImageHeight) / 2;
+ gc.drawImage(image, 0, 0, imageWidth, imageHeight, destX, destY, newImageWidth, newImageHeight);
+ }
+
+ /**
+ * @return the string clipped to have width less than given. Clipping is done as trailing "...".
+ */
+ public static String clipString(GC gc, String text, int width) {
+ if (width <= 0) {
+ return "";
+ }
+ // check if text already fits in given width
+ if (gc.stringExtent(text).x <= width) {
+ return text;
+ }
+ // use average count of characters as base
+ int count = Math.min(width / gc.getFontMetrics().getAverageCharWidth(), text.length());
+ if (gc.stringExtent(text.substring(0, count) + DOTS).x > width) {
+ while (count > 0 && gc.stringExtent(text.substring(0, count) + DOTS).x > width) {
+ count--;
+ }
+ } else {
+ while (count < text.length() - 1
+ && gc.stringExtent(text.substring(0, count + 1) + DOTS).x < width) {
+ count++;
+ }
+ }
+ return text.substring(0, count) + DOTS;
+ }
+
+ /**
+ * Draws {@link String} in rectangle, wraps at any character (not by words).
+ */
+ public static void drawTextWrap(GC gc, String text, int x, int y, int width, int height) {
+ int y_ = y;
+ int x_ = x;
+ int lineHeight = 0;
+ for (int i = 0; i < text.length(); i++) {
+ String c = text.substring(i, i + 1);
+ Point extent = gc.stringExtent(c);
+ if (x_ + extent.x > x + width) {
+ y_ += lineHeight;
+ if (y_ > y + height) {
+ return;
+ }
+ x_ = x;
+ }
+ gc.drawText(c, x_, y_);
+ x_ += extent.x;
+ lineHeight = Math.max(lineHeight, extent.y);
+ }
+ }
+
+ /**
+ * Draws 3D highlight rectangle.
+ */
+ public static void drawHighlightRectangle(GC gc, int x, int y, int width, int height) {
+ int right = x + width - 1;
+ int bottom = y + height - 1;
+ //
+ Color oldForeground = gc.getForeground();
+ try {
+ gc.setForeground(IColorConstants.buttonLightest);
+ gc.drawLine(x, y, right, y);
+ gc.drawLine(x, y, x, bottom);
+ //
+ gc.setForeground(IColorConstants.buttonDarker);
+ gc.drawLine(right, y, right, bottom);
+ gc.drawLine(x, bottom, right, bottom);
+ } finally {
+ gc.setForeground(oldForeground);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Images
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /**
+ * @return the {@link Image} loaded relative to given {@link Class}.
+ */
+ public static Image loadImage(Class<?> clazz, String path) {
+ try {
+ URL resource = clazz.getResource(path);
+ if (resource != null) {
+ InputStream stream = resource.openStream();
+ try {
+ return new Image(null, stream);
+ } finally {
+ Closeables.closeQuietly(stream);
+ }
+ }
+ } catch (Throwable e) {
+ }
+ return null;
+ }
+
+ /**
+ * @return the thumbnail {@link Image} of required size for given "big" {@link Image}, centered or
+ * scaled down.
+ */
+ public static Image getThubmnail(Image image,
+ int minWidth,
+ int minHeight,
+ int maxWidth,
+ int maxHeight) {
+ Rectangle imageBounds = image.getBounds();
+ int imageWidth = imageBounds.width;
+ int imageHeight = imageBounds.height;
+ if (imageWidth < minWidth && imageHeight < minHeight) {
+ // create "thumbnail" Image with required size
+ Image thumbnail = new Image(null, minWidth, minHeight);
+ GC gc = new GC(thumbnail);
+ try {
+ drawImageCHCV(gc, image, 0, 0, minWidth, minHeight);
+ } finally {
+ gc.dispose();
+ }
+ // recreate "thumbnail" Image with transparent pixel
+ try {
+ ImageData thumbnailData = thumbnail.getImageData();
+ thumbnailData.transparentPixel = thumbnailData.getPixel(0, 0);
+ return new Image(null, thumbnailData);
+ } finally {
+ thumbnail.dispose();
+ }
+ } else if (imageWidth <= maxWidth && imageHeight <= maxHeight) {
+ return new Image(null, image, SWT.IMAGE_COPY);
+ } else {
+ double kX = (double) maxWidth / imageWidth;
+ double kY = (double) maxHeight / imageHeight;
+ double k = Math.max(kX, kY);
+ int dWidth = (int) (imageWidth * k);
+ int dHeight = (int) (imageHeight * k);
+ ImageData scaledImageData = image.getImageData().scaledTo(dWidth, dHeight);
+ return new Image(null, scaledImageData);
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Colors
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /**
+ * @return new {@link Color} based on given {@link Color} and shifted on given value to make it
+ * darker or lighter.
+ */
+ public static Color getShiftedColor(Color color, int delta) {
+ int r = Math.max(0, Math.min(color.getRed() + delta, 255));
+ int g = Math.max(0, Math.min(color.getGreen() + delta, 255));
+ int b = Math.max(0, Math.min(color.getBlue() + delta, 255));
+ return new Color(color.getDevice(), r, g, b);
+ }
+
+ /**
+ * @return <code>true</code> if the given <code>color</code> is dark.
+ */
+ public static boolean isDarkColor(Color c) {
+ int value =
+ (int) Math.sqrt(c.getRed()
+ * c.getRed()
+ * .241
+ + c.getGreen()
+ * c.getGreen()
+ * .691
+ + c.getBlue()
+ * c.getBlue()
+ * .068);
+ return value < 130;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ //
+ // Fonts
+ //
+ ////////////////////////////////////////////////////////////////////////////
+ /**
+ * @return the bold version of given {@link Font}.
+ */
+ public static Font getBoldFont(Font baseFont) {
+ FontData[] boldData = getModifiedFontData(baseFont, SWT.BOLD);
+ return new Font(Display.getCurrent(), boldData);
+ }
+
+ /**
+ * @return the italic version of given {@link Font}.
+ */
+ public static Font getBoldItalicFont(Font baseFont) {
+ FontData[] boldData = getModifiedFontData(baseFont, SWT.BOLD | SWT.ITALIC);
+ return new Font(Display.getCurrent(), boldData);
+ }
+
+ /**
+ * @return the italic version of given {@link Font}.
+ */
+ public static Font getItalicFont(Font baseFont) {
+ FontData[] boldData = getModifiedFontData(baseFont, SWT.ITALIC);
+ return new Font(Display.getCurrent(), boldData);
+ }
+
+ /**
+ * @return the array of {@link FontData} with the specified style.
+ */
+ private static FontData[] getModifiedFontData(Font baseFont, int style) {
+ FontData[] baseData = baseFont.getFontData();
+ FontData[] styleData = new FontData[baseData.length];
+ for (int i = 0; i < styleData.length; i++) {
+ FontData base = baseData[i];
+ styleData[i] = new FontData(base.getName(), base.getHeight(), base.getStyle() | style);
+ }
+ return styleData;
+ }
+}