KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > rice > cs > drjava > ui > ErrorPanel


1 /*BEGIN_COPYRIGHT_BLOCK
2  *
3  * This file is part of DrJava. Download the current version of this project from http://www.drjava.org/
4  * or http://sourceforge.net/projects/drjava/
5  *
6  * DrJava Open Source License
7  *
8  * Copyright (C) 2001-2005 JavaPLT group at Rice University (javaplt@rice.edu). All rights reserved.
9  *
10  * Developed by: Java Programming Languages Team, Rice University, http://www.cs.rice.edu/~javaplt/
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
13  * documentation files (the "Software"), to deal with the Software without restriction, including without limitation
14  * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
15  * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
16  *
17  * - Redistributions of source code must retain the above copyright notice, this list of conditions and the
18  * following disclaimers.
19  * - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
20  * following disclaimers in the documentation and/or other materials provided with the distribution.
21  * - Neither the names of DrJava, the JavaPLT, Rice University, nor the names of its contributors may be used to
22  * endorse or promote products derived from this Software without specific prior written permission.
23  * - Products derived from this software may not be called "DrJava" nor use the term "DrJava" as part of their
24  * names without prior written permission from the JavaPLT group. For permission, write to javaplt@rice.edu.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
27  * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28  * CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30  * WITH THE SOFTWARE.
31  *
32  END_COPYRIGHT_BLOCK*/

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.DefaultDJDocument;
43
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 // TODO: Check synchronization.
52
import java.util.Hashtable JavaDoc;
53
54 import javax.swing.*;
55 import javax.swing.text.*;
56 import javax.swing.text.SimpleAttributeSet JavaDoc;
57 import javax.swing.border.EmptyBorder JavaDoc;
58 import java.awt.datatransfer.*;
59 import java.awt.*;
60 import java.awt.event.MouseAdapter JavaDoc;
61 import java.awt.event.MouseEvent JavaDoc;
62 import java.awt.event.ItemListener JavaDoc;
63 import java.awt.event.ItemEvent JavaDoc;
64 import java.awt.event.ActionListener JavaDoc;
65 import java.awt.event.ActionEvent JavaDoc;
66 import java.io.IOException JavaDoc;
67
68 /** This class contains common code and interfaces from CompilerErrorPanel, JUnitPanel, and JavadocErrorPanel.
69  * TODO: parameterize the types of CompilerErrors used here
70  * @version $Id: ErrorPanel.java 4043 2006-11-22 23:04:59Z rcartwright $
71  */

72 public abstract class ErrorPanel extends TabbedPanel implements OptionConstants {
73   
74   protected static final SimpleAttributeSet JavaDoc NORMAL_ATTRIBUTES = _getNormalAttributes();
75   protected static final SimpleAttributeSet JavaDoc BOLD_ATTRIBUTES = _getBoldAttributes();
76   
77   /** The total number of errors in the list */
78   protected volatile int _numErrors;
79   protected volatile JCheckBox _showHighlightsCheckBox;
80   
81   // TODO: is this necessary, or can we get by with installing a domain-specific
82
// model in the constructor - e.g. JavadocModel
83
protected SingleDisplayModel _model;
84   
85   private JScrollPane _scroller;
86   
87   /** This contains the _scroller and the _errorNavPanel. */
88   private JPanel _leftPanel;
89   
90   /** This contains the label, showHighlightsCheckBox, and the customPanel. */
91   private JPanel _rightPanel;
92   
93   private JPanel _errorNavPanel;
94   
95   private JPanel _errorNavButtonsPanel;
96   
97   /** This JPanel contains each child panel's specific UI components. **/
98   protected JPanel customPanel;
99   
100   private JButton _nextErrorButton;
101   private JButton _prevErrorButton;
102   
103   /** Highlight painter for selected list items. */
104   static ReverseHighlighter.DefaultHighlightPainter _listHighlightPainter =
105     new ReverseHighlighter.DefaultHighlightPainter(DrJava.getConfig().getSetting(COMPILER_ERROR_COLOR));
106   
107   protected static final SimpleAttributeSet JavaDoc _getBoldAttributes() {
108     SimpleAttributeSet JavaDoc s = new SimpleAttributeSet JavaDoc();
109     StyleConstants.setBold(s, true);
110     return s;
111   }
112   
113   protected static final SimpleAttributeSet JavaDoc _getNormalAttributes() {
114     SimpleAttributeSet JavaDoc s = new SimpleAttributeSet JavaDoc();
115     return s;
116   }
117   
118   public ErrorPanel(SingleDisplayModel model, MainFrame frame, String JavaDoc tabString, String JavaDoc 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     /******** Initialize the error navigation buttons ********/
130     _errorNavButtonsPanel = new JPanel(new BorderLayout());
131     
132     _nextErrorButton = new JButton(MainFrame.getIcon("Down16.gif"));//new JButton("Next Error");
133
_prevErrorButton = new JButton(MainFrame.getIcon("Up16.gif"));//new JButton("Prev Error");
134

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     // _errorPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 0, 3));
142
// _errorPanel.setPreferredSize(new Dimension(27,35));
143
// _errorPanel.add(_prevErrorButton);
144
// _errorPanel.add(_nextErrorButton);
145
// _uiBox.add(_errorPanel, BorderLayout.WEST);
146
_errorNavButtonsPanel.add(_prevErrorButton, BorderLayout.NORTH);
147     _errorNavButtonsPanel.add(_nextErrorButton, BorderLayout.SOUTH);
148     _errorNavButtonsPanel.setBorder(new EmptyBorder JavaDoc(18,5,18,5)); // 5 pix padding on sides
149

150     // JPanel middlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
151
// middlePanel.add(_errorNavButtonsPanel);
152

153     _errorNavPanel.add(_errorNavButtonsPanel);//, BorderLayout.CENTER);
154
_showHighlightsCheckBox = new JCheckBox( "Highlight source", true);
155     
156     // _mainPanel.setMinimumSize(new Dimension(225,60));
157
// We make the vertical scrollbar always there.
158
// If we don't, when it pops up it cuts away the right edge of the
159
// text. Very bad.
160
_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 JavaDoc(0,5,0,5)); // 5 pix padding on sides
169
// uiBox.setBorder(new EmptyBorder(5,0,0,0)); // 5 pix padding on top
170
_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 JavaDoc() {
182       public void actionPerformed(ActionEvent JavaDoc e) {
183         elp.nextError();
184         // _prevErrorButton.setEnabled(_errorListPane.hasPrevError());
185
// _nextErrorButton.setEnabled(_errorListPane.hasNextError());
186
}
187     });
188     _prevErrorButton.setEnabled(false);
189     _prevErrorButton.addActionListener(new ActionListener JavaDoc() {
190       public void actionPerformed(ActionEvent JavaDoc e) {
191         elp.prevError();
192         // _prevErrorButton.setEnabled(_errorListPane.hasPrevError());
193
// _nextErrorButton.setEnabled(_errorListPane.hasNextError());
194
}
195     });
196   }
197   
198   /** Changes the font of the error list. */
199   public void setListFont(Font f) {
200     SimpleAttributeSet JavaDoc set = new SimpleAttributeSet JavaDoc();
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   /** Updates all document styles with the attributes contained in newSet.
218    * @param newSet Style containing new attributes to use.
219    */

220   protected void _updateStyles(AttributeSet JavaDoc newSet) {
221     NORMAL_ATTRIBUTES.addAttributes(newSet);
222     BOLD_ATTRIBUTES.addAttributes(newSet);
223     StyleConstants.setBold(BOLD_ATTRIBUTES, true); // bold should always be bold
224
}
225   
226   abstract protected ErrorListPane getErrorListPane();
227   
228   protected SingleDisplayModel getModel() {
229     return _model;
230   }
231   
232   /**
233    * This function returns the correct error model
234    */

235   abstract protected CompilerErrorModel getErrorModel();
236   
237   /** Pane to show compiler errors. Similar to a listbox (clicking selects an item) but items can each wrap, etc. */
238   public abstract class ErrorListPane extends JEditorPane implements ClipboardOwner {
239     /** The custom keymap for the error list pane. */
240     protected Keymap _keymap;
241     
242     /** Index into _errorListPositions of the currently selected error. */
243     private int _selectedIndex;
244     
245     /**
246      * The start position of each error in the list. This position is the place
247      * where the error starts in the error list, as opposed to the place where
248      * the error exists in the source.
249      */

250     protected Position[] _errorListPositions;
251     
252     /** Table mapping Positions in the error list to CompilerErrors. */
253     protected final Hashtable JavaDoc<Position, CompilerError> _errorTable = new Hashtable JavaDoc<Position, CompilerError>();
254     
255     // when we create a highlight we get back a tag we can use to remove it
256
private HighlightManager.HighlightInfo _listHighlightTag = null;
257     
258     private HighlightManager _highlightManager = new HighlightManager(this);
259     
260     protected MouseAdapter JavaDoc defaultMouseListener = new MouseAdapter JavaDoc() {
261       public void mousePressed(MouseEvent JavaDoc e) { selectNothing(); }
262       public void mouseReleased(MouseEvent JavaDoc e) {
263         CompilerError error = _errorAtPoint(e.getPoint());
264         
265         if (_isEmptySelection() && error != null) getErrorListPane().switchToError(error);
266         else selectNothing();
267       }
268     };
269     
270 // private Hashtable<Position, CompilerError> _setUpErrorTable() {
271
// return new Hashtable<Position, CompilerError>();
272
// }
273

274     /** Constructs the CompilerErrorListPane.*/
275     public ErrorListPane() {
276 // // If we set this pane to be of type text/rtf, it wraps based on words
277
// // as opposed to based on characters.
278

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       // We set the editor pane disabled so it won't get keyboard focus,
291
// which makes it uneditable, and so you can't select text inside it.
292
//setEnabled(false);
293

294       // Set the editor pane to be uneditable, but allow selecting text.
295
setEditable(false);
296       
297       DrJava.getConfig().addOptionListener(COMPILER_ERROR_COLOR,
298                                            new CompilerErrorColorOptionListener());
299       
300       // Set the colors.
301
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       // Add OptionListeners for the colors.
310
DrJava.getConfig().addOptionListener(DEFINITIONS_NORMAL_COLOR,
311                                            new ForegroundColorListener());
312       DrJava.getConfig().addOptionListener(DEFINITIONS_BACKGROUND_COLOR,
313                                            new BackgroundColorListener());
314       
315       /* Item listener instead of change listener so that this code won't be called (twice) every time the mouse moves
316        * over the _showHighlightsCheckBox (5/26/05)
317        */

318       _showHighlightsCheckBox.addItemListener(new ItemListener JavaDoc() {
319         public void itemStateChanged(ItemEvent JavaDoc 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 // Commented out because they are redudant; done in switchToError(...)
329
// DefinitionsPane curDefPane = _frame.getCurrentDefPane();
330
// lastDefPane.requestFocusInWindow();
331
// lastDefPane.getCaret().setVisible(true);
332
}
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     /** Gets the SwingDocument associated with this ErrorListPane. The inherited getDocument method must be preserved
359       * because the ErrorListPane constructor uses it fetch a Document that is NOT a SwingDocument. ErrorListPane
360       * immediately sets the Document corresponding to this JEditorPane to a SwingDocument and strictly maintains it as
361       * a SwingDocument, but the JEditorPane constructor binds its document to a PlainDocument and uses getDocument
362       * before ErrorListPane can set this field to a SwingDocument.
363       */

364     public SwingDocument getSwingDocument() { return (SwingDocument) getDocument(); }
365     
366     /** Assigns the given keystroke to the given action in this pane.
367      * @param stroke keystroke that triggers the action
368      * @param action Action to perform
369      */

370     public void addActionForKeyStroke(KeyStroke stroke, Action action) {
371       // we don't want multiple keys bound to the same action
372
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     /** We lost ownership of what we put in the clipboard. */
383     public void lostOwnership(Clipboard clipboard, Transferable contents) {
384       // ignore
385
}
386
387     /** Default cut action. */
388     Action cutAction = new DefaultEditorKit.CutAction() {
389       public void actionPerformed(ActionEvent JavaDoc e) {
390         if (getSelectedText()!=null) {
391           super.actionPerformed(e);
392           String JavaDoc 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     /** Default copy action. */
399     Action copyAction = new DefaultEditorKit.CopyAction() {
400       public void actionPerformed(ActionEvent JavaDoc e) {
401         if (getSelectedText()!=null) {
402           super.actionPerformed(e);
403           String JavaDoc 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     /** No-op paste action. */
410     Action pasteAction = new DefaultEditorKit.PasteAction() {
411       public void actionPerformed(ActionEvent JavaDoc e) { }
412     };
413     
414     /** Returns true if the errors should be highlighted in the source
415      * @return the status of the JCheckBox _showHighlightsCheckBox
416      */

417     public boolean shouldShowHighlightsInSource() { return _showHighlightsCheckBox.isSelected(); }
418     
419     /** Get the index of the current error in the error array. */
420     public int getSelectedIndex() { return _selectedIndex; }
421     
422     /** Returns CompilerError associated with the given visual coordinates. Returns null if none. */
423     protected CompilerError _errorAtPoint(Point p) {
424       int modelPos = viewToModel(p);
425       
426       if (modelPos == -1) return null;
427       
428       // Find the first error whose position preceeds this model position
429
int errorNum = -1;
430       for (int i = 0; i < _errorListPositions.length; i++) {
431         if (_errorListPositions[i].getOffset() <= modelPos) errorNum = i;
432         else break; // we've gone past the correct error; the last value was right
433
}
434       
435       if (errorNum >= 0) return _errorTable.get(_errorListPositions[errorNum]);
436       return null;
437     }
438     
439     /** Returns the index into _errorListPositions corresponding to the given CompilerError. */
440     private int _getIndexForError(CompilerError error) {
441       
442       if (error == null) throw new IllegalArgumentException JavaDoc("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 JavaDoc("Couldn't find index for error " + error);
450     }
451     
452     /** Returns true if the text selection interval is empty. */
453     protected boolean _isEmptySelection() { return getSelectionStart() == getSelectionEnd(); }
454     
455     /** Update the pane which holds the list of errors for the viewer. */
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       // Force UI to redraw
467
// revalidate();
468
}
469     
470     abstract protected void _updateNoErrors(boolean done) throws BadLocationException;
471     
472     abstract protected void _updateWithErrors() throws BadLocationException;
473     
474     /** Gets the message indicating the number of errors and warnings.*/
475     protected String JavaDoc _getNumErrorsMessage(String JavaDoc failureName, String JavaDoc failureMeaning) {
476       StringBuilder JavaDoc numErrMsg;
477       
478       /** Used for display purposes only */
479       int numCompErrs = getErrorModel().getNumCompErrors();
480       int numWarnings = getErrorModel().getNumWarnings();
481       
482       if (!getErrorModel().hasOnlyWarnings()) {
483         numErrMsg = new StringBuilder JavaDoc(numCompErrs + " " + failureName); //failureName = error or test (for compilation and JUnit testing respectively)
484
if (numCompErrs > 1) numErrMsg.append("s");
485         if (numWarnings > 0) numErrMsg.append(" and " + numWarnings + " warning");
486       }
487       
488       else numErrMsg = new StringBuilder JavaDoc(numWarnings + " warning");
489       
490       if (numWarnings > 1) numErrMsg.append("s");
491      
492       numErrMsg.append(" " + failureMeaning + ":\n");
493       return numErrMsg.toString();
494     }
495     
496     /**
497      * Gets the message to title the block containing only errors.
498      */

499     protected String JavaDoc _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     /**
507      * Gets the message to title the block containing only warnings.
508      */

509     protected String JavaDoc _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     /** Used to show that the last compile was unsuccessful.*/
517     protected void _updateWithErrors(String JavaDoc failureName, String JavaDoc failureMeaning, SwingDocument doc)
518       throws BadLocationException {
519       // Print how many errors
520
String JavaDoc numErrsMsg = _getNumErrorsMessage(failureName, failureMeaning);
521       doc.append(numErrsMsg, BOLD_ATTRIBUTES);
522       
523       _insertErrors(doc);
524       setDocument(doc);
525       
526       // Select the first error if there are some errors (i.e. does not select if there are only warnings)
527
if (!getErrorModel().hasOnlyWarnings())
528         getErrorListPane().switchToError(0);
529     }
530     
531     /** Returns true if there is an error after the selected error. */
532     public boolean hasNextError() { return this.getSelectedIndex() + 1 < _numErrors; }
533     
534     /** Returns true if there is an error before the selected error. */
535     public boolean hasPrevError() { return this.getSelectedIndex() > 0; }
536     
537     /** Switches to the next error. */
538     public void nextError() {
539       // Select the error
540
if (hasNextError()) {
541         this._selectedIndex += 1;
542 // Utilities.showDebug("selected index in nextError is " + _selectedIndex + " _numErrors is " + _numErrors);
543
getErrorListPane().switchToError(this.getSelectedIndex());
544       }
545     }
546     
547     /** Switches to the previous error. */
548     public void prevError() {
549       // Select the error
550
if (hasPrevError()) {
551         this._selectedIndex -= 1;
552         getErrorListPane().switchToError(this.getSelectedIndex());
553       }
554     }
555     
556     /** Inserts all of the errors into the given document.
557      * @param doc the document into which to insert the errors
558      */

559     protected void _insertErrors(SwingDocument doc) throws BadLocationException {
560       CompilerErrorModel cem = getErrorModel();
561       int numErrors = cem.getNumErrors();
562       
563       //Added this counter in order to add errors and warnings in correct order and select them correctly
564
//Previous version used errorNum as a counter, but this doesn't work anymore because we are not doing
565
//errors and variables at the same time.
566
int errorPositionInListOfErrors = 0;
567       // Show errors first and warnings second
568

569       String JavaDoc 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 JavaDoc 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     /** Prints a message for the given error
603      * @param error the error to print
604      * @param doc the document in the error pane
605      */

606     protected void _insertErrorText(CompilerError error, SwingDocument doc) throws BadLocationException {
607       // Show file and line number
608
doc.append("File: ", BOLD_ATTRIBUTES);
609       String JavaDoc 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     /** Returns the string to identify a warning. */
620     protected String JavaDoc _getWarningText() { return "Warning: "; }
621     
622     /** Returns the string to identify an error. */
623     protected String JavaDoc _getErrorText() { return "Error: "; }
624     
625     /** When the selection of the current error changes, remove the highlight in the error pane. */
626     protected void _removeListHighlight() {
627       if (_listHighlightTag != null) {
628         _listHighlightTag.remove();
629         _listHighlightTag = null;
630       }
631       // _prevErrorButton.setEnabled(false);
632
// _nextErrorButton.setEnabled(false);
633
}
634     
635     /** Don't select any errors in the error pane. */
636     public void selectNothing() {
637       // _selectedIndex = -1;
638
_removeListHighlight();
639       
640       // Remove highlight from the defPane that has it
641
_frame.getCurrentDefPane().removeErrorHighlight();
642     }
643     
644     /** Selects the given error inside the error list pane. */
645     public void selectItem(CompilerError error) {
646 // Utilities.showDebug("selectItem(" + error + ") called");
647
try {
648         // Find corresponding index
649
int i = _getIndexForError(error);
650         
651         _selectedIndex = i;
652 // Utilities.showDebug("selected index = " + i);
653
_removeListHighlight();
654         
655         int startPos = _errorListPositions[i].getOffset();
656 // Utilities.showDebug("startPos = " + startPos);
657

658         // end pos is either the end of the document (if this is the last error)
659
// or the end of the error if the last error (i.e. before the warnings title)
660
// or the char where the next error starts
661
int endPos;
662         if (i + 1 >= (_numErrors)) endPos = getDocument().getLength();
663         else {
664           endPos = _errorListPositions[i + 1].getOffset();
665 // Utilities.showDebug("endPos(before) = " + endPos);
666
CompilerError nextError = _errorTable.get(_errorListPositions[i+1]);
667 // Utilities.showDebug("nextError = " + nextError);
668
if (!error.isWarning() && nextError.isWarning()) endPos = endPos - _getWarningTitle().length();
669 // Utilities.showDebug("endPos(after) = " + endPos);
670
}
671         
672 // Utilities.showDebug("startpos = " + startPos + " endpos = " + endPos);
673

674         try {
675           _listHighlightTag = _highlightManager.addHighlight(startPos, endPos, _listHighlightPainter);
676           
677           // If first error, show number of errors and warnings preferentially to showing the error
678
// Otherwise, scroll to make sure this item is visible
679
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             // Add the end rect onto the start rect to make a rectangle
688
// that encompasses the entire error
689
startRect.add(endRect);
690             
691             //System.err.println("scrll vis: " + startRect);
692

693             scrollRectToVisible(startRect);
694             _updateScrollButtons();
695           }
696           else {
697 // Utilities.showDebug("Either startRect or endRect is null!");
698
// Couldn't draw the box to highlight, so don't highlight anything
699
_removeListHighlight();
700           }
701         }
702         catch (BadLocationException badBadLocation) { }
703         
704       }
705       catch (IllegalArgumentException JavaDoc iae) {
706         // This shouldn't be happening, but it was reported in bug 704006.
707
// (_getIndexForError throws it.)
708
// We'll at least fail a little more gracefully.
709
_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     /** Change all state to select a new error, including moving the caret to the error, if a corresponding position
729      * exists.
730      * @param error The error to switch to
731      */

732     void switchToError(CompilerError error) {
733 // Utilities.showDebug("ErrorPanel.switchToError called");
734
if (error == null) return;
735       
736       SingleDisplayModel model = getModel();
737       
738       DefinitionsPane prevPane = _frame.getCurrentDefPane();
739       prevPane.removeErrorHighlight(); // hide previous error highlight
740
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); // null if error has no Position
748
// Utilities.showDebug("The position of the error is: " + pos);
749
// switch to correct def pane and move caret to error position
750
// Utilities.showDebug("active document being set to " + doc + " in ErrorPanel.switchToError");
751

752           if (! prevDoc.equals(doc)) {
753             model.addToBrowserHistory();
754             model.setActiveDocument(doc);
755           }
756           else model.refreshActiveDocument();
757           
758 // Utilities.showDebug("setting active document has completed");
759

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               /* The folowing fixes a bug where, if two consecutive errors are in the same position, the previous error
768                * is unhighlighted and the new error is not highlighted because the CaretListener does not act because there
769                * is no change in caret position. (This is the only place where updateHighlight was called from before) */

770               defPane.getErrorCaretListener().updateHighlight(errPos);
771             }
772             
773           }
774           // The following line is a brute force hack that fixed a bug plaguing the DefinitionsPane immediately after a compilation
775
// with errors. In some cases (which were consistently reproducible), the DefinitionsPane editing functions would break
776
// whereby the keystrokes had their usual meaning but incorrect updates were performed in the DefintionsPane. For example,
777
// the display behaved as if the editor were in "overwrite" mode.
778
// _frame._switchDefScrollPane(); // resets an out-of-kilter DefinitionsPane on the first error after a compilation
779
defPane.requestFocusInWindow();
780           defPane.getCaret().setVisible(true);
781         }
782         catch (IOException JavaDoc ioe) {
783           // Don't highlight the source if file can't be opened
784
}
785       }
786 // Utilities.showDebug("Calling selectItem(...) from switchToError");
787
/* setActiveDocument(doc) selects the first error corresponding to the current position (caret location) but this may not
788        * be the correct error if there are multiple errors for this this position. The following selects the correct error.*/

789       getErrorListPane().selectItem(error);
790     }
791     
792     
793     /** Another interface to switchToError.
794      * @param index Index into the array of positions in the CompilerErrorListPane
795      */

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     /** The OptionListener for compiler COMPILER_ERROR_COLOR */
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     /** The OptionListener for compiler DEFINITIONS_NORMAL_COLOR */
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         // Re-attribute the existing text with the new color.
822
SwingDocument doc = getErrorListPane().getSwingDocument();
823         SimpleAttributeSet JavaDoc set = new SimpleAttributeSet JavaDoc();
824         set.addAttribute(StyleConstants.Foreground, oce.value);
825         doc.acquireWriteLock();
826         try { doc.setCharacterAttributes(0, doc.getLength(), set, false); }
827         finally { doc.releaseWriteLock(); }
828         // ErrorListPane.this.repaint();
829
}
830     }
831     
832     /** The OptionListener for compiler DEFINITIONS_BACKGROUND_COLOR. */
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