package iiuf.awt;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Component;
import java.awt.TextComponent;
import java.awt.Frame;
import java.awt.Button;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.Dimension;
import java.awt.Rectangle;
import java.awt.GridBagConstraints;
import java.awt.Image;
import java.awt.Window;
import java.awt.image.BufferedImage;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.net.URL;
import java.io.InputStream;
import java.lang.reflect.Method;
import javax.swing.ImageIcon;
import iiuf.util.Util;
import iiuf.util.AsyncInvocation;
import iiuf.util.AsyncAccelerator;
import iiuf.log.Log;
/**
Awt utilities.
(c) 1999, 2000, 2001, IIUF, DIUF<p>
@author $Author: ohitz $
@version $Revision: 1.1 $
*/
public class Awt {
public static Cursor STOP_CURSOR = makeCursor("stop", new Point(8, 8));
private static Component emptyCmp = newComponent();
private static final double PI2 = Math.PI * 2;
public static double getAngle(int ox, int oy, int x, int y) {
double dx = x - ox;
double dy = y - oy;
double r = Math.sqrt(dx * dx + dy * dy);
double result = dy < 0 ? Math.PI + Math.asin(dx / r) : -Math.asin(dx / r);
result %= PI2;
return result < 0 ? PI2 + result : result;
}
public static Point place(Rectangle rectToPlace, int x, int y, Rectangle outerLimit) {
rectToPlace.setLocation(x - rectToPlace.width / 2, y - rectToPlace.height / 2);
return fitSmallerIntoBigger(rectToPlace.x, rectToPlace.y, rectToPlace.width, rectToPlace.height, outerLimit);
}
public static Point centerOnScreen(Dimension dim) {
Toolkit tk = Toolkit.getDefaultToolkit();
Dimension sd = tk.getScreenSize();
return new Point((sd.width - dim.width) / 2, (sd.height - dim.height) / 2);
}
public static Point fitSmallerIntoBigger(int x, int y, int width, int height, Rectangle bigger) {
return new Point(x < bigger.x ?
bigger.x :
x + width > bigger.x + bigger.width ? bigger.x + bigger.width -
width : x,
y < bigger.y ?
bigger.y :
y + height > bigger.y + bigger.height ? bigger.y + bigger.height -
height : y);
}
public final static boolean near(int x, int y, int x0, int y0, int x1, int y1, int tolerance) {
int t2 = tolerance * tolerance;
int x1_x0 = x1 - x0;
int y1_y0 = y1 - y0;
int x_x0 = x - x0;
int y_y0 = y - y0;
int denom = x1_x0 * x1_x0 + y1_y0 * y1_y0;
if(denom == 0)
return x_x0 * x_x0 + y_y0 * y_y0 <= t2;
else {
int nom = x_x0 * x1_x0 + y_y0 * y1_y0;
if(nom < 0 || nom > denom)
return false;
else {
double u = (double)nom / (double)denom;
double dx = x - (x0 + u * x1_x0);
double dy = y - (y0 + u * y1_y0);
return dx * dx + dy * dy <= t2;
}
}
}
private static Cursor makeCursor(String name, Point hotSpot) {
return makeCursor(Awt.class.getResource("rsrc/" + name + "_crsr.gif"), hotSpot, name);
}
public static Cursor makeCursor(URL cursorImage, Point hotSpot, String name) {
Toolkit tk = Toolkit.getDefaultToolkit();
int ccolors = tk.getMaximumCursorColors();
ImageIcon ic = null;
// try to get optimized version
try {
String url = cursorImage.toExternalForm();
int idx = url.lastIndexOf('.');
int bpp = -1;
for(bpp = 31; bpp >= 0; bpp--)
if((ccolors & (1 << bpp)) != 0)
break;
if(idx == -1)
url += bpp + "bpp";
else
url = url.substring(0, idx) + bpp + "bpp" + url.substring(idx);
URL curl = new URL(url);
InputStream in = curl.openStream();
in.close();
ic = new ImageIcon(new URL(url));
} catch(Exception e) {
ic = new ImageIcon(cursorImage);
}
Image crsr = ic.getImage();
Dimension d = tk.getBestCursorSize(ic.getIconWidth(), ic.getIconHeight());
if(d.width != ic.getIconWidth() || d.height != ic.getIconHeight()) {
Image tmp = crsr;
crsr = new BufferedImage(d.width, d.height, BufferedImage.TYPE_4BYTE_ABGR);
ic.paintIcon(emptyCmp, crsr.getGraphics(), 0, 0);
}
return tk.createCustomCursor(crsr, hotSpot, name);
}
public static void setCursor(Container container, int cursor) {
Component[] cmps = container.getComponents();
container.setCursor(Cursor.getPredefinedCursor(cursor));
for(int i = 0; i < cmps.length; i++) {
if(cmps[i] instanceof Container)
setCursor((Container)cmps[i], cursor);
else if (cmps[i] instanceof TextComponent &&
cursor == Cursor.DEFAULT_CURSOR)
cmps[i].setCursor(Cursor.getPredefinedCursor(Cursor.TEXT_CURSOR));
else
cmps[i].setCursor(Cursor.getPredefinedCursor(cursor));
}
}
public static Window getWindow(Component component) {
if(component == null) return null;
if(component instanceof Window) return (Window)component;
else return getWindow(component.getParent());
}
public static Frame getFrame(Component component) {
if(component == null) return null;
if(component instanceof Frame) return (Frame)component;
else return getFrame(component.getParent());
}
public static void setFrameCursor(Component component, int cursor) {
setCursor(getFrame(component), cursor);
}
public static GridBagConstraints constraints(boolean last) {
return constraints(last, 0, 0, GridBagConstraints.NONE);
}
public static GridBagConstraints constraints(boolean last, int fill) {
return constraints(last, 0, 0, fill);
}
public static GridBagConstraints constraints(boolean last, int fill, float weightx, float weighty) {
return constraints(last, 0, 0, fill, weightx, weighty);
}
public static GridBagConstraints constraints(boolean last, int insetx, int insety) {
return constraints(last, insetx, insety, GridBagConstraints.NONE);
}
public static GridBagConstraints constraints(boolean last, int insetx, int insety, int fill) {
float weightx = 0;
float weighty = 0;
if(fill == GridBagConstraints.HORIZONTAL) weightx = 1;
if(fill == GridBagConstraints.VERTICAL) weighty = 1;
if(fill == GridBagConstraints.BOTH)
weightx =weighty = 1;
return constraints(last, insetx, insety, fill, weightx, weighty);
}
public static GridBagConstraints constraints(boolean last,
int insetx, int insety,
int fill,
float weightx, float weighty) {
GridBagConstraints result = new GridBagConstraints();
result.weightx = weightx;
result.weighty = weighty;
result.anchor = GridBagConstraints.WEST;
result.fill = fill;
result.insets.left = result.insets.right = insetx;
result.insets.bottom = result.insets.top = insety;
if(last) result.gridwidth = GridBagConstraints.REMAINDER;
return result;
}
public static Button newButton(String label, ActionListener listener) {
return newButton(label, label, listener);
}
public static Button newButton(String label, String command, ActionListener listener) {
Button result = new Button(label);
result.addActionListener(listener);
result.setActionCommand(command);
return result;
}
public static int getIndex(Container container, Component component) {
Component[] cmps = container.getComponents();
for(int i = 0; i < cmps.length; i++)
if(component == cmps[i]) {
return i;
}
return -1;
}
static class EmptyComponent extends Component {}
public static Component newComponent() {
return new EmptyComponent() {};
}
// ----------------------- async stuff
private static AsyncInvocation async = new AsyncInvocation("AWT-AsyncInvocation");
public static AsyncInvocation.Result invokeAsync(Object object, String method, Class argType, Object arg) {
return async.invoke(object, method, argType, arg);
}
private static boolean check(Method m, String method, Class argType) {
return
m.getName().equals(method) &&
argType == m.getParameterTypes()[0] &&
m.getParameterTypes().length == 1;
}
public static void addAsyncAccelerator(AsyncAccelerator accel) {
async.addAsyncAccelerator(accel);
}
static {
addAsyncAccelerator(new AsyncAccelerator() {
public void handle(AsyncInvocation.Invocation i, AsyncInvocation.Result result) {
if(i.object instanceof MouseListener) {
MouseListener ml = (MouseListener)i.object;
if( check(i.method, "mouseClicked", MouseEvent.class)) ml.mouseClicked( (MouseEvent)i.args[0]);
else if(check(i.method, "mouseEntered", MouseEvent.class)) ml.mouseEntered( (MouseEvent)i.args[0]);
else if(check(i.method, "mouseExited", MouseEvent.class)) ml.mouseExited( (MouseEvent)i.args[0]);
else if(check(i.method, "mousePressed", MouseEvent.class)) ml.mousePressed( (MouseEvent)i.args[0]);
else if(check(i.method, "mouseReleased", MouseEvent.class)) ml.mouseReleased((MouseEvent)i.args[0]);
else throw new IllegalArgumentException("Unknown MouseListener method:" + i.method);
result.set(null);
}
}
});
addAsyncAccelerator(new AsyncAccelerator() {
public void handle(AsyncInvocation.Invocation i, AsyncInvocation.Result result) {
if(i.object instanceof ActionListener) {
ActionListener al = (ActionListener)i.object;
if(check(i.method, "actionPerformed", ActionEvent.class)) al.actionPerformed( (ActionEvent)i.args[0]);
else throw new IllegalArgumentException("Unknown MouseListener method:" + i.method);
result.set(null);
}
}
});
}
private static MouseListener tmpMouseListener;
public static synchronized MouseListener asyncWrapper(MouseListener listener_) {
tmpMouseListener = listener_;
return new MouseListener() {
MouseListener listener = tmpMouseListener;
public void mouseClicked(MouseEvent e) {invokeAsync(listener, "mouseClicked", MouseEvent.class, e);}
public void mouseEntered(MouseEvent e) {invokeAsync(listener, "mouseEntered", MouseEvent.class, e);}
public void mouseExited(MouseEvent e) {invokeAsync(listener, "mouseExited", MouseEvent.class, e);}
public void mousePressed(MouseEvent e) {invokeAsync(listener, "mousePressed", MouseEvent.class, e);}
public void mouseReleased(MouseEvent e) {invokeAsync(listener, "mouseReleased", MouseEvent.class, e);}
};
}
private static ActionListener tmpActionListener;
public static synchronized ActionListener asyncWrapper(ActionListener listener_) {
tmpActionListener = listener_;
return new ActionListener() {
ActionListener listener = tmpActionListener;
public void actionPerformed(ActionEvent e) {invokeAsync(listener, "actionPerformed", ActionEvent.class, e);}
};
}
}
/*
$Log: Awt.java,v $
Revision 1.1 2002/07/11 09:20:36 ohitz
Initial checkin
Revision 1.16 2001/03/09 15:30:50 schubige
Added markers to graph panel
Revision 1.15 2001/03/02 09:06:43 schubige
interim checkin for soundium
Revision 1.14 2001/03/01 10:42:48 schubige
interim checkin for soundium
Revision 1.13 2001/02/23 11:03:15 schubige
try to recover table_source.png
Revision 1.12 2001/02/12 17:50:05 schubige
still working on soundium gui
Revision 1.11 2001/01/14 13:21:13 schubige
Win NT update
Revision 1.10 2001/01/04 16:28:28 schubige
Header update for 2001 and DIUF
Revision 1.9 2001/01/03 08:30:39 schubige
graph stuff beta
Revision 1.8 2000/12/28 09:29:09 schubige
SourceWatch beta
Revision 1.7 2000/12/18 12:39:08 schubige
Added ports to iiuf.util.graph
Revision 1.6 2000/11/20 17:36:56 schubige
tinja project ide
Revision 1.5 2000/11/09 07:48:43 schubige
early checkin for DCJava
Revision 1.4 2000/07/14 13:40:54 schubige
Various updates/fixes
Revision 1.3 1999/12/02 16:07:32 schubige
updated block, general cleanup
Revision 1.2 1999/11/26 09:14:29 schubige
intermediate commit
Revision 1.1 1999/11/26 08:51:15 schubige
*** empty log message ***
Revision 1.6 1999/09/10 06:54:18 schubige
Dialogs & requesters are now placed at 1/2 x and 1/3 y of the screen.
Revision 1.5 1999/09/09 14:31:20 schubige
Added DateChooser, Dilog and Line, updated Awt.
Revision 1.4 1999/09/03 15:50:08 schubige
Changed to new header & log conventions.
Revision 1.3 1999/09/03 14:06:14 schubige
MacCVS testing
Revision 1.2 1999/09/02 14:15:28 schubige
added @serial tag or transient to make javadoc happy
*/