/*
* Copyright (C) 2012 Jason Gedge <http://www.gedge.ca>
*
* This file is part of the OpGraph project.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package ca.gedge.opgraph.app.util;
import java.awt.Color;
import java.awt.Component;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.font.LineMetrics;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
/**
* A class similar to {@link SwingUtilities} that has some helper functions
* for drawing things.
*/
public class GUIHelper {
/**
* Returns the point at which to draw a string so that it appears
* center-aligned within a given rectangle.
*
* @param g the graphics context to work with
* @param txt the string
* @param rect the rectangle to place the string in
*
* @return the point at which text should be drawn so that it is aligned
* in the center of the given rectangle.
*/
public static Point centerTextInRectangle(Graphics g, String txt, Rectangle rect) {
return placeTextInRectangle(g, txt, rect, SwingConstants.CENTER, SwingConstants.CENTER);
}
/**
* Returns the point at which to draw a string so that it appears aligned
* within a given rectangle.
*
* @param g the graphics context to work with
* @param txt the string
* @param rect the rectangle to place the string in
*
* @param horizontalAlignment the horizontal alignment; one of
* {@link SwingConstants#LEFT}, {@link SwingConstants#CENTER}
* or {@link SwingConstants#RIGHT}
*
* @param verticalAlignment the vertical alignment; one of
* {@link SwingConstants#TOP}, {@link SwingConstants#CENTER}
* or {@link SwingConstants#BOTTOM}
*
* @return the point at which text should be drawn so that it is aligned
* appropriately with the given rectangle.
*/
public static Point placeTextInRectangle(Graphics g,
String txt,
Rectangle rect,
int horizontalAlignment,
int verticalAlignment)
{
final FontMetrics fm = g.getFontMetrics();
final LineMetrics lm = fm.getLineMetrics(txt, g);
final Rectangle2D r = fm.getStringBounds(txt, g);
int x = rect.x;
int y = rect.y;
switch(horizontalAlignment) {
case SwingConstants.CENTER:
x += (rect.width - r.getWidth()) * 0.5;
break;
case SwingConstants.RIGHT:
x += rect.width - r.getWidth();
break;
}
switch(verticalAlignment) {
case SwingConstants.TOP:
y += lm.getAscent();
break;
case SwingConstants.CENTER:
y += (rect.height - r.getHeight()) * 0.5 + lm.getAscent();
break;
case SwingConstants.BOTTOM:
y += rect.height - lm.getDescent();
break;
}
return new Point(x, y);
}
/**
* Gets the interior drawing region of a component. That is, the drawing
* area inside of its border.
*
* @param comp the component to get the interior rectangle of
*
* @return the interior rectangle
*/
public static Rectangle getInterior(JComponent comp) {
final Insets insets = comp.getInsets();
final Rectangle rect = new Rectangle(0, 0, comp.getWidth(), comp.getHeight());
rect.x += insets.left;
rect.y += insets.top;
rect.width -= insets.left + insets.right;
rect.height -= insets.top + insets.bottom;
return rect;
}
/**
* Gets a color that "highlights" a given color. If the given color is dark,
* the returned color is brighter, otherwise the returned color is darker.
*
* @param c the color to highlight
*
* @return a highlighted color
*/
public static Color highlightColor(Color c) {
final int brightness = (int)(0.3*c.getRed() + 0.59*c.getGreen() + 0.11*c.getBlue());
return (brightness > 127 ? c.darker() : c.brighter());
}
/**
* Returns the first ancestor of a given component that is of a specified
* class, or the component itself if it is an instance of the given class.
*
* @param cls the class to look for
* @param comp the component to start searching from
*
* @return the ancestor of the given class, or <code>null</code> if
* no ancestor of the given class could be found
*
* @see SwingUtilities#getAncestorOfClass(Class, Component)
*/
public static <T> T getAncestorOrSelfOfClass(Class<T> cls, Component comp) {
if(cls.isInstance(comp))
return cls.cast(comp);
return cls.cast(SwingUtilities.getAncestorOfClass(cls, comp));
}
}