1 9 package bluej.editor.moe; 10 11 import bluej.editor.*; 12 import java.awt.*; 13 import java.awt.event.*; 14 import java.awt.print.PageFormat ; 15 import java.awt.print.PrinterJob ; 16 import java.io.*; 17 import java.net.URL ; 18 import java.util.*; 19 import java.util.List ; 20 21 import javax.swing.*; 22 import javax.swing.border.EmptyBorder ; 23 import javax.swing.event.*; 24 import javax.swing.text.*; 25 import javax.swing.text.html.HTMLDocument ; 26 import javax.swing.text.html.HTMLEditorKit ; 27 import javax.swing.text.html.HTMLFrameHyperlinkEvent ; 28 import javax.swing.undo.UndoManager ; 29 30 import org.syntax.jedit.tokenmarker.JavaTokenMarker; 31 32 import bluej.BlueJEvent; 33 import bluej.BlueJEventListener; 34 import bluej.Config; 35 import bluej.editor.EditorWatcher; 36 import bluej.pkgmgr.PkgMgrFrame; 37 import bluej.prefmgr.PrefMgr; 38 import bluej.utility.Debug; 39 import bluej.utility.DialogManager; 40 import bluej.utility.FileUtility; 41 import bluej.utility.Utility; 42 43 54 55 public final class MoeEditor extends JFrame 56 implements bluej.editor.Editor, BlueJEventListener, HyperlinkListener, DocumentListener 57 { 58 60 final static int version = 200; 62 final static String versionString = "2.0"; 63 64 final static Color textColor = new Color(0, 0, 0); final static Color textBgColor = Config.getItemColour("colour.text.bg"); final static Color cursorColor = new Color(255, 0, 100); 69 final static Color frameBgColor = new Color(196, 196, 196); 70 final static Color infoColor = new Color(240, 240, 240); 71 final static Color lightGrey = new Color(224, 224, 224); 72 final static Color selectionColour = Config.getSelectionColour(); 73 final static Color titleCol = Config.getItemColour("colour.text.fg"); 74 final static Color envOpColour = Config.getItemColour("colour.menu.environOp"); 75 76 final static Image iconImage = Config.getImageAsIcon("image.icon.editor").getImage(); 78 79 public static int printFontSize = Config.getDefaultPropInteger("bluej.fontsize.printText", 10); 81 public static Font printFont = new Font("Monospaced", Font.PLAIN, printFontSize); 82 83 String implementationString = Config.getString("editor.implementationLabel"); 85 String interfaceString = Config.getString("editor.interfaceLabel"); 86 87 final static String LabelSuffix = "Label"; 89 final static String ActionSuffix = "Action"; 90 final static String TooltipSuffix = "Tooltip"; 91 final static String AcceleratorSuffix = "Accelerator"; 92 93 final static String CRASHFILE_SUFFIX = "#"; 95 final static String BACKUP_SUFFIX = "~"; 96 97 final static String spaces = " "; 98 99 final static String COMPILED = "compiled"; 100 101 private static PageFormat pageFormat; 103 104 private static boolean matchBrackets = false; 105 106 108 private EditorWatcher watcher; 109 private Properties resources; 110 111 private AbstractDocument document; 112 private MoeSyntaxDocument sourceDocument; 113 private HTMLDocument htmlDocument; 114 115 private MoeActions actions; 116 public UndoManager undoManager; 117 public List undoComponents; public List redoComponents; 120 JEditorPane currentTextPane; private JEditorPane sourcePane; 123 private JEditorPane htmlPane; private MoeCaret moeCaret; 125 126 private Info info; private JPanel statusArea; private StatusLabel saveState; private JComboBox interfaceToggle; 130 private GoToLineDialog goToLineDialog; 131 132 private JScrollPane scrollPane; 133 private JComponent toolbar; 135 private String filename; private long lastModified; private String windowTitle; private String docFilename; 140 private boolean sourceIsCode; private boolean viewingHTML; 142 143 private int currentStepPos; private boolean mayHaveBreakpoints; private boolean ignoreChanges = false; 146 private boolean tabsAreExpanded = false; 147 148 private MoePrinter printer; 149 150 private TextInsertNotifier doTextInsert = new TextInsertNotifier(); 151 152 private ClassLoader projectClassLoader; 153 private HashMap propertyMap = new HashMap(); 154 155 157 159 162 private class MoeUndoableEditListener 163 implements UndoableEditListener 164 { 165 public void undoableEditHappened(UndoableEditEvent e) 166 { 167 undoManager.addEdit(e.getEdit()); 168 updateUndoControls(); 169 updateRedoControls(); 170 } 171 } 172 173 176 public MoeEditor(String title, boolean isCode, EditorWatcher watcher, boolean showToolbar, 177 boolean showLineNum, Properties resources, ClassLoader aProjectClassLoader) 178 { 179 super("Moe"); 180 this.watcher = watcher; 181 this.resources = resources; 182 filename = null; 183 windowTitle = title; 184 sourceIsCode = isCode; 185 viewingHTML = false; 186 currentStepPos = -1; 187 mayHaveBreakpoints = false; 188 matchBrackets = PrefMgr.getFlag(PrefMgr.MATCH_BRACKETS); 189 projectClassLoader = aProjectClassLoader; 190 undoManager = new UndoManager (); 191 undoComponents = new ArrayList(1); 192 redoComponents = new ArrayList(1); 193 194 initWindow(); 195 } 196 197 199 202 public void updateUndoControls() 203 { 204 boolean canUndo = undoManager.canUndo(); 205 Iterator i = undoComponents.iterator(); 206 while (i.hasNext()) { 207 ((JComponent) i.next()).setEnabled(canUndo); 208 } 209 } 210 211 214 public void updateRedoControls() 215 { 216 boolean canRedo = undoManager.canRedo(); 217 Iterator i = redoComponents.iterator(); 218 while (i.hasNext()) { 219 ((JComponent) i.next()).setEnabled(canRedo); 220 } 221 } 222 223 229 public ClassLoader getProjectClassLoader() 230 { 231 return projectClassLoader; 232 } 233 234 237 public boolean showFile(String filename, boolean compiled, String docFilename, Rectangle bounds) 239 { 240 this.filename = filename; 241 this.docFilename = docFilename; 242 243 if (bounds != null) { 244 setBounds(bounds); 245 } 246 247 boolean loaded = false; 248 boolean readError = false; 249 250 if (filename != null) { 251 252 try { 253 String crashFilename = filename + CRASHFILE_SUFFIX; 255 String backupFilename = crashFilename + "backup"; 256 File crashFile = new File(crashFilename); 257 if (crashFile.exists()) { 258 File backupFile = new File(backupFilename); 259 backupFile.delete(); 260 crashFile.renameTo(backupFile); 261 DialogManager.showMessage(this, "editor-crashed"); 262 } 263 264 FileReader reader = new FileReader(filename); 265 sourcePane.read(reader, null); 266 reader.close(); 267 File file = new File(filename); 268 lastModified = file.lastModified(); 269 270 sourceDocument = (MoeSyntaxDocument) sourcePane.getDocument(); 271 272 checkSyntaxStatus(); 274 275 sourceDocument.addDocumentListener(this); 276 sourceDocument.addUndoableEditListener(new MoeUndoableEditListener()); 277 document = sourceDocument; 278 loaded = true; 279 } 280 catch (FileNotFoundException ex) { 281 clear(); 282 } 283 catch (IOException ex) { 284 readError = true; 285 } 286 } 287 288 if (!loaded) return false; 290 291 303 if (loaded) 304 info.message(Config.getString("editor.info.version") + " " + versionString); 305 else if (readError) 306 info.warning(Config.getString("editor.info.readingProblem"), 307 Config.getString("editor.info.regularFile")); 308 else 309 info.message(Config.getString("editor.info.version" + versionString), 310 Config.getString("editor.info.newFile")); 311 312 setWindowTitle(); 313 sourcePane.setFont(PrefMgr.getStandardEditorFont()); 314 sourcePane.setSelectionColor(selectionColour); 315 316 setCompileStatus(compiled); 317 318 return true; 319 } 320 321 325 public void reloadFile() { 327 doReload(); 328 } 329 330 333 public void clear() { 335 ignoreChanges = true; 336 sourcePane.setText(""); 337 ignoreChanges = false; 338 } 339 340 349 public void insertText(String text, boolean caretBack) { 351 sourcePane.replaceSelection(text); 352 if (caretBack) { 353 sourcePane.setCaretPosition(sourcePane.getCaretPosition() - text.length()); 354 } 355 } 356 357 363 public void setVisible(boolean vis) { 365 if (vis) { 366 currentTextPane.setFont(PrefMgr.getStandardEditorFont()); 367 checkSyntaxStatus(); 368 checkBracketStatus(); 369 setState(Frame.NORMAL); toFront(); } 372 Utility.bringToFront(); 373 super.setVisible(vis); } 375 376 379 public void refresh() { 381 currentTextPane.setFont(PrefMgr.getStandardEditorFont()); 382 checkBracketStatus(); 383 checkSyntaxStatus(); 384 currentTextPane.repaint(); 385 } 386 387 392 public boolean isShowing() { 394 if (isVisible() != super.isShowing()) { 395 Debug.message("isVisible is not isShowing!"); 396 } 397 return super.isShowing(); 398 } 399 400 405 public void save() throws IOException 407 { 408 IOException failureException = null; 409 if (saveState.isChanged()) { 410 BufferedWriter writer = null; 411 try { 412 String crashFilename = filename + CRASHFILE_SUFFIX; 416 String backupFilename = filename + BACKUP_SUFFIX; 417 418 FileUtility.copyFile(filename, crashFilename); 420 421 writer = new BufferedWriter(new FileWriter(filename)); 422 sourcePane.write(writer); 423 writer.close(); 424 setSaved(); 425 File file = new File(filename); 426 lastModified = file.lastModified(); 427 428 if (PrefMgr.getFlag(PrefMgr.MAKE_BACKUP)) { 429 File crashFile = new File(crashFilename); 432 File backupFile = new File(backupFilename); 433 crashFile.renameTo(backupFile); 434 } 435 else { 436 File crashFile = new File(crashFilename); 437 crashFile.delete(); 438 } 439 } 440 catch (IOException ex) { 441 failureException = ex; 442 info.warning(Config.getString("editor.info.errorSaving") + " - " + ex.getLocalizedMessage()); 443 } 444 finally { 445 try { 446 if(writer != null) 447 writer.close(); 448 } 449 catch (IOException ex) { 450 failureException = ex; 451 } 452 } 453 } 454 455 if (failureException != null) { 458 info.warning(Config.getString("editor.info.errorSaving") 459 + " - " + failureException.getLocalizedMessage()); 460 throw failureException; 461 } 462 } 463 464 468 public void close() { 470 try { 471 save(); 472 } 473 catch (IOException ioe) {} 474 doClose(); 476 } 477 478 490 public void displayMessage(String message, int lineNumber, int column, boolean beep, 491 boolean setStepMark, String help) { 493 switchToSourceView(); 494 495 Element line = getLine(lineNumber); 496 int pos = line.getStartOffset(); 497 498 if (setStepMark) { 499 setStepMark(pos); 500 } 501 502 504 currentTextPane.setCaretPosition(pos); 505 currentTextPane.moveCaretPosition(line.getEndOffset() - 1); 506 moeCaret.setPersistentHighlight(); 507 509 511 if (beep) 512 info.warning(message); 513 else 514 info.message(message); 515 516 if (help != null) 517 info.setHelp(help); 518 } 519 520 528 public void setSelection(int lineNumber, int columnNumber, int len) 529 { 530 Element line = getLine(lineNumber); 531 532 currentTextPane.select(line.getStartOffset() + columnNumber - 1, 533 line.getStartOffset() + columnNumber + len - 1); 534 } 535 536 544 public void setSelection(int lineNumber1, int columnNumber1, int lineNumber2, int columnNumber2) 545 { 546 550 Element line1 = getLine(lineNumber1); 551 Element line2 = getLine(lineNumber2); 552 553 currentTextPane.select(line1.getStartOffset() + columnNumber1 - 1, line2.getStartOffset() + columnNumber2 - 1); 554 } 555 556 561 public String getSelectedText() 562 { 563 return currentTextPane.getSelectedText(); 564 } 565 566 571 public void removeStepMark() { 573 if (currentStepPos != -1) { 574 SimpleAttributeSet a = new SimpleAttributeSet(); 575 a.addAttribute(MoeSyntaxView.STEPMARK, Boolean.FALSE); 576 sourceDocument.setParagraphAttributes(currentStepPos, a); 577 currentStepPos = -1; 578 sourcePane.setCaretPosition(sourcePane.getCaretPosition()); 580 repaint(); 582 } 583 } 584 585 591 public void changeName(String title, String filename) { 593 this.filename = filename; 594 windowTitle = title; 596 setWindowTitle(); 597 } 598 599 604 public void setCompiled(boolean compiled) 605 { 606 setCompileStatus(compiled); 607 if (compiled) { 608 info.message(Config.getString("editor.info.compiled")); 609 } 610 } 611 612 615 public void removeBreakpoints() 616 { 617 EventQueue.invokeLater(new Runnable () { 621 public void run() 622 { 623 clearAllBreakpoints(); 624 } 625 }); 626 } 627 628 633 public boolean isModified() { 635 return (saveState.isChanged()); 636 } 637 638 643 public void setReadOnly(boolean readOnly) 644 { 645 if (readOnly) { 646 saveState.setState(StatusLabel.READONLY); 647 undoManager.discardAllEdits(); 648 updateUndoControls(); 649 updateRedoControls(); 650 } 651 currentTextPane.setEditable(!readOnly); 652 } 653 654 660 public boolean isReadOnly() 661 { 662 return !currentTextPane.isEditable(); 663 } 664 665 671 public void showInterface(boolean interfaceStatus) 672 { 673 interfaceToggle.setSelectedIndex(interfaceStatus ? 1 : 0); 674 } 675 676 682 public boolean isShowingInterface() 683 { 684 return viewingHTML; 685 } 686 687 690 private void checkForChangeOnDisk() 691 { 692 File file = new File(filename); 693 long modified = file.lastModified(); 694 if(modified != lastModified) { 695 if (saveState.isChanged()) { 696 int answer = DialogManager.askQuestion(this, "changed-on-disk"); 697 if (answer == 0) 698 doReload(); 699 else 700 lastModified = modified; } 702 else { 703 doReload(); 704 } 705 } 706 } 707 708 713 public LineColumn getCaretLocation() 714 { 715 int caretOffset = currentTextPane.getCaretPosition(); 716 return getLineColumnFromOffset(caretOffset); 717 } 718 719 727 public LineColumn getLineColumnFromOffset(int offset) 728 { 729 int lineNumber = document.getDefaultRootElement().getElementIndex(offset); 730 731 if (lineNumber < 0) { 732 return null; 733 } 734 735 Element lineElement = getLineAt(offset); 736 int column = offset - lineElement.getStartOffset(); 737 738 if (column < 0) { 739 return null; 740 } 741 742 return new LineColumn(lineNumber, column); 743 } 744 745 753 public void setCaretLocation(LineColumn location) 754 { 755 currentTextPane.setCaretPosition(getOffsetFromLineColumn(location)); 756 } 757 758 764 public LineColumn getSelectionBegin() 765 { 766 Caret aCaret = currentTextPane.getCaret(); 767 768 if (aCaret.getDot() == aCaret.getMark()) { 770 return null; 771 } 772 773 int beginOffset = Math.min(aCaret.getDot(), aCaret.getMark()); 774 775 return getLineColumnFromOffset(beginOffset); 776 } 777 778 783 public LineColumn getSelectionEnd() 784 { 785 Caret aCaret = currentTextPane.getCaret(); 786 787 if (aCaret.getDot() == aCaret.getMark()) { 789 return null; 790 } 791 792 int endOffset = Math.max(aCaret.getDot(), aCaret.getMark()); 793 794 return getLineColumnFromOffset(endOffset); 795 } 796 797 807 public String getText(LineColumn begin, LineColumn end) 808 { 809 int first = getOffsetFromLineColumn(begin); 810 int last = getOffsetFromLineColumn(end); 811 int beginOffset = Math.min(first, last); 812 int endOffset = Math.max(first, last); 813 814 try { 815 return document.getText(beginOffset, endOffset - beginOffset); 816 } 817 catch (BadLocationException exc) { 818 throw new IllegalArgumentException (exc.getMessage()); 819 } 820 } 821 822 836 public void setText(LineColumn begin, LineColumn end, String newText) 837 throws BadLocationException 838 { 839 int start = getOffsetFromLineColumn(begin); 840 int finish = getOffsetFromLineColumn(end); 841 842 int beginOffset = Math.min(start, finish); 843 int endOffset = Math.max(start, finish); 844 845 if (beginOffset != endOffset) { 846 document.remove(beginOffset, endOffset - beginOffset); 847 } 848 849 document.insertString(beginOffset, newText, null); 850 } 851 852 861 public void setSelection(LineColumn begin, LineColumn end) 862 { 863 int start = getOffsetFromLineColumn(begin); 864 int finish = getOffsetFromLineColumn(end); 865 866 int selectionStart = Math.min(start, finish); 867 int selectionEnd = Math.max(start, finish); 868 869 currentTextPane.setCaretPosition(selectionStart); 870 currentTextPane.moveCaretPosition(selectionEnd); 871 } 872 873 882 public int getOffsetFromLineColumn(LineColumn location) 883 { 884 if (location.getLine() < 0) { 885 throw new IllegalArgumentException ("line < 0"); 886 } 887 888 Element lineElement = document.getDefaultRootElement().getElement(location.getLine()); 889 if (lineElement == null) { 890 throw new IllegalArgumentException ("line=" + location.getLine() + " is out of bound"); 891 } 892 893 int lineOffset = lineElement.getStartOffset(); 894 895 if (location.getColumn() < 0) { 896 throw new IllegalArgumentException ("column < 0 "); 897 } 898 899 int lineLen = lineElement.getEndOffset() - lineOffset; 900 901 if (location.getColumn() >= lineLen) { 902 throw new IllegalArgumentException ("column=" + location.getColumn() + " greater than line len=" + lineLen); 903 } 904 905 return lineOffset + location.getColumn(); 906 } 907 908 914 public Object getProperty(String propertyKey) 915 { 916 return propertyMap.get(propertyKey); 917 } 918 919 920 927 public void setProperty(String propertyKey, Object value) 928 { 929 if ( propertyKey == null ) { 930 return; 931 } 932 933 propertyMap.put(propertyKey,value); 934 } 935 936 943 public int getLineLength(int line) 944 { 945 if (line < 0) { 946 return -1; 947 } 948 949 Element lineElement = document.getDefaultRootElement().getElement(line); 950 if (lineElement == null) { 951 return -1; 952 } 953 954 int startOffset = lineElement.getStartOffset(); 955 956 return lineElement.getEndOffset() - startOffset; 957 } 958 959 960 969 public int getTextLength () 970 { 971 return document.getLength(); 972 } 973 974 977 public int numberOfLines() 978 { 979 return document.getDefaultRootElement().getElementCount(); 980 } 981 982 983 987 989 993 public void blueJEvent(int eventId, Object arg) 994 { 995 switch(eventId) { 996 case BlueJEvent.DOCU_GENERATED : 997 BlueJEvent.removeListener(this); 998 displayInterface(true); 999 break; 1000 case BlueJEvent.DOCU_ABORTED : 1001 BlueJEvent.removeListener(this); 1002 info.warning(Config.getString("editor.info.docAborted")); 1003 break; 1004 } 1005 } 1006 1007 1009 1012 public void insertUpdate(DocumentEvent e) 1013 { 1014 if (!saveState.isChanged()) { 1015 saveState.setState(StatusLabel.CHANGED); 1016 setChanged(); 1017 } 1018 actions.userAction(); 1019 doTextInsert.setEvent(e, currentTextPane); 1020 SwingUtilities.invokeLater(doTextInsert); 1021 } 1022 1023 1026 public void removeUpdate(DocumentEvent e) 1027 { 1028 if (!saveState.isChanged()) { 1029 saveState.setState(StatusLabel.CHANGED); 1030 setChanged(); 1031 } 1032 actions.userAction(); 1033 } 1034 1035 1038 public void changedUpdate(DocumentEvent e) 1039 {} 1040 1041 1045 public void clearMessage() 1046 { 1047 info.clear(); 1048 } 1049 1050 1055 public void writeMessage(String msg) 1056 { 1057 info.message(msg); 1058 } 1059 1060 1066 public void writeWarningMessage(String msg) 1067 { 1068 info.warning(msg); 1069 } 1070 1071 1073 1076 public void userSave() 1077 { 1078 if (saveState.isSaved()) 1079 info.message(Config.getString("editor.info.noChanges")); 1080 else { 1081 try { 1082 save(); 1083 } 1084 catch (IOException ioe) {} 1085 } 1088 } 1089 1090 1093 public void reload() 1094 { 1095 if (filename == null) { 1096 info.warning(Config.getString("editor.info.cannotReload"), 1097 Config.getString("editor.info.reload")); 1098 } 1099 else if (saveState.isChanged()) { 1100 int answer = DialogManager.askQuestion(this, "really-reload"); 1101 if (answer == 0) 1102 doReload(); 1103 } 1104 else { 1105 doReload(); 1106 } 1107 } 1108 1109 1111 1116 public void print(PrinterJob printerJob) 1117 { 1118 PrintHandler pt = new PrintHandler(printerJob); 1119 pt.print(); 1120 } 1121 1122 1127 public void print() 1128 { 1129 PrinterJob job = PrinterJob.getPrinterJob(); 1131 1132 if(pageFormat == null) { 1134 pageFormat = PkgMgrFrame.getPageFormat(); 1135 } 1136 pageFormat = job.validatePage(pageFormat); 1137 if (job.printDialog()) { 1138 PrintHandler pt = new PrintHandler(job); 1139 Thread printJobThread = new Thread (pt); 1140 printJobThread.setPriority((Thread.currentThread().getPriority() - 1)); 1141 printJobThread.start(); 1142 } 1143 } 1144 1145 1150 public void pageSetup() 1151 { 1152 PrinterJob job = PrinterJob.getPrinterJob(); 1153 pageFormat = job.pageDialog(PkgMgrFrame.getPageFormat()); 1154 PkgMgrFrame.setPageFormat(pageFormat); 1155 } 1156 1157 1161 public void doClose() 1162 { 1163 setVisible(false); 1164 if (watcher != null) { 1165 watcher.closeEvent(this); 1166 } 1167 } 1168 1169 1176 public boolean checkExpandTabs() 1177 { 1178 if (tabsAreExpanded) 1179 return false; 1180 1181 else { 1182 tabsAreExpanded = true; 1183 return true; 1184 } 1185 } 1186 1187 1191 public void find() 1192 { 1193 Finder finder = MoeEditorManager.editorManager.getFinder(); 1194 finder.show(this, currentTextPane.getSelectedText(), false); 1195 } 1196 1197 1203 public void replace() 1204 { 1205 Finder finder = MoeEditorManager.editorManager.getFinder(); 1206 finder.show(this, currentTextPane.getSelectedText(), true); 1207 } 1208 1209 1213 public void findNext() 1214 { 1215 Finder finder = MoeEditorManager.editorManager.getFinder(); 1216 String s = currentTextPane.getSelectedText(); 1217 if (s == null) { 1218 s = finder.getSearchString(); 1219 if (s == null) { 1220 info.warning(DialogManager.getMessage("no-search-string")); 1221 return; 1222 } 1223 } 1224 findNextString(finder, s, false); 1225 } 1226 1227 1231 public void findNextBackward() 1232 { 1233 Finder finder = MoeEditorManager.editorManager.getFinder(); 1234 String s = currentTextPane.getSelectedText(); 1235 if (s == null) { 1236 s = finder.getSearchString(); 1237 if (s == null) { 1238 info.warning(DialogManager.getMessage("no-search-string")); 1239 return; 1240 } 1241 } 1242 findNextString(finder, s, true); 1243 } 1244 1245 1249 private void findNextString(Finder finder, String s, boolean backward) 1250 { 1251 boolean found = findString(s, backward, finder.getIgnoreCase(), 1252 finder.getWholeWord(), (!finder.getSearchFound())); 1253 1254 finder.setSearchString(s); 1255 finder.setSearchFound(found); 1256 } 1257 1258 1262 boolean findString(String s, boolean backward, boolean ignoreCase, 1263 boolean wholeWord, boolean wrap) 1264 { 1265 if (s.length() == 0) { 1266 info.warning(Config.getString("editor.info.emptySearchString")); 1267 return false; 1268 } 1269 1270 boolean found; 1271 if (backward) 1272 found = doFindBackward(s, ignoreCase, wholeWord, wrap); 1273 else 1274 found = doFind(s, ignoreCase, wholeWord, wrap); 1275 1276 StringBuffer msg = new StringBuffer (Config.getString("editor.find.find.label") + " "); 1277 msg.append(backward ? Config.getString("editor.find.backward") : Config.getString("editor.find.forward")); 1278 if (ignoreCase || wholeWord || wrap) 1279 msg.append(" ("); 1280 1281 if (ignoreCase) 1282 msg.append(Config.getString("editor.find.ignoreCase").toLowerCase() + ", "); 1283 1284 if (wholeWord) 1285 msg.append(Config.getString("editor.find.wholeWord").toLowerCase() + ", "); 1286 1287 if (wrap) 1288 msg.append(Config.getString("editor.find.wrapAround").toLowerCase() + ", "); 1289 1290 if (ignoreCase || wholeWord || wrap) 1291 msg.replace(msg.length() - 2, msg.length(), "): "); 1292 else 1293 msg.append(": "); 1294 1295 msg.append(s); 1296 1297 if (found) 1298 info.message(msg.toString()); 1299 else 1300 info.warning(msg.toString(), Config.getString("editor.info.notFound")); 1301 1302 return found; 1303 } 1304 1305 1309 boolean doFind(String s, boolean ignoreCase, boolean wholeWord, boolean wrap) 1310 { 1311 int docLength = document.getLength(); 1312 int startPosition = currentTextPane.getCaretPosition(); 1313 int endPos = docLength; 1314 1315 boolean found = false; 1316 boolean finished = false; 1317 1318 int start = startPosition; 1320 Element line = getLineAt(start); 1321 int lineEnd = Math.min(line.getEndOffset(), endPos); 1322 1323 try { 1325 while (!found && !finished) { 1326 String lineText = document.getText(start, lineEnd - start); 1327 if (lineText != null && lineText.length() > 0) { 1328 int foundPos = findSubstring(lineText, s, ignoreCase, wholeWord, false); 1329 if (foundPos != -1) { 1330 currentTextPane.select(start + foundPos, start + foundPos + s.length()); 1331 found = true; 1332 } 1333 } 1334 if (lineEnd >= endPos) { 1335 if (wrap) { 1336 endPos = startPosition; 1338 line = document.getParagraphElement(0); 1339 start = line.getStartOffset(); 1340 lineEnd = Math.min(line.getEndOffset(), endPos); 1341 wrap = false; 1342 } 1344 else { 1345 finished = true; 1346 } 1347 } 1348 else { 1349 line = document.getParagraphElement(lineEnd + 1); 1351 start = line.getStartOffset(); 1352 lineEnd = Math.min(line.getEndOffset(), endPos); 1353 } 1354 } 1355 } 1356 catch (BadLocationException ex) { 1357 Debug.message("error in editor find operation"); 1358 } 1359 return found; 1360 } 1361 1362 1367 boolean doFindBackward(String s, boolean ignoreCase, boolean wholeWord, boolean wrap) 1368 { 1369 int docLength = document.getLength(); 1370 int startPosition = currentTextPane.getCaretPosition() - 1; 1371 if (startPosition < 0) { 1372 startPosition = docLength; 1373 } 1374 int endPos = 0; 1376 boolean found = false; 1377 boolean finished = false; 1378 1379 int start = startPosition; Element line = getLineAt(start); 1381 int lineStart = Math.max(line.getStartOffset(), endPos); 1382 1383 try { 1384 while (!found && !finished) { 1385 String lineText = document.getText(lineStart, start - lineStart); 1386 if (lineText != null && lineText.length() > 0) { 1387 int foundPos = findSubstring(lineText, s, ignoreCase, wholeWord, true); 1388 if (foundPos != -1) { 1389 currentTextPane.select(lineStart + foundPos, lineStart + foundPos + s.length()); 1390 found = true; 1391 } 1392 } 1393 if (lineStart <= endPos) { if (wrap) { endPos = startPosition; 1396 line = document.getParagraphElement(docLength); 1397 start = line.getEndOffset(); 1398 lineStart = Math.max(line.getStartOffset(), endPos); 1399 wrap = false; } 1401 else { 1402 finished = true; 1403 } 1404 } 1405 else { line = document.getParagraphElement(lineStart - 1); 1407 start = line.getEndOffset(); 1408 lineStart = Math.max(line.getStartOffset(), endPos); 1409 } 1410 } 1411 } 1412 catch (BadLocationException ex) { 1413 Debug.reportError("error in editor find operation"); 1414 ex.printStackTrace(); 1415 } 1416 return found; 1417 } 1418 1419 1422 public void goToLine() 1423 { 1424 if (goToLineDialog == null) { 1425 goToLineDialog = new GoToLineDialog(this); 1426 } 1427 1428 DialogManager.centreDialog(goToLineDialog); 1429 goToLineDialog.showDialog(numberOfLines()); 1430 int newPosition = goToLineDialog.getLineNumber(); 1431 if (newPosition > 0) { 1432 setSelection(newPosition, 1, 0); 1433 } 1434 } 1435 1436 1449 private int findSubstring(String text, String sub, boolean ignoreCase, 1450 boolean wholeWord, boolean backwards) 1451 { 1452 int strlen = text.length(); 1453 int sublen = sub.length(); 1454 1455 if (sublen == 0) { 1456 return -1; 1457 } 1458 1459 if (!Character.isJavaIdentifierPart(sub.charAt(0)) || !Character.isJavaIdentifierPart(sub.charAt(sublen - 1))) { 1463 wholeWord = false; 1464 } 1465 1466 boolean found = false; 1467 int pos = (backwards ? strlen - sublen : 0); 1468 boolean itsOver = (backwards ? (pos < 0) : (pos + sublen > strlen)); 1469 1470 while (!found && !itsOver) { 1471 found = text.regionMatches(ignoreCase, pos, sub, 0, sublen); 1472 if (found && wholeWord) { 1473 found = ((pos == 0) || !Character.isJavaIdentifierPart(text.charAt(pos - 1))) 1474 && ((pos + sublen >= strlen) || !Character.isJavaIdentifierPart(text.charAt(pos + sublen))); 1475 } 1476 if (!found) { 1477 pos = (backwards ? pos - 1 : pos + 1); 1478 itsOver = (backwards ? (pos < 0) : (pos + sublen > strlen)); 1479 } 1480 } 1481 if (found) { 1482 return pos; 1483 } 1484 else { 1485 return -1; 1486 } 1487 } 1488 1489 1493 public void compile() 1494 { 1495 if (watcher == null) { 1496 return; 1497 } 1498 if (!viewingCode()) { 1499 info.warning(" "); 1500 return; 1501 } 1502 1503 info.message(Config.getString("editor.info.compiling")); 1504 watcher.compile(this); 1505 } 1506 1507 1512 public void toggleInterfaceMenu() 1513 { 1514 if (!sourceIsCode) 1515 return; 1516 1517 if (interfaceToggle.getSelectedIndex() == 0) 1518 interfaceToggle.setSelectedIndex(1); 1519 else 1520 interfaceToggle.setSelectedIndex(0); 1521 } 1522 1523 1528 public void toggleInterface() 1529 { 1530 if (!sourceIsCode) 1531 return; 1532 1533 boolean wantHTML = (interfaceToggle.getSelectedItem() == interfaceString); 1534 if (wantHTML && !viewingHTML) 1535 switchToInterfaceView(); 1536 else if (!wantHTML && viewingHTML) 1537 switchToSourceView(); 1538 } 1539 1540 1548 public void enablePrinting(boolean flag) 1549 { 1550 Action printAction = actions.getActionByName("print"); 1551 if (printAction != null) { 1552 printAction.setEnabled(flag); 1553 } 1554 Action pageSetupAction = actions.getActionByName("page-setup"); 1555 if (pageSetupAction != null) { 1556 pageSetupAction.setEnabled(flag); 1557 } 1558 1559 } 1560 1561 1565 private void switchToSourceView() 1566 { 1567 if (!viewingHTML) { 1568 return; 1569 } 1570 1571 enablePrinting(true); 1573 document = sourceDocument; 1574 currentTextPane = sourcePane; 1575 viewingHTML = false; 1576 scrollPane.setViewportView(currentTextPane); 1577 checkSyntaxStatus(); 1578 currentTextPane.requestFocus(); 1579 } 1580 1581 1586 private void switchToInterfaceView() 1587 { 1588 if (viewingHTML) { 1589 return; 1590 } 1591 1592 enablePrinting(false); 1594 try { 1595 save(); 1596 if (docUpToDate()) { 1597 displayInterface(false); 1598 } 1599 else { 1600 info.message(Config.getString("editor.info.generatingDoc")); 1602 BlueJEvent.addListener(this); 1603 watcher.generateDoc(); 1604 } 1605 } 1606 catch (IOException ioe) { 1607 } 1611 } 1612 1613 1619 private boolean docUpToDate() 1620 { 1621 try { 1622 File src = new File(filename); 1623 File doc = new File(docFilename); 1624 1625 if (!doc.exists() || (src.exists() && (src.lastModified() > doc.lastModified()))) { 1626 return false; 1627 } 1628 } 1629 catch (Exception e) { 1630 e.printStackTrace(); 1631 return false; 1632 } 1633 return true; 1634 } 1635 1636 1645 private void displayInterface(boolean reload) 1646 { 1647 info.message(Config.getString("editor.info.loadingDoc")); 1648 1649 Thread loadThread = new HTMLDisplayThread(reload); 1651 loadThread.start(); 1653 } 1654 1655 1658 public void createHTMLPane() 1659 { 1660 htmlPane = new JEditorPane(); 1661 htmlPane.setEditorKit(new HTMLEditorKit ()); 1662 htmlPane.setEditable(false); 1663 htmlPane.addHyperlinkListener(this); 1664 } 1665 1666 1670 public void hyperlinkUpdate(HyperlinkEvent e) 1671 { 1672 info.clear(); 1673 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { 1674 JEditorPane pane = (JEditorPane) e.getSource(); 1675 if (e instanceof HTMLFrameHyperlinkEvent ) { 1676 HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent ) e; 1677 HTMLDocument doc = (HTMLDocument ) pane.getDocument(); 1678 doc.processHTMLFrameHyperlinkEvent(evt); 1679 } 1680 else { 1681 try { 1682 pane.setPage(e.getURL()); 1683 } 1684 catch (Throwable t) { 1685 info.warning("cannot display hyperlink: " + e.getURL()); 1686 Debug.reportError("hyperlink failed: " + t); 1687 } 1688 } 1689 } 1690 } 1691 1692 1696 public void toggleBreakpoint() 1697 { 1698 if (!viewingCode()) { 1699 info.warning(" "); return; 1701 } 1702 toggleBreakpoint(sourcePane.getCaretPosition()); 1703 } 1704 1705 1709 public void toggleBreakpoint(int pos) 1710 { 1711 if (positionHasBreakpoint(pos)) 1712 setUnsetBreakpoint(pos, false); else 1714 setUnsetBreakpoint(pos, true); } 1716 1717 1721 private void clearAllBreakpoints() 1722 { 1723 if (mayHaveBreakpoints) { 1724 1725 for (int i = 1; i <= numberOfLines(); i++) { 1726 if (lineHasBreakpoint(i)) { 1727 doRemoveBreakpoint(getPositionInLine(i)); 1728 } 1729 } 1730 mayHaveBreakpoints = false; 1731 } 1732 } 1733 1734 1738 private boolean positionHasBreakpoint(int pos) 1739 { 1740 Element line = getLineAt(pos); 1741 return Boolean.TRUE.equals(line.getAttributes().getAttribute(MoeSyntaxView.BREAKPOINT)); 1742 } 1743 1744 1748 private boolean lineHasBreakpoint(int lineNo) 1749 { 1750 Element line = getLine(lineNo); 1751 return (Boolean.TRUE.equals(line.getAttributes().getAttribute(MoeSyntaxView.BREAKPOINT))); 1752 } 1753 1754 1759 private void setUnsetBreakpoint(int pos, boolean set) 1760 { 1761 if (watcher != null) { 1762 int line = getLineNumberAt(pos); 1763 String result = watcher.breakpointToggleEvent(this, line, set); 1764 1765 if (result == null) { 1766 SimpleAttributeSet a = new SimpleAttributeSet(); 1768 if (set) { 1769 a.addAttribute(MoeSyntaxView.BREAKPOINT, Boolean.TRUE); 1770 mayHaveBreakpoints = true; 1771 } 1772 else { 1773 a.addAttribute(MoeSyntaxView.BREAKPOINT, Boolean.FALSE); 1774 } 1775 1776 sourceDocument.setParagraphAttributes(pos, a); 1777 } 1778 else { 1779 info.warning(result); 1780 } 1781 1782 repaint(); 1784 } 1785 else { 1786 info.warning(Config.getString("editor.info.cannotSetBreak")); 1787 } 1788 1789 } 1790 1791 1795 private void doRemoveBreakpoint(int pos) 1796 { 1797 SimpleAttributeSet a = new SimpleAttributeSet(); 1798 a.addAttribute(MoeSyntaxView.BREAKPOINT, Boolean.FALSE); 1799 sourceDocument.setParagraphAttributes(pos, a); 1800 repaint(); 1801 } 1802 1803 1810 private void setStepMark(int pos) 1811 { 1812 removeStepMark(); 1813 SimpleAttributeSet a = new SimpleAttributeSet(); 1814 a.addAttribute(MoeSyntaxView.STEPMARK, Boolean.TRUE); 1815 sourceDocument.setParagraphAttributes(pos, a); 1816 currentStepPos = pos; 1817 repaint(); 1819 } 1820 1821 1823 1827 private boolean viewingCode() 1828 { 1829 return sourceIsCode && (!viewingHTML); 1830 } 1831 1832 1833 1837 1842 1846 private Element getLine(int lineNo) 1847 { 1848 return document.getDefaultRootElement().getElement(lineNo - 1); 1849 } 1850 1851 1855 private Element getLineAt(int pos) 1856 { 1857 return document.getParagraphElement(pos); 1858 } 1859 1860 1864 private int getPositionInLine(int lineNo) 1865 { 1866 return getLine(lineNo).getStartOffset(); 1867 } 1868 1869 1873 1879 1883 private int getLineNumberAt(int pos) 1884 { 1885 return document.getDefaultRootElement().getElementIndex(pos) + 1; 1886 } 1887 1888 1893 public void doReload() 1894 { 1895 FileReader reader = null; 1896 try { 1897 reader = new FileReader(filename); 1898 sourcePane.read(reader, null); 1899 reader.close(); 1900 File file = new File(filename); 1901 lastModified = file.lastModified(); 1902 1903 sourceDocument = (MoeSyntaxDocument) sourcePane.getDocument(); 1904 if(!viewingHTML) 1905 document = sourceDocument; 1906 1907 checkSyntaxStatus(); 1910 sourceDocument.addDocumentListener(this); 1911 sourceDocument.addUndoableEditListener(new MoeUndoableEditListener()); 1912 1913 saveState.setState(StatusLabel.SAVED); 1917 setChanged(); setSaved(); } 1920 catch (FileNotFoundException ex) { 1921 info.warning(Config.getString("editor.info.fileDisappeared")); 1922 } 1923 catch (IOException ex) { 1924 info.warning(Config.getString("editor.info.fileReadError")); 1925 setChanged(); 1926 } 1927 finally { 1928 try { 1929 if (reader != null) 1930 reader.close(); 1931 } 1932 catch (IOException ioe) {} 1933 } 1934 } 1935 1936 1941 private void checkSyntaxStatus() 1942 { 1943 if (sourceDocument != null) { 1944 1945 if (viewingCode() && PrefMgr.getFlag(PrefMgr.HILIGHTING)) { 1948 if (sourceDocument.getTokenMarker() == null) { 1949 sourceDocument.setTokenMarker(new JavaTokenMarker()); 1950 } 1951 } 1952 else { 1953 sourceDocument.setTokenMarker(null); 1954 } 1955 } 1956 } 1958 1959 1964 private void checkBracketStatus() 1965 { 1966 matchBrackets = PrefMgr.getFlag(PrefMgr.MATCH_BRACKETS); 1967 if (matchBrackets) 1971 doBracketMatch(); 1972 else 1973 moeCaret.removeBracket(); 1974 } 1975 1976 1981 public boolean matchBrackets() 1982 { 1983 return matchBrackets; 1984 } 1985 1986 1991 private void setCompileStatus(boolean compiled) 1992 { 1993 actions.getActionByName("toggle-breakpoint").setEnabled(compiled && viewingCode()); 1994 if (compiled) 1995 document.putProperty(COMPILED, Boolean.TRUE); 1996 else 1997 document.putProperty(COMPILED, Boolean.FALSE); 1998 1999 currentTextPane.repaint(); 2000 } 2001 2002 2006 private void setSaved() 2007 { 2008 info.message(Config.getString("editor.info.saved")); 2009 saveState.setState(StatusLabel.SAVED); 2010 if (watcher != null) { 2011 watcher.saveEvent(this); 2012 } 2013 } 2014 2015 2019 private void setChanged() 2020 { 2021 if (ignoreChanges) { 2022 return; 2023 } 2024 setCompileStatus(false); 2025 if (watcher != null) { 2026 watcher.modificationEvent(this); 2027 } 2028 } 2029 2030 2034 void caretMoved() 2035 { 2036 clearMessage(); 2037 if (matchBrackets) { 2038 doBracketMatch(); 2039 } 2040 actions.userAction(); 2041 } 2042 2043 2049 public int getBracketMatch() 2050 { 2051 int pos = -1; 2052 try { 2053 int caretPos = sourcePane.getCaretPosition(); 2054 if (caretPos != 0) { 2055 caretPos--; 2056 } 2057 pos = TextUtilities.findMatchingBracket(sourceDocument, caretPos); 2058 } 2059 catch (BadLocationException ble) { 2060 Debug.reportError("Bad document location reached while trying to match brackets"); 2061 } 2062 return pos; 2063 } 2064 2065 2068 private void doBracketMatch() 2069 { 2070 Caret caret = sourcePane.getCaret(); 2071 if (caret instanceof MoeCaret) { 2072 ((MoeCaret) caret).paintMatchingBracket(); 2073 } 2074 } 2075 2076 2079 private void setWindowTitle() 2080 { 2081 String title = windowTitle; 2082 2083 if (title == null) { 2084 if (filename == null) 2085 title = "Moe: <no name>"; 2086 else 2087 title = "Moe: " + filename; 2088 } 2089 setTitle(title); 2090 } 2091 2092 2096 private String getDocPath() 2097 { 2098 return docFilename; 2099 } 2100 2101 2103 2106 private String getResource(String name) 2107 { 2108 return resources.getProperty(name); 2109 } 2110 2111 2113 2116 private String [] tokenize(String input) 2117 { 2118 List list = new ArrayList(); 2119 StringTokenizer t = new StringTokenizer(input); 2120 String tokens[]; 2121 2122 while (t.hasMoreTokens()) { 2123 list.add(t.nextToken()); 2124 } 2125 2126 tokens = new String [list.size()]; 2127 list.toArray(tokens); 2128 return tokens; 2129 } 2130 2131 2133 2137 private void initWindow() 2138 { 2139 setIconImage(iconImage); 2140 2141 2143 JPanel contentPane = new JPanel(new BorderLayout(5, 5)); 2144 contentPane.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 6)); 2145 setContentPane(contentPane); 2146 2147 2149 JPanel bottomArea = new JPanel(); 2150 2151 bottomArea.setLayout(new BorderLayout(5, 5)); 2153 2154 info = new Info(); 2155 bottomArea.add(info, BorderLayout.CENTER); 2156 2157 statusArea = new JPanel(); 2158 statusArea.setLayout(new GridLayout(0, 1)); 2159 statusArea.setBackground(infoColor); 2161 statusArea.setBorder(BorderFactory.createLineBorder(Color.black)); 2162 2163 saveState = new StatusLabel(StatusLabel.SAVED); 2164 statusArea.add(saveState); 2165 bottomArea.add(statusArea, BorderLayout.EAST); 2166 2167 contentPane.add(bottomArea, BorderLayout.SOUTH); 2168 2169 2171 sourceDocument = new MoeSyntaxDocument(); 2172 sourceDocument.addDocumentListener(this); 2173 sourceDocument.addUndoableEditListener(new MoeUndoableEditListener()); 2174 2175 2177 MoeSyntaxEditorKit kit = new MoeSyntaxEditorKit(false); 2178 sourcePane = new MoeEditorPane(); 2179 2180 sourcePane.setDocument(sourceDocument); 2181 sourcePane.setCaretPosition(0); 2182 sourcePane.setMargin(new Insets(2, 2, 2, 2)); 2183 sourcePane.setOpaque(true); 2184 sourcePane.setEditorKit(kit); 2185 moeCaret = new MoeCaret(this); 2186 sourcePane.setCaret(moeCaret); 2187 sourcePane.setBackground(textBgColor); 2188 sourcePane.setCaretColor(cursorColor); 2190 2191 document = sourceDocument; 2193 currentTextPane = sourcePane; 2194 2195 scrollPane = new JScrollPane(currentTextPane); 2196 scrollPane.setPreferredSize(new Dimension(598, 400)); 2197 scrollPane.getVerticalScrollBar().setUnitIncrement(16); 2198 2199 contentPane.add(scrollPane, BorderLayout.CENTER); 2200 2201 2203 actions = MoeActions.getActions(sourcePane); 2204 2205 actions.getActionByName("show-manual").setEnabled(false); 2207 2209 2211 JMenuBar menubar = createMenuBar(); 2212 setJMenuBar(menubar); 2213 2214 2216 toolbar = createToolbar(); 2217 contentPane.add(toolbar, BorderLayout.NORTH); 2218 2219 2221 addWindowListener(new WindowAdapter() { 2222 public void windowClosing(WindowEvent e) { 2223 close(); 2224 } 2225 public void windowActivated(WindowEvent e) { 2226 checkForChangeOnDisk(); 2227 } 2228 }); 2229 2230 setFocusTraversalPolicy(new MoeFocusTraversalPolicy()); 2231 2232 setWindowTitle(); 2233 pack(); 2234 } 2235 2236 2238 2241 private JMenuBar createMenuBar() 2242 { 2243 JMenuBar menubar = new JMenuBar(); 2244 JMenu menu = null; 2245 2246 String [] menuKeys = tokenize(getResource("menubar")); 2247 for (int i = 0; i < menuKeys.length; i++) { 2248 menu = createMenu(menuKeys[i]); 2249 if (menu != null) { 2250 menubar.add(menu); 2251 } 2252 } 2253 return menubar; 2254 } 2255 2256 2258 2262 private JMenu createMenu(String key) 2263 { 2264 JMenuItem item; 2265 String label; 2266 2267 JMenu menu = new JMenu(Config.getString("editor." + key + LabelSuffix)); 2269 2270 String itemString = getResource(key); 2272 if (itemString == null) { 2273 Debug.message("Moe: cannot find menu definition for " + key); 2274 return null; 2275 } 2276 2277 String [] itemKeys = tokenize(itemString); 2279 2280 for (int i = 0; i < itemKeys.length; i++) { 2282 if (itemKeys[i].equals("-")) { 2283 menu.addSeparator(); 2284 } 2285 else { 2286 Action action = actions.getActionByName(itemKeys[i]); 2287 if (action == null) { 2288 Debug.message("Moe: cannot find action " + itemKeys[i]); 2289 } 2290 else { 2291 item = menu.add(action); 2292 if (action == actions.undoAction) { 2293 undoComponents.add(item); 2294 } 2295 if (action == actions.redoAction) { 2296 redoComponents.add(item); 2297 } 2298 label = Config.getString("editor." + itemKeys[i] + LabelSuffix); 2299 if (label != null) { 2300 item.setText(label); 2301 } 2302 KeyStroke[] keys = actions.getKeyStrokesForAction(action); 2303 if (keys != null) { 2304 item.setAccelerator(chooseKey(keys)); 2305 } 2306 } 2307 } 2308 } 2309 return menu; 2310 } 2311 2312 2315 private KeyStroke chooseKey(KeyStroke[] keys) 2316 { 2317 if (keys.length == 1) { 2318 return keys[0]; 2319 } 2320 else { 2321 KeyStroke key = keys[0]; 2322 for (int i = 1; i < keys.length; i++) { 2325 if (keys[i].getKeyCode() >= 'A' && keys[i].getKeyCode() <= 'Z') { 2326 key = keys[i]; 2327 } 2328 } 2329 return key; 2330 } 2331 } 2332 2333 2335 2340 private JComponent createToolbar() 2341 { 2342 JPanel toolbar = new JPanel(); 2343 toolbar.setLayout(new BoxLayout(toolbar, BoxLayout.X_AXIS)); 2344 2346 String [] toolKeys = tokenize(getResource("toolbar")); 2347 for (int i = 0; i < toolKeys.length; i++) { 2348 toolbar.add(createToolbarButton(toolKeys[i], false)); 2349 toolbar.add(Box.createHorizontalStrut(4)); 2350 } 2351 2352 toolbar.add(Box.createHorizontalGlue()); 2353 toolbar.add(Box.createHorizontalGlue()); 2354 toolbar.add(createInterfaceSelector()); 2355 2356 return toolbar; 2357 } 2358 2359 2361 2364 private AbstractButton createToolbarButton(String key, boolean isToggle) 2365 { 2366 String label = Config.getString("editor." + key + LabelSuffix); 2367 AbstractButton button; 2368 2369 if (isToggle) 2370 button = new JToggleButton(label); 2371 else 2372 button = new JButton(label); 2373 2374 button.setRequestFocusEnabled(false); 2375 2377 Insets margin = button.getMargin(); 2378 button.setMargin(new Insets(margin.top, 3, margin.bottom, 3)); 2379 2380 button.setFont(PrefMgr.getStandardFont()); 2381 2382 String actionName = getResource(key + ActionSuffix); 2383 if (actionName == null) { 2384 actionName = key; 2385 } 2386 Action action = actions.getActionByName(actionName); 2387 if (action != null) { if (action == actions.undoAction) { 2389 undoComponents.add(button); 2390 button.setEnabled(false); 2391 } 2392 if (action == actions.redoAction) { 2393 redoComponents.add(button); 2394 button.setEnabled(false); 2395 } 2396 button.addActionListener(action); 2397 button.setActionCommand(actionName); 2398 } 2399 else { 2400 button.setEnabled(false); 2401 Debug.message("Moe: action not found for button " + label); 2402 } 2403 2404 button.putClientProperty("JButton.buttonType", "toolbar"); 2406 2407 return button; 2408 } 2409 2410 2412 2415 private JComboBox createInterfaceSelector() 2416 { 2417 String [] choiceStrings = {implementationString, interfaceString}; 2418 interfaceToggle = new JComboBox(choiceStrings); 2419 2420 interfaceToggle.setRequestFocusEnabled(false); 2421 interfaceToggle.setFont(PrefMgr.getStandardFont()); 2422 interfaceToggle.setBorder(new EmptyBorder (2, 2, 2, 2)); 2423 interfaceToggle.setForeground(envOpColour); 2424 2425 String actionName = "toggle-interface-view"; 2426 Action action = actions.getActionByName(actionName); 2427 if (action != null) { interfaceToggle.setAction(action); 2429 } 2430 else { 2431 interfaceToggle.setEnabled(false); 2432 Debug.message("Moe: action not found: " + actionName); 2433 } 2434 if (!sourceIsCode) { 2435 interfaceToggle.setEnabled(false); 2436 } 2437 return interfaceToggle; 2438 } 2439 2440 2442 2448 class PrintHandler 2449 implements Runnable 2450 { 2451 PrinterJob printJob; 2452 2453 2456 public PrintHandler(PrinterJob pj) 2457 { 2458 super(); 2459 printJob = pj; 2460 } 2461 2462 2465 public void run() 2466 { 2467 print(); 2468 } 2469 2470 2473 public void print() 2474 { 2475 if (printer == null) { 2476 printer = new MoePrinter(); 2477 } 2478 2479 info.message(Config.getString("editor.info.printing")); 2481 if (printer.printDocument(printJob, sourceDocument, windowTitle, printFont, pageFormat)) { 2482 info.message(Config.getString("editor.info.printed")); 2483 } 2484 else { 2485 info.message(Config.getString("editor.info.cancelled")); 2486 } 2487 2488 } 2489 2490 } 2491 2492 2494 2497 class HTMLDisplayThread extends Thread 2498 { 2499 private boolean reload; 2500 2501 2503 HTMLDisplayThread(boolean load) 2504 { 2505 reload = load; 2506 } 2507 2508 2511 public void run() 2512 { 2513 if (htmlDocument == null) { 2514 createHTMLPane(); 2515 reload = true; 2516 } 2517 2518 if (reload) { 2519 try { 2520 try { 2521 htmlPane.setPage("file:/dummy"); 2524 } 2525 catch (Exception e) {} 2526 2527 File urlFile = new File(getDocPath()); 2528 URL myURL = urlFile.toURI().toURL(); 2529 htmlPane.setPage(myURL); 2530 htmlDocument = (HTMLDocument ) htmlPane.getDocument(); 2531 htmlDocument.setBase(myURL); 2532 info.message(Config.getString("editor.info.docLoaded")); 2533 } 2534 catch (Exception exc) { 2535 info.warning(Config.getString("editor.info.docDisappeared"), getDocPath()); 2536 Debug.reportError("loading class interface failed: " + exc); 2537 } 2538 } 2539 document = htmlDocument; 2540 currentTextPane = htmlPane; 2541 viewingHTML = true; 2542 scrollPane.setViewportView(currentTextPane); 2543 currentTextPane.requestFocus(); 2544 } 2545 2546 } 2547 2548 2550 2553 class TextInsertNotifier 2554 implements Runnable 2555 { 2556 private DocumentEvent evt; 2557 private JEditorPane editorPane; 2558 2559 2562 public void setEvent(DocumentEvent e, JEditorPane editorPane) 2563 { 2564 evt = e; 2565 this.editorPane = editorPane; 2566 } 2567 2568 2571 public void run() 2572 { 2573 actions.textInsertAction(evt, editorPane); 2574 } 2575 } 2576 2577 2581 class MoeFocusTraversalPolicy extends FocusTraversalPolicy 2582 { 2583 public Component getComponentAfter(Container focusCycleRoot, Component aComponent) { 2584 return currentTextPane; 2585 } 2586 2587 public Component getComponentBefore(Container focusCycleRoot, Component aComponent) { 2588 return currentTextPane; 2589 } 2590 2591 public Component getDefaultComponent(Container focusCycleRoot) { 2592 return currentTextPane; 2593 } 2594 2595 public Component getFirstComponent(Container focusCycleRoot) { 2596 return currentTextPane; 2597 } 2598 2599 public Component getInitialComponent(Window window) { 2600 return currentTextPane; 2601 } 2602 2603 public Component getLastComponent(Container focusCycleRoot) { 2604 return currentTextPane; 2605 } 2606 } 2607} 2608 | Popular Tags |