package ij.plugin.frame; import java.awt.*; import java.awt.event.*; import java.util.*; import java.io.*; import ij.*; import ij.plugin.*; import ij.plugin.frame.*; import ij.text.*; import ij.gui.*; import ij.util.*; import ij.io.*; import ij.process.*; import ij.measure.*; /** This is ImageJ's macro recorder. */ public class Recorder extends PlugInFrame implements PlugIn, ActionListener, ImageListener, ItemListener { /** This variable is true if the recorder is running. */ public static boolean record; /** Set this variable true to allow recording within IJ.run() calls. */ public static boolean recordInMacros; private final static int MACRO=0, JAVASCRIPT=1, PLUGIN=2; private final static String[] modes = {"Macro", "JavaScript", "Plugin"}; private Choice mode; private Button makeMacro, help; private TextField fileName; private String fitTypeStr = CurveFitter.fitList[0]; private static TextArea textArea; private static Recorder instance; private static String commandName; private static String commandOptions; private static String defaultName = "Macro.ijm"; private static boolean recordPath = true; private static boolean scriptMode; private static boolean imageUpdated; private static int imageID; public Recorder() { super("Recorder"); if (instance!=null) { WindowManager.toFront(instance); return; } WindowManager.addWindow(this); instance = this; record = true; scriptMode = false; recordInMacros = false; Panel panel = new Panel(new FlowLayout(FlowLayout.LEFT, 0, 0)); panel.add(new Label(" Record:")); mode = new Choice(); for (int i=0; i-1) key = key.substring(0,index); index = key.indexOf(":"); if (index>-1) key = key.substring(0,index); key = key.toLowerCase(Locale.US); return key; } /** Writes the current command and options to the Recorder window. */ public static void saveCommand() { String name = commandName; if (name!=null) { if (commandOptions==null && (name.equals("Fill")||name.equals("Clear"))) commandOptions = "slice"; if (commandOptions!=null) { if (name.equals("Open...")) { String s = scriptMode?"imp = IJ.openImage":"open"; if (scriptMode && isTextOrTable(commandOptions)) s = "IJ.open"; textArea.append(s+"(\""+strip(commandOptions)+"\");\n"); } else if (isSaveAs()) { if (name.endsWith("...")) name= name.substring(0, name.length()-3); String path = strip(commandOptions); String s = scriptMode?"IJ.saveAs(imp, ":"saveAs("; textArea.append(s+"\""+name+"\", \""+path+"\");\n"); } else if (name.equals("Image...")) appendNewImage(); else if (name.equals("Set Slice...")) textArea.append((scriptMode?"imp.":"")+"setSlice("+strip(commandOptions)+");\n"); else if (name.equals("Rename...")) textArea.append((scriptMode?"imp.setTitle":"rename")+"(\""+strip(commandOptions)+"\");\n"); else if (name.equals("Wand Tool...")) textArea.append("//run(\""+name+"\", \""+commandOptions+"\");\n"); else if (name.equals("Results... ")&&commandOptions.indexOf(".txt")==-1) textArea.append((scriptMode?"IJ.":"")+"open(\""+strip(commandOptions)+"\");\n"); else if (name.equals("Results...")) // Save As>Results ; else if (name.equals("Run...")) // Plugins>Macros>Run ; else { String prefix = "run("; if (scriptMode) prefix = imageUpdated?"IJ.run(imp, ":"IJ.run("; textArea.append(prefix+"\""+name+"\", \""+commandOptions+"\");\n"); } } else { if (name.equals("Threshold...") || name.equals("Fonts...") || name.equals("Brightness/Contrast...")) textArea.append("//run(\""+name+"\");\n"); else if (name.equals("Start Animation [\\]")) textArea.append("doCommand(\"Start Animation [\\\\]\");\n"); else if (name.equals("Add to Manager ")) ; else if (name.equals("Draw")&&!scriptMode) { ImagePlus imp = WindowManager.getCurrentImage(); Roi roi = imp.getRoi(); if (roi!=null && (roi instanceof TextRoi)) textArea.append(((TextRoi)roi).getMacroCode(imp.getProcessor())); else textArea.append("run(\""+name+"\");\n"); } else { if (IJ.altKeyDown() && (name.equals("Open Next")||name.equals("Plot Profile"))) textArea.append("setKeyDown(\"alt\"); "); if (scriptMode) { String prefix = imageUpdated||name.equals("Select None")?"IJ.run(imp, ":"IJ.run("; textArea.append(prefix+"\""+name+"\", \"\");\n"); } else textArea.append("run(\""+name+"\");\n"); } } } commandName = null; commandOptions = null; if (imageID!=0) { ImagePlus.removeImageListener(instance); imageID = 0; } } static boolean isTextOrTable(String path) { return path.endsWith(".txt") || path.endsWith(".csv") || path.endsWith(".xls"); } static boolean isSaveAs() { return commandName.equals("Tiff...") || commandName.equals("Gif...") || commandName.equals("Jpeg...") || commandName.equals("Text Image...") || commandName.equals("ZIP...") || commandName.equals("Raw Data...") || commandName.equals("BMP...") || commandName.equals("PNG...") || commandName.equals("PGM...") || commandName.equals("FITS...") || commandName.equals("LUT...") || commandName.equals("Selection...") || commandName.equals("XY Coordinates...") //|| commandName.equals("Results...") || commandName.equals("Text... "); } static void appendNewImage() { String options = getCommandOptions() + " "; String title = Macro.getValue(options, "name", "Untitled"); String type = Macro.getValue(options, "type", "8-bit"); String fill = Macro.getValue(options, "fill", ""); if (!fill.equals("")) type = type +" " + fill; int width = (int)Tools.parseDouble(Macro.getValue(options, "width", "512")); int height = (int)Tools.parseDouble(Macro.getValue(options, "height", "512")); int depth= (int)Tools.parseDouble(Macro.getValue(options, "slices", "1")); textArea.append((scriptMode?"imp = IJ.createImage":"newImage") +"(\""+title+"\", "+"\""+type+"\", "+width+", "+height+", "+depth+");\n"); } static String strip(String value) { int index = value.indexOf('='); if (index>=0) value = value.substring(index+1); if (value.startsWith("[")) { int index2 = value.indexOf(']'); if (index2==-1) index2 = value.length(); value = value.substring(1, index2); } else { index = value.indexOf(' '); if (index!=-1) value = value.substring(0, index); } return value; } static String addQuotes(String value) { int index = value.indexOf(' '); if (index>-1) value = "["+value+"]"; return value; } /** Used by GenericDialog to determine if any options have been recorded. */ static public String getCommandOptions() { return commandOptions; } void createMacro() { String text = textArea.getText(); if (text==null || text.equals("")) { IJ.showMessage("Recorder", "A macro cannot be created until at least\none command has been recorded."); return; } Editor ed = (Editor)IJ.runPlugIn("ij.plugin.frame.Editor", ""); if (ed==null) return; boolean java = mode.getSelectedItem().equals(modes[PLUGIN]); String name = fileName.getText(); int dotIndex = name.lastIndexOf("."); if (scriptMode) { // JavaScript or Java if (dotIndex>=0) name = name.substring(0, dotIndex); if (text.indexOf("rm.")!=-1) { text = (java?"RoiManager ":"")+ "rm = RoiManager.getInstance();\n" + "if (rm==null) rm = new RoiManager();\n" + "rm.runCommand(\"reset\");\n" + text; } if (text.indexOf("imp =")==-1 && text.indexOf("IJ.openImage")==-1 && text.indexOf("IJ.createImage")==-1) text = (java?"ImagePlus ":"") + "imp = IJ.getImage();\n" + text; if (text.indexOf("imp =")!=-1 && !(text.indexOf("IJ.getImage")!=-1||text.indexOf("IJ.saveAs")!=-1||text.indexOf("imp.close")!=-1)) text = text + "imp.show();\n"; if (java) { name += ".java"; createPlugin(text, name); return; } else name += ".js"; } else { // ImageJ macro if (!name.endsWith(".txt")) { if (dotIndex>=0) name = name.substring(0, dotIndex); name += ".ijm"; } } ed.createMacro(name, text); } void createPlugin(String text, String name) { StringTokenizer st = new StringTokenizer(text, "\n"); int n = st.countTokens(); boolean impDeclared = false; String line; StringBuffer sb = new StringBuffer(); for(int i=0; i3) { sb.append("\t\t"); if (line.startsWith("imp =") && !impDeclared) { sb.append("ImagePlus "); impDeclared = true; } sb.append(line); sb.append('\n'); } } String text2 = new String(sb); text2 = text2.replaceAll("print", "IJ.log"); NewPlugin np = (NewPlugin)IJ.runPlugIn("ij.plugin.NewPlugin", text2); Editor ed = np.getEditor(); ed.updateClassName(ed.getTitle(), name); ed.setTitle(name); } /** Temporarily disables path recording. */ public static void disablePathRecording() { recordPath = false; } public static boolean scriptMode() { return scriptMode; } public void actionPerformed(ActionEvent e) { if (e.getSource()==makeMacro) createMacro(); else if (e.getSource()==help) showHelp(); } public void itemStateChanged(ItemEvent e) { setFileName(); } void setFileName() { String name = mode.getSelectedItem(); scriptMode = name.equals(modes[JAVASCRIPT])||name.equals(modes[PLUGIN]); if (name.equals(modes[MACRO])) fileName.setText("Macro.ijm"); else if (name.equals(modes[JAVASCRIPT])) fileName.setText("script.js"); else fileName.setText("My_Plugin.java"); } public void imageUpdated(ImagePlus imp) { if (imp.getID()==imageID) imageUpdated = true; } public void imageOpened(ImagePlus imp) { } public void imageClosed(ImagePlus imp) { } void showHelp() { IJ.showMessage("Recorder", "Click \"Create\" to open recorded commands\n" +"as a macro in an editor window.\n" +" \n" +"In the editor:\n" +" \n" +" Type ctrl+R (Macros>Run Macro) to\n" +" run the macro.\n" +" \n" +" Use File>Save As to save it and\n" +" ImageJ's Open command to open it.\n" +" \n" +" To create a command, save in the plugins\n" +" folder and run Help>Refresh Menus.\n" ); } public void close() { super.close(); record = false; textArea = null; commandName = null; instance = null; Prefs.set("recorder.mode", mode.getSelectedItem()); } public String getText() { if (textArea==null) return ""; else return textArea.getText(); } public static Recorder getInstance() { return instance; } }