Widening.

git-svn-id: https://samskivert.googlecode.com/svn/trunk@2507 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
samskivert
2008-12-18 01:29:32 +00:00
parent c1f89f9227
commit b7e85472f4
+109 -159
View File
@@ -70,6 +70,33 @@ import com.samskivert.util.SortableArrayList;
*/
public class SwingUtil
{
/**
* An operation that may be applied to a component.
*/
public static interface ComponentOp
{
/** Apply an operation to the given component. */
public void apply (Component comp);
}
/**
* An interface for validating the text contained within a document.
*/
public static interface DocumentValidator
{
/** Return false if the text is not valid for any reason. */
public boolean isValid (String text);
}
/**
* An interface for transforming the text contained within a document.
*/
public static interface DocumentTransformer
{
/** Transform the specified text in some way, or simply return the text untransformed. */
public String transform (String text);
}
/**
* Center the given window within the screen boundaries.
*
@@ -98,13 +125,12 @@ public class SwingUtil
public static void centerComponent (Component a, Component b)
{
Dimension asize = a.getSize(), bsize = b.getSize();
b.setLocation((asize.width - bsize.width) / 2,
(asize.height - bsize.height) / 2);
b.setLocation((asize.width - bsize.width) / 2, (asize.height - bsize.height) / 2);
}
/**
* Draw a string centered within a rectangle. The string is drawn
* using the graphics context's current font and color.
* Draw a string centered within a rectangle. The string is drawn using the graphics context's
* current font and color.
*
* @param g the graphics context.
* @param str the string.
@@ -114,7 +140,7 @@ public class SwingUtil
* @param height the bounding height.
*/
public static void drawStringCentered (
Graphics g, String str, int x, int y, int width, int height)
Graphics g, String str, int x, int y, int width, int height)
{
FontMetrics fm = g.getFontMetrics(g.getFont());
int xpos = x + ((width - fm.stringWidth(str)) / 2);
@@ -123,41 +149,35 @@ public class SwingUtil
}
/**
* Returns the most reasonable position for the specified rectangle to
* be placed at so as to maximize its containment by the specified
* bounding rectangle while still placing it as near its original
* coordinates as possible.
* Returns the most reasonable position for the specified rectangle to be placed at so as to
* maximize its containment by the specified bounding rectangle while still placing it as near
* its original coordinates as possible.
*
* @param rect the rectangle to be positioned.
* @param bounds the containing rectangle.
*/
public static Point fitRectInRect (
Rectangle rect, Rectangle bounds)
public static Point fitRectInRect (Rectangle rect, Rectangle bounds)
{
// Guarantee that the right and bottom edges will be contained
// and do our best for the top and left edges.
return new Point(
Math.min(bounds.x + bounds.width - rect.width,
Math.max(rect.x, bounds.x)),
Math.min(bounds.y + bounds.height - rect.height,
Math.max(rect.y, bounds.y)));
// Guarantee that the right and bottom edges will be contained and do our best for the top
// and left edges.
return new Point(Math.min(bounds.x + bounds.width - rect.width,
Math.max(rect.x, bounds.x)),
Math.min(bounds.y + bounds.height - rect.height,
Math.max(rect.y, bounds.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.
* 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.
* The collection will be destructively modified.
* @param bounds the bounding box within which the rectangle must be positioned.
* @param avoidShapes a collection of Shapes that must not be overlapped. The collection will
* be destructively modified.
*
* @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.
* @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<? extends Shape> avoidShapes)
@@ -165,8 +185,7 @@ public class SwingUtil
Point origPos = r.getLocation();
Comparator<Point> comp = createPointComparator(origPos);
SortableArrayList<Point> possibles = new SortableArrayList<Point>();
// we start things off with the passed-in point (adjusted to
// be inside the bounds, if needed)
// 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
@@ -184,7 +203,6 @@ public class SwingUtil
// see if it hits any shapes we're trying to avoid
for (Iterator<? extends Shape> iter = avoidShapes.iterator(); iter.hasNext(); ) {
Shape shape = iter.next();
if (shape.intersects(r)) {
// remove that shape from our avoid list
iter.remove();
@@ -193,7 +211,6 @@ public class SwingUtil
// 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));
@@ -215,17 +232,14 @@ public class SwingUtil
}
/**
* Create a comparator that compares against the distance from
* the specified point.
* Create a comparator that compares against the distance from the specified point.
*
* Note: The comparator will continue to sort by distance from the origin
* point, even if the origin point's coordinates are modified after
* the comparator is created.
* Note: The comparator will continue to sort by distance from the origin point, even if the
* origin point's coordinates are modified after the comparator is created.
*
* Used by positionRect().
*/
public static <P extends Point2D> Comparator<P> createPointComparator (
final P origin)
public static <P extends Point2D> Comparator<P> createPointComparator (final P origin)
{
return new Comparator<P>() {
public int compare (P p1, P p2)
@@ -238,11 +252,10 @@ public class SwingUtil
}
/**
* Enables (or disables) the specified component, <em>and all of its
* children.</cite> A simple call to {@link Container#setEnabled}
* does not propagate the enabled state to the children of a
* component, which is senseless in our opinion, but was surely done
* for some arguably good reason.
* Enables (or disables) the specified component, <em>and all of its children.</em> A simple
* call to {@link Container#setEnabled} does not propagate the enabled state to the children of
* a component, which is senseless in our opinion, but was surely done for some arguably good
* reason.
*/
public static void setEnabled (Container comp, final boolean enabled)
{
@@ -254,8 +267,7 @@ public class SwingUtil
}
/**
* Set the opacity on the specified component, <em>and all of its
* children.</cite>
* Set the opacity on the specified component, <em>and all of its children.</em>
*/
public static void setOpaque (JComponent comp, final boolean opaque)
{
@@ -269,8 +281,7 @@ public class SwingUtil
}
/**
* Apply the specified ComponentOp to the supplied component
* and then all its descendants.
* Apply the specified ComponentOp to the supplied component and then all its descendants.
*/
public static void applyToHierarchy (Component comp, ComponentOp op)
{
@@ -278,11 +289,10 @@ public class SwingUtil
}
/**
* Apply the specified ComponentOp to the supplied component
* and then all its descendants, up to the specified maximum depth.
* Apply the specified ComponentOp to the supplied component and then all its descendants, up
* to the specified maximum depth.
*/
public static void applyToHierarchy (
Component comp, int depth, ComponentOp op)
public static void applyToHierarchy (Component comp, int depth, ComponentOp op)
{
if (comp == null) {
return;
@@ -299,78 +309,36 @@ public class SwingUtil
}
/**
* An operation that may be applied to a component.
*/
public static interface ComponentOp
{
/**
* Apply an operation to the given component.
*/
public void apply (Component comp);
}
/**
* An interface for validating the text contained within a document.
*/
public static interface DocumentValidator
{
/**
* Should return false if the text is not valid for any reason.
*/
public boolean isValid (String text);
}
/**
* An interface for transforming the text contained within a document.
*/
public static interface DocumentTransformer
{
/**
* Should transform the specified text in some way, or simply
* return the text untransformed.
*/
public String transform (String text);
}
/**
* Set active Document helpers on the specified text component.
* Changes will not and cannot be made (either via user inputs or
* direct method manipulation) unless the validator says that the
* changes are ok.
* Set active Document helpers on the specified text component. Changes will not and cannot be
* made (either via user inputs or direct method manipulation) unless the validator says that
* the changes are ok.
*
* @param validator if non-null, all changes are sent to this for approval.
* @param transformer if non-null, is queried to change the text
* after all changes are made.
* @param transformer if non-null, is queried to change the text after all changes are made.
*/
public static void setDocumentHelpers (
JTextComponent comp, DocumentValidator validator,
DocumentTransformer transformer)
public static void setDocumentHelpers (JTextComponent comp, DocumentValidator validator,
DocumentTransformer transformer)
{
setDocumentHelpers(comp.getDocument(), validator, transformer);
}
/**
* Set active Document helpers on the specified Document.
* Changes will not and cannot be made (either via user inputs or
* direct method manipulation) unless the validator says that the
* Set active Document helpers on the specified Document. Changes will not and cannot be made
* (either via user inputs or direct method manipulation) unless the validator says that the
* changes are ok.
*
* @param validator if non-null, all changes are sent to this for approval.
* @param transformer if non-null, is queried to change the text
* after all changes are made.
* @param transformer if non-null, is queried to change the text after all changes are made.
*/
public static void setDocumentHelpers (
final Document doc, final DocumentValidator validator,
final DocumentTransformer transformer)
public static void setDocumentHelpers (final Document doc, final DocumentValidator validator,
final DocumentTransformer transformer)
{
if (!(doc instanceof AbstractDocument)) {
throw new IllegalArgumentException(
"Specified document cannot be filtered!");
throw new IllegalArgumentException("Specified document cannot be filtered!");
}
// set up the filter.
((AbstractDocument) doc).setDocumentFilter(new DocumentFilter()
{
((AbstractDocument) doc).setDocumentFilter(new DocumentFilter() {
@Override public void remove (FilterBypass fb, int offset, int length)
throws BadLocationException
{
@@ -391,8 +359,7 @@ public class SwingUtil
}
@Override public void replace (
FilterBypass fb, int offset, int length, String text,
AttributeSet attrs)
FilterBypass fb, int offset, int length, String text, AttributeSet attrs)
throws BadLocationException
{
if (replaceOk(offset, length, text)) {
@@ -402,8 +369,7 @@ public class SwingUtil
}
/**
* Convenience for remove/insert/replace to see if the
* proposed change is valid.
* Convenience for remove/insert/replace to see if the proposed change is valid.
*/
protected boolean replaceOk (int offset, int length, String text)
throws BadLocationException
@@ -414,20 +380,18 @@ public class SwingUtil
try {
String current = doc.getText(0, doc.getLength());
String potential = current.substring(0, offset) +
text + current.substring(offset + length);
text + current.substring(offset + length);
// validate the potential text.
return validator.isValid(potential);
} catch (IndexOutOfBoundsException ioobe) {
throw new BadLocationException(
"Bad Location", offset + length);
throw new BadLocationException("Bad Location", offset + length);
}
}
/**
* After a remove/insert/replace has taken place, we may
* want to transform the text in some way.
* After a remove/insert/replace has taken place, we may want to transform the text in
* some way.
*/
protected void transform (FilterBypass fb)
{
@@ -476,8 +440,7 @@ public class SwingUtil
}
/**
* Adjusts the widths and heights of the cells of the supplied table
* to fit their contents.
* Adjusts the widths and heights of the cells of the supplied table to fit their contents.
*/
public static void sizeToContents (JTable table)
{
@@ -491,9 +454,8 @@ public class SwingUtil
int headerWidth = 0, cellWidth = 0;
column = table.getColumnModel().getColumn(cc);
try {
comp = column.getHeaderRenderer().
getTableCellRendererComponent(null, column.getHeaderValue(),
false, false, 0, 0);
comp = column.getHeaderRenderer().getTableCellRendererComponent(
null, column.getHeaderValue(), false, false, 0, 0);
headerWidth = comp.getPreferredSize().width;
} catch (NullPointerException e) {
// getHeaderRenderer() this doesn't work in 1.3
@@ -502,8 +464,7 @@ public class SwingUtil
for (int rr = 0; rr < rcount; rr++) {
Object cellValue = model.getValueAt(rr, cc);
comp = table.getDefaultRenderer(model.getColumnClass(cc)).
getTableCellRendererComponent(table, cellValue,
false, false, 0, cc);
getTableCellRendererComponent(table, cellValue, false, false, 0, cc);
Dimension psize = comp.getPreferredSize();
cellWidth = Math.max(psize.width, cellWidth);
cellHeight = Math.max(psize.height, cellHeight);
@@ -517,11 +478,10 @@ public class SwingUtil
}
/**
* Refreshes the supplied {@link JComponent} to effect a call to
* {@link JComponent#revalidate} and {@link JComponent#repaint}, which
* is frequently necessary in cases such as adding components to or
* removing components from a {@link JPanel} since Swing doesn't
* automatically invalidate things for proper re-rendering.
* Refreshes the supplied {@link JComponent} to effect a call to {@link JComponent#revalidate}
* and {@link JComponent#repaint}, which is frequently necessary in cases such as adding
* components to or removing components from a {@link JPanel} since Swing doesn't automatically
* invalidate things for proper re-rendering.
*/
public static void refresh (JComponent c)
{
@@ -530,8 +490,8 @@ public class SwingUtil
}
/**
* Create a custom cursor out of the specified image, putting the hotspot
* in the exact center of the created cursor.
* Create a custom cursor out of the specified image, putting the hotspot in the exact center
* of the created cursor.
*/
public static Cursor createImageCursor (Image img)
{
@@ -539,8 +499,7 @@ public class SwingUtil
}
/**
* Create a custom cursor out of the specified image, with the specified
* hotspot.
* Create a custom cursor out of the specified image, with the specified hotspot.
*/
public static Cursor createImageCursor (Image img, Point hotspot)
{
@@ -555,8 +514,7 @@ public class SwingUtil
// ", bestSize=" + d.width + "x" + d.height +
// ", maxcolors=" + colors + "].");
// if the passed-in image is smaller, pad it with transparent pixels
// and use it anyway.
// if the passed-in image is smaller, pad it with transparent pixels and use it anyway.
if (((w < d.width) && (h <= d.height)) ||
((w <= d.width) && (h < d.height))) {
Image padder = GraphicsEnvironment.getLocalGraphicsEnvironment().
@@ -587,8 +545,8 @@ public class SwingUtil
}
/**
* Adds a one pixel border of random color to this and all panels
* contained in this panel's child hierarchy.
* Adds a one pixel border of random color to this and all panels contained in this panel's
* child hierarchy.
*/
public static void addDebugBorders (JPanel panel)
{
@@ -606,15 +564,14 @@ public class SwingUtil
}
/**
* Aligns the first <code>rows</code> * <code>cols</code> components
* of <code>parent</code> in a grid. Each component in a column is as
* wide as the maximum preferred width of the components in that
* column; height is similarly determined for each row. The parent is
* made just big enough to fit them all. The components should be
* already added to the parent in row-major order.
* Aligns the first <code>rows</code> * <code>cols</code> components of <code>parent</code> in
* a grid. Each component in a column is as wide as the maximum preferred width of the
* components in that column; height is similarly determined for each row. The parent is made
* just big enough to fit them all. The components should be already added to the parent in
* row-major order.
*
* @param parent the container component; must be configured with a
* {@link SpringLayout} prior to calling this method.
* @param parent the container component; must be configured with a {@link SpringLayout} prior
* to calling this method.
* @param rows number of rows.
* @param cols number of columns.
* @param initialX x location at which to start the grid.
@@ -622,9 +579,8 @@ public class SwingUtil
* @param xPad x padding between cells.
* @param yPad y padding between cells.
*/
public static void makeCompactGrid (
Container parent, int rows, int cols,
int initialX, int initialY, int xPad, int yPad)
public static void makeCompactGrid (Container parent, int rows, int cols,
int initialX, int initialY, int xPad, int yPad)
{
SpringLayout layout = (SpringLayout)parent.getLayout();
@@ -633,13 +589,10 @@ public class SwingUtil
for (int c = 0; c < cols; c++) {
Spring width = Spring.constant(0);
for (int r = 0; r < rows; r++) {
width = Spring.max(
width, getConstraintsForCell(
r, c, parent, cols).getWidth());
width = Spring.max(width, getConstraintsForCell(r, c, parent, cols).getWidth());
}
for (int r = 0; r < rows; r++) {
SpringLayout.Constraints constraints =
getConstraintsForCell(r, c, parent, cols);
SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
constraints.setX(x);
constraints.setWidth(width);
}
@@ -651,13 +604,10 @@ public class SwingUtil
for (int r = 0; r < rows; r++) {
Spring height = Spring.constant(0);
for (int c = 0; c < cols; c++) {
height = Spring.max(
height, getConstraintsForCell(
r, c, parent, cols).getHeight());
height = Spring.max(height, getConstraintsForCell(r, c, parent, cols).getHeight());
}
for (int c = 0; c < cols; c++) {
SpringLayout.Constraints constraints =
getConstraintsForCell(r, c, parent, cols);
SpringLayout.Constraints constraints = getConstraintsForCell(r, c, parent, cols);
constraints.setY(y);
constraints.setHeight(height);
}