5 import java.awt.image.*;
6 import java.awt.event.*;
9 import java.applet.Applet;
10 import java.awt.event.*;
11 import java.util.zip.*;
26 public static final char PLUGINS_MENU =
'p';
27 public static final char IMPORT_MENU =
'i';
28 public static final char SAVE_AS_MENU =
's';
29 public static final char SHORTCUTS_MENU =
'h';
30 public static final char ABOUT_MENU =
'a';
31 public static final char FILTERS_MENU =
'f';
32 public static final char TOOLS_MENU =
't';
33 public static final char UTILITIES_MENU =
'u';
35 public static final int WINDOW_MENU_ITEMS = 5;
37 public static final int NORMAL_RETURN = 0;
38 public static final int COMMAND_IN_USE = -1;
39 public static final int INVALID_SHORTCUT = -2;
40 public static final int SHORTCUT_IN_USE = -3;
41 public static final int NOT_INSTALLED = -4;
42 public static final int COMMAND_NOT_FOUND = -5;
44 private static JMenuBar mbar;
45 private static JCheckBoxMenuItem gray8Item,gray16Item,gray32Item,
46 color256Item,colorRGBItem;
47 private static JPopupMenu popup;
50 private static Applet applet;
51 private static Hashtable demoImagesTable =
new Hashtable();
52 private static String pluginsPath;
53 private static JMenu pluginsMenu, importMenu, saveAsMenu, shortcutsMenu,
54 aboutMenu, filtersMenu, toolsMenu, utilitiesMenu, optionsMenu;
55 private static Hashtable pluginsTable;
59 private static Hashtable shortcuts =
new Hashtable();
60 private static Vector pluginsPrefs =
new Vector();
61 static int windowMenuItems2;
62 private static String error;
63 private String jarError;
64 private boolean isJarErrorHeading;
65 private boolean installingJars, duplicateCommand;
66 private static Vector jarFiles;
67 private int importCount, saveAsCount, toolsCount, optionsCount;
68 private static Hashtable menusTable;
69 private int userPluginsIndex;
70 private boolean addSorted;
74 applet = appletInstance;
79 pluginsTable =
new Hashtable();
81 JMenu file =
new JMenu(
"File");
82 addItem(file,
"Open Local", KeyEvent.VK_O,
false);
83 importMenu = addSubMenu(file,
"Import");
86 addItem(file,
"Revert", KeyEvent.VK_R,
false);
88 JMenu edit =
new JMenu(
"Edit");
89 addItem(edit,
"Undo", KeyEvent.VK_Z,
false);
91 addItem(edit,
"Cut", KeyEvent.VK_X,
false);
92 addItem(edit,
"Copy", KeyEvent.VK_C,
false);
93 addItem(edit,
"Paste", KeyEvent.VK_V,
false);
95 addPlugInItem(edit,
"Clear",
"ij.plugin.filter.Filler(\"clear\")", 0,
false);
96 addPlugInItem(edit,
"Clear Outside",
"ij.plugin.filter.Filler(\"outside\")", 0,
false);
97 addPlugInItem(edit,
"Fill",
"ij.plugin.filter.Filler(\"fill\")", KeyEvent.VK_F,
false);
98 addPlugInItem(edit,
"Draw",
"ij.plugin.filter.Filler(\"draw\")", KeyEvent.VK_D,
false);
99 addPlugInItem(edit,
"Invert",
"ij.plugin.filter.Filters(\"invert\")", KeyEvent.VK_I,
true);
101 addSubMenu(edit,
"Selection");
102 optionsMenu = addSubMenu(edit,
"Options");
104 JMenu image =
new JMenu(
"Image");
105 JMenu imageType =
new JMenu(
"Set Type");
106 gray8Item = addCheckboxItem(imageType,
"8-bit Greyscale",
"ij.plugin.Converter(\"8-bit\")");
107 gray16Item = addCheckboxItem(imageType,
"16-bit Greyscale",
"ij.plugin.Converter(\"16-bit\")");
108 gray32Item = addCheckboxItem(imageType,
"32-bit Greyscale",
"ij.plugin.Converter(\"32-bit\")");
109 color256Item = addCheckboxItem(imageType,
"8-bit Colour",
"ij.plugin.Converter(\"8-bit Color\")");
110 colorRGBItem = addCheckboxItem(imageType,
"RGB Colour",
"ij.plugin.Converter(\"RGB Color\")");
111 imageType.add(
new JMenuItem(
"-"));
112 image.add(imageType);
114 image.addSeparator();
115 addSubMenu(image,
"Adjust");
116 image.addSeparator();
117 addPlugInItem(image,
"Set Size...",
"ij.plugin.filter.Resizer", 0,
false);
118 addPlugInItem(image,
"Scale Size...",
"ij.plugin.filter.Scaler", KeyEvent.VK_E,
false);
119 addPlugInItem(image,
"Resize Canvas",
"ij.plugin.CanvasResizer", 0,
false);
120 addPlugInItem(image,
"Crop",
"ij.plugin.filter.Resizer(\"crop\")", 0,
false);
121 addSubMenu(image,
"Rotate");
123 JMenu process =
new JMenu(
"Process");
124 addPlugInItem(process,
"Smooth",
"ij.plugin.filter.Filters(\"smooth\")", KeyEvent.VK_S,
true);
125 addPlugInItem(process,
"Sharpen",
"ij.plugin.filter.Filters(\"sharpen\")", 0,
false);
126 addPlugInItem(process,
"Find Edges",
"ij.plugin.filter.Filters(\"edge\")", KeyEvent.VK_F,
true);
127 addPlugInItem(process,
"Enhance Contrast",
"ij.plugin.ContrastEnhancer", 0,
false);
128 addSubMenu(process,
"Noise");
129 addSubMenu(process,
"Shadows");
130 addSubMenu(process,
"Binary");
131 addSubMenu(process,
"Math");
132 process.addSeparator();
133 addPlugInItem(process,
"Subtract Background...",
"ij.plugin.filter.BackgroundSubtracter", 0,
false);
134 addItem(process,
"Repeat Command", KeyEvent.VK_R,
true);
135 JMenu help =
new JMenu(
"Help");
136 addPlugInItem(help,
"About Image Editor",
"ij.plugin.AboutBox", 0,
false);
138 mbar =
new JMenuBar();
139 mbar.setBorder(BorderFactory.createMatteBorder(1, 1, 0, 1, Color.BLACK));
146 ij.setJMenuBar(mbar);
149 error = error!=null?error+=
"\n"+jarError:jarError;
154 void addItem(JMenu menu, String label,
int shortcut,
boolean shift) {
158 item =
new JMenuItem(label);
159 if (addSorted && menu==pluginsMenu)
160 addItemSorted(menu, item, userPluginsIndex);
163 item.addActionListener(ij);
166 void addPlugInItem(JMenu menu, String label, String className,
int shortcut,
boolean shift) {
167 pluginsTable.put(label, className);
169 addItem(menu, label, shortcut, shift);
172 JCheckBoxMenuItem addCheckboxItem(JMenu menu, String label, String className) {
173 pluginsTable.put(label, className);
175 JCheckBoxMenuItem item =
new JCheckBoxMenuItem(label);
177 item.addItemListener(ij);
178 item.setState(
false);
182 JMenu addSubMenu(JMenu menu, String name)
185 String key = name.toLowerCase(Locale.US);
187 JMenu submenu=
new JMenu(name.replace(
'_',
' '));
189 index = key.indexOf(
' ');
191 key = key.substring(0, index);
193 for (
int count=1; count<100; count++) {
199 if (value.equals(
"-"))
200 submenu.addSeparator();
202 addPluginItem(submenu, value);
208 void addPluginItem(JMenu submenu, String s) {
209 if (s.equals(
"\"-\"")) {
211 addSeparator(submenu);
214 int lastComma = s.lastIndexOf(
',');
217 String command = s.substring(1,lastComma-1);
219 boolean shift =
false;
220 if (command.endsWith(
"]")) {
221 int openBracket = command.lastIndexOf(
'[');
223 String shortcut = command.substring(openBracket+1,command.length()-1);
224 keyCode = convertShortcutToCode(shortcut);
225 boolean functionKey = keyCode>=KeyEvent.VK_F1 && keyCode<=KeyEvent.VK_F12;
226 if (keyCode>0 && !functionKey)
227 command = command.substring(0,openBracket);
231 if (keyCode>=KeyEvent.VK_F1 && keyCode<=KeyEvent.VK_F12) {
232 shortcuts.put(
new Integer(keyCode),command);
234 }
else if (keyCode>200) {
238 addItem(submenu,command,keyCode,shift);
239 while(s.charAt(lastComma+1)==
' ' && lastComma+2<s.length())
241 String className = s.substring(lastComma+1,s.length());
244 duplicateCommand = pluginsTable.get(command)!=null;
245 pluginsTable.put(command, className);
249 void checkForDuplicate(String command) {
250 if (pluginsTable.get(command)!=null) {
254 void addPluginsMenu() {
255 String value,label,className;
257 pluginsMenu =
new JMenu(
"Plugins");
258 for (
int count=1; count<100; count++) {
262 char firstChar = value.charAt(0);
264 pluginsMenu.addSeparator();
265 else if (firstChar==
'>') {
266 String submenu = value.substring(2,value.length()-1);
267 JMenu menu = addSubMenu(pluginsMenu, submenu);
268 if (submenu.equals(
"Shortcuts"))
269 shortcutsMenu = menu;
270 else if (submenu.equals(
"Utilities"))
271 utilitiesMenu = menu;
273 addPluginItem(pluginsMenu, value);
275 userPluginsIndex = pluginsMenu.getItemCount();
276 if (userPluginsIndex<0) userPluginsIndex = 0;
282 void installPlugins() {
283 String value, className;
287 String[] plugins2 = null;
288 Hashtable skipList =
new Hashtable();
289 for (
int index=0; index<100; index++) {
293 menuCode = value.charAt(0);
295 case PLUGINS_MENU:
default: menu = pluginsMenu;
break;
296 case IMPORT_MENU: menu = importMenu;
break;
297 case SAVE_AS_MENU: menu = saveAsMenu;
break;
298 case SHORTCUTS_MENU: menu = shortcutsMenu;
break;
299 case ABOUT_MENU: menu = aboutMenu;
break;
300 case FILTERS_MENU: menu = filtersMenu;
break;
301 case TOOLS_MENU: menu = toolsMenu;
break;
302 case UTILITIES_MENU: menu = utilitiesMenu;
break;
304 String prefsValue = value;
305 value = value.substring(2,value.length());
306 className = value.substring(value.lastIndexOf(
',')+1,value.length());
307 boolean found = className.startsWith(
"ij.");
308 if (!found && plugins!=null) {
310 plugins2 = getStrippedPlugins(plugins);
311 for (
int i=0; i<plugins2.length; i++) {
312 if (className.startsWith(plugins2[i])) {
319 addPluginItem(menu, value);
320 pluginsPrefs.addElement(prefsValue);
321 if (className.endsWith(
"\")")) {
322 int argStart = className.lastIndexOf(
"(\"");
324 className = className.substring(0, argStart);
326 skipList.put(className,
"");
330 for (
int i=0; i<plugins.length; i++) {
331 if (!skipList.containsKey(plugins[i]))
332 installUserPlugin(plugins[i]);
340 void installJarPlugins() {
343 installingJars =
true;
344 for (
int i=0; i<jarFiles.size(); i++) {
345 isJarErrorHeading =
false;
346 String jar = (String)jarFiles.elementAt(i);
347 InputStream is = getConfigurationFile(jar);
348 if (is==null)
continue;
349 LineNumberReader lnr =
new LineNumberReader(
new InputStreamReader(is));
352 String s = lnr.readLine();
354 installJarPlugin(jar, s);
357 catch (IOException e) {}
359 try {
if (lnr!=null) lnr.close();}
360 catch (IOException e) {}
366 void installJarPlugin(String jar, String s) {
368 if (s.length()<3)
return;
369 char firstChar = s.charAt(0);
370 if (firstChar==
'#')
return;
373 if (s.startsWith(
"Plugins>")) {
374 int firstComma = s.indexOf(
',');
375 if (firstComma==-1 || firstComma<=8)
378 String name = s.substring(8, firstComma);
379 menu = getPluginsSubmenu(name);
381 }
else if (firstChar==
'"' || s.startsWith(
"Plugins")) {
382 String name = getSubmenuName(jar);
384 menu = getPluginsSubmenu(name);
389 }
else if (s.startsWith(
"File>Import")) {
391 if (importCount==0) addSeparator(menu);
393 }
else if (s.startsWith(
"File>Save")) {
395 if (saveAsCount==0) addSeparator(menu);
397 }
else if (s.startsWith(
"Analyze>Tools")) {
399 if (toolsCount==0) addSeparator(menu);
401 }
else if (s.startsWith(
"Help>About")) {
403 }
else if (s.startsWith(
"Edit>Options")) {
405 if (optionsCount==0) addSeparator(menu);
408 if (jarError==null) jarError =
"";
409 addJarErrorHeading(jar);
410 jarError +=
" Invalid menu: " + s +
"\n";
413 int firstQuote = s.indexOf(
'"');
416 s = s.substring(firstQuote, s.length());
418 addPluginItem(menu, s);
421 if (duplicateCommand) {
422 if (jarError==null) jarError =
"";
423 addJarErrorHeading(jar);
424 jarError +=
" Duplicate command: " + s +
"\n";
426 duplicateCommand =
false;
429 void addJarErrorHeading(String jar) {
430 if (!isJarErrorHeading) {
431 if (!jarError.equals(
""))
433 jarError +=
"Plugin configuration error: " + jar +
"\n";
434 isJarErrorHeading =
true;
438 JMenu getPluginsSubmenu(String submenuName) {
439 if (menusTable!=null) {
440 JMenu menu = (JMenu)menusTable.get(submenuName);
444 JMenu menu =
new JMenu(submenuName);
446 addItemSorted(pluginsMenu, menu, userPluginsIndex);
447 if (menusTable==null) menusTable =
new Hashtable();
448 menusTable.put(submenuName, menu);
453 String getSubmenuName(String jarPath) {
455 int index = jarPath.lastIndexOf(File.separatorChar);
456 if (index<0)
return null;
457 String name = jarPath.substring(0, index);
458 index = name.lastIndexOf(File.separatorChar);
459 if (index<0)
return null;
460 name = name.substring(index+1);
461 if (name.equals(
"plugins"))
return null;
466 void addItemSorted(JMenu menu, JMenuItem item,
int startingIndex) {
467 String itemLabel = item.getText();
468 int count = menu.getItemCount();
469 boolean inserted =
false;
470 for (
int i=startingIndex; i<count; i++) {
471 JMenuItem mi = menu.getItem(i);
472 String label = mi.getText();
474 if (itemLabel.compareTo(label)<0) {
475 menu.insert(item, i);
480 if (!inserted) menu.add(item);
483 void addSeparator(JMenu menu) {
488 InputStream getConfigurationFile(String jar) {
490 ZipFile jarFile =
new ZipFile(jar);
491 Enumeration entries = jarFile.entries();
492 while (entries.hasMoreElements()) {
493 ZipEntry entry = (ZipEntry) entries.nextElement();
494 if (entry.getName().endsWith(
"plugins.config"))
495 return jarFile.getInputStream(entry);
498 catch (Exception e) {}
503 String[] getStrippedPlugins(String[] plugins) {
504 String[] plugins2 =
new String[plugins.length];
506 for (
int i=0; i<plugins2.length; i++) {
507 plugins2[i] = plugins[i];
508 slashPos = plugins2[i].lastIndexOf(
'/');
510 plugins2[i] = plugins[i].substring(slashPos+1,plugins2[i].length());
520 if (homeDir.endsWith(
"plugins"))
521 pluginsPath = homeDir;
523 String pluginsDir = System.getProperty(
"plugins.dir");
524 if (pluginsDir==null)
525 pluginsDir = homeDir;
526 else if (pluginsDir.equals(
"user.home"))
527 pluginsDir = System.getProperty(
"user.home");
530 File f = pluginsPath!=null?
new File(pluginsPath):null;
531 if (f==null || (f!=null && !f.isDirectory())) {
532 error =
"Plugins folder not found at "+pluginsPath;
536 String[] list = f.list();
539 Vector v =
new Vector();
541 for (
int i=0; i<list.length; i++) {
542 String name = list[i];
543 boolean isClassFile = name.endsWith(
".class");
544 boolean hasUnderscore = name.indexOf(
'_')>=0;
545 if (hasUnderscore && isClassFile && name.indexOf(
'$')<0 ) {
546 name = name.substring(0, name.length()-6);
548 }
else if (hasUnderscore && (name.endsWith(
".jar") || name.endsWith(
".zip"))) {
549 if (jarFiles==null) jarFiles =
new Vector();
550 jarFiles.addElement(pluginsPath + name);
551 }
else if (hasUnderscore && (name.endsWith(
".txt"))) {
554 checkSubdirectory(pluginsPath, name, v);
557 list =
new String[v.size()];
558 v.copyInto((String[])list);
559 StringSorter.sort(list);
564 static void checkSubdirectory(String path, String dir, Vector v) {
565 if (dir.endsWith(
".java"))
567 File f =
new File(path, dir);
568 if (!f.isDirectory())
570 String[] list = f.list();
574 for (
int i=0; i<list.length; i++) {
575 String name = list[i];
576 boolean hasUnderscore = name.indexOf(
'_')>=0;
577 if (hasUnderscore && name.endsWith(
".class") && name.indexOf(
'$')<0) {
578 name = name.substring(0, name.length()-6);
579 v.addElement(dir+name);
581 }
else if (hasUnderscore && (name.endsWith(
".jar") || name.endsWith(
".zip"))) {
582 if (jarFiles==null) jarFiles =
new Vector();
583 jarFiles.addElement(f.getPath() + File.separator + name);
584 }
else if (hasUnderscore && (name.endsWith(
".txt"))) {
589 static String submenuName;
590 static JMenu submenu;
594 void installUserPlugin(String className) {
595 JMenu menu = pluginsMenu;
596 int slashIndex = className.indexOf(
'/');
598 String dir = className.substring(0, slashIndex);
599 className = className.substring(slashIndex+1, className.length());
601 if (submenu==null || !submenuName.equals(dir)) {
603 submenu =
new JMenu(submenuName);
604 pluginsMenu.add(submenu);
605 if (menusTable==null) menusTable =
new Hashtable();
606 menusTable.put(submenuName, submenu);
611 String command = className.replace(
'_',
' ');
613 JMenuItem item =
new JMenuItem(command);
615 item.addActionListener(ij);
616 pluginsTable.put(command, className);
620 void installPopupMenu(ImageJ ij) {
624 popup =
new JPopupMenu(
"");
628 s =
Prefs.getString(
"popup" + (count/10)%10 + count%10);
632 popup.addSeparator();
633 else if (!s.equals(
"")) {
634 mi =
new JMenuItem(s);
635 mi.addActionListener(ij);
641 public static JMenuBar getMenuBar() {
649 if (ij==null)
return;
650 gray8Item.setState(
false);
651 gray16Item.setState(
false);
652 gray32Item.setState(
false);
653 color256Item.setState(
false);
654 colorRGBItem.setState(
false);
661 if (ip!=null && ip.getMinThreshold()==ImageProcessor.NO_THRESHOLD && ip.isColorLut()) {
663 if (!ip.isPseudoColorLut())
669 gray8Item.setState(
true);
672 gray16Item.setState(
true);
675 gray32Item.setState(
true);
678 color256Item.setState(
true);
681 colorRGBItem.setState(
true);
687 static boolean isColorLut(
ImagePlus imp) {
689 IndexColorModel cm = (IndexColorModel)ip.getColorModel();
690 if (cm==null)
return false;
691 int mapSize = cm.getMapSize();
692 byte[] reds =
new byte[mapSize];
693 byte[] greens =
new byte[mapSize];
694 byte[] blues =
new byte[mapSize];
696 cm.getGreens(greens);
698 boolean isColor =
false;
699 for (
int i=0; i<mapSize; i++) {
700 if ((reds[i] != greens[i]) || (greens[i] != blues[i])) {
728 public static JPopupMenu getPopupMenu() {
741 public static int installPlugin(String plugin,
char menuCode, String command, String shortcut,
ImageJ ij) {
742 if (command.equals(
"")) {
747 return NORMAL_RETURN;
750 if (commandInUse(command))
751 return COMMAND_IN_USE;
752 if (!validShortcut(shortcut))
753 return INVALID_SHORTCUT;
754 if (shortcutInUse(shortcut))
755 return SHORTCUT_IN_USE;
759 case PLUGINS_MENU: menu = pluginsMenu;
break;
760 case IMPORT_MENU: menu = importMenu;
break;
761 case SAVE_AS_MENU: menu = saveAsMenu;
break;
762 case SHORTCUTS_MENU: menu = shortcutsMenu;
break;
763 case ABOUT_MENU: menu = aboutMenu;
break;
764 case FILTERS_MENU: menu = filtersMenu;
break;
765 case TOOLS_MENU: menu = toolsMenu;
break;
766 case UTILITIES_MENU: menu = utilitiesMenu;
break;
769 int code = convertShortcutToCode(shortcut);
771 boolean functionKey = code>=KeyEvent.VK_F1 && code<=KeyEvent.VK_F12;
773 item =
new JMenuItem(command);
774 else if (functionKey) {
775 command +=
" [F"+(code-KeyEvent.VK_F1+1)+
"]";
776 shortcuts.put(
new Integer(code),command);
777 item =
new JMenuItem(command);
779 shortcuts.put(
new Integer(code),command);
781 boolean shift =
false;
786 item =
new JMenuItem(command);
789 item.addActionListener(ij);
790 pluginsTable.put(command, plugin);
791 shortcut = code>0 && !functionKey?
"["+shortcut+
"]":
"";
793 pluginsPrefs.addElement(menuCode+
",\""+command+shortcut+
"\","+plugin);
794 return NORMAL_RETURN;
799 boolean found =
false;
800 for (Enumeration en=pluginsPrefs.elements(); en.hasMoreElements();) {
801 String cmd = (String)en.nextElement();
802 if (cmd.indexOf(command)>0) {
803 pluginsPrefs.removeElement((Object)cmd);
809 return NORMAL_RETURN;
811 return COMMAND_NOT_FOUND;
815 public static boolean commandInUse(String command) {
816 if (pluginsTable.get(command)!=null)
822 public static int convertShortcutToCode(String shortcut) {
824 int len = shortcut.length();
825 if (len==2 && shortcut.startsWith(
"F")) {
826 code = KeyEvent.VK_F1+(int)shortcut.charAt(1)-49;
827 if (code>=KeyEvent.VK_F1 && code<=KeyEvent.VK_F9)
832 if (len==3 && shortcut.startsWith(
"F")) {
833 code = KeyEvent.VK_F10+(int)shortcut.charAt(2)-48;
834 if (code>=KeyEvent.VK_F10 && code<=KeyEvent.VK_F12)
841 int c = (int)shortcut.charAt(0);
843 code = KeyEvent.VK_A+c-65 + 200;
844 else if (c>=97&&c<=122)
845 code = KeyEvent.VK_A+c-97;
846 else if (c>=48&&c<=57)
847 code = KeyEvent.VK_0+c-48;
851 static boolean validShortcut(String shortcut) {
852 int len = shortcut.length();
853 if (shortcut.equals(
""))
857 else if (shortcut.startsWith(
"F") && (len==2 || len==3))
863 public static boolean shortcutInUse(String shortcut) {
864 int code = convertShortcutToCode(shortcut);
865 if (shortcuts.get(
new Integer(code))!=null)
874 for (Enumeration en=pluginsPrefs.elements(); en.hasMoreElements();) {
875 String key =
"plugin" + (index/10)%10 + index%10;
876 prefs.put(key, (String)en.nextElement());