// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.gui.preferences.plugin; import static org.openstreetmap.josm.tools.I18n.tr; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.Rectangle; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.List; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import javax.swing.event.HyperlinkEvent.EventType; import org.openstreetmap.josm.gui.widgets.HtmlPanel; import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; import org.openstreetmap.josm.plugins.PluginInformation; import org.openstreetmap.josm.tools.OpenBrowser; /** * A panel displaying the list of known plugins. */ public class PluginListPanel extends VerticallyScrollablePanel { static final class PluginCheckBoxMouseAdapter extends MouseAdapter { private final PluginCheckBox cbPlugin; PluginCheckBoxMouseAdapter(PluginCheckBox cbPlugin) { this.cbPlugin = cbPlugin; } @Override public void mouseClicked(MouseEvent e) { cbPlugin.doClick(); } } private transient PluginPreferencesModel model; /** * Constructs a new {@code PluginListPanel} with a default model. */ public PluginListPanel() { this(new PluginPreferencesModel()); } /** * Constructs a new {@code PluginListPanel} with a given model. * @param model The plugin model */ public PluginListPanel(PluginPreferencesModel model) { this.model = model; setLayout(new GridBagLayout()); } protected static String formatPluginRemoteVersion(PluginInformation pi) { StringBuilder sb = new StringBuilder(); if (pi.version == null || pi.version.trim().isEmpty()) { sb.append(tr("unknown")); } else { sb.append(pi.version); if (pi.oldmode) { sb.append('*'); } } return sb.toString(); } protected static String formatPluginLocalVersion(PluginInformation pi) { if (pi == null) return tr("unknown"); if (pi.localversion == null || pi.localversion.trim().isEmpty()) return tr("unknown"); return pi.localversion; } protected static String formatCheckboxTooltipText(PluginInformation pi) { if (pi == null) return ""; if (pi.downloadlink == null) return tr("Plugin bundled with JOSM"); else return pi.downloadlink; } /** * Displays a message when the plugin list is empty. */ public void displayEmptyPluginListInformation() { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.anchor = GridBagConstraints.CENTER; gbc.fill = GridBagConstraints.BOTH; gbc.insets = new Insets(40, 0, 40, 0); gbc.weightx = 1.0; gbc.weighty = 1.0; HtmlPanel hint = new HtmlPanel(); hint.setText( "<html>" + tr("Please click on <strong>Download list</strong> to download and display a list of available plugins.") + "</html>" ); add(hint, gbc); } /** * Refreshes the list. */ public void refreshView() { final Rectangle visibleRect = getVisibleRect(); List<PluginInformation> displayedPlugins = model.getDisplayedPlugins(); removeAll(); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.weightx = 1.0; if (displayedPlugins.isEmpty()) { displayEmptyPluginListInformation(); return; } int row = -1; for (final PluginInformation pi : displayedPlugins) { boolean selected = model.isSelectedPlugin(pi.getName()); String remoteversion = formatPluginRemoteVersion(pi); String localversion = formatPluginLocalVersion(model.getPluginInformation(pi.getName())); final PluginCheckBox cbPlugin = new PluginCheckBox(pi, selected, this, model); String pluginText = tr("{0}: Version {1} (local: {2})", pi.getName(), remoteversion, localversion); if (pi.requires != null && !pi.requires.isEmpty()) { pluginText += tr(" (requires: {0})", pi.requires); } JLabel lblPlugin = new JLabel( pluginText, pi.getScaledIcon(), SwingConstants.LEFT); lblPlugin.addMouseListener(new PluginCheckBoxMouseAdapter(cbPlugin)); gbc.gridx = 0; gbc.gridy = ++row; gbc.insets = new Insets(5, 5, 0, 5); gbc.weighty = 0.0; gbc.weightx = 0.0; add(cbPlugin, gbc); gbc.gridx = 1; gbc.weightx = 1.0; add(lblPlugin, gbc); HtmlPanel description = new HtmlPanel(); description.setText(pi.getDescriptionAsHtml()); description.getEditorPane().addHyperlinkListener(e -> { if (e.getEventType() == EventType.ACTIVATED) { OpenBrowser.displayUrl(e.getURL().toString()); } }); lblPlugin.setLabelFor(description); gbc.gridx = 1; gbc.gridy = ++row; gbc.insets = new Insets(3, 25, 5, 5); gbc.weighty = 1.0; add(description, gbc); } revalidate(); repaint(); SwingUtilities.invokeLater(() -> scrollRectToVisible(visibleRect)); } }