package com.xoetrope.swing;
import com.xoetrope.swing.animation.AnimationStep;
import com.xoetrope.swing.animation.AnimationThread;
import com.xoetrope.swing.animation.XAnimationContext;
import com.xoetrope.swing.animation.XAnimationSurface;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
/**
* Displays text by scrolling/animating its position across the controls width.
* Not all the text need be visible at once. The animation can be one-off or a
* loop
*
* <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
* the GNU Public License (GPL), please see license.txt for more details. If
* you make commercial use of this software you must purchase a commercial
* license from Xoetrope.</p>
* <p> $Revision: 1.18 $</p>
*/
public class XMarqueeText extends XAnimationSurface //implements AnimationStep, XAnimationContext
{
protected int fade;
protected int loopLength;
protected int ascent;
protected int maxExtent;
// Debugging/diagnostic code variables
//private static int frames;
//private static long startTime;
protected TextLayout layout;
/**
* Create a new marquee
*/
public XMarqueeText( )
{
fade = 0;
maxExtent = 1000;
increment = 300;
setDoubleBuffered( true );
setLoopTime( 60000 );
setSleepTime( 32 );
}
/**
* Attempts to load and reference the associated view/datastore.
*/
public void init()
{
Point p = getLocation();
Dimension size = getSize();
oX = p.x;
oY = p.y;
oW = size.width;
oH = size.height;
inc = oW;
}
/**
* This method will receive all of the timing events from an Animator
* during an animation. The fraction is the percent elapsed (0 to 1)
* of the current animation cycle.
* @param fraction the fraction of completion between the start and
* end of the current cycle. Note that on reversing cycles
* ({@link Animator.Direction#BACKWARD}) the fraction decreases
* from 1.0 to 0 on backwards-running cycles. Note also that animations
* with a duration of {@link Animator#INFINITE INFINITE} will call
* timingEvent with an undefined value for fraction, since there is
* no fraction that makes sense if the animation has no defined length.
* @see Animator.Direction
*/
public void timingEvent( float fraction )
{
timingFraction = fraction;
repaint();
}
//=========================================================================
// Rendering
//=========================================================================
/**
* All classes that extend JAnimationSurface must implement this routine...
* @param w the width
* @param h the height
* @param g2 the graphics context
*/
public void drawObjects( int w, int h, Graphics2D g2 )
{
if (( label == null ) || ( label.length() <= 0 ))
return;
//inc = (int)((long)oW - animationThread.getStepPosition() % maxExtent );
inc = (int)((long)oW - ( timingFraction * maxExtent ));
Color bkColor = getBackground();
g2.setColor( bkColor );
g2.fillRect( 0, 0, oW, oH );
g2.setColor( getForeground() );
if ( layout == null ) {
Font font = getFont( );
FontMetrics fm = g2.getFontMetrics( font );
FontRenderContext frc = g2.getFontRenderContext();
Point2D.Double pen = new Point2D.Double( 0, 0 );
layout = new TextLayout( label, font, frc );
//layoutShape = layout.getOutline( null );
ascent = fm.getAscent();
}
AffineTransform at = AffineTransform.getTranslateInstance( inc, ( oH + ascent ) / 2 );
Shape s = layout.getOutline( at );// at.createTransformedShape( layoutShape );
// Paint the full/new version
g2.fill( s );
if ( fade > 0 ) {
int fadeWidth = ( oW * fade ) / 100;
// Fade out the start
GradientPaint painter = new GradientPaint( 0.0F, 0.0F,
new Color( bkColor.getRed(), bkColor.getGreen(), bkColor.getBlue(), 255 ), fadeWidth, 0.0F,
new Color( bkColor.getRed(), bkColor.getGreen(), bkColor.getBlue(), 0 ), false );
g2.setPaint( painter );
g2.fill( new Rectangle2D.Double( 0, 0, fadeWidth, oH ));
// Fade out the end
GradientPaint painter2 = new GradientPaint( oW - fadeWidth, 0.0F,
new Color( bkColor.getRed(), bkColor.getGreen(), bkColor.getBlue(), 0 ), oW, 0.0F,
new Color( bkColor.getRed(), bkColor.getGreen(), bkColor.getBlue(), 255 ), false );
g2.setPaint( painter2 );
g2.fill( new Rectangle2D.Double( oW - fadeWidth, 0, fadeWidth, oH ));
}
maxExtent = ((int)s.getBounds().getWidth()) + increment;
}
//=========================================================================
// Access Functions
//=========================================================================
/**
* Set the percentage of the width over which to fade the ends in and out.
* By default the fade is set to zero for no fade.
* @param percentage the new fade percentage
*/
public void setFade( int percentage )
{
fade = percentage;
}
/**
* Get the percentage of the width over which to fade the ends in and out.
* By default the fade is set to zero for no fade.
* @return the new fade percentage
*/
public int getFade()
{
return fade;
}
public void setRampUp( int rampUp )
{
}
/**
* Set one or more attributes of the component.
* @param attribName the name of the attribute
* <ul>
* <li>fade - the percentage of the width by which to fade each end of the marquee</li>
* </ul>
* @param attribValue the value of the attribute
* @return 0 for success, non zero otherwise
*/
public int setAttribute( String attribName, Object attribValue )
{
String attribNameLwr = attribName.toLowerCase();
String attribValueStr = (String)attribValue;
if ( attribNameLwr.equals( "fade" ))
setFade( Integer.parseInt( attribValueStr ));
else
super.setAttribute( attribName, attribValue );
return 0;
}
private int inc = 0;
protected int oX, oY, oW, oH;
}
|