/*
Copyright (C) 2001, 2006 United States Government as represented by
the Administrator of the National Aeronautics and Space Administration.
All Rights Reserved.
*/
package gov.nasa.worldwind.render;
import com.sun.opengl.util.j2d.TextRenderer;
import gov.nasa.worldwind.util.Logging;
import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import javax.swing.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.geom.*;
/**
* @author dcollins
* @version $Id: ToolTipRenderer.java 5168 2008-04-24 21:32:51Z dcollins $
*/
public class ToolTipRenderer
{
private static final Font toolTipFont = UIManager.getFont("ToolTip.font");
private static final Color toolTipFg = UIManager.getColor("ToolTip.foreground");
private static final Color toolTipBg = UIManager.getColor("ToolTip.background");
private static final Border toolTipBorder = UIManager.getBorder("ToolTip.border");
private Color foreground;
private Color background;
private Insets insets;
private float borderWidth;
private boolean useSystemLookAndFeel = false;
private TextRenderer textRenderer;
private int orthoWidth;
private int orthoHeight;
private GLU glu = new GLU();
public ToolTipRenderer()
{
this(new TextRenderer(toolTipFont, true, true), false);
}
public ToolTipRenderer(TextRenderer textRenderer)
{
this(textRenderer, false);
}
public ToolTipRenderer(TextRenderer textRenderer, boolean useSystemLookAndFeel)
{
if (textRenderer == null)
{
String message = Logging.getMessage(""); // TODO
Logging.logger().fine(message);
throw new IllegalArgumentException(message);
}
this.textRenderer = textRenderer;
this.textRenderer.setUseVertexArrays(false);
this.useSystemLookAndFeel = useSystemLookAndFeel;
this.borderWidth = 1;
}
public void beginRendering(int width, int height)
{
GL gl = GLU.getCurrentGL();
int attribBits =
GL.GL_ENABLE_BIT
| GL.GL_COLOR_BUFFER_BIT // for alpha test func and ref, and blend
| GL.GL_CURRENT_BIT // for current color
| GL.GL_TRANSFORM_BIT // for modelview and perspective
| GL.GL_POLYGON_BIT; // for polygon mode
gl.glPushAttrib(attribBits);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPushMatrix();
gl.glLoadIdentity();
glu.gluOrtho2D(0, width, 0, height);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPushMatrix();
gl.glLoadIdentity();
gl.glDisable(GL.GL_LIGHTING);
gl.glDisable(GL.GL_TEXTURE_2D);
gl.glDisable(GL.GL_DEPTH_TEST);
gl.glDisable(GL.GL_CULL_FACE);
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_ALPHA);
// Suppress any fully transparent image pixels
final float ALPHA_EPSILON = 0.001f;
gl.glEnable(GL.GL_ALPHA_TEST);
gl.glAlphaFunc(GL.GL_GREATER, ALPHA_EPSILON);
this.orthoWidth = width;
this.orthoHeight = height;
}
public void endRendering()
{
GL gl = GLU.getCurrentGL();
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glPopMatrix();
gl.glMatrixMode(GL.GL_TEXTURE);
gl.glPopMatrix();
gl.glPopAttrib();
}
private static Rectangle2D ensureVisibleBounds(Rectangle2D bounds, int orthoWidth, int orthoHeight)
{
double newX;
if (bounds.getMinX() < 0)
newX = 0;
else if (bounds.getMaxX() > orthoWidth)
newX = orthoWidth - bounds.getWidth() - 1;
else
newX = bounds.getX();
double newY;
if (bounds.getMinY() < 0)
newY = 0;
else if (bounds.getMaxY() > orthoHeight)
newY = orthoHeight - bounds.getHeight() - 1;
else
newY = bounds.getY();
return new Rectangle2D.Double(newX, newY, bounds.getWidth(), bounds.getHeight());
}
public Color getBackground()
{
return this.background;
}
public float getBorderWidth()
{
return this.borderWidth;
}
public Color getForeground()
{
return this.foreground;
}
public Insets getInsets()
{
return this.insets;
}
public boolean getUseSystemLookAndFeel()
{
return this.useSystemLookAndFeel;
}
public void draw(String str, int x, int y)
{
if (str == null)
{
String message = Logging.getMessage("nullValue.StringIsNull");
Logging.logger().fine(message);
throw new IllegalArgumentException(message);
}
Color fg;
Color bg;
Insets insets;
GL gl = GLU.getCurrentGL();
if (this.useSystemLookAndFeel)
{
insets = toolTipBorder.getBorderInsets(null);
fg = toolTipFg;
bg = toolTipBg;
}
else
{
if (this.foreground != null)
{
fg = this.foreground;
}
else
{
float[] colorArray = new float[4];
gl.glGetFloatv(GL.GL_CURRENT_COLOR, colorArray, 0);
fg = new Color(colorArray[0], colorArray[1], colorArray[2], colorArray[3]);
}
if (this.background != null)
{
bg = this.background;
}
else
{
float[] hsbvals = new float[3];
Color.RGBtoHSB(fg.getRed(), fg.getGreen(), fg.getBlue(), hsbvals);
bg = Color.getHSBColor(0, 0, (hsbvals[2] + 0.5f) % 1f);
}
if (this.insets != null)
insets = this.insets;
else
insets = new Insets(1, 1, 1, 1);
}
Rectangle2D strBounds = this.textRenderer.getBounds(str);
Rectangle2D ttBounds = new Rectangle2D.Double(
x, y,
strBounds.getWidth() + insets.left + insets.right,
strBounds.getHeight() + insets.bottom + insets.top);
ttBounds = ensureVisibleBounds(ttBounds, this.orthoWidth, this.orthoHeight);
double strX = ttBounds.getX() + insets.left - strBounds.getX();
double strY = ttBounds.getY() + insets.bottom + strBounds.getY() + strBounds.getHeight();
this.setDrawColor(bg);
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
gl.glRectd(ttBounds.getMinX(), ttBounds.getMinY(), ttBounds.getMaxX(), ttBounds.getMaxY());
this.setDrawColor(fg);
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_LINE);
gl.glLineWidth(this.borderWidth);
gl.glRectd(ttBounds.getMinX(), ttBounds.getMinY(), ttBounds.getMaxX(), ttBounds.getMaxY());
this.textRenderer.setColor(fg);
gl.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL);
this.textRenderer.begin3DRendering();
this.textRenderer.draw3D(str, (float) strX, (float) strY, 0, 1);
this.textRenderer.end3DRendering();
}
public void setBackground(Color color)
{
this.background = color;
}
public void setBorderWidth(float borderWidth)
{
this.borderWidth = borderWidth;
}
private void setDrawColor(float r, float g, float b, float a)
{
GL gl = GLU.getCurrentGL();
gl.glColor4f(r * a, g * a, b * a, a);
}
private void setDrawColor(Color color)
{
float[] compArray = new float[4];
color.getRGBComponents(compArray);
this.setDrawColor(compArray[0], compArray[1], compArray[2], compArray[3]);
}
public void setForeground(Color color)
{
this.foreground = color;
}
public void setInsets(Insets insets)
{
this.insets = insets;
}
public void setUseSystemLookAndFeel(boolean useSystemLookAndFeel)
{
this.useSystemLookAndFeel = useSystemLookAndFeel;
}
}