import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.util.Random; public class TextBouncer extends AnimationComponent { public static void main(String[] args) { String s = "Firenze"; final int size = 64; if (args.length > 0) s = args[0]; Panel controls = new Panel(); final Choice choice = new Choice(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] allFonts = ge.getAllFonts(); for (int i = 0; i < allFonts.length; i++) choice.addItem(allFonts[i].getName()); Font defaultFont = new Font(allFonts[0].getName(), Font.PLAIN, size); final TextBouncer bouncer = new TextBouncer(s, defaultFont); Frame f = new AnimationFrame(bouncer); f.setFont(new Font("Serif", Font.PLAIN, 12)); controls.add(bouncer.createCheckbox("Antialiasing", TextBouncer.ANTIALIASING)); controls.add(bouncer.createCheckbox("Gradient", TextBouncer.GRADIENT)); controls.add(bouncer.createCheckbox("Shear", TextBouncer.SHEAR)); controls.add(bouncer.createCheckbox("Rotate", TextBouncer.ROTATE)); controls.add(bouncer.createCheckbox("Axes", TextBouncer.AXES)); Panel fontControls = new Panel(); choice.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ie) { Font font = new Font(choice.getSelectedItem(), Font.PLAIN, size); bouncer.setFont(font); } }); fontControls.add(choice); Panel allControls = new Panel(new GridLayout(2, 1)); allControls.add(controls); allControls.add(fontControls); f.add(allControls, BorderLayout.NORTH); f.setVisible(true); } private boolean mAntialiasing = false, mGradient = false; private boolean mShear = false, mRotate = false, mAxes = false; public static final int ANTIALIASING = 0; public static final int GRADIENT = 1; public static final int SHEAR = 2; public static final int ROTATE = 3; public static final int AXES = 5; private float mDeltaX, mDeltaY; private float mX, mY, mWidth, mHeight; private float mTheta; private float mShearX, mShearY, mShearDeltaX, mShearDeltaY; private String mString; public TextBouncer(String s, Font f) { mString = s; setFont(f); Random random = new Random(); mX = random.nextFloat() * 500; mY = random.nextFloat() * 500; mDeltaX = random.nextFloat() * 3; mDeltaY = random.nextFloat() * 3; mShearX = random.nextFloat() / 2; mShearY = random.nextFloat() / 2; mShearDeltaX = mShearDeltaY = .05f; FontRenderContext frc = new FontRenderContext(null, true, false); Rectangle2D bounds = getFont().getStringBounds(mString, frc); mWidth = (float)bounds.getWidth(); mHeight = (float)bounds.getHeight(); // Make sure points are within range. addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent ce) { Dimension d = getSize(); if (mX < 0) mX = 0; else if (mX + mWidth >= d.width) mX = d.width - mWidth - 1; if (mY < 0) mY = 0; else if (mY + mHeight >= d.height) mY = d.height - mHeight - 1; } }); } public void setSwitch(int item, boolean value) { switch(item) { case ANTIALIASING: mAntialiasing = value; break; case GRADIENT: mGradient = value; break; case SHEAR: mShear = value; break; case ROTATE: mRotate = value; break; case AXES: mAxes = value; break; default: break; } } protected Checkbox createCheckbox(String label, final int item) { Checkbox check = new Checkbox(label); check.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent ie) { setSwitch(item, (ie.getStateChange() == ie.SELECTED)); } }); return check; } public void timeStep() { Dimension d = getSize(); if (mX + mDeltaX < 0) mDeltaX = -mDeltaX; else if (mX + mWidth + mDeltaX >= d.width) mDeltaX = -mDeltaX; if (mY + mDeltaY < 0) mDeltaY = -mDeltaY; else if (mY + mHeight + mDeltaY >= d.height) mDeltaY = -mDeltaY; mX += mDeltaX; mY += mDeltaY; mTheta += Math.PI / 192; if (mTheta > (2 * Math.PI)) mTheta -= (2 * Math.PI); if (mShearX + mShearDeltaX > .5) mShearDeltaX = -mShearDeltaX; else if (mShearX + mShearDeltaX < -.5) mShearDeltaX = -mShearDeltaX; if (mShearY + mShearDeltaY > .5) mShearDeltaY = -mShearDeltaY; else if (mShearY + mShearDeltaY < -.5) mShearDeltaY = -mShearDeltaY; mShearX += mShearDeltaX; mShearY += mShearDeltaY; } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D)g; setAntialiasing(g2); setTransform(g2); setPaint(g2); // Draw the string. g2.setFont(getFont()); g2.drawString(mString, mX, mY + mHeight); drawAxes(g2); } protected void setAntialiasing(Graphics2D g2) { if (mAntialiasing == false) return; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } protected void setTransform(Graphics2D g2) { Dimension d = getSize(); int cx = d.width / 2; int cy = d.height / 2; g2.translate(cx, cy); if (mShear) g2.shear(mShearX, mShearY); if (mRotate) g2.rotate(mTheta); g2.translate(-cx, -cy); } protected void setPaint(Graphics2D g2) { if (mGradient) { GradientPaint gp = new GradientPaint(0, 0, Color.blue, 50, 25, Color.green, true); g2.setPaint(gp); } else g2.setPaint(Color.orange); } protected void drawAxes(Graphics2D g2) { if (mAxes == false) return; g2.setPaint(getForeground()); g2.setStroke(new BasicStroke()); Dimension d = getSize(); int side = 20; int arrow = 4; int w = d.width / 2, h = d.height / 2; g2.drawLine(w - side, h, w + side, h); g2.drawLine(w + side - arrow, h - arrow, w + side, h); g2.drawLine(w, h - side, w, h + side); g2.drawLine(w + arrow, h + side - arrow, w, h + side); } }