package eu.irreality.age.swing; import java.awt.Color; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Timer; import javax.swing.text.SimpleAttributeSet; import javax.swing.text.StyleConstants; import javax.swing.text.StyledDocument; import eu.irreality.age.ColoredSwingClient; /** * A timer used to slowly fade in a text from the background color to its foreground color. * @author carlos * */ public class ColorFadeInTimer extends Timer { /**The client where the text effect is going to be shown.*/ private ColoredSwingClient cl; /**The color that the text should have at the end of the timer.*/ private Color targetColor; /**Starting offset of the text to which the effect should be applied.*/ private int offset; /**Length of the text to which the effect should be applied.*/ private int length; /**Duration of the effect in milliseconds*/ private int duration; /**Whether alpha transparency should be used*/ private boolean useAlpha = true; /** * Sets the duration (in milliseconds) of the text color fade-in effect. * @param duration The duration of the text fade-in effect, in ms. */ public void setDuration ( int duration ) { this.duration = duration; } /** * @return The duration (in milliseconds) of the text color fade-in effect. */ public int getDuration() { return duration; } private Color getSourceColor ( ColoredSwingClient cl , Color targetColor ) { if ( useAlpha ) return new Color ( targetColor.getRed() , targetColor.getGreen() , targetColor.getBlue() , 0 /*transparent*/ ); else return cl.getTextArea().getBackground(); } public ColorFadeInTimer ( final int delay , final ColoredSwingClient cl , int offset , int length , final Color targetColor , int effectDuration ) { super ( delay , null ); this.cl = cl; this.offset = offset; this.length = length; this.targetColor = targetColor; this.duration = effectDuration; Action colorFadeInAction = new AbstractAction() { Color sourceColor = getSourceColor(cl,targetColor); //initially, the text's color is the text area background Color currentColor = sourceColor; int iters = 0; public void actionPerformed ( ActionEvent evt ) { double progress = (double)(iters * ColorFadeInTimer.this.getDelay()) / (double)duration; if ( progress <= 0.0 ) currentColor = sourceColor; else if ( progress >= 1.0 ) currentColor = ColorFadeInTimer.this.targetColor; else currentColor = getTransitionColor ( sourceColor , ColorFadeInTimer.this.targetColor , progress ); //System.err.println("Iter " + iters + " color " + currentColor); StyledDocument sd = (StyledDocument) cl.getTextArea().getDocument(); SimpleAttributeSet colorAttrToApply = new SimpleAttributeSet(); StyleConstants.setForeground(colorAttrToApply,currentColor); sd.setCharacterAttributes(ColorFadeInTimer.this.offset, ColorFadeInTimer.this.length, colorAttrToApply, false); if ( progress >= 1.0 ) ColorFadeInTimer.this.stop(); else iters++; } }; this.addActionListener(colorFadeInAction); } /** * Obtains the color obtained from a weighted average, progress*destination + (1-progress)*source. * @param source * @param destination * @param progress * @return */ public Color getTransitionColor ( Color source , Color destination , double progress ) { double remaining = 1.0 - progress; int red = (int) ( progress * destination.getRed() + remaining * source.getRed() ); int green = (int) ( progress * destination.getGreen() + remaining * source.getGreen() ); int blue = (int) ( progress * destination.getBlue() + remaining * source.getBlue() ); int alpha = (int) ( progress * destination.getAlpha() + remaining * source.getAlpha() ); return new Color ( red , green , blue , alpha ); } }