Package ij

Source Code of ij.Menus

package ij;
import ij.process.*;
import ij.util.*;
import ij.gui.ImageWindow;
import ij.plugin.MacroInstaller;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import java.applet.Applet;
import java.awt.event.*;
import java.util.zip.*;

/**
This class installs and updates ImageJ's menus. Note that menu labels,
even in submenus, must be unique. This is because ImageJ uses a single
hash table for all menu labels. If you look closely, you will see that
File->Import->Text Image... and File->Save As->Text Image... do not use
the same label. One of the labels has an extra space.

@see ImageJ
*/

public class Menus {

  public static final char PLUGINS_MENU = 'p';
  public static final char IMPORT_MENU = 'i';
  public static final char SAVE_AS_MENU = 's';
  public static final char SHORTCUTS_MENU = 'h'; // 'h'=hotkey
  public static final char ABOUT_MENU = 'a';
  public static final char FILTERS_MENU = 'f';
  public static final char TOOLS_MENU = 't';
  public static final char UTILITIES_MENU = 'u';
   
  public static final int WINDOW_MENU_ITEMS = 5; // fixed items at top of Window menu
 
  public static final int NORMAL_RETURN = 0;
  public static final int COMMAND_IN_USE = -1;
  public static final int INVALID_SHORTCUT = -2;
  public static final int SHORTCUT_IN_USE = -3;
  public static final int NOT_INSTALLED = -4;
  public static final int COMMAND_NOT_FOUND = -5;
 
  public static final int MAX_OPEN_RECENT_ITEMS = 15;
 
  private static MenuBar mbar;
  private static CheckboxMenuItem gray8Item,gray16Item,gray32Item,
      color256Item,colorRGBItem,RGBStackItem,HSBStackItem;
  private static PopupMenu popup;

  private static ImageJ ij;
  private static Applet applet;
  private static Hashtable demoImagesTable = new Hashtable();
  private static String pluginsPath, macrosPath;
  private static Menu pluginsMenu, importMenu, saveAsMenu, shortcutsMenu,
    aboutMenu, filtersMenu, toolsMenu, utilitiesMenu, macrosMenu, optionsMenu;
  private static Hashtable pluginsTable;
 
  static Menu window, openRecentMenu;
  int nPlugins, nMacros;
  private static Hashtable shortcuts = new Hashtable();
  private static Hashtable macroShortcuts;
  private static Vector pluginsPrefs = new Vector(); // commands saved in IJ_Prefs
  static int windowMenuItems2; // non-image windows listed in Window menu + separator
  private static String error;
  private String jarError;
  private String pluginError;
    private boolean isJarErrorHeading;
  private boolean installingJars, duplicateCommand;
  private static Vector jarFiles;  // JAR files in plugins folder with "_" in their name
  private static Vector macroFiles;  // Macro files in plugins folder with "_" in their name
  private int importCount, saveAsCount, toolsCount, optionsCount;
  private static Hashtable menusTable; // Submenus of Plugins menu
  private int userPluginsIndex; // First user plugin or submenu in Plugins menu
  private boolean addSorted;
  private static int defaultFontSize = IJ.isWindows()?14:0;
  private static int fontSize = Prefs.getInt(Prefs.MENU_SIZE, defaultFontSize);
  private static Font menuFont;
  static boolean jnlp; // true when using Java WebStart
   
  Menus(ImageJ ijInstance, Applet appletInstance) {
    ij = ijInstance;
    applet = appletInstance;
  }

  String addMenuBar() {
    error = null;
    pluginsTable = new Hashtable();
   
    Menu file = new Menu("File");
    addSubMenu(file, "New");
    addPlugInItem(file, "Open...", "ij.plugin.Commands(\"open\")", KeyEvent.VK_O, false);
    addPlugInItem(file, "Open Next", "ij.plugin.NextImageOpener", KeyEvent.VK_O, true);
    addSubMenu(file, "Open Samples");
    addOpenRecentSubMenu(file);
    importMenu = addSubMenu(file, "Import");
    file.addSeparator();
    addPlugInItem(file, "Close", "ij.plugin.Commands(\"close\")", KeyEvent.VK_W, false);
    addPlugInItem(file, "Save", "ij.plugin.Commands(\"save\")", KeyEvent.VK_S, false);
    saveAsMenu = addSubMenu(file, "Save As");
    addPlugInItem(file, "Revert", "ij.plugin.Commands(\"revert\")", KeyEvent.VK_R,  false);
    file.addSeparator();
    addPlugInItem(file, "Page Setup...", "ij.plugin.filter.Printer(\"setup\")", 0, false);
    addPlugInItem(file, "Print...", "ij.plugin.filter.Printer(\"print\")", KeyEvent.VK_P, false);
    file.addSeparator();
    addPlugInItem(file, "Quit", "ij.plugin.Commands(\"quit\")", 0, false);
   
    Menu edit = new Menu("Edit");
    addPlugInItem(edit, "Undo", "ij.plugin.Commands(\"undo\")", KeyEvent.VK_Z, false);
    edit.addSeparator();
    addPlugInItem(edit, "Cut", "ij.plugin.Clipboard(\"cut\")", KeyEvent.VK_X, false);
    addPlugInItem(edit, "Copy", "ij.plugin.Clipboard(\"copy\")", KeyEvent.VK_C, false);
    addPlugInItem(edit, "Copy to System", "ij.plugin.Clipboard(\"scopy\")", 0, false);
    addPlugInItem(edit, "Paste", "ij.plugin.Clipboard(\"paste\")", KeyEvent.VK_V, false);
    addPlugInItem(edit, "Paste Control...", "ij.plugin.frame.PasteController", 0, false);
    edit.addSeparator();
    addPlugInItem(edit, "Clear", "ij.plugin.filter.Filler(\"clear\")", 0, false);
    addPlugInItem(edit, "Clear Outside", "ij.plugin.filter.Filler(\"outside\")", 0, false);
    addPlugInItem(edit, "Fill", "ij.plugin.filter.Filler(\"fill\")", KeyEvent.VK_F, false);
    addPlugInItem(edit, "Draw", "ij.plugin.filter.Filler(\"draw\")", KeyEvent.VK_D, false);
    addPlugInItem(edit, "Invert", "ij.plugin.filter.Filters(\"invert\")", KeyEvent.VK_I, true);
    edit.addSeparator();
    addSubMenu(edit, "Selection");
    optionsMenu = addSubMenu(edit, "Options");
   
    Menu image = new Menu("Image");
    Menu imageType = new Menu("Type");
      gray8Item = addCheckboxItem(imageType, "8-bit", "ij.plugin.Converter(\"8-bit\")");
      gray16Item = addCheckboxItem(imageType, "16-bit", "ij.plugin.Converter(\"16-bit\")");
      gray32Item = addCheckboxItem(imageType, "32-bit", "ij.plugin.Converter(\"32-bit\")");
      color256Item = addCheckboxItem(imageType, "8-bit Color", "ij.plugin.Converter(\"8-bit Color\")");
      colorRGBItem = addCheckboxItem(imageType, "RGB Color", "ij.plugin.Converter(\"RGB Color\")");
      imageType.add(new MenuItem("-"));
      RGBStackItem = addCheckboxItem(imageType, "RGB Stack", "ij.plugin.Converter(\"RGB Stack\")");
      HSBStackItem = addCheckboxItem(imageType, "HSB Stack", "ij.plugin.Converter(\"HSB Stack\")");
      image.add(imageType);
     
    image.addSeparator();
    addSubMenu(image, "Adjust");
    addPlugInItem(image, "Show Info...", "ij.plugin.filter.Info", KeyEvent.VK_I, false);
    addPlugInItem(image, "Properties...", "ij.plugin.filter.ImageProperties", KeyEvent.VK_P, true);
    //addSubMenu(image, "Benchmarks");
    addSubMenu(image, "Color");
    addSubMenu(image, "Stacks");
    addSubMenu(image, "HyperStacks");
    image.addSeparator();
    addPlugInItem(image, "Crop", "ij.plugin.filter.Resizer(\"crop\")", KeyEvent.VK_X, true);
    addPlugInItem(image, "Duplicate...", "ij.plugin.filter.Duplicater", KeyEvent.VK_D, true);
    addPlugInItem(image, "Rename...", "ij.plugin.SimpleCommands(\"rename\")", 0, false);
    addPlugInItem(image, "Scale...", "ij.plugin.Scaler", KeyEvent.VK_E, false);
    addPlugInItem(image, "Translate...", "ij.plugin.filter.Translator", 0, false);
    addSubMenu(image, "Rotate");
    addSubMenu(image, "Zoom");
    image.addSeparator();
    addSubMenu(image, "Lookup Tables");
   
    Menu process = new Menu("Process");
    addPlugInItem(process, "Smooth", "ij.plugin.filter.Filters(\"smooth\")", KeyEvent.VK_S, true);
    addPlugInItem(process, "Sharpen", "ij.plugin.filter.Filters(\"sharpen\")", 0, false);
    addPlugInItem(process, "Find Edges", "ij.plugin.filter.Filters(\"edge\")", 0, false);
    addPlugInItem(process, "Enhance Contrast", "ij.plugin.ContrastEnhancer", 0, false);
    addSubMenu(process, "Noise");
    addSubMenu(process, "Shadows");
    addSubMenu(process, "Binary");
    addSubMenu(process, "Math");
    addSubMenu(process, "FFT");
    filtersMenu = addSubMenu(process, "Filters");
    process.addSeparator();
    addPlugInItem(process, "Image Calculator...", "ij.plugin.ImageCalculator", 0, false);
    addPlugInItem(process, "Subtract Background...", "ij.plugin.filter.BackgroundSubtracter", 0, false);
    addItem(process, "Repeat Command", KeyEvent.VK_R, true);
   
    Menu analyze = new Menu("Analyze");
    addPlugInItem(analyze, "Measure", "ij.plugin.filter.Analyzer", KeyEvent.VK_M, false);
    addPlugInItem(analyze, "Analyze Particles...", "ij.plugin.filter.ParticleAnalyzer", 0, false);
    addPlugInItem(analyze, "Summarize", "ij.plugin.filter.Analyzer(\"sum\")", 0, false);
    addPlugInItem(analyze, "Distribution...", "ij.plugin.Distribution", 0, false);
    addPlugInItem(analyze, "Label", "ij.plugin.filter.Filler(\"label\")", 0, false);
    addPlugInItem(analyze, "Clear Results", "ij.plugin.filter.Analyzer(\"clear\")", 0, false);
    addPlugInItem(analyze, "Set Measurements...", "ij.plugin.filter.Analyzer(\"set\")", 0, false);
    analyze.addSeparator();
    addPlugInItem(analyze, "Set Scale...", "ij.plugin.filter.ScaleDialog", 0, false);
    addPlugInItem(analyze, "Calibrate...", "ij.plugin.filter.Calibrator", 0, false);
    addPlugInItem(analyze, "Histogram", "ij.plugin.Histogram", KeyEvent.VK_H, false);
    addPlugInItem(analyze, "Plot Profile", "ij.plugin.filter.Profiler(\"plot\")", KeyEvent.VK_K, false);
    addPlugInItem(analyze, "Surface Plot...", "ij.plugin.SurfacePlotter", 0, false);
    addSubMenu(analyze, "Gels");
    toolsMenu = addSubMenu(analyze, "Tools");

    window = new Menu("Window");
    addPlugInItem(window, "Show All", "ij.plugin.WindowOrganizer(\"show\")", KeyEvent.VK_F, true);
    addPlugInItem(window, "Put Behind [tab]", "ij.plugin.Commands(\"tab\")", 0, false);
    addPlugInItem(window, "Cascade", "ij.plugin.WindowOrganizer(\"cascade\")", 0, false);
    addPlugInItem(window, "Tile", "ij.plugin.WindowOrganizer(\"tile\")", 0, false);
    window.addSeparator();

    Menu help = new Menu("Help");
    addPlugInItem(help, "ImageJ Website...", "ij.plugin.BrowserLauncher", 0, false);
    addPlugInItem(help, "ImageJ News...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/notes.html\")", 0, false);
    addPlugInItem(help, "Documentation...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/docs\")", 0, false);
    addPlugInItem(help, "Installation...", "ij.plugin.SimpleCommands(\"install\")", 0, false);
    addPlugInItem(help, "Search Website...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/search.html\")", 0, false);
    addPlugInItem(help, "List Archives...", "ij.plugin.BrowserLauncher(\"https://list.nih.gov/archives/imagej.html\")", 0, false);
    help.addSeparator();
    addPlugInItem(help, "Plugins...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/plugins\")", 0, false);
    addPlugInItem(help, "Macros...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/macros/\")", 0, false);
    addPlugInItem(help, "Source Code...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/developer/source/\")", 0, false);
    addPlugInItem(help, "Macro Language...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/developer/macro/macros.html\")", 0, false);
    addPlugInItem(help, "Macro Functions...", "ij.plugin.BrowserLauncher(\"http://rsb.info.nih.gov/ij/developer/macro/functions.html\")", 0, false);
    help.addSeparator();
    aboutMenu = addSubMenu(help, "About Plugins");
    addPlugInItem(help, "About ImageJ...", "ij.plugin.AboutBox", 0, false);
       
    addPluginsMenu();
    if (applet==null)
      installPlugins();
   
    mbar = new MenuBar();
    if (fontSize!=0)
      mbar.setFont(getFont());
    mbar.add(file);
    mbar.add(edit);
    mbar.add(image);
    mbar.add(process);
    mbar.add(analyze);
    mbar.add(pluginsMenu);
    mbar.add(window);
    mbar.setHelpMenu(help);
    if (ij!=null)
      ij.setMenuBar(mbar);
   
    if (pluginError!=null)
      error = error!=null?error+="\n"+pluginError:pluginError;
    if (jarError!=null)
      error = error!=null?error+="\n"+jarError:jarError;
    return error;
  }
 
  void addOpenRecentSubMenu(Menu menu) {
    openRecentMenu = new Menu("Open Recent");
     for (int i=0; i<MAX_OPEN_RECENT_ITEMS; i++) {
      String path = Prefs.getString("recent" + (i/10)%10 + i%10);
      if (path==null) break;
      MenuItem item = new MenuItem(path);
      openRecentMenu.add(item);
      item.addActionListener(ij);
    }
    menu.add(openRecentMenu);
  }

  void addItem(Menu menu, String label, int shortcut, boolean shift) {
    if (menu==null)
      return;
    MenuItem item;
    if (shortcut==0)
      item = new MenuItem(label);
    else {
      if (shift) {
        item = new MenuItem(label, new MenuShortcut(shortcut, true));
        shortcuts.put(new Integer(shortcut+200),label);
      } else {
        item = new MenuItem(label, new MenuShortcut(shortcut));
        shortcuts.put(new Integer(shortcut),label);
      }
    }
    if (addSorted) {
      if (menu==pluginsMenu)
        addItemSorted(menu, item, userPluginsIndex);
      else
        addOrdered(menu, item);
    } else
      menu.add(item);
    item.addActionListener(ij);
  }

  void addPlugInItem(Menu menu, String label, String className, int shortcut, boolean shift) {
    pluginsTable.put(label, className);
    nPlugins++;
    addItem(menu, label, shortcut, shift);
  }

  CheckboxMenuItem addCheckboxItem(Menu menu, String label, String className) {
    pluginsTable.put(label, className);
    nPlugins++;
    CheckboxMenuItem item = new CheckboxMenuItem(label);
    menu.add(item);
    item.addItemListener(ij);
    item.setState(false);
    return item;
  }

  Menu addSubMenu(Menu menu, String name) {
    String value;
    String key = name.toLowerCase(Locale.US);
    int index;
     Menu submenu=new Menu(name.replace('_', ' '));
    index = key.indexOf(' ');
    if (index>0)
      key = key.substring(0, index);
     for (int count=1; count<100; count++) {
      value = Prefs.getString(key + (count/10)%10 + count%10);
      if (value==null)
        break;
      if (count==1)
        menu.add(submenu);
      if (value.equals("-"))
        submenu.addSeparator();
      else
        addPluginItem(submenu, value);
    }
    if (name.equals("Lookup Tables") && applet==null)
      addLuts(submenu);
    return submenu;
  }
 
  void addLuts(Menu submenu) {
    String path = Prefs.getHomeDir()+File.separator;
    File f = new File(path+"luts");
    String[] list = null;
    if (applet==null && f.exists() && f.isDirectory())
      list = f.list();
    if (list==null) return;
    if (IJ.isLinux()) StringSorter.sort(list);
    submenu.addSeparator();
     for (int i=0; i<list.length; i++) {
       String name = list[i];
       if (name.endsWith(".lut")) {
         name = name.substring(0,name.length()-4);
         MenuItem item = new MenuItem(name);
        submenu.add(item);
        item.addActionListener(ij);
        nPlugins++;
      }
    }
  }

  void addPluginItem(Menu submenu, String s) {
    if (s.startsWith("\"-\"")) {
      // add menu separator if command="-"
      addSeparator(submenu);
      return;
    }
    int lastComma = s.lastIndexOf(',');
    if (lastComma<=0)
      return;
    String command = s.substring(1,lastComma-1);
    int keyCode = 0;
    boolean shift = false;
    if (command.endsWith("]")) {
      int openBracket = command.lastIndexOf('[');
      if (openBracket>0) {
        String shortcut = command.substring(openBracket+1,command.length()-1);
        keyCode = convertShortcutToCode(shortcut);
        boolean functionKey = keyCode>=KeyEvent.VK_F1 && keyCode<=KeyEvent.VK_F12;
        if (keyCode>0 && !functionKey)
          command = command.substring(0,openBracket);
        //IJ.write(command+": "+shortcut);
      }
    }
    if (keyCode>=KeyEvent.VK_F1 && keyCode<=KeyEvent.VK_F12) {
      shortcuts.put(new Integer(keyCode),command);
      keyCode = 0;
    } else if (keyCode>=265 && keyCode<=290) {
      keyCode -= 200;
      shift = true;
    }
    addItem(submenu,command,keyCode,shift);
    while(s.charAt(lastComma+1)==' ' && lastComma+2<s.length())
      lastComma++; // remove leading spaces
    String className = s.substring(lastComma+1,s.length());
    //IJ.log(command+"  "+className);
    if (installingJars)
      duplicateCommand = pluginsTable.get(command)!=null;
    pluginsTable.put(command, className);
    nPlugins++;
  }

  void checkForDuplicate(String command) {
    if (pluginsTable.get(command)!=null) {
    }
  }
 
  void addPluginsMenu() {
    String value,label,className;
    int index;
    pluginsMenu = new Menu("Plugins");
    for (int count=1; count<100; count++) {
      value = Prefs.getString("plug-in" + (count/10)%10 + count%10);
      if (value==null)
        break;
      char firstChar = value.charAt(0);
      if (firstChar=='-')
        pluginsMenu.addSeparator();
      else if (firstChar=='>') {
        String submenu = value.substring(2,value.length()-1);
        Menu menu = addSubMenu(pluginsMenu, submenu);
        if (submenu.equals("Shortcuts"))
          shortcutsMenu = menu;
        else if (submenu.equals("Utilities"))
          utilitiesMenu = menu;
        else if (submenu.equals("Macros"))
          macrosMenu = menu;
      } else
        addPluginItem(pluginsMenu, value);
    }
    userPluginsIndex = pluginsMenu.getItemCount();
    if (userPluginsIndex<0) userPluginsIndex = 0;
  }

  /** Install plugins using "pluginxx=" keys in IJ_Prefs.txt.
    Plugins not listed in IJ_Prefs are added to the end
    of the Plugins menu. */
  void installPlugins() {
    String value, className;
    char menuCode;
    Menu menu;
    String[] plugins = getPlugins();
    String[] plugins2 = null;
    Hashtable skipList = new Hashtable();
     for (int index=0; index<100; index++) {
      value = Prefs.getString("plugin" + (index/10)%10 + index%10);
      if (value==null)
        break;
      menuCode = value.charAt(0);
      switch (menuCode) {
        case PLUGINS_MENU: default: menu = pluginsMenu; break;
        case IMPORT_MENU: menu = importMenu; break;
        case SAVE_AS_MENU: menu = saveAsMenu; break;
        case SHORTCUTS_MENU: menu = shortcutsMenu; break;
        case ABOUT_MENU: menu = aboutMenu; break;
        case FILTERS_MENU: menu = filtersMenu; break;
        case TOOLS_MENU: menu = toolsMenu; break;
        case UTILITIES_MENU: menu = utilitiesMenu; break;
      }
      String prefsValue = value;
      value = value.substring(2,value.length()); //remove menu code and coma
      className = value.substring(value.lastIndexOf(',')+1,value.length());
      boolean found = className.startsWith("ij.");
      if (!found && plugins!=null) { // does this plugin exist?
        if (plugins2==null)
          plugins2 = getStrippedPlugins(plugins);
        for (int i=0; i<plugins2.length; i++) {
          if (className.startsWith(plugins2[i])) {
            found = true;
            break;
          }
        }
      }
      if (found) {
        addPluginItem(menu, value);
        pluginsPrefs.addElement(prefsValue);
        if (className.endsWith("\")")) { // remove any argument
          int argStart = className.lastIndexOf("(\"");
          if (argStart>0)
            className = className.substring(0, argStart);
        }
        skipList.put(className, "");
      }
    }
    if (plugins!=null) {
      for (int i=0; i<plugins.length; i++) {
        if (!skipList.containsKey(plugins[i]))
          installUserPlugin(plugins[i]);
      }
    }
    installJarPlugins();
    installMacros();
  }
 
  /** Installs macro files that are located in the plugins folder and have a "_" in their name. */
  void installMacros() {
    if (macroFiles==null)
      return;
    for (int i=0; i<macroFiles.size(); i++) {
      String name = (String)macroFiles.elementAt(i);
      installMacro(name);
    }   
  }

  /** Installs a macro in the Plugins menu, or submenu, with
    with underscores in the file name replaced by spaces. */
  void installMacro(String name) {
    Menu menu = pluginsMenu;
    String dir = null;
    int slashIndex = name.indexOf('/');
    if (slashIndex>0) {
      dir = name.substring(0, slashIndex);
      name = name.substring(slashIndex+1, name.length());
      menu = getPluginsSubmenu(dir);
    }
    String command = name.replace('_',' ');
    command = command.substring(0, command.length()-4); //remove ".txt" or ".ijm"
    command.trim();
    if (pluginsTable.get(command)!=null) // duplicate command?
      command = command + " Macro";
    MenuItem item = new MenuItem(command);
    addOrdered(menu, item);
    item.addActionListener(ij);
    String path = (dir!=null?dir+File.separator:"") + name;
    pluginsTable.put(command, "ij.plugin.Macro_Runner(\""+path+"\")");
    nMacros++;
  }

  /** Inserts 'item' into 'menu' in alphanumeric order. */
  void addOrdered(Menu menu, MenuItem item) {
    if (menu==pluginsMenu)
      {menu.add(item); return;}
    String label = item.getLabel();
    for (int i=0; i<menu.getItemCount(); i++) {
      if (label.compareTo(menu.getItem(i).getLabel())<0) {
        menu.insert(item, i);
        return;
      }
    }
    menu.add(item);
  }
 
  /** Install plugins located in JAR files. */
  void installJarPlugins() {
    if (jarFiles==null)
      return;
    installingJars = true;
    for (int i=0; i<jarFiles.size(); i++) {
            isJarErrorHeading = false;
      String jar = (String)jarFiles.elementAt(i);
      InputStream is = getConfigurationFile(jar);
            if (is==null) continue;
            LineNumberReader lnr = new LineNumberReader(new InputStreamReader(is));
            try {
                while(true) {
                    String s = lnr.readLine();
                    if (s==null) break;
                    installJarPlugin(jar, s);
                }
            }
            catch (IOException e) {}
      finally {
        try {if (lnr!=null) lnr.close();}
        catch (IOException e) {}
      }
    }   
  }
   
    /** Install a plugin located in a JAR file. */
    void installJarPlugin(String jar, String s) {
    //IJ.log(s);
    if (s.length()<3) return;
    char firstChar = s.charAt(0);
    if (firstChar=='#') return;
    addSorted = false;
    Menu menu;
        if (s.startsWith("Plugins>")) {
      int firstComma = s.indexOf(',');
      if (firstComma==-1 || firstComma<=8)
        menu = null;
      else {
            String name = s.substring(8, firstComma);
        menu = getPluginsSubmenu(name);
      }
        } else if (firstChar=='"' || s.startsWith("Plugins")) {
          String name = getSubmenuName(jar);
          if (name!=null)
            menu = getPluginsSubmenu(name);
          else
        menu = pluginsMenu;
      addSorted = true;
    } else if (s.startsWith("File>Import")) {
      menu = importMenu;
      if (importCount==0) addSeparator(menu);
      importCount++;
    } else if (s.startsWith("File>Save")) {
      menu = saveAsMenu;
      if (saveAsCount==0) addSeparator(menu);
      saveAsCount++;
    } else if (s.startsWith("Analyze>Tools")) {
      menu = toolsMenu;
      if (toolsCount==0) addSeparator(menu);
      toolsCount++;
    } else if (s.startsWith("Help>About")) {
      menu = aboutMenu;
    } else if (s.startsWith("Edit>Options")) {
      menu = optionsMenu;
      if (optionsCount==0) addSeparator(menu);
      optionsCount++;
    } else {
      if (jarError==null) jarError = "";
            addJarErrorHeading(jar);
      jarError += "    Invalid menu: " + s + "\n";
      return;
    }
    int firstQuote = s.indexOf('"');
    if (firstQuote==-1)
      return;
    s = s.substring(firstQuote, s.length()); // remove menu
    if (menu!=null) {
            addPluginItem(menu, s);
            addSorted = false;
        }
    if (duplicateCommand) {
      if (jarError==null) jarError = "";
            addJarErrorHeading(jar);
      jarError += "    Duplicate command: " + s + "\n";
    }
    duplicateCommand = false;
    }
   
    void addJarErrorHeading(String jar) {
        if (!isJarErrorHeading) {
                if (!jarError.equals(""))
                    jarError += " \n";
                jarError += "Plugin configuration error: " + jar + "\n";
                isJarErrorHeading = true;
            }
    }

  Menu getPluginsSubmenu(String submenuName) {
        if (menusTable!=null) {
            Menu menu = (Menu)menusTable.get(submenuName);
            if (menu!=null)
                return menu;
        }
        Menu menu = new Menu(submenuName);
        //pluginsMenu.add(menu);
        addItemSorted(pluginsMenu, menu, userPluginsIndex);
        if (menusTable==null) menusTable = new Hashtable();
        menusTable.put(submenuName, menu);
        //IJ.log("getPluginsSubmenu: "+submenuName);       
        return menu;
    }
   
  String getSubmenuName(String jarPath) {
    //IJ.log("getSubmenuName: \n"+jarPath+"\n"+pluginsPath);
    if (jarPath.startsWith(pluginsPath))
      jarPath = jarPath.substring(pluginsPath.length() - 1);
    int index = jarPath.lastIndexOf(File.separatorChar);
    if (index<0) return null;
    String name = jarPath.substring(0, index);
    index = name.lastIndexOf(File.separatorChar);
    if (index<0) return null;
    name = name.substring(index+1);
    if (name.equals("plugins")) return null;
    return name;
    }

  void addItemSorted(Menu menu, MenuItem item, int startingIndex) {
    String itemLabel = item.getLabel();
    int count = menu.getItemCount();
    boolean inserted = false;
    for (int i=startingIndex; i<count; i++) {
      MenuItem mi = menu.getItem(i);
      String label = mi.getLabel();
      //IJ.log(i+ "  "+itemLabel+"  "+label + "  "+(itemLabel.compareTo(label)));
      if (itemLabel.compareTo(label)<0) {
        menu.insert(item, i);
        inserted = true;
        break;
      }
    }
    if (!inserted) menu.add(item);
  }

    void addSeparator(Menu menu) {
      menu.addSeparator();
    }

    /** Opens the configuration file ("plugins.txt") from a JAR file and returns it as an InputStream. */
  InputStream getConfigurationFile(String jar) {
    try {
      ZipFile jarFile = new ZipFile(jar);
      Enumeration entries = jarFile.entries();
      while (entries.hasMoreElements()) {
        ZipEntry entry = (ZipEntry) entries.nextElement();
            if (entry.getName().endsWith("plugins.config"))
          return jarFile.getInputStream(entry);
      }
    }
      catch (Exception e) {}
    return autoGenerateConfigFile(jar);
  }
 
    /** Creates a configuration file for JAR/ZIP files that do not have one. */
  InputStream autoGenerateConfigFile(String jar) {
    StringBuffer sb = null;
    try {
      ZipFile jarFile = new ZipFile(jar);
      Enumeration entries = jarFile.entries();
      while (entries.hasMoreElements()) {
        ZipEntry entry = (ZipEntry) entries.nextElement();
        String name = entry.getName();
        if (name.endsWith(".class") && name.indexOf("_")>0 && name.indexOf("$")==-1
        && name.indexOf("/_")==-1 && !name.startsWith("_")) {
          if (sb==null) sb = new StringBuffer();
          String className = name.substring(0, name.length()-6);
          int slashIndex = className.lastIndexOf('/');
          String plugins = "Plugins";
          if (slashIndex >= 0) {
            plugins += ">" + className.substring(0, slashIndex).replace('/', '>').replace('_', ' ');
            name = className.substring(slashIndex + 1);
          } else
            name = className;
          name = name.replace('_', ' ');
          className = className.replace('/', '.');
          sb.append(plugins + ", \""+name+"\", "+className+"\n");
        }
      }
    }
      catch (Exception e) {}
    //IJ.log(""+(sb!=null?sb.toString():"null"));
    if (sb==null)
      return null;
    else
        return new ByteArrayInputStream(sb.toString().getBytes());
  }

  /** Returns a list of the plugins with directory names removed. */
  String[] getStrippedPlugins(String[] plugins) {
    String[] plugins2 = new String[plugins.length];
    int slashPos;
    for (int i=0; i<plugins2.length; i++) {
      plugins2[i] = plugins[i];
      slashPos = plugins2[i].lastIndexOf('/');
      if (slashPos>=0)
        plugins2[i] = plugins[i].substring(slashPos+1,plugins2[i].length());
    }
    return plugins2;
  }
   
  /** Returns a list of the plugins in the plugins menu. */
  public static synchronized String[] getPlugins() {
    String homeDir = Prefs.getHomeDir();
    if (homeDir==null)
      return null;
    if (homeDir.endsWith("plugins"))
      pluginsPath = homeDir+Prefs.separator;
    else {
      String property = System.getProperty("plugins.dir");
      if (property!=null && (property.endsWith("/")||property.endsWith("\\")))
        property = property.substring(0, property.length()-1);
      String pluginsDir = property;
      if (pluginsDir==null)
        pluginsDir = homeDir;
      else if (pluginsDir.equals("user.home")) {
        pluginsDir = System.getProperty("user.home");
        if (!(new File(pluginsDir+Prefs.separator+"plugins")).isDirectory())
          pluginsDir = pluginsDir + Prefs.separator + "ImageJ";
        property = null;
        // needed to run plugins when ImageJ launched using Java WebStart
        if (applet==null) System.setSecurityManager(null);
        jnlp = true;
      }
      pluginsPath = pluginsDir+Prefs.separator+"plugins"+Prefs.separator;
      if (property!=null&&!(new File(pluginsPath)).isDirectory())
        pluginsPath = pluginsDir + Prefs.separator;
      macrosPath = pluginsDir+Prefs.separator+"macros"+Prefs.separator;
    }
    File f = macrosPath!=null?new File(macrosPath):null;
    if (f!=null && !f.isDirectory())
      macrosPath = null;
    f = pluginsPath!=null?new File(pluginsPath):null;
    if (f==null || (f!=null && !f.isDirectory())) {
      //error = "Plugins folder not found at "+pluginsPath;
      pluginsPath = null;
      return null;
    }
    String[] list = f.list();
    if (list==null)
      return null;
    Vector v = new Vector();
    jarFiles = null;
    macroFiles = null;
    for (int i=0; i<list.length; i++) {
      String name = list[i];
      boolean isClassFile = name.endsWith(".class");
      boolean hasUnderscore = name.indexOf('_')>=0;
      if (hasUnderscore && isClassFile && name.indexOf('$')<0 ) {
        name = name.substring(0, name.length()-6); // remove ".class"
        v.addElement(name);
      } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) {
        if (jarFiles==null) jarFiles = new Vector();
        jarFiles.addElement(pluginsPath + name);
      } else if (hasUnderscore && (name.endsWith(".txt")||name.endsWith(".ijm"))) {
        if (macroFiles==null) macroFiles = new Vector();
        macroFiles.addElement(name);
      } else {
        if (!isClassFile)
          checkSubdirectory(pluginsPath, name, v);
      }
    }
    list = new String[v.size()];
    v.copyInto((String[])list);
    StringSorter.sort(list);
    return list;
  }
 
  /** Looks for plugins and jar files in a subdirectory of the plugins directory. */
  static void checkSubdirectory(String path, String dir, Vector v) {
    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];
      boolean hasUnderscore = name.indexOf('_')>=0;
      if (hasUnderscore && name.endsWith(".class") && name.indexOf('$')<0) {
        name = name.substring(0, name.length()-6); // remove ".class"
        v.addElement(dir+name);
        //IJ.write("File: "+f+"/"+name);
      } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) {
        if (jarFiles==null) jarFiles = new Vector();
        jarFiles.addElement(f.getPath() + File.separator + name);
      } else if (hasUnderscore && (name.endsWith(".txt")||name.endsWith(".ijm"))) {
        if (macroFiles==null) macroFiles = new Vector();
        macroFiles.addElement(dir + name);
      }
    }
  }
 
  static String submenuName;
  static Menu submenu;

  /** Installs a plugin in the Plugins menu using the class name,
    with underscores replaced by spaces, as the command. */
  void installUserPlugin(String className) {
    Menu menu = pluginsMenu;
    int slashIndex = className.indexOf('/');
    String command = className;
    if (slashIndex>0) {
      String dir = className.substring(0, slashIndex);
      command = className.substring(slashIndex+1, className.length());
      //className = className.replace('/', '.');
      if (submenu==null || !submenuName.equals(dir)) {
         submenuName = dir;
         submenu = new Menu(submenuName);
         pluginsMenu.add(submenu);
         if (menusTable==null) menusTable = new Hashtable();
         menusTable.put(submenuName, submenu);
      }
      menu = submenu;
    //IJ.write(dir + "  " + className);
    }
    command = command.replace('_',' ');
    command.trim();
    if (pluginsTable.get(command)!=null// duplicate command?
      command = command + " Plugin";
    MenuItem item = new MenuItem(command);
    menu.add(item);
    item.addActionListener(ij);
    pluginsTable.put(command, className.replace('/', '.'));
    nPlugins++;
  }
 
  void installPopupMenu(ImageJ ij) {
    String s;
    int count = 0;
    MenuItem mi;
    popup = new PopupMenu("");
    if (fontSize!=0)
      popup.setFont(getFont());

    while (true) {
      count++;
      s = Prefs.getString("popup" + (count/10)%10 + count%10);
      if (s==null)
        break;
      if (s.equals("-"))
        popup.addSeparator();
      else if (!s.equals("")) {
        mi = new MenuItem(s);
        mi.addActionListener(ij);
        popup.add(mi);
      }
    }
  }

  public static MenuBar getMenuBar() {
    return mbar;
  }
   
  public static Menu getMacrosMenu() {
    return macrosMenu;
  }
   
  static final int RGB_STACK=10, HSB_STACK=11;
 
  /** Updates the Image/Type and Window menus. */
  public static void updateMenus() {
 
    if (ij==null) return;
    gray8Item.setState(false);
    gray16Item.setState(false);
    gray32Item.setState(false);
    color256Item.setState(false);
    colorRGBItem.setState(false);
    RGBStackItem.setState(false);
    HSBStackItem.setState(false);
    ImagePlus imp = WindowManager.getCurrentImage();
    if (imp==null)
      return;
      int type = imp.getType();
       if (imp.getStackSize()>1) {
        ImageStack stack = imp.getStack();
        if (stack.isRGB()) type = RGB_STACK;
        else if (stack.isHSB()) type = HSB_STACK;
      }
      if (type==ImagePlus.GRAY8) {
      ImageProcessor ip = imp.getProcessor();
        if (ip!=null && ip.getMinThreshold()==ImageProcessor.NO_THRESHOLD && ip.isColorLut()) {
          type = ImagePlus.COLOR_256;
          if (!ip.isPseudoColorLut())
            imp.setType(ImagePlus.COLOR_256);
        }
      }
      switch (type) {
        case ImagePlus.GRAY8:
        gray8Item.setState(true);
        break;
         case ImagePlus.GRAY16:
        gray16Item.setState(true);
        break;
         case ImagePlus.GRAY32:
        gray32Item.setState(true);
        break;
         case ImagePlus.COLOR_256:
        color256Item.setState(true);
        break;
        case ImagePlus.COLOR_RGB:
        colorRGBItem.setState(true);
        break;
        case RGB_STACK:
        RGBStackItem.setState(true);
        break;
        case HSB_STACK:
        HSBStackItem.setState(true);
        break;
    }
   
      //update Window menu
      int nItems = window.getItemCount();
      int start = WINDOW_MENU_ITEMS + windowMenuItems2;
      int index = start + WindowManager.getCurrentIndex();
      try // workaround for Linux/Java 5.0/bug
      for (int i=start; i<nItems; i++) {
        CheckboxMenuItem item = (CheckboxMenuItem)window.getItem(i);
        item.setState(i==index);
      }
    } catch (NullPointerException e) {}
  }
 
  static boolean isColorLut(ImagePlus imp) {
    ImageProcessor ip = imp.getProcessor();
      IndexColorModel cm = (IndexColorModel)ip.getColorModel();
      if (cm==null) return false;
    int mapSize = cm.getMapSize();
    byte[] reds = new byte[mapSize];
    byte[] greens = new byte[mapSize];
    byte[] blues = new byte[mapSize]
    cm.getReds(reds);
    cm.getGreens(greens);
    cm.getBlues(blues);
    boolean isColor = false;
    for (int i=0; i<mapSize; i++) {
      if ((reds[i] != greens[i]) || (greens[i] != blues[i])) {
        isColor = true;
        break;
      }
    }
    return isColor;
  }

 
  /** Returns the path to the user plugins directory or
    null if the plugins directory was not found. */
  public static String getPlugInsPath() {
    return pluginsPath;
  }

  /** Returns the path to the macros directory or
    null if the macros directory was not found. */
  public static String getMacrosPath() {
    return macrosPath;
  }
       
  /** Returns the hashtable that associates commands with plugins. */
  public static Hashtable getCommands() {
    return pluginsTable;
  }
       
  /** Returns the hashtable that associates shortcuts with commands. The keys
    in the hashtable are Integer keycodes, or keycode+200 for uppercase. */
  public static Hashtable getShortcuts() {
    return shortcuts;
  }
       
  /** Returns the hashtable that associates keyboard shortcuts with macros. The keys
    in the hashtable are Integer keycodes, or keycode+200 for uppercase. */
  public static Hashtable getMacroShortcuts() {
    if (macroShortcuts==null) macroShortcuts = new Hashtable();
    return macroShortcuts;
  }
       
  /** Returns the hashtable that associates menu names with menus. */
  //public static Hashtable getMenus() {
  //  return menusTable;
  //}

  /** Inserts one item (a non-image window) into the Window menu. */
  static synchronized void insertWindowMenuItem(Frame win) {
    if (ij==null || win==null)
      return;
    CheckboxMenuItem item = new CheckboxMenuItem(win.getTitle());
    item.addItemListener(ij);
    int index = WINDOW_MENU_ITEMS+windowMenuItems2;
    if (windowMenuItems2>=2)
      index--;
    window.insert(item, index);
    windowMenuItems2++;
    if (windowMenuItems2==1) {
      window.insertSeparator(WINDOW_MENU_ITEMS+windowMenuItems2);
      windowMenuItems2++;
    }
    //IJ.write("insertWindowMenuItem: "+windowMenuItems2);
  }

  /** Adds one image to the end of the Window menu. */
  static synchronized void addWindowMenuItem(ImagePlus imp) {
    //IJ.log("addWindowMenuItem: "+imp);
    if (ij==null) return;
    String name = imp.getTitle();
    int size = (imp.getWidth()*imp.getHeight()*imp.getStackSize())/1024;
    switch (imp.getType()) {
      case ImagePlus.GRAY32: case ImagePlus.COLOR_RGB: // 32-bit
        size *=4;
        break;
      case ImagePlus.GRAY16:  // 16-bit
        size *= 2;
        break;
      default: // 8-bit
        ;
    }
    CheckboxMenuItem item = new CheckboxMenuItem(name + " " + size + "K");
    window.add(item);
    item.addItemListener(ij);
  }
 
  /** Removes the specified item from the Window menu. */
  static synchronized void removeWindowMenuItem(int index) {
    //IJ.log("removeWindowMenuItem: "+index+" "+windowMenuItems2+" "+window.getItemCount());
    if (ij==null)
      return;
    if (index>=0 && index<window.getItemCount()) {
      window.remove(WINDOW_MENU_ITEMS+index);
      if (index<windowMenuItems2) {
        windowMenuItems2--;
        if (windowMenuItems2==1) {
          window.remove(WINDOW_MENU_ITEMS);
          windowMenuItems2 = 0;
        }
      }
    }
  }

  /** Changes the name of an item in the Window menu. */
  public static synchronized void updateWindowMenuItem(String oldLabel, String newLabel) {
    if (oldLabel.equals(newLabel))
      return;
    int first = WINDOW_MENU_ITEMS;
    int last = window.getItemCount()-1;
    //IJ.write("updateWindowMenuItem: "+" "+first+" "+last+" "+oldLabel+" "+newLabel);
    try // workaround for Linux/Java 5.0/bug
      for (int i=first; i<=last; i++) {
        MenuItem item = window.getItem(i);
        //IJ.write(i+" "+item.getLabel()+" "+newLabel);
        String label = item.getLabel();
        if (item!=null && label.startsWith(oldLabel)) {
          if (label.endsWith("K")) {
            int index = label.lastIndexOf(' ');
            if (index>-1)
              newLabel += label.substring(index, label.length());
          }
          item.setLabel(newLabel);
          return;
        }
      }
    } catch (NullPointerException e) {}
  }
 
  /** Adds a file path to the beginning of the File/Open Recent submenu. */
  public static synchronized void addOpenRecentItem(String path) {
    if (ij==null) return;
    int count = openRecentMenu.getItemCount();
    if (count>0 && openRecentMenu.getItem(0).getLabel().equals(path))
      return;
    if (count==MAX_OPEN_RECENT_ITEMS)
      openRecentMenu.remove(MAX_OPEN_RECENT_ITEMS-1);
    MenuItem item = new MenuItem(path);
    openRecentMenu.insert(item, 0);
    item.addActionListener(ij);
  }

  public static PopupMenu getPopupMenu() {
    return popup;
  }
 
  /** Adds a plugin based command to the end of a specified menu.
  * @param plugin      the plugin (e.g. "Inverter_", "Inverter_("arg")")
  * @param menuCode    PLUGINS_MENU, IMPORT_MENU, SAVE_AS_MENU or HOT_KEYS
  * @param command    the menu item label (set to "" to uninstall)
  * @param shortcut    the keyboard shortcut (e.g. "y", "Y", "F1")
  * @param ij        ImageJ (the action listener)
  *
  * @return        returns an error code(NORMAL_RETURN,COMMAND_IN_USE_ERROR, etc.)
  */
  public static int installPlugin(String plugin, char menuCode, String command, String shortcut, ImageJ ij) {
    if (command.equals("")) { //uninstall
      //Object o = pluginsPrefs.remove(plugin);
      //if (o==null)
      //  return NOT_INSTALLED;
      //else
        return NORMAL_RETURN;
    }
   
    if (commandInUse(command))
      return COMMAND_IN_USE;
    if (!validShortcut(shortcut))
      return INVALID_SHORTCUT;
    if (shortcutInUse(shortcut))
      return SHORTCUT_IN_USE;
     
    Menu menu;
    switch (menuCode) {
      case PLUGINS_MENU: menu = pluginsMenu; break;
      case IMPORT_MENU: menu = importMenu; break;
      case SAVE_AS_MENU: menu = saveAsMenu; break;
      case SHORTCUTS_MENU: menu = shortcutsMenu; break;
      case ABOUT_MENU: menu = aboutMenu; break;
      case FILTERS_MENU: menu = filtersMenu; break;
      case TOOLS_MENU: menu = toolsMenu; break;
      case UTILITIES_MENU: menu = utilitiesMenu; break;
      default: return 0;
    }
    int code = convertShortcutToCode(shortcut);
    MenuItem item;
    boolean functionKey = code>=KeyEvent.VK_F1 && code<=KeyEvent.VK_F12;
    if (code==0)
      item = new MenuItem(command);
    else if (functionKey) {
      command += " [F"+(code-KeyEvent.VK_F1+1)+"]";
      shortcuts.put(new Integer(code),command);
      item = new MenuItem(command);
    }else {
      shortcuts.put(new Integer(code),command);
      int keyCode = code;
      boolean shift = false;
      if (keyCode>=265 && keyCode<=290) {
        keyCode -= 200;
        shift = true;
      }
      item = new MenuItem(command, new MenuShortcut(keyCode, shift));
    }
    menu.add(item);
    item.addActionListener(ij);
    pluginsTable.put(command, plugin);
    shortcut = code>0 && !functionKey?"["+shortcut+"]":"";
    //IJ.write("installPlugin: "+menuCode+",\""+command+shortcut+"\","+plugin);
    pluginsPrefs.addElement(menuCode+",\""+command+shortcut+"\","+plugin);
    return NORMAL_RETURN;
  }
 
  /** Deletes a command installed by installPlugin. */
  public static int uninstallPlugin(String command) {
    boolean found = false;
    for (Enumeration en=pluginsPrefs.elements(); en.hasMoreElements();) {
      String cmd = (String)en.nextElement();
      if (cmd.indexOf(command)>0) {
        pluginsPrefs.removeElement((Object)cmd);
        found = true;
        break;
      }
    }
    if (found)
      return NORMAL_RETURN;
    else
      return COMMAND_NOT_FOUND;

  }
 
  public static boolean commandInUse(String command) {
    if (pluginsTable.get(command)!=null)
      return true;
    else
      return false;
  }

  public static int convertShortcutToCode(String shortcut) {
    int code = 0;
    int len = shortcut.length();
    if (len==2 && shortcut.charAt(0)=='F') {
      code = KeyEvent.VK_F1+(int)shortcut.charAt(1)-49;
      if (code>=KeyEvent.VK_F1 && code<=KeyEvent.VK_F9)
        return code;
      else
        return 0;
    }
    if (len==3 && shortcut.charAt(0)=='F') {
      code = KeyEvent.VK_F10+(int)shortcut.charAt(2)-48;
      if (code>=KeyEvent.VK_F10 && code<=KeyEvent.VK_F12)
        return code;
      else
        return 0;
    }
    if (len==2 && shortcut.charAt(0)=='N') { // numeric keypad
      code = KeyEvent.VK_NUMPAD0+(int)shortcut.charAt(1)-48;
      if (code>=KeyEvent.VK_NUMPAD0 && code<=KeyEvent.VK_NUMPAD9)
        return code;
      switch (shortcut.charAt(1)) {
        case '/': return KeyEvent.VK_DIVIDE;
        case '*': return KeyEvent.VK_MULTIPLY;
        case '-': return KeyEvent.VK_SUBTRACT;
        case '+': return KeyEvent.VK_ADD;
        case '.': return KeyEvent.VK_DECIMAL;
        default: return 0;
      }
    }
    if (len!=1)
      return 0;
    int c = (int)shortcut.charAt(0);
    if (c>=65&&c<=90) //A-Z
      code = KeyEvent.VK_A+c-65 + 200;
    else if (c>=97&&c<=122) //a-z
      code = KeyEvent.VK_A+c-97;
    else if (c>=48&&c<=57) //0-9
      code = KeyEvent.VK_0+c-48;
    else {
      switch (c) {
        case 43: code = KeyEvent.VK_PLUS; break;
        case 45: code = KeyEvent.VK_MINUS; break;
        //case 92: code = KeyEvent.VK_BACK_SLASH; break;
        default: return 0;
      }
    }
    return code;
  }
 
  void installStartupMacroSet() {
    if (applet!=null) {
      String docBase = ""+applet.getDocumentBase();
      if (!docBase.endsWith("/")) {
        int index = docBase.lastIndexOf("/");
        if (index!=-1)
          docBase = docBase.substring(0, index+1);
      }
      IJ.runPlugIn("ij.plugin.URLOpener", docBase+"StartupMacros.txt");
      return;
    }
    if (macrosPath==null) {
      (new MacroInstaller()).installFromIJJar("/macros/StartupMacros.txt");
      return;
    }
    String path = macrosPath + "StartupMacros.txt";
    File f = new File(path);
    if (!f.exists()) {
      path = macrosPath + "StartupMacros.ijm";
      f = new File(path);
      if (!f.exists()) {
        (new MacroInstaller()).installFromIJJar("/macros/StartupMacros.txt");
        return;
      }
    }
    String libraryPath = macrosPath + "Library.txt";
    f = new File(libraryPath);
    boolean isLibrary = f.exists();
    try {
      MacroInstaller mi = new MacroInstaller();
      if (isLibrary) mi.installLibrary(libraryPath);
      mi.installFile(path);
      nMacros += mi.getMacroCount();
    } catch (Exception e) {}
  }
 
  static boolean validShortcut(String shortcut) {
    int len = shortcut.length();
    if (shortcut.equals(""))
      return true;
    else if (len==1)
      return true;
    else if (shortcut.startsWith("F") && (len==2 || len==3))
      return true;
    else
      return false;
  }

  public static boolean shortcutInUse(String shortcut) {
    int code = convertShortcutToCode(shortcut);
    if (shortcuts.get(new Integer(code))!=null)
      return true;
    else
      return false;
  }
 
  /** Set the size (in points) used for the fonts in ImageJ menus.
    Set the size to 0 to use the Java default size. */
  public static void setFontSize(int size) {
    if (size<9 && size!=0) size = 9;
    if (size>24) size = 24;
    fontSize = size;
  }
 
  /** Returns the size (in points) used for the fonts in ImageJ menus. Returns
    0 if the default font size is being used or if this is a Macintosh. */
  public static int getFontSize() {
    return IJ.isMacintosh()?0:fontSize;
  }
 
  public static Font getFont() {
    if (menuFont==null)
      menuFont =  new Font("SanSerif", Font.PLAIN, fontSize==0?12:fontSize);
    return menuFont;
  }

  /** Called once when ImageJ quits. */
  public static void savePreferences(Properties prefs) {
    int index = 0;
    for (Enumeration en=pluginsPrefs.elements(); en.hasMoreElements();) {
      String key = "plugin" + (index/10)%10 + index%10;
      String value = (String)en.nextElement();
      prefs.put(key, value);
      index++;
    }
    int n = openRecentMenu.getItemCount();
    for (int i=0; i<n; i++) {
      String key = ""+i;
      if (key.length()==1) key = "0"+key;
      key = "recent"+key;
      prefs.put(key, openRecentMenu.getItem(i).getLabel());
    }
    prefs.put(Prefs.MENU_SIZE, Integer.toString(fontSize));
  }

}
TOP

Related Classes of ij.Menus

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.