/* Wotonomy: OpenStep design patterns for pure Java applications. Copyright (C) 2000 Blacksmith, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org */ package net.wotonomy.ui.swing.util; import java.awt.Component; import java.awt.Container; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.net.URL; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JRootPane; import javax.swing.SwingUtilities; import javax.swing.Timer; /** * Visually highlights a component with the specified image for a brief period. * * @author michael@mpowers.net * @author $Author: cgruber $ * @version $Revision: 904 $ $Date: 2006-02-18 18:19:05 -0500 (Sat, 18 Feb 2006) * $ */ public class ComponentHighlighter implements ActionListener { // lots of state to track JRootPane rootPane; JComponent component; Component oldGlassPane; JLabel imageLabel; Timer timer; JPanel glassPane; /** * Alternate "Fire-and-forget" constructor loads an image from a URL. * * @param aComponent A Component that will be highlighted. * @param aURL A URL pointing to an image. */ public ComponentHighlighter(JComponent aComponent, URL aURL) { if (aURL == null) return; init(aComponent, Toolkit.getDefaultToolkit().getImage(aURL)); } /** * "Fire-and-forget" constructor. * * @param aComponent A Component that will be highlighted. * @param anImage An image, preferably an animated GIF with transparency, * that will slide along the length of the component. */ public ComponentHighlighter(JComponent aComponent, Image anImage) { init(aComponent, anImage); } protected void init(JComponent aComponent, Image anImage) { if ((aComponent == null) || (anImage == null)) return; component = aComponent; rootPane = SwingUtilities.getRootPane(component); oldGlassPane = rootPane.getGlassPane(); glassPane = new JPanel(); rootPane.setGlassPane(glassPane); glassPane.setVisible(true); glassPane.setOpaque(false); glassPane.setLayout(null); ImageIcon icon = new ImageIcon(anImage); imageLabel = new JLabel(); imageLabel.setIconTextGap(0); imageLabel.setIcon(icon); imageLabel.setSize(icon.getIconWidth(), icon.getIconHeight()); glassPane.add(imageLabel); Rectangle bounds = component.getBounds(); if (component.getParent() instanceof Component) { bounds = SwingUtilities.convertRectangle((Container) component.getParent(), bounds, rootPane.getContentPane()); } imageLabel.setLocation(bounds.x, bounds.y + bounds.height - imageLabel.getBounds().height); glassPane.revalidate(); glassPane.repaint(); component.transferFocus(); // halts a caret, if necessary timer = new Timer(80, this); timer.setRepeats(true); timer.start(); } public void actionPerformed(ActionEvent evt) { Rectangle bounds = imageLabel.getBounds(); Rectangle target = component.getBounds(); if (component.getParent() instanceof Component) { target = SwingUtilities.convertRectangle((Container) component.getParent(), target, rootPane.getContentPane()); } if (bounds.x + bounds.width > target.x + target.width) { // clean up and end timer.stop(); rootPane.setGlassPane(oldGlassPane); component.requestFocus(); return; } // else, slide to the right and continue imageLabel.setLocation(bounds.x + Math.max(bounds.width / 12, 1), bounds.y); imageLabel.repaint(); } } /* * $Log$ Revision 1.2 2006/02/18 23:19:05 cgruber Update imports and maven * dependencies. * * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in * eclipse-friendly maven-enabled packages. * * Revision 1.1.1.1 2000/12/21 15:51:18 mpowers Contributing wotonomy. * * Revision 1.2 2000/12/20 16:25:45 michael Added log to all files. * * */