KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > jgoodies > animation > components > AnimatedLabel


1 /*
2  * Copyright (c) 2001-2004 JGoodies Karsten Lentzsch. All Rights Reserved.
3  *
4  * This software is the proprietary information of Karsten Lentzsch.
5  * Use is subject to license terms.
6  *
7  */

8
9 package com.jgoodies.animation.components;
10
11 import java.awt.*;
12
13 import javax.swing.JLabel JavaDoc;
14 import javax.swing.JPanel JavaDoc;
15 import javax.swing.SwingConstants JavaDoc;
16 import javax.swing.SwingUtilities JavaDoc;
17 import javax.swing.plaf.FontUIResource JavaDoc;
18
19 import com.jgoodies.animation.AbstractAnimation;
20 import com.jgoodies.animation.Animation;
21 import com.jgoodies.animation.AnimationAdapter;
22 import com.jgoodies.animation.AnimationEvent;
23 import com.jgoodies.animation.Animator;
24
25 /**
26  * An anti-aliased text label that can animate text changes
27  * using a blend over effect.<p>
28  *
29  * <strong>Note: This is preview code that is not supported.
30  * It is more raw than other classes that you have downloaded
31  * from JGoodies.com in the past and contains known bugs.</strong>
32  *
33  * @author Karsten Lentzsch
34  * @version $Revision: 1.4 $
35  */

36
37 public final class AnimatedLabel extends JPanel JavaDoc {
38
39     public static final int RIGHT = SwingConstants.RIGHT;
40     public static final int CENTER = SwingConstants.CENTER;
41     public static final int LEFT = SwingConstants.LEFT;
42
43     public static final Color DEFAULT_BASE_COLOR = new Color(64, 64, 64);
44     public static final int DEFAULT_FONT_EXTRA_SIZE = 8;
45
46     private static final int DEFAULT_DURATION = 300;
47     private static final int DEFAULT_ANIMATION_FPS = 30;
48
49     private JLabel JavaDoc[] labels;
50     private int foreground = 0;
51     private int background = 1;
52
53     private Color baseColor;
54     private boolean animationEnabled;
55     private int orientation;
56     private long duration;
57     private int fps;
58     private Animation animation;
59
60     // Instance Creation ****************************************************
61

62     /**
63      * Constructs an <code>AnimatedLabel</code> with the given properties.
64      *
65      * @param baseColor the color used as a basis for the text color
66      * @param fontExtraSize pixels that are added to the dialog font size
67      * @param text the initial text to be displayed
68      * @param orientation the label's orientation
69      * @param duration the duration of the blend over animation
70      * @param frames_per_second the blend over animation's frame rate
71      */

72     public AnimatedLabel(
73         Color baseColor,
74         int fontExtraSize,
75         String JavaDoc text,
76         int orientation,
77         int duration,
78         int frames_per_second) {
79         this.baseColor = baseColor;
80         this.orientation = orientation;
81         this.duration = duration;
82         this.fps = frames_per_second;
83         this.animationEnabled = true;
84         initComponents(fontExtraSize);
85         build();
86         setTextImmediately(text);
87     }
88
89     /**
90      * Constructs an <code>AnimatedLabel</code> with the given initial text
91      * and orientation.
92      *
93      * @param baseColor the color used as a basis for the text color
94      * @param fontExtraSize pixels that are added to the dialog font size
95      * @param text the initial text to be displayed
96      * @param orientation the label's orientation
97      */

98     public AnimatedLabel(
99         Color baseColor,
100         int fontExtraSize,
101         String JavaDoc text,
102         int orientation) {
103         this(
104             baseColor,
105             fontExtraSize,
106             text,
107             orientation,
108             DEFAULT_DURATION,
109             DEFAULT_ANIMATION_FPS);
110     }
111
112     /**
113      * Constructs an <code>AnimatedLabel</code> with the given initial text
114      * using a left oriented label.
115      *
116      * @param baseColor the color used as a basis for the text color
117      * @param fontExtraSize pixels that are added to the dialog font size
118      * @param text the initial text to be displayed
119      */

120     public AnimatedLabel(Color baseColor, int fontExtraSize, String JavaDoc text) {
121         this(baseColor, fontExtraSize, text, LEFT);
122     }
123
124     /**
125      * Constructs an <code>AnimatedLabel</code> with default base color,
126      * default font extra size, and an empty text.
127      */

128     public AnimatedLabel() {
129         this(DEFAULT_BASE_COLOR, DEFAULT_FONT_EXTRA_SIZE, "");
130     }
131
132     // Public API ***********************************************************
133

134     /**
135      * Returns whether the animation is currently enabled.
136      *
137      * @return true if the animation is enabled, false if disabled
138      */

139     public boolean isAnimationEnabled() {
140         return animationEnabled;
141     }
142
143     /**
144      * Enables or disables the blend over effect. This can be useful in
145      * environments with a poor rendering performance or if the user disables
146      * all kinds of animations. You can still use this class but enable and
147      * disable the animations.
148      *
149      * @param enable true to enable the blend over effect, false to disable it
150      */

151     public void setAnimationEnabled(boolean enable) {
152         boolean oldValue = animationEnabled;
153         animationEnabled = enable;
154         firePropertyChange("animationEnabled", oldValue, enable);
155     }
156
157     /**
158      * Returns the label's foreground base color.
159      *
160      * @return this label's foreground base color
161      */

162     public Color getForeground() {
163         return baseColor;
164     }
165
166     /**
167      * Sets a new foreground base color.
168      *
169      * @param newForeground the color to be set as new foreground base color
170      */

171     public void setForeground(Color newForeground) {
172         Color oldForeground = getForeground();
173         baseColor = newForeground;
174         firePropertyChange("foreground", oldForeground, newForeground);
175     }
176
177     /**
178      * Returns the duration of the blend over animation.
179      *
180      * @return the duration of the blend over animaton
181      */

182     public long getDuration() {
183         return duration;
184     }
185
186     /**
187      * Sets the animation's duration and invalidates the animation cache.
188      *
189      * @param newDuration the duration to be set
190      */

191     public void setDuration(int newDuration) {
192         long oldDuration = duration;
193         duration = newDuration;
194         animation = null;
195         firePropertyChange("duration", oldDuration, newDuration);
196     }
197
198     // Animation Creation ***************************************************
199

200     /**
201      * Returns the text of the foreground label.
202      *
203      * @return the text of the foreground label
204      */

205     public synchronized String JavaDoc getText() {
206         return labels[foreground].getText();
207     }
208
209     /**
210      * Sets a new text. If the animation is disabled the text will
211      * be set immediately otherwise a blend over animation is used.
212      *
213      * @param newText the new text to be displayed
214      */

215     public synchronized void setText(String JavaDoc newText) {
216         if (!isAnimationEnabled()) {
217             setTextImmediately(newText);
218             return;
219         }
220         
221         String JavaDoc oldText = getText();
222         labels[background].setText(newText);
223         foreground = 1 - foreground;
224         background = 1 - background;
225         new Animator(animation(), fps).start();
226         firePropertyChange("text", oldText, newText);
227     }
228
229     /**
230      * Sets a new text without using the blend over animation.
231      *
232      * @param newText the text to be set
233      */

234     public void setTextImmediately(String JavaDoc newText) {
235         String JavaDoc oldText = getText();
236         labels[background].setText(newText);
237         foreground = 1 - foreground;
238         background = 1 - background;
239         setAlpha(255, 0);
240         firePropertyChange("text", oldText, newText);
241     }
242
243     /**
244      * Lazily creates and returns the blend over animation.
245      *
246      * @return the lazily created blend over animation
247      */

248     private Animation animation() {
249         if (animation == null) {
250             animation = new BlendOverAnimation(duration);
251             animation.addAnimationListener(new AnimationAdapter() {
252                 public void animationStopped(AnimationEvent e) {
253                     setAlpha(255, 0);
254                 }
255             });
256         }
257         return animation;
258     }
259
260     // Building *************************************************************
261

262     /**
263      * Creates and configures the UI components. The label's size is specified
264      * using an <code>fontExtraSize</code> that is a delta in pixel to the
265      * dialog font size.
266      *
267      * @param fontExtraSize the pixel size delta for the label sizes
268      */

269     private void initComponents(int fontExtraSize) {
270         labels = new JLabel JavaDoc[2];
271         labels[foreground] =
272             createBoldLabel(fontExtraSize, getTranslucentColor(255));
273         labels[background] =
274             createBoldLabel(fontExtraSize, getTranslucentColor(255));
275     }
276
277     private void build() {
278         setOpaque(false);
279         setLayout(new GridBagLayout());
280         GridBagConstraints gbc = new GridBagConstraints();
281         gbc.anchor = anchor();
282         gbc.gridx = 0;
283         gbc.gridy = 0;
284         add(labels[foreground], gbc);
285         add(labels[background], gbc);
286     }
287
288     private int anchor() {
289         if (orientation == RIGHT) {
290             return GridBagConstraints.EAST;
291         } else if (orientation == CENTER) {
292             return GridBagConstraints.CENTER;
293         } else {
294             return GridBagConstraints.WEST;
295         }
296     }
297
298     /**
299      * Creates and returns an anti-aliased label with a bold font for the
300      * specified size increment and foreground color.
301      *
302      * @param sizeIncrement a size delta in pixels relative to
303      * the dialog font size
304      * @param aForeground the label's foreground base color
305      * @return a bold anti aliased label
306      */

307     private JLabel JavaDoc createBoldLabel(int sizeIncrement, Color aForeground) {
308         JLabel JavaDoc label = new AntiAliasedLabel("", Font.BOLD, sizeIncrement);
309         label.setForeground(aForeground);
310         return label;
311     }
312
313     // Helper Methods *******************************************************
314

315     /**
316      * Creates and returns a translucent color with the label's base color.
317      *
318      * @param alpha the current alpha value
319      * @return a translucent color with the given alpha based on this label's
320      * foreground base color.
321      */

322     private Color getTranslucentColor(int alpha) {
323         return new Color(
324             baseColor.getRed(),
325             baseColor.getGreen(),
326             baseColor.getBlue(),
327             alpha);
328     }
329
330     /**
331      * Sets the foreground and background colors using the given alpha values.
332      *
333      * @param foregroundAlpha alpha value for the foreground label
334      * @param backgroundAlpha alpha value for the background label
335      */

336     private void setAlpha0(int foregroundAlpha, int backgroundAlpha) {
337         labels[foreground].setForeground(getTranslucentColor(foregroundAlpha));
338         labels[background].setForeground(getTranslucentColor(backgroundAlpha));
339     }
340
341     /**
342      * Sets the foreground and background colors in the event dispatch thread.
343      *
344      * @param foregroundAlpha alpha value for the foreground label
345      * @param backgroundAlpha alpha value for the background label
346      */

347     private void setAlpha(
348         final int foregroundAlpha,
349         final int backgroundAlpha) {
350         if (SwingUtilities.isEventDispatchThread()) {
351             setAlpha0(foregroundAlpha, backgroundAlpha);
352             return;
353         }
354         Runnable JavaDoc runnable = new Runnable JavaDoc() {
355             public void run() {
356                 setAlpha0(foregroundAlpha, backgroundAlpha);
357             }
358         };
359         SwingUtilities.invokeLater(runnable);
360     }
361
362     // Animation Class ******************************************************
363

364     /**
365      * An animation that changes the colors of overlapping labels
366      * to implement a blend over effect.
367      */

368     private class BlendOverAnimation extends AbstractAnimation {
369
370         /**
371          * Constructs an animation that changes the colors of the
372          * prefix and suffix labels over the duration.
373          *
374          * @param duration the animation's duration
375          */

376         public BlendOverAnimation(long duration) {
377             super(duration, true);
378         }
379
380         /**
381          * Applies the effect: sets the text and time.
382          *
383          * @param time the time point used to apply the effect
384          */

385         protected void applyEffect(long time) {
386             int foregroundAlpha = (int) (255 * time / duration());
387             int backgroundAlpha = 255 - foregroundAlpha;
388             setAlpha(foregroundAlpha, backgroundAlpha);
389         }
390     }
391
392     // Helper Class ***********************************************************
393

394     private static class AntiAliasedLabel extends JLabel JavaDoc {
395
396         private final int fontExtraSize;
397         private final int fontStyle;
398
399         /**
400          * Constructs an <code>AntiAliasedLabel</code> for the given text,
401          * font style and font extra size.
402          *
403          * @param text the label's initial text
404          * @param fontStyle the font style attribute
405          * @param fontExtraSize a size delta in pixel relative to the dialog
406          * font size in pixels
407          */

408         private AntiAliasedLabel(
409             String JavaDoc text,
410             int fontStyle,
411             int fontExtraSize) {
412             super(text);
413             this.fontStyle = fontStyle;
414             this.fontExtraSize = fontExtraSize;
415             updateUI();
416         }
417
418         /**
419          * Switches anti-aliasing on, paints, and switches it off again.
420          *
421          * @param g the Graphics object to render on
422          */

423         public void paint(Graphics g) {
424             Graphics2D g2 = (Graphics2D) g;
425             Object JavaDoc oldHint =
426                 g2.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
427             g2.setRenderingHint(
428                 RenderingHints.KEY_ANTIALIASING,
429                 RenderingHints.VALUE_ANTIALIAS_ON);
430             super.paint(g2);
431             g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldHint);
432         }
433
434         /**
435          * Restores the font after the UI has changed.
436          */

437         public void updateUI() {
438             super.updateUI();
439             Font font = getFont();
440             if (0 == fontExtraSize) {
441                 if (font.getStyle() != fontStyle)
442                     setFont(new FontUIResource JavaDoc(font.deriveFont(fontStyle)));
443             } else
444                 setFont(
445                     new FontUIResource JavaDoc(
446                         new Font(
447                             font.getName(),
448                             fontStyle,
449                             font.getSize() + fontExtraSize)));
450         }
451     }
452
453 }
Popular Tags