package org.rr.commons.swing.components.button; import java.awt.Dimension; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.SwingConstants; import javax.swing.SwingWorker; import org.rr.commons.swing.components.resources.ImageResourceBundle; import org.rr.commons.swing.icon.AnimatedIcon; /** * The progress button shows a progress indicator icon during the * action is performed. * <BR><BR> * Hint: Use {@link #setHorizontalTextPosition(int)} for control the icon / progress icon * icon location. * <BR><BR> * Use {@link #setIconTextGap(int)} to control the distance between the text and the icon / progress icon */ public class JProgressButton extends JButton { private static final long serialVersionUID = -7625670036906963026L; private String progressString = "Wait..."; private final ProgressAction progressAction = new ProgressAction(); public String getProgressString() { return progressString; } public void setProgressString(String progressString) { this.progressString = progressString; } protected void fireActionPerformed(final ActionEvent event) { final SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { final Dimension oldSize = getPreferredSize(); //change to progress mode. progressAction.setWrapp(false); //update the button properties configurePropertiesFromAction(progressAction); setPreferredSize(oldSize); //fire the action internalFireActionPerformed(event); return null; } @Override protected void done() { //change to wrapping mode. progressAction.setWrapp(true); //update the button properties configurePropertiesFromAction(progressAction); } }; sw.execute(); } protected void internalFireActionPerformed(ActionEvent event) { // Guaranteed to return a non-null array Object[] listeners = listenerList.getListenerList(); ActionEvent e = null; // Process the listeners last to first, notifying // those that are interested in this event for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ActionListener.class) { // Lazily create the event: if (e == null) { String actionCommand = event.getActionCommand(); if (actionCommand == null) { actionCommand = getActionCommand(); } e = new ActionEvent(JProgressButton.this, ActionEvent.ACTION_PERFORMED, actionCommand, event.getWhen(), event.getModifiers()); } if (((ActionListener) listeners[i + 1]) instanceof ProgressAction) { ((ProgressAction) listeners[i + 1]).wrappedAction.actionPerformed(e); } else { ((ActionListener) listeners[i + 1]).actionPerformed(e); } } } } @Override public void setAction(Action a) { this.progressAction.setText(progressString); this.progressAction.setWrappedAction(a); super.setAction(this.progressAction); } private static class ProgressAction extends AbstractAction { private static final long serialVersionUID = -3981953770330568086L; Action wrappedAction; private boolean wrapp = true; ProgressAction() { super(); ImageIcon progressIcon = ImageResourceBundle.getResourceAsImageIcon("progress.gif"); final AnimatedIcon icon = new AnimatedIcon(progressIcon); setLargeIcon(icon); } /** * Tells if the Action is in wrapping or progress mode. * @param wrapp <code>true</code> for wrappign mode and <code>false</code> for progress mode. */ void setWrapp(boolean wrapp) { this.wrapp = wrapp; } /** * Sets the indicator text * @param text The indicator text. */ public void setText(String text) { super.putValue(Action.NAME, text); } /** * Sets the indicator icon. * @param icon indicator icon */ public void setLargeIcon(Icon icon) { super.putValue(Action.LARGE_ICON_KEY, icon); } public void setWrappedAction(Action a) { this.wrappedAction = a; } @Override public void actionPerformed(ActionEvent e) { if(wrapp) { wrappedAction.actionPerformed(e); } } @Override public boolean isEnabled() { if(wrapp) { return wrappedAction.isEnabled(); } else { //false in progress mode return false; } } @Override public void putValue(String key, Object newValue) { wrappedAction.putValue(key, newValue); } @Override public Object getValue(String key) { if(wrapp) { return wrappedAction.getValue(key); } else { return super.getValue(key); } } } public static void main(String[] args) { JFrame frame = new JFrame(); JProgressButton b = new JProgressButton(); b.setSize(100, 25); b.setLocation(10, 10); AbstractAction abstractAction = new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { System.out.println("actionPerformed"); try { Thread.sleep(2000); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } System.out.println("actionPerformed end"); } }; abstractAction.putValue(AbstractAction.NAME, "test"); b.setAction(abstractAction); b.setHorizontalTextPosition(SwingConstants.LEADING); b.setIconTextGap(16); frame.setSize(800, 600); frame.getContentPane().setLayout(null); frame.getContentPane().add(b); frame.setVisible(true); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } }