1 33 34 package edu.rice.cs.drjava.ui; 35 36 import javax.swing.*; 37 import javax.swing.undo.*; 38 import javax.swing.event.*; 39 import javax.swing.text.*; 40 import java.awt.*; 41 import java.awt.event.*; 42 import java.util.List ; 43 import java.util.LinkedList ; 44 45 import edu.rice.cs.plt.tuple.Pair; 47 import edu.rice.cs.util.UnexpectedException; 48 import edu.rice.cs.util.OperationCanceledException; 49 import edu.rice.cs.util.swing.HighlightManager; 50 import edu.rice.cs.util.swing.RightClickMouseAdapter; 51 import edu.rice.cs.util.text.SwingDocument; 52 import edu.rice.cs.drjava.model.*; 53 import edu.rice.cs.drjava.model.definitions.CompoundUndoManager; 54 import edu.rice.cs.drjava.model.definitions.DefinitionsEditorKit; 55 import edu.rice.cs.drjava.model.definitions.NoSuchDocumentException; 56 import edu.rice.cs.drjava.model.definitions.indent.Indenter; 57 import edu.rice.cs.drjava.model.definitions.reducedmodel.ReducedModelState; 58 import edu.rice.cs.drjava.config.*; 59 import edu.rice.cs.drjava.DrJava; 60 import edu.rice.cs.drjava.CodeStatus; 61 import edu.rice.cs.drjava.model.debug.Breakpoint; 62 63 67 public class DefinitionsPane extends AbstractDJPane implements Finalizable<DefinitionsPane> { 68 69 70 private static DefinitionsEditorKit EDITOR_KIT; 71 72 73 private static int INDENT_WARNING_THRESHOLD = 20000; 74 75 76 private final MainFrame _mainFrame; 77 78 private final OpenDefinitionsDocument _doc; 79 80 private volatile UndoAction _undoAction; 81 private volatile RedoAction _redoAction; 82 private volatile boolean testVariable; 85 88 private volatile boolean _hasWarnedAboutModified = false; 89 90 93 94 private volatile boolean _antiAliasText = false; 95 96 97 private volatile HighlightManager.HighlightInfo _errorHighlightTag = null; 98 99 100 static volatile ReverseHighlighter.DefaultUnderlineHighlightPainter BOOKMARK_PAINTER = 101 new ReverseHighlighter.DefaultUnderlineHighlightPainter(DrJava.getConfig().getSetting(BOOKMARK_COLOR), 3); 102 103 104 static volatile ReverseHighlighter.DefaultUnderlineHighlightPainter[] FIND_RESULTS_PAINTERS; 105 106 static { 107 FIND_RESULTS_PAINTERS = new ReverseHighlighter.DefaultUnderlineHighlightPainter[FIND_RESULTS_COLORS.length+1]; 108 for(int i = 0; i < FIND_RESULTS_COLORS.length; ++i) { 109 FIND_RESULTS_PAINTERS[i] = 110 new ReverseHighlighter.DefaultUnderlineHighlightPainter(DrJava.getConfig().getSetting(FIND_RESULTS_COLORS[i]), 3); 111 } 112 FIND_RESULTS_PAINTERS[FIND_RESULTS_COLORS.length] = 113 new ReverseHighlighter.DefaultUnderlineHighlightPainter(Color.WHITE, 0); 114 } 115 116 117 static volatile int[] FIND_RESULTS_PAINTERS_USAGE = new int[FIND_RESULTS_COLORS.length]; 118 119 120 static ReverseHighlighter.DefaultHighlightPainter BREAKPOINT_PAINTER = 121 new ReverseHighlighter.DefaultHighlightPainter(DrJava.getConfig().getSetting(DEBUG_BREAKPOINT_COLOR)); 122 123 124 static volatile ReverseHighlighter.DefaultHighlightPainter DISABLED_BREAKPOINT_PAINTER = 125 new ReverseHighlighter.DefaultHighlightPainter(DrJava.getConfig().getSetting(DEBUG_BREAKPOINT_DISABLED_COLOR)); 126 127 128 static volatile ReverseHighlighter.DefaultHighlightPainter THREAD_PAINTER = 129 new ReverseHighlighter.DefaultHighlightPainter(DrJava.getConfig().getSetting(DEBUG_THREAD_COLOR)); 130 131 132 public static final String INDENT_KEYMAP_NAME = "INDENT_KEYMAP"; 133 134 135 protected void _updateMatchHighlight() { 136 int to = getCaretPosition(); 137 int from = _doc.balanceBackward(); if (from > -1) { 139 from = to - from; 141 _addHighlight(from, to); 142 144 String matchText = _matchText(from); 145 146 if (matchText != null) _mainFrame.updateFileTitle("Matches: " + matchText); 147 else _mainFrame.updateFileTitle(); 148 } 149 150 else { 152 from = to; 154 155 to = _doc.balanceForward(); 156 if (to > -1) { 157 to = to + from; 158 _addHighlight(from - 1, to); 159 } 161 _mainFrame.updateFileTitle(); 162 } 163 } 164 165 166 private String _matchText(int braceIndex) { 167 DJDocument doc = _doc; 168 String docText; 169 docText = doc.getText(); 170 171 if (docText.charAt(braceIndex) == '{') { Character charBefore = null; 173 int charBeforeIndex = braceIndex-1; 174 boolean previousLine = false; 175 176 if (charBeforeIndex != -1) charBefore = docText.charAt(charBeforeIndex); 177 178 charBeforeIndex--; 179 180 while (charBeforeIndex >= 0 && (charBefore == '\n' || charBefore == ' ')) { 181 charBefore = docText.charAt(charBeforeIndex); 182 if (!previousLine && charBefore != '\n' && charBefore != ' ') charBeforeIndex = braceIndex-1; 183 if (charBefore == '\n') previousLine = true; 184 charBeforeIndex--; 185 } 186 187 final StringBuilder returnText = new StringBuilder (docText.substring(0, charBeforeIndex+2)); 188 if (previousLine) returnText.append("..."); 189 returnText.append("{"); 190 191 int lastNewLineIndex = returnText.lastIndexOf("\n"); 192 return returnText.substring(lastNewLineIndex+1); 193 } 194 else return null; 196 } 197 198 199 private class MatchColorOptionListener implements OptionListener<Color> { 200 public void optionChanged(OptionEvent<Color> oce) { 201 MATCH_PAINTER = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 202 if (_matchHighlight != null) { 203 int start = _matchHighlight.getStartOffset(); 204 int end = _matchHighlight.getEndOffset(); 205 _matchHighlight.remove(); 206 _addHighlight(start, end); 207 } 208 } 209 } 210 211 212 private class ErrorColorOptionListener implements OptionListener<Color> { 213 public void optionChanged(OptionEvent<Color> oce) { 214 ERROR_PAINTER = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 215 if (_errorHighlightTag != null) { 216 int start = _errorHighlightTag.getStartOffset(); 217 int end = _errorHighlightTag.getEndOffset(); 218 _errorHighlightTag.remove(); 219 addErrorHighlight(start, end); 220 } 221 } 222 } 223 224 225 private class BookmarkColorOptionListener implements OptionListener<Color> { 226 public void optionChanged(OptionEvent<Color> oce) { 227 BOOKMARK_PAINTER = new ReverseHighlighter.DefaultUnderlineHighlightPainter(oce.value, BOOKMARK_PAINTER.getThickness()); 228 _mainFrame.refreshBookmarkHighlightPainter(); 229 } 230 } 231 232 233 private class FindResultsColorOptionListener implements OptionListener<Color> { 234 private int _index; 235 public FindResultsColorOptionListener(int i) { _index = i; } 236 public void optionChanged(OptionEvent<Color> oce) { 237 FIND_RESULTS_PAINTERS[_index] = 238 new ReverseHighlighter.DefaultUnderlineHighlightPainter(oce.value, FIND_RESULTS_PAINTERS[_index].getThickness()); 239 } 240 } 241 242 243 private class BreakpointColorOptionListener implements OptionListener<Color> { 244 public void optionChanged(OptionEvent<Color> oce) { 245 BREAKPOINT_PAINTER = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 246 _mainFrame.refreshBreakpointHighlightPainter(); 247 } 248 } 249 250 251 private class DisabledBreakpointColorOptionListener implements OptionListener<Color> { 252 public void optionChanged(OptionEvent<Color> oce) { 253 DISABLED_BREAKPOINT_PAINTER = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 254 _mainFrame.refreshBreakpointHighlightPainter(); 255 } 256 } 257 258 259 private static class ThreadColorOptionListener implements OptionListener<Color> { 260 public void optionChanged(OptionEvent<Color> oce) { 261 THREAD_PAINTER = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 262 } 263 } 264 265 266 private class AntiAliasOptionListener implements OptionListener<Boolean > { 267 public void optionChanged(OptionEvent<Boolean > oce) { 268 _antiAliasText = oce.value.booleanValue(); 269 DefinitionsPane.this.repaint(); 270 } 271 } 272 273 276 private final UndoableEditListener _undoListener = new UndoableEditListener() { 277 278 281 public void undoableEditHappened(UndoableEditEvent e) { 282 UndoWithPosition undo = new UndoWithPosition(e.getEdit(), getCaretPosition()); 283 if (!_inCompoundEdit) { 284 CompoundUndoManager undoMan = _doc.getUndoManager(); 285 _inCompoundEdit = true; 286 _compoundEditKey = undoMan.startCompoundEdit(); 287 getUndoAction().updateUndoState(); 288 getRedoAction().updateRedoState(); 289 } 290 _doc.getUndoManager().addEdit(undo); 291 getRedoAction().setEnabled(false); 292 } 293 }; 294 295 298 private volatile JMenuItem _toggleBreakpointMenuItem; 299 300 305 306 private volatile JPopupMenu _popMenu; 307 308 309 private volatile PopupMenuMouseAdapter _popupMenuMA; 310 311 312 private volatile ErrorCaretListener _errorListener; 313 314 private volatile ActionListener _setSizeListener = null; 315 316 317 private class IndentKeyActionTab extends AbstractAction { 318 319 320 public void actionPerformed(ActionEvent e) { 321 indent(); 325 } 326 } 327 328 329 private class IndentKeyAction extends AbstractAction { 330 331 335 private final String _key; 336 337 338 private final Action _defaultAction; 339 340 341 private final boolean _indentNonCode; 342 343 346 IndentKeyAction(String key, Action defaultAction) { 347 this(key, defaultAction, false); 348 } 349 350 355 IndentKeyAction(String key, Action defaultAction, boolean indentNonCode) { 356 _key = key; 357 _defaultAction = defaultAction; 358 _indentNonCode = indentNonCode; 359 } 360 361 364 protected int getIndentReason() { return Indenter.OTHER; } 365 366 369 public void actionPerformed(ActionEvent e) { 370 _defaultAction.actionPerformed(e); 371 372 374 _doc.setCurrentLocation(getCaretPosition()); 375 ReducedModelState state = _doc.getStateAtCurrent(); 376 if (state.equals(ReducedModelState.FREE) || _indentNonCode) indent(getIndentReason()); 377 } 378 } 379 380 381 private volatile Action _indentKeyActionTab = new IndentKeyActionTab(); 382 383 388 private final Action _indentKeyActionLine = 389 new IndentKeyAction("\n", (Action) getActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)), 390 true ) { 391 394 protected int getIndentReason() { return Indenter.ENTER_KEY_PRESS; } 395 }; 396 397 400 private final Action _indentKeyActionSquiggly = new IndentKeyAction("}", getKeymap().getDefaultAction()); 401 private final Action _indentKeyActionOpenSquiggly = new IndentKeyAction("{", getKeymap().getDefaultAction()); 402 private final Action _indentKeyActionColon = new IndentKeyAction(":", getKeymap().getDefaultAction()); 403 404 407 private volatile boolean _inCompoundEdit = false; 408 private volatile int _compoundEditKey; 409 410 411 final Keymap ourMap; 412 413 416 public DefinitionsPane(MainFrame mf, final OpenDefinitionsDocument doc) { 417 super(new SwingDocument()); 418 419 _mainFrame = mf; 420 421 addFocusListener(new FocusListener() { 422 public void focusGained(FocusEvent e) { 423 _mainFrame.getModel().getDocumentNavigator().requestSelectionUpdate(doc); 424 } 425 public void focusLost(FocusEvent e) { } 426 }); 427 428 _doc = doc; 430 _selStart = _doc.getInitialSelectionStart(); 433 _selEnd = _doc.getInitialSelectionEnd(); 434 _savedVScroll = _doc.getInitialVerticalScroll(); 435 _savedHScroll = _doc.getInitialHorizontalScroll(); 436 437 _resetUndo(); 439 440 Font mainFont = DrJava.getConfig().getSetting(FONT_MAIN); 441 setFont(mainFont); 442 443 setEditable(true); 444 445 ourMap = addKeymap(INDENT_KEYMAP_NAME, getKeymap()); 447 ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), _indentKeyActionLine); 448 ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(KeyEvent.VK_TAB, 0), _indentKeyActionTab); 449 ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke('}'), _indentKeyActionSquiggly); 450 ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke('{'), _indentKeyActionOpenSquiggly); 451 ourMap.addActionForKeyStroke(KeyStroke.getKeyStroke(':'), _indentKeyActionColon); 452 setKeymap(ourMap); 453 454 466 468 if (CodeStatus.DEVELOPMENT) _antiAliasText = DrJava.getConfig().getSetting(TEXT_ANTIALIAS).booleanValue(); 469 470 OptionListener<Color> temp; 471 Pair<Option<Color>, OptionListener<Color>> pair; 472 473 temp = new ForegroundColorListener(this); 476 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEFINITIONS_NORMAL_COLOR, temp); 477 _colorOptionListeners.add(pair); 478 479 temp = new BackgroundColorListener(this); 480 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEFINITIONS_BACKGROUND_COLOR, temp); 481 _colorOptionListeners.add(pair); 482 483 temp = new MatchColorOptionListener(); 485 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEFINITIONS_MATCH_COLOR, temp); 486 _colorOptionListeners.add(pair); 487 DrJava.getConfig().addOptionListener(OptionConstants.DEFINITIONS_MATCH_COLOR, temp); 488 489 temp = new ErrorColorOptionListener(); 490 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.COMPILER_ERROR_COLOR, temp); 491 _colorOptionListeners.add(pair); 492 DrJava.getConfig().addOptionListener(OptionConstants.COMPILER_ERROR_COLOR, temp); 493 494 temp = new BookmarkColorOptionListener(); 495 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.BOOKMARK_COLOR, temp); 496 _colorOptionListeners.add(pair); 497 DrJava.getConfig().addOptionListener(OptionConstants.BOOKMARK_COLOR, temp); 498 499 for (int i=0; i<FIND_RESULTS_COLORS.length; ++i) { 500 temp = new FindResultsColorOptionListener(i); 501 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.FIND_RESULTS_COLORS[i], temp); 502 _colorOptionListeners.add(pair); 503 DrJava.getConfig().addOptionListener(OptionConstants.FIND_RESULTS_COLORS[i], temp); 504 } 505 506 temp = new BreakpointColorOptionListener(); 507 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEBUG_BREAKPOINT_COLOR, temp); 508 _colorOptionListeners.add(pair); 509 DrJava.getConfig().addOptionListener(OptionConstants.DEBUG_BREAKPOINT_COLOR, temp); 510 511 temp = new DisabledBreakpointColorOptionListener(); 512 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEBUG_BREAKPOINT_DISABLED_COLOR, temp); 513 _colorOptionListeners.add(pair); 514 DrJava.getConfig().addOptionListener( OptionConstants.DEBUG_BREAKPOINT_DISABLED_COLOR, temp); 515 516 temp = new ThreadColorOptionListener(); 517 pair = new Pair<Option<Color>, OptionListener<Color>>(OptionConstants.DEBUG_THREAD_COLOR, temp); 518 _colorOptionListeners.add(pair); 519 DrJava.getConfig().addOptionListener( OptionConstants.DEBUG_THREAD_COLOR, temp); 520 521 if (CodeStatus.DEVELOPMENT) { 522 OptionListener<Boolean > aaTemp = new AntiAliasOptionListener(); 523 Pair<Option<Boolean >, OptionListener<Boolean >> aaPair = new Pair<Option<Boolean >, OptionListener<Boolean >>(OptionConstants.TEXT_ANTIALIAS, aaTemp); 524 _booleanOptionListeners.add(aaPair); 525 DrJava.getConfig().addOptionListener( OptionConstants.TEXT_ANTIALIAS, aaTemp); 526 } 527 528 createPopupMenu(); 529 530 _popupMenuMA = new PopupMenuMouseAdapter(); 532 this.addMouseListener(_popupMenuMA); 533 this.setHighlighter(new ReverseHighlighter()); 534 _highlightManager = new HighlightManager(this); 535 536 int rate = this.getCaret().getBlinkRate(); 537 this.setCaret(new DefaultCaret() { 540 public void focusLost(FocusEvent e) { setVisible(false); } 541 }); 542 this.getCaret().setBlinkRate(rate); 543 } 545 546 547 public void endCompoundEdit() { 548 if (_inCompoundEdit) { 549 CompoundUndoManager undoMan = _doc.getUndoManager(); 550 _inCompoundEdit = false; 551 undoMan.endCompoundEdit(_compoundEditKey); 552 } 553 } 554 555 560 public void processKeyEvent(KeyEvent e) { 561 if (_mainFrame.getAllowKeyEvents()) { 562 KeyStroke ks = KeyStroke.getKeyStrokeForEvent(e); 563 Action a = KeyBindingManager.Singleton.get(ks); 564 if ((ks != KeyStrokeOption.NULL_KEYSTROKE) && (a != null)) { 566 endCompoundEdit(); 568 SwingUtilities.notifyAction(a, ks, e, e.getSource(), e.getModifiers()); 570 571 e.consume(); 573 } 574 else { 575 Keymap km = getKeymap(); 577 578 if (km.isLocallyDefined(ks) || km.isLocallyDefined(KeyStroke.getKeyStroke(ks.getKeyChar()))) { 579 if (e.getKeyCode() == KeyEvent.VK_ENTER) endCompoundEdit(); 581 582 CompoundUndoManager undoMan = _doc.getUndoManager(); 583 586 super.processKeyEvent(e); 587 endCompoundEdit(); 590 } 593 else { 594 595 if ((e.getModifiers() & InputEvent.META_MASK) != 0 600 && e.getKeyCode() == KeyEvent.VK_UNDEFINED) { 602 603 return; 605 } 606 607 if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) { 611 int newModifiers = e.getModifiers() & ~(InputEvent.SHIFT_MASK); 612 613 KeyStroke newKs = KeyStroke.getKeyStroke(ks.getKeyCode(), newModifiers, ks.isOnKeyRelease()); 614 String name = KeyBindingManager.Singleton.getName(newKs); 615 616 if (name != null && (name.equals("Delete Previous") || name.equals("Delete Next"))) { 617 endCompoundEdit(); 618 SwingUtilities.notifyAction(KeyBindingManager.Singleton.get(newKs), newKs, e, e.getSource(), newModifiers); 621 e.consume(); 622 return; 624 } 625 } 626 627 630 if (e.getID() != KeyEvent.KEY_TYPED) { 631 super.processKeyEvent(e); 632 return; 633 } 634 } 635 if ((e.getModifiers() & InputEvent.ALT_MASK) != 0) testVariable = true; else testVariable = false; 638 639 super.processKeyEvent(e); 640 } 641 } 642 } 643 644 647 public static void setEditorKit(DefinitionsEditorKit editorKit) { EDITOR_KIT = editorKit; } 648 649 650 protected void paintComponent(Graphics g) { 651 if (CodeStatus.DEVELOPMENT) { 652 if (_antiAliasText && g instanceof Graphics2D) { 653 Graphics2D g2d = (Graphics2D)g; 654 g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 655 } 656 } 657 super.paintComponent(g); 658 } 659 660 661 private void createPopupMenu() { 662 _popMenu = new JPopupMenu(); 664 665 _popMenu.add(_mainFrame.cutAction); 666 _popMenu.add(_mainFrame.copyAction); 667 _popMenu.add(_mainFrame.pasteAction); 668 _popMenu.addSeparator(); 669 670 JMenuItem indentItem = new JMenuItem("Indent Line(s)"); 671 indentItem.addActionListener(new AbstractAction() { 672 public void actionPerformed(ActionEvent ae) { indent(); } 673 }); 674 _popMenu.add(indentItem); 675 676 JMenuItem commentLinesItem = new JMenuItem("Comment Line(s)"); 677 commentLinesItem.addActionListener(new AbstractAction() { 678 public void actionPerformed( ActionEvent ae) { 679 _mainFrame.hourglassOn(); 680 try{ 681 _doc.setCurrentLocation(getCaretPosition()); 682 _commentLines(); 683 } 684 finally{ _mainFrame.hourglassOff(); } 685 } 686 }); 687 _popMenu.add(commentLinesItem); 688 689 JMenuItem uncommentLinesItem = new JMenuItem("Uncomment Line(s)"); 690 uncommentLinesItem.addActionListener ( new AbstractAction() { 691 public void actionPerformed( ActionEvent ae) { 692 _doc.setCurrentLocation(getCaretPosition()); 693 _uncommentLines(); 694 } 695 }); 696 _popMenu.add(uncommentLinesItem); 697 698 699 _popMenu.addSeparator(); 700 JMenuItem gotoFileUnderCursorItem = new JMenuItem("Go to File Under Cursor"); 701 gotoFileUnderCursorItem.addActionListener ( new AbstractAction() { 702 public void actionPerformed( ActionEvent ae) { 703 _doc.setCurrentLocation(getCaretPosition()); 704 _mainFrame._gotoFileUnderCursor(); 705 } 706 }); 707 _popMenu.add(gotoFileUnderCursorItem); 708 709 710 JMenuItem toggleBookmarkItem = new JMenuItem("Toggle Bookmark"); 711 toggleBookmarkItem.addActionListener ( new AbstractAction() { 712 public void actionPerformed( ActionEvent ae) { 713 if (getSelectionStart()==getSelectionEnd()) { setCaretPosition(viewToModel(_popupMenuMA.getLastMouseClick().getPoint())); 716 } 717 _mainFrame.toggleBookmark(); 718 } 719 }); 720 _popMenu.add(toggleBookmarkItem); 721 722 if (_mainFrame.getModel().getDebugger().isAvailable()) { 723 _popMenu.addSeparator(); 724 725 JMenuItem breakpointItem = new JMenuItem("Toggle Breakpoint"); 727 breakpointItem.addActionListener( new AbstractAction() { 728 public void actionPerformed( ActionEvent ae ) { 729 setCaretPosition(viewToModel(_popupMenuMA.getLastMouseClick().getPoint())); 731 _mainFrame.debuggerToggleBreakpoint(); 732 } 733 }); 734 _toggleBreakpointMenuItem = _popMenu.add(breakpointItem); 735 } 736 } 737 738 739 private class PopupMenuMouseAdapter extends RightClickMouseAdapter { 740 741 private MouseEvent _lastMouseClick = null; 742 743 public void mousePressed(MouseEvent e) { 744 super.mousePressed(e); 745 746 _lastMouseClick = e; 747 endCompoundEdit(); 748 749 if ((viewToModel(e.getPoint()) < getSelectionStart()) || 751 (viewToModel(e.getPoint()) > getSelectionEnd()) ) { 752 setCaretPosition(viewToModel(e.getPoint())); 754 } 755 } 756 757 protected void _popupAction(MouseEvent e) { 758 requestFocusInWindow(); 759 _popMenu.show(e.getComponent(), e.getX(), e.getY()); 760 } 761 762 public MouseEvent getLastMouseClick() { return _lastMouseClick; } 763 } 764 765 766 private void _commentLines() { 767 _mainFrame.commentLines(); 768 } 770 771 772 private void _uncommentLines() { 773 _mainFrame.uncommentLines(); 774 } 776 777 778 public UndoAction getUndoAction() { return _undoAction; } 779 780 781 public RedoAction getRedoAction() { return _redoAction; } 782 783 784 public OpenDefinitionsDocument getOpenDefDocument() { return _doc; } 785 786 789 public DJDocument getDJDocument() { return _doc; } 790 791 792 public HighlightManager getHighlightManager() { return _highlightManager; } 793 794 797 public void setPositionAndScroll(int pos) { 798 try { 799 setCaretPosition(pos); 800 scrollRectToVisible(modelToView(pos)); 801 } 802 catch (BadLocationException ble) { throw new UnexpectedException(ble); } 803 } 804 805 808 public void setDocument(Document d) { 809 if (_doc != null) { if ((d == null) || (!d.equals(_doc))) { 811 throw new IllegalStateException ("Cannot set the document of a DefinitionsPane to a different document."); 812 } 813 } 814 super.setDocument(d); } 816 817 public boolean checkAltKey() { return testVariable; 819 } 820 821 822 public void addErrorCaretListener(ErrorCaretListener listener) { 823 _errorListener = listener; 824 addCaretListener(listener); 825 } 826 827 828 public ErrorCaretListener getErrorCaretListener() { return _errorListener; } 829 830 833 public void addErrorHighlight(int from, int to) { 834 removeErrorHighlight(); 835 _errorHighlightTag = _highlightManager.addHighlight(from, to, ERROR_PAINTER); 836 } 837 838 839 public void removeErrorHighlight() { 840 if (_errorHighlightTag != null) { 841 _errorHighlightTag.remove(); 842 _errorHighlightTag = null; 843 } 844 } 845 846 public boolean hasWarnedAboutModified() { return _hasWarnedAboutModified; } 847 848 public void hasWarnedAboutModified( boolean hasWarned) { 849 _hasWarnedAboutModified = hasWarned; 850 } 851 852 public void addBreakpointHighlight( Breakpoint bp ) { } 853 854 public void removeBreakpointHighlight( Breakpoint bp) { } 855 856 859 private volatile JScrollPane _scrollPane; 860 861 public void setScrollPane(JScrollPane s) { _scrollPane = s; } 862 863 864 private volatile int _savedVScroll; 865 private volatile int _savedHScroll; 866 private volatile int _position; 867 private volatile int _selStart; 868 private volatile int _selEnd; 869 870 875 public void notifyInactive() { 876 try { 881 getOpenDefDocument().setCurrentLocation(getCaretPosition()); 883 884 removeErrorHighlight(); 886 887 _position = _doc.getCurrentLocation(); 888 _selStart = getSelectionStart(); 889 _selEnd = getSelectionEnd(); 890 891 _savedVScroll = _scrollPane.getVerticalScrollBar().getValue(); 892 _savedHScroll = _scrollPane.getHorizontalScrollBar().getValue(); 893 894 super.setDocument(NULL_DOCUMENT); 895 } 896 catch(NoSuchDocumentException e) { 897 } 901 } 902 903 907 public void notifyActive() { 908 assert ! _mainFrame.isVisible() || EventQueue.isDispatchThread(); 909 super.setDocument(_doc); 910 if (_doc.getUndoableEditListeners().length == 0) _resetUndo(); 911 912 _doc.acquireWriteLock(); 913 int len = _doc.getLength(); 914 if (len < _position || len < _selEnd) { 915 _position = len; 918 _selStart = len; 919 _selEnd = len; 920 } 921 try { 922 if (_position == _selStart) { 923 setCaretPosition(_selEnd); 924 moveCaretPosition(_selStart); 925 _doc.setCurrentLocation(_selStart); 926 } 927 else { 928 setCaretPosition(_selStart); 929 moveCaretPosition(_selEnd); 930 _doc.setCurrentLocation(_selEnd); 931 } 932 } 933 finally { _doc.releaseWriteLock(); } 934 _scrollPane.getVerticalScrollBar().setValue(_savedVScroll); 935 _scrollPane.getHorizontalScrollBar().setValue(_savedHScroll); 936 _scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 938 _scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 939 } 940 941 public int getVerticalScroll() { 942 if (getDocument() == NULL_DOCUMENT) return _savedVScroll; 943 else return _scrollPane.getVerticalScrollBar().getValue(); 944 } 945 946 public int getHorizontalScroll() { 947 if (getDocument() == NULL_DOCUMENT) return _savedHScroll; 948 else return _scrollPane.getHorizontalScrollBar().getValue(); 949 } 950 951 public int getCurrentLine() { 952 try { 953 int pos = getCaretPosition(); 954 FontMetrics metrics = getFontMetrics(getFont()); 955 Rectangle startRect = modelToView(pos); 956 if (startRect == null) return 1; 957 return (new Double (startRect.getY() / metrics.getHeight()).intValue() + 1); 959 } catch (BadLocationException e) { 960 throw new UnexpectedException(e); 962 } 963 } 964 965 966 public int getCurrentLinefromDoc() { return _doc.getCurrentLine(); } 967 968 public int getCurrentCol() { return _doc.getCurrentCol(); } 969 970 public void setSize(int width, int height) { 971 super.setSize(width, height); 972 if (_setSizeListener != null) _setSizeListener.actionPerformed(null); 973 } 974 975 978 public void centerViewOnOffset(int offset) { 979 assert EventQueue.isDispatchThread(); 980 try { 981 FontMetrics metrics = getFontMetrics(getFont()); 982 JViewport defViewPort = _mainFrame.getDefViewport(); 983 double viewWidth = defViewPort.getWidth(); 984 double viewHeight = defViewPort.getHeight(); 985 Rectangle startRect; 988 startRect = modelToView(offset); 989 990 if (startRect != null) { 991 int startRectX = (int) startRect.getX(); 992 int startRectY = (int) startRect.getY(); 993 startRect.setLocation(startRectX - (int)(viewWidth/2), startRectY - (int)(viewHeight/2)); 994 Point endPoint = new Point(startRectX+(int)(viewWidth/2), 995 startRectY+(int)(viewHeight/2 + metrics.getHeight()/2)); 996 997 startRect.add(endPoint); 1000 1001 scrollRectToVisible(startRect); 1002 } 1003 1005 setCaretPosition(offset); 1006 } 1007 catch (BadLocationException e) { throw new UnexpectedException(e); } 1008 } 1009 1010 public void centerViewOnLine(int lineNumber) { 1011 FontMetrics metrics = getFontMetrics(getFont()); 1012 Point p = new Point(0, metrics.getHeight() * (lineNumber)); 1013 int offset = this.viewToModel(p); 1014 this.centerViewOnOffset(offset); 1015 } 1016 1017 1021 public void select(int selectionStart, int selectionEnd) { 1022 if (selectionStart < 0) selectionStart = 0; 1023 if (selectionEnd < 0) selectionEnd = 0; 1024 setCaretPosition(selectionStart); 1025 moveCaretPosition(selectionEnd); } 1027 1028 1029 public void resetUndo() { 1030 _doc.getUndoManager().discardAllEdits(); 1031 1032 _undoAction.updateUndoState(); 1033 _redoAction.updateRedoState(); 1034 } 1035 1036 1037 private void _resetUndo() { 1038 if (_undoAction == null) _undoAction = new UndoAction(); 1039 if (_redoAction == null) _redoAction = new RedoAction(); 1040 1041 _doc.resetUndoManager(); 1042 1043 getDocument().addUndoableEditListener(_undoListener); 1044 _undoAction.updateUndoState(); 1045 _redoAction.updateRedoState(); 1046 } 1047 1048 1049 1052 protected EditorKit createDefaultEditorKit() { 1053 return EDITOR_KIT; 1055 } 1056 1057 1062 protected boolean shouldIndent(int selStart, int selEnd) { 1063 if (selEnd > (selStart + INDENT_WARNING_THRESHOLD)) { 1064 Object [] options = {"Yes", "No"}; 1065 int n = JOptionPane.showOptionDialog 1066 (_mainFrame, 1067 "Re-indenting this block may take a very long time. Are you sure?", 1068 "Confirm Re-indent", 1069 JOptionPane.YES_NO_OPTION, 1070 JOptionPane.QUESTION_MESSAGE, 1071 null, 1072 options, 1073 options[1]); 1074 switch (n) { 1075 case JOptionPane.CANCEL_OPTION: 1076 case JOptionPane.CLOSED_OPTION: 1077 case JOptionPane.NO_OPTION: 1078 return false; 1079 default: 1080 return true; 1081 } 1082 } 1083 return true; 1084 } 1085 1086 1087 1093 protected void indentLines(int selStart, int selEnd, int reason, ProgressMonitor pm) { 1094 try { 1097 _doc.indentLines(selStart, selEnd, reason, pm); 1098 endCompoundEdit(); 1099 } 1100 catch (OperationCanceledException oce) { 1101 endCompoundEdit(); 1103 _doc.getUndoManager().undo(); 1104 throw new UnexpectedException(oce); 1106 } 1107 catch (RuntimeException e) { 1108 1110 endCompoundEdit(); 1111 throw e; 1112 } 1113 1114 setCaretPosition(_doc.getCurrentLocation()); 1116 } 1117 1118 1119 private List <Pair<Option<Color>, OptionListener<Color>>> _colorOptionListeners = 1120 new LinkedList <Pair<Option<Color>, OptionListener<Color>>>(); 1121 1122 private List <Pair<Option<Boolean >, OptionListener<Boolean >>> _booleanOptionListeners = 1123 new LinkedList <Pair<Option<Boolean >, OptionListener<Boolean >>>(); 1124 1125 1128 public void close() { 1129 for (Pair<Option<Color>, OptionListener<Color>> p: _colorOptionListeners) { 1130 DrJava.getConfig().removeOptionListener(p.first(), p.second()); 1131 } 1132 for (Pair<Option<Boolean >, OptionListener<Boolean >> p: _booleanOptionListeners) { 1133 DrJava.getConfig().removeOptionListener(p.first(), p.second()); 1134 } 1135 _colorOptionListeners.clear(); 1136 _booleanOptionListeners.clear(); 1137 1138 ourMap.removeBindings(); 1139 removeKeymap(ourMap.getName()); 1140 1141 _popMenu.removeAll(); 1142 } 1143 1144 1145 public class UndoAction extends AbstractAction { 1146 1147 1148 private UndoAction() { 1149 super("Undo"); 1150 setEnabled(false); 1151 } 1152 1153 1156 public void actionPerformed(ActionEvent e) { 1157 try { 1158 _doc.getUndoManager().undo(); 1169 _doc.updateModifiedSinceSave(); 1170 _mainFrame.updateFileTitle(); 1171 } 1172 catch (CannotUndoException ex) { 1173 throw new UnexpectedException(ex); 1174 } 1175 updateUndoState(); 1176 _redoAction.updateRedoState(); 1177 } 1178 1179 1180 protected void updateUndoState() { 1181 if (_doc.undoManagerCanUndo()) { 1182 setEnabled(true); 1183 putValue(Action.NAME, _doc.getUndoManager().getUndoPresentationName()); 1184 } 1185 else { 1186 setEnabled(false); 1187 putValue(Action.NAME, "Undo"); 1188 } 1189 } 1190 } 1191 1192 1193 public class RedoAction extends AbstractAction { 1194 1195 1196 private RedoAction() { 1197 super("Redo"); 1198 setEnabled(false); 1199 } 1200 1201 1204 public void actionPerformed(ActionEvent e) { 1205 try { 1206 _doc.getUndoManager().redo(); 1212 1213 _doc.updateModifiedSinceSave(); 1218 _mainFrame.updateFileTitle(); 1219 } catch (CannotRedoException ex) { 1220 throw new UnexpectedException(ex); 1221 } 1222 updateRedoState(); 1223 _undoAction.updateUndoState(); 1224 } 1225 1226 1227 protected void updateRedoState() { 1228 if (_doc.undoManagerCanRedo()) { 1229 setEnabled(true); 1230 putValue(Action.NAME, _doc.getUndoManager().getRedoPresentationName()); 1231 } 1232 else { 1233 setEnabled(false); 1234 putValue(Action.NAME, "Redo"); 1235 } 1236 } 1237 } 1238 1239 1240 private class UndoWithPosition implements UndoableEdit { 1241 private final UndoableEdit _undo; 1242 private final int _pos; 1243 1244 public UndoWithPosition(UndoableEdit undo, int pos) { 1245 _undo = undo; 1246 _pos = pos; 1247 } 1248 1249 public int getPosition() { return _pos; } 1250 public boolean addEdit(UndoableEdit ue) { return _undo.addEdit(ue); } 1251 public boolean canRedo() { return _undo.canRedo(); } 1252 public boolean canUndo() { return _undo.canUndo(); } 1253 public void die() { _undo.die(); } 1254 public String getPresentationName() { return _undo.getPresentationName(); } 1255 public String getUndoPresentationName() { return _undo.getUndoPresentationName(); } 1256 public String getRedoPresentationName() { return _undo.getRedoPresentationName(); } 1257 public boolean isSignificant() { return _undo.isSignificant(); } 1258 1259 public void redo() { 1260 _undo.redo(); 1261 if (_pos > -1) setCaretPosition(_pos); 1262 } 1263 1264 public boolean replaceEdit(UndoableEdit ue) { return _undo.replaceEdit(ue); } 1265 1266 public void undo() { 1267 if (_pos > -1) setCaretPosition(_pos); 1268 _undo.undo(); 1269 } 1270 } 1271 1272 1273 private List <FinalizationListener<DefinitionsPane>> _finalizationListeners = 1274 new LinkedList <FinalizationListener<DefinitionsPane>>(); 1275 1276 1281 public void addFinalizationListener(FinalizationListener<DefinitionsPane> fl) { _finalizationListeners.add(fl); } 1282 1283 public List <FinalizationListener<DefinitionsPane>> getFinalizationListeners() { return _finalizationListeners; } 1284 1285 1288 protected void finalize() { 1289 FinalizationEvent<DefinitionsPane> fe = new FinalizationEvent<DefinitionsPane>(this); 1290 for (FinalizationListener<DefinitionsPane> fl: _finalizationListeners) fl.finalized(fe); 1291 } 1292} 1293 | Popular Tags |