package org.rr.commons.swing.components.util;
import java.awt.Color;
import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
/**
* Adds highlight border color functionality to the given component.
*/
public class EnablePropertyChangeHighlighterSupport {
private final JComponent target;
private Color color;
int lineWidth;
/**
* @param target Component which should get the highlight support.
* @param color The highlight color. If it is null, highlight support will be removed from the component.
* @param lineWidth The with of the highlight border.
*/
public EnablePropertyChangeHighlighterSupport(JComponent target, Color color, int lineWidth) {
this.target = target;
this.color = color;
this.lineWidth = lineWidth;
removeHighlightPropertyChangeListener(target);
if(color != null) {
target.addPropertyChangeListener(new HighlightPropertyChangeListener());
}
}
/**
* Removes all registered {@link HighlightPropertyChangeListener} from the given component.
*/
private void removeHighlightPropertyChangeListener(JComponent c) {
final PropertyChangeListener[] propertyChangeListeners = c.getPropertyChangeListeners();
for (PropertyChangeListener listener : propertyChangeListeners) {
if(listener instanceof HighlightPropertyChangeListener) {
c.removePropertyChangeListener(listener);
}
}
}
private class HighlightPropertyChangeListener implements PropertyChangeListener {
private boolean isBlinking = false;
@Override
public void propertyChange(PropertyChangeEvent evt) {
if(!isBlinking && evt.getPropertyName().equals("enabled") && target.isEnabled()) {
isBlinking = true;
new Thread() {
public void run() {
try {
final Border oldBorder = target.getBorder();
final Insets borderInsets = setupInset(oldBorder.getBorderInsets(target), lineWidth);
final Border highlight = new CompoundBorder(new LineBorder(color, lineWidth), new EmptyBorder(borderInsets));
for(int i = 0; i < 3 && target.isEnabled(); i++) {
//set the highlight border
SwingUtilities.invokeLater(new Runnable() {
public void run() {
target.setBorder(highlight);
}
});
try {Thread.sleep(200); } catch (InterruptedException e) {}
//reset the border
SwingUtilities.invokeLater(new Runnable() {
public void run() {
target.setBorder(oldBorder);
}
});
try {Thread.sleep(200); } catch (InterruptedException e) {}
}
//reset the border
SwingUtilities.invokeLater(new Runnable() {
public void run() {
target.setBorder(oldBorder);
}
});
} finally {
try {Thread.sleep(200); } catch (InterruptedException e) {}
isBlinking = false;
}
}
private Insets setupInset(Insets borderInsets, int subtract) {
borderInsets.top = borderInsets.top - lineWidth >= 0 ? borderInsets.top - lineWidth : 0;
borderInsets.bottom = borderInsets.bottom - lineWidth >= 0 ? borderInsets.bottom - lineWidth : 0;
borderInsets.left = borderInsets.left - lineWidth >= 0 ? borderInsets.left - lineWidth : 0;
borderInsets.right = borderInsets.right - lineWidth >= 0 ? borderInsets.right - lineWidth : 0;
return borderInsets;
}
}.start();
}
}
}
}