001    /*
002     * Copyright 2002-2004 the original author or authors.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005     * use this file except in compliance with the License. You may obtain a copy of
006     * the License at
007     * 
008     * http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012     * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013     * License for the specific language governing permissions and limitations under
014     * the License.
015     */
016    package org.springframework.richclient.progress;
017    
018    import java.awt.Component;
019    import java.awt.Cursor;
020    import java.awt.event.KeyAdapter;
021    import java.awt.event.MouseAdapter;
022    import java.awt.event.MouseMotionAdapter;
023    
024    import javax.swing.JPanel;
025    import javax.swing.JRootPane;
026    import javax.swing.SwingUtilities;
027    
028    /**
029     * Support for showing a Busy Cursor during a long running process.
030     */
031    public class BusyIndicator {
032    
033        public static class BusyGlassPanel extends JPanel {
034    
035            public static final Component INSTANCE = new BusyGlassPanel();
036    
037            public static Component instance() {
038                return INSTANCE;
039            }
040    
041            public BusyGlassPanel() {
042                super.setOpaque(false);
043                super.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
044                super.addKeyListener((new KeyAdapter() {
045                }));
046                super.addMouseListener((new MouseAdapter() {
047                }));
048                super.addMouseMotionListener((new MouseMotionAdapter() {
049                }));
050            }
051        }
052    
053        /**
054         * Runs the given <code>Runnable</code> while providing busy feedback
055         * using this busy indicator.
056         *
057         * @param component the display on which the busy feedback should be displayed. If the
058         *                  display is null, the Display for the current thread will be
059         *                  used. If there is no Display for the current thread, the
060         *                  runnable code will be executed and no busy feedback will be
061         *                  displayed.
062         * @param runnable  the runnable for which busy feedback is to be shown
063         *
064         * @see #showWhile
065         */
066        public static void showWhile(Component component, Runnable runnable) {
067            if (component != null) {
068                showAt(component);
069            }
070            try {
071                runnable.run();
072            }
073            catch (RuntimeException x) {
074                x.printStackTrace();
075                throw x;
076            }
077            catch (Error x) {
078                x.printStackTrace();
079                throw x;
080            }
081            finally {
082                if (component != null) {
083                    clearAt(component);
084                }
085            }
086        }
087    
088        public static void showAt(Component component) {
089            JRootPane root = SwingUtilities.getRootPane(component);
090            if (root != null && root.isShowing()) {
091                root.setGlassPane(BusyGlassPanel.INSTANCE);
092                root.getGlassPane().setVisible(true);
093            }
094        }
095    
096        public static void clearAt(Component component) {
097            JRootPane root = SwingUtilities.getRootPane(component);
098            if (root != null && root.isShowing()) {
099                root.getGlassPane().setVisible(false);
100            }
101        }
102    
103    }
104