| Installer |

    package ij.plugin;
    import ij.*;
    import ij.gui.*;
    import ij.io.*;
    import ij.util.*;
    import java.awt.*;
    import java.io.*;
    import java.util.*;
    import java.lang.reflect.*;

    /** Implements the Plugins/Shortcuts/Install... command. */
    public class Installer implements PlugIn {

        private static String[] menus = {"Shortcuts", "Plugins", "Import", "Save As",
            "Filters", "Tools", "Utilities"};
        private static final String TITLE = "Installer";
        private static String command = "";
        private static String shortcut = "";
        private static String defaultPlugin = "";
        private static String menuStr = menus[0];

        public void run(String arg) {
            installPlugin();
        }

        void installPlugin() {
            String[] plugins = getPlugins();
            if (plugins==null || plugins.length==0) {
                IJ.error("No plugins found");
                return;
            }
            GenericDialog gd = new GenericDialog("Install Plugin", IJ.getInstance());
            gd.addChoice("Plugin:", plugins, defaultPlugin);
            gd.addChoice("Menu:", menus, menuStr);
            gd.addStringField("Command:", command, 16);
            gd.addStringField("Shortcut:", shortcut, 3);
            gd.addStringField("Argument:", "", 12);
            gd.showDialog();
            if (gd.wasCanceled())
                return;
            String plugin = gd.getNextChoice();
            menuStr = gd.getNextChoice();
            command = gd.getNextString();
            shortcut = gd.getNextString();
            String argument = gd.getNextString();
            IJ.register(Installer.class);
            defaultPlugin = plugin;
            if (command.equals("")) {
                IJ.showMessage(TITLE, "Command required");
                return;
            }
            if (shortcut.length()>1)
                shortcut = shortcut.replace('f','F');
            char menu = ' ';
            if (menuStr.equals(menus[0]))
                menu = Menus.SHORTCUTS_MENU;
            else if (menuStr.equals(menus[1]))
                menu = Menus.PLUGINS_MENU;
            else if (menuStr.equals(menus[2]))
                menu = Menus.IMPORT_MENU;
            else if (menuStr.equals(menus[3]))
                menu = Menus.SAVE_AS_MENU;
            else if (menuStr.equals(menus[4]))
                menu = Menus.FILTERS_MENU;
            else if (menuStr.equals(menus[5]))
                menu = Menus.TOOLS_MENU;
            else if (menuStr.equals(menus[6]))
                menu = Menus.UTILITIES_MENU;
            if (!argument.equals(""))
                plugin += "(\"" + argument +"\")";
            int err = Menus.installPlugin(plugin,menu,command,shortcut,IJ.getInstance());
            switch (err) {
                case Menus.COMMAND_IN_USE:
                    IJ.showMessage(TITLE, "The command \""+command+"\" \nis already being used.");
                    return;
                case Menus.INVALID_SHORTCUT:
                    IJ.showMessage(TITLE, "The shortcut must be a single character or \"F1\"-\"F12\".");
                    return;
                case Menus.SHORTCUT_IN_USE:
                    IJ.showMessage("The \""+shortcut+"\" shortcut is already being used.");
                    return;
                default:
                    command = "";
                    shortcut = "";
                    break;
            }
            if (!plugin.endsWith(")"))
                installAbout(plugin);
        }

        void installAbout(String plugin) {
            boolean hasShowAboutMethod=false;
            PluginClassLoader loader = new PluginClassLoader(Menus.getPlugInsPath());
            try {
                Class c = loader.loadClass(plugin);
                Method m = c.getDeclaredMethod("showAbout", new Class[0]);
                if (m!=null)
                    hasShowAboutMethod = true;
            }
            catch (Exception e) {}
            //IJ.write("installAbout: "+plugin+" "+hasShowAboutMethod);
            if (hasShowAboutMethod)
                Menus.installPlugin(plugin+"(\"about\")",Menus.ABOUT_MENU,plugin+"...","",IJ.getInstance());
        }

        String[] getPlugins() {
            String path = Menus.getPlugInsPath();
            if (path==null)
                return null;
            File f = new File(path);
            String[] list = f.list();
            if (list==null) return null;
            Vector v = new Vector();
            for (int i=0; i<list.length; i++) {
                String className = list[i];
                boolean isClassFile = className.endsWith(".class");
                if (className.indexOf('_')>=0 && isClassFile && className.indexOf('$')<0 ) {
                    className = className.substring(0, className.length()-6);
                    v.addElement(className);
                } else {
                    if (!isClassFile)
                        getSubdirectoryPlugins(path, className, v);
                }
            }
            list = new String[v.size()];
            v.copyInto((String[])list);
            StringSorter.sort(list);
            return list;
        }

        /** Looks for plugins in a subdirectorie of the plugins directory. */
        void getSubdirectoryPlugins(String path, String dir, Vector v) {
            //IJ.write("getSubdirectoryPlugins: "+path+dir);
            if (dir.endsWith(".java"))
                return;
            File f = new File(path, dir);
            if (!f.isDirectory())
                return;
            String[] list = f.list();
            if (list==null)
                return;
            dir += "/";
            for (int i=0; i<list.length; i++) {
                String name = list[i];
                if (name.indexOf('_')>=0 && name.endsWith(".class") && name.indexOf('$')<0 ) {
                    name = name.substring(0, name.length()-6); // remove ".class"
                    v.addElement(name);
                    //IJ.write("File: "+f+"/"+name);
                }
            }
        }

    }

| Installer |