001    // License: GPL. Copyright 2007 by Immanuel Scholz and others
002    package org.openstreetmap.josm.gui;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.Component;
007    import java.awt.GridBagConstraints;
008    import java.awt.GridBagLayout;
009    import java.awt.event.ActionListener;
010    import java.awt.event.ComponentEvent;
011    import java.awt.event.ComponentListener;
012    
013    import javax.swing.BorderFactory;
014    import javax.swing.BoundedRangeModel;
015    import javax.swing.JButton;
016    import javax.swing.JDialog;
017    import javax.swing.JLabel;
018    import javax.swing.JOptionPane;
019    import javax.swing.JPanel;
020    import javax.swing.JProgressBar;
021    import javax.swing.JScrollPane;
022    import javax.swing.JTextArea;
023    import javax.swing.UIManager;
024    
025    import org.openstreetmap.josm.Main;
026    import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor.ProgressMonitorDialog;
027    import org.openstreetmap.josm.tools.GBC;
028    import org.openstreetmap.josm.tools.ImageProvider;
029    
030    public class PleaseWaitDialog extends JDialog implements ProgressMonitorDialog {
031    
032        private final JProgressBar progressBar = new JProgressBar();
033    
034        public final JLabel currentAction = new JLabel("");
035        private final JLabel customText = new JLabel("");
036        public final BoundedRangeModel progress = progressBar.getModel();
037        private JButton btnCancel;
038        private JButton btnInBackground;
039        /** the text area and the scroll pane for the log */
040        private JTextArea taLog = new JTextArea(5,50);
041        private  JScrollPane spLog;
042    
043        private void initDialog() {
044            setLayout(new GridBagLayout());
045            JPanel pane = new JPanel(new GridBagLayout());
046            pane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
047            pane.add(currentAction, GBC.eol().fill(GBC.HORIZONTAL));
048            pane.add(customText, GBC.eol().fill(GBC.HORIZONTAL));
049            pane.add(progressBar, GBC.eop().fill(GBC.HORIZONTAL));
050            JPanel buttons = new JPanel();
051            buttons.setLayout(new GridBagLayout());
052            btnCancel = new JButton(tr("Cancel"));
053            btnCancel.setIcon(ImageProvider.get("cancel"));
054            btnCancel.setToolTipText(tr("Click to cancel the current operation"));
055            buttons.add(btnCancel);
056            btnInBackground = new JButton(tr("In background"));
057            btnInBackground.setToolTipText(tr("Click to run job in background"));
058            buttons.add(btnInBackground, GBC.std().fill(GBC.VERTICAL).insets(5, 0, 0, 0));
059            pane.add(buttons, GBC.eol().anchor(GBC.CENTER));
060            GridBagConstraints gc = GBC.eol().fill(GBC.BOTH);
061            gc.weighty = 1.0;
062            gc.weightx = 1.0;
063            pane.add(spLog = new JScrollPane(taLog), gc);
064            spLog.setVisible(false);
065            setContentPane(pane);
066            setCustomText("");
067            setLocationRelativeTo(getParent());
068            addComponentListener(new ComponentListener() {
069                public void componentHidden(ComponentEvent e) {}
070                public void componentMoved(ComponentEvent e) {}
071                public void componentShown(ComponentEvent e) {}
072                public void componentResized(ComponentEvent ev) {
073                    int w = getWidth();
074                    if(w > 200) {
075                        Main.pref.putInteger("progressdialog.size",w);
076                    }
077                }
078            });
079        }
080    
081        public PleaseWaitDialog(Component parent) {
082            super(JOptionPane.getFrameForComponent(parent), ModalityType.DOCUMENT_MODAL);
083            initDialog();
084        }
085    
086        public void setIndeterminate(boolean newValue) {
087            UIManager.put("ProgressBar.cycleTime", UIManager.getInt("ProgressBar.repaintInterval") * 100);
088            progressBar.setIndeterminate(newValue);
089        }
090    
091        protected void adjustLayout() {
092            invalidate();
093            pack();
094            setSize(Main.pref.getInteger("progressdialog.size", 600), getSize().height);
095        }
096    
097        /**
098         * Sets a custom text line below currentAction. Can be used to display additional information
099         * @param text
100         */
101        public void setCustomText(String text) {
102            if(text == null || text.trim().length() == 0) {
103                customText.setVisible(false);
104                adjustLayout();
105                return;
106            }
107            customText.setText(text);
108            if (!customText.isVisible()) {
109                customText.setVisible(true);
110                adjustLayout();
111            }
112        }
113    
114        public void setCurrentAction(String text) {
115            currentAction.setText(text);
116        }
117    
118        /**
119         * Appends a log message to the progress dialog. If the log area isn't visible yet
120         * it becomes visible. The height of the progress dialog is slightly increased too.
121         *
122         * @param message the message to append to the log. Ignore if null or white space only.
123         */
124        public void appendLogMessage(String message) {
125            if (message == null || message.trim().length() ==0 )
126                return;
127            if (!spLog.isVisible()) {
128                spLog.setVisible(true);
129                taLog.setVisible(true);
130                adjustLayout();
131            }
132            taLog.append(message);
133            taLog.append("\n");
134            spLog.getVerticalScrollBar().setValue(spLog.getVerticalScrollBar().getMaximum());
135        }
136    
137        /**
138         * Sets whether the cancel button is enabled or not
139         *
140         * @param enabled true, if the cancel button is enabled; false otherwise
141         */
142        public void setCancelEnabled(boolean enabled) {
143            btnCancel.setEnabled(enabled);
144        }
145    
146        public void setInBackgroundPossible(boolean value) {
147            btnInBackground.setVisible(value);
148        }
149    
150        /**
151         * Installs a callback for the cancel button. If callback is null, all action listeners
152         * are removed from the cancel button.
153         *
154         * @param callback the cancel callback
155         */
156        public void setCancelCallback(ActionListener callback) {
157            if (callback == null) {
158                ActionListener[] listeners = btnCancel.getActionListeners();
159                for (ActionListener l: listeners) {
160                    btnCancel.removeActionListener(l);
161                }
162            } else {
163                btnCancel.addActionListener(callback);
164            }
165        }
166    
167        /**
168         * Installs a callback for the "In background" button. If callback is null, all action listeners
169         * are removed from the cancel button.
170         *
171         * @param callback the cancel callback
172         */
173        public void setInBackgroundCallback(ActionListener callback) {
174            if (callback == null) {
175                ActionListener[] listeners = btnInBackground.getActionListeners();
176                for (ActionListener l: listeners) {
177                    btnInBackground.removeActionListener(l);
178                }
179            } else {
180                btnInBackground.addActionListener(callback);
181            }
182        }
183    
184        @Override
185        public void updateProgress(int progress) {
186            this.progress.setValue(progress);
187        }
188    
189    }