Ignore:
Timestamp:
2011-12-27T12:56:27+01:00 (12 years ago)
Author:
jttt
Message:

Add posibility to run please wait runnable tasks in background

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
3 added
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapStatus.java

    r4604 r4718  
    3232import javax.swing.JLabel;
    3333import javax.swing.JPanel;
     34import javax.swing.JProgressBar;
    3435import javax.swing.JScrollPane;
    3536import javax.swing.JTextField;
    3637import javax.swing.Popup;
    3738import javax.swing.PopupFactory;
     39import javax.swing.UIManager;
    3840
    3941import org.openstreetmap.josm.Main;
     
    4446import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    4547import org.openstreetmap.josm.gui.help.Helpful;
     48import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor;
     49import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor.ProgressMonitorDialog;
    4650import org.openstreetmap.josm.tools.GBC;
    4751import org.openstreetmap.josm.tools.ImageProvider;
     
    9599    }
    96100
     101    public class BackgroundProgressMonitor implements ProgressMonitorDialog {
     102
     103        private String title;
     104        private String customText;
     105
     106        private void updateText() {
     107            if (customText != null && !customText.isEmpty()) {
     108                progressBar.setToolTipText(tr("{0} ({1})", title, customText));
     109            } else {
     110                progressBar.setToolTipText(title);
     111            }
     112        }
     113
     114        public void setVisible(boolean visible) {
     115            progressBar.setVisible(visible);
     116        }
     117
     118        public void updateProgress(int progress) {
     119            progressBar.setValue(progress);
     120            MapStatus.this.doLayout();
     121        }
     122
     123        public void setCustomText(String text) {
     124            this.customText = text;
     125            updateText();
     126        }
     127
     128        public void setTitle(String text) {
     129            this.title = text;
     130            updateText();
     131        }
     132
     133        public void setIndeterminate(boolean newValue) {
     134            UIManager.put("ProgressBar.cycleTime", UIManager.getInt("ProgressBar.repaintInterval") * 100);
     135            progressBar.setIndeterminate(newValue);
     136        }
     137
     138        @Override
     139        public void appendLogMessage(String message) {
     140            if (message != null && !message.isEmpty()) {
     141                System.out.println("appendLogMessage not implemented for background tasks. Message was: " + message);
     142            }
     143        }
     144
     145    }
     146
    97147    final ImageLabel lonText = new ImageLabel("lon", tr("The geographic longitude at the mouse pointer."), 11);
    98148    final ImageLabel nameText = new ImageLabel("name", tr("The name of the object at the mouse pointer."), 20);
     
    102152    final ImageLabel headingText = new ImageLabel("heading", tr("The (compass) heading of the line segment being drawn."), 6);
    103153    final ImageLabel distText = new ImageLabel("dist", tr("The length of the new way segment being drawn."), 10);
     154    final JProgressBar progressBar = new JProgressBar();
     155    public final BackgroundProgressMonitor progressMonitor = new BackgroundProgressMonitor();
    104156
    105157    /**
     
    658710        helpText.setEditable(false);
    659711        add(nameText, GBC.std().insets(3,0,0,0));
    660         add(helpText, GBC.eol().insets(3,0,0,0).fill(GBC.HORIZONTAL));
     712        add(helpText, GBC.std().insets(3,0,0,0).fill(GBC.HORIZONTAL));
     713
     714        progressBar.setMaximum(PleaseWaitProgressMonitor.PROGRESS_BAR_MAX);
     715        {
     716            GBC gbc = GBC.eol();
     717            gbc.ipadx = 100;
     718            add(progressBar,gbc);
     719        }
     720        progressBar.addMouseListener(new MouseAdapter() {
     721            @Override
     722            public void mouseClicked(MouseEvent e) {
     723                PleaseWaitProgressMonitor monitor = Main.currentProgressMonitor;
     724                if (monitor != null) {
     725                    monitor.showForegroundDialog();
     726                }
     727            }
     728        });
    661729
    662730        // The background thread
  • trunk/src/org/openstreetmap/josm/gui/PleaseWaitDialog.java

    r3501 r4718  
    2424
    2525import org.openstreetmap.josm.Main;
     26import org.openstreetmap.josm.gui.progress.PleaseWaitProgressMonitor.ProgressMonitorDialog;
    2627import org.openstreetmap.josm.tools.GBC;
    2728import org.openstreetmap.josm.tools.ImageProvider;
    2829
    29 public class PleaseWaitDialog extends JDialog {
     30public class PleaseWaitDialog extends JDialog implements ProgressMonitorDialog {
    3031
    3132    private final JProgressBar progressBar = new JProgressBar();
     
    3435    private final JLabel customText = new JLabel("");
    3536    public final BoundedRangeModel progress = progressBar.getModel();
    36     private  JButton btnCancel;
     37    private JButton btnCancel;
     38    private JButton btnInBackground;
    3739    /** the text area and the scroll pane for the log */
    3840    private JTextArea taLog = new JTextArea(5,50);
     
    4648        pane.add(customText, GBC.eol().fill(GBC.HORIZONTAL));
    4749        pane.add(progressBar, GBC.eop().fill(GBC.HORIZONTAL));
     50        JPanel buttons = new JPanel();
     51        buttons.setLayout(new GridBagLayout());
    4852        btnCancel = new JButton(tr("Cancel"));
    4953        btnCancel.setIcon(ImageProvider.get("cancel"));
    5054        btnCancel.setToolTipText(tr("Click to cancel the current operation"));
    51         pane.add(btnCancel, GBC.eol().anchor(GBC.CENTER));
     55        buttons.add(btnCancel);
     56        btnInBackground = new JButton(tr("In background"));
     57        btnInBackground.setToolTipText(tr("Click to run job in background"));
     58        buttons.add(btnInBackground, GBC.std().fill(GBC.VERTICAL).insets(5, 0, 0, 0));
     59        pane.add(buttons, GBC.eol().anchor(GBC.CENTER));
    5260        GridBagConstraints gc = GBC.eol().fill(GBC.BOTH);
    5361        gc.weighty = 1.0;
     
    132140    }
    133141
     142    public void setInBackgroundPossible(boolean value) {
     143        btnInBackground.setVisible(value);
     144    }
     145
    134146    /**
    135147     * Installs a callback for the cancel button. If callback is null, all action listeners
     
    148160        }
    149161    }
     162
     163    /**
     164     * Installs a callback for the "In background" button. If callback is null, all action listeners
     165     * are removed from the cancel button.
     166     *
     167     * @param callback the cancel callback
     168     */   
     169    public void setInBackgroundCallback(ActionListener callback) {
     170        if (callback == null) {
     171            ActionListener[] listeners = btnInBackground.getActionListeners();
     172            for (ActionListener l: listeners) {
     173                btnInBackground.removeActionListener(l);
     174            }
     175        } else {
     176            btnInBackground.addActionListener(callback);
     177        }
     178    }
     179
     180    @Override
     181    public void updateProgress(int progress) {
     182        this.progress.setValue(progress);
     183    }
     184
    150185}
  • trunk/src/org/openstreetmap/josm/gui/PleaseWaitRunnable.java

    r4310 r4718  
    1111import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    1212import org.openstreetmap.josm.gui.progress.ProgressMonitor.CancelListener;
     13import org.openstreetmap.josm.gui.progress.ProgressTaskId;
    1314import org.openstreetmap.josm.io.OsmTransferException;
    1415import org.openstreetmap.josm.tools.BugReportExceptionHandler;
     
    3536        this(title, false);
    3637    }
    37 
    3838    /**
    3939     * Create the runnable object with a given message for the user.
     
    7373    private void doRealRun() {
    7474        try {
     75            ProgressTaskId oldTaskId = null;
    7576            try {
    7677                progressMonitor.addCancelListener(this);
    7778                progressMonitor.beginTask(title);
     79                oldTaskId = progressMonitor.getProgressTaskId();
     80                progressMonitor.setProgressTaskId(canRunInBackground());
    7881                try {
    7982                    realRun();
     
    9295                progressMonitor.finishTask();
    9396                progressMonitor.removeCancelListener(this);
     97                progressMonitor.setProgressTaskId(oldTaskId);
    9498                if (progressMonitor instanceof PleaseWaitProgressMonitor) {
    9599                    ((PleaseWaitProgressMonitor)progressMonitor).close();
    96100                }
     101                afterFinish();
    97102            }
    98103        } catch (final Exception e) {
     
    110115            }
    111116        }
     117    }
     118
     119    /**
     120     * Can be overriden if something needs to run after progress monitor is closed.
     121     */
     122    protected void afterFinish() {
     123
    112124    }
    113125
     
    152164        return progressMonitor;
    153165    }
     166
     167    /**
     168     * Task can run in background if returned value <> null. Note that it's tasks responsibility
     169     * to ensure proper synchronization, PleaseWaitRunnable doesn't with it.
     170     * @return If returned value is <> null then task can run in background. TaskId could be used in future for "Always run in background" checkbox
     171     */
     172    public ProgressTaskId canRunInBackground() {
     173        return null;
     174    }
    154175}
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r4701 r4718  
    10211021                    getClass().getName() + ".geometry",
    10221022                    WindowGeometry.centerInWindow(Main.parent, new Dimension(1000, 500))
    1023             );
     1023                    );
    10241024            ed.showDialog();
    10251025            int v = ed.getValue();
     
    11771177                @Override
    11781178                protected void finish() {
     1179                }
     1180
     1181                @Override
     1182                protected void afterFinish() {
    11791183                    if(cancel)
    11801184                        return;
     
    12741278
    12751279            if (toDownload.size() > 1) {
    1276                 // hide progress dialog before displaying another pop up. Really closing the
    1277                 // dialog will be handled by PleaseWaitRunnable.
    1278                 if (progressMonitor instanceof PleaseWaitProgressMonitor) {
    1279                     ((PleaseWaitProgressMonitor) progressMonitor).getDialog().setVisible(false);
    1280                 }
    1281 
    12821280                int ret = JOptionPane.showConfirmDialog(
    12831281                        Main.parent,
  • trunk/src/org/openstreetmap/josm/gui/progress/AbstractProgressMonitor.java

    r4310 r4718  
    66import java.util.LinkedList;
    77import java.util.Queue;
     8
     9import javax.swing.SwingUtilities;
    810
    911public abstract class AbstractProgressMonitor implements ProgressMonitor {
     
    6163    }
    6264
     65    protected void doInEDT(Runnable runnable) {
     66        if (SwingUtilities.isEventDispatchThread()) {
     67            runnable.run();
     68        } else {
     69            SwingUtilities.invokeLater(runnable);
     70        }
     71    }
     72
    6373    /*=======
    6474     * Tasks
     
    6979    }
    7080
    71     public synchronized void beginTask(final String title, int ticks) {
     81    public synchronized void beginTask(String title, int ticks) {
    7282        this.taskTitle = title;
    7383        checkState(State.INIT);
  • trunk/src/org/openstreetmap/josm/gui/progress/ChildProgress.java

    r4642 r4718  
    5555        parent.childFinished(this);
    5656    }
     57
     58    @Override
     59    public void setProgressTaskId(ProgressTaskId taskId) {
     60        parent.setProgressTaskId(taskId);
     61    }
     62
     63    @Override
     64    public ProgressTaskId getProgressTaskId() {
     65        return parent.getProgressTaskId();
     66    }
    5767}
  • trunk/src/org/openstreetmap/josm/gui/progress/NullProgressMonitor.java

    r4310 r4718  
    8080        return 0;
    8181    }
     82
     83    @Override
     84    public void setProgressTaskId(ProgressTaskId taskId) {
     85    }
     86
     87    @Override
     88    public ProgressTaskId getProgressTaskId() {
     89        return null;
     90    }
    8291}
  • trunk/src/org/openstreetmap/josm/gui/progress/PleaseWaitProgressMonitor.java

    r4684 r4718  
    44import java.awt.Component;
    55import java.awt.Dialog;
    6 import java.awt.EventQueue;
    76import java.awt.Frame;
    87import java.awt.Window;
     
    1615
    1716import org.openstreetmap.josm.Main;
     17import org.openstreetmap.josm.gui.MapFrame;
     18import org.openstreetmap.josm.gui.MapStatus.BackgroundProgressMonitor;
    1819import org.openstreetmap.josm.gui.PleaseWaitDialog;
    1920
    2021public class PleaseWaitProgressMonitor extends AbstractProgressMonitor {
    2122
    22     private static final int PROGRESS_BAR_MAX = 100;
     23        /**
     24         * Implemented by both foreground dialog and background progress dialog (in status bar)
     25         */
     26    public interface ProgressMonitorDialog {
     27        void setVisible(boolean visible);
     28        void updateProgress(int progress);
     29        void setCustomText(String text);
     30        void setTitle(String text);
     31        void setIndeterminate(boolean newValue);
     32        void appendLogMessage(String message);
     33    }
     34
     35    public static final int PROGRESS_BAR_MAX = 100;
    2336    private final Window dialogParent;
    2437    private int currentProgressValue = 0;
    2538
     39    private boolean isInBackground;
    2640    private PleaseWaitDialog dialog;
    2741    private String windowTitle;
    28    
     42    protected ProgressTaskId taskId;
     43
    2944    private boolean cancelable;
     45
     46    private ProgressMonitorDialog getDialog() {
     47
     48        BackgroundProgressMonitor backgroundMonitor = null;
     49        MapFrame map = Main.map;
     50        if (map != null) {
     51            backgroundMonitor = map.statusLine.progressMonitor;
     52        }
     53
     54        if (backgroundMonitor != null) {
     55            backgroundMonitor.setVisible(isInBackground);
     56        }
     57        if (dialog != null) {
     58            dialog.setVisible(!isInBackground || backgroundMonitor == null);
     59        }
     60
     61        if (isInBackground && backgroundMonitor != null) {
     62            backgroundMonitor.setVisible(true);
     63            if (dialog != null) {
     64                dialog.setVisible(false);
     65            }
     66            return backgroundMonitor;
     67        } else if (backgroundMonitor != null) {
     68            backgroundMonitor.setVisible(false);
     69            if (dialog != null) {
     70                dialog.setVisible(true);
     71            }
     72            return dialog;
     73        } else if (dialog != null) {
     74            dialog.setVisible(true);
     75            return dialog;
     76        } else
     77            return null;
     78    }
    3079
    3180    public PleaseWaitProgressMonitor() {
     
    55104    };
    56105
     106    private ActionListener inBackgroundListener = new ActionListener() {
     107        @Override
     108        public void actionPerformed(ActionEvent e) {
     109            isInBackground = true;
     110            ProgressMonitorDialog dialog = getDialog();
     111            if (dialog != null) {
     112                dialog.setVisible(true);
     113            }
     114        }
     115    };
     116
    57117    private WindowListener windowListener = new WindowAdapter(){
    58118        @Override public void windowClosing(WindowEvent e) {
     
    69129    }
    70130
    71     private void doInEDT(Runnable runnable) {
    72         EventQueue.invokeLater(runnable);
    73     }
    74 
    75131    @Override
    76132    public void doBeginTask() {
    77133        doInEDT(new Runnable() {
    78134            public void run() {
     135                Main.currentProgressMonitor = PleaseWaitProgressMonitor.this;
    79136                if (dialogParent instanceof Frame && dialog == null) {
    80137                    dialog = new PleaseWaitDialog(dialogParent);
     
    89146                dialog.setCancelEnabled(cancelable);
    90147                dialog.setCancelCallback(cancelListener);
     148                dialog.setInBackgroundCallback(inBackgroundListener);
    91149                dialog.setCustomText("");
    92150                dialog.addWindowListener(windowListener);
     
    109167            doInEDT(new Runnable() {
    110168                public void run() {
    111                     dialog.progress.setValue(currentProgressValue);
     169                    ProgressMonitorDialog dialog = getDialog();
     170                    if (dialog != null) {
     171                        dialog.updateProgress(currentProgressValue);
     172                    }
    112173                }
    113174            });
     
    120181        doInEDT(new Runnable() {
    121182            public void run() {
    122                 dialog.setCustomText(title);
     183                ProgressMonitorDialog dialog = getDialog();
     184                if (dialog != null) {
     185                    dialog.setCustomText(title);
     186                }
    123187            }
    124188        });
     
    130194        doInEDT(new Runnable() {
    131195            public void run() {
    132                 dialog.currentAction.setText(title);
     196                ProgressMonitorDialog dialog = getDialog();
     197                if (dialog != null) {
     198                    dialog.setTitle(title);
     199                }
    133200            }
    134201        });
     
    139206        doInEDT(new Runnable() {
    140207            public void run() {
    141                 if (value && dialog.progress.getValue() == 0) {
    142                     // Enable only if progress is at the beginning. Doing intermediate progress in the middle
    143                     // will hide already reached progress
    144                     dialog.setIndeterminate(true);
    145                 } else {
    146                     dialog.setIndeterminate(false);
     208                // Enable only if progress is at the beginning. Doing intermediate progress in the middle
     209                // will hide already reached progress
     210                ProgressMonitorDialog dialog = getDialog();
     211                if (dialog != null) {
     212                    dialog.setIndeterminate(value && PleaseWaitProgressMonitor.this.dialog.progress.getValue() == 0);
    147213                }
    148214            }
     
    154220        doInEDT(new Runnable() {
    155221            public void run() {
    156                 dialog.appendLogMessage(message);
     222                ProgressMonitorDialog dialog = getDialog();
     223                if (dialog != null) {
     224                    dialog.appendLogMessage(message);
     225                }
    157226            }
    158227        });
     
    160229
    161230    public void close() {
    162         dialog.setVisible(false);
    163         dialog.setCancelCallback(null);
    164         dialog.removeWindowListener(windowListener);
    165         dialog.dispose();
    166         dialog = null;
    167     }
    168    
    169     public Component getDialog() {
    170         return dialog;
    171     }
     231        doInEDT(new Runnable() {
     232            @Override
     233            public void run() {
     234                dialog.setVisible(false);
     235                dialog.setCancelCallback(null);
     236                dialog.setInBackgroundCallback(null);
     237                dialog.removeWindowListener(windowListener);
     238                dialog.dispose();
     239                dialog = null;
     240                MapFrame map = Main.map;
     241                if (map != null) {
     242                    map.statusLine.progressMonitor.setVisible(false);
     243                }
     244                Main.currentProgressMonitor = null;
     245            }
     246        });
     247    }
     248
     249    public void showForegroundDialog() {
     250        isInBackground = false;
     251        doInEDT(new Runnable() {
     252            @Override
     253            public void run() {
     254                dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
     255                getDialog();
     256            }
     257        });
     258
     259    }
     260
     261    @Override
     262    public void setProgressTaskId(ProgressTaskId taskId) {
     263        this.taskId = taskId;
     264        doInEDT(new Runnable() {
     265            @Override
     266            public void run() {
     267                dialog.setInBackgroundPossible(PleaseWaitProgressMonitor.this.taskId != null && Main.isDisplayingMapView());
     268            }
     269        });
     270    }
     271
     272    @Override
     273    public ProgressTaskId getProgressTaskId() {
     274        return taskId;
     275    }
     276
    172277}
  • trunk/src/org/openstreetmap/josm/gui/progress/ProgressMonitor.java

    r4310 r4718  
    5050     */
    5151    void beginTask(String title, int ticks);
     52
    5253    /**
    5354     * Finish this progress monitor, close the dialog or inform the parent progress monitor
     
    5556     * then further calls are ignored)
    5657     */
     58
    5759    void finishTask();
    5860    /**
     
    126128     */
    127129    void appendLogMessage(String message);
     130
     131    /**
     132     * Should be used only by PleaseWaitRunnable. If taskId <> null then "In background" button will be shown
     133     * @param taskId
     134     */
     135    void setProgressTaskId(ProgressTaskId taskId);
     136
     137    /**
     138     * Should be used only by PleaseWaitRunnable
     139     * @param taskId
     140     */
     141    ProgressTaskId getProgressTaskId();
    128142}
  • trunk/src/org/openstreetmap/josm/gui/progress/SwingRenderingProgressMonitor.java

    r3083 r4718  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.gui.progress;
    3 
    4 import javax.swing.SwingUtilities;
    53
    64import org.openstreetmap.josm.tools.CheckParameterUtil;
     
    2725        CheckParameterUtil.ensureParameterNotNull(delegate, "delegate");
    2826        this.delegate = delegate;
    29     }
    30 
    31     private void doInEDT(Runnable runnable) {
    32         if (SwingUtilities.isEventDispatchThread()) {
    33             runnable.run();
    34         } else {
    35             SwingUtilities.invokeLater(runnable);
    36         }
    3727    }
    3828
     
    9383        });
    9484    }
     85
     86    @Override
     87    public void setProgressTaskId(ProgressTaskId taskId) {
     88    }
     89
     90    @Override
     91    public ProgressTaskId getProgressTaskId() {
     92        return null;
     93    }
    9594}
Note: See TracChangeset for help on using the changeset viewer.