Menus.WINDOW_MENU_ITEMS && !(IJ.macroRunning()&&WindowManager.getImageCount()==0)) {
+ GenericDialog gd = new GenericDialog("ImageJ", this);
+ gd.addMessage("Are you sure you want to quit ImageJ?");
+ gd.showDialog();
+ quitting = !gd.wasCanceled();
+ windowClosed = false;
+ }
+ if (!quitting)
+ return;
+ if (!WindowManager.closeAllWindows()) {
+ quitting = false;
+ return;
+ }
+ if (applet==null) {
+ saveWindowLocations();
+ Prefs.set(ImageWindow.LOC_KEY,null); // don't save image window location
+ Prefs.savePreferences();
+ }
+ IJ.cleanup();
+ dispose();
+ if (exitWhenQuitting)
+ System.exit(0);
+ }
+
+ void saveWindowLocations() {
+ Window win = WindowManager.getWindow("B&C");
+ if (win!=null)
+ Prefs.saveLocation(ContrastAdjuster.LOC_KEY, win.getLocation());
+ win = WindowManager.getWindow("Threshold");
+ if (win!=null)
+ Prefs.saveLocation(ThresholdAdjuster.LOC_KEY, win.getLocation());
+ win = WindowManager.getWindow("Results");
+ if (win!=null) {
+ Prefs.saveLocation(TextWindow.LOC_KEY, win.getLocation());
+ Dimension d = win.getSize();
+ Prefs.set(TextWindow.WIDTH_KEY, d.width);
+ Prefs.set(TextWindow.HEIGHT_KEY, d.height);
+ }
+ win = WindowManager.getWindow("Log");
+ if (win!=null) {
+ Prefs.saveLocation(TextWindow.LOG_LOC_KEY, win.getLocation());
+ Dimension d = win.getSize();
+ Prefs.set(TextWindow.LOG_WIDTH_KEY, d.width);
+ Prefs.set(TextWindow.LOG_HEIGHT_KEY, d.height);
+ }
+ win = WindowManager.getWindow("ROI Manager");
+ if (win!=null)
+ Prefs.saveLocation(RoiManager.LOC_KEY, win.getLocation());
+ }
+
+ public static String getCommandName() {
+ return commandName!=null?commandName:"null";
+ }
+
+ public static void setCommandName(String name) {
+ commandName = name;
+ }
+
+ public void resize() {
+ double scale = Prefs.getGuiScale();
+ toolbar.init();
+ statusLine.setFont(new Font("SansSerif", Font.PLAIN, (int)(13*scale)));
+ progressBar.init((int)(ProgressBar.WIDTH*scale), (int)(ProgressBar.HEIGHT*scale));
+ pack();
+ }
+
+ /** Handles exceptions on the EDT. */
+ public static class ExceptionHandler implements Thread.UncaughtExceptionHandler {
+
+ // for EDT exceptions
+ public void handle(Throwable thrown) {
+ handleException(Thread.currentThread().getName(), thrown);
+ }
+
+ // for other uncaught exceptions
+ public void uncaughtException(Thread thread, Throwable thrown) {
+ handleException(thread.getName(), thrown);
+ }
+
+ protected void handleException(String tname, Throwable e) {
+ if (Macro.MACRO_CANCELED.equals(e.getMessage()))
+ return;
+ CharArrayWriter caw = new CharArrayWriter();
+ PrintWriter pw = new PrintWriter(caw);
+ e.printStackTrace(pw);
+ String s = caw.toString();
+ if (s!=null && s.contains("ij.")) {
+ if (IJ.getInstance()!=null)
+ s = IJ.getInstance().getInfo()+"\n"+s;
+ IJ.log(s);
+ }
+ }
+
+ } // inner class ExceptionHandler
+
+}
diff --git a/mrj/26/ij/ImageJApplet.java b/mrj/26/ij/ImageJApplet.java
new file mode 100644
index 00000000..e820e01b
--- /dev/null
+++ b/mrj/26/ij/ImageJApplet.java
@@ -0,0 +1,37 @@
+package ij;
+
+import ij.stub.Applet;
+
+/**
+ Runs ImageJ as an applet and optionally opens up to
+ nine images using URLs passed as a parameters.
+
+ Here is an example applet tag that launches ImageJ as an applet
+ and passes it the URLs of two images:
+
+ <applet archive="../ij.jar" code="ij.ImageJApplet.class" width=0 height=0>
+ <param name=url1 value="http://imagej.nih.gov/ij/images/FluorescentCells.jpg">
+ <param name=url2 value="http://imagej.nih.gov/ij/images/blobs.gif">
+ </applet>
+
+ To use plugins, add them to ij.jar and add entries to IJ_Props.txt file (in ij.jar) that will
+ create commands for them in the Plugins menu, or a submenu. There are examples
+ of such entries in IJ.Props.txt, in the "Plugins installed in the Plugins menu" section.
+
+ Macros contained in a file named "StartupMacros.txt", in the same directory as the HTML file
+ containing the applet tag, will be installed on startup.
+ @deprecated All methods can unconditionally throw since removal of Applets in Java 26.
+*/
+@Deprecated(since = "IJ XX; Java 26")
+public class ImageJApplet extends Applet {
+
+ /** Starts ImageJ if it's not already running. */
+ public void init() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void destroy() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+}
+
diff --git a/mrj/26/ij/Menus.java b/mrj/26/ij/Menus.java
new file mode 100644
index 00000000..d3fca3c2
--- /dev/null
+++ b/mrj/26/ij/Menus.java
@@ -0,0 +1,1747 @@
+package ij;
+import ij.process.*;
+import ij.stub.Applet;
+import ij.util.*;
+import ij.gui.ImageWindow;
+import ij.plugin.MacroInstaller;
+import ij.gui.Toolbar;
+import ij.macro.Interpreter;
+import java.awt.*;
+import java.awt.image.*;
+import java.awt.event.*;
+import java.util.*;
+import java.io.*;
+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 = 6; // 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 Menus instance;
+ private static MenuBar mbar;
+ private static CheckboxMenuItem gray8Item,gray16Item,gray32Item,
+ color256Item,colorRGBItem,RGBStackItem,HSBStackItem,LabStackItem,HSB32Item;
+ private static PopupMenu popup;
+
+ private static ImageJ ij;
+ private static Applet applet;
+ private Hashtable demoImagesTable = new Hashtable();
+ private static String ImageJPath, pluginsPath, macrosPath;
+ private static Properties menus;
+ private static Properties menuSeparators;
+ private static Menu pluginsMenu, saveAsMenu, shortcutsMenu, utilitiesMenu, macrosMenu;
+ static Menu window, openRecentMenu;
+ private static Hashtable pluginsTable;
+
+ private static int nPlugins, nMacros;
+ private static Hashtable shortcuts;
+ private static Hashtable macroShortcuts;
+ private static Vector pluginsPrefs; // commands saved in IJ_Prefs
+ static int windowMenuItems2; // non-image windows listed in Window menu + separator
+ private String error;
+ private String jarError;
+ private String pluginError;
+ private boolean isJarErrorHeading;
+ private static boolean installingJars, duplicateCommand;
+ private static Vector jarFiles; // JAR files in plugins folder with "_" in their name
+ private Map menuEntry2jarFile = new HashMap();
+ private static Vector macroFiles; // Macros and scripts in the plugins folder
+ private static int userPluginsIndex; // First user plugin or submenu in Plugins menu
+ private static boolean addSorted;
+ private static int defaultFontSize = IJ.isWindows()?15:0;
+ private static int fontSize;
+ private static double scale = 1.0;
+ private static Font cachedFont;
+
+ static boolean jnlp; // true when using Java WebStart
+ public static int setMenuBarCount;
+
+ Menus(ImageJ ijInstance, Applet appletInstance) {
+ ij = ijInstance;
+ String title = ij!=null?ij.getTitle():null;
+ applet = appletInstance;
+ instance = this;
+ fontSize = Prefs.getInt(Prefs.MENU_SIZE, defaultFontSize);
+ }
+
+ String addMenuBar() {
+ scale = Prefs.getGuiScale();
+ //if ((scale>=1.5&&scale<2.0) || (scale>=2.5&&scale<3.0))
+ // scale = (int)Math.round(scale);
+ nPlugins = nMacros = userPluginsIndex = 0;
+ addSorted = installingJars = duplicateCommand = false;
+ error = null;
+ mbar = null;
+ menus = new Properties();
+ pluginsTable = new Hashtable();
+ shortcuts = new Hashtable();
+ pluginsPrefs = new Vector();
+ macroShortcuts = null;
+ setupPluginsAndMacrosPaths();
+ Menu file = getMenu("File");
+ Menu newMenu = getMenu("File>New", true);
+ addPlugInItem(file, "Open...", "ij.plugin.Commands(\"open\")", KeyEvent.VK_O, false);
+ addPlugInItem(file, "Open Next", "ij.plugin.NextImageOpener", KeyEvent.VK_O, true);
+ Menu openSamples = getMenu("File>Open Samples", true);
+ openSamples.addSeparator();
+ addPlugInItem(openSamples, "Cache Sample Images ", "ij.plugin.URLOpener(\"cache\")", 0, false);
+ addOpenRecentSubMenu(file);
+ Menu importMenu = getMenu("File>Import", true);
+ Menu showFolderMenu = new Menu("Show Folder");
+ fixFontSize(showFolderMenu);
+ file.add(showFolderMenu);
+ addPlugInItem(showFolderMenu, "Image", "ij.plugin.SimpleCommands(\"showdirImage\")", 0, false);
+ addPlugInItem(showFolderMenu, "Plugins", "ij.plugin.SimpleCommands(\"showdirPlugins\")", 0, false);
+ addPlugInItem(showFolderMenu, "Macros", "ij.plugin.SimpleCommands(\"showdirMacros\")", 0, false);
+ addPlugInItem(showFolderMenu, "LUTs", "ij.plugin.SimpleCommands(\"showdirLuts\")", 0, false);
+ addPlugInItem(showFolderMenu, "ImageJ", "ij.plugin.SimpleCommands(\"showdirImageJ\")", 0, false);
+ addPlugInItem(showFolderMenu, "temp", "ij.plugin.SimpleCommands(\"showdirTemp\")", 0, false);
+ addPlugInItem(showFolderMenu, "Home", "ij.plugin.SimpleCommands(\"showdirHome\")", 0, false);
+ file.addSeparator();
+ addPlugInItem(file, "Close", "ij.plugin.Commands(\"close\")", KeyEvent.VK_W, false);
+ addPlugInItem(file, "Close All", "ij.plugin.Commands(\"close-all\")", KeyEvent.VK_W, true);
+ addPlugInItem(file, "Save", "ij.plugin.Commands(\"save\")", KeyEvent.VK_S, false);
+ saveAsMenu = getMenu("File>Save As", true);
+ addPlugInItem(file, "Revert", "ij.plugin.Commands(\"revert\")", KeyEvent.VK_R, true);
+ 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);
+
+ Menu edit = getMenu("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();
+ getMenu("Edit>Selection", true);
+ Menu optionsMenu = getMenu("Edit>Options", true);
+
+ Menu image = getMenu("Image");
+ Menu imageType = getMenu("Image>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\")");
+ HSB32Item = addCheckboxItem(imageType, "HSB (32-bit)", "ij.plugin.Converter(\"HSB (32-bit)\")");
+ LabStackItem = addCheckboxItem(imageType, "Lab Stack", "ij.plugin.Converter(\"Lab Stack\")");
+ image.add(imageType);
+
+ image.addSeparator();
+ getMenu("Image>Adjust", true);
+ addPlugInItem(image, "Show Info...", "ij.plugin.ImageInfo", KeyEvent.VK_I, false);
+ addPlugInItem(image, "Properties...", "ij.plugin.filter.ImageProperties", KeyEvent.VK_P, true);
+ getMenu("Image>Color", true);
+ getMenu("Image>Stacks", true);
+ getMenu("Image>Stacks>Animation_", true);
+ getMenu("Image>Stacks>Tools_", true);
+ Menu hyperstacksMenu = getMenu("Image>Hyperstacks", true);
+ image.addSeparator();
+ addPlugInItem(image, "Crop", "ij.plugin.Resizer(\"crop\")", KeyEvent.VK_X, true);
+ addPlugInItem(image, "Duplicate...", "ij.plugin.Duplicator", KeyEvent.VK_D, true);
+ addPlugInItem(image, "Rename...", "ij.plugin.SimpleCommands(\"rename\")", 0, false);
+ addPlugInItem(image, "Scale...", "ij.plugin.Scaler", KeyEvent.VK_E, false);
+ getMenu("Image>Transform", true);
+ getMenu("Image>Zoom", true);
+ getMenu("Image>Overlay", true);
+ image.addSeparator();
+ getMenu("Image>Lookup Tables", true);
+
+ Menu process = getMenu("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, "Find Maxima...", "ij.plugin.filter.MaximumFinder", 0, false);
+ addPlugInItem(process, "Enhance Contrast...", "ij.plugin.ContrastEnhancer", 0, false);
+ getMenu("Process>Noise", true);
+ getMenu("Process>Shadows", true);
+ getMenu("Process>Binary", true);
+ getMenu("Process>Math", true);
+ getMenu("Process>FFT", true);
+ Menu filtersMenu = getMenu("Process>Filters", true);
+ process.addSeparator();
+ getMenu("Process>Batch", true);
+ 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, false);
+
+ Menu analyzeMenu = getMenu("Analyze");
+ addPlugInItem(analyzeMenu, "Measure", "ij.plugin.filter.Analyzer", KeyEvent.VK_M, false);
+ addPlugInItem(analyzeMenu, "Analyze Particles...", "ij.plugin.filter.ParticleAnalyzer", 0, false);
+ addPlugInItem(analyzeMenu, "Summarize", "ij.plugin.filter.Analyzer(\"sum\")", 0, false);
+ addPlugInItem(analyzeMenu, "Distribution...", "ij.plugin.Distribution", 0, false);
+ addPlugInItem(analyzeMenu, "Label", "ij.plugin.filter.Filler(\"label\")", 0, false);
+ addPlugInItem(analyzeMenu, "Clear Results", "ij.plugin.filter.Analyzer(\"clear\")", 0, false);
+ addPlugInItem(analyzeMenu, "Set Measurements...", "ij.plugin.filter.Analyzer(\"set\")", 0, false);
+ analyzeMenu.addSeparator();
+ addPlugInItem(analyzeMenu, "Set Scale...", "ij.plugin.filter.ScaleDialog", 0, false);
+ addPlugInItem(analyzeMenu, "Calibrate...", "ij.plugin.filter.Calibrator", 0, false);
+ if (IJ.isMacOSX()) {
+ addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", 0, false);
+ shortcuts.put(Integer.valueOf(KeyEvent.VK_H),"Histogram");
+ } else
+ addPlugInItem(analyzeMenu, "Histogram", "ij.plugin.Histogram", KeyEvent.VK_H, false);
+ addPlugInItem(analyzeMenu, "Plot Profile", "ij.plugin.Profiler(\"plot\")", KeyEvent.VK_K, false);
+ addPlugInItem(analyzeMenu, "Surface Plot...", "ij.plugin.SurfacePlotter", 0, false);
+ getMenu("Analyze>Gels", true);
+ Menu toolsMenu = getMenu("Analyze>Tools", true);
+
+ // the plugins will be added later, after a separator
+ addPluginsMenu();
+
+ Menu window = getMenu("Window");
+ addPlugInItem(window, "Show All", "ij.plugin.WindowOrganizer(\"show\")", KeyEvent.VK_CLOSE_BRACKET, false);
+ String key = IJ.isWindows()?"enter":"return";
+ addPlugInItem(window, "Main Window ["+key+"]", "ij.plugin.WindowOrganizer(\"imagej\")", 0, false);
+ 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 = getMenu("Help");
+ addPlugInItem(help, "ImageJ Website...", "ij.plugin.BrowserLauncher", 0, false);
+ help.addSeparator();
+ addPlugInItem(help, "Dev. Resources...", "ij.plugin.BrowserLauncher(\""+IJ.URL2+"/developer/index.html\")", 0, false);
+ addPlugInItem(help, "Macro Functions...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/developer/macro/functions.html\")", 0, false);
+ Menu examplesMenu = getExamplesMenu(ij);
+ addPlugInItem(examplesMenu, "Open as Panel", "ij.plugin.SimpleCommands(\"opencp\")", 0, false);
+ help.add(examplesMenu);
+ help.addSeparator();
+ addPlugInItem(help, "Update ImageJ...", "ij.plugin.ImageJ_Updater", 0, false);
+ addPlugInItem(help, "Release Notes...", "ij.plugin.BrowserLauncher(\"https://wsr.imagej.net/notes.html\")", 0, false);
+ addPlugInItem(help, "Refresh Menus", "ij.plugin.ImageJ_Updater(\"menus\")", 0, false);
+ help.addSeparator();
+ Menu aboutMenu = getMenu("Help>About Plugins", true);
+ addPlugInItem(help, "About ImageJ...", "ij.plugin.AboutBox", 0, false);
+
+ if (applet==null) {
+ menuSeparators = new Properties();
+ installPlugins();
+ }
+
+ // make sure "Quit" is the last item in the File menu
+ file.addSeparator();
+ addPlugInItem(file, "Quit", "ij.plugin.Commands(\"quit\")", 0, false);
+
+ //System.out.println("MenuBar.setFont: "+fontSize+" "+scale+" "+getFont());
+ if (fontSize!=0 || scale>1.0)
+ mbar.setFont(getFont());
+ if (ij!=null) {
+ ij.setMenuBar(mbar);
+ Menus.setMenuBarCount++;
+ }
+
+ // Add deleted sample images to commands table
+ pluginsTable.put("Lena (68K)", "ij.plugin.URLOpener(\"lena-std.tif\")");
+ pluginsTable.put("Bridge (174K)", "ij.plugin.URLOpener(\"bridge.gif\")");
+
+ if (pluginError!=null)
+ error = error!=null?error+="\n"+pluginError:pluginError;
+ if (jarError!=null)
+ error = error!=null?error+="\n"+jarError:jarError;
+ return error;
+ }
+
+ public static Menu getExamplesMenu(ActionListener listener) {
+ Menu menu = new Menu("Examples");
+ Menu submenu = new Menu("Plots");
+ addExample(submenu, "Example Plot", "Example_Plot_.ijm");
+ addExample(submenu, "Semi-log Plot", "Semi-log_Plot_.ijm");
+ addExample(submenu, "Arrow Plot", "Arrow_Plot_.ijm");
+ addExample(submenu, "Damped Wave Plot", "Damped_Wave_Plot_.ijm");
+ addExample(submenu, "Dynamic Plot", "Dynamic_Plot_.ijm");
+ addExample(submenu, "Dynamic Plot 2D", "Dynamic_Plot_2D_.ijm");
+ addExample(submenu, "Custom Plot Symbols", "Custom_Plot_Symbols_.ijm");
+ addExample(submenu, "Histograms", "Histograms_.ijm");
+ addExample(submenu, "Bar Charts", "Bar_Charts_.ijm");
+ addExample(submenu, "Shapes", "Plot_Shapes_.ijm");
+ addExample(submenu, "Plot Styles", "Plot_Styles_.ijm");
+ addExample(submenu, "Random Data", "Random_Data_.ijm");
+ addExample(submenu, "Plot Results", "Plot_Results_.ijm");
+ addExample(submenu, "Plot With Spectrum", "Plot_With_Spectrum_.ijm");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+
+ submenu = new Menu("Tools");
+ addExample(submenu, "Annular Selection", "Annular_Selection_Tool.ijm");
+ addExample(submenu, "Big Cursor", "Big_Cursor_Tool.ijm");
+ addExample(submenu, "Circle Tool", "Circle_Tool.ijm");
+ addExample(submenu, "Point Picker", "Point_Picker_Tool.ijm");
+ addExample(submenu, "Star Tool", "Star_Tool.ijm");
+ addExample(submenu, "Animated Icon Tool", "Animated_Icon_Tool.ijm");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+
+ submenu = new Menu("Macro");
+ addExample(submenu, "Sphere", "Sphere.ijm");
+ addExample(submenu, "Dialog Box", "Dialog_Box.ijm");
+ addExample(submenu, "Process Folder", "Batch_Process_Folder.ijm");
+ addExample(submenu, "OpenDialog Demo", "OpenDialog_Demo.ijm");
+ addExample(submenu, "Save All Images", "Save_All_Images.ijm");
+ addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.ijm");
+ addExample(submenu, "Non-numeric Table", "Non-numeric_Table.ijm");
+ addExample(submenu, "Overlay", "Overlay.ijm");
+ addExample(submenu, "Stack Overlay", "Stack_Overlay.ijm");
+ addExample(submenu, "Array Functions", "Array_Functions.ijm");
+ addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.ijm");
+ addExample(submenu, "Grab Viridis Colormap", "Grab_Viridis_Colormap.ijm");
+ addExample(submenu, "Custom Measurement", "Custom_Measurement.ijm");
+ addExample(submenu, "Synthetic Images", "Synthetic_Images.ijm");
+ addExample(submenu, "Spiral Rotation", "Spiral_Rotation.ijm");
+ addExample(submenu, "Curve Fitting", "Curve_Fitting.ijm");
+ addExample(submenu, "Colors of 2021", "Colors_of_2021.ijm");
+ addExample(submenu, "Turtle Graphics", "Turtle_Graphics.ijm");
+ addExample(submenu, "Easter Eggs", "Easter_Eggs.ijm");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+
+ submenu = new Menu("JavaScript");
+ addExample(submenu, "Sphere", "Sphere.js");
+ addExample(submenu, "Plasma Cloud", "Plasma_Cloud.js");
+ addExample(submenu, "Cloud Debugger", "Cloud_Debugger.js");
+ addExample(submenu, "Synthetic Images", "Synthetic_Images.js");
+ addExample(submenu, "Points", "Points.js");
+ addExample(submenu, "Spiral Rotation", "Spiral_Rotation.js");
+ addExample(submenu, "Example Plot", "Example_Plot.js");
+ addExample(submenu, "Semi-log Plot", "Semi-log_Plot.js");
+ addExample(submenu, "Arrow Plot", "Arrow_Plot.js");
+ addExample(submenu, "Dynamic Plot", "Dynamic_Plot.js");
+ addExample(submenu, "Plot Styles", "Plot_Styles.js");
+ addExample(submenu, "Plot Random Data", "Plot_Random_Data.js");
+ addExample(submenu, "Histogram Plots", "Histogram_Plots.js");
+ addExample(submenu, "JPEG Quality Plot", "JPEG_Quality_Plot.js");
+ addExample(submenu, "Process Folder", "Batch_Process_Folder.js");
+ addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.js");
+ addExample(submenu, "Non-numeric Table", "Non-numeric_Table.js");
+ addExample(submenu, "Overlay", "Overlay.js");
+ addExample(submenu, "Stack Overlay", "Stack_Overlay.js");
+ addExample(submenu, "Dual Progress Bars", "Dual_Progress_Bars.js");
+ addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.js");
+ addExample(submenu, "Custom Measurement", "Custom_Measurement.js");
+ addExample(submenu, "Terabyte VirtualStack", "Terabyte_VirtualStack.js");
+ addExample(submenu, "Event Listener", "Event_Listener.js");
+ addExample(submenu, "FFT Filter", "FFT_Filter.js");
+ addExample(submenu, "Curve Fitting", "Curve_Fitting.js");
+ addExample(submenu, "Overlay Text", "Overlay_Text.js");
+ addExample(submenu, "Crop Multiple Rois", "Crop_Multiple_Rois.js");
+ addExample(submenu, "Show all LUTs", "Show_all_LUTs.js");
+ addExample(submenu, "Dialog Demo", "Dialog_Demo.js");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+ submenu = new Menu("BeanShell");
+ addExample(submenu, "Sphere", "Sphere.bsh");
+ addExample(submenu, "Example Plot", "Example_Plot.bsh");
+ addExample(submenu, "Semi-log Plot", "Semi-log_Plot.bsh");
+ addExample(submenu, "Arrow Plot", "Arrow_Plot.bsh");
+ addExample(submenu, "Sine/Cosine Table", "Sine_Cosine_Table.bsh");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+ submenu = new Menu("Python");
+ addExample(submenu, "Sphere", "Sphere.py");
+ addExample(submenu, "Animated Gaussian Blur", "Animated_Gaussian_Blur.py");
+ addExample(submenu, "Spiral Rotation", "Spiral_Rotation.py");
+ addExample(submenu, "Overlay", "Overlay.py");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+ submenu = new Menu("Java");
+ addExample(submenu, "Sphere", "Sphere_.java");
+ addExample(submenu, "Plasma Cloud", "Plasma_Cloud.java");
+ addExample(submenu, "Gamma Adjuster", "Gamma_Adjuster.java");
+ addExample(submenu, "Plugin", "My_Plugin.java");
+ addExample(submenu, "Plugin Filter", "Filter_Plugin.java");
+ addExample(submenu, "Plugin Frame", "Plugin_Frame.java");
+ addExample(submenu, "Plugin Tool", "Prototype_Tool.java");
+ submenu.addActionListener(listener);
+ menu.add(submenu);
+ menu.addSeparator();
+ CheckboxMenuItem item = new CheckboxMenuItem("Autorun Examples");
+ menu.add(item);
+ item.addItemListener(ij);
+ item.setState(Prefs.autoRunExamples);
+ fixFontSize(menu);
+ return menu;
+ }
+
+ private static void addExample(Menu menu, String label, String command) {
+ MenuItem item = new MenuItem(label);
+ menu.add(item);
+ item.setActionCommand(command);
+ fixFontSize(item);
+ }
+
+ void addOpenRecentSubMenu(Menu menu) {
+ openRecentMenu = getMenu("File>Open Recent");
+ for (int i=0; i0)
+ 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);
+ fixFontSize(submenu);
+ return submenu;
+ }
+
+ static void addLuts(Menu submenu) {
+ String path = IJ.getDirectory("luts");
+ if (path==null) return;
+ File f = new File(path);
+ String[] list = null;
+ if (applet==null && f.exists() && f.isDirectory())
+ list = f.list();
+ if (list==null) return;
+ if (IJ.isLinux() || IJ.isMacOSX())
+ Arrays.sort(list);
+ submenu.addSeparator();
+ for (int i=0; i0) {
+ 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);
+ }
+ }
+ if (keyCode>=KeyEvent.VK_F1 && keyCode<=KeyEvent.VK_F12) {
+ shortcuts.put(Integer.valueOf(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') {
+ String submenu = value.substring(2,value.length()-1);
+ //Menu menu = getMenu("Plugins>" + submenu, true);
+ 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() {
+ int nPlugins0 = nPlugins;
+ String value, className;
+ char menuCode;
+ Menu menu;
+ String[] pluginList = getPlugins();
+ String[] pluginsList2 = 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 = getMenu("File>Import"); break;
+ case SAVE_AS_MENU: menu = getMenu("File>Save As"); break;
+ case SHORTCUTS_MENU: menu = shortcutsMenu; break;
+ case ABOUT_MENU: menu = getMenu("Help>About Plugins"); break;
+ case FILTERS_MENU: menu = getMenu("Process>Filters"); break;
+ case TOOLS_MENU: menu = getMenu("Analyze>Tools"); 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 && pluginList!=null) { // does this plugin exist?
+ if (pluginsList2==null)
+ pluginsList2 = getStrippedPlugins(pluginList);
+ for (int i=0; i0)
+ className = className.substring(0, argStart);
+ }
+ skipList.put(className, "");
+ }
+ }
+ if (pluginList!=null) {
+ for (int i=0; i0) {
+ dir = name.substring(0, slashIndex);
+ name = name.substring(slashIndex+1, name.length());
+ menu = getPluginsSubmenu(dir);
+ slashIndex = name.indexOf('/');
+ if (slashIndex>0) {
+ String dir2 = name.substring(0, slashIndex);
+ name = name.substring(slashIndex+1, name.length());
+ String menuName = "Plugins>"+dir+">"+dir2;
+ menu = getMenu(menuName);
+ dir += File.separator+dir2;
+ }
+ }
+ String command = name.replace('_',' ');
+ if (command.endsWith(".js")||command.endsWith(".py"))
+ command = command.substring(0, command.length()-3); //remove ".js" or ".py"
+ else
+ command = command.substring(0, command.length()-4); //remove ".txt", ".ijm" or ".bsh"
+ command = 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++;
+ }
+
+ static int addPluginSeparatorIfNeeded(Menu menu) {
+ if (menuSeparators == null)
+ return 0;
+ Integer i = (Integer)menuSeparators.get(menu);
+ if (i == null) {
+ if (menu.getItemCount() > 0)
+ addSeparator(menu);
+ i = Integer.valueOf(menu.getItemCount());
+ menuSeparators.put(menu, i);
+ }
+ return i.intValue();
+ }
+
+ /** Inserts 'item' into 'menu' in alphanumeric order. */
+ static void addOrdered(Menu menu, MenuItem item) {
+ String label = item.getLabel();
+ int start = addPluginSeparatorIfNeeded(menu);
+ for (int i=start; i=3 && !s.startsWith("#"))
+ entries.add(s);
+ }
+ }
+ catch (IOException e) {}
+ finally {
+ try {if (lnr!=null) lnr.close();}
+ catch (IOException e) {}
+ }
+ for (int j=0; j")) {
+ int firstComma = s.indexOf(',');
+ if (firstComma==-1 || firstComma<=8)
+ menu = null;
+ else {
+ String name = s.substring(8, firstComma);
+ menu = getPluginsSubmenu(name);
+ }
+ } else if (s.startsWith("\"") || s.startsWith("Plugins")) {
+ String name = getSubmenuName(jar);
+ if (name!=null)
+ menu = getPluginsSubmenu(name);
+ else
+ menu = pluginsMenu;
+ addSorted = true;
+ } else {
+ int firstQuote = s.indexOf('"');
+ String name = firstQuote<0 ? s : s.substring(0, firstQuote).trim();
+ int comma = name.indexOf(',');
+ if (comma >= 0)
+ name = name.substring(0, comma);
+ if (name.startsWith("Help>About")) // for backward compatibility
+ name = "Help>About Plugins";
+ menu = getMenu(name);
+ }
+ int firstQuote = s.indexOf('"');
+ if (firstQuote==-1)
+ return;
+ s = s.substring(firstQuote, s.length()); // remove menu
+ if (menu!=null) {
+ addPluginSeparatorIfNeeded(menu);
+ addPluginItem(menu, s);
+ addSorted = false;
+ }
+ String menuEntry = s;
+ if (s.startsWith("\"")) {
+ int quote = s.indexOf('"', 1);
+ menuEntry = quote<0?s.substring(1):s.substring(1, quote);
+ } else {
+ int comma = s.indexOf(',');
+ if (comma > 0)
+ menuEntry = s.substring(0, comma);
+ }
+ if (duplicateCommand) {
+ if (jarError==null) jarError = "";
+ addJarErrorHeading(jar);
+ String jar2 = (String)menuEntry2jarFile.get(menuEntry);
+ if (jar2 != null && jar2.startsWith(pluginsPath))
+ jar2 = jar2.substring(pluginsPath.length());
+ jarError += " Duplicate command: " + s
+ + (jar2 != null ? " (already in " + jar2 + ")"
+ : "") + "\n";
+ } else
+ menuEntry2jarFile.put(menuEntry, jar);
+ duplicateCommand = false;
+ }
+
+ void addJarErrorHeading(String jar) {
+ if (!isJarErrorHeading) {
+ if (!jarError.equals(""))
+ jarError += " \n";
+ jarError += "Plugin configuration error: " + jar + "\n";
+ isJarErrorHeading = true;
+ }
+ }
+
+ /** Returns the specified ImageJ menu (e.g., "File>New") or null if it is not found. */
+ public static Menu getImageJMenu(String menuPath) {
+ if (menus==null && !GraphicsEnvironment.isHeadless())
+ IJ.init();
+ if (menus==null)
+ return null;
+ if (menus.get(menuPath)!=null)
+ return getMenu(menuPath, false);
+ else
+ return null;
+ }
+
+ private static Menu getMenu(String menuPath) {
+ if (GraphicsEnvironment.isHeadless())
+ return null;
+ else
+ return getMenu(menuPath, false);
+ }
+
+ private static Menu getMenu(String menuName, boolean readFromProps) {
+ if (menuName.endsWith(">"))
+ menuName = menuName.substring(0, menuName.length() - 1);
+ Menu result = (Menu)menus.get(menuName);
+ if (result==null) {
+ int offset = menuName.lastIndexOf('>');
+ if (offset < 0) {
+ result = new Menu(menuName);
+ if (mbar == null)
+ mbar = new MenuBar();
+ if (menuName.equals("Help"))
+ mbar.setHelpMenu(result);
+ else
+ mbar.add(result);
+ if (menuName.equals("Window"))
+ window = result;
+ else if (menuName.equals("Plugins"))
+ pluginsMenu = result;
+ } else {
+ String parentName = menuName.substring(0, offset);
+ String menuItemName = menuName.substring(offset + 1);
+ Menu parentMenu = getMenu(parentName);
+ result = new Menu(menuItemName);
+ addPluginSeparatorIfNeeded(parentMenu);
+ if (readFromProps)
+ result = addSubMenu(parentMenu, menuItemName);
+ else if (parentName.startsWith("Plugins") && menuSeparators != null)
+ addItemSorted(parentMenu, result, parentName.equals("Plugins")?userPluginsIndex:0);
+ else
+ parentMenu.add(result);
+ if (menuName.equals("File>Open Recent"))
+ openRecentMenu = result;
+ }
+ menus.put(menuName, result);
+ }
+ //System.out.println("menuName: "+menuName);
+ if (IJ.isWindows() && menuName!=null && menuName.contains(">"))
+ fixFontSize(result);
+ return result;
+ }
+
+ Menu getPluginsSubmenu(String submenuName) {
+ return getMenu("Plugins>" + submenuName);
+ }
+
+ String getSubmenuName(String jarPath) {
+ //IJ.log("getSubmenuName: \n"+jarPath+"\n"+pluginsPath);
+ if (pluginsPath == null)
+ return null;
+ 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;
+ }
+
+ static void addItemSorted(Menu menu, MenuItem item, int startingIndex) {
+ String itemLabel = item.getLabel();
+ int count = menu.getItemCount();
+ boolean inserted = false;
+ for (int i=startingIndex; i0 && name.indexOf("$")==-1
+ && name.indexOf("/_")==-1 && !name.startsWith("_")) {
+ if (Character.isLowerCase(name.charAt(0))&&name.indexOf("/")!=-1)
+ continue;
+ 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");
+ }
+ }
+ jarFile.close();
+ }
+ catch (Throwable e) {
+ IJ.log(jar+": "+e);
+ }
+ 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=0)
+ plugins2[i] = plugins[i].substring(slashPos+1,plugins2[i].length());
+ }
+ return plugins2;
+ }
+
+ void setupPluginsAndMacrosPaths() {
+ ImageJPath = pluginsPath = macrosPath = null;
+ String currentDir = Prefs.getHomeDir(); // "user.dir"
+ if (currentDir==null)
+ return;
+ if (currentDir.endsWith("plugins"))
+ ImageJPath = pluginsPath = currentDir+File.separator;
+ else {
+ String ijDir = Prefs.getPluginsDirProperty();
+ if (ijDir==null)
+ ijDir = currentDir;
+ else if (ijDir.equals("user.home")) {
+ ijDir = System.getProperty("user.home");
+ if (!(new File(ijDir+File.separator+"plugins")).isDirectory())
+ ijDir = ijDir + File.separator + "ImageJ";
+ // needed to run plugins when ImageJ launched using Java WebStart
+ if (applet==null)
+ System.setSecurityManager(null);
+ jnlp = true;
+ }
+ pluginsPath = ijDir+File.separator+"plugins"+File.separator;
+ macrosPath = ijDir+File.separator+"macros"+File.separator;
+ ImageJPath = ijDir+File.separator;
+ }
+ File f = pluginsPath!=null?new File(pluginsPath):null;
+ if (f==null || !f.isDirectory()) {
+ ImageJPath = currentDir+File.separator;
+ pluginsPath = ImageJPath+"plugins"+File.separator;
+ f = new File(pluginsPath);
+ if (!f.isDirectory()) {
+ String altPluginsPath = System.getProperty("plugins.dir");
+ if (altPluginsPath!=null) {
+ f = new File(altPluginsPath);
+ if (!f.isDirectory())
+ altPluginsPath = null;
+ else {
+ ImageJPath = f.getParent() + File.separator;
+ pluginsPath = ImageJPath + f.getName() + File.separator;
+ macrosPath = ImageJPath+"macros"+File.separator;
+ }
+ }
+ if (altPluginsPath==null)
+ ImageJPath = pluginsPath = null;
+ }
+ }
+ f = macrosPath!=null?new File(macrosPath):null;
+ if (f!=null && !f.isDirectory()) {
+ macrosPath = currentDir+File.separator+"macros"+File.separator;
+ f = new File(macrosPath);
+ if (!f.isDirectory())
+ macrosPath = null;
+ }
+ if (IJ.debugMode) {
+ IJ.log("Menus.setupPluginsAndMacrosPaths");
+ IJ.log(" user.dir: "+currentDir);
+ IJ.log(" plugins.dir: "+System.getProperty("plugins.dir"));
+ IJ.log(" ImageJPath: "+ImageJPath);
+ IJ.log(" pluginsPath: "+pluginsPath);
+ }
+ }
+
+ /** Returns a list of the plugins in the plugins menu. */
+ public static synchronized String[] getPlugins() {
+ File f = pluginsPath!=null?new File(pluginsPath):null;
+ if (f==null || (f!=null && !f.isDirectory()))
+ return null;
+ String[] list = f.list();
+ if (list==null)
+ return null;
+ Vector v = new Vector();
+ jarFiles = null;
+ macroFiles = null;
+ for (int i=0; i=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 (validMacroName(name,hasUnderscore)) {
+ 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. */
+ private 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 += "/";
+ int classCount=0, otherCount=0;
+ String className = null;
+ for (int i=0; i=0;
+ if (hasUnderscore && name.endsWith(".class") && name.indexOf('$')<0) {
+ name = name.substring(0, name.length()-6); // remove ".class"
+ v.addElement(dir+name);
+ classCount++;
+ className = name;
+ } else if (hasUnderscore && (name.endsWith(".jar") || name.endsWith(".zip"))) {
+ if (jarFiles==null) jarFiles = new Vector();
+ jarFiles.addElement(f.getPath() + File.separator + name);
+ otherCount++;
+ } else if (validMacroName(name,hasUnderscore)) {
+ if (macroFiles==null) macroFiles = new Vector();
+ macroFiles.addElement(dir + name);
+ otherCount++;
+ } else {
+ File f2 = new File(f, name);
+ if (f2.isDirectory()) installSubdirectorMacros(f2, dir+name);
+ }
+ }
+ if (Prefs.moveToMisc && classCount==1 && otherCount==0 && dir.indexOf("_")==-1)
+ v.setElementAt("Miscellaneous/" + className,
+ v.size() - 1);
+ }
+
+ /** Installs macros and scripts located in subdirectories. */
+ private static void installSubdirectorMacros(File f2, String dir) {
+ if (dir.endsWith("Launchers")) return;
+ String[] list = f2.list();
+ if (list==null) return;
+ for (int i=0; i=0;
+ if (validMacroName(name,hasUnderscore)) {
+ if (macroFiles==null) macroFiles = new Vector();
+ macroFiles.addElement(dir+"/"+name);
+ }
+ }
+ }
+
+ private static boolean validMacroName(String name, boolean hasUnderscore) {
+ return (hasUnderscore&&name.endsWith(".txt")) || name.endsWith(".ijm")
+ || name.endsWith(".js") || name.endsWith(".bsh") || name.endsWith(".py");
+ }
+
+ /** Installs a plugin in the Plugins menu using the class name,
+ with underscores replaced by spaces, as the command. */
+ void installUserPlugin(String className) {
+ installUserPlugin(className, false);
+ }
+
+ public void installUserPlugin(String className, boolean force) {
+ int slashIndex = className.indexOf('/');
+ String menuName = slashIndex < 0 ? "Plugins" : "Plugins>" +
+ className.substring(0, slashIndex).replace('/', '>');
+ Menu menu = getMenu(menuName);
+ String command = className;
+ if (slashIndex>0) {
+ command = className.substring(slashIndex+1);
+ }
+ command = command.replace('_',' ');
+ //command = command.trim();
+ boolean itemExists = (pluginsTable.get(command)!=null);
+ if(force && itemExists)
+ return;
+
+ if (!force && itemExists) // duplicate command?
+ command = command + " Plugin";
+ MenuItem item = new MenuItem(command);
+ if (force)
+ addItemSorted(menu,item,0);
+ else
+ addOrdered(menu, 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 || scale>1.0)
+ popup.setFont(getCachedFont());
+ 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;
+ }
+
+ public static Menu getOpenRecentMenu() {
+ return openRecentMenu;
+ }
+
+ public int getMacroCount() {
+ return nMacros;
+ }
+
+ public int getPluginCount() {
+ return nPlugins;
+ }
+
+ static final int RGB_STACK=10, HSB_STACK=11, LAB_STACK=12, HSB32_STACK=13;
+
+ /** 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);
+ LabStackItem.setState(false);
+ HSB32Item.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;
+ else if (stack.isLab())
+ type = LAB_STACK;
+ else if (stack.isHSB32())
+ type = HSB32_STACK;
+ }
+ 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;
+ case LAB_STACK:
+ LabStackItem.setState(true);
+ break;
+ case HSB32_STACK:
+ HSB32Item.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=2)
+ index--;
+ window.insert(item, index);
+ windowMenuItems2++;
+ if (windowMenuItems2==1) {
+ window.insertSeparator(WINDOW_MENU_ITEMS+windowMenuItems2);
+ windowMenuItems2++;
+ }
+ }
+
+ /** Adds one image to the end of the Window menu. */
+ static synchronized void addWindowMenuItem(ImagePlus imp) {
+ if (ij==null)
+ return;
+ String name = imp.getTitle();
+ String size = ImageWindow.getImageSize(imp);
+ CheckboxMenuItem item = new CheckboxMenuItem(name+" "+size);
+ item.setActionCommand("" + imp.getID());
+ window.add(item);
+ fixFontSize(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;
+ try {
+ if (index>=0 && index-1)
+ label = label.substring(0, index);
+ }
+ if (item!=null && label.equals(oldLabel) && (imp==null||(""+imp.getID()).equals(cmd))) {
+ String size = "";
+ if (imp!=null)
+ size = " " + ImageWindow.getImageSize(imp);
+ item.setLabel(newLabel+size);
+ return;
+ }
+ }
+ } catch (Exception 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();
+ for (int i=0; iImport"); break;
+ case SAVE_AS_MENU: menu = getMenu("File>Save As"); break;
+ case SHORTCUTS_MENU: menu = shortcutsMenu; break;
+ case ABOUT_MENU: menu = getMenu("Help>About Plugins"); break;
+ case FILTERS_MENU: menu = getMenu("Process>Filters"); break;
+ case TOOLS_MENU: menu = getMenu("Analyze>Tools"); 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(Integer.valueOf(code),command);
+ item = new MenuItem(command);
+ } else {
+ shortcuts.put(Integer.valueOf(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+"]":"";
+ pluginsPrefs.addElement(menuCode+",\""+command+shortcut+"\","+plugin);
+ return NORMAL_RETURN;
+ }
+
+ /** Deletes a command installed by Plugins/Shortcuts/Add Shortcut. */
+ public static int uninstallPlugin(String command) {
+ boolean found = false;
+ for (Enumeration en=pluginsPrefs.elements(); en.hasMoreElements();) {
+ String cmd = (String)en.nextElement();
+ if (cmd.contains(command)) {
+ boolean ok = 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;
+ return code;
+ }
+
+ void installStartupMacroSet() {
+ if (macrosPath==null) {
+ MacroInstaller.installFromJar("/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;
+ }
+ } else {
+ if ("StartupMacros.fiji.ijm".equals(f.getName()))
+ path = f.getPath();
+ }
+ String libraryPath = macrosPath + "Library.txt";
+ f = new File(libraryPath);
+ boolean isLibrary = f.exists();
+ try {
+ MacroInstaller mi = new MacroInstaller();
+ if (isLibrary) mi.installLibrary(libraryPath);
+ mi.installStartupMacros(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;
+ }
+
+ /** Returns 'true' if this keyboard shortcut is in use. */
+ public static boolean shortcutInUse(String shortcut) {
+ int code = convertShortcutToCode(shortcut);
+ if (shortcuts.get(Integer.valueOf(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 fontSize;
+ }
+
+ public static Font getFont() {
+ return getFont(true);
+ }
+
+ public static Font getFont(boolean checkSize) {
+ int size = fontSize==0?13:fontSize;
+ if (size<7)
+ size = 7;
+ if (scale>1.0 && !checkSize)
+ size = 13;
+ int size0 = size;
+ size = (int)Math.round(size*scale);
+ //if (cachedFont==null) System.out.println("getFont: "+size0+" "+size+" "+fontSize+" "+scale+" "+checkSize);
+ if (checkSize && IJ.isWindows() && size>17)
+ size = 17; // On Windows, the menu bar font size is set 12 if you set it to >17
+ Font menuFont = new Font("SanSerif", Font.PLAIN, size);
+ return menuFont;
+ }
+
+ public static Font getCachedFont() {
+ if (cachedFont==null)
+ cachedFont = getFont(false);
+ return cachedFont;
+ }
+
+ /** Called once when ImageJ quits. */
+ public static void savePreferences(Properties prefs) {
+ if (pluginsPrefs==null)
+ return;
+ 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");
+ if (index==-1 || index==menuPath.length()-1)
+ return;
+ String label = menuPath.substring(index+1, menuPath.length());
+ menuPath = menuPath.substring(0, index);
+ pluginsTable.put(label, plugin);
+ addItem(getMenu(menuPath), label, 0, false);
+ }
+
+ /** Work around Windows bug that limits menu bar sub-menu to 17 points. */
+ private static void fixFontSize(MenuItem item) {
+ if (IJ.isWindows() && item!=null)
+ item.setFont(getCachedFont());
+ }
+
+}
diff --git a/mrj/26/ij/Prefs.java b/mrj/26/ij/Prefs.java
new file mode 100644
index 00000000..ba6ee38b
--- /dev/null
+++ b/mrj/26/ij/Prefs.java
@@ -0,0 +1,833 @@
+package ij;
+import ij.stub.Applet;
+import ij.util.Java2;
+import java.io.*;
+import java.util.*;
+import java.net.URL;
+import java.awt.*;
+import ij.io.*;
+import ij.util.Tools;
+import ij.gui.*;
+import ij.plugin.filter.*;
+import ij.process.ImageConverter;
+import ij.plugin.Animator;
+import ij.process.FloatBlitter;
+import ij.plugin.GelAnalyzer;
+import ij.process.ColorProcessor;
+import ij.text.TextWindow;
+
+/**
+This class contains the ImageJ preferences, which are
+loaded from the "IJ_Props.txt" and "IJ_Prefs.txt" files.
+@see ImageJ
+*/
+public class Prefs {
+
+ public static final String PROPS_NAME = "IJ_Props.txt";
+ public static final String PREFS_NAME = "IJ_Prefs.txt";
+ public static final String DIR_IMAGE = "dir.image";
+ public static final String FCOLOR = "fcolor";
+ public static final String BCOLOR = "bcolor";
+ public static final String ROICOLOR = "roicolor";
+ public static final String SHOW_ALL_COLOR = "showcolor";
+ public static final String JPEG = "jpeg";
+ public static final String FPS = "fps";
+ public static final String DIV_BY_ZERO_VALUE = "div-by-zero";
+ public static final String NOISE_SD = "noise.sd";
+ public static final String MENU_SIZE = "menu.size";
+ public static final String GUI_SCALE = "gui.scale";
+ public static final String THREADS = "threads";
+ public static final String KEY_PREFIX = ".";
+
+ private static final int USE_POINTER=1<<0, ANTIALIASING=1<<1, INTERPOLATE=1<<2, ONE_HUNDRED_PERCENT=1<<3,
+ BLACK_BACKGROUND=1<<4, JFILE_CHOOSER=1<<5, UNUSED=1<<6, BLACK_CANVAS=1<<7, WEIGHTED=1<<8,
+ AUTO_MEASURE=1<<9, REQUIRE_CONTROL=1<<10, USE_INVERTING_LUT=1<<11, ANTIALIASED_TOOLS=1<<12,
+ INTEL_BYTE_ORDER=1<<13, DOUBLE_BUFFER=1<<14, NO_POINT_LABELS=1<<15, NO_BORDER=1<<16,
+ SHOW_ALL_SLICE_ONLY=1<<17, COPY_HEADERS=1<<18, NO_ROW_NUMBERS=1<<19,
+ MOVE_TO_MISC=1<<20, ADD_TO_MANAGER=1<<21, RUN_SOCKET_LISTENER=1<<22,
+ MULTI_POINT_MODE=1<<23, ROTATE_YZ=1<<24, FLIP_XZ=1<<25,
+ DONT_SAVE_HEADERS=1<<26, DONT_SAVE_ROW_NUMBERS=1<<27, NO_CLICK_TO_GC=1<<28,
+ AVOID_RESLICE_INTERPOLATION=1<<29, KEEP_UNDO_BUFFERS=1<<30;
+ public static final String OPTIONS = "prefs.options";
+
+ public static final String vistaHint = ""; // no longer used
+
+ private static final int USE_SYSTEM_PROXIES=1<<0, USE_FILE_CHOOSER=1<<1,
+ SUBPIXEL_RESOLUTION=1<<2, ENHANCED_LINE_TOOL=1<<3, SKIP_RAW_DIALOG=1<<4,
+ REVERSE_NEXT_PREVIOUS_ORDER=1<<5, AUTO_RUN_EXAMPLES=1<<6, SHOW_ALL_POINTS=1<<7,
+ DO_NOT_SAVE_WINDOW_LOCS=1<<8, JFILE_CHOOSER_CHANGED=1<<9,
+ CANCEL_BUTTON_ON_RIGHT=1<<10, IGNORE_RESCALE_SLOPE=1<<11,
+ NON_BLOCKING_DIALOGS=1<<12, FIXED_DICOM_SCALING=1<<13,
+ CALIBRATE_CONVERSIONS=1<<14;
+ public static final String OPTIONS2 = "prefs.options2";
+
+ /** file.separator system property */
+ public static String separator = System.getProperty("file.separator");
+ /** Use pointer cursor instead of cross */
+ public static boolean usePointerCursor;
+ /** No longer used */
+ public static boolean antialiasedText;
+ /** Display images scaled <100% using bilinear interpolation */
+ public static boolean interpolateScaledImages;
+ /** Open images at 100% magnification*/
+ public static boolean open100Percent;
+ /** Backgound is black in binary images*/
+ public static boolean blackBackground;
+ /** Use JFileChooser instead of FileDialog to open and save files. */
+ public static boolean useJFileChooser;
+ /** Color to grayscale conversion is weighted (0.299, 0.587, 0.114) if the variable is true. */
+ public static boolean weightedColor;
+ /** Use black image border. */
+ public static boolean blackCanvas;
+ /** Point tool auto-measure mode. */
+ public static boolean pointAutoMeasure;
+ /** Point tool auto-next slice mode (not saved in IJ_Prefs). */
+ public static boolean pointAutoNextSlice;
+ /** Require control or command key for keybaord shortcuts. */
+ public static boolean requireControlKey;
+ /** Open 8-bit images with inverting LUT so 0 is white and 255 is black. */
+ public static boolean useInvertingLut;
+ /** Draw tool icons using antialiasing (always true). */
+ public static boolean antialiasedTools = true;
+ /** Export TIFF and Raw using little-endian byte order. */
+ public static boolean intelByteOrder = true;
+ /** No longer used */
+ public static boolean doubleBuffer = true;
+ /** Do not label multiple points created using point tool. */
+ public static boolean noPointLabels;
+ /** Disable Edit/Undo command. */
+ public static boolean disableUndo;
+ /** Do not draw black border around image. */
+ public static boolean noBorder;
+ /** Only show ROIs associated with current slice in Roi Manager "Show All" mode. */
+ public static boolean showAllSliceOnly = true;
+ /** Include column headers when copying tables to clipboard. */
+ public static boolean copyColumnHeaders;
+ /** Do not include row numbers when copying tables to clipboard. */
+ public static boolean noRowNumbers;
+ /** Move isolated plugins to Miscellaneous submenu. */
+ public static boolean moveToMisc;
+ /** Add points to ROI Manager. */
+ public static boolean pointAddToManager;
+ /** Add points to overlay. */
+ public static boolean pointAddToOverlay;
+ /** Extend the borders to foreground for binary erosions and closings. */
+ public static boolean padEdges;
+ /** Run the SocketListener. */
+ public static boolean runSocketListener;
+ /** Use MultiPoint tool. */
+ public static boolean multiPointMode;
+ /** Open DICOMs as 32-bit float images */
+ public static boolean openDicomsAsFloat;
+ /** Ignore Rescale Slope when opening DICOMs */
+ public static boolean ignoreRescaleSlope;
+ /** Assume DICOM volumes use identical RescaleSlope and RescaleIntercept across all slices */
+ public static boolean fixedDicomScaling;
+ /** Plot rectangular selectons vertically */
+ public static boolean verticalProfile;
+ /** Rotate YZ orthogonal views 90 degrees */
+ public static boolean rotateYZ;
+ /** Rotate XZ orthogonal views 180 degrees */
+ public static boolean flipXZ;
+ /** Don't save Results table column headers */
+ public static boolean dontSaveHeaders;
+ /** Don't save Results table row numbers */
+ public static boolean dontSaveRowNumbers;
+ /** Don't run garbage collector when user clicks in status bar */
+ public static boolean noClickToGC;
+ /** Angle tool measures reflex angle */
+ public static boolean reflexAngle;
+ /** Avoid interpolation when re-slicing */
+ public static boolean avoidResliceInterpolation;
+ /** Preserve undo (snapshot) buffers when switching images */
+ public static boolean keepUndoBuffers;
+ /** Use ROI names as "show all" labels in the ROI Manager */
+ public static boolean useNamesAsLabels;
+ /** Set the "java.net.useSystemProxies" property */
+ public static boolean useSystemProxies;
+ /** Use the file chooser to import and export image sequences on Windows and Linux*/
+ public static boolean useFileChooser;
+ /** Use sub-pixel resolution with line selections */
+ public static boolean subPixelResolution;
+ /** Adjust contrast when scrolling stacks */
+ public static boolean autoContrast;
+ /** Allow lines to be created with one click at start and another at the end */
+ public static boolean enhancedLineTool;
+ /** Keep arrow selection after adding to overlay */
+ public static boolean keepArrowSelections;
+ /** Aways paint images using double buffering */
+ public static boolean paintDoubleBuffered;
+ /** Do not display dialog when opening .raw files */
+ public static boolean skipRawDialog;
+ /** Reverse channel-slice-frame priority used by Next Slice and Previous Slice commands. */
+ public static boolean reverseNextPreviousOrder;
+ /** Automatically run examples in Help/Examples menu. */
+ public static boolean autoRunExamples = true;
+ /** Ignore stack positions when displaying points. */
+ public static boolean showAllPoints;
+ /** Show ImageJ menu bar on image window activation on Macs. */
+ public static boolean setIJMenuBar = IJ.isMacOSX();
+ /** "ImageJ" window is always on top. */
+ public static boolean alwaysOnTop;
+ /** Automatically spline fit line selections */
+ public static boolean splineFitLines;
+ /** Enable this option to workaround a bug with some Linux window
+ managers that causes windows to wander down the screen. */
+ public static boolean doNotSaveWindowLocations;
+ /** Use JFileChooser setting changed/ */
+ public static boolean jFileChooserSettingChanged;
+ /** Convert tiff units to microns if pixel width is less than 0.0001 cm. */
+ public static boolean convertToMicrons = true;
+ /** Wand tool "Smooth if thresholded" option */
+ public static boolean smoothWand;
+ /** "Close All" command running */
+ public static boolean closingAll;
+ /** Dialog "Cancel" button is on right on Linux */
+ public static boolean dialogCancelButtonOnRight;
+ /** Support TRANSFORM Undo in macros */
+ public static boolean supportMacroUndo;
+ /** Use NonBlockingGenericDialogs in filters */
+ public static boolean nonBlockingFilterDialogs;
+ /** Turn live display on plots automatically */
+ public static boolean autoLivePlots;
+ /** Use full range for 16-bit inversions */
+ public static boolean fullRange16bitInversions;
+ /** Calibrate image type conversions */
+ public static boolean calibrateConversions;
+ /** Open grayscale RGB JPEGs as RGB */
+ public static boolean openGrayscaleJpegsAsRGB;
+ /** Scroll stacks using mouse wheel */
+ public static boolean mouseWheelStackScrolling = true;
+
+ //Save location of moved image windows */
+ //public static boolean saveImageLocation = true;
+
+ static boolean commandLineMacro;
+ static Properties ijPrefs = new Properties();
+ static Properties props = new Properties(ijPrefs);
+ static String prefsDir;
+ static String imagesURL;
+ static String ImageJDir;
+ static String pluginsDirProperty;
+ static int threads;
+ static int transparentIndex = -1;
+ private static boolean resetPreferences;
+ private static double guiScale = 1.0;
+ private static Properties locKeys = new Properties();
+ private static String propertiesPath; // location of custom IJ_Props.txt
+ private static String preferencesPath; // location of custom IJ_Prefs.txt
+
+ /** Saves the value of the string text in the preferences
+ * file using the keyword key. The string can be
+ * retrieved using the appropriate get() method.
+ * @see #get(String,String)
+ */
+ public static void set(String key, String text) {
+ if (key.indexOf('.')<1)
+ throw new IllegalArgumentException("Key must have a prefix");
+ if (text==null)
+ ijPrefs.remove(KEY_PREFIX+key);
+ else
+ ijPrefs.put(KEY_PREFIX+key, text);
+ }
+
+ /** Saves the value of the integer value in the preferences
+ * file using the keyword key. The value can be
+ * retrieved using the appropriate get() method.
+ * @see #get(String,double)
+ */
+ public static void set(String key, int value) {
+ set(key, Integer.toString(value));
+ }
+
+ /** Saves the value of the double value in the preferences
+ * file using the keyword key. The value can be
+ * retrieved using the appropriate get() method.
+ * @see #get(String,double)
+ */
+ public static void set(String key, double value) {
+ set(key, ""+value);
+ }
+
+ /** Saves the value of the boolean value in the preferences
+ * file using the keyword key. The value can be
+ * retrieved using the appropriate get() method.
+ * @see #get(String,boolean)
+ */
+ public static void set(String key, boolean value) {
+ set(key, ""+value);
+ }
+
+ /** Uses the keyword key to retrieve a string from the
+ preferences file. Returns defaultValue if the key
+ is not found. */
+ public static String get(String key, String defaultValue) {
+ String value = ijPrefs.getProperty(KEY_PREFIX+key);
+ if (value == null)
+ return defaultValue;
+ else
+ return value;
+ }
+
+ /** Uses the keyword key to retrieve a number from the
+ preferences file. Returns defaultValue if the key
+ is not found. */
+ public static double get(String key, double defaultValue) {
+ String s = ijPrefs.getProperty(KEY_PREFIX+key);
+ Double d = null;
+ if (s!=null) {
+ try {d = Double.valueOf(s);}
+ catch (NumberFormatException e) {d = null;}
+ if (d!=null)
+ return(d.doubleValue());
+ }
+ return defaultValue;
+ }
+
+ /** Uses the keyword key to retrieve a boolean from
+ the preferences file. Returns defaultValue if
+ the key is not found. */
+ public static boolean get(String key, boolean defaultValue) {
+ String value = ijPrefs.getProperty(KEY_PREFIX+key);
+ if (value==null)
+ return defaultValue;
+ else
+ return value.equals("true");
+ }
+
+ /**
+ * Finds and loads the configuration file ("IJ_Props.txt")
+ * and the preferences file ("IJ_Prefs.txt").
+ *
+ * @param ij
+ * @return an error message if "IJ_Props.txt" not found.
+ */
+ public static String load(Object ij) {
+ return load(ij, null);
+ }
+
+ /** Finds and loads the configuration file ("IJ_Props.txt")
+ * and the preferences file ("IJ_Prefs.txt").
+ * @return an error message if "IJ_Props.txt" not found.
+ */
+ @Deprecated(since = "IJ XX; Java 26")
+ public static String load(Object ij, Applet applet) {
+ if (ImageJDir==null)
+ ImageJDir = System.getProperty("user.dir");
+ if (ij!=null) {
+ InputStream f = null;
+ try { // Look for IJ_Props.txt in ImageJ folder
+ f = new FileInputStream(ImageJDir+"/"+PROPS_NAME);
+ propertiesPath = ImageJDir+"/"+PROPS_NAME;
+ } catch (FileNotFoundException e) {
+ f = null;
+ }
+ if (f==null) {
+ // Look in ij.jar if not found in ImageJ folder
+ f = ij.getClass().getResourceAsStream("/"+PROPS_NAME);
+ }
+ if (applet!=null)
+ return loadAppletProps(f, applet);
+ if (f==null)
+ return PROPS_NAME+" not found in ij.jar or in "+ImageJDir;
+ f = new BufferedInputStream(f);
+ try {
+ props.load(f);
+ f.close();
+ } catch (IOException e) {
+ return("Error loading "+PROPS_NAME);
+ }
+ imagesURL = props.getProperty(IJ.isJava18()?"images.location":"images.location2");
+ }
+ loadPreferences();
+ loadOptions();
+ guiScale = get(GUI_SCALE, 1.0);
+ return null;
+ }
+
+ /*
+ static void dumpPrefs() {
+ System.out.println("");
+ Enumeration e = ijPrefs.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ System.out.println(key+": "+ijPrefs.getProperty(key));
+ }
+ }
+ */
+
+ @Deprecated(since = "IJ XX; Java 26")
+ static String loadAppletProps(InputStream f, Applet applet) {
+ if (f==null)
+ return PROPS_NAME+" not found in ij.jar";
+ try {
+ props.load(f);
+ f.close();
+ }
+ catch (IOException e) {return("Error loading "+PROPS_NAME);}
+ try {
+ URL url = new URL(applet.getDocumentBase(), "images/");
+ imagesURL = url.toString();
+ }
+ catch (Exception e) {}
+ return null;
+ }
+
+ /** Returns the URL of the directory that contains the ImageJ sample images. */
+ public static String getImagesURL() {
+ return imagesURL;
+ }
+
+ /** Sets the URL of the directory that contains the ImageJ sample images. */
+ public static void setImagesURL(String url) {
+ imagesURL = url;
+ }
+
+ /** Obsolete, replaced by getImageJDir(), which, unlike this method,
+ returns a path that ends with File.separator. */
+ public static String getHomeDir() {
+ return ImageJDir;
+ }
+
+ /** Returns the path, ending in File.separator, to the ImageJ directory. */
+ public static String getImageJDir() {
+ String path = Menus.getImageJPath();
+ if (path==null) {
+ String ijPath = ImageJDir;
+ if (ijPath==null)
+ ijPath = getPluginsDirProperty();
+ if (ijPath==null)
+ ijPath = System.getProperty("user.dir");
+ return ijPath + File.separator;
+ } else
+ return path;
+ }
+
+ public static String getPluginsDirProperty() {
+ if (pluginsDirProperty==null) {
+ String ijDir = System.getProperty("plugins.dir");
+ if (ijDir!=null) {
+ if (ijDir.endsWith("/")||ijDir.endsWith("\\"))
+ ijDir = ijDir.substring(0, ijDir.length()-1);
+ if (ijDir.endsWith("/plugins")||ijDir.endsWith("\\plugins"))
+ ijDir = ijDir.substring(0, ijDir.length()-8);
+ pluginsDirProperty = ijDir;
+ } else
+ pluginsDirProperty = "";
+ }
+ return pluginsDirProperty.length()>0?pluginsDirProperty:null;
+ }
+
+ /** Returns the path to the directory where the
+ preferences file (IJPrefs.txt) is saved. */
+ public static String getPrefsDir() {
+ // look in current directory
+ if (prefsDir==null) {
+ String cwd = System.getProperty("user.dir");
+ File f = new File(cwd+File.separator+PREFS_NAME);
+ if (f.exists()) {
+ prefsDir = cwd;
+ preferencesPath = cwd+"/"+PREFS_NAME;
+ }
+ // look in ImageJ directory
+ if (prefsDir==null) {
+ String ijDir = getImageJDir();
+ ijDir = ijDir.substring(0, ijDir.length()-1);
+ f = new File(ijDir+File.separator+PREFS_NAME);
+ if (f.exists()) {
+ prefsDir = ijDir;
+ preferencesPath = ijDir+"/"+PREFS_NAME;
+ }
+ }
+ // use home directory
+ if (prefsDir==null) {
+ String dir = System.getProperty("user.home");
+ if (IJ.isMacOSX())
+ dir += "/Library/Preferences";
+ else
+ dir += File.separator+".imagej";
+ prefsDir = dir;
+ }
+ }
+ return prefsDir;
+ }
+
+ /** Sets the path to the ImageJ directory. */
+ static void setHomeDir(String path) {
+ if (path.endsWith(File.separator) || path.endsWith("/"))
+ path = path.substring(0, path.length()-1);
+ ImageJDir = path;
+ }
+
+ /** Returns the default directory, if any, or null. */
+ public static String getDefaultDirectory() {
+ if (commandLineMacro)
+ return null;
+ else
+ return getString(DIR_IMAGE);
+ }
+
+ /** Returns the file.separator system property. */
+ public static String getFileSeparator() {
+ return separator;
+ }
+
+ /** Opens the ImageJ preferences file ("IJ_Prefs.txt") file. */
+ static void loadPreferences() {
+ String path = getPrefsDir()+separator+PREFS_NAME;
+ boolean ok = loadPrefs(path);
+ if (!ok) { // not found
+ if (IJ.isWindows())
+ path = ImageJDir +separator+PREFS_NAME;
+ else
+ path = System.getProperty("user.home")+separator+PREFS_NAME; //User's home dir
+ ok = loadPrefs(path);
+ if (ok)
+ new File(path).delete();
+ }
+
+ }
+
+ static boolean loadPrefs(String path) {
+ try {
+ InputStream is = new BufferedInputStream(new FileInputStream(path));
+ ijPrefs.load(is);
+ is.close();
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /** Saves user preferences in the IJ_Prefs.txt properties file. */
+ public static void savePreferences() {
+ String path = null;
+ commandLineMacro = false;
+ try {
+ Properties prefs = new Properties();
+ String dir = OpenDialog.getDefaultDirectory();
+ if (dir!=null)
+ prefs.put(DIR_IMAGE, dir);
+ prefs.put(ROICOLOR, Tools.c2hex(Roi.getColor()));
+ prefs.put(SHOW_ALL_COLOR, Tools.c2hex(ImageCanvas.getShowAllColor()));
+ prefs.put(FCOLOR, Tools.c2hex(Toolbar.getForegroundColor()));
+ prefs.put(BCOLOR, Tools.c2hex(Toolbar.getBackgroundColor()));
+ prefs.put(JPEG, Integer.toString(FileSaver.getJpegQuality()));
+ prefs.put(FPS, Double.toString(Animator.getFrameRate()));
+ prefs.put(DIV_BY_ZERO_VALUE, Double.toString(FloatBlitter.divideByZeroValue));
+ prefs.put(NOISE_SD, Double.toString(Filters.getSD()));
+ if (threads>1) prefs.put(THREADS, Integer.toString(threads));
+ if (IJ.isMacOSX()) useJFileChooser = false;
+ if (!IJ.isLinux()) dialogCancelButtonOnRight = false;
+ saveOptions(prefs);
+ savePluginPrefs(prefs);
+ ImageJ ij = IJ.getInstance();
+ if (ij!=null)
+ ij.savePreferences(prefs);
+ Menus.savePreferences(prefs);
+ ParticleAnalyzer.savePreferences(prefs);
+ Analyzer.savePreferences(prefs);
+ ImportDialog.savePreferences(prefs);
+ PlotWindow.savePreferences(prefs);
+ NewImage.savePreferences(prefs);
+ String prefsDir = getPrefsDir();
+ path = prefsDir+separator+PREFS_NAME;
+ if (prefsDir.endsWith(".imagej")) {
+ File f = new File(prefsDir);
+ if (!f.exists()) f.mkdir(); // create .imagej directory
+ }
+ if (resetPreferences) {
+ File f = new File(path);
+ if (!f.exists())
+ IJ.error("Edit>Options>Reset", "Unable to reset preferences. File not found at\n"+path);
+ boolean rtn = f.delete();
+ resetPreferences = false;
+ } else
+ savePrefs(prefs, path);
+ } catch (Throwable t) {
+ String msg = t.getMessage();
+ if (msg==null) msg = ""+t;
+ int delay = 4000;
+ try {
+ new TextWindow("Error Saving Preferences:\n"+path, msg, 500, 200);
+ IJ.wait(delay);
+ } catch (Throwable t2) {}
+ }
+ }
+
+ /** Delete the preferences file when ImageJ quits. */
+ public static void resetPreferences() {
+ resetPreferences = true;
+ }
+
+ static void loadOptions() {
+ int defaultOptions = ANTIALIASING+AVOID_RESLICE_INTERPOLATION+ANTIALIASED_TOOLS+MULTI_POINT_MODE
+ +(!IJ.isMacOSX()?RUN_SOCKET_LISTENER:0)+BLACK_BACKGROUND;
+ int options = getInt(OPTIONS, defaultOptions);
+ usePointerCursor = (options&USE_POINTER)!=0;
+ //antialiasedText = (options&ANTIALIASING)!=0;
+ antialiasedText = false;
+ interpolateScaledImages = (options&INTERPOLATE)!=0;
+ open100Percent = (options&ONE_HUNDRED_PERCENT)!=0;
+ blackBackground = (options&BLACK_BACKGROUND)!=0;
+ useJFileChooser = (options&JFILE_CHOOSER)!=0;
+ weightedColor = (options&WEIGHTED)!=0;
+ if (weightedColor)
+ ColorProcessor.setWeightingFactors(0.299, 0.587, 0.114);
+ blackCanvas = (options&BLACK_CANVAS)!=0;
+ requireControlKey = (options&REQUIRE_CONTROL)!=0;
+ useInvertingLut = (options&USE_INVERTING_LUT)!=0;
+ intelByteOrder = (options&INTEL_BYTE_ORDER)!=0;
+ noBorder = (options&NO_BORDER)!=0;
+ //showAllSliceOnly = (options&SHOW_ALL_SLICE_ONLY)!=0;
+ copyColumnHeaders = (options©_HEADERS)!=0;
+ noRowNumbers = (options&NO_ROW_NUMBERS)!=0;
+ moveToMisc = (options&MOVE_TO_MISC)!=0;
+ runSocketListener = (options&RUN_SOCKET_LISTENER)!=0;
+ multiPointMode = (options&MULTI_POINT_MODE)!=0;
+ rotateYZ = (options&ROTATE_YZ)!=0;
+ flipXZ = (options&FLIP_XZ)!=0;
+ //dontSaveHeaders = (options&DONT_SAVE_HEADERS)!=0;
+ //dontSaveRowNumbers = (options&DONT_SAVE_ROW_NUMBERS)!=0;
+ noClickToGC = (options&NO_CLICK_TO_GC)!=0;
+ avoidResliceInterpolation = (options&AVOID_RESLICE_INTERPOLATION)!=0;
+ keepUndoBuffers = (options&KEEP_UNDO_BUFFERS)!=0;
+
+ defaultOptions = (!IJ.isMacOSX()?USE_FILE_CHOOSER:0);
+ int options2 = getInt(OPTIONS2, defaultOptions);
+ useSystemProxies = (options2&USE_SYSTEM_PROXIES)!=0;
+ useFileChooser = (options2&USE_FILE_CHOOSER)!=0;
+ subPixelResolution = (options2&SUBPIXEL_RESOLUTION)!=0;
+ enhancedLineTool = (options2&ENHANCED_LINE_TOOL)!=0;
+ skipRawDialog = (options2&SKIP_RAW_DIALOG)!=0;
+ reverseNextPreviousOrder = (options2&REVERSE_NEXT_PREVIOUS_ORDER)!=0;
+ autoRunExamples = (options2&AUTO_RUN_EXAMPLES)!=0;
+ showAllPoints = (options2&SHOW_ALL_POINTS)!=0;
+ doNotSaveWindowLocations = (options2&DO_NOT_SAVE_WINDOW_LOCS)!=0;
+ jFileChooserSettingChanged = (options2&JFILE_CHOOSER_CHANGED)!=0;
+ dialogCancelButtonOnRight = (options2&CANCEL_BUTTON_ON_RIGHT)!=0;
+ ignoreRescaleSlope = (options2&IGNORE_RESCALE_SLOPE)!=0;
+ nonBlockingFilterDialogs = (options2&NON_BLOCKING_DIALOGS)!=0;
+ fixedDicomScaling = (options2&FIXED_DICOM_SCALING)!=0;
+ //calibrateConversions = (options2&CALIBRATE_CONVERSIONS)!=0;
+ }
+
+ static void saveOptions(Properties prefs) {
+ int options = (usePointerCursor?USE_POINTER:0) + (antialiasedText?ANTIALIASING:0)
+ + (interpolateScaledImages?INTERPOLATE:0) + (open100Percent?ONE_HUNDRED_PERCENT:0)
+ + (blackBackground?BLACK_BACKGROUND:0) + (useJFileChooser?JFILE_CHOOSER:0)
+ + (blackCanvas?BLACK_CANVAS:0) + (weightedColor?WEIGHTED:0)
+ + (requireControlKey?REQUIRE_CONTROL:0)
+ + (useInvertingLut?USE_INVERTING_LUT:0)
+ + (intelByteOrder?INTEL_BYTE_ORDER:0) + (doubleBuffer?DOUBLE_BUFFER:0)
+ + (noPointLabels?NO_POINT_LABELS:0) + (noBorder?NO_BORDER:0)
+ + (showAllSliceOnly?SHOW_ALL_SLICE_ONLY:0) + (copyColumnHeaders?COPY_HEADERS:0)
+ + (noRowNumbers?NO_ROW_NUMBERS:0) + (moveToMisc?MOVE_TO_MISC:0)
+ + (runSocketListener?RUN_SOCKET_LISTENER:0)
+ + (multiPointMode?MULTI_POINT_MODE:0) + (rotateYZ?ROTATE_YZ:0)
+ + (flipXZ?FLIP_XZ:0) + (dontSaveHeaders?DONT_SAVE_HEADERS:0)
+ + (dontSaveRowNumbers?DONT_SAVE_ROW_NUMBERS:0) + (noClickToGC?NO_CLICK_TO_GC:0)
+ + (avoidResliceInterpolation?AVOID_RESLICE_INTERPOLATION:0)
+ + (keepUndoBuffers?KEEP_UNDO_BUFFERS:0);
+ prefs.put(OPTIONS, Integer.toString(options));
+
+ int options2 = (useSystemProxies?USE_SYSTEM_PROXIES:0)
+ + (useFileChooser?USE_FILE_CHOOSER:0) + (subPixelResolution?SUBPIXEL_RESOLUTION:0)
+ + (enhancedLineTool?ENHANCED_LINE_TOOL:0) + (skipRawDialog?SKIP_RAW_DIALOG:0)
+ + (reverseNextPreviousOrder?REVERSE_NEXT_PREVIOUS_ORDER:0)
+ + (autoRunExamples?AUTO_RUN_EXAMPLES:0) + (showAllPoints?SHOW_ALL_POINTS:0)
+ + (doNotSaveWindowLocations?DO_NOT_SAVE_WINDOW_LOCS:0)
+ + (jFileChooserSettingChanged?JFILE_CHOOSER_CHANGED:0)
+ + (dialogCancelButtonOnRight?CANCEL_BUTTON_ON_RIGHT:0)
+ + (ignoreRescaleSlope?IGNORE_RESCALE_SLOPE:0)
+ + (nonBlockingFilterDialogs?NON_BLOCKING_DIALOGS:0)
+ + (fixedDicomScaling?FIXED_DICOM_SCALING:0);
+ //+ (calibrateConversions?CALIBRATE_CONVERSIONS:0);
+ prefs.put(OPTIONS2, Integer.toString(options2));
+ }
+
+ /** Saves the Point loc in the preferences
+ file as a string using the keyword key. */
+ public static void saveLocation(String key, Point loc) {
+ if (!doNotSaveWindowLocations)
+ set(key, loc!=null?loc.x+","+loc.y:null);
+ }
+
+ /** Uses the keyword key to retrieve a location
+ from the preferences file. Returns null if the
+ key is not found or the location is not valid (e.g., offscreen). */
+ public static Point getLocation(String key) {
+ String value = ijPrefs.getProperty(KEY_PREFIX+key);
+ if (value==null) return null;
+ int index = value.indexOf(",");
+ if (index==-1) return null;
+ double xloc = Tools.parseDouble(value.substring(0, index));
+ if (Double.isNaN(xloc) || index==value.length()-1) return null;
+ double yloc = Tools.parseDouble(value.substring(index+1));
+ if (Double.isNaN(yloc)) return null;
+ Point p = new Point((int)xloc, (int)yloc);
+ Rectangle bounds = GUI.getScreenBounds(p); // get bounds of screen that contains p
+ if (bounds!=null && p.x+100<=bounds.x+bounds.width && p.y+ 40<=bounds.y+bounds.height) {
+ if (locKeys.get(key)==null) { // first time for this key?
+ locKeys.setProperty(key, "");
+ Rectangle primaryScreen = GUI.getMaxWindowBounds();
+ ImageJ ij = IJ.getInstance();
+ Point ijLoc = ij!=null?ij.getLocation():null;
+ //System.out.println("getLoc: "+key+" "+(ijLoc!=null&&primaryScreen.contains(ijLoc)) + " "+!primaryScreen.contains(p));
+ if ((ijLoc!=null&&primaryScreen.contains(ijLoc)) && !primaryScreen.contains(p))
+ return null; // return null if "ImageJ" window on primary screen and this location is not
+ }
+ return p;
+ } else
+ return null;
+ }
+
+ /** Save plugin preferences. */
+ static void savePluginPrefs(Properties prefs) {
+ Enumeration e = ijPrefs.keys();
+ while (e.hasMoreElements()) {
+ String key = (String) e.nextElement();
+ if (key.indexOf(KEY_PREFIX) == 0)
+ prefs.put(key, ijPrefs.getProperty(key));
+ }
+ }
+
+ public static void savePrefs(Properties prefs, String path) throws IOException{
+ FileOutputStream fos = new FileOutputStream(path);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ prefs.store(bos, "ImageJ "+ImageJ.VERSION+" Preferences");
+ bos.close();
+ }
+
+ /** Returns the number of threads used by PlugInFilters to process images and stacks. */
+ public static int getThreads() {
+ if (threads==0) {
+ threads = getInt(THREADS, 0);
+ int processors = Runtime.getRuntime().availableProcessors();
+ if (threads<1 || threads>processors)
+ threads = processors;
+ }
+ return threads;
+ }
+
+ /** Sets the number of threads (1-32) used by PlugInFilters to process stacks. */
+ public static void setThreads(int n) {
+ if (n<1) n = 1;
+ threads = n;
+ }
+
+ /** Sets the transparent index (0-255), or set to -1 to disable transparency. */
+ public static void setTransparentIndex(int index) {
+ if (index<-1 || index>255) index = -1;
+ transparentIndex = index;
+ }
+
+ /** Returns the transparent index (0-255), or -1 if transparency is disabled. */
+ public static int getTransparentIndex() {
+ return transparentIndex;
+ }
+
+ public static Properties getControlPanelProperties() {
+ return ijPrefs;
+ }
+
+ public static String defaultResultsExtension() {
+ return get("options.ext", ".csv");
+ }
+
+ /** Sets the GenericDialog and Command Finder text scale (0.5 to 3.0). */
+ public static void setGuiScale(double scale) {
+ if (scale>=0.5 && scale<=3.0) {
+ guiScale = scale;
+ set(GUI_SCALE, guiScale);
+ Roi.resetDefaultHandleSize();
+ }
+ }
+
+ /** Returns the GenericDialog and Command Finder text scale. */
+ public static double getGuiScale() {
+ return guiScale;
+ }
+
+ /** Returns the custom properties (IJ_Props.txt) file path. */
+ public static String getCustomPropsPath() {
+ return propertiesPath;
+ }
+
+ /** Returns the custom preferences (IJ_Prefs.txt) file path. */
+ public static String getCustomPrefsPath() {
+ return preferencesPath;
+ }
+
+ /** Retrieves a string from IJ_Props or IJ_Prefs.txt.
+ Does not retrieve strings set using Prefs.set(). */
+ public static String getString(String key, String defaultString) {
+ if (props==null)
+ return defaultString;
+ String s = props.getProperty(key);
+ if (s==null)
+ return defaultString;
+ else
+ return s;
+ }
+
+ /** Retrieves a string from string in IJ_Props or IJ_Prefs.txt. */
+ public static String getString(String key) {
+ return props.getProperty(key);
+ }
+
+ /** Retrieves a number from IJ_Props or IJ_Prefs.txt.
+ Does not retrieve numbers set using Prefs.set(). */
+ public static int getInt(String key, int defaultValue) {
+ if (props==null) //workaround for Netscape JIT bug
+ return defaultValue;
+ String s = props.getProperty(key);
+ if (s!=null) {
+ try {
+ return Integer.decode(s).intValue();
+ } catch (NumberFormatException e) {IJ.log(""+e);}
+ }
+ return defaultValue;
+ }
+
+ /** Retrieves a number from IJ_Props or IJ_Prefs.txt.
+ Does not retrieve numbers set using Prefs.set(). */
+ public static double getDouble(String key, double defaultValue) {
+ if (props==null)
+ return defaultValue;
+ String s = props.getProperty(key);
+ Double d = null;
+ if (s!=null) {
+ try {d = Double.valueOf(s);}
+ catch (NumberFormatException e){d = null;}
+ if (d!=null)
+ return(d.doubleValue());
+ }
+ return defaultValue;
+ }
+
+ /** Retrieves a boolean from IJ_Props or IJ_Prefs.txt.
+ Does not retrieve boolean set using Prefs.set(). */
+ public static boolean getBoolean(String key, boolean defaultValue) {
+ if (props==null) return defaultValue;
+ String s = props.getProperty(key);
+ if (s==null)
+ return defaultValue;
+ else
+ return s.equals("true");
+ }
+
+ /** Finds a color in IJ_Props or IJ_Prefs.txt. */
+ public static Color getColor(String key, Color defaultColor) {
+ int i = getInt(key, 0xaaa);
+ if (i == 0xaaa)
+ return defaultColor;
+ return new Color((i >> 16) & 0xFF, (i >> 8) & 0xFF, i & 0xFF);
+ }
+
+ public static boolean commandLineMacro() {
+ return commandLineMacro;
+ }
+
+}
+
diff --git a/mrj/26/ij/stub/Applet.java b/mrj/26/ij/stub/Applet.java
new file mode 100644
index 00000000..0f915245
--- /dev/null
+++ b/mrj/26/ij/stub/Applet.java
@@ -0,0 +1,137 @@
+package ij.stub;
+
+import java.awt.Dimension;
+import java.awt.HeadlessException;
+import java.awt.Image;
+import java.awt.Panel;
+import java.net.URL;
+import java.util.Locale;
+
+import javax.accessibility.AccessibleContext;
+import javax.accessibility.AccessibleRole;
+import javax.accessibility.AccessibleState;
+import javax.accessibility.AccessibleStateSet;
+
+public class Applet extends Panel {
+ public Applet() throws HeadlessException {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public final void setStub(AppletStub stub) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public boolean isActive() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public URL getDocumentBase() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public URL getCodeBase() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public String getParameter(String name) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public AppletContext getAppletContext() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void resize(int width, int height) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void resize(Dimension d) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ @Override
+ public boolean isValidateRoot() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void showStatus(String msg) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public Image getImage(URL url) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public Image getImage(URL url, String name) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public static final AudioClip newAudioClip(URL url) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public AudioClip getAudioClip(URL url) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public AudioClip getAudioClip(URL url, String name) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public String getAppletInfo() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public String[][] getParameterInfo() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void play(URL url) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void play(URL url, String name) {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void init() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void start() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void stop() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ public void destroy() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ @SuppressWarnings("serial") // Not statically typed as Serializable
+ AccessibleContext accessibleContext = null;
+
+ public AccessibleContext getAccessibleContext() {
+ throw new UnsupportedOperationException("Java 26 has removed Applets");
+ }
+
+ protected class AccessibleApplet extends AccessibleAWTPanel {
+ protected AccessibleApplet() {}
+
+ public AccessibleRole getAccessibleRole() {
+ return AccessibleRole.FRAME;
+ }
+
+ public AccessibleStateSet getAccessibleStateSet() {
+ AccessibleStateSet states = super.getAccessibleStateSet();
+ states.add(AccessibleState.ACTIVE);
+ return states;
+ }
+ }
+}
diff --git a/mrj/26/ij/stub/AppletContext.java b/mrj/26/ij/stub/AppletContext.java
new file mode 100644
index 00000000..6b19d015
--- /dev/null
+++ b/mrj/26/ij/stub/AppletContext.java
@@ -0,0 +1,31 @@
+package ij.stub;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Iterator;
+
+public interface AppletContext {
+
+ AudioClip getAudioClip(URL url);
+
+ Image getImage(URL url);
+
+ Applet getApplet(String name);
+
+ Enumeration