Ignore:
Timestamp:
2010-01-11T21:06:49+01:00 (14 years ago)
Author:
Gubaer
Message:

fixed #3063: Downloading a plugin yields 3 dialogs at the same time: Downloading plugin / You should restart JOSM / Plugin downloaded
fixed #3628: JOSM blocking itself updating broken plugin
fixed #4187: JOSM deleted random files from disk after start (data loss)
fixed #4199: new version - plugins update vs josm start [should be fixed. Be careful if you have two JOSM instances running. Auto-update of plugins in the second instance will fail because plugin files are locked by the first instance]
fixed #4034: JOSM should auto-download plugin list when it hasn't been downloaded before [JOSM now displays a hint]

fixed: splash screen showing again even if plugins are auto-updated
new: progress indication integrated in splash screen
new: cancelable, asynchronous download of plugins from preferences
new: cancelable, asynchronous download of plugin list from plugin download sites
new: asynchronous loading of plugin information, launch of preferences dialog accelerated
refactored: clean up, documentation of plugin management code (PluginHandler)

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

Legend:

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

    r2801 r2817  
    2222import org.openstreetmap.josm.Main;
    2323import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
     24import org.openstreetmap.josm.gui.progress.ProgressMonitor;
    2425import org.openstreetmap.josm.io.DefaultProxySelector;
    2526import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
    2627import org.openstreetmap.josm.io.auth.DefaultAuthenticator;
    2728import org.openstreetmap.josm.plugins.PluginHandler;
     29import org.openstreetmap.josm.plugins.PluginInformation;
    2830import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    2931import org.openstreetmap.josm.tools.I18n;
     
    4547     * display the frame.
    4648     */
    47     public MainApplication(JFrame mainFrame, SplashScreen splash) {
    48         super(splash);
     49    public MainApplication(JFrame mainFrame) {
     50        super();
    4951        mainFrame.setContentPane(contentPane);
    5052        mainFrame.setJMenuBar(menu);
     
    151153        }
    152154
    153         SplashScreen splash = new SplashScreen(Main.pref.getBoolean("draw.splashscreen", true));
    154 
    155         splash.setStatus(tr("Activating updated plugins"));
    156         PluginHandler.earlyCleanup();
    157 
    158         splash.setStatus(tr("Loading early plugins"));
    159         PluginHandler.loadPlugins(true);
    160 
    161         splash.setStatus(tr("Setting defaults"));
     155        SplashScreen splash = new SplashScreen();
     156        ProgressMonitor monitor = splash.getProgressMonitor();
     157        monitor.beginTask(tr("Initializing"));
     158        monitor.setTicksCount(7);
     159        splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true));
     160
     161        List<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(monitor.createSubTaskMonitor(1, false));
     162        if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate()) {
     163            monitor.subTask(tr("Updating plugins..."));
     164            PluginHandler.updatePlugins(pluginsToLoad, monitor.createSubTaskMonitor(1, false));
     165        }
     166        monitor.worked(1);
     167
     168        monitor.subTask(tr("Installing updated plugins"));
     169        PluginHandler.installDownloadedPlugins();
     170        monitor.worked(1);
     171
     172        monitor.subTask(tr("Loading early plugins"));
     173        PluginHandler.loadEarlyPlugins(pluginsToLoad, monitor.createSubTaskMonitor(1, false));
     174        monitor.worked(1);
     175
     176        monitor.subTask(tr("Setting defaults"));
    162177        preConstructorInit(args);
    163178        removeObsoletePreferences();
    164         splash.setStatus(tr("Creating main GUI"));
     179        monitor.worked(1);
     180
     181        monitor.indeterminateSubTask(tr("Creating main GUI"));
    165182        JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor"));
    166183        Main.parent = mainFrame;
    167         final Main main = new MainApplication(mainFrame, splash);
    168         splash.setStatus(tr("Loading plugins"));
    169         PluginHandler.loadPlugins(false);
     184        final Main main = new MainApplication(mainFrame);
     185        monitor.worked(1);
     186
     187        monitor.subTask(tr("Loading plugins"));
     188        PluginHandler.loadLatePlugins(pluginsToLoad,  monitor.createSubTaskMonitor(1, false));
     189        monitor.worked(1);
    170190        toolbar.refreshToolbarControl();
    171 
     191        splash.setVisible(false);
     192        splash.dispose();
    172193        mainFrame.setVisible(true);
    173         splash.closeSplash();
    174194
    175195        if (((!args.containsKey("no-maximize") && !args.containsKey("geometry")
  • trunk/src/org/openstreetmap/josm/gui/SplashScreen.java

    r2358 r2817  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.AWTEvent;
    76import java.awt.Color;
    87import java.awt.Dimension;
     
    1211import java.awt.Insets;
    1312import java.awt.Toolkit;
    14 import java.awt.event.AWTEventListener;
    1513import java.awt.event.MouseAdapter;
    1614import java.awt.event.MouseEvent;
     
    1816import javax.swing.JLabel;
    1917import javax.swing.JPanel;
     18import javax.swing.JProgressBar;
    2019import javax.swing.JSeparator;
    2120import javax.swing.JWindow;
    22 import javax.swing.SwingUtilities;
    2321import javax.swing.border.Border;
    2422import javax.swing.border.EmptyBorder;
    2523import javax.swing.border.EtchedBorder;
    2624
    27 import org.openstreetmap.josm.actions.AboutAction;
    2825import org.openstreetmap.josm.data.Version;
     26import org.openstreetmap.josm.gui.progress.ProgressMonitor;
     27import org.openstreetmap.josm.gui.progress.ProgressRenderer;
     28import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor;
    2929import org.openstreetmap.josm.tools.ImageProvider;
    3030
     
    3232 * Show a splash screen so the user knows what is happening during startup.
    3333 *
    34  * @author cbrill
    3534 */
    3635public class SplashScreen extends JWindow {
    3736
    38     private JLabel status;
    39     private boolean visible;
     37    private SplashScreenProgressRenderer progressRenderer;
     38    private SwingRenderingProgressMonitor progressMonitor;
    4039
    41     private Runnable closerRunner;
    42 
    43     public SplashScreen(boolean visible) {
     40    public SplashScreen() {
    4441        super();
    45         this.visible=visible;
    46 
    47         if (!visible)
    48             return;
    4942
    5043        // Add a nice border to the main splash screen
     
    8982
    9083        // Add a status message
    91         status = new JLabel();
     84        progressRenderer = new SplashScreenProgressRenderer();
    9285        gbc.gridy = 3;
    93         gbc.insets = new Insets(0, 0, 0, 0);
    94         innerContentPane.add(status, gbc);
    95         setStatus(tr("Initializing"));
     86        gbc.insets = new Insets(5, 5, 10, 5);
     87        innerContentPane.add(progressRenderer, gbc);
     88        progressMonitor = new SwingRenderingProgressMonitor(progressRenderer);
    9689
    9790        pack();
     
    10396                screenSize.height / 2 - (labelSize.height / 2));
    10497
    105         // Method to close the splash screen when being clicked or when closeSplash is called
    106         closerRunner = new Runnable() {
    107             public void run() {
    108                 setVisible(false);
    109                 dispose();
    110             }
    111         };
    112 
    11398        // Add ability to hide splash screen by clicking it
    11499        addMouseListener(new MouseAdapter() {
     100            @Override
    115101            public void mousePressed(MouseEvent event) {
    116                 try {
    117                     closerRunner.run();
    118                 } catch (Exception e) {
    119                     e.printStackTrace();
    120                     // can catch InvocationTargetException
    121                     // can catch InterruptedException
    122                 }
     102                setVisible(false);
    123103            }
    124104        });
    125 
    126         // Hide splashscreen when other window is created
    127         Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.WINDOW_EVENT_MASK);
    128 
    129         setVisible(true);
    130105    }
    131106
    132     private AWTEventListener awtListener = new AWTEventListener() {
    133         public void eventDispatched(AWTEvent event) {
    134             if (event.getSource() != SplashScreen.this) {
    135                 closeSplash();
    136             }
    137         }
    138     };
    139 
    140     /**
    141      * This method sets the status message. It should be called prior to
    142      * actually doing the action.
    143      *
    144      * @param message
    145      *            the message to be displayed
    146      */
    147     public void setStatus(String message) {
    148         if (!visible)
    149             return;
    150         status.setText(message + "...");
     107    public ProgressMonitor getProgressMonitor() {
     108        return progressMonitor;
    151109    }
    152110
    153     /**
    154      * Closes the splashscreen. Call once you are done starting.
    155      */
    156     public void closeSplash() {
    157         if (!visible)
    158             return;
    159         Toolkit.getDefaultToolkit().removeAWTEventListener(awtListener);
    160         try {
    161             SwingUtilities.invokeLater(closerRunner);
    162         } catch (Exception e) {
    163             e.printStackTrace();
    164             // can catch InvocationTargetException
    165             // can catch InterruptedException
     111    static private class SplashScreenProgressRenderer extends JPanel implements ProgressRenderer {
     112        private JLabel lblTaskTitle;
     113        private JLabel lblCustomText;
     114        private JProgressBar progressBar;
     115
     116        protected void build() {
     117            setLayout(new GridBagLayout());
     118            GridBagConstraints gc = new GridBagConstraints();
     119            gc.gridx = 0;
     120            gc.gridy = 0;
     121            gc.fill = GridBagConstraints.HORIZONTAL;
     122            gc.weightx = 1.0;
     123            gc.weighty = 0.0;
     124            gc.insets = new Insets(5,0,0,5);
     125            add(lblTaskTitle = new JLabel(""), gc);
     126
     127            gc.gridx = 0;
     128            gc.gridy = 1;
     129            gc.fill = GridBagConstraints.HORIZONTAL;
     130            gc.weightx = 1.0;
     131            gc.weighty = 0.0;
     132            gc.insets = new Insets(5,0,0,5);
     133            add(lblCustomText = new JLabel(""), gc);
     134
     135            gc.gridx = 0;
     136            gc.gridy = 2;
     137            gc.fill = GridBagConstraints.HORIZONTAL;
     138            gc.weightx = 1.0;
     139            gc.weighty = 0.0;
     140            gc.insets = new Insets(5,0,0,5);
     141            add(progressBar = new JProgressBar(JProgressBar.HORIZONTAL), gc);
     142        }
     143
     144        public SplashScreenProgressRenderer() {
     145            build();
     146        }
     147
     148        public void setCustomText(String message) {
     149            lblCustomText.setText(message);
     150            repaint();
     151        }
     152
     153        public void setIndeterminate(boolean indeterminate) {
     154            progressBar.setIndeterminate(indeterminate);
     155            repaint();
     156        }
     157
     158        public void setMaximum(int maximum) {
     159            progressBar.setMaximum(maximum);
     160            repaint();
     161        }
     162
     163        public void setTaskTitle(String taskTitle) {
     164            lblTaskTitle.setText(taskTitle);
     165            repaint();
     166        }
     167
     168        public void setValue(int value) {
     169            progressBar.setValue(value);
     170            repaint();
    166171        }
    167172    }
  • trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java

    r2745 r2817  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import java.awt.Dimension;
     5import static org.openstreetmap.josm.tools.I18n.trn;
     6
     7import java.awt.BorderLayout;
     8import java.awt.Component;
     9import java.awt.FlowLayout;
     10import java.awt.GridBagConstraints;
    711import java.awt.GridBagLayout;
    8 import java.awt.Rectangle;
     12import java.awt.Insets;
    913import java.awt.event.ActionEvent;
    10 import java.awt.event.ActionListener;
     14import java.awt.event.ComponentAdapter;
     15import java.awt.event.ComponentEvent;
    1116import java.util.Collection;
    1217import java.util.LinkedList;
     18import java.util.List;
     19import java.util.logging.Logger;
    1320
    1421import javax.swing.AbstractAction;
     22import javax.swing.BorderFactory;
    1523import javax.swing.DefaultListModel;
    1624import javax.swing.JButton;
    1725import javax.swing.JLabel;
    1826import javax.swing.JList;
    19 import javax.swing.JTextField;
    2027import javax.swing.JOptionPane;
    2128import javax.swing.JPanel;
    2229import javax.swing.JScrollPane;
    23 import javax.swing.Scrollable;
     30import javax.swing.JTabbedPane;
     31import javax.swing.JTextField;
     32import javax.swing.SwingUtilities;
     33import javax.swing.UIManager;
     34import javax.swing.event.ChangeEvent;
     35import javax.swing.event.ChangeListener;
    2436import javax.swing.event.DocumentEvent;
    2537import javax.swing.event.DocumentListener;
    2638
    2739import org.openstreetmap.josm.Main;
    28 import org.openstreetmap.josm.plugins.PluginDownloader;
    29 import org.openstreetmap.josm.plugins.PluginSelection;
     40import org.openstreetmap.josm.gui.HelpAwareOptionPane;
     41import org.openstreetmap.josm.gui.help.HelpUtil;
     42import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesModel;
     43import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesPanel;
     44import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
     45import org.openstreetmap.josm.plugins.PluginDownloadTask;
     46import org.openstreetmap.josm.plugins.PluginInformation;
     47import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask;
     48import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask;
    3049import org.openstreetmap.josm.tools.GBC;
     50import org.openstreetmap.josm.tools.ImageProvider;
    3151
    3252public class PluginPreference implements PreferenceSetting {
     53    private final static Logger logger = Logger.getLogger(PluginPreference.class.getName());
    3354
    3455    public static class Factory implements PreferenceSettingFactory {
     
    3859    }
    3960
    40     private JPanel plugin;
    41     private JPanel pluginPanel = new NoHorizontalScrollPanel(new GridBagLayout());
    42     private PreferenceTabbedPane gui;
    43     private JScrollPane pluginPane;
    44     private PluginSelection selection = new PluginSelection();
    45     private JTextField txtFilter;
     61    public static String buildDownloadSummary(PluginDownloadTask task) {
     62        Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
     63        Collection<PluginInformation> failed = task.getFailedPlugins();
     64        StringBuilder sb = new StringBuilder();
     65        if (! downloaded.isEmpty()) {
     66            sb.append(trn(
     67                    "The following plugin has been downloaded <strong>successfully</strong>:",
     68                    "The following {0} plugins have been downloaded successfully:",
     69                    downloaded.size(),
     70                    downloaded.size()
     71            ));
     72            sb.append("<ul>");
     73            for(PluginInformation pi: downloaded) {
     74                sb.append("<li>").append(pi.name).append("</li>");
     75            }
     76            sb.append("</ul>");
     77        }
     78        if (! failed.isEmpty()) {
     79            sb.append(trn(
     80                    "Downloading the following plugin has <strong>failed</strong>:",
     81                    "Downloading the following {0} plugins has <strong>failed</strong>:",
     82                    failed.size(),
     83                    failed.size()
     84            ));
     85            sb.append("<ul>");
     86            for(PluginInformation pi: failed) {
     87                sb.append("<li>").append(pi.name).append("</li>");
     88            }
     89            sb.append("</ul>");
     90        }
     91        return sb.toString();
     92    }
     93
     94    private JTextField tfFilter;
     95    private PluginPreferencesPanel pnlPluginPreferences;
     96    private PluginPreferencesModel model;
     97    private JScrollPane spPluginPreferences;
     98
     99    protected JPanel buildSearchFieldPanel() {
     100        JPanel pnl  = new JPanel(new GridBagLayout());
     101        pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
     102        GridBagConstraints gc = new GridBagConstraints();
     103
     104        gc.anchor = GridBagConstraints.NORTHWEST;
     105        gc.fill = GridBagConstraints.HORIZONTAL;
     106        gc.weightx = 0.0;
     107        gc.insets = new Insets(0,0,0,3);
     108        pnl.add(new JLabel(tr("Search:")), gc);
     109
     110        gc.gridx = 1;
     111        gc.weightx = 1.0;
     112        pnl.add(tfFilter = new JTextField(), gc);
     113        tfFilter.setToolTipText(tr("Enter a search expression"));
     114        SelectAllOnFocusGainedDecorator.decorate(tfFilter);
     115        tfFilter.getDocument().addDocumentListener(new SearchFieldAdapter());
     116        return pnl;
     117    }
     118
     119    protected JPanel buildActionPanel() {
     120        JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
     121
     122        pnl.add(new JButton(new DownloadAvailablePluginsAction()));
     123        pnl.add(new JButton(new UpdateSelectedPluginsAction()));
     124        pnl.add(new JButton(new ConfigureSitesAction()));
     125        return pnl;
     126    }
     127
     128    protected JPanel buildContentPane() {
     129        JPanel pnl = new JPanel(new BorderLayout());
     130        pnl.add(buildSearchFieldPanel(), BorderLayout.NORTH);
     131        model  = new PluginPreferencesModel();
     132        spPluginPreferences = new JScrollPane(pnlPluginPreferences = new PluginPreferencesPanel(model));
     133        spPluginPreferences.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
     134        spPluginPreferences.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
     135        spPluginPreferences.getVerticalScrollBar().addComponentListener(
     136                new ComponentAdapter(){
     137                    @Override
     138                    public void componentShown(ComponentEvent e) {
     139                        spPluginPreferences.setBorder(UIManager.getBorder("ScrollPane.border"));
     140                    }
     141                    @Override
     142                    public void componentHidden(ComponentEvent e) {
     143                        spPluginPreferences.setBorder(null);
     144                    }
     145                }
     146        );
     147
     148        pnl.add(spPluginPreferences, BorderLayout.CENTER);
     149        pnl.add(buildActionPanel(), BorderLayout.SOUTH);
     150        return pnl;
     151    }
    46152
    47153    public void addGui(final PreferenceTabbedPane gui) {
    48         this.gui = gui;
    49         plugin = gui.createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false);
    50 
    51         txtFilter = new JTextField();
    52         JLabel lbFilter = new JLabel(tr("Search: "));
    53         lbFilter.setLabelFor(txtFilter);
    54         plugin.add(lbFilter);
    55         plugin.add(txtFilter, GBC.eol().fill(GBC.HORIZONTAL));
    56         txtFilter.getDocument().addDocumentListener(new DocumentListener(){
    57             public void changedUpdate(DocumentEvent e) {
    58                 action();
    59             }
    60 
    61             public void insertUpdate(DocumentEvent e) {
    62                 action();
    63             }
    64 
    65             public void removeUpdate(DocumentEvent e) {
    66                 action();
    67             }
    68 
    69             private void action() {
    70                 selection.drawPanel(pluginPanel);
    71             }
    72         });
    73         plugin.add(GBC.glue(0,10), GBC.eol());
    74 
    75         /* main plugin area */
    76         pluginPane = new JScrollPane(pluginPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    77         pluginPane.setBorder(null);
    78         plugin.add(pluginPane, GBC.eol().fill(GBC.BOTH));
    79         plugin.add(GBC.glue(0,10), GBC.eol());
    80 
    81         /* buttons at the bottom */
    82         JButton morePlugins = new JButton(tr("Download List"));
    83         morePlugins.addActionListener(new ActionListener(){
    84             public void actionPerformed(ActionEvent e) {
    85                 selection.updateDescription(pluginPanel);
    86             }
    87         });
    88         plugin.add(morePlugins, GBC.std().insets(0,0,10,0));
    89 
    90         JButton update = new JButton(tr("Update"));
    91         update.addActionListener(new ActionListener(){
    92             public void actionPerformed(ActionEvent e) {
    93                 selection.update(pluginPanel);
    94             }
    95         });
    96         plugin.add(update, GBC.std().insets(0,0,10,0));
    97 
    98         JButton configureSites = new JButton(tr("Configure Sites..."));
    99         configureSites.addActionListener(new ActionListener(){
    100             public void actionPerformed(ActionEvent e) {
    101                 configureSites();
    102             }
    103         });
    104         plugin.add(configureSites, GBC.std());
    105 
    106         selection.passTxtFilter(txtFilter);
    107         selection.loadPlugins();
    108         selection.drawPanel(pluginPanel);
     154        GridBagConstraints gc = new GridBagConstraints();
     155        gc.weightx = 1.0;
     156        gc.weighty = 1.0;
     157        gc.anchor = GridBagConstraints.NORTHWEST;
     158        gc.fill = GridBagConstraints.BOTH;
     159        gui.plugins.add(buildContentPane(), gc);
     160        pnlPluginPreferences.refreshView();
     161        gui.addChangeListener(new PluginPreferenceActivationListener(gui.plugins));
    109162    }
    110163
     
    113166        p.add(new JLabel(tr("Add JOSM Plugin description URL.")), GBC.eol());
    114167        final DefaultListModel model = new DefaultListModel();
    115         for (String s : PluginDownloader.getSites()) {
     168        for (String s : Main.pref.getPluginSites()) {
    116169            model.addElement(s);
    117170        }
     
    122175            public void actionPerformed(ActionEvent e) {
    123176                String s = JOptionPane.showInputDialog(
    124                         gui,
     177                        JOptionPane.getFrameForComponent(pnlPluginPreferences),
    125178                        tr("Add JOSM Plugin description URL."),
    126179                        tr("Enter URL"),
     
    136189                if (list.getSelectedValue() == null) {
    137190                    JOptionPane.showMessageDialog(
    138                             gui,
     191                            JOptionPane.getFrameForComponent(pnlPluginPreferences),
    139192                            tr("Please select an entry."),
    140193                            tr("Warning"),
     
    159212                if (list.getSelectedValue() == null) {
    160213                    JOptionPane.showMessageDialog(
    161                             gui,
     214                            JOptionPane.getFrameForComponent(pnlPluginPreferences),
    162215                            tr("Please select an entry."),
    163216                            tr("Warning"),
     
    171224        p.add(buttons, GBC.eol());
    172225        int answer = JOptionPane.showConfirmDialog(
    173                 gui,
     226                JOptionPane.getFrameForComponent(pnlPluginPreferences),
    174227                p,
    175228                tr("Configure Plugin Sites"), JOptionPane.OK_CANCEL_OPTION,
     
    181234            sites.add((String)model.getElementAt(i));
    182235        }
    183         PluginDownloader.setSites(sites);
     236        Main.pref.setPluginSites(sites);
     237    }
     238
     239    /**
     240     * Replies the list of plugins waiting for update or download
     241     *
     242     * @return the list of plugins waiting for update or download
     243     */
     244    public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() {
     245        return model.getPluginsScheduledForUpdateOrDownload();
    184246    }
    185247
    186248    public boolean ok() {
    187         return selection.finish();
    188     }
    189 
    190     private static class NoHorizontalScrollPanel extends JPanel implements Scrollable {
    191         public NoHorizontalScrollPanel(GridBagLayout gridBagLayout) {
    192             super(gridBagLayout);
    193         }
    194 
    195         public Dimension getPreferredScrollableViewportSize() {
    196             return super.getPreferredSize();
    197         }
    198 
    199         public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
    200             return 30;
    201         }
    202 
    203         public boolean getScrollableTracksViewportHeight() {
    204             return false;
    205         }
    206 
    207         public boolean getScrollableTracksViewportWidth() {
     249        if (model.isActivePluginsChanged()) {
     250            Main.pref.putCollection("plugins", model.getSelectedPluginNames());
    208251            return true;
    209252        }
    210 
    211         public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
    212             return 10;
     253        return false;
     254    }
     255
     256    public void readLocalPluginInformation() {
     257        final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask();
     258        Runnable r = new Runnable() {
     259            public void run() {
     260                if (task.isCanceled()) return;
     261                SwingUtilities.invokeLater(new Runnable() {
     262                    public void run() {
     263                        model.setAvailablePlugins(task.getAvailablePlugins());
     264                        pnlPluginPreferences.refreshView();
     265                    }
     266                });
     267            };
     268        };
     269        Main.worker.submit(task);
     270        Main.worker.submit(r);
     271    }
     272
     273    /**
     274     * The action for downloading the list of available plugins
     275     *
     276     */
     277    class DownloadAvailablePluginsAction extends AbstractAction {
     278
     279        public DownloadAvailablePluginsAction() {
     280            putValue(NAME,tr("Download list"));
     281            putValue(SHORT_DESCRIPTION, tr("Download the list of available plugins"));
     282            putValue(SMALL_ICON, ImageProvider.get("download"));
     283        }
     284
     285        public void actionPerformed(ActionEvent e) {
     286            final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
     287            Runnable continuation = new Runnable() {
     288                public void run() {
     289                    if (task.isCanceled()) return;
     290                    SwingUtilities.invokeLater(new Runnable() {
     291                        public void run() {
     292                            model.setAvailablePlugins(task.getAvailabePlugins());
     293                            pnlPluginPreferences.refreshView();
     294
     295                        }
     296                    });
     297                }
     298            };
     299            Main.worker.submit(task);
     300            Main.worker.submit(continuation);
     301        }
     302    }
     303
     304    /**
     305     * The action for downloading the list of available plugins
     306     *
     307     */
     308    class UpdateSelectedPluginsAction extends AbstractAction {
     309        public UpdateSelectedPluginsAction() {
     310            putValue(NAME,tr("Update plugins"));
     311            putValue(SHORT_DESCRIPTION, tr("Update the selected plugins"));
     312            putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
     313        }
     314
     315        protected void notifyDownloadResults(PluginDownloadTask task) {
     316            Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
     317            Collection<PluginInformation> failed = task.getFailedPlugins();
     318            StringBuilder sb = new StringBuilder();
     319            sb.append("<html>");
     320            sb.append(buildDownloadSummary(task));
     321            if (!downloaded.isEmpty()) {
     322                sb.append("Please restart JOSM to activate the downloaded plugins.");
     323            }
     324            sb.append("</html>");
     325            HelpAwareOptionPane.showOptionDialog(
     326                    pnlPluginPreferences,
     327                    sb.toString(),
     328                    tr("Update plugins"),
     329                    failed.isEmpty() ? JOptionPane.WARNING_MESSAGE : JOptionPane.INFORMATION_MESSAGE,
     330                            // FIXME: check help topic
     331                            HelpUtil.ht("/Preferences/Plugin")
     332            );
     333        }
     334
     335        public void actionPerformed(ActionEvent e) {
     336            List<PluginInformation> toUpdate = model.getSelectedPlugins();
     337            final PluginDownloadTask task = new PluginDownloadTask(
     338                    pnlPluginPreferences,
     339                    toUpdate,
     340                    tr("Update plugins")
     341            );
     342            Runnable r = new Runnable() {
     343                public void run() {
     344                    if (task.isCanceled())
     345                        return;
     346                    notifyDownloadResults(task);
     347                    model.refreshLocalPluginVersion(task.getDownloadedPlugins());
     348                    pnlPluginPreferences.refreshView();
     349                }
     350            };
     351            Main.worker.submit(task);
     352            Main.worker.submit(r);
     353        }
     354    }
     355
     356
     357    /**
     358     * The action for configuring the plugin download sites
     359     *
     360     */
     361    class ConfigureSitesAction extends AbstractAction {
     362        public ConfigureSitesAction() {
     363            putValue(NAME,tr("Configure sites..."));
     364            putValue(SHORT_DESCRIPTION, tr("Configure the list of sites where plugins are downloaded from"));
     365        }
     366
     367        public void actionPerformed(ActionEvent e) {
     368            configureSites();
     369        }
     370    }
     371
     372    /**
     373     * Listens to the activation of the plugin preferences tab. On activation it
     374     * reloads plugin information from the local file system.
     375     *
     376     */
     377    class PluginPreferenceActivationListener implements ChangeListener {
     378        private Component pane;
     379        public PluginPreferenceActivationListener(Component preferencesPane) {
     380            pane = preferencesPane;
     381        }
     382
     383        public void stateChanged(ChangeEvent e) {
     384            JTabbedPane tp = (JTabbedPane)e.getSource();
     385            if (tp.getSelectedComponent() == pane) {
     386                readLocalPluginInformation();
     387            }
     388        }
     389    }
     390
     391    /**
     392     * Applies the current filter condition in the filter text field to the
     393     * model
     394     */
     395    class SearchFieldAdapter implements DocumentListener {
     396        public void filter() {
     397            String expr = tfFilter.getText().trim();
     398            if (expr.equals("")) {
     399                expr = null;
     400            }
     401            model.filterDisplayedPlugins(expr);
     402            pnlPluginPreferences.refreshView();
     403        }
     404
     405        public void changedUpdate(DocumentEvent arg0) {
     406            filter();
     407        }
     408
     409        public void insertUpdate(DocumentEvent arg0) {
     410            filter();
     411        }
     412
     413        public void removeUpdate(DocumentEvent arg0) {
     414            filter();
    213415        }
    214416    }
  • trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java

    r2745 r2817  
    2323import javax.swing.JScrollPane;
    2424import javax.swing.JTabbedPane;
     25import javax.swing.SwingUtilities;
    2526
    2627import org.openstreetmap.josm.Main;
     28import org.openstreetmap.josm.plugins.PluginDownloadTask;
    2729import org.openstreetmap.josm.plugins.PluginHandler;
     30import org.openstreetmap.josm.plugins.PluginInformation;
    2831import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    2932import org.openstreetmap.josm.tools.GBC;
     
    4750    public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation."));
    4851    public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers."));
     52    public final JPanel plugins = createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false);
    4953
    5054    public final javax.swing.JTabbedPane displaycontent = new javax.swing.JTabbedPane();
     
    9599    }
    96100
     101    protected PluginPreference getPluginPreference() {
     102        for (PreferenceSetting setting: settings) {
     103            if (setting instanceof PluginPreference)
     104                return (PluginPreference) setting;
     105        }
     106        return null;
     107    }
     108
    97109    public void savePreferences() {
    98         boolean requiresRestart = false;
    99         for (PreferenceSetting setting : settings)
    100         {
    101             if(setting.ok()) {
    102                 requiresRestart = true;
     110
     111        // create a task for downloading plugins if the user has activated, yet not downloaded,
     112        // new plugins
     113        //
     114        final PluginPreference preference = getPluginPreference();
     115        final List<PluginInformation> toDownload = preference.getPluginsScheduledForUpdateOrDownload();
     116        final PluginDownloadTask task;
     117        if (! toDownload.isEmpty()) {
     118            task = new PluginDownloadTask(this, toDownload, tr("Download plugins"));
     119        } else {
     120            task = null;
     121        }
     122
     123        // this is the task which will run *after* the plugins are downloaded
     124        //
     125        final Runnable continuation = new Runnable() {
     126            public void run() {
     127                boolean requiresRestart = false;
     128                if (task != null && !task.isCanceled()) {
     129                    if (!task.getDownloadedPlugins().isEmpty()) {
     130                        requiresRestart = true;
     131                    }
     132                }
     133
     134                for (PreferenceSetting setting : settings) {
     135                    if (setting.ok()) {
     136                        requiresRestart = true;
     137                    }
     138                }
     139
     140                // build the messages. We only display one message, including the status
     141                // information from the plugin download task and - if necessary - a hint
     142                // to restart JOSM
     143                //
     144                StringBuffer sb = new StringBuffer();
     145                sb.append("<html>");
     146                if (task != null && !task.isCanceled()) {
     147                    sb.append(PluginPreference.buildDownloadSummary(task));
     148                }
     149                if (requiresRestart) {
     150                    sb.append(tr("You have to restart JOSM for some settings to take effect."));
     151                }
     152                sb.append("</html>");
     153
     154                // display the message, if necessary
     155                //
     156                if ((task != null && !task.isCanceled()) || requiresRestart) {
     157                    JOptionPane.showMessageDialog(
     158                            Main.parent,
     159                            sb.toString(),
     160                            tr("Warning"),
     161                            JOptionPane.WARNING_MESSAGE
     162                    );
     163                }
     164                Main.parent.repaint();
    103165            }
    104         }
    105         if (requiresRestart) {
    106             JOptionPane.showMessageDialog(
    107                     Main.parent,
    108                     tr("You have to restart JOSM for some settings to take effect."),
    109                     tr("Warning"),
    110                     JOptionPane.WARNING_MESSAGE
     166        };
     167
     168        if (task != null) {
     169            // if we have to launch a plugin download task we do it asynchronously, followed
     170            // by the remaining "save preferences" activites run on the Swing EDT.
     171            //
     172            Main.worker.submit(task);
     173            Main.worker.submit(
     174                    new Runnable() {
     175                        public void run() {
     176                            SwingUtilities.invokeLater(continuation);
     177                        }
     178                    }
    111179            );
    112         }
    113         Main.parent.repaint();
     180        } else {
     181            // no need for asynchronous activities. Simply run the remaining "save preference"
     182            // activities on this thread (we are already on the Swing EDT
     183            //
     184            continuation.run();
     185        }
    114186    }
    115187
Note: See TracChangeset for help on using the changeset viewer.