Widening.
git-svn-id: https://samskivert.googlecode.com/svn/trunk@2507 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user