added positionRect() and createPointComparator(), both originally from
the internals of comic chat. git-svn-id: https://samskivert.googlecode.com/svn/trunk@874 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: SwingUtil.java,v 1.14 2002/09/24 09:47:14 shaper Exp $
|
// $Id: SwingUtil.java,v 1.15 2002/10/18 21:45:10 ray Exp $
|
||||||
//
|
//
|
||||||
// samskivert library - useful routines for java programs
|
// samskivert library - useful routines for java programs
|
||||||
// Copyright (C) 2001 Michael Bayne
|
// Copyright (C) 2001 Michael Bayne
|
||||||
@@ -22,6 +22,12 @@ package com.samskivert.swing.util;
|
|||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
|
import java.awt.geom.Area;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import javax.swing.text.AbstractDocument;
|
import javax.swing.text.AbstractDocument;
|
||||||
import javax.swing.text.AttributeSet;
|
import javax.swing.text.AttributeSet;
|
||||||
import javax.swing.text.BadLocationException;
|
import javax.swing.text.BadLocationException;
|
||||||
@@ -29,6 +35,8 @@ import javax.swing.text.Document;
|
|||||||
import javax.swing.text.DocumentFilter;
|
import javax.swing.text.DocumentFilter;
|
||||||
import javax.swing.text.JTextComponent;
|
import javax.swing.text.JTextComponent;
|
||||||
|
|
||||||
|
import com.samskivert.util.SortableArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Miscellaneous useful Swing-related utility functions.
|
* Miscellaneous useful Swing-related utility functions.
|
||||||
*/
|
*/
|
||||||
@@ -114,6 +122,108 @@ public class SwingUtil
|
|||||||
return new Point(erect.x, erect.y);
|
return new Point(erect.x, erect.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Position the specified rectangle as closely as possible to
|
||||||
|
* its current position, but make sure it is within the specified
|
||||||
|
* bounds and that it does not overlap any of the Shapes contained
|
||||||
|
* in the avoid list.
|
||||||
|
*
|
||||||
|
* @param r the rectangle to attempt to position.
|
||||||
|
* @param bounds the bounding box within which the rectangle must be
|
||||||
|
* positioned.
|
||||||
|
* @param avoidShapes a collection of Shapes that must not be overlapped.
|
||||||
|
*
|
||||||
|
* @return true if the rectangle was successfully placed, given the
|
||||||
|
* constraints, or false if the positioning failed (the rectangle will
|
||||||
|
* be left at it's original location.
|
||||||
|
*/
|
||||||
|
public static boolean positionRect (
|
||||||
|
Rectangle r, Rectangle bounds, Collection avoidShapes)
|
||||||
|
{
|
||||||
|
Point origPos = r.getLocation();
|
||||||
|
Comparator comp = createPointComparator(origPos);
|
||||||
|
SortableArrayList possibles = new SortableArrayList();
|
||||||
|
// we start things off with the passed-in point (adjusted to
|
||||||
|
// be inside the bounds, if needed)
|
||||||
|
possibles.add(fitRectInRect(r, bounds));
|
||||||
|
|
||||||
|
// keep track of area that doesn't generate new possibles
|
||||||
|
Area dead = new Area();
|
||||||
|
|
||||||
|
CHECKPOSSIBLES:
|
||||||
|
while (!possibles.isEmpty()) {
|
||||||
|
r.setLocation((Point) possibles.remove(0));
|
||||||
|
|
||||||
|
// make sure the rectangle is in the view and not over a dead area
|
||||||
|
if ((!bounds.contains(r)) || dead.intersects(r)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// see if it hits any shapes we're trying to avoid
|
||||||
|
for (Iterator iter=avoidShapes.iterator(); iter.hasNext(); ) {
|
||||||
|
Shape shape = (Shape) iter.next();
|
||||||
|
|
||||||
|
if (shape.intersects(r)) {
|
||||||
|
// remove that shape from our avoid list
|
||||||
|
iter.remove();
|
||||||
|
// but add it to our dead area
|
||||||
|
dead.add(new Area(shape));
|
||||||
|
|
||||||
|
// add 4 new possible points, each pushed in one direction
|
||||||
|
Rectangle pusher = shape.getBounds();
|
||||||
|
|
||||||
|
possibles.add(new Point(pusher.x - r.width, r.y));
|
||||||
|
possibles.add(new Point(r.x, pusher.y - r.height));
|
||||||
|
possibles.add(new Point(pusher.x + pusher.width, r.y));
|
||||||
|
possibles.add(new Point(r.x, pusher.y + pusher.height));
|
||||||
|
|
||||||
|
// re-sort the list
|
||||||
|
possibles.sort(comp);
|
||||||
|
continue CHECKPOSSIBLES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// hey! if we got here, then it worked!
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// we never found a match, move the rectangle back
|
||||||
|
r.setLocation(origPos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a comparator that compares against the distance from
|
||||||
|
* the specified point.
|
||||||
|
*
|
||||||
|
* Used by positionRect().
|
||||||
|
*/
|
||||||
|
public static Comparator createPointComparator (Point origin)
|
||||||
|
{
|
||||||
|
final int xo = origin.x;
|
||||||
|
final int yo = origin.y;
|
||||||
|
|
||||||
|
return new Comparator() {
|
||||||
|
public int compare (Object o1, Object o2)
|
||||||
|
{
|
||||||
|
Point p1 = (Point) o1;
|
||||||
|
Point p2 = (Point) o2;
|
||||||
|
|
||||||
|
int x1 = xo - p1.x;
|
||||||
|
int y1 = yo - p1.y;
|
||||||
|
int x2 = xo - p2.x;
|
||||||
|
int y2 = yo - p2.y;
|
||||||
|
|
||||||
|
// since we are dealing with positive integers, we can
|
||||||
|
// omit the Math.sqrt() step for optimization
|
||||||
|
int dist1 = (x1 * x1) + (y1 * y1);
|
||||||
|
int dist2 = (x2 * x2) + (y2 * y2);
|
||||||
|
|
||||||
|
return dist1 - dist2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a polygon representing the rectangle defined by the
|
* Return a polygon representing the rectangle defined by the
|
||||||
* specified upper left coordinate and the supplied dimensions.
|
* specified upper left coordinate and the supplied dimensions.
|
||||||
|
|||||||
Reference in New Issue
Block a user