001: /*
002: * @(#)Flashable.java 3/16/2007
003: *
004: * Copyright 2002 - 2007 JIDE Software Inc. All rights reserved.
005: */
006:
007: package com.jidesoft.swing;
008:
009: import javax.swing.*;
010: import java.awt.*;
011: import java.awt.event.ActionEvent;
012: import java.awt.event.ActionListener;
013:
014: /**
015: * <code>Flashable</code> is a basic interface to enable flashing in any component.
016: * Internally it uses {@link Animator} to create the flashing effect.
017: * <p/>
018: * Whenever a Flashable is installed to a JComponent, you can always use {@link #isFlashableInstalled(javax.swing.JComponent)}
019: * to check if it is installed.
020: */
021: public abstract class Flashable {
022: public final static String CLIENT_PROPERTY_FLASHABLE = "jide.flashable";
023: private int _interval = 500;
024:
025: protected JComponent _component;
026:
027: protected Animator _animator;
028: protected Timer _timer = null;
029:
030: private static boolean _synchonized FlashFlag;
031: private static Timer _synchonized FlashTimer;
032:
033: public Flashable(JComponent component) {
034: _component = component;
035: install(_component);
036: }
037:
038: static class FlashTimer extends Timer implements ActionListener {
039: public FlashTimer(int delay, ActionListener listener) {
040: super (delay, listener);
041: addActionListener(this );
042: }
043:
044: public void actionPerformed(ActionEvent e) {
045: _synchonized FlashFlag = !_synchonized FlashFlag;
046: }
047: }
048:
049: public boolean getSynchonizedFlashFlag() {
050: return _synchonized FlashFlag;
051: }
052:
053: private void install(JComponent component) {
054: _animator = new Animator(component, 0, getInterval(), -1) {
055: @Override
056: protected Timer createTimer(int delay,
057: ActionListener listener) {
058: if (_synchonized FlashTimer == null) {
059: _synchonized FlashTimer = new FlashTimer(delay,
060: listener);
061: }
062: _synchonized FlashTimer.addActionListener(listener);
063: return _synchonized FlashTimer;
064: }
065: };
066: _animator.setAnimatorListener(new AnimatorListener() {
067: public void animationStarts(Component component) {
068:
069: }
070:
071: public void animationFrame(Component component,
072: int totalStep, int step) {
073: flash();
074: }
075:
076: public void animationEnds(Component component) {
077:
078: }
079: });
080: component.putClientProperty(CLIENT_PROPERTY_FLASHABLE, this );
081: }
082:
083: /**
084: * Gets the table that will flash.
085: *
086: * @return the table.
087: */
088: public JComponent getComponent() {
089: return _component;
090: }
091:
092: /**
093: * Sets the table that will flash.
094: *
095: * @param component the new table.
096: */
097: public void setComponent(JComponent component) {
098: JComponent old = _component;
099: if (old != component) {
100: _component.putClientProperty(CLIENT_PROPERTY_FLASHABLE,
101: null);
102: _component = component;
103: _component.putClientProperty(CLIENT_PROPERTY_FLASHABLE,
104: this );
105: }
106: }
107:
108: /**
109: * Gets the interval, in ms.
110: *
111: * @return the interval.
112: */
113: public int getInterval() {
114: return _interval;
115: }
116:
117: /**
118: * Sets the inteveral, in ms. If the flashing is running, the new interval will take effect immediately. By default, it is 300 ms.
119: *
120: * @param interval the new interval.
121: */
122: public void setInterval(int interval) {
123: int old = _interval;
124: if (old != interval) {
125: _interval = interval;
126: getAnimator().setDelay(interval);
127: }
128: }
129:
130: /**
131: * This method actually does the flashing. This method is called in the actionPerformed of the timer.
132: */
133: abstract public void flash();
134:
135: /**
136: * Clears any flashing effect. This method will be called in {@link #startFlashing()} and {@link #stopFlashing()}.
137: */
138: abstract public void clearFlashing();
139:
140: protected Animator getAnimator() {
141: return _animator;
142: }
143:
144: /**
145: * Starts flashing.
146: */
147: public void startFlashing() {
148: clearFlashing();
149: getAnimator().start();
150: }
151:
152: /**
153: * Stops flashing.
154: */
155: public void stopFlashing() {
156: clearFlashing();
157: getAnimator().stop();
158: }
159:
160: /**
161: * Unstalls the <code>Flashable</code> from the component. Once uninstalled,
162: * you have to create a new Flashable in order to use the flahsing feature again. If you just want to stop flashing,
163: * you should use {@link #stopFlashing()}.
164: */
165: public void uninstall() {
166: stopFlashing();
167: _animator.dispose();
168: _animator = null;
169: getComponent().putClientProperty(CLIENT_PROPERTY_FLASHABLE,
170: null);
171: }
172:
173: /**
174: * Checks if it is flashing.
175: *
176: * @return true if flashing.
177: */
178: public boolean isFlashing() {
179: return getAnimator().isRunning();
180: }
181:
182: /**
183: * Checks if there is a Flashable installed on the component.
184: *
185: * @param component the component.
186: * @return true if installed.
187: */
188: public static boolean isFlashableInstalled(JComponent component) {
189: Object flashable = component
190: .getClientProperty(CLIENT_PROPERTY_FLASHABLE);
191: return flashable instanceof Flashable;
192: }
193:
194: /**
195: * Gets the TableFlashable installed on the table, if any.
196: *
197: * @param component the component.
198: * @return whether a Flashable is installed.
199: */
200: public static Flashable getFlashable(JComponent component) {
201: Object flashable = component
202: .getClientProperty(CLIENT_PROPERTY_FLASHABLE);
203: if (flashable instanceof Flashable) {
204: return ((Flashable) flashable);
205: } else {
206: return null;
207: }
208: }
209: }
|