Changeset 5121 in josm


Ignore:
Timestamp:
Mar 25, 2012 10:47:16 PM (14 months ago)
Author:
Don-vip
Message:

Enhancements in plugin dependencies system (view "requires" in plugin prefs + auto selection of required plugins + alert when unselecting a plugin still required)

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginListPanel.java

    r5120 r5121  
    33 
    44import static org.openstreetmap.josm.tools.I18n.tr; 
    5  
     5import static org.openstreetmap.josm.tools.I18n.trn; 
     6 
     7import java.awt.Component; 
    68import java.awt.GridBagConstraints; 
    79import java.awt.GridBagLayout; 
     
    1012import java.awt.event.ActionEvent; 
    1113import java.awt.event.ActionListener; 
     14import java.util.HashSet; 
    1215import java.util.List; 
     16import java.util.Set; 
    1317 
    1418import javax.swing.JCheckBox; 
    1519import javax.swing.JLabel; 
     20import javax.swing.JOptionPane; 
    1621import javax.swing.SwingConstants; 
    1722import javax.swing.SwingUtilities; 
     
    2227import org.openstreetmap.josm.gui.widgets.HtmlPanel; 
    2328import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel; 
     29import org.openstreetmap.josm.plugins.PluginHandler; 
    2430import org.openstreetmap.josm.plugins.PluginInformation; 
    2531import org.openstreetmap.josm.tools.OpenBrowser; 
     
    8288        add(hint, gbc); 
    8389    } 
     90     
     91    /** 
     92     * A plugin checkbox. 
     93     * 
     94     */ 
     95    private class JPluginCheckBox extends JCheckBox { 
     96        public final PluginInformation pi; 
     97        public JPluginCheckBox(final PluginInformation pi, boolean selected) { 
     98            this.pi = pi; 
     99            setSelected(selected); 
     100            setToolTipText(formatCheckboxTooltipText(pi)); 
     101            addActionListener(new PluginCbActionListener(this)); 
     102        } 
     103    } 
     104     
     105    /** 
     106     * Listener called when the user selects/unselects a plugin checkbox. 
     107     * 
     108     */ 
     109    private class PluginCbActionListener implements ActionListener { 
     110        private final JPluginCheckBox cb; 
     111        public PluginCbActionListener(JPluginCheckBox cb) { 
     112            this.cb = cb; 
     113        } 
     114        public void actionPerformed(ActionEvent e) { 
     115            // Select/unselect corresponding plugin in the model 
     116            model.setPluginSelected(cb.pi.getName(), cb.isSelected()); 
     117            // Does the newly selected plugin require other plugins ? 
     118            if (cb.isSelected() && cb.pi.requires != null) { 
     119                // Select required plugins 
     120                for (String s : cb.pi.requires.split(";")) { 
     121                    model.setPluginSelected(s.trim(), true); 
     122                } 
     123                // Alert user if plugin requirements are not met 
     124                PluginHandler.checkRequiredPluginsPreconditions(PluginListPanel.this, model.getAvailablePlugins(), cb.pi); 
     125            } 
     126            // If the plugin has been unselected, was it required by other plugins still selected ? 
     127            else if (!cb.isSelected()) { 
     128                Set<String> otherPlugins = new HashSet<String>(); 
     129                for (PluginInformation pi : model.getAvailablePlugins()) { 
     130                    if (!pi.equals(cb.pi) && pi.requires != null && model.isSelectedPlugin(pi.getName())) { 
     131                        for (String s : pi.requires.split(";")) { 
     132                            if (s.trim().equals(cb.pi.getName())) { 
     133                                otherPlugins.add(pi.getName());  
     134                                break; 
     135                            } 
     136                        } 
     137                    } 
     138                } 
     139                if (!otherPlugins.isEmpty()) { 
     140                    alertPluginStillRequired(PluginListPanel.this, cb.pi.getName(), otherPlugins); 
     141                } 
     142            } 
     143        } 
     144    }; 
     145     
     146 
     147    /** 
     148     * Alerts the user if an unselected plugin is still required by another plugins 
     149     * 
     150     * @param parent The parent Component used to display error popup 
     151     * @param plugin the plugin 
     152     * @param otherPlugins the other plugins 
     153     */ 
     154    private static void alertPluginStillRequired(Component parent, String plugin, Set<String> otherPlugins) { 
     155        StringBuilder sb = new StringBuilder(); 
     156        sb.append("<html>"); 
     157        sb.append(trn("Plugin {0} is still required by this plugin:", 
     158                "Plugin {0} is still required by these {1} plugins:", 
     159                otherPlugins.size(), 
     160                plugin, 
     161                otherPlugins.size() 
     162        )); 
     163        sb.append("<ul>"); 
     164        for (String p: otherPlugins) { 
     165            sb.append("<li>").append(p).append("</li>"); 
     166        } 
     167        sb.append("</ul>").append("</html>"); 
     168        JOptionPane.showMessageDialog( 
     169                parent, 
     170                sb.toString(), 
     171                tr("Warning"), 
     172                JOptionPane.WARNING_MESSAGE 
     173        ); 
     174    } 
    84175 
    85176    public void refreshView() { 
     
    105196            String localversion = formatPluginLocalVersion(model.getPluginInformation(pi.getName())); 
    106197 
    107             final JCheckBox cbPlugin = new JCheckBox(); 
    108             cbPlugin.setSelected(selected); 
    109             cbPlugin.setToolTipText(formatCheckboxTooltipText(pi)); 
    110             cbPlugin.addActionListener(new ActionListener(){ 
    111                 public void actionPerformed(ActionEvent e) { 
    112                     model.setPluginSelected(pi.getName(), cbPlugin.isSelected()); 
    113                 } 
    114             }); 
     198            JPluginCheckBox cbPlugin = new JPluginCheckBox(pi, selected); 
     199            String pluginText = tr("{0}: Version {1} (local: {2})", pi.getName(), remoteversion, localversion); 
     200            if (pi.requires != null && !pi.requires.isEmpty()) { 
     201                pluginText += tr(" (requires: {0})", pi.requires); 
     202            } 
    115203            JLabel lblPlugin = new JLabel( 
    116                     tr("{0}: Version {1} (local: {2})", pi.getName(), remoteversion, localversion), 
     204                    pluginText, 
    117205                    pi.getScaledIcon(), 
    118206                    SwingConstants.LEFT); 
  • trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java

    r4191 r5121  
    294294        return ret; 
    295295    } 
     296     
     297    /** 
     298     * Replies the set of all available plugins. 
     299     * 
     300     * @return the set of all available plugins 
     301     */ 
     302    public List<PluginInformation> getAvailablePlugins() { 
     303        return new LinkedList<PluginInformation>(availablePlugins); 
     304    } 
    296305 
    297306    /** 
  • trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java

    r5029 r5121  
    66import static org.openstreetmap.josm.tools.I18n.trn; 
    77 
     8import java.awt.Component; 
    89import java.awt.Font; 
    910import java.awt.GridBagConstraints; 
    1011import java.awt.GridBagLayout; 
    1112import java.awt.Insets; 
    12 import java.awt.Window; 
    1313import java.awt.event.ActionEvent; 
    1414import java.io.File; 
     
    175175     * Also notifies the user about removed deprecated plugins 
    176176     * 
     177     * @param parent The parent Component used to display warning popup 
    177178     * @param plugins the collection of plugins 
    178179     */ 
    179     private static void filterDeprecatedPlugins(Window parent, Collection<String> plugins) { 
     180    private static void filterDeprecatedPlugins(Component parent, Collection<String> plugins) { 
    180181        Set<DeprecatedPlugin> removedPlugins = new TreeSet<DeprecatedPlugin>(); 
    181182        for (DeprecatedPlugin depr : DEPRECATED_PLUGINS) { 
     
    226227     * @param plugins the collection of plugins 
    227228     */ 
    228     private static void filterUnmaintainedPlugins(Window parent, Collection<String> plugins) { 
     229    private static void filterUnmaintainedPlugins(Component parent, Collection<String> plugins) { 
    229230        for (String unmaintained : UNMAINTAINED_PLUGINS) { 
    230231            if (!plugins.contains(unmaintained)) { 
     
    247248     * if the plugins were last updated a long time ago. 
    248249     * 
    249      * @param parent the parent window relative to which the confirmation dialog 
     250     * @param parent the parent component relative to which the confirmation dialog 
    250251     * is to be displayed 
    251252     * @return true if a plugin update should be run; false, otherwise 
    252253     */ 
    253     public static boolean checkAndConfirmPluginUpdate(Window parent) { 
     254    public static boolean checkAndConfirmPluginUpdate(Component parent) { 
    254255        String message = null; 
    255256        String togglePreferenceKey = null; 
     
    355356     * Alerts the user if a plugin required by another plugin is missing 
    356357     * 
     358     * @param parent The parent Component used to display error popup 
    357359     * @param plugin the plugin 
    358360     * @param missingRequiredPlugin the missing required plugin 
    359361     */ 
    360     private static void alertMissingRequiredPlugin(Window parent, String plugin, Set<String> missingRequiredPlugin) { 
     362    private static void alertMissingRequiredPlugin(Component parent, String plugin, Set<String> missingRequiredPlugin) { 
    361363        StringBuilder sb = new StringBuilder(); 
    362364        sb.append("<html>"); 
     
    380382    } 
    381383 
    382     private static void alertJOSMUpdateRequired(Window parent, String plugin, int requiredVersion) { 
     384    private static void alertJOSMUpdateRequired(Component parent, String plugin, int requiredVersion) { 
    383385        HelpAwareOptionPane.showOptionDialog( 
    384386                parent, 
     
    398400     * depends on should be missing. 
    399401     * 
     402     * @param parent The parent Component used to display error popup 
    400403     * @param plugins the collection of all loaded plugins 
    401404     * @param plugin the plugin for which preconditions are checked 
    402405     * @return true, if the preconditions are met; false otherwise 
    403406     */ 
    404     public static boolean checkLoadPreconditions(Window parent, Collection<PluginInformation> plugins, PluginInformation plugin) { 
     407    public static boolean checkLoadPreconditions(Component parent, Collection<PluginInformation> plugins, PluginInformation plugin) { 
    405408 
    406409        // make sure the plugin is compatible with the current JOSM version 
     
    411414            return false; 
    412415        } 
     416 
     417        return checkRequiredPluginsPreconditions(parent, plugins, plugin); 
     418    } 
     419 
     420    /** 
     421     * Checks if required plugins preconditions for loading the plugin <code>plugin</code> are met. 
     422     * No other plugins this plugin depends on should be missing. 
     423     * 
     424     * @param parent The parent Component used to display error popup 
     425     * @param plugins the collection of all loaded plugins 
     426     * @param plugin the plugin for which preconditions are checked 
     427     * @return true, if the preconditions are met; false otherwise 
     428     */ 
     429    public static boolean checkRequiredPluginsPreconditions(Component parent, Collection<PluginInformation> plugins, PluginInformation plugin) { 
    413430 
    414431        // make sure the dependencies to other plugins are not broken 
     
    469486     * @param pluginClassLoader the plugin class loader 
    470487     */ 
    471     public static void loadPlugin(Window parent, PluginInformation plugin, ClassLoader pluginClassLoader) { 
     488    public static void loadPlugin(Component parent, PluginInformation plugin, ClassLoader pluginClassLoader) { 
    472489        String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name); 
    473490        try { 
     
    499516     * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 
    500517     */ 
    501     public static void loadPlugins(Window parent,Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
     518    public static void loadPlugins(Component parent,Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
    502519        if (monitor == null) { 
    503520            monitor = NullProgressMonitor.INSTANCE; 
     
    548565     * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 
    549566     */ 
    550     public static void loadEarlyPlugins(Window parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
     567    public static void loadEarlyPlugins(Component parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
    551568        List<PluginInformation> earlyPlugins = new ArrayList<PluginInformation>(plugins.size()); 
    552569        for (PluginInformation pi: plugins) { 
     
    565582     * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 
    566583     */ 
    567     public static void loadLatePlugins(Window parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
     584    public static void loadLatePlugins(Component parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) { 
    568585        List<PluginInformation> latePlugins = new ArrayList<PluginInformation>(plugins.size()); 
    569586        for (PluginInformation pi: plugins) { 
     
    610627    } 
    611628 
    612     private static void alertMissingPluginInformation(Window parent, Collection<String> plugins) { 
     629    private static void alertMissingPluginInformation(Component parent, Collection<String> plugins) { 
    613630        StringBuilder sb = new StringBuilder(); 
    614631        sb.append("<html>"); 
     
    642659     * @return the set of plugins to load (as set of plugin names) 
    643660     */ 
    644     public static List<PluginInformation> buildListOfPluginsToLoad(Window parent, ProgressMonitor monitor) { 
     661    public static List<PluginInformation> buildListOfPluginsToLoad(Component parent, ProgressMonitor monitor) { 
    645662        if (monitor == null) { 
    646663            monitor = NullProgressMonitor.INSTANCE; 
     
    675692    } 
    676693 
    677     private static void alertFailedPluginUpdate(Window parent, Collection<PluginInformation> plugins) { 
     694    private static void alertFailedPluginUpdate(Component parent, Collection<PluginInformation> plugins) { 
    678695        StringBuffer sb = new StringBuffer(); 
    679696        sb.append("<html>"); 
     
    707724     * Updates the plugins in <code>plugins</code>. 
    708725     * 
    709      * @param parent the parent window for message boxes 
     726     * @param parent the parent component for message boxes 
    710727     * @param plugins the collection of plugins to update. Must not be null. 
    711728     * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 
    712729     * @throws IllegalArgumentException thrown if plugins is null 
    713730     */ 
    714     public static List<PluginInformation>  updatePlugins(Window parent, 
     731    public static List<PluginInformation>  updatePlugins(Component parent, 
    715732            List<PluginInformation> plugins, ProgressMonitor monitor) 
    716733            throws IllegalArgumentException{ 
     
    797814     * @return true, if the plugin shall be disabled; false, otherwise 
    798815     */ 
    799     public static boolean confirmDisablePlugin(Window parent, String reason, String name) { 
     816    public static boolean confirmDisablePlugin(Component parent, String reason, String name) { 
    800817        ButtonSpec [] options = new ButtonSpec[] { 
    801818                new ButtonSpec( 
  • trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java

    r4737 r5121  
    55 
    66import java.awt.Image; 
     7import java.awt.image.BufferedImage; 
    78import java.io.File; 
    89import java.io.FileInputStream; 
     
    5556    public List<URL> libraries = new LinkedList<URL>(); 
    5657    public final Map<String, String> attr = new TreeMap<String, String>(); 
     58     
     59    private static final ImageIcon emptyIcon = new ImageIcon(new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB)); 
    5760 
    5861    /** 
     
    447450    public ImageIcon getScaledIcon() { 
    448451        if (icon == null) 
    449             return null; 
     452            return emptyIcon; 
    450453        return new ImageIcon(icon.getImage().getScaledInstance(24, 24, Image.SCALE_SMOOTH)); 
    451454    } 
Note: See TracChangeset for help on using the changeset viewer.