All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.arakhne.afc.ui.awt.AwtUtil Maven / Gradle / Ivy

There is a newer version: 13.0
Show newest version
/* 
 * $Id: org/arakhne/afc/ui/awt/AwtUtil.java v12.0 2015-04-09 01:26:21$
 * 
 * Copyright (C) 2012-13 Stephane GALLAND.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * This program is free software; you can redistribute it and/or modify
 */
package org.arakhne.afc.ui.awt;

import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.font.FontRenderContext;
import java.awt.geom.AffineTransform;
import java.awt.geom.Dimension2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;

import javax.swing.Icon;
import javax.swing.ImageIcon;

import org.arakhne.afc.math.continous.object2d.Vector2f;
import org.arakhne.afc.math.generic.Vector2D;
import org.arakhne.afc.ui.MouseCursor;

/** Swing-oriented utilities. 
 *
 * @author Stéphane GALLAND
 * @version 12.0 2015-04-09 01:26:21
 * @mavengroupid org.arakhne.afc.ui
 * @mavenartifactid awt
 */
public class AwtUtil {

	private static FontRenderContext frc =  null;

	/** Replies the AWT identifier of the mouse cursor.
	 * 
	 * @param cursor
	 * @return the AWT identifier of the mouse cursor.
	 */
	public static int getAWTCursorId(MouseCursor cursor) {
		switch(cursor) {
		case CROSSHAIR:
			return Cursor.CROSSHAIR_CURSOR;
		case TEXT:
			return Cursor.TEXT_CURSOR;
		case WAIT:
			return Cursor.WAIT_CURSOR;
		case SW_RESIZE:
			return Cursor.SW_RESIZE_CURSOR;
		case SE_RESIZE:
			return Cursor.SE_RESIZE_CURSOR;
		case NW_RESIZE:
			return Cursor.NW_RESIZE_CURSOR;
		case NE_RESIZE:
			return Cursor.NE_RESIZE_CURSOR;
		case N_RESIZE:
			return Cursor.N_RESIZE_CURSOR;
		case S_RESIZE:
			return Cursor.S_RESIZE_CURSOR;
		case W_RESIZE:
			return Cursor.W_RESIZE_CURSOR;
		case E_RESIZE:
			return Cursor.E_RESIZE_CURSOR;
		case HAND:
			return Cursor.HAND_CURSOR;
		case MOVE:
			return Cursor.MOVE_CURSOR;
		case INVALID:
			return Cursor.CUSTOM_CURSOR;
		case DEFAULT:
		default:
		}
		return Cursor.DEFAULT_CURSOR;
	}

	/** Replies the AWT mouse cursor.
	 * 
	 * @param cursor
	 * @return the AWT mouse cursor.
	 */
	public static Cursor getCursor(MouseCursor cursor) {
		if (cursor==null || cursor==MouseCursor.DEFAULT)
			return Cursor.getDefaultCursor();
		if (cursor==MouseCursor.INVALID) {
			try {
				return Cursor.getSystemCustomCursor("Invalid.32x32"); //$NON-NLS-1$
			}
			catch (Throwable _) {
				return Cursor.getDefaultCursor();
			}
		}
		return Cursor.getPredefinedCursor(getAWTCursorId(cursor));
	}

	/** Compute and reply a transparent version of the given color.
	 * 
	 * @param c
	 * @return the transparent color.
	 */
	public static Color makeTransparentColor(Color c) {
		int alpha = c.getAlpha() / 2;
		return new Color(
				c.getRed(), c.getGreen(), c.getBlue(),
				alpha);
	}

	/** Replies the current font render context.
	 * 
	 * @return the current font render context.
	 */
	public static FontRenderContext getVectorFontRenderContext() {
		synchronized(AwtUtil.class) {
			FontRenderContext c = frc;
			if (c==null) {
				c = new FontRenderContext(new AffineTransform(), true, true);
				frc = c;
			}
			return c;
		}
	}

	/** Move the first specified rectangle to avoid collision 
	 * with the reference.
	 * 
	 * @param rectangleToMove is the rectangle to move.
	 * @param reference is the rectangle to avoid collision with.
	 * @return the displacement vector.
	 */
	public static Vector2D avoidCollision(Rectangle2D rectangleToMove, Rectangle2D reference) {
		double dx1 = reference.getMaxX() - rectangleToMove.getMinX();
		double dx2 = rectangleToMove.getMaxX() - reference.getMinX();
		double dy1 = reference.getMaxY() - rectangleToMove.getMinY();
		double dy2 = rectangleToMove.getMaxY() - reference.getMinY();

		double absdx1 = Math.abs(dx1);
		double absdx2 = Math.abs(dx2);
		double absdy1 = Math.abs(dy1);
		double absdy2 = Math.abs(dy2);

		double dx = 0;
		double dy = 0;

		if (dx1>=0 && absdx1<=absdx2 && absdx1<=absdy1 && absdx1<=absdy2) {
			// Move according to dx1
			dx = dx1; 
		}
		else if (dx2>=0 && absdx2<=absdx1 && absdx2<=absdy1 && absdx2<=absdy2) {
			// Move according to dx2
			dx = - dx2;
		}
		else if (dy1>=0 && absdy1<=absdx1 && absdy1<=absdx2 && absdy1<=absdy2) {
			// Move according to dy1
			dy = dy1; 
		}
		else {
			// Move according to dy2
			dy = - dy2;
		}

		rectangleToMove.setFrame(
				rectangleToMove.getMinX()+dx,
				rectangleToMove.getMinY()+dy,
				rectangleToMove.getWidth(),
				rectangleToMove.getHeight());

		return new Vector2f((float)dx, (float)dy);
	}

	/** Move the first specified rectangle to avoid collision 
	 * with the reference.
	 * 
	 * @param rectangleToMove is the rectangle to move.
	 * @param reference is the rectangle to avoid collision with.
	 * @param displacementDirection is the direction of the allowed displacement.
	 * @return the displacement vector.
	 */
	public static Vector2D avoidCollision(Rectangle2D rectangleToMove, Rectangle2D reference, Vector2D displacementDirection) {
		if (displacementDirection==null || displacementDirection.lengthSquared()==0f)
			return avoidCollision(rectangleToMove, reference);

		double dx1 = reference.getMaxX() - rectangleToMove.getMinX();
		double dx2 = reference.getMinX() - rectangleToMove.getMaxX();
		double dy1 = reference.getMaxY() - rectangleToMove.getMinY();
		double dy2 = reference.getMinY() - rectangleToMove.getMaxY();

		double absdx1 = Math.abs(dx1);
		double absdx2 = Math.abs(dx2);
		double absdy1 = Math.abs(dy1);
		double absdy2 = Math.abs(dy2);

		double dx, dy;

		if (displacementDirection.getX()<0) {
			dx = -Math.min(absdx1, absdx2);
		}
		else {
			dx = Math.min(absdx1, absdx2);
		}

		if (displacementDirection.getY()<0) {
			dy = -Math.min(absdy1, absdy2);
		}
		else {
			dy = Math.min(absdy1, absdy2);
		}

		rectangleToMove.setFrame(
				rectangleToMove.getMinX()+dx,
				rectangleToMove.getMinY()+dy,
				rectangleToMove.getWidth(),
				rectangleToMove.getHeight());

		displacementDirection.set((float)dx, (float)dy);
		return displacementDirection;
	}

	/** Replies the specified image filtered with the given transparency amount.
	 * 

* If this function replies null, you might invokes * {@link #getTransparencyFilteredImage(Image, float)} * with a not-null component parameter to obtain an * image. * * @param image is the image to filter. * @param alpha indicates how the alpha-component of the image is changed. * The value is in [-1;1]. * A value of -1 means that the alpha-component is set to none. * A value of 1 means that the alpha-component is completely * set. A value of 0 means that the alpha-component * remains the same. * @return the filtered image or null. */ public static Image getTransparencyFilteredImage(Image image, float alpha) { if (image==null) return null; return TransparencyFilter.createFilteredImage( image, alpha); } /** Scale the given image. * * @param image is the image to scale. * @param width is the new width. * @param height is the new height. * @param observer is invoked when the image becomes ready to use. * @return the scaled image; or null if the image is not ready or * not computable. */ public static Image computeScaledImage(ImageIcon image, int width, int height, ImageObserver observer) { if (image==null) return null; Image imageToScale = extractIconImage(null, image); if (imageToScale==null) return null; int currentWidth = imageToScale.getWidth(observer); if (currentWidth<0) return null; int currentHeight = imageToScale.getHeight(observer); if (currentHeight<0) return null; Dimension2D d = computeBothScaledSize( currentWidth, currentHeight, width, height); if (d==null) return imageToScale; // Scaling not necessary return imageToScale.getScaledInstance( (int)d.getWidth(),(int)d.getHeight(),Image.SCALE_SMOOTH); } /** Extract an image from the specified icon. * * @param component * @param icon * @return the image. */ public static Image extractIconImage(Component component, Icon icon) { Image source; if (icon instanceof ImageIcon) { source = ((ImageIcon)icon).getImage(); } else if (component!=null) { source = new BufferedImage(icon.getIconWidth(), icon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g = (Graphics2D)source.getGraphics(); icon.paintIcon(component, g, 0, 0); g.dispose(); } else { source = null; } return source; } /** Scale the given image. * * @param image is the image to scale. * @param width is the new width. * @param height is the new height. * @param observer is notified when the image cannot be loaded. * @return the scaled image; or null if the image cannot be loaded. */ public static Image computeScaledImage(Image image, int width, int height, ImageObserver observer) { if (image==null) return null; int currentWidth = image.getWidth(observer); if (currentWidth<0) return null; int currentHeight = image.getHeight(observer); if (currentHeight<0) return null; Dimension2D d = computeBothScaledSize( currentWidth, currentHeight, width, height); if (d==null) return image; // scaling is not necessary return image.getScaledInstance( (int)d.getWidth(),(int)d.getHeight(),Image.SCALE_SMOOTH); } private static Dimension2D computeBothScaledSize(int currentWidth, int currentHeight, int desiredWidth, int desiredHeight) { int targetWidth = desiredWidth; int targetHeight = desiredHeight; if (targetWidth==-1) targetWidth = currentWidth; if (targetHeight==-1) targetHeight = currentHeight; if (targetWidth==currentWidth && targetHeight==currentHeight) return null; float wscale = (float)targetWidth / (float)currentWidth; float hscale = (float)targetHeight / (float)currentHeight; if (hscaletargetWidth) targetHeight = -1; else targetWidth = -1; } else { int nheight = (int)(currentHeight * wscale); if (nheight>targetHeight) targetWidth = -1; else targetHeight = -1; } return new DoubleDimension(targetWidth,targetHeight); } /** This class permits to filter the alpha component of an icon. * * @author Stéphane GALLAND * @version 12.0 2015-04-09 01:26:21 * @mavengroupid org.arakhne.afc.ui * @mavenartifactid awt */ public static class TransparencyFilter extends RGBImageFilter { private final float alpha; /** * Creates a alpha-filtered image * * @param i is the image to filter * @param alpha indicates how the alpha-component of the icon is changed. * The value is in [-1;1]. * A value of -1 means that the alpha-component is set to none. * A value of 1 means that the alpha-component is completely * set. A value of 0 means that the alpha-component * remains the same. * @return the result of the filtering. */ public static Image createFilteredImage(Image i, float alpha) { TransparencyFilter filter = new TransparencyFilter(alpha); ImageProducer prod = new FilteredImageSource(i.getSource(), filter); Image filteredImage = Toolkit.getDefaultToolkit().createImage(prod); return filteredImage; } /** * Constructs an TransparencyFilter object that filters a color image to a * alphaed image. * * @param alpha indicates how the alpha-component of the icon is changed. * The value is in [-1;1]. * A value of -1 means that the alpha-component is set to none. * A value of 1 means that the alpha-component is completely * set. A value of 0 means that the alpha-component * remains the same. */ public TransparencyFilter(float alpha) { float f = alpha; if (f<-1f) f = -1f; else if (f>1f) f = 1f; assert(f>=-1f && f<=1f); this.alpha = -f; // canFilterIndexColorModel indicates whether or not it is acceptable // to apply the color filtering of the filterRGB method to the color // table entries of an IndexColorModel object in lieu of pixel by pixel // filtering. this.canFilterIndexColorModel = true; } /** * Filter the specified color. */ @Override public int filterRGB(int x, int y, int rgb) { int color_a = (rgb >> 24) & 0xFF; int color_rgb = rgb & 0x00FFFFFF; if (this.alpha<0f) { color_a += color_a * this.alpha; } else { color_a += (256-color_a) * this.alpha; } if (color_a<0) color_a = 0; else if (color_a>255) color_a = 255; return ((color_a << 24) & 0xFF000000) | color_rgb; } } // class AlphaFilter }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy