source: josm/trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java@ 2990

Last change on this file since 2990 was 2990, checked in by jttt, 14 years ago

Fix some eclipse warnings

  • Property svn:eol-style set to native
File size: 17.2 KB
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui.preferences;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
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;
11import java.awt.GridBagLayout;
12import java.awt.Insets;
13import java.awt.event.ActionEvent;
14import java.awt.event.ComponentAdapter;
15import java.awt.event.ComponentEvent;
16import java.util.Collection;
17import java.util.Collections;
18import java.util.LinkedList;
19import java.util.List;
20import java.util.logging.Logger;
21
22import javax.swing.AbstractAction;
23import javax.swing.BorderFactory;
24import javax.swing.DefaultListModel;
25import javax.swing.JButton;
26import javax.swing.JLabel;
27import javax.swing.JList;
28import javax.swing.JOptionPane;
29import javax.swing.JPanel;
30import javax.swing.JScrollPane;
31import javax.swing.JTabbedPane;
32import javax.swing.JTextField;
33import javax.swing.SwingUtilities;
34import javax.swing.UIManager;
35import javax.swing.event.ChangeEvent;
36import javax.swing.event.ChangeListener;
37import javax.swing.event.DocumentEvent;
38import javax.swing.event.DocumentListener;
39
40import org.openstreetmap.josm.Main;
41import org.openstreetmap.josm.gui.HelpAwareOptionPane;
42import org.openstreetmap.josm.gui.help.HelpUtil;
43import org.openstreetmap.josm.gui.preferences.plugin.PluginListPanel;
44import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesModel;
45import org.openstreetmap.josm.gui.preferences.plugin.PluginUpdatePolicyPanel;
46import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
47import org.openstreetmap.josm.plugins.PluginDownloadTask;
48import org.openstreetmap.josm.plugins.PluginInformation;
49import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask;
50import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask;
51import org.openstreetmap.josm.tools.GBC;
52import org.openstreetmap.josm.tools.ImageProvider;
53
54public class PluginPreference implements PreferenceSetting {
55 @SuppressWarnings("unused")
56 private final static Logger logger = Logger.getLogger(PluginPreference.class.getName());
57
58 public static class Factory implements PreferenceSettingFactory {
59 public PreferenceSetting createPreferenceSetting() {
60 return new PluginPreference();
61 }
62 }
63
64 public static String buildDownloadSummary(PluginDownloadTask task) {
65 Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
66 Collection<PluginInformation> failed = task.getFailedPlugins();
67 StringBuilder sb = new StringBuilder();
68 if (! downloaded.isEmpty()) {
69 sb.append(trn(
70 "The following plugin has been downloaded <strong>successfully</strong>:",
71 "The following {0} plugins have been downloaded <strong>successfully</strong>:",
72 downloaded.size(),
73 downloaded.size()
74 ));
75 sb.append("<ul>");
76 for(PluginInformation pi: downloaded) {
77 sb.append("<li>").append(pi.name).append("</li>");
78 }
79 sb.append("</ul>");
80 }
81 if (! failed.isEmpty()) {
82 sb.append(trn(
83 "Downloading the following plugin has <strong>failed</strong>:",
84 "Downloading the following {0} plugins has <strong>failed</strong>:",
85 failed.size(),
86 failed.size()
87 ));
88 sb.append("<ul>");
89 for(PluginInformation pi: failed) {
90 sb.append("<li>").append(pi.name).append("</li>");
91 }
92 sb.append("</ul>");
93 }
94 return sb.toString();
95 }
96
97 private JTextField tfFilter;
98 private PluginListPanel pnlPluginPreferences;
99 private PluginPreferencesModel model;
100 private JScrollPane spPluginPreferences;
101 private PluginUpdatePolicyPanel pnlPluginUpdatePolicy;
102
103 /**
104 * is set to true if this preference pane has been selected
105 * by the user
106 */
107 private boolean pluginPreferencesActivated = false;
108
109 protected JPanel buildSearchFieldPanel() {
110 JPanel pnl = new JPanel(new GridBagLayout());
111 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
112 GridBagConstraints gc = new GridBagConstraints();
113
114 gc.anchor = GridBagConstraints.NORTHWEST;
115 gc.fill = GridBagConstraints.HORIZONTAL;
116 gc.weightx = 0.0;
117 gc.insets = new Insets(0,0,0,3);
118 pnl.add(new JLabel(tr("Search:")), gc);
119
120 gc.gridx = 1;
121 gc.weightx = 1.0;
122 pnl.add(tfFilter = new JTextField(), gc);
123 tfFilter.setToolTipText(tr("Enter a search expression"));
124 SelectAllOnFocusGainedDecorator.decorate(tfFilter);
125 tfFilter.getDocument().addDocumentListener(new SearchFieldAdapter());
126 return pnl;
127 }
128
129 protected JPanel buildActionPanel() {
130 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER));
131
132 pnl.add(new JButton(new DownloadAvailablePluginsAction()));
133 pnl.add(new JButton(new UpdateSelectedPluginsAction()));
134 pnl.add(new JButton(new ConfigureSitesAction()));
135 return pnl;
136 }
137
138 protected JPanel buildPluginListPanel() {
139 JPanel pnl = new JPanel(new BorderLayout());
140 pnl.add(buildSearchFieldPanel(), BorderLayout.NORTH);
141 model = new PluginPreferencesModel();
142 spPluginPreferences = new JScrollPane(pnlPluginPreferences = new PluginListPanel(model));
143 spPluginPreferences.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
144 spPluginPreferences.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
145 spPluginPreferences.getVerticalScrollBar().addComponentListener(
146 new ComponentAdapter(){
147 @Override
148 public void componentShown(ComponentEvent e) {
149 spPluginPreferences.setBorder(UIManager.getBorder("ScrollPane.border"));
150 }
151 @Override
152 public void componentHidden(ComponentEvent e) {
153 spPluginPreferences.setBorder(null);
154 }
155 }
156 );
157
158 pnl.add(spPluginPreferences, BorderLayout.CENTER);
159 pnl.add(buildActionPanel(), BorderLayout.SOUTH);
160 return pnl;
161 }
162
163 protected JPanel buildContentPanel() {
164 JPanel pnl = new JPanel(new BorderLayout());
165 JTabbedPane tpPluginPreferences = new JTabbedPane();
166 tpPluginPreferences.add(buildPluginListPanel());
167 tpPluginPreferences.add(pnlPluginUpdatePolicy =new PluginUpdatePolicyPanel());
168 tpPluginPreferences.setTitleAt(0, tr("Plugins"));
169 tpPluginPreferences.setTitleAt(1, tr("Plugin update policy"));
170
171 pnl.add(tpPluginPreferences, BorderLayout.CENTER);
172 return pnl;
173 }
174
175 public void addGui(final PreferenceTabbedPane gui) {
176 GridBagConstraints gc = new GridBagConstraints();
177 gc.weightx = 1.0;
178 gc.weighty = 1.0;
179 gc.anchor = GridBagConstraints.NORTHWEST;
180 gc.fill = GridBagConstraints.BOTH;
181 gui.plugins.add(buildContentPanel(), gc);
182 pnlPluginPreferences.refreshView();
183 gui.addChangeListener(new PluginPreferenceActivationListener(gui.plugins));
184 }
185
186 private void configureSites() {
187 JPanel p = new JPanel(new GridBagLayout());
188 p.add(new JLabel(tr("Add JOSM Plugin description URL.")), GBC.eol());
189 final DefaultListModel model = new DefaultListModel();
190 for (String s : Main.pref.getPluginSites()) {
191 model.addElement(s);
192 }
193 final JList list = new JList(model);
194 p.add(new JScrollPane(list), GBC.std().fill());
195 JPanel buttons = new JPanel(new GridBagLayout());
196 buttons.add(new JButton(new AbstractAction(tr("Add")){
197 public void actionPerformed(ActionEvent e) {
198 String s = JOptionPane.showInputDialog(
199 JOptionPane.getFrameForComponent(pnlPluginPreferences),
200 tr("Add JOSM Plugin description URL."),
201 tr("Enter URL"),
202 JOptionPane.QUESTION_MESSAGE
203 );
204 if (s != null) {
205 model.addElement(s);
206 }
207 }
208 }), GBC.eol().fill(GBC.HORIZONTAL));
209 buttons.add(new JButton(new AbstractAction(tr("Edit")){
210 public void actionPerformed(ActionEvent e) {
211 if (list.getSelectedValue() == null) {
212 JOptionPane.showMessageDialog(
213 JOptionPane.getFrameForComponent(pnlPluginPreferences),
214 tr("Please select an entry."),
215 tr("Warning"),
216 JOptionPane.WARNING_MESSAGE
217 );
218 return;
219 }
220 String s = (String)JOptionPane.showInputDialog(
221 Main.parent,
222 tr("Edit JOSM Plugin description URL."),
223 tr("JOSM Plugin description URL"),
224 JOptionPane.QUESTION_MESSAGE,
225 null,
226 null,
227 list.getSelectedValue()
228 );
229 model.setElementAt(s, list.getSelectedIndex());
230 }
231 }), GBC.eol().fill(GBC.HORIZONTAL));
232 buttons.add(new JButton(new AbstractAction(tr("Delete")){
233 public void actionPerformed(ActionEvent event) {
234 if (list.getSelectedValue() == null) {
235 JOptionPane.showMessageDialog(
236 JOptionPane.getFrameForComponent(pnlPluginPreferences),
237 tr("Please select an entry."),
238 tr("Warning"),
239 JOptionPane.WARNING_MESSAGE
240 );
241 return;
242 }
243 model.removeElement(list.getSelectedValue());
244 }
245 }), GBC.eol().fill(GBC.HORIZONTAL));
246 p.add(buttons, GBC.eol());
247 int answer = JOptionPane.showConfirmDialog(
248 JOptionPane.getFrameForComponent(pnlPluginPreferences),
249 p,
250 tr("Configure Plugin Sites"), JOptionPane.OK_CANCEL_OPTION,
251 JOptionPane.PLAIN_MESSAGE);
252 if (answer != JOptionPane.OK_OPTION)
253 return;
254 Collection<String> sites = new LinkedList<String>();
255 for (int i = 0; i < model.getSize(); ++i) {
256 sites.add((String)model.getElementAt(i));
257 }
258 Main.pref.setPluginSites(sites);
259 }
260
261 /**
262 * Replies the list of plugins waiting for update or download
263 *
264 * @return the list of plugins waiting for update or download
265 */
266 public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() {
267 return model.getPluginsScheduledForUpdateOrDownload();
268 }
269
270 public boolean ok() {
271 if (! pluginPreferencesActivated)
272 return false;
273 pnlPluginUpdatePolicy.rememberInPreferences();
274 if (model.isActivePluginsChanged()) {
275 LinkedList<String> l = new LinkedList<String>(model.getSelectedPluginNames());
276 Collections.sort(l);
277 Main.pref.putCollection("plugins", l);
278 return true;
279 }
280 return false;
281 }
282
283 /**
284 * Reads locally available information about plugins from the local file system.
285 * Scans cached plugin lists from plugin download sites and locally available
286 * plugin jar files.
287 *
288 */
289 public void readLocalPluginInformation() {
290 final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask();
291 Runnable r = new Runnable() {
292 public void run() {
293 if (task.isCanceled()) return;
294 SwingUtilities.invokeLater(new Runnable() {
295 public void run() {
296 model.setAvailablePlugins(task.getAvailablePlugins());
297 pnlPluginPreferences.refreshView();
298 }
299 });
300 }
301 };
302 Main.worker.submit(task);
303 Main.worker.submit(r);
304 }
305
306 /**
307 * The action for downloading the list of available plugins
308 *
309 */
310 class DownloadAvailablePluginsAction extends AbstractAction {
311
312 public DownloadAvailablePluginsAction() {
313 putValue(NAME,tr("Download list"));
314 putValue(SHORT_DESCRIPTION, tr("Download the list of available plugins"));
315 putValue(SMALL_ICON, ImageProvider.get("download"));
316 }
317
318 public void actionPerformed(ActionEvent e) {
319 final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites());
320 Runnable continuation = new Runnable() {
321 public void run() {
322 if (task.isCanceled()) return;
323 SwingUtilities.invokeLater(new Runnable() {
324 public void run() {
325 model.setAvailablePlugins(task.getAvailabePlugins());
326 pnlPluginPreferences.refreshView();
327
328 }
329 });
330 }
331 };
332 Main.worker.submit(task);
333 Main.worker.submit(continuation);
334 }
335 }
336
337 /**
338 * The action for downloading the list of available plugins
339 *
340 */
341 class UpdateSelectedPluginsAction extends AbstractAction {
342 public UpdateSelectedPluginsAction() {
343 putValue(NAME,tr("Update plugins"));
344 putValue(SHORT_DESCRIPTION, tr("Update the selected plugins"));
345 putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh"));
346 }
347
348 protected void notifyDownloadResults(PluginDownloadTask task) {
349 Collection<PluginInformation> downloaded = task.getDownloadedPlugins();
350 Collection<PluginInformation> failed = task.getFailedPlugins();
351 StringBuilder sb = new StringBuilder();
352 sb.append("<html>");
353 sb.append(buildDownloadSummary(task));
354 if (!downloaded.isEmpty()) {
355 sb.append("Please restart JOSM to activate the downloaded plugins.");
356 }
357 sb.append("</html>");
358 HelpAwareOptionPane.showOptionDialog(
359 pnlPluginPreferences,
360 sb.toString(),
361 tr("Update plugins"),
362 failed.isEmpty() ? JOptionPane.WARNING_MESSAGE : JOptionPane.INFORMATION_MESSAGE,
363 // FIXME: check help topic
364 HelpUtil.ht("/Preferences/Plugin")
365 );
366 }
367
368 public void actionPerformed(ActionEvent e) {
369 List<PluginInformation> toUpdate = model.getSelectedPlugins();
370 final PluginDownloadTask task = new PluginDownloadTask(
371 pnlPluginPreferences,
372 toUpdate,
373 tr("Update plugins")
374 );
375 Runnable r = new Runnable() {
376 public void run() {
377 if (task.isCanceled())
378 return;
379 notifyDownloadResults(task);
380 model.refreshLocalPluginVersion(task.getDownloadedPlugins());
381 pnlPluginPreferences.refreshView();
382 }
383 };
384 Main.worker.submit(task);
385 Main.worker.submit(r);
386 }
387 }
388
389
390 /**
391 * The action for configuring the plugin download sites
392 *
393 */
394 class ConfigureSitesAction extends AbstractAction {
395 public ConfigureSitesAction() {
396 putValue(NAME,tr("Configure sites..."));
397 putValue(SHORT_DESCRIPTION, tr("Configure the list of sites where plugins are downloaded from"));
398 putValue(SMALL_ICON, ImageProvider.get("dialogs", "propertiesdialog"));
399 }
400
401 public void actionPerformed(ActionEvent e) {
402 configureSites();
403 }
404 }
405
406 /**
407 * Listens to the activation of the plugin preferences tab. On activation it
408 * reloads plugin information from the local file system.
409 *
410 */
411 class PluginPreferenceActivationListener implements ChangeListener {
412 private Component pane;
413 public PluginPreferenceActivationListener(Component preferencesPane) {
414 pane = preferencesPane;
415 }
416
417 public void stateChanged(ChangeEvent e) {
418 JTabbedPane tp = (JTabbedPane)e.getSource();
419 if (tp.getSelectedComponent() == pane) {
420 readLocalPluginInformation();
421 pluginPreferencesActivated = true;
422 }
423 }
424 }
425
426 /**
427 * Applies the current filter condition in the filter text field to the
428 * model
429 */
430 class SearchFieldAdapter implements DocumentListener {
431 public void filter() {
432 String expr = tfFilter.getText().trim();
433 if (expr.equals("")) {
434 expr = null;
435 }
436 model.filterDisplayedPlugins(expr);
437 pnlPluginPreferences.refreshView();
438 }
439
440 public void changedUpdate(DocumentEvent arg0) {
441 filter();
442 }
443
444 public void insertUpdate(DocumentEvent arg0) {
445 filter();
446 }
447
448 public void removeUpdate(DocumentEvent arg0) {
449 filter();
450 }
451 }
452}
Note: See TracBrowser for help on using the repository browser.