/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ro.nextreports.designer.util; import java.awt.*; import javax.swing.*; import javax.swing.border.EtchedBorder; import javax.swing.border.BevelBorder; /** * Created by IntelliJ IDEA. * User: mihai.panaitescu * Date: Sep 1, 2006 * Time: 5:31:15 PM */ /** * UIActivator is an utility class used for showing long task execution. * It's purpose is to block all possible user interactions with the parent * frame, parent dialog or a parent rootPane and to show a progress bar. * If an action is passed in the "start" method a stop button is shown, which * allows to regain user interactions on the parent frame. * The action is responsible to 'really' stop the task execution! * <p/> * <p> * Usage : * UIActivator activator = new UIActivator(frame, "Wait ...", tasks); * Thread t = new Thread(new TestRunnable(activator)); * activator.start(new StopAction(t)); * t.start(); * <p/> * Inside TestRunnable (updateProgress and stop activator methods must be called from the EDT) : * <p/> * try { * .... * for (int i = 0; i < activator.getTasks(); i++) { * // the long task must be interruptible * try { * // long task .... * } catch (InterruptedException e) { * activator.stop(); * return; * } * final String message = (i + 1) + " files ..."; * SwingUtilities.invokeLater(new Runnable() { * public void run() { * activator.updateProgress(message); * } * }); * } * .... * } finally { * SwingUtilities.invokeLater(new Runnable() { * public void run() { * activator.stop(); * } * }); * } * </p> */ public class UIActivator { private Color PB_FOREGROUND = new Color(0, 130, 130); private WaitGlassPane glass; private String message; private JPanel panel; private JFrame parentFrame; private JDialog parentDialog; private JRootPane parentRootPane; private boolean indeterminate; private JLabel textLabel; private JProgressBar progressBar; private boolean disableProgressBar; private int tasks; /** * Constructor. Creates an UIActivator with an indeterminate progress bar * The glass panel is set on the specified frame. * * @param parentFrame parent frame * @param message message that appears in a label before the progress bar */ public UIActivator(JFrame parentFrame, String message) { this.parentFrame = parentFrame; this.message = message; this.indeterminate = true; this.tasks = 0; // does not matter } /** * Constructor. Creates an UIActivator with a determinate progress bar * The glass panel is set on the specified frame. * * @param parentFrame parent frame * @param message message that appears in a label before the progress bar * @param tasks number of tasks which represents the maximum value for progress bar */ public UIActivator(JFrame parentFrame, String message, int tasks) { this.parentFrame = parentFrame; this.message = message; this.indeterminate = false; this.tasks = tasks; // cell spacing and length are used only if progress bar has setStringPainted(false)!!! //UIDefaults defaults = UIManager.getDefaults(); //defaults.put("ProgressBar.cellSpacing", 2); //defaults.put("ProgressBar.cellLength", 3); } /** * Constructor. Creates an UIActivator with an indeterminate progress bar * The glass panel is set on the specified dialog. * * @param parentDialog parent dialog * @param message message that appears in a label before the progress bar */ public UIActivator(JDialog parentDialog, String message) { this.parentDialog = parentDialog; this.message = message; this.indeterminate = true; this.tasks = 0; // does not matter } /** * Constructor. Creates an UIActivator with a determinate progress bar * The glass panel is set on the specified dialog. * * @param parentDialog parent dialog * @param message message that appears in a label before the progress bar * @param tasks number of tasks which represents the maximum value for progress bar */ public UIActivator(JDialog parentDialog, String message, int tasks) { this.parentDialog = parentDialog; this.message = message; this.indeterminate = false; this.tasks = tasks; // cell spacing and length are used only if progress bar has setStringPainted(false)!!! //UIDefaults defaults = UIManager.getDefaults(); //defaults.put("ProgressBar.cellSpacing", 2); //defaults.put("ProgressBar.cellLength", 3); } /** * Constructor. Creates an UIActivator with an indeterminate progress bar * The glass panel is set on the specified rootPane. * This constructor is useful when we want to block only a component from a window. * <p/> * Instead of adding the component directly to the layout, we will add it to a rootPane and * the rootPane is added to the layout : * JRootPane rootPane = new JRootPane(); * rootPane.setContentPane(panel); * layout.add(rootPane); * * @param parentRootPane parent rootPane * @param message message that appears in a label before the progress bar */ public UIActivator(JRootPane parentRootPane, String message) { this.parentRootPane = parentRootPane; this.message = message; this.indeterminate = true; this.tasks = 0; // does not matter } /** * Constructor. Creates an UIActivator with a determinate progress bar * The glass panel is set on the specified rootPane. * This constructor is useful when we want to block only a component from a window. * <p/> * Instead of adding the component directly to the layout, we will add it to a rootPane and * the rootPane is added to the layout : * JRootPane rootPane = new JRootPane(); * rootPane.setContentPane(panel); * layout.add(rootPane); * * @param parentRootPane parent rootPane * @param message message that appears in a label before the progress bar * @param tasks number of tasks which represents the maximum value for progress bar */ public UIActivator(JRootPane parentRootPane, String message, int tasks) { this.parentRootPane = parentRootPane; this.message = message; this.indeterminate = false; this.tasks = tasks; // cell spacing and length are used only if progress bar has setStringPainted(false)!!! //UIDefaults defaults = UIManager.getDefaults(); //defaults.put("ProgressBar.cellSpacing", 2); //defaults.put("ProgressBar.cellLength", 3); } /** * Start UIActivator * no stop button is shown */ public void start() { start(null); } /** * Start UIActivator * * @param action action used to stop long task * if action is null no stop button is shown, otherwise a stop button is shown * and the action is called when button is clicked */ public void start(AbstractAction action) { if (parentFrame != null) { parentFrame.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } else if (parentDialog != null) { parentDialog.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } else if (parentRootPane != null) { parentRootPane.setCursor(new Cursor(Cursor.WAIT_CURSOR)); } else { return; } glass = new WaitGlassPane(); //glass.setText(message); glass.setLayout(new GridBagLayout()); // Panel shown over glass panel String text = decorateText(message); textLabel = new JLabel(text); progressBar = new JProgressBar(); progressBar.setIndeterminate(indeterminate); //progressBar.setForeground(PB_FOREGROUND); //progressBar.setUI(new GradientProgressBarUI()); //progressBar.setBorderPainted(false); //progressBar.setOpaque(false); progressBar.setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED)); if (!indeterminate) { progressBar.setMinimum(0); progressBar.setMaximum(tasks); progressBar.setValue(0); progressBar.setStringPainted(true); } panel = new JPanel(new GridBagLayout()); panel.setBackground(new Color(192, 192, 192, 150)); panel.setBorder(new EtchedBorder(EtchedBorder.RAISED)); panel.add(textLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 10, 0)); if (!disableProgressBar) { panel.add(progressBar, new GridBagConstraints(0, 1, 1, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(0, 5, 5, 5), 0, 0)); } if (action != null) { JButton stopButton = new JButton(action); stopButton.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEtchedBorder(), BorderFactory.createCompoundBorder( BorderFactory.createBevelBorder(BevelBorder.LOWERED), BorderFactory.createBevelBorder(BevelBorder.RAISED)))); stopButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); panel.add(stopButton, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0)); } glass.add(new JLabel(""), new GridBagConstraints(0, 0, 1, 1, 0.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.VERTICAL, new Insets(10, 10, 10, 10), 0, 0)); if (!disableProgressBar || (action != null)) { glass.add(panel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(10, 10, 40, 10), 0, 0)); } if (parentFrame != null) { parentFrame.setGlassPane(glass); } else if (parentDialog != null) { parentDialog.setGlassPane(glass); } else { parentRootPane.setGlassPane(glass); } glass.start(); } /** * Update text * * @param message text */ public void updateText(String message) { if ((message != null) && (!message.trim().equals(""))) { textLabel.setText(decorateText(message)); } } /** * Update progress bar * * @param message progress bar message * if message is null percentage is shown, otherwise the message is shown */ public void updateProgress(String message) { if ((message != null) && (!message.trim().equals(""))) { progressBar.setString(message); } progressBar.setValue(progressBar.getValue() + 1); } /** * Update progress bar * * @param value progress bar value * @param message progress bar message * if message is null percentage is shown, otherwise the message is shown */ public void updateProgress(int value, String message) { if ((message != null) && (!message.trim().equals(""))) { progressBar.setString(message); } progressBar.setValue(value); } /** * Update progress bar, percentage is shown over the progress bar */ public void updateProgress() { updateProgress(null); } /** * Update progress bar * * @param value progress bar value */ public void updateProgress(int value) { updateProgress(value, null); } /** * Stop UIActivator * User regains the input interactions over the parent frame */ public void stop() { // a small delay after the job is done (just for visualization effects : // see full percent for a small amount of time) try { Thread.sleep(200); } catch (InterruptedException e) { // notihing to do } if (parentFrame != null) { parentFrame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } else if (parentDialog != null) { parentDialog.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } else if (parentRootPane != null) { parentRootPane.setCursor(new Cursor(Cursor.DEFAULT_CURSOR)); } if (glass != null) { glass.stop(); // components added to glass panel must be removed // otherwise they will appear at every repaint ! if (panel != null) { glass.remove(panel); } panel = null; glass = null; } } /** * Get the number of tasks * * @return number of tasks */ public int getTasks() { return tasks; } /** * Disable progress bar */ public void disableProgressBar() { this.disableProgressBar = true; } private String decorateText(String text) { return "<html><b><font size=\"3\">" + text + "</font></b></html>"; } }