PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/ImageJ/source/ij/plugin/frame/Editor.java

https://bitbucket.org/Sciumo/imagej
Java | 1016 lines | 954 code | 47 blank | 15 comment | 214 complexity | 5d24ab4cd13b4b7600ba788717357b9b MD5 | raw file
  1. package ij.plugin.frame;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.io.*;
  5. import java.util.*;
  6. import java.awt.datatransfer.*;
  7. import ij.*;
  8. import ij.gui.*;
  9. import ij.util.Tools;
  10. import ij.text.*;
  11. import ij.macro.*;
  12. import ij.plugin.MacroInstaller;
  13. import ij.plugin.NewPlugin;
  14. import ij.io.SaveDialog;
  15. /** This is a simple TextArea based editor for editing and compiling plugins. */
  16. public class Editor extends PlugInFrame implements ActionListener, ItemListener,
  17. TextListener, ClipboardOwner, MacroConstants {
  18. /** ImportPackage statements added in front of scripts. Contains no
  19. newlines so that lines numbers in error messages are not changed. */
  20. public static String JavaScriptIncludes =
  21. "importPackage(Packages.ij);"+
  22. "importPackage(Packages.ij.gui);"+
  23. "importPackage(Packages.ij.process);"+
  24. "importPackage(Packages.ij.measure);"+
  25. "importPackage(Packages.ij.util);"+
  26. "importPackage(Packages.ij.plugin);"+
  27. "importPackage(Packages.ij.io);"+
  28. "importPackage(Packages.ij.plugin.filter);"+
  29. "importPackage(Packages.ij.plugin.frame);"+
  30. "importPackage(java.lang);"+
  31. "importPackage(java.awt);"+
  32. "importPackage(java.awt.image);"+
  33. "importPackage(java.awt.geom);"+
  34. "importPackage(java.util);"+
  35. "importPackage(java.io);"+
  36. "function print(s) {IJ.log(s);};";
  37. public static String JS_NOT_FOUND =
  38. "JavaScript.jar was not found in the plugins\nfolder. It can be downloaded from:\n \n"+IJ.URL+"/download/tools/JavaScript.jar";
  39. public static final int MAX_SIZE=28000, XINC=10, YINC=18;
  40. public static final int MONOSPACED=1, MENU_BAR=2;
  41. public static final int MACROS_MENU_ITEMS = 8;
  42. static final String FONT_SIZE = "editor.font.size";
  43. static final String FONT_MONO= "editor.font.mono";
  44. static final String CASE_SENSITIVE= "editor.case-sensitive";
  45. static final String DEFAULT_DIR= "editor.dir";
  46. private TextArea ta;
  47. private String path;
  48. private boolean changes;
  49. private static String searchString = "";
  50. private static boolean caseSensitive = Prefs.get(CASE_SENSITIVE, true);
  51. private static int lineNumber = 1;
  52. private static int xoffset, yoffset;
  53. private static int nWindows;
  54. private Menu fileMenu, editMenu;
  55. private Properties p = new Properties();
  56. private int[] macroStarts;
  57. private String[] macroNames;
  58. private MenuBar mb;
  59. private Menu macrosMenu;
  60. private int nMacros;
  61. private Program pgm;
  62. private int eventCount;
  63. private String shortcutsInUse;
  64. private int inUseCount;
  65. private MacroInstaller installer;
  66. private static String defaultDir = Prefs.get(DEFAULT_DIR, null);;
  67. private boolean dontShowWindow;
  68. private int[] sizes = {9, 10, 11, 12, 13, 14, 16, 18, 20, 24, 36, 48, 60, 72};
  69. private int fontSize = (int)Prefs.get(FONT_SIZE, 6); // defaults to 16-point
  70. private CheckboxMenuItem monospaced;
  71. private static boolean wholeWords;
  72. private boolean isMacroWindow;
  73. private int debugStart, debugEnd;
  74. private static TextWindow debugWindow;
  75. private boolean step;
  76. private int previousLine;
  77. private static Editor instance;
  78. private int runToLine;
  79. private boolean fixedLineEndings;
  80. public Editor() {
  81. this(16, 60, 0, MENU_BAR);
  82. }
  83. public Editor(int rows, int columns, int fontSize, int options) {
  84. super("Editor");
  85. WindowManager.addWindow(this);
  86. addMenuBar(options);
  87. ta = new TextArea(rows, columns);
  88. ta.addTextListener(this);
  89. if (IJ.isLinux()) ta.setBackground(Color.white);
  90. addKeyListener(IJ.getInstance()); // ImageJ handles keyboard shortcuts
  91. add(ta);
  92. pack();
  93. if (fontSize<0) fontSize = 0;
  94. if (fontSize>=sizes.length) fontSize = sizes.length-1;
  95. setFont();
  96. positionWindow();
  97. }
  98. void addMenuBar(int options) {
  99. mb = new MenuBar();
  100. if (Menus.getFontSize()!=0) ;
  101. mb.setFont(Menus.getFont());
  102. Menu m = new Menu("File");
  103. m.add(new MenuItem("New...", new MenuShortcut(KeyEvent.VK_N, true)));
  104. m.add(new MenuItem("Open...", new MenuShortcut(KeyEvent.VK_O)));
  105. m.add(new MenuItem("Save", new MenuShortcut(KeyEvent.VK_S)));
  106. m.add(new MenuItem("Save As..."));
  107. m.add(new MenuItem("Print...", new MenuShortcut(KeyEvent.VK_P)));
  108. m.addActionListener(this);
  109. fileMenu = m;
  110. mb.add(m);
  111. m = new Menu("Edit");
  112. String key = IJ.isMacintosh()?" Cmd ":" Ctrl+";
  113. MenuItem item = new MenuItem("Undo"+key+"Z");
  114. item.setEnabled(false);
  115. m.add(item);
  116. m.addSeparator();
  117. boolean shortcutsBroken = IJ.isWindows()
  118. && (System.getProperty("java.version").indexOf("1.1.8")>=0
  119. ||System.getProperty("java.version").indexOf("1.5.")>=0);
  120. if (shortcutsBroken)
  121. item = new MenuItem("Cut Ctrl+X");
  122. else
  123. item = new MenuItem("Cut",new MenuShortcut(KeyEvent.VK_X));
  124. m.add(item);
  125. if (shortcutsBroken)
  126. item = new MenuItem("Copy Ctrl+C");
  127. else
  128. item = new MenuItem("Copy", new MenuShortcut(KeyEvent.VK_C));
  129. m.add(item);
  130. if (shortcutsBroken)
  131. item = new MenuItem("Paste Ctrl+V");
  132. else
  133. item = new MenuItem("Paste",new MenuShortcut(KeyEvent.VK_V));
  134. m.add(item);
  135. m.addSeparator();
  136. m.add(new MenuItem("Find...", new MenuShortcut(KeyEvent.VK_F)));
  137. m.add(new MenuItem("Find Next", new MenuShortcut(KeyEvent.VK_G)));
  138. m.add(new MenuItem("Go to Line...", new MenuShortcut(KeyEvent.VK_L)));
  139. m.addSeparator();
  140. m.add(new MenuItem("Select All", new MenuShortcut(KeyEvent.VK_A)));
  141. m.add(new MenuItem("Zap Gremlins"));
  142. m.add(new MenuItem("Copy to Image Info"));
  143. m.addActionListener(this);
  144. mb.add(m);
  145. editMenu = m;
  146. if ((options&MENU_BAR)!=0)
  147. setMenuBar(mb);
  148. m = new Menu("Font");
  149. m.add(new MenuItem("Make Text Smaller", new MenuShortcut(KeyEvent.VK_N)));
  150. m.add(new MenuItem("Make Text Larger", new MenuShortcut(KeyEvent.VK_M)));
  151. m.addSeparator();
  152. monospaced = new CheckboxMenuItem("Monospaced Font", Prefs.get(FONT_MONO, false));
  153. if ((options&MONOSPACED)!=0) monospaced.setState(true);
  154. monospaced.addItemListener(this);
  155. m.add(monospaced);
  156. m.add(new MenuItem("Save Settings"));
  157. m.addActionListener(this);
  158. mb.add(m);
  159. }
  160. public void positionWindow() {
  161. Dimension screen = IJ.getScreenSize();
  162. Dimension window = getSize();
  163. if (window.width==0)
  164. return;
  165. int left = screen.width/2-window.width/2;
  166. int top = (screen.height-window.height)/4;
  167. if (top<0) top = 0;
  168. if (nWindows<=0 || xoffset>8*XINC)
  169. {xoffset=0; yoffset=0;}
  170. setLocation(left+xoffset, top+yoffset);
  171. xoffset+=XINC; yoffset+=YINC;
  172. nWindows++;
  173. }
  174. void setWindowTitle(String title) {
  175. Menus.updateWindowMenuItem(getTitle(), title);
  176. setTitle(title);
  177. }
  178. public void create(String name, String text) {
  179. if (text!=null && text.length()>0) fixedLineEndings = true;
  180. ta.append(text);
  181. if (IJ.isMacOSX()) IJ.wait(25); // needed to get setCaretPosition() on OS X
  182. ta.setCaretPosition(0);
  183. setWindowTitle(name);
  184. boolean macroExtension = name.endsWith(".txt") || name.endsWith(".ijm");
  185. if (macroExtension || name.endsWith(".js") || name.indexOf(".")==-1) {
  186. macrosMenu = new Menu("Macros");
  187. macrosMenu.add(new MenuItem("Run Macro", new MenuShortcut(KeyEvent.VK_R)));
  188. macrosMenu.add(new MenuItem("Evaluate Line", new MenuShortcut(KeyEvent.VK_Y)));
  189. macrosMenu.add(new MenuItem("Abort Macro"));
  190. macrosMenu.add(new MenuItem("Install Macros", new MenuShortcut(KeyEvent.VK_I)));
  191. macrosMenu.add(new MenuItem("Function Finder...", new MenuShortcut(KeyEvent.VK_F, true)));
  192. macrosMenu.addSeparator();
  193. macrosMenu.add(new MenuItem("Evaluate JavaScript", new MenuShortcut(KeyEvent.VK_J, false)));
  194. macrosMenu.addSeparator();
  195. // MACROS_MENU_ITEMS must be updated if items are added to this menu
  196. macrosMenu.addActionListener(this);
  197. mb.add(macrosMenu);
  198. if (!name.endsWith(".js")) {
  199. Menu debugMenu = new Menu("Debug");
  200. debugMenu.add(new MenuItem("Debug Macro", new MenuShortcut(KeyEvent.VK_D)));
  201. debugMenu.add(new MenuItem("Step", new MenuShortcut(KeyEvent.VK_E)));
  202. debugMenu.add(new MenuItem("Trace", new MenuShortcut(KeyEvent.VK_T)));
  203. debugMenu.add(new MenuItem("Fast Trace", new MenuShortcut(KeyEvent.VK_T,true)));
  204. debugMenu.add(new MenuItem("Run"));
  205. debugMenu.add(new MenuItem("Run to Insertion Point", new MenuShortcut(KeyEvent.VK_E, true)));
  206. debugMenu.add(new MenuItem("Abort"));
  207. debugMenu.addActionListener(this);
  208. mb.add(debugMenu);
  209. }
  210. if (macroExtension && text.indexOf("macro ")!=-1)
  211. installMacros(text, false);
  212. } else {
  213. fileMenu.addSeparator();
  214. fileMenu.add(new MenuItem("Compile and Run", new MenuShortcut(KeyEvent.VK_R)));
  215. }
  216. if (IJ.getInstance()!=null && !dontShowWindow)
  217. show();
  218. if (dontShowWindow) {
  219. dispose();
  220. dontShowWindow = false;
  221. }
  222. WindowManager.setWindow(this);
  223. changes = false;
  224. }
  225. public void createMacro(String name, String text) {
  226. create(name, text);
  227. }
  228. void installMacros(String text, boolean installInPluginsMenu) {
  229. String functions = Interpreter.getAdditionalFunctions();
  230. if (functions!=null && text!=null) {
  231. if (!(text.endsWith("\n") || functions.startsWith("\n")))
  232. text = text + "\n" + functions;
  233. else
  234. text = text + functions;
  235. }
  236. installer = new MacroInstaller();
  237. installer.setFileName(getTitle());
  238. int nShortcutsOrTools = installer.install(text, macrosMenu);
  239. if (installInPluginsMenu || nShortcutsOrTools>0)
  240. installer.install(null);
  241. dontShowWindow = installer.isAutoRunAndHide();
  242. }
  243. public void open(String dir, String name) {
  244. path = dir+name;
  245. File file = new File(path);
  246. try {
  247. StringBuffer sb = new StringBuffer(5000);
  248. BufferedReader r = new BufferedReader(new FileReader(file));
  249. while (true) {
  250. String s=r.readLine();
  251. if (s==null)
  252. break;
  253. else
  254. sb.append(s+"\n");
  255. }
  256. r.close();
  257. create(name, new String(sb));
  258. changes = false;
  259. }
  260. catch (Exception e) {
  261. IJ.handleException(e);
  262. return;
  263. }
  264. }
  265. public String getText() {
  266. if (ta==null)
  267. return "";
  268. else
  269. return ta.getText();
  270. }
  271. public TextArea getTextArea() {
  272. return ta;
  273. }
  274. public void display(String title, String text) {
  275. ta.selectAll();
  276. ta.replaceRange(text, ta.getSelectionStart(), ta.getSelectionEnd());
  277. ta.setCaretPosition(0);
  278. setWindowTitle(title);
  279. changes = false;
  280. if (IJ.getInstance()!=null)
  281. show();
  282. WindowManager.setWindow(this);
  283. }
  284. void save() {
  285. if (path==null) {
  286. saveAs();
  287. return;
  288. }
  289. File f = new File(path);
  290. if (f.exists() && !f.canWrite()) {
  291. IJ.showMessage("Editor", "Unable to save because file is write-protected. \n \n" + path);
  292. return;
  293. }
  294. String text = ta.getText();
  295. char[] chars = new char[text.length()];
  296. text.getChars(0, text.length(), chars, 0);
  297. try {
  298. BufferedReader br = new BufferedReader(new CharArrayReader(chars));
  299. BufferedWriter bw = new BufferedWriter(new FileWriter(path));
  300. while (true) {
  301. String s = br.readLine();
  302. if (s==null) break;
  303. bw.write(s, 0, s.length());
  304. bw.newLine();
  305. }
  306. bw.close();
  307. IJ.showStatus(text.length()+" chars saved to " + path);
  308. changes = false;
  309. } catch
  310. (IOException e) {}
  311. }
  312. void compileAndRun() {
  313. if (path==null)
  314. saveAs();
  315. if (path!=null) {
  316. save();
  317. String text = ta.getText();
  318. if (text.contains("implements PlugInFilter") && text.contains("IJ.run("))
  319. IJ.log("Plugins that call IJ.run() should probably implement PlugIn, not PlugInFilter.");
  320. IJ.runPlugIn("ij.plugin.Compiler", path);
  321. }
  322. }
  323. final void runMacro(boolean debug) {
  324. if (getTitle().endsWith(".js"))
  325. {evaluateJavaScript(); return;}
  326. int start = ta.getSelectionStart();
  327. int end = ta.getSelectionEnd();
  328. String text;
  329. if (start==end)
  330. text = ta.getText();
  331. else
  332. text = ta.getSelectedText();
  333. new MacroRunner(text, debug?this:null);
  334. }
  335. void evaluateJavaScript() {
  336. if (!getTitle().endsWith(".js"))
  337. setTitle(SaveDialog.setExtension(getTitle(), ".js"));
  338. int start = ta.getSelectionStart();
  339. int end = ta.getSelectionEnd();
  340. String text;
  341. if (start==end)
  342. text = ta.getText();
  343. else
  344. text = ta.getSelectedText();
  345. if (text.equals("")) return;
  346. text = getJSPrefix("") + text;
  347. if (IJ.isJava16() && !(IJ.isMacOSX()&&!IJ.is64Bit()))
  348. IJ.runPlugIn("JavaScriptEvaluator", text);
  349. else {
  350. Object js = IJ.runPlugIn("JavaScript", text);
  351. if (js==null) IJ.error(JS_NOT_FOUND);
  352. }
  353. }
  354. void evaluateLine() {
  355. int start = ta.getSelectionStart();
  356. int end = ta.getSelectionEnd();
  357. if (end>start)
  358. {runMacro(false); return;}
  359. String text = ta.getText();
  360. while (start>0) {
  361. start--;
  362. if (text.charAt(start)=='\n')
  363. {start++; break;}
  364. }
  365. while (end<text.length()-1) {
  366. end++;
  367. if (text.charAt(end)=='\n')
  368. break;
  369. }
  370. ta.setSelectionStart(start);
  371. ta.setSelectionEnd(end);
  372. runMacro(false);
  373. }
  374. void print () {
  375. PrintJob pjob = Toolkit.getDefaultToolkit().getPrintJob(this, "Cool Stuff", p);
  376. if (pjob != null) {
  377. Graphics pg = pjob.getGraphics( );
  378. if (pg != null) {
  379. String s = ta.getText();
  380. printString(pjob, pg, s);
  381. pg.dispose( );
  382. }
  383. pjob.end( );
  384. }
  385. }
  386. void printString (PrintJob pjob, Graphics pg, String s) {
  387. int pageNum = 1;
  388. int linesForThisPage = 0;
  389. int linesForThisJob = 0;
  390. int topMargin = 30;
  391. int leftMargin = 30;
  392. int bottomMargin = 30;
  393. if (!(pg instanceof PrintGraphics))
  394. throw new IllegalArgumentException ("Graphics contextt not PrintGraphics");
  395. if (IJ.isMacintosh()) {
  396. topMargin = 0;
  397. leftMargin = 0;
  398. bottomMargin = 0;
  399. }
  400. StringReader sr = new StringReader (s);
  401. LineNumberReader lnr = new LineNumberReader (sr);
  402. String nextLine;
  403. int pageHeight = pjob.getPageDimension().height - bottomMargin;
  404. Font helv = new Font(getFontName(), Font.PLAIN, 10);
  405. pg.setFont (helv);
  406. FontMetrics fm = pg.getFontMetrics(helv);
  407. int fontHeight = fm.getHeight();
  408. int fontDescent = fm.getDescent();
  409. int curHeight = topMargin;
  410. try {
  411. do {
  412. nextLine = lnr.readLine();
  413. if (nextLine != null) {
  414. nextLine = detabLine(nextLine);
  415. if ((curHeight + fontHeight) > pageHeight) {
  416. // New Page
  417. pageNum++;
  418. linesForThisPage = 0;
  419. pg.dispose();
  420. pg = pjob.getGraphics();
  421. if (pg != null)
  422. pg.setFont (helv);
  423. curHeight = topMargin;
  424. }
  425. curHeight += fontHeight;
  426. if (pg != null) {
  427. pg.drawString (nextLine, leftMargin, curHeight - fontDescent);
  428. linesForThisPage++;
  429. linesForThisJob++;
  430. }
  431. }
  432. } while (nextLine != null);
  433. } catch (EOFException eof) {
  434. // Fine, ignore
  435. } catch (Throwable t) { // Anything else
  436. IJ.handleException(t);
  437. }
  438. }
  439. String detabLine(String s) {
  440. if (s.indexOf('\t')<0)
  441. return s;
  442. int tabSize = 4;
  443. StringBuffer sb = new StringBuffer((int)(s.length()*1.25));
  444. char c;
  445. for (int i=0; i<s.length(); i++) {
  446. c = s.charAt(i);
  447. if (c=='\t') {
  448. for (int j=0; j<tabSize; j++)
  449. sb.append(' ');
  450. } else
  451. sb.append(c);
  452. }
  453. return sb.toString();
  454. }
  455. boolean copy() {
  456. String s;
  457. s = ta.getSelectedText();
  458. Clipboard clip = getToolkit().getSystemClipboard();
  459. if (clip!=null) {
  460. StringSelection cont = new StringSelection(s);
  461. clip.setContents(cont,this);
  462. return true;
  463. } else
  464. return false;
  465. }
  466. void cut() {
  467. if (copy()) {
  468. int start = ta.getSelectionStart();
  469. int end = ta.getSelectionEnd();
  470. ta.replaceRange("", start, end);
  471. if (IJ.isMacOSX())
  472. ta.setCaretPosition(start);
  473. }
  474. }
  475. void paste() {
  476. String s;
  477. s = ta.getSelectedText();
  478. Clipboard clipboard = getToolkit( ). getSystemClipboard();
  479. Transferable clipData = clipboard.getContents(s);
  480. try {
  481. s = (String)(clipData.getTransferData(DataFlavor.stringFlavor));
  482. }
  483. catch (Exception e) {
  484. s = e.toString( );
  485. }
  486. if (!fixedLineEndings && IJ.isWindows())
  487. fixLineEndings();
  488. fixedLineEndings = true;
  489. int start = ta.getSelectionStart( );
  490. int end = ta.getSelectionEnd( );
  491. ta.replaceRange(s, start, end);
  492. if (IJ.isMacOSX())
  493. ta.setCaretPosition(start+s.length());
  494. }
  495. void copyToInfo() {
  496. ImagePlus imp = WindowManager.getCurrentImage();
  497. if (imp==null) {
  498. IJ.noImage();
  499. return;
  500. }
  501. int start = ta.getSelectionStart();
  502. int end = ta.getSelectionEnd();
  503. String text;
  504. if (start==end)
  505. text = ta.getText();
  506. else
  507. text = ta.getSelectedText();
  508. imp.setProperty("Info", text);
  509. }
  510. public void actionPerformed(ActionEvent e) {
  511. String what = e.getActionCommand();
  512. int flags = e.getModifiers();
  513. boolean altKeyDown = (flags & Event.ALT_MASK)!=0;
  514. if (IJ.debugMode) IJ.log("actionPerformed: "+e);
  515. if ("Save".equals(what))
  516. save();
  517. else if ("Compile and Run".equals(what))
  518. compileAndRun();
  519. else if ("Run Macro".equals(what)) {
  520. if (altKeyDown) {
  521. enableDebugging();
  522. runMacro(true);
  523. } else
  524. runMacro(false);
  525. } else if ("Debug Macro".equals(what)) {
  526. enableDebugging();
  527. runMacro(true);
  528. } else if ("Step".equals(what))
  529. setDebugMode(Interpreter.STEP);
  530. else if ("Trace".equals(what))
  531. setDebugMode(Interpreter.TRACE);
  532. else if ("Fast Trace".equals(what))
  533. setDebugMode(Interpreter.FAST_TRACE);
  534. else if ("Run".equals(what))
  535. setDebugMode(Interpreter.RUN);
  536. else if ("Run to Insertion Point".equals(what))
  537. runToInsertionPoint();
  538. else if ("Abort".equals(what) || "Abort Macro".equals(what)) {
  539. Interpreter.abort();
  540. IJ.beep();
  541. } else if ("Evaluate Line".equals(what))
  542. evaluateLine();
  543. else if ("Install Macros".equals(what))
  544. installMacros(ta.getText(), true);
  545. else if ("Function Finder...".equals(what))
  546. new FunctionFinder();
  547. else if ("Evaluate JavaScript".equals(what))
  548. evaluateJavaScript();
  549. else if ("Print...".equals(what))
  550. print();
  551. else if (what.equals("Paste"))
  552. paste();
  553. else if (what.equals("Copy"))
  554. copy();
  555. else if (what.equals("Cut"))
  556. cut();
  557. else if ("Save As...".equals(what))
  558. saveAs();
  559. else if ("Select All".equals(what))
  560. selectAll();
  561. else if ("Find...".equals(what))
  562. find(null);
  563. else if ("Find Next".equals(what))
  564. find(searchString);
  565. else if ("Go to Line...".equals(what))
  566. gotoLine();
  567. else if ("Zap Gremlins".equals(what))
  568. zapGremlins();
  569. else if ("Make Text Larger".equals(what))
  570. changeFontSize(true);
  571. else if ("Make Text Smaller".equals(what))
  572. changeFontSize(false);
  573. else if ("Save Settings".equals(what))
  574. saveSettings();
  575. else if ("New...".equals(what))
  576. IJ.run("Text Window");
  577. else if ("Open...".equals(what))
  578. IJ.open();
  579. else if (what.equals("Copy to Image Info"))
  580. copyToInfo();
  581. else {
  582. if (altKeyDown) {
  583. enableDebugging();
  584. installer.runMacro(what, this);
  585. } else
  586. installer.runMacro(what, null);
  587. }
  588. }
  589. final void runToInsertionPoint() {
  590. Interpreter interp = Interpreter.getInstance();
  591. if (interp==null)
  592. IJ.beep();
  593. else {
  594. runToLine = getCurrentLine();
  595. //IJ.log("runToLine: "+runToLine);
  596. setDebugMode(Interpreter.RUN_TO_CARET);
  597. }
  598. }
  599. final int getCurrentLine() {
  600. int pos = ta.getCaretPosition();
  601. int currentLine = 0;
  602. String text = ta.getText();
  603. if (IJ.isWindows() && !IJ.isVista())
  604. text = text.replaceAll("\r\n", "\n");
  605. char[] chars = new char[text.length()];
  606. chars = text.toCharArray();
  607. int count=0;
  608. int start=0, end=0;
  609. int len = chars.length;
  610. for (int i=0; i<len; i++) {
  611. if (chars[i]=='\n') {
  612. count++;
  613. start = end;
  614. end = i;
  615. if (pos>=start && pos<end) {
  616. currentLine = count;
  617. break;
  618. }
  619. }
  620. }
  621. if (currentLine==0 && pos>end)
  622. currentLine = count;
  623. return currentLine;
  624. }
  625. final void enableDebugging() {
  626. step = true;
  627. Interpreter interp = Interpreter.getInstance();
  628. if (interp!=null && interp.getEditor()==this) {
  629. interp.abort();
  630. IJ.wait(100);
  631. }
  632. int start = ta.getSelectionStart();
  633. int end = ta.getSelectionEnd();
  634. if (start==debugStart && end==debugEnd)
  635. ta.select(start, start);
  636. }
  637. final void setDebugMode(int mode) {
  638. step = true;
  639. Interpreter interp = Interpreter.getInstance();
  640. if (interp!=null) {
  641. interp.setEditor(this);
  642. interp.setDebugMode(mode);
  643. }
  644. }
  645. public void textValueChanged(TextEvent evt) {
  646. if (isMacroWindow) return;
  647. // first few textValueChanged events may be bogus
  648. eventCount++;
  649. if (eventCount>2 || !IJ.isMacOSX() && eventCount>1)
  650. changes = true;
  651. if (IJ.isMacOSX()) // screen update bug work around
  652. ta.setCaretPosition(ta.getCaretPosition());
  653. }
  654. public void itemStateChanged(ItemEvent e) {
  655. CheckboxMenuItem item = (CheckboxMenuItem)e.getSource();
  656. setFont();
  657. }
  658. /** Override windowActivated in PlugInFrame to
  659. prevent Mac menu bar from being installed. */
  660. public void windowActivated(WindowEvent e) {
  661. WindowManager.setWindow(this);
  662. instance = this;
  663. }
  664. /** Overrides close() in PlugInFrame. */
  665. public void close() {
  666. boolean okayToClose = true;
  667. ImageJ ij = IJ.getInstance();
  668. if (!getTitle().equals("Errors") && changes && !IJ.isMacro() && ij!=null) {
  669. String msg = "Save changes to \"" + getTitle() + "\"?";
  670. YesNoCancelDialog d = new YesNoCancelDialog(this, "Editor", msg);
  671. if (d.cancelPressed())
  672. okayToClose = false;
  673. else if (d.yesPressed())
  674. save();
  675. }
  676. if (okayToClose) {
  677. //setVisible(false);
  678. dispose();
  679. WindowManager.removeWindow(this);
  680. nWindows--;
  681. instance = null;
  682. changes = false;
  683. }
  684. }
  685. public void saveAs() {
  686. String name1 = getTitle();
  687. if (name1.indexOf(".")==-1) name1 += ".txt";
  688. if (defaultDir==null) {
  689. if (name1.endsWith(".txt")||name1.endsWith(".ijm"))
  690. defaultDir = Menus.getMacrosPath();
  691. else
  692. defaultDir = Menus.getPlugInsPath();
  693. }
  694. SaveDialog sd = new SaveDialog("Save As...", defaultDir, name1, null);
  695. String name2 = sd.getFileName();
  696. String dir = sd.getDirectory();
  697. if (name2!=null) {
  698. if (name2.endsWith(".java"))
  699. updateClassName(name1, name2);
  700. path = dir+name2;
  701. save();
  702. changes = false;
  703. setWindowTitle(name2);
  704. setDefaultDirectory(dir);
  705. if (defaultDir!=null)
  706. Prefs.set(DEFAULT_DIR, defaultDir);
  707. if (Recorder.record)
  708. Recorder.record("saveAs", "Text", path);
  709. }
  710. }
  711. /** Changes a plugins class name to reflect a new file name. */
  712. public void updateClassName(String oldName, String newName) {
  713. if (newName.indexOf("_")<0)
  714. IJ.showMessage("Plugin Editor", "Plugins without an underscore in their name will not\n"
  715. +"be automatically installed when ImageJ is restarted.");
  716. if (oldName.equals(newName) || !oldName.endsWith(".java") || !newName.endsWith(".java"))
  717. return;
  718. oldName = oldName.substring(0,oldName.length()-5);
  719. newName = newName.substring(0,newName.length()-5);
  720. String text1 = ta.getText();
  721. int index = text1.indexOf("public class "+oldName);
  722. if (index<0)
  723. return;
  724. String text2 = text1.substring(0,index+13)+newName+text1.substring(index+13+oldName.length(),text1.length());
  725. ta.setText(text2);
  726. }
  727. void find(String s) {
  728. if (s==null) {
  729. GenericDialog gd = new GenericDialog("Find", this);
  730. gd.addStringField("Find: ", searchString, 20);
  731. String[] labels = {"Case Sensitive", "Whole Words"};
  732. boolean[] states = {caseSensitive, wholeWords};
  733. //boolean[] states = new boolean[2];
  734. //states[0]=caseSensitive; states[1]=wholeWords;
  735. gd.addCheckboxGroup(1, 2, labels, states);
  736. gd.showDialog();
  737. if (gd.wasCanceled())
  738. return;
  739. s = gd.getNextString();
  740. caseSensitive = gd.getNextBoolean();
  741. wholeWords = gd.getNextBoolean();
  742. Prefs.set(CASE_SENSITIVE, caseSensitive);
  743. }
  744. if (s.equals(""))
  745. return;
  746. String text = ta.getText();
  747. String s2 = s;
  748. if (!caseSensitive) {
  749. text = text.toLowerCase(Locale.US);
  750. s = s.toLowerCase(Locale.US);
  751. }
  752. int index = -1;
  753. if (wholeWords) {
  754. int position = ta.getCaretPosition()+1;
  755. while (true) {
  756. index = text.indexOf(s, position);
  757. if (index==-1) break;
  758. if (isWholeWordMatch(text, s, index)) break;
  759. position = index + 1;
  760. if (position>=text.length()-1)
  761. {index=-1; break;}
  762. }
  763. } else
  764. index = text.indexOf(s, ta.getCaretPosition()+1);
  765. searchString = s2;
  766. if (index<0)
  767. {IJ.beep(); return;}
  768. ta.setSelectionStart(index);
  769. ta.setSelectionEnd(index+s.length());
  770. }
  771. boolean isWholeWordMatch(String text, String word, int index) {
  772. char c = index==0?' ':text.charAt(index-1);
  773. if (Character.isLetterOrDigit(c) || c=='_') return false;
  774. c = index+word.length()>=text.length()?' ':text.charAt(index+word.length());
  775. if (Character.isLetterOrDigit(c) || c=='_') return false;
  776. return true;
  777. }
  778. void gotoLine() {
  779. GenericDialog gd = new GenericDialog("Go to Line", this);
  780. gd.addNumericField("Go to line number: ", lineNumber, 0);
  781. gd.showDialog();
  782. if (gd.wasCanceled())
  783. return;
  784. int n = (int)gd.getNextNumber();
  785. if (n<1) return;
  786. String text = ta.getText();
  787. char[] chars = new char[text.length()];
  788. chars = text.toCharArray();
  789. int count=1, loc=0;
  790. for (int i=0; i<chars.length; i++) {
  791. if (chars[i]=='\n') count++;
  792. if (count==n)
  793. {loc=i+1; break;}
  794. }
  795. ta.setCaretPosition(loc);
  796. lineNumber = n;
  797. }
  798. void zapGremlins() {
  799. String text = ta.getText();
  800. char[] chars = new char[text.length()];
  801. chars = text.toCharArray();
  802. int count=0;
  803. boolean inQuotes = false;
  804. char quoteChar = 0;
  805. for (int i=0; i<chars.length; i++) {
  806. char c = chars[i];
  807. if (!inQuotes && (c=='"' || c=='\'')) {
  808. inQuotes = true;
  809. quoteChar = c;
  810. } else {
  811. if (inQuotes && (c==quoteChar || c=='\n'))
  812. inQuotes = false;
  813. }
  814. if (!inQuotes && c!='\n' && c!='\t' && (c<32||c>127)) {
  815. count++;
  816. chars[i] = ' ';
  817. //IJ.log(""+(0+c));
  818. }
  819. }
  820. if (count>0) {
  821. text = new String(chars);
  822. ta.setText(text);
  823. }
  824. if (count>0)
  825. IJ.showMessage("Zap Gremlins", count+" invalid characters converted to spaces");
  826. else
  827. IJ.showMessage("Zap Gremlins", "No invalid characters found");
  828. }
  829. void selectAll() {
  830. ta.selectAll();
  831. }
  832. void changeFontSize(boolean larger) {
  833. int in = fontSize;
  834. if (larger) {
  835. fontSize++;
  836. if (fontSize==sizes.length)
  837. fontSize = sizes.length-1;
  838. } else {
  839. fontSize--;
  840. if (fontSize<0)
  841. fontSize = 0;
  842. }
  843. IJ.showStatus(sizes[fontSize]+" point");
  844. setFont();
  845. }
  846. void saveSettings() {
  847. Prefs.set(FONT_SIZE, fontSize);
  848. Prefs.set(FONT_MONO, monospaced.getState());
  849. IJ.showStatus("Font settings saved (size="+sizes[fontSize]+", monospaced="+monospaced.getState()+")");
  850. }
  851. void setFont() {
  852. ta.setFont(new Font(getFontName(), Font.PLAIN, sizes[fontSize]));
  853. }
  854. String getFontName() {
  855. return monospaced.getState()?"Monospaced":"SansSerif";
  856. }
  857. public void setFont(Font font) {
  858. ta.setFont(font);
  859. }
  860. public void append(String s) {
  861. ta.append(s);
  862. }
  863. public void setIsMacroWindow(boolean mw) {
  864. isMacroWindow = mw;
  865. }
  866. public static void setDefaultDirectory(String defaultDirectory) {
  867. defaultDir = defaultDirectory;
  868. if (defaultDir!=null && !(defaultDir.endsWith(File.separator)||defaultDir.endsWith("/")))
  869. defaultDir += File.separator;
  870. }
  871. //public void keyReleased(KeyEvent e) {}
  872. //public void keyTyped(KeyEvent e) {}
  873. public void lostOwnership (Clipboard clip, Transferable cont) {}
  874. public int debug(Interpreter interp, int mode) {
  875. if (IJ.debugMode)
  876. IJ.log("debug: "+interp.getLineNumber()+" "+mode+" "+interp);
  877. if (mode==Interpreter.RUN)
  878. return 0;
  879. if (!isVisible()) { // abort macro if user closes window
  880. interp.abortMacro();
  881. return 0;
  882. }
  883. if (!isActive())
  884. toFront();
  885. int n = interp.getLineNumber();
  886. if (n==previousLine)
  887. {previousLine=0; return 0;}
  888. previousLine = n;
  889. if (mode==Interpreter.RUN_TO_CARET) {
  890. if (n==runToLine) {
  891. mode = Interpreter.STEP;
  892. interp.setDebugMode(mode);
  893. } else
  894. return 0;
  895. }
  896. String text = ta.getText();
  897. if (IJ.isWindows() && !IJ.isVista())
  898. text = text.replaceAll("\r\n", "\n");
  899. char[] chars = new char[text.length()];
  900. chars = text.toCharArray();
  901. int count=1;
  902. debugStart=0;
  903. int len = chars.length;
  904. debugEnd = len;
  905. for (int i=0; i<len; i++) {
  906. if (chars[i]=='\n') count++;
  907. if (count==n && debugStart==0)
  908. debugStart=i+1;
  909. else if (count==n+1) {
  910. debugEnd=i;
  911. break;
  912. }
  913. }
  914. //IJ.log("debug: "+debugStart+" "+debugEnd+" "+len+" "+count);
  915. if (debugStart==1) debugStart = 0;
  916. if ((debugStart==0||debugStart==len) && debugEnd==len)
  917. return 0; // skip code added with Interpreter.setAdditionalFunctions()
  918. ta.select(debugStart, debugEnd);
  919. if (debugWindow!=null && !debugWindow.isShowing()) {
  920. interp.setEditor(null);
  921. debugWindow = null;
  922. } else
  923. debugWindow = interp.updateDebugWindow(interp.getVariables(), debugWindow);
  924. if (mode==Interpreter.STEP) {
  925. step = false;
  926. while (!step && !interp.done() && isVisible())
  927. IJ.wait(5);
  928. } else {
  929. if (mode==Interpreter.FAST_TRACE)
  930. IJ.wait(5);
  931. else
  932. IJ.wait(150);
  933. }
  934. return 0;
  935. }
  936. public static Editor getInstance() {
  937. return instance;
  938. }
  939. public static String getJSPrefix(String arg) {
  940. return JavaScriptIncludes+"function getArgument() {return \""+arg+"\";};";
  941. }
  942. /** Changes Mac OS 9 (CR) and Windows (CRLF) line separators to line feeds (LF). */
  943. public void fixLineEndings() {
  944. String text = ta.getText();
  945. text = text.replaceAll("\r\n", "\n");
  946. text = text.replaceAll("\r", "\n");
  947. ta.setText(text);
  948. }
  949. public boolean fileChanged() {
  950. return changes;
  951. }
  952. }