1 33 34 package edu.rice.cs.drjava.ui; 35 36 import edu.rice.cs.drjava.DrJava; 37 import edu.rice.cs.drjava.config.OptionConstants; 38 import edu.rice.cs.drjava.config.OptionEvent; 39 import edu.rice.cs.drjava.config.OptionListener; 40 import edu.rice.cs.drjava.model.OpenDefinitionsDocument; 41 import edu.rice.cs.drjava.model.SingleDisplayModel; 42 import edu.rice.cs.drjava.model.compiler.CompilerError; 44 import edu.rice.cs.drjava.model.compiler.CompilerErrorModel; 45 import edu.rice.cs.drjava.model.ClipboardHistoryModel; 46 import edu.rice.cs.util.UnexpectedException; 47 import edu.rice.cs.util.swing.HighlightManager; 48 import edu.rice.cs.util.swing.BorderlessScrollPane; 49 import edu.rice.cs.util.text.SwingDocument; 50 51 import java.util.Hashtable ; 53 54 import javax.swing.*; 55 import javax.swing.text.*; 56 import javax.swing.text.SimpleAttributeSet ; 57 import javax.swing.border.EmptyBorder ; 58 import java.awt.datatransfer.*; 59 import java.awt.*; 60 import java.awt.event.MouseAdapter ; 61 import java.awt.event.MouseEvent ; 62 import java.awt.event.ItemListener ; 63 import java.awt.event.ItemEvent ; 64 import java.awt.event.ActionListener ; 65 import java.awt.event.ActionEvent ; 66 import java.io.IOException ; 67 68 72 public abstract class ErrorPanel extends TabbedPanel implements OptionConstants { 73 74 protected static final SimpleAttributeSet NORMAL_ATTRIBUTES = _getNormalAttributes(); 75 protected static final SimpleAttributeSet BOLD_ATTRIBUTES = _getBoldAttributes(); 76 77 78 protected volatile int _numErrors; 79 protected volatile JCheckBox _showHighlightsCheckBox; 80 81 protected SingleDisplayModel _model; 84 85 private JScrollPane _scroller; 86 87 88 private JPanel _leftPanel; 89 90 91 private JPanel _rightPanel; 92 93 private JPanel _errorNavPanel; 94 95 private JPanel _errorNavButtonsPanel; 96 97 98 protected JPanel customPanel; 99 100 private JButton _nextErrorButton; 101 private JButton _prevErrorButton; 102 103 104 static ReverseHighlighter.DefaultHighlightPainter _listHighlightPainter = 105 new ReverseHighlighter.DefaultHighlightPainter(DrJava.getConfig().getSetting(COMPILER_ERROR_COLOR)); 106 107 protected static final SimpleAttributeSet _getBoldAttributes() { 108 SimpleAttributeSet s = new SimpleAttributeSet (); 109 StyleConstants.setBold(s, true); 110 return s; 111 } 112 113 protected static final SimpleAttributeSet _getNormalAttributes() { 114 SimpleAttributeSet s = new SimpleAttributeSet (); 115 return s; 116 } 117 118 public ErrorPanel(SingleDisplayModel model, MainFrame frame, String tabString, String labelString) { 119 super(frame, tabString); 120 _model = model; 121 122 _mainPanel.setLayout(new BorderLayout()); 123 124 _leftPanel = new JPanel(new BorderLayout()); 125 126 _errorNavPanel = new JPanel(new GridBagLayout()); 127 128 129 130 _errorNavButtonsPanel = new JPanel(new BorderLayout()); 131 132 _nextErrorButton = new JButton(MainFrame.getIcon("Down16.gif")); _prevErrorButton = new JButton(MainFrame.getIcon("Up16.gif")); 135 _nextErrorButton.setMargin(new Insets(0,0,0,0)); 136 _nextErrorButton.setToolTipText("Go to the next error"); 137 _prevErrorButton.setMargin(new Insets(0,0,0,0)); 138 _prevErrorButton.setToolTipText("Go to the previous error"); 139 140 141 _errorNavButtonsPanel.add(_prevErrorButton, BorderLayout.NORTH); 147 _errorNavButtonsPanel.add(_nextErrorButton, BorderLayout.SOUTH); 148 _errorNavButtonsPanel.setBorder(new EmptyBorder (18,5,18,5)); 150 153 _errorNavPanel.add(_errorNavButtonsPanel); _showHighlightsCheckBox = new JCheckBox( "Highlight source", true); 155 156 _scroller = new BorderlessScrollPane(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, 161 JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 162 163 _leftPanel.add(_scroller, BorderLayout.CENTER); 164 _leftPanel.add(_errorNavPanel, BorderLayout.EAST); 165 166 customPanel = new JPanel(new BorderLayout()); 167 _rightPanel = new JPanel(new BorderLayout()); 168 _rightPanel.setBorder(new EmptyBorder (0,5,0,5)); _rightPanel.add(new JLabel(labelString, SwingConstants.LEFT), BorderLayout.NORTH); 171 _rightPanel.add(customPanel, BorderLayout.CENTER); 172 _rightPanel.add(_showHighlightsCheckBox, BorderLayout.SOUTH); 173 174 _mainPanel.add(_leftPanel, BorderLayout.CENTER); 175 _mainPanel.add(_rightPanel, BorderLayout.EAST); 176 } 177 178 protected void setErrorListPane(final ErrorListPane elp) { 179 _scroller.setViewportView(elp); 180 _nextErrorButton.setEnabled(false); 181 _nextErrorButton.addActionListener(new ActionListener () { 182 public void actionPerformed(ActionEvent e) { 183 elp.nextError(); 184 } 187 }); 188 _prevErrorButton.setEnabled(false); 189 _prevErrorButton.addActionListener(new ActionListener () { 190 public void actionPerformed(ActionEvent e) { 191 elp.prevError(); 192 } 195 }); 196 } 197 198 199 public void setListFont(Font f) { 200 SimpleAttributeSet set = new SimpleAttributeSet (); 201 StyleConstants.setFontFamily(set, f.getFamily()); 202 StyleConstants.setFontSize(set, f.getSize()); 203 StyleConstants.setBold(set, f.isBold()); 204 StyleConstants.setItalic(set, f.isItalic()); 205 206 _updateStyles(set); 207 208 getErrorListPane().setFont(f); 209 210 SwingDocument doc = getErrorListPane().getSwingDocument(); 211 doc.acquireWriteLock(); 212 try { doc.setCharacterAttributes(0, doc.getLength() + 1, set, false); } 213 finally { doc.releaseWriteLock(); } 214 } 215 216 217 220 protected void _updateStyles(AttributeSet newSet) { 221 NORMAL_ATTRIBUTES.addAttributes(newSet); 222 BOLD_ATTRIBUTES.addAttributes(newSet); 223 StyleConstants.setBold(BOLD_ATTRIBUTES, true); } 225 226 abstract protected ErrorListPane getErrorListPane(); 227 228 protected SingleDisplayModel getModel() { 229 return _model; 230 } 231 232 235 abstract protected CompilerErrorModel getErrorModel(); 236 237 238 public abstract class ErrorListPane extends JEditorPane implements ClipboardOwner { 239 240 protected Keymap _keymap; 241 242 243 private int _selectedIndex; 244 245 250 protected Position[] _errorListPositions; 251 252 253 protected final Hashtable <Position, CompilerError> _errorTable = new Hashtable <Position, CompilerError>(); 254 255 private HighlightManager.HighlightInfo _listHighlightTag = null; 257 258 private HighlightManager _highlightManager = new HighlightManager(this); 259 260 protected MouseAdapter defaultMouseListener = new MouseAdapter () { 261 public void mousePressed(MouseEvent e) { selectNothing(); } 262 public void mouseReleased(MouseEvent e) { 263 CompilerError error = _errorAtPoint(e.getPoint()); 264 265 if (_isEmptySelection() && error != null) getErrorListPane().switchToError(error); 266 else selectNothing(); 267 } 268 }; 269 270 274 275 public ErrorListPane() { 276 279 setContentType("text/rtf"); 280 setDocument(new SwingDocument()); 281 setHighlighter(new ReverseHighlighter()); 282 283 addMouseListener(defaultMouseListener); 284 285 _selectedIndex = 0; 286 _errorListPositions = new Position[0]; 287 288 this.setFont(new Font("Courier", 0, 20)); 289 290 294 setEditable(false); 296 297 DrJava.getConfig().addOptionListener(COMPILER_ERROR_COLOR, 298 new CompilerErrorColorOptionListener()); 299 300 StyleConstants.setForeground(NORMAL_ATTRIBUTES, 302 DrJava.getConfig().getSetting 303 (DEFINITIONS_NORMAL_COLOR)); 304 StyleConstants.setForeground(BOLD_ATTRIBUTES, 305 DrJava.getConfig().getSetting 306 (DEFINITIONS_NORMAL_COLOR)); 307 setBackground(DrJava.getConfig().getSetting(DEFINITIONS_BACKGROUND_COLOR)); 308 309 DrJava.getConfig().addOptionListener(DEFINITIONS_NORMAL_COLOR, 311 new ForegroundColorListener()); 312 DrJava.getConfig().addOptionListener(DEFINITIONS_BACKGROUND_COLOR, 313 new BackgroundColorListener()); 314 315 318 _showHighlightsCheckBox.addItemListener(new ItemListener () { 319 public void itemStateChanged(ItemEvent e) { 320 DefinitionsPane lastDefPane = _frame.getCurrentDefPane(); 321 322 if (e.getStateChange() == ItemEvent.DESELECTED) { 323 lastDefPane.removeErrorHighlight(); 324 } 325 326 else if (e.getStateChange() == ItemEvent.SELECTED) { 327 getErrorListPane().switchToError(getSelectedIndex()); 328 } 333 } 334 }); 335 336 _keymap = addKeymap("ERRORLIST_KEYMAP", getKeymap()); 337 338 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_CUT), cutAction); 339 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_COPY), copyAction); 340 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_PASTE_FROM_HISTORY), pasteAction); 341 DrJava.getConfig().addOptionListener(OptionConstants.KEY_CUT, new OptionListener<KeyStroke>() { 342 public void optionChanged(OptionEvent<KeyStroke> oe) { 343 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_CUT), cutAction); 344 } 345 }); 346 DrJava.getConfig().addOptionListener(OptionConstants.KEY_COPY, new OptionListener<KeyStroke>() { 347 public void optionChanged(OptionEvent<KeyStroke> oe) { 348 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_COPY), copyAction); 349 } 350 }); 351 DrJava.getConfig().addOptionListener(OptionConstants.KEY_PASTE_FROM_HISTORY, new OptionListener<KeyStroke>() { 352 public void optionChanged(OptionEvent<KeyStroke> oe) { 353 addActionForKeyStroke(DrJava.getConfig().getSetting(OptionConstants.KEY_PASTE_FROM_HISTORY), pasteAction); 354 } 355 }); 356 } 357 358 364 public SwingDocument getSwingDocument() { return (SwingDocument) getDocument(); } 365 366 370 public void addActionForKeyStroke(KeyStroke stroke, Action action) { 371 KeyStroke[] keys = _keymap.getKeyStrokesForAction(action); 373 if (keys != null) { 374 for (int i = 0; i < keys.length; i++) { 375 _keymap.removeKeyStrokeBinding(keys[i]); 376 } 377 } 378 _keymap.addActionForKeyStroke(stroke, action); 379 setKeymap(_keymap); 380 } 381 382 383 public void lostOwnership(Clipboard clipboard, Transferable contents) { 384 } 386 387 388 Action cutAction = new DefaultEditorKit.CutAction() { 389 public void actionPerformed(ActionEvent e) { 390 if (getSelectedText()!=null) { 391 super.actionPerformed(e); 392 String s = edu.rice.cs.util.swing.Utilities.getClipboardSelection(ErrorListPane.this); 393 if ((s!=null) && (s.length()!=0)) { ClipboardHistoryModel.singleton().put(s); } 394 } 395 } 396 }; 397 398 399 Action copyAction = new DefaultEditorKit.CopyAction() { 400 public void actionPerformed(ActionEvent e) { 401 if (getSelectedText()!=null) { 402 super.actionPerformed(e); 403 String s = edu.rice.cs.util.swing.Utilities.getClipboardSelection(ErrorListPane.this); 404 if ((s!=null) && (s.length()!=0)){ ClipboardHistoryModel.singleton().put(s); } 405 } 406 } 407 }; 408 409 410 Action pasteAction = new DefaultEditorKit.PasteAction() { 411 public void actionPerformed(ActionEvent e) { } 412 }; 413 414 417 public boolean shouldShowHighlightsInSource() { return _showHighlightsCheckBox.isSelected(); } 418 419 420 public int getSelectedIndex() { return _selectedIndex; } 421 422 423 protected CompilerError _errorAtPoint(Point p) { 424 int modelPos = viewToModel(p); 425 426 if (modelPos == -1) return null; 427 428 int errorNum = -1; 430 for (int i = 0; i < _errorListPositions.length; i++) { 431 if (_errorListPositions[i].getOffset() <= modelPos) errorNum = i; 432 else break; } 434 435 if (errorNum >= 0) return _errorTable.get(_errorListPositions[errorNum]); 436 return null; 437 } 438 439 440 private int _getIndexForError(CompilerError error) { 441 442 if (error == null) throw new IllegalArgumentException ("Couldn't find index for null error"); 443 444 for (int i = 0; i < _errorListPositions.length; i++) { 445 CompilerError e= _errorTable.get(_errorListPositions[i]); 446 if (error.equals(e)) return i; 447 } 448 449 throw new IllegalArgumentException ("Couldn't find index for error " + error); 450 } 451 452 453 protected boolean _isEmptySelection() { return getSelectionStart() == getSelectionEnd(); } 454 455 456 protected void updateListPane(boolean done) { 457 try { 458 _errorListPositions = new Position[_numErrors]; 459 _errorTable.clear(); 460 461 if (_numErrors == 0) _updateNoErrors(done); 462 else _updateWithErrors(); 463 } 464 catch (BadLocationException e) { throw new UnexpectedException(e); } 465 466 } 469 470 abstract protected void _updateNoErrors(boolean done) throws BadLocationException; 471 472 abstract protected void _updateWithErrors() throws BadLocationException; 473 474 475 protected String _getNumErrorsMessage(String failureName, String failureMeaning) { 476 StringBuilder numErrMsg; 477 478 479 int numCompErrs = getErrorModel().getNumCompErrors(); 480 int numWarnings = getErrorModel().getNumWarnings(); 481 482 if (!getErrorModel().hasOnlyWarnings()) { 483 numErrMsg = new StringBuilder (numCompErrs + " " + failureName); if (numCompErrs > 1) numErrMsg.append("s"); 485 if (numWarnings > 0) numErrMsg.append(" and " + numWarnings + " warning"); 486 } 487 488 else numErrMsg = new StringBuilder (numWarnings + " warning"); 489 490 if (numWarnings > 1) numErrMsg.append("s"); 491 492 numErrMsg.append(" " + failureMeaning + ":\n"); 493 return numErrMsg.toString(); 494 } 495 496 499 protected String _getErrorTitle() { 500 CompilerErrorModel cem = getErrorModel(); 501 if (cem.getNumCompErrors() > 1) return "--------------\n*** Errors ***\n--------------\n"; 502 if (cem.getNumCompErrors() > 0) return "-------------\n*** Error ***\n-------------\n"; 503 return ""; 504 } 505 506 509 protected String _getWarningTitle() { 510 CompilerErrorModel cem = getErrorModel(); 511 if (cem.getNumWarnings() > 1) return "--------------\n** Warnings **\n--------------\n"; 512 if (cem.getNumWarnings() > 0) return "-------------\n** Warning **\n-------------\n"; 513 return ""; 514 } 515 516 517 protected void _updateWithErrors(String failureName, String failureMeaning, SwingDocument doc) 518 throws BadLocationException { 519 String numErrsMsg = _getNumErrorsMessage(failureName, failureMeaning); 521 doc.append(numErrsMsg, BOLD_ATTRIBUTES); 522 523 _insertErrors(doc); 524 setDocument(doc); 525 526 if (!getErrorModel().hasOnlyWarnings()) 528 getErrorListPane().switchToError(0); 529 } 530 531 532 public boolean hasNextError() { return this.getSelectedIndex() + 1 < _numErrors; } 533 534 535 public boolean hasPrevError() { return this.getSelectedIndex() > 0; } 536 537 538 public void nextError() { 539 if (hasNextError()) { 541 this._selectedIndex += 1; 542 getErrorListPane().switchToError(this.getSelectedIndex()); 544 } 545 } 546 547 548 public void prevError() { 549 if (hasPrevError()) { 551 this._selectedIndex -= 1; 552 getErrorListPane().switchToError(this.getSelectedIndex()); 553 } 554 } 555 556 559 protected void _insertErrors(SwingDocument doc) throws BadLocationException { 560 CompilerErrorModel cem = getErrorModel(); 561 int numErrors = cem.getNumErrors(); 562 563 int errorPositionInListOfErrors = 0; 567 569 String errorTitle = _getErrorTitle(); 570 if (cem.getNumWarnings() > 0) doc.append(errorTitle, BOLD_ATTRIBUTES); 571 572 for (int errorNum = 0; errorNum < numErrors; errorNum++) { 573 int startPos = doc.getLength(); 574 CompilerError err = cem.getError(errorNum); 575 576 if (!err.isWarning()){ 577 _insertErrorText(err, doc); 578 Position pos = doc.createPosition(startPos); 579 _errorListPositions[errorPositionInListOfErrors] = pos; 580 _errorTable.put(pos, err); 581 errorPositionInListOfErrors++; 582 } 583 } 584 585 String warningTitle = _getWarningTitle(); 586 if (cem.getNumCompErrors() > 0) doc.append(warningTitle, BOLD_ATTRIBUTES); 587 588 for (int errorNum = 0; errorNum < numErrors; errorNum++) { 589 int startPos = doc.getLength(); 590 CompilerError err = cem.getError(errorNum); 591 592 if (err.isWarning()){ 593 _insertErrorText(err, doc); 594 Position pos = doc.createPosition(startPos); 595 _errorListPositions[errorPositionInListOfErrors] = pos; 596 _errorTable.put(pos, err); 597 errorPositionInListOfErrors++; 598 } 599 } 600 } 601 602 606 protected void _insertErrorText(CompilerError error, SwingDocument doc) throws BadLocationException { 607 doc.append("File: ", BOLD_ATTRIBUTES); 609 String fileAndLineNumber = error.getFileMessage() + " [line: " + error.getLineMessage() + "]"; 610 doc.append(fileAndLineNumber + "\n", NORMAL_ATTRIBUTES); 611 612 if (error.isWarning()) doc.append(_getWarningText(), BOLD_ATTRIBUTES); 613 else doc.append(_getErrorText(), BOLD_ATTRIBUTES); 614 615 doc.append(error.message(), NORMAL_ATTRIBUTES); 616 doc.append("\n", NORMAL_ATTRIBUTES); 617 } 618 619 620 protected String _getWarningText() { return "Warning: "; } 621 622 623 protected String _getErrorText() { return "Error: "; } 624 625 626 protected void _removeListHighlight() { 627 if (_listHighlightTag != null) { 628 _listHighlightTag.remove(); 629 _listHighlightTag = null; 630 } 631 } 634 635 636 public void selectNothing() { 637 _removeListHighlight(); 639 640 _frame.getCurrentDefPane().removeErrorHighlight(); 642 } 643 644 645 public void selectItem(CompilerError error) { 646 try { 648 int i = _getIndexForError(error); 650 651 _selectedIndex = i; 652 _removeListHighlight(); 654 655 int startPos = _errorListPositions[i].getOffset(); 656 658 int endPos; 662 if (i + 1 >= (_numErrors)) endPos = getDocument().getLength(); 663 else { 664 endPos = _errorListPositions[i + 1].getOffset(); 665 CompilerError nextError = _errorTable.get(_errorListPositions[i+1]); 667 if (!error.isWarning() && nextError.isWarning()) endPos = endPos - _getWarningTitle().length(); 669 } 671 672 674 try { 675 _listHighlightTag = _highlightManager.addHighlight(startPos, endPos, _listHighlightPainter); 676 677 Rectangle startRect; 680 if (i == 0) startRect = modelToView(0); 681 682 else startRect = modelToView(startPos); 683 684 Rectangle endRect = modelToView(endPos - 1); 685 686 if (startRect != null && endRect != null) { 687 startRect.add(endRect); 690 691 693 scrollRectToVisible(startRect); 694 _updateScrollButtons(); 695 } 696 else { 697 _removeListHighlight(); 700 } 701 } 702 catch (BadLocationException badBadLocation) { } 703 704 } 705 catch (IllegalArgumentException iae) { 706 _removeListHighlight(); 710 } 711 } 712 713 protected void _updateScrollButtons() { 714 if (hasNextError()) { 715 _nextErrorButton.setEnabled(true); 716 } 717 else { 718 _nextErrorButton.setEnabled(false); 719 } 720 if (hasPrevError()) { 721 _prevErrorButton.setEnabled(true); 722 } 723 else { 724 _prevErrorButton.setEnabled(false); 725 } 726 } 727 728 732 void switchToError(CompilerError error) { 733 if (error == null) return; 735 736 SingleDisplayModel model = getModel(); 737 738 DefinitionsPane prevPane = _frame.getCurrentDefPane(); 739 prevPane.removeErrorHighlight(); OpenDefinitionsDocument prevDoc = prevPane.getOpenDefDocument(); 741 742 if (error.file() != null) { 743 try { 744 OpenDefinitionsDocument doc = model.getDocumentForFile(error.file()); 745 CompilerErrorModel errorModel = getErrorModel(); 746 747 Position pos = errorModel.getPosition(error); 752 if (! prevDoc.equals(doc)) { 753 model.addToBrowserHistory(); 754 model.setActiveDocument(doc); 755 } 756 else model.refreshActiveDocument(); 757 758 760 DefinitionsPane defPane = _frame.getCurrentDefPane(); 761 762 if (pos != null) { 763 int errPos = pos.getOffset(); 764 if (errPos >= 0 && errPos <= doc.getLength()) { 765 defPane.centerViewOnOffset(errPos); 766 767 770 defPane.getErrorCaretListener().updateHighlight(errPos); 771 } 772 773 } 774 defPane.requestFocusInWindow(); 780 defPane.getCaret().setVisible(true); 781 } 782 catch (IOException ioe) { 783 } 785 } 786 789 getErrorListPane().selectItem(error); 790 } 791 792 793 796 void switchToError(int index) { 797 if ((index >= 0) && (index < _errorListPositions.length)) { 798 Position pos = _errorListPositions[index]; 799 CompilerError error= _errorTable.get(pos); 800 switchToError(error); 801 } 802 } 803 804 805 private class CompilerErrorColorOptionListener implements OptionListener<Color> { 806 807 public void optionChanged(OptionEvent<Color> oce) { 808 _listHighlightPainter = new ReverseHighlighter.DefaultHighlightPainter(oce.value); 809 if (_listHighlightTag != null) { 810 _listHighlightTag.refresh(_listHighlightPainter); 811 } 812 } 813 } 814 815 816 private class ForegroundColorListener implements OptionListener<Color> { 817 public void optionChanged(OptionEvent<Color> oce) { 818 StyleConstants.setForeground(NORMAL_ATTRIBUTES, oce.value); 819 StyleConstants.setForeground(BOLD_ATTRIBUTES, oce.value); 820 821 SwingDocument doc = getErrorListPane().getSwingDocument(); 823 SimpleAttributeSet set = new SimpleAttributeSet (); 824 set.addAttribute(StyleConstants.Foreground, oce.value); 825 doc.acquireWriteLock(); 826 try { doc.setCharacterAttributes(0, doc.getLength(), set, false); } 827 finally { doc.releaseWriteLock(); } 828 } 830 } 831 832 833 private class BackgroundColorListener implements OptionListener<Color> { 834 public void optionChanged(OptionEvent<Color> oce) { 835 setBackground(oce.value); 836 ErrorListPane.this.repaint(); 837 } 838 } 839 } 840 } | Popular Tags |