/src/net/java/swingfx/waitwithstyle/CancelableProgessAdapter.java
https://code.google.com/p/ascension-log-visualizer/ · Java · 209 lines · 108 code · 18 blank · 83 comment · 27 complexity · f8369d0816e406244954763b006da618 MD5 · raw file
- package net.java.swingfx.waitwithstyle;
-
- import java.awt.Cursor;
- import java.awt.Rectangle;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.beans.PropertyChangeEvent;
- import java.beans.PropertyChangeListener;
-
- import javax.swing.*;
-
- /**
- * An InfiniteProgressAdapter that adds a cancel button to a CancelableAdaptee
- * (the InfiniteProgressPanel or the PerformanceProgressPanel).
- *
- * @author Michael Bushe michael@bushe.com
- */
- public class CancelableProgessAdapter implements InfiniteProgressAdapter {
- protected CancelableAdaptee progressPanel;
-
- protected JLabel textLabel;
-
- protected JButton cancelButton;
-
- protected JButton applicationDefaultButton;
-
- private JRootPane rootPane;
-
- /**
- * Construct with an adaptee
- *
- * @param progressPanel
- * the adaptee, if null, setAdaptee() can be called later (before
- * animation starting) with a non-null value.
- */
- public CancelableProgessAdapter(
- final CancelableAdaptee progressPanel) {
- setAdaptee(progressPanel);
- }
-
- /**
- * Must be called with a non-null before any of the adaptee's calls to
- * animationStarting, etc. are called.
- *
- * @param progressPanel
- */
- public void setAdaptee(
- final CancelableAdaptee progressPanel) {
- this.progressPanel = progressPanel;
- }
-
- /**
- * Adds a cancel listener that will be called back when the the cancel
- * button is clicked.
- *
- * @param listener
- * a cancel callback
- */
- public void addCancelListener(
- final ActionListener listener) {
- if (cancelButton == null)
- cancelButton = createCancelButton();
- if (cancelButton != null)
- cancelButton.addActionListener(listener);
- }
-
- /**
- * Eemoves a cancel listener that would have been called back when the the
- * cancel button was clicked.
- *
- * @param listener
- * a cancel callback
- */
- public void removeCancelListener(
- final ActionListener listener) {
- if (cancelButton != null)
- cancelButton.removeActionListener(listener);
- }
-
- /**
- * Overridable to supply your own button. Overriders should:
- * <ul>
- * <li>Call progresspanel.stop() on action performed.
- * <li>Set the cursor on their button, else the busy cursor will not
- * indicate to the user that the button is clickable.
- * </ul>
- */
- protected JButton createCancelButton() {
- if (progressPanel instanceof JComponent) {
- rootPane = ((JComponent) progressPanel).getRootPane();
- if (rootPane != null)
- rootPane.addPropertyChangeListener(new PropertyChangeListener() {
- public void propertyChange(
- final PropertyChangeEvent evt) {
- if ("defaultButton".equals(evt.getPropertyName())) {
- /*
- * Track the default button every time it changes so
- * that when the cancel button becomes the default
- * button, as it must when the user clicks it, its
- * possible to reset the default button back to
- * being the button that the application expects it
- * to be... Ideally, the cancel button should never
- * even get focus as a focus change is not
- * transparent to application code. A better scheme
- * might be to set cancel button to be not focusable
- * and then click the button programmatically as
- * appropriate.
- */
- final JButton oldDefaultButton = (JButton) evt.getOldValue();
- if (oldDefaultButton != cancelButton)
- applicationDefaultButton = oldDefaultButton;
- }
- }
- });
- }
-
- final JButton button = new JButton("Cancel");
- button.setCursor(Cursor.getDefaultCursor());
- button.addActionListener(new ActionListener() {
- public void actionPerformed(
- final ActionEvent e) {
- progressPanel.stop();
- if (rootPane != null) {
- if (applicationDefaultButton != null)
- rootPane.setDefaultButton(applicationDefaultButton);
- applicationDefaultButton = null;
- }
- }
- });
- return button;
- }
-
- /**
- * Called by the CancelableAdaptee (progress panel) when the animation is
- * starting. Does nothing by default.
- */
- public void animationStarting() {}
-
- /**
- * Called by the CancelableAdaptee (progress panel) when the animation is
- * stopping. Removes the button from the progressPanel by default.
- */
- public void animationStopping() {
- if (cancelButton != null)
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- progressPanel.getComponent().remove(cancelButton);
- }
- });
- }
-
- /**
- * Called by the CancelableAdaptee (progress panel) when it is finished
- * painting itself.
- * <p>
- * By default, paints the cancelButton if it is not null.
- *
- * @param maxY
- * the lowest (on the screen) Y that the adapteee used - you
- * should paint your components before this.
- */
- public void paintSubComponents(
- final double maxY) {
- if (cancelButton != null) {
- final int buttonWidth = 80;
- final Rectangle cancelButtonBoundedRectangle = new Rectangle((progressPanel.getComponent()
- .getWidth() / 2 - buttonWidth / 2),
- (int) maxY + 10,
- 80,
- 21);
- cancelButton.setBounds(cancelButtonBoundedRectangle);
- }
- }
-
- /**
- * Called by the CancelableAdaptee (progress panel) when the animation's
- * ramp up (fade in) is over. Adds the cancel button to the progressPanel by
- * default (if not null), via an invokeLater().
- */
- public void rampUpEnded() {
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- if (cancelButton != null)
- progressPanel.getComponent().add(cancelButton);
- }
- });
- }
-
- /**
- * Called to programmatically click the cancel button. Can be called from
- * any thread.
- */
- public void doCancel() {
- final Runnable runner = new Runnable() {
- public void run() {
- if (cancelButton == null)
- // could be called programmatically, easy way to simulate,
- // don't care about expense
- cancelButton = createCancelButton();
- if (cancelButton != null)
- cancelButton.doClick();
- }
- };
- if (SwingUtilities.isEventDispatchThread())
- runner.run();
- else
- SwingUtilities.invokeLater(runner);
- }
- }