package de.javagl.snippets.viewer;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Locale;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import de.javagl.snippets.viewer.Viewer.Painter;
import de.javagl.snippets.viewer.Viewer.Transformer;
/**
* Simple test and demonstration of the Viewer class
*/
public class ViewerTest
{
/**
* The entry point of this test
*
* @param args Not used
*/
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
/**
* Create and show the GUI, to be called on the EDT
*/
private static void createAndShowGUI()
{
JFrame f = new JFrame("Viewer");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(
new JLabel("Mouse drags to pan, mouse wheel to zoom"),
BorderLayout.NORTH);
final Viewer viewerComponent = new Viewer();
viewerComponent.addPainter(new TestPainterGraphics());
viewerComponent.addPainter(new TestPainterShapes());
f.getContentPane().add(viewerComponent, BorderLayout.CENTER);
final JLabel infoLabel = new JLabel("");
f.getContentPane().add(infoLabel, BorderLayout.SOUTH);
// Add a mouse motion listener to the viewer, which
// will update the info label containing the current
// mouse position in screen- and world coordinates
viewerComponent.addMouseMotionListener(new MouseMotionListener()
{
@Override
public void mouseMoved(MouseEvent e)
{
updateInfo(e.getPoint());
}
@Override
public void mouseDragged(MouseEvent e)
{
updateInfo(e.getPoint());
}
/**
* Update the info label depending on the given screen point
* @param screenPoint The screen point
*/
private void updateInfo(Point screenPoint)
{
Transformer transformer = viewerComponent.getTransformer();
Point2D worldPoint =
transformer.screenToWorld(screenPoint, null);
infoLabel.setText(
"Screen: "+format(screenPoint)+
" World: "+format(worldPoint));
}
/**
* Create a simple string representation of the given point
*
* @param p The point
* @return The string representation
*/
private String format(Point2D p)
{
String xs = String.format(Locale.ENGLISH, "%.2f", p.getX());
String ys = String.format(Locale.ENGLISH, "%.2f", p.getY());
return "("+xs+","+ys+")";
}
});
f.setSize(500,500);
f.setVisible(true);
}
/**
* Implementation of the {@link Painter} interface that
* shows some painting in a transformed Graphics2D
*/
private static class TestPainterGraphics implements Painter
{
@Override
public void paint(Graphics2D g, AffineTransform at, int w, int h)
{
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Path2D grid = new Path2D.Double();
for (int x=0; x<100; x+=10)
{
for (int y=0; y<50; y+=10)
{
grid.moveTo(x, y);
grid.lineTo(x+10, y);
grid.moveTo(x, y);
grid.lineTo(x, y+10);
}
}
Rectangle2D border = new Rectangle2D.Double(0,0,100,50);
AffineTransform oldAT = g.getTransform();
g.transform(at);
g.setColor(Color.LIGHT_GRAY);
g.draw(grid);
g.setColor(Color.BLACK);
g.draw(border);
g.setColor(Color.RED);
g.drawString("This is painted", 10, 15);
g.drawString("by transforming", 10, 30);
g.drawString("the Graphics2D", 10, 45);
g.setTransform(oldAT);
}
}
/**
* Implementation of the {@link Painter} interface that
* shows some painting of transformed Shapes
*/
private static class TestPainterShapes implements Painter
{
@Override
public void paint(Graphics2D g, AffineTransform at, int w, int h)
{
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
Path2D grid = new Path2D.Double();
for (int x=0; x<100; x+=10)
{
for (int y=50; y<100; y+=10)
{
grid.moveTo(x, y);
grid.lineTo(x+10, y);
grid.moveTo(x, y);
grid.lineTo(x, y+10);
}
}
Rectangle2D border = new Rectangle2D.Double(0,50,100,50);
g.setColor(Color.LIGHT_GRAY);
g.draw(at.createTransformedShape(grid));
g.setColor(Color.BLACK);
g.draw(at.createTransformedShape(border));
g.setColor(Color.RED);
g.fill(createText("This is painted", g.getFont(), at, 10, 65));
g.fill(createText("by transforming", g.getFont(), at, 10, 80));
g.fill(createText("the shapes", g.getFont(), at, 10, 95));
}
/**
* Create a shape of the specified text. Caution, this is a
* very inefficient solution!
*
* @param text The text
* @param font The font
* @param at The AffineTransform
* @param x The x-coordinate
* @param y The y-coordinate
* @return The shape of the text
*/
private static Shape createText(
String text, Font font, AffineTransform at, int x, int y)
{
FontRenderContext fontRenderContext =
new FontRenderContext(null, true, true);
GlyphVector glyphVector =
font.createGlyphVector(fontRenderContext, text);
AffineTransform fullAt = new AffineTransform(at);
fullAt.translate(x, y);
return fullAt.createTransformedShape(glyphVector.getOutline());
}
}
}