Index: trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginListPanel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginListPanel.java	(revision 5120)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginListPanel.java	(revision 5121)
@@ -3,5 +3,7 @@
 
 import static org.openstreetmap.josm.tools.I18n.tr;
-
+import static org.openstreetmap.josm.tools.I18n.trn;
+
+import java.awt.Component;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
@@ -10,8 +12,11 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 
 import javax.swing.JCheckBox;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.SwingConstants;
 import javax.swing.SwingUtilities;
@@ -22,4 +27,5 @@
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
+import org.openstreetmap.josm.plugins.PluginHandler;
 import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.OpenBrowser;
@@ -82,4 +88,89 @@
         add(hint, gbc);
     }
+    
+    /**
+     * A plugin checkbox.
+     *
+     */
+    private class JPluginCheckBox extends JCheckBox {
+        public final PluginInformation pi;
+        public JPluginCheckBox(final PluginInformation pi, boolean selected) {
+            this.pi = pi;
+            setSelected(selected);
+            setToolTipText(formatCheckboxTooltipText(pi));
+            addActionListener(new PluginCbActionListener(this));
+        }
+    }
+    
+    /**
+     * Listener called when the user selects/unselects a plugin checkbox.
+     *
+     */
+    private class PluginCbActionListener implements ActionListener {
+        private final JPluginCheckBox cb;
+        public PluginCbActionListener(JPluginCheckBox cb) {
+            this.cb = cb;
+        }
+        public void actionPerformed(ActionEvent e) {
+            // Select/unselect corresponding plugin in the model
+            model.setPluginSelected(cb.pi.getName(), cb.isSelected());
+            // Does the newly selected plugin require other plugins ?
+            if (cb.isSelected() && cb.pi.requires != null) {
+                // Select required plugins
+                for (String s : cb.pi.requires.split(";")) {
+                    model.setPluginSelected(s.trim(), true);
+                }
+                // Alert user if plugin requirements are not met
+                PluginHandler.checkRequiredPluginsPreconditions(PluginListPanel.this, model.getAvailablePlugins(), cb.pi);
+            }
+            // If the plugin has been unselected, was it required by other plugins still selected ?
+            else if (!cb.isSelected()) {
+                Set<String> otherPlugins = new HashSet<String>();
+                for (PluginInformation pi : model.getAvailablePlugins()) {
+                    if (!pi.equals(cb.pi) && pi.requires != null && model.isSelectedPlugin(pi.getName())) {
+                        for (String s : pi.requires.split(";")) {
+                            if (s.trim().equals(cb.pi.getName())) {
+                                otherPlugins.add(pi.getName()); 
+                                break;
+                            }
+                        }
+                    }
+                }
+                if (!otherPlugins.isEmpty()) {
+                    alertPluginStillRequired(PluginListPanel.this, cb.pi.getName(), otherPlugins);
+                }
+            }
+        }
+    };
+    
+
+    /**
+     * Alerts the user if an unselected plugin is still required by another plugins
+     *
+     * @param parent The parent Component used to display error popup
+     * @param plugin the plugin
+     * @param otherPlugins the other plugins
+     */
+    private static void alertPluginStillRequired(Component parent, String plugin, Set<String> otherPlugins) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("<html>");
+        sb.append(trn("Plugin {0} is still required by this plugin:",
+                "Plugin {0} is still required by these {1} plugins:",
+                otherPlugins.size(),
+                plugin,
+                otherPlugins.size()
+        ));
+        sb.append("<ul>");
+        for (String p: otherPlugins) {
+            sb.append("<li>").append(p).append("</li>");
+        }
+        sb.append("</ul>").append("</html>");
+        JOptionPane.showMessageDialog(
+                parent,
+                sb.toString(),
+                tr("Warning"),
+                JOptionPane.WARNING_MESSAGE
+        );
+    }
 
     public void refreshView() {
@@ -105,14 +196,11 @@
             String localversion = formatPluginLocalVersion(model.getPluginInformation(pi.getName()));
 
-            final JCheckBox cbPlugin = new JCheckBox();
-            cbPlugin.setSelected(selected);
-            cbPlugin.setToolTipText(formatCheckboxTooltipText(pi));
-            cbPlugin.addActionListener(new ActionListener(){
-                public void actionPerformed(ActionEvent e) {
-                    model.setPluginSelected(pi.getName(), cbPlugin.isSelected());
-                }
-            });
+            JPluginCheckBox cbPlugin = new JPluginCheckBox(pi, selected);
+            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(
-                    tr("{0}: Version {1} (local: {2})", pi.getName(), remoteversion, localversion),
+                    pluginText,
                     pi.getScaledIcon(),
                     SwingConstants.LEFT);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java	(revision 5120)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/plugin/PluginPreferencesModel.java	(revision 5121)
@@ -294,4 +294,13 @@
         return ret;
     }
+    
+    /**
+     * Replies the set of all available plugins.
+     *
+     * @return the set of all available plugins
+     */
+    public List<PluginInformation> getAvailablePlugins() {
+        return new LinkedList<PluginInformation>(availablePlugins);
+    }
 
     /**
Index: trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 5120)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 5121)
@@ -6,9 +6,9 @@
 import static org.openstreetmap.josm.tools.I18n.trn;
 
+import java.awt.Component;
 import java.awt.Font;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
-import java.awt.Window;
 import java.awt.event.ActionEvent;
 import java.io.File;
@@ -175,7 +175,8 @@
      * Also notifies the user about removed deprecated plugins
      *
+     * @param parent The parent Component used to display warning popup
      * @param plugins the collection of plugins
      */
-    private static void filterDeprecatedPlugins(Window parent, Collection<String> plugins) {
+    private static void filterDeprecatedPlugins(Component parent, Collection<String> plugins) {
         Set<DeprecatedPlugin> removedPlugins = new TreeSet<DeprecatedPlugin>();
         for (DeprecatedPlugin depr : DEPRECATED_PLUGINS) {
@@ -226,5 +227,5 @@
      * @param plugins the collection of plugins
      */
-    private static void filterUnmaintainedPlugins(Window parent, Collection<String> plugins) {
+    private static void filterUnmaintainedPlugins(Component parent, Collection<String> plugins) {
         for (String unmaintained : UNMAINTAINED_PLUGINS) {
             if (!plugins.contains(unmaintained)) {
@@ -247,9 +248,9 @@
      * if the plugins were last updated a long time ago.
      *
-     * @param parent the parent window relative to which the confirmation dialog
+     * @param parent the parent component relative to which the confirmation dialog
      * is to be displayed
      * @return true if a plugin update should be run; false, otherwise
      */
-    public static boolean checkAndConfirmPluginUpdate(Window parent) {
+    public static boolean checkAndConfirmPluginUpdate(Component parent) {
         String message = null;
         String togglePreferenceKey = null;
@@ -355,8 +356,9 @@
      * Alerts the user if a plugin required by another plugin is missing
      *
+     * @param parent The parent Component used to display error popup
      * @param plugin the plugin
      * @param missingRequiredPlugin the missing required plugin
      */
-    private static void alertMissingRequiredPlugin(Window parent, String plugin, Set<String> missingRequiredPlugin) {
+    private static void alertMissingRequiredPlugin(Component parent, String plugin, Set<String> missingRequiredPlugin) {
         StringBuilder sb = new StringBuilder();
         sb.append("<html>");
@@ -380,5 +382,5 @@
     }
 
-    private static void alertJOSMUpdateRequired(Window parent, String plugin, int requiredVersion) {
+    private static void alertJOSMUpdateRequired(Component parent, String plugin, int requiredVersion) {
         HelpAwareOptionPane.showOptionDialog(
                 parent,
@@ -398,9 +400,10 @@
      * depends on should be missing.
      *
+     * @param parent The parent Component used to display error popup
      * @param plugins the collection of all loaded plugins
      * @param plugin the plugin for which preconditions are checked
      * @return true, if the preconditions are met; false otherwise
      */
-    public static boolean checkLoadPreconditions(Window parent, Collection<PluginInformation> plugins, PluginInformation plugin) {
+    public static boolean checkLoadPreconditions(Component parent, Collection<PluginInformation> plugins, PluginInformation plugin) {
 
         // make sure the plugin is compatible with the current JOSM version
@@ -411,4 +414,18 @@
             return false;
         }
+
+        return checkRequiredPluginsPreconditions(parent, plugins, plugin);
+    }
+
+    /**
+     * Checks if required plugins preconditions for loading the plugin <code>plugin</code> are met.
+     * No other plugins this plugin depends on should be missing.
+     *
+     * @param parent The parent Component used to display error popup
+     * @param plugins the collection of all loaded plugins
+     * @param plugin the plugin for which preconditions are checked
+     * @return true, if the preconditions are met; false otherwise
+     */
+    public static boolean checkRequiredPluginsPreconditions(Component parent, Collection<PluginInformation> plugins, PluginInformation plugin) {
 
         // make sure the dependencies to other plugins are not broken
@@ -469,5 +486,5 @@
      * @param pluginClassLoader the plugin class loader
      */
-    public static void loadPlugin(Window parent, PluginInformation plugin, ClassLoader pluginClassLoader) {
+    public static void loadPlugin(Component parent, PluginInformation plugin, ClassLoader pluginClassLoader) {
         String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name);
         try {
@@ -499,5 +516,5 @@
      * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null.
      */
-    public static void loadPlugins(Window parent,Collection<PluginInformation> plugins, ProgressMonitor monitor) {
+    public static void loadPlugins(Component parent,Collection<PluginInformation> plugins, ProgressMonitor monitor) {
         if (monitor == null) {
             monitor = NullProgressMonitor.INSTANCE;
@@ -548,5 +565,5 @@
      * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null.
      */
-    public static void loadEarlyPlugins(Window parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) {
+    public static void loadEarlyPlugins(Component parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) {
         List<PluginInformation> earlyPlugins = new ArrayList<PluginInformation>(plugins.size());
         for (PluginInformation pi: plugins) {
@@ -565,5 +582,5 @@
      * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null.
      */
-    public static void loadLatePlugins(Window parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) {
+    public static void loadLatePlugins(Component parent, Collection<PluginInformation> plugins, ProgressMonitor monitor) {
         List<PluginInformation> latePlugins = new ArrayList<PluginInformation>(plugins.size());
         for (PluginInformation pi: plugins) {
@@ -610,5 +627,5 @@
     }
 
-    private static void alertMissingPluginInformation(Window parent, Collection<String> plugins) {
+    private static void alertMissingPluginInformation(Component parent, Collection<String> plugins) {
         StringBuilder sb = new StringBuilder();
         sb.append("<html>");
@@ -642,5 +659,5 @@
      * @return the set of plugins to load (as set of plugin names)
      */
-    public static List<PluginInformation> buildListOfPluginsToLoad(Window parent, ProgressMonitor monitor) {
+    public static List<PluginInformation> buildListOfPluginsToLoad(Component parent, ProgressMonitor monitor) {
         if (monitor == null) {
             monitor = NullProgressMonitor.INSTANCE;
@@ -675,5 +692,5 @@
     }
 
-    private static void alertFailedPluginUpdate(Window parent, Collection<PluginInformation> plugins) {
+    private static void alertFailedPluginUpdate(Component parent, Collection<PluginInformation> plugins) {
         StringBuffer sb = new StringBuffer();
         sb.append("<html>");
@@ -707,10 +724,10 @@
      * Updates the plugins in <code>plugins</code>.
      *
-     * @param parent the parent window for message boxes
+     * @param parent the parent component for message boxes
      * @param plugins the collection of plugins to update. Must not be null.
      * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null.
      * @throws IllegalArgumentException thrown if plugins is null
      */
-    public static List<PluginInformation>  updatePlugins(Window parent,
+    public static List<PluginInformation>  updatePlugins(Component parent,
             List<PluginInformation> plugins, ProgressMonitor monitor)
             throws IllegalArgumentException{
@@ -797,5 +814,5 @@
      * @return true, if the plugin shall be disabled; false, otherwise
      */
-    public static boolean confirmDisablePlugin(Window parent, String reason, String name) {
+    public static boolean confirmDisablePlugin(Component parent, String reason, String name) {
         ButtonSpec [] options = new ButtonSpec[] {
                 new ButtonSpec(
Index: trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 5120)
+++ trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 5121)
@@ -5,4 +5,5 @@
 
 import java.awt.Image;
+import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.FileInputStream;
@@ -55,4 +56,6 @@
     public List<URL> libraries = new LinkedList<URL>();
     public final Map<String, String> attr = new TreeMap<String, String>();
+    
+    private static final ImageIcon emptyIcon = new ImageIcon(new BufferedImage(24, 24, BufferedImage.TYPE_INT_ARGB));
 
     /**
@@ -447,5 +450,5 @@
     public ImageIcon getScaledIcon() {
         if (icon == null)
-            return null;
+            return emptyIcon;
         return new ImageIcon(icon.getImage().getScaledInstance(24, 24, Image.SCALE_SMOOTH));
     }
