source: josm/trunk/src/org/openstreetmap/josm/plugins/PluginSelection.java@ 1397

Last change on this file since 1397 was 1397, checked in by stoecker, 15 years ago

apply patches from xeen for #1977.

File size: 13.2 KB
Line 
1//License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.plugins;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5import static org.openstreetmap.josm.tools.I18n.trn;
6
7import java.awt.GridBagConstraints;
8import java.awt.GridBagLayout;
9import java.awt.Insets;
10import java.awt.event.ActionEvent;
11import java.awt.event.ActionListener;
12
13import java.io.File;
14import java.io.FileReader;
15import java.io.IOException;
16import java.util.Arrays;
17import java.util.Collection;
18import java.util.Collections;
19import java.util.Comparator;
20import java.util.HashMap;
21import java.util.HashSet;
22import java.util.LinkedList;
23import java.util.Map;
24import java.util.Set;
25import java.util.SortedMap;
26import java.util.TreeMap;
27import java.util.Map.Entry;
28
29import javax.swing.AbstractAction;
30import javax.swing.BorderFactory;
31import javax.swing.JCheckBox;
32import javax.swing.JEditorPane;
33import javax.swing.JOptionPane;
34import javax.swing.JPanel;
35import javax.swing.event.HyperlinkEvent;
36import javax.swing.event.HyperlinkListener;
37import javax.swing.event.HyperlinkEvent.EventType;
38import javax.swing.UIManager;
39
40import org.openstreetmap.josm.Main;
41import org.openstreetmap.josm.gui.ExtendedDialog;
42import org.openstreetmap.josm.tools.OpenBrowser;
43import org.openstreetmap.josm.tools.XmlObjectParser.Uniform;
44
45public class PluginSelection {
46
47 private Map<String, Boolean> pluginMap;
48 private Map<String, PluginDescription> availablePlugins;
49
50 public void updateDescription(JPanel pluginPanel) {
51 int count = PluginDownloader.downloadDescription();
52 if (count > 0)
53 JOptionPane.showMessageDialog(Main.parent,
54 trn("Downloaded plugin information from {0} site",
55 "Downloaded plugin information from {0} sites", count, count));
56 else
57 JOptionPane.showMessageDialog(Main.parent, tr("No plugin information found."));
58 drawPanel(pluginPanel);
59 }
60
61 public void update(JPanel pluginPanel) {
62 // refresh description
63 int num = PluginDownloader.downloadDescription();
64 Boolean done = false;
65 drawPanel(pluginPanel);
66
67 Set<PluginDescription> toUpdate = new HashSet<PluginDescription>();
68 StringBuilder toUpdateStr = new StringBuilder();
69 for (PluginProxy proxy : PluginHandler.pluginList) {
70 PluginDescription description = availablePlugins.get(proxy.info.name);
71 if (description != null && (description.version == null || description.version.equals("")) ?
72 (proxy.info.version != null && proxy.info.version.equals("")) : !description.version.equals(proxy.info.version)) {
73 toUpdate.add(description);
74 toUpdateStr.append(description.name+"\n");
75 }
76 }
77 if (toUpdate.isEmpty()) {
78 JOptionPane.showMessageDialog(Main.parent, tr("All installed plugins are up to date."));
79 done = true;
80 } else {
81 int answer = new ExtendedDialog(Main.parent,
82 tr("Update"),
83 tr("Update the following plugins:\n\n{0}", toUpdateStr.toString()),
84 new String[] {tr("Update Plugins"), tr("Cancel")},
85 new String[] {"dialogs/refresh.png", "cancel.png"}).getValue();
86 if (answer == 1) {
87 PluginDownloader.update(toUpdate);
88 done = true;
89 }
90 }
91 if (done && num >= 1)
92 Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis()));
93 drawPanel(pluginPanel);
94 }
95
96 public Boolean finish() {
97 Collection<PluginDescription> toDownload = new LinkedList<PluginDescription>();
98 String msg = "";
99 for (Entry<String, Boolean> entry : pluginMap.entrySet()) {
100 if (entry.getValue() && PluginInformation.findPlugin(entry.getKey()) == null) {
101 toDownload.add(availablePlugins.get(entry.getKey()));
102 msg += entry.getKey() + "\n";
103 }
104 }
105 if (!toDownload.isEmpty()) {
106 int answer = new ExtendedDialog(Main.parent,
107 tr("Download missing plugins"),
108 tr("Download the following plugins?\n\n{0}", msg),
109 new String[] {tr("Download Plugins"), tr("Cancel")},
110 new String[] {"download.png", "cancel.png"}).getValue();
111 if (answer != 1)
112 for (PluginDescription pd : toDownload)
113 pluginMap.put(pd.name, false);
114 else
115 for (PluginDescription pd : toDownload)
116 if (!PluginDownloader.downloadPlugin(pd))
117 pluginMap.put(pd.name, false);
118
119 }
120 LinkedList<String> plugins = new LinkedList<String>();
121 for (Map.Entry<String, Boolean> d : pluginMap.entrySet()) {
122 if (d.getValue())
123 plugins.add(d.getKey());
124 }
125
126 Collections.sort(plugins);
127 return Main.pref.putCollection("plugins", plugins);
128 }
129
130 /* return true when plugin list changed */
131 public void drawPanel(JPanel pluginPanel) {
132 availablePlugins = getAvailablePlugins();
133 Collection<String> enabledPlugins = Main.pref.getCollection("plugins", null);
134
135 if (pluginMap == null)
136 pluginMap = new HashMap<String, Boolean>();
137 else
138 // Keep the map in bounds; possibly slightly pointless.
139 for (final String pname : pluginMap.keySet())
140 if (availablePlugins.get(pname) == null) pluginMap.remove(pname);
141
142 pluginPanel.removeAll();
143
144 GridBagConstraints gbc = new GridBagConstraints();
145 gbc.gridx = 0;
146 gbc.anchor = GridBagConstraints.NORTHWEST;
147
148 int row = 0;
149 for (final PluginDescription plugin : availablePlugins.values()) {
150 boolean enabled = (enabledPlugins != null) && enabledPlugins.contains(plugin.name);
151 if (pluginMap.get(plugin.name) == null)
152 pluginMap.put(plugin.name, enabled);
153
154 String remoteversion = plugin.version;
155 if ((remoteversion == null) || remoteversion.equals(""))
156 remoteversion = tr("unknown");
157
158 String localversion;
159 PluginInformation p = PluginInformation.findPlugin(plugin.name);
160 if (p != null) {
161 if (p.version != null && !p.version.equals(""))
162 localversion = p.version;
163 else
164 localversion = tr("unknown");
165 localversion = " (" + localversion + ")";
166 } else
167 localversion = "";
168
169 final JCheckBox pluginCheck = new JCheckBox(
170 tr("{0}: Version {1}{2}", plugin.name, remoteversion, localversion),
171 pluginMap.get(plugin.name));
172 gbc.gridy = row++;
173 gbc.insets = new Insets(5,5,0,5);
174 gbc.weighty = 0.1;
175 gbc.fill = GridBagConstraints.NONE;
176 pluginPanel.add(pluginCheck, gbc);
177
178 pluginCheck.setToolTipText(plugin.resource != null ? ""+plugin.resource : tr("Plugin bundled with JOSM"));
179
180 JEditorPane description = new JEditorPane();
181 description.setContentType("text/html");
182 description.setEditable(false);
183 description.setText("<html><i>"+(plugin.description==null?tr("no description available"):plugin.description)+"</i></html>");
184 description.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
185 description.setBackground(UIManager.getColor("Panel.background"));
186 description.addHyperlinkListener(new HyperlinkListener() {
187 public void hyperlinkUpdate(HyperlinkEvent e) {
188 if(e.getEventType() == EventType.ACTIVATED) {
189 OpenBrowser.displayUrl(e.getURL().toString());
190 }
191 }
192 });
193
194 gbc.gridy = row++;
195 gbc.insets = new Insets(3,5,5,5);
196 gbc.weighty = 0.9;
197 gbc.weightx = 1.0;
198 gbc.anchor = GridBagConstraints.WEST;
199 gbc.fill = GridBagConstraints.HORIZONTAL;
200 pluginPanel.add(description, gbc);
201
202 pluginCheck.addActionListener(new ActionListener(){
203 public void actionPerformed(ActionEvent e) {
204 // if user enabled a plugin, it is not loaded but found somewhere on disk: offer to delete jar
205 if (pluginCheck.isSelected()) {
206 PluginInformation plinfo = PluginInformation.findPlugin(plugin.name);
207 if ((getLoaded(plugin.name) == null) && (plinfo != null)) {
208 try {
209 int answer = new ExtendedDialog(Main.parent,
210 tr("Plugin already exists"),
211 tr("Plugin archive already available. Do you want to download"
212 + " the current version by deleting existing archive?\n\n{0}",
213 plinfo.file.getCanonicalPath()),
214 new String[] {tr("Delete and Download"), tr("Cancel")},
215 new String[] {"download.png", "cancel.png"}).getValue();
216
217 if (answer == 1) {
218 if (!plinfo.file.delete()) {
219 JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", plinfo.file.getCanonicalPath()));
220 }
221 }
222 } catch (IOException e1) {
223 e1.printStackTrace();
224 JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", e1.getMessage()));
225 }
226 }
227 }
228 pluginMap.put(plugin.name, pluginCheck.isSelected());
229 }
230 });
231 }
232 pluginPanel.updateUI();
233 }
234
235 /**
236 * Return information about a loaded plugin.
237 *
238 * Note that if you call this in your plugins bootstrap, you may get <code>null</code> if
239 * the plugin requested is not loaded yet.
240 *
241 * @return The PluginInformation to a specific plugin, but only if the plugin is loaded.
242 * If it is not loaded, <code>null</code> is returned.
243 */
244 private static PluginInformation getLoaded(String pluginName) {
245 for (PluginProxy p : PluginHandler.pluginList)
246 if (p.info.name.equals(pluginName))
247 return p.info;
248 return null;
249 }
250
251 private Map<String, PluginDescription> getAvailablePlugins() {
252 SortedMap<String, PluginDescription> availablePlugins = new TreeMap<String, PluginDescription>(new Comparator<String>(){
253 public int compare(String o1, String o2) {
254 return o1.compareToIgnoreCase(o2);
255 }
256 });
257 for (String location : PluginInformation.getPluginLocations()) {
258 File[] pluginFiles = new File(location).listFiles();
259 if (pluginFiles != null) {
260 Arrays.sort(pluginFiles);
261 for (File f : pluginFiles) {
262 if (!f.isFile())
263 continue;
264 if (f.getName().endsWith(".jar")) {
265 try {
266 PluginInformation info = new PluginInformation(f);
267 if (!availablePlugins.containsKey(info.name))
268 availablePlugins.put(info.name, new PluginDescription(
269 info.name,
270 info.description,
271 PluginInformation.fileToURL(f).toString(),
272 info.version));
273 } catch (PluginException x) {
274 }
275 } else if (f.getName().matches("^[0-9]+-site.*\\.xml$")) {
276 try {
277 Uniform<PluginDescription> parser = new Uniform<PluginDescription>(new FileReader(f), "plugin", PluginDescription.class);
278 for (PluginDescription pd : parser)
279 if (!availablePlugins.containsKey(pd.name))
280 availablePlugins.put(pd.name, pd);
281 } catch (Exception e) {
282 e.printStackTrace();
283 JOptionPane.showMessageDialog(Main.parent, tr("Error reading plugin information file: {0}", f.getName()));
284 }
285 }
286 }
287 }
288 }
289 for (PluginProxy proxy : PluginHandler.pluginList)
290 if (!availablePlugins.containsKey(proxy.info.name))
291 availablePlugins.put(proxy.info.name, new PluginDescription(
292 proxy.info.name,
293 proxy.info.description,
294 proxy.info.file == null ? null :
295 PluginInformation.fileToURL(proxy.info.file).toString(),
296 proxy.info.version));
297 return availablePlugins;
298 }
299}
Note: See TracBrowser for help on using the repository browser.